diff --git a/.travis.yml b/.travis.yml index de320b59a3ae43020889d62362e2a9a0ff6c18cb..e43a89e453a7fd0831c8aed07ffbce96dfd726e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,11 @@ before_install: - sudo add-apt-repository ppa:h-rayflood/llvm -y - sudo apt-get update -qq - sudo apt-get install -qq libgtest-dev libgflags-dev python-virtualenv clang-3.5 + - sudo pip install cpp-coveralls env: global: - RUBY_VERSION=2.1 + - COVERALLS_PARALLEL=true matrix: - CONFIG=dbg TEST=c - CONFIG=dbg TEST=c++ @@ -15,9 +17,15 @@ env: - CONFIG=opt TEST=node - CONFIG=opt TEST=ruby - CONFIG=opt TEST=python + - CONFIG=gcov TEST=c + - CONFIG=gcov TEST=c++ script: - rvm use $RUBY_VERSION - gem install bundler - ./tools/run_tests/run_tests.py -l $TEST -t -j 16 -c $CONFIG -s 4.0 +after_success: + - if [ "$CONFIG" = "gcov" ] ; then coveralls --exclude third_party --exclude gens -b. --gcov-options '\-p' ; fi notifications: - email: false \ No newline at end of file + email: false + webhooks: + - https://coveralls.io/webhook?repo_token=54IxAHPjJNdQJzJAhPU0MFpCtg7KvcydQ diff --git a/Makefile b/Makefile index ace93ea84e2d5b9304c8acef8f406902dee45166..8c6fc3220da66fb292cdb9327de95c3616c97e2b 100644 --- a/Makefile +++ b/Makefile @@ -544,12 +544,11 @@ interop_test: $(BINDIR)/$(CONFIG)/interop_test pubsub_client: $(BINDIR)/$(CONFIG)/pubsub_client pubsub_publisher_test: $(BINDIR)/$(CONFIG)/pubsub_publisher_test pubsub_subscriber_test: $(BINDIR)/$(CONFIG)/pubsub_subscriber_test -qps_client: $(BINDIR)/$(CONFIG)/qps_client -qps_client_async: $(BINDIR)/$(CONFIG)/qps_client_async -qps_server: $(BINDIR)/$(CONFIG)/qps_server -qps_server_async: $(BINDIR)/$(CONFIG)/qps_server_async +qps_driver: $(BINDIR)/$(CONFIG)/qps_driver +qps_worker: $(BINDIR)/$(CONFIG)/qps_worker status_test: $(BINDIR)/$(CONFIG)/status_test thread_pool_test: $(BINDIR)/$(CONFIG)/thread_pool_test +chttp2_fake_security_bad_hostname_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test chttp2_fake_security_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test chttp2_fake_security_cancel_after_accept_and_writes_closed_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test chttp2_fake_security_cancel_after_invoke_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test @@ -598,6 +597,7 @@ chttp2_fake_security_simple_delayed_request_legacy_test: $(BINDIR)/$(CONFIG)/cht chttp2_fake_security_simple_request_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_legacy_test chttp2_fake_security_thread_stress_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_legacy_test chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test +chttp2_fullstack_bad_hostname_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test chttp2_fullstack_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test chttp2_fullstack_cancel_after_accept_and_writes_closed_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test chttp2_fullstack_cancel_after_invoke_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test @@ -646,6 +646,7 @@ chttp2_fullstack_simple_delayed_request_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_ chttp2_fullstack_simple_request_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_legacy_test chttp2_fullstack_thread_stress_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_legacy_test chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test +chttp2_fullstack_uds_bad_hostname_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_bad_hostname_test chttp2_fullstack_uds_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_test chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test chttp2_fullstack_uds_cancel_after_invoke_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_test @@ -694,6 +695,7 @@ chttp2_fullstack_uds_simple_delayed_request_legacy_test: $(BINDIR)/$(CONFIG)/cht chttp2_fullstack_uds_simple_request_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_legacy_test chttp2_fullstack_uds_thread_stress_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_legacy_test chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test +chttp2_simple_ssl_fullstack_bad_hostname_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test chttp2_simple_ssl_fullstack_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test chttp2_simple_ssl_fullstack_cancel_after_invoke_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test @@ -742,6 +744,7 @@ chttp2_simple_ssl_fullstack_simple_delayed_request_legacy_test: $(BINDIR)/$(CONF chttp2_simple_ssl_fullstack_simple_request_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_legacy_test chttp2_simple_ssl_fullstack_thread_stress_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_legacy_test chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test +chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test @@ -790,6 +793,7 @@ chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_legacy_test: $(BI chttp2_simple_ssl_with_oauth2_fullstack_simple_request_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_legacy_test chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test +chttp2_socket_pair_bad_hostname_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test chttp2_socket_pair_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test chttp2_socket_pair_cancel_after_accept_and_writes_closed_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test chttp2_socket_pair_cancel_after_invoke_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test @@ -838,6 +842,7 @@ chttp2_socket_pair_simple_delayed_request_legacy_test: $(BINDIR)/$(CONFIG)/chttp chttp2_socket_pair_simple_request_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_legacy_test chttp2_socket_pair_thread_stress_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_legacy_test chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test +chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test: $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test @@ -937,13 +942,13 @@ static: static_c static_cxx static_c: $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a -static_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++.a +static_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a shared: shared_c shared_cxx shared_c: $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT) -shared_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) +shared_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT) shared_csharp: shared_c $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) grpc_csharp_ext: shared_csharp @@ -952,15 +957,15 @@ plugins: $(PROTOC_PLUGINS) privatelibs: privatelibs_c privatelibs_cxx -privatelibs_c: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack_uds.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags.a $(LIBDIR)/$(CONFIG)/libend2end_test_empty_batch.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_large_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_thread_stress.a $(LIBDIR)/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_trailing_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_large_metadata_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_thread_stress_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a +privatelibs_c: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack_uds.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags.a $(LIBDIR)/$(CONFIG)/libend2end_test_empty_batch.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_large_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_thread_stress.a $(LIBDIR)/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_trailing_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_large_metadata_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_thread_stress_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a $(LIBDIR)/$(CONFIG)/libqps.a buildtests: buildtests_c buildtests_cxx -buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/census_hash_table_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test $(BINDIR)/$(CONFIG)/census_statistics_performance_test $(BINDIR)/$(CONFIG)/census_statistics_quick_test $(BINDIR)/$(CONFIG)/census_statistics_small_log_test $(BINDIR)/$(CONFIG)/census_stub_test $(BINDIR)/$(CONFIG)/census_window_stats_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/chttp2_transport_end2end_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/echo_client $(BINDIR)/$(CONFIG)/echo_server $(BINDIR)/$(CONFIG)/echo_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/metadata_buffer_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_legacy_test +buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/census_hash_table_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test $(BINDIR)/$(CONFIG)/census_statistics_performance_test $(BINDIR)/$(CONFIG)/census_statistics_quick_test $(BINDIR)/$(CONFIG)/census_statistics_small_log_test $(BINDIR)/$(CONFIG)/census_stub_test $(BINDIR)/$(CONFIG)/census_window_stats_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/chttp2_transport_end2end_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/echo_client $(BINDIR)/$(CONFIG)/echo_server $(BINDIR)/$(CONFIG)/echo_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/metadata_buffer_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_legacy_test -buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/pubsub_client $(BINDIR)/$(CONFIG)/pubsub_publisher_test $(BINDIR)/$(CONFIG)/pubsub_subscriber_test $(BINDIR)/$(CONFIG)/qps_client $(BINDIR)/$(CONFIG)/qps_client_async $(BINDIR)/$(CONFIG)/qps_server $(BINDIR)/$(CONFIG)/qps_server_async $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/thread_pool_test +buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/pubsub_client $(BINDIR)/$(CONFIG)/pubsub_publisher_test $(BINDIR)/$(CONFIG)/pubsub_subscriber_test $(BINDIR)/$(CONFIG)/qps_driver $(BINDIR)/$(CONFIG)/qps_worker $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/thread_pool_test test: test_c test_cxx @@ -1099,6 +1104,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/transport_metadata_test || ( echo test transport_metadata_test failed ; exit 1 ) $(E) "[RUN] Testing transport_security_test" $(Q) $(BINDIR)/$(CONFIG)/transport_security_test || ( echo test transport_security_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_fake_security_bad_hostname_test" + $(Q) $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test || ( echo test chttp2_fake_security_bad_hostname_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_cancel_after_accept_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test || ( echo test chttp2_fake_security_cancel_after_accept_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_cancel_after_accept_and_writes_closed_test" @@ -1195,6 +1202,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_legacy_test || ( echo test chttp2_fake_security_thread_stress_legacy_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test || ( echo test chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_fullstack_bad_hostname_test" + $(Q) $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test || ( echo test chttp2_fullstack_bad_hostname_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fullstack_cancel_after_accept_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test || ( echo test chttp2_fullstack_cancel_after_accept_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fullstack_cancel_after_accept_and_writes_closed_test" @@ -1291,6 +1300,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_legacy_test || ( echo test chttp2_fullstack_thread_stress_legacy_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test || ( echo test chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_fullstack_uds_bad_hostname_test" + $(Q) $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_bad_hostname_test || ( echo test chttp2_fullstack_uds_bad_hostname_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fullstack_uds_cancel_after_accept_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_test || ( echo test chttp2_fullstack_uds_cancel_after_accept_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test" @@ -1387,6 +1398,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_legacy_test || ( echo test chttp2_fullstack_uds_thread_stress_legacy_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test || ( echo test chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_simple_ssl_fullstack_bad_hostname_test" + $(Q) $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test || ( echo test chttp2_simple_ssl_fullstack_bad_hostname_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_fullstack_cancel_after_accept_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test || ( echo test chttp2_simple_ssl_fullstack_cancel_after_accept_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test" @@ -1483,6 +1496,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_legacy_test || ( echo test chttp2_simple_ssl_fullstack_thread_stress_legacy_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test || ( echo test chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test" + $(Q) $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test || ( echo test chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test || ( echo test chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test" @@ -1579,6 +1594,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test || ( echo test chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test || ( echo test chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_socket_pair_bad_hostname_test" + $(Q) $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test || ( echo test chttp2_socket_pair_bad_hostname_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_cancel_after_accept_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test || ( echo test chttp2_socket_pair_cancel_after_accept_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_cancel_after_accept_and_writes_closed_test" @@ -1675,6 +1692,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_legacy_test || ( echo test chttp2_socket_pair_thread_stress_legacy_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test || ( echo test chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test failed ; exit 1 ) + $(E) "[RUN] Testing chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test" + $(Q) $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test || ( echo test chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test || ( echo test chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test" @@ -1825,6 +1844,8 @@ strip-static_cxx: static_cxx ifeq ($(CONFIG),opt) $(E) "[STRIP] Stripping libgrpc++.a" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++.a + $(E) "[STRIP] Stripping libgrpc++_unsecure.a" + $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a endif strip-shared_c: shared_c @@ -1841,6 +1862,8 @@ strip-shared_cxx: shared_cxx ifeq ($(CONFIG),opt) $(E) "[STRIP] Stripping libgrpc++.so" $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) + $(E) "[STRIP] Stripping libgrpc++_unsecure.so" + $(Q) $(STRIP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT) endif strip-shared_csharp: shared_csharp @@ -2000,6 +2023,9 @@ install-static_cxx: static_cxx strip-static_cxx $(E) "[INSTALL] Installing libgrpc++.a" $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(prefix)/lib/libgrpc++.a + $(E) "[INSTALL] Installing libgrpc++_unsecure.a" + $(Q) $(INSTALL) -d $(prefix)/lib + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(prefix)/lib/libgrpc++_unsecure.a @@ -2064,6 +2090,19 @@ ifneq ($(SYSTEM),Darwin) $(Q) ln -sf libgrpc++.$(SHARED_EXT) $(prefix)/lib/libgrpc++.so endif endif +ifeq ($(SYSTEM),MINGW32) + $(E) "[INSTALL] Installing grpc++_unsecure.$(SHARED_EXT)" + $(Q) $(INSTALL) -d $(prefix)/lib + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/grpc++_unsecure.$(SHARED_EXT) $(prefix)/lib/grpc++_unsecure.$(SHARED_EXT) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure-imp.a $(prefix)/lib/libgrpc++_unsecure-imp.a +else + $(E) "[INSTALL] Installing libgrpc++_unsecure.$(SHARED_EXT)" + $(Q) $(INSTALL) -d $(prefix)/lib + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT) $(prefix)/lib/libgrpc++_unsecure.$(SHARED_EXT) +ifneq ($(SYSTEM),Darwin) + $(Q) ln -sf libgrpc++_unsecure.$(SHARED_EXT) $(prefix)/lib/libgrpc++_unsecure.so +endif +endif ifneq ($(SYSTEM),MINGW32) ifneq ($(SYSTEM),Darwin) $(Q) ldconfig || true @@ -2331,7 +2370,6 @@ LIBGRPC_SRC = \ src/core/security/server_secure_chttp2.c \ src/core/surface/init_secure.c \ src/core/surface/secure_channel_create.c \ - src/core/surface/secure_server_create.c \ src/core/tsi/fake_transport_security.c \ src/core/tsi/ssl_transport_security.c \ src/core/tsi/transport_security.c \ @@ -2477,7 +2515,6 @@ src/core/security/security_context.c: $(OPENSSL_DEP) src/core/security/server_secure_chttp2.c: $(OPENSSL_DEP) src/core/surface/init_secure.c: $(OPENSSL_DEP) src/core/surface/secure_channel_create.c: $(OPENSSL_DEP) -src/core/surface/secure_server_create.c: $(OPENSSL_DEP) src/core/tsi/fake_transport_security.c: $(OPENSSL_DEP) src/core/tsi/ssl_transport_security.c: $(OPENSSL_DEP) src/core/tsi/transport_security.c: $(OPENSSL_DEP) @@ -2583,13 +2620,13 @@ $(LIBDIR)/$(CONFIG)/libgrpc.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(LIBGRPC_OBJS) $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc.a $(Q) $(AR) rcs $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBGRPC_OBJS) - $(Q) rm -rf tmp-merge - $(Q) mkdir tmp-merge - $(Q) ( cd tmp-merge ; $(AR) x ../$(LIBDIR)/$(CONFIG)/libgrpc.a ) - $(Q) for l in $(OPENSSL_MERGE_LIBS) ; do ( cd tmp-merge ; ar x ../$${l} ) ; done - $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc.a tmp-merge/__.SYMDEF* - $(Q) ar rcs $(LIBDIR)/$(CONFIG)/libgrpc.a tmp-merge/* - $(Q) rm -rf tmp-merge + $(Q) rm -rf tmp-merge-grpc + $(Q) mkdir tmp-merge-grpc + $(Q) ( cd tmp-merge-grpc ; $(AR) x ../$(LIBDIR)/$(CONFIG)/libgrpc.a ) + $(Q) for l in $(OPENSSL_MERGE_LIBS) ; do ( cd tmp-merge-grpc ; ar x ../$${l} ) ; done + $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc.a tmp-merge-grpc/__.SYMDEF* + $(Q) ar rcs $(LIBDIR)/$(CONFIG)/libgrpc.a tmp-merge-grpc/* + $(Q) rm -rf tmp-merge-grpc ifeq ($(SYSTEM),Darwin) $(Q) ranlib $(LIBDIR)/$(CONFIG)/libgrpc.a endif @@ -2640,7 +2677,6 @@ $(OBJDIR)/$(CONFIG)/src/core/security/security_context.o: $(OBJDIR)/$(CONFIG)/src/core/security/server_secure_chttp2.o: $(OBJDIR)/$(CONFIG)/src/core/surface/init_secure.o: $(OBJDIR)/$(CONFIG)/src/core/surface/secure_channel_create.o: -$(OBJDIR)/$(CONFIG)/src/core/surface/secure_server_create.o: $(OBJDIR)/$(CONFIG)/src/core/tsi/fake_transport_security.o: $(OBJDIR)/$(CONFIG)/src/core/tsi/ssl_transport_security.o: $(OBJDIR)/$(CONFIG)/src/core/tsi/transport_security.o: @@ -3055,17 +3091,21 @@ $(OBJDIR)/$(CONFIG)/src/core/transport/transport.o: LIBGRPC++_SRC = \ + src/cpp/client/secure_credentials.cc \ + src/cpp/server/secure_server_credentials.cc \ src/cpp/client/channel.cc \ src/cpp/client/channel_arguments.cc \ src/cpp/client/client_context.cc \ src/cpp/client/client_unary_call.cc \ src/cpp/client/create_channel.cc \ src/cpp/client/credentials.cc \ + src/cpp/client/insecure_credentials.cc \ src/cpp/client/internal_stub.cc \ src/cpp/common/call.cc \ src/cpp/common/completion_queue.cc \ src/cpp/common/rpc_method.cc \ src/cpp/proto/proto_utils.cc \ + src/cpp/server/insecure_server_credentials.cc \ src/cpp/server/server.cc \ src/cpp/server/server_builder.cc \ src/cpp/server/server_context.cc \ @@ -3132,17 +3172,21 @@ ifneq ($(OPENSSL_DEP),) # This is to ensure the embedded OpenSSL is built beforehand, properly # installing headers to their final destination on the drive. We need this # otherwise parallel compilation will fail if a source is compiled first. +src/cpp/client/secure_credentials.cc: $(OPENSSL_DEP) +src/cpp/server/secure_server_credentials.cc: $(OPENSSL_DEP) src/cpp/client/channel.cc: $(OPENSSL_DEP) src/cpp/client/channel_arguments.cc: $(OPENSSL_DEP) src/cpp/client/client_context.cc: $(OPENSSL_DEP) src/cpp/client/client_unary_call.cc: $(OPENSSL_DEP) src/cpp/client/create_channel.cc: $(OPENSSL_DEP) src/cpp/client/credentials.cc: $(OPENSSL_DEP) +src/cpp/client/insecure_credentials.cc: $(OPENSSL_DEP) src/cpp/client/internal_stub.cc: $(OPENSSL_DEP) src/cpp/common/call.cc: $(OPENSSL_DEP) src/cpp/common/completion_queue.cc: $(OPENSSL_DEP) src/cpp/common/rpc_method.cc: $(OPENSSL_DEP) src/cpp/proto/proto_utils.cc: $(OPENSSL_DEP) +src/cpp/server/insecure_server_credentials.cc: $(OPENSSL_DEP) src/cpp/server/server.cc: $(OPENSSL_DEP) src/cpp/server/server_builder.cc: $(OPENSSL_DEP) src/cpp/server/server_context.cc: $(OPENSSL_DEP) @@ -3167,15 +3211,15 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++.$(SHARED_EXT): $(LIBGRPC++_OBJS) $(ZLIB_DEP)$(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT)$(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++.def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++-imp.a -o $(LIBDIR)/$(CONFIG)/grpc++.$(SHARED_EXT) $(LIBGRPC++_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc-imp + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++.def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++-imp.a -o $(LIBDIR)/$(CONFIG)/grpc++.$(SHARED_EXT) $(LIBGRPC++_OBJS) $(LDLIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc-imp else $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) $(LIBGRPC++_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) $(LIBGRPC++_OBJS) $(LDLIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc else - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) $(LIBGRPC++_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) $(LIBGRPC++_OBJS) $(LDLIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc $(Q) ln -sf libgrpc++.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++.so.0 $(Q) ln -sf libgrpc++.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++.so endif @@ -3191,17 +3235,21 @@ ifneq ($(NO_DEPS),true) endif endif +$(OBJDIR)/$(CONFIG)/src/cpp/client/secure_credentials.o: +$(OBJDIR)/$(CONFIG)/src/cpp/server/secure_server_credentials.o: $(OBJDIR)/$(CONFIG)/src/cpp/client/channel.o: $(OBJDIR)/$(CONFIG)/src/cpp/client/channel_arguments.o: $(OBJDIR)/$(CONFIG)/src/cpp/client/client_context.o: $(OBJDIR)/$(CONFIG)/src/cpp/client/client_unary_call.o: $(OBJDIR)/$(CONFIG)/src/cpp/client/create_channel.o: $(OBJDIR)/$(CONFIG)/src/cpp/client/credentials.o: +$(OBJDIR)/$(CONFIG)/src/cpp/client/insecure_credentials.o: $(OBJDIR)/$(CONFIG)/src/cpp/client/internal_stub.o: $(OBJDIR)/$(CONFIG)/src/cpp/common/call.o: $(OBJDIR)/$(CONFIG)/src/cpp/common/completion_queue.o: $(OBJDIR)/$(CONFIG)/src/cpp/common/rpc_method.o: $(OBJDIR)/$(CONFIG)/src/cpp/proto/proto_utils.o: +$(OBJDIR)/$(CONFIG)/src/cpp/server/insecure_server_credentials.o: $(OBJDIR)/$(CONFIG)/src/cpp/server/server.o: $(OBJDIR)/$(CONFIG)/src/cpp/server/server_builder.o: $(OBJDIR)/$(CONFIG)/src/cpp/server/server_context.o: @@ -3276,6 +3324,125 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/util/create_test_channel.o: $(GENDIR)/test/cpp/util/messages.pb.cc $(GENDIR)/test/cpp/util/echo.pb.cc $(GENDIR)/test/cpp/util/echo_duplicate.pb.cc +LIBGRPC++_UNSECURE_SRC = \ + src/cpp/client/channel.cc \ + src/cpp/client/channel_arguments.cc \ + src/cpp/client/client_context.cc \ + src/cpp/client/client_unary_call.cc \ + src/cpp/client/create_channel.cc \ + src/cpp/client/credentials.cc \ + src/cpp/client/insecure_credentials.cc \ + src/cpp/client/internal_stub.cc \ + src/cpp/common/call.cc \ + src/cpp/common/completion_queue.cc \ + src/cpp/common/rpc_method.cc \ + src/cpp/proto/proto_utils.cc \ + src/cpp/server/insecure_server_credentials.cc \ + src/cpp/server/server.cc \ + src/cpp/server/server_builder.cc \ + src/cpp/server/server_context.cc \ + src/cpp/server/server_credentials.cc \ + src/cpp/server/thread_pool.cc \ + src/cpp/util/status.cc \ + src/cpp/util/time.cc \ + +PUBLIC_HEADERS_CXX += \ + include/grpc++/async_unary_call.h \ + include/grpc++/channel_arguments.h \ + include/grpc++/channel_interface.h \ + include/grpc++/client_context.h \ + include/grpc++/completion_queue.h \ + include/grpc++/config.h \ + include/grpc++/create_channel.h \ + include/grpc++/credentials.h \ + include/grpc++/impl/call.h \ + include/grpc++/impl/client_unary_call.h \ + include/grpc++/impl/internal_stub.h \ + include/grpc++/impl/rpc_method.h \ + include/grpc++/impl/rpc_service_method.h \ + include/grpc++/impl/service_type.h \ + include/grpc++/server.h \ + include/grpc++/server_builder.h \ + include/grpc++/server_context.h \ + include/grpc++/server_credentials.h \ + include/grpc++/status.h \ + include/grpc++/status_code_enum.h \ + include/grpc++/stream.h \ + include/grpc++/thread_pool_interface.h \ + +LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC)))) + +ifeq ($(NO_PROTOBUF),true) + +# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. + +$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a: protobuf_dep_error + +ifeq ($(SYSTEM),MINGW32) +$(LIBDIR)/$(CONFIG)/grpc++_unsecure.$(SHARED_EXT): protobuf_dep_error +else +$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT): protobuf_dep_error +endif + +else + +$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a: $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBGRPC++_UNSECURE_OBJS) + $(E) "[AR] Creating $@" + $(Q) mkdir -p `dirname $@` + $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a + $(Q) $(AR) rcs $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBGRPC++_UNSECURE_OBJS) +ifeq ($(SYSTEM),Darwin) + $(Q) ranlib $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a +endif + + + +ifeq ($(SYSTEM),MINGW32) +$(LIBDIR)/$(CONFIG)/grpc++_unsecure.$(SHARED_EXT): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP)$(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT)$(LIBDIR)/$(CONFIG)/grpc_unsecure.$(SHARED_EXT) + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure.def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure-imp.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure.$(SHARED_EXT) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_unsecure-imp +else +$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT) + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` +ifeq ($(SYSTEM),Darwin) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure +else + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure + $(Q) ln -sf libgrpc++_unsecure.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.so.0 + $(Q) ln -sf libgrpc++_unsecure.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.so +endif +endif + +endif + +ifneq ($(NO_DEPS),true) +-include $(LIBGRPC++_UNSECURE_OBJS:.o=.dep) +endif + +$(OBJDIR)/$(CONFIG)/src/cpp/client/channel.o: +$(OBJDIR)/$(CONFIG)/src/cpp/client/channel_arguments.o: +$(OBJDIR)/$(CONFIG)/src/cpp/client/client_context.o: +$(OBJDIR)/$(CONFIG)/src/cpp/client/client_unary_call.o: +$(OBJDIR)/$(CONFIG)/src/cpp/client/create_channel.o: +$(OBJDIR)/$(CONFIG)/src/cpp/client/credentials.o: +$(OBJDIR)/$(CONFIG)/src/cpp/client/insecure_credentials.o: +$(OBJDIR)/$(CONFIG)/src/cpp/client/internal_stub.o: +$(OBJDIR)/$(CONFIG)/src/cpp/common/call.o: +$(OBJDIR)/$(CONFIG)/src/cpp/common/completion_queue.o: +$(OBJDIR)/$(CONFIG)/src/cpp/common/rpc_method.o: +$(OBJDIR)/$(CONFIG)/src/cpp/proto/proto_utils.o: +$(OBJDIR)/$(CONFIG)/src/cpp/server/insecure_server_credentials.o: +$(OBJDIR)/$(CONFIG)/src/cpp/server/server.o: +$(OBJDIR)/$(CONFIG)/src/cpp/server/server_builder.o: +$(OBJDIR)/$(CONFIG)/src/cpp/server/server_context.o: +$(OBJDIR)/$(CONFIG)/src/cpp/server/server_credentials.o: +$(OBJDIR)/$(CONFIG)/src/cpp/server/thread_pool.o: +$(OBJDIR)/$(CONFIG)/src/cpp/util/status.o: +$(OBJDIR)/$(CONFIG)/src/cpp/util/time.o: + + LIBPUBSUB_CLIENT_LIB_SRC = \ $(GENDIR)/examples/pubsub/label.pb.cc \ $(GENDIR)/examples/pubsub/empty.pb.cc \ @@ -3344,6 +3511,68 @@ $(OBJDIR)/$(CONFIG)/examples/pubsub/publisher.o: $(GENDIR)/examples/pubsub/l $(OBJDIR)/$(CONFIG)/examples/pubsub/subscriber.o: $(GENDIR)/examples/pubsub/label.pb.cc $(GENDIR)/examples/pubsub/empty.pb.cc $(GENDIR)/examples/pubsub/pubsub.pb.cc +LIBQPS_SRC = \ + $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ + test/cpp/qps/driver.cc \ + test/cpp/qps/timer.cc \ + + +LIBQPS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBQPS_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure libraries if you don't have OpenSSL with ALPN. + +$(LIBDIR)/$(CONFIG)/libqps.a: openssl_dep_error + + +else + +ifeq ($(NO_PROTOBUF),true) + +# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. + +$(LIBDIR)/$(CONFIG)/libqps.a: protobuf_dep_error + + +else + +ifneq ($(OPENSSL_DEP),) +# This is to ensure the embedded OpenSSL is built beforehand, properly +# installing headers to their final destination on the drive. We need this +# otherwise parallel compilation will fail if a source is compiled first. +test/cpp/qps/qpstest.proto: $(OPENSSL_DEP) +test/cpp/qps/driver.cc: $(OPENSSL_DEP) +test/cpp/qps/timer.cc: $(OPENSSL_DEP) +endif + +$(LIBDIR)/$(CONFIG)/libqps.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBQPS_OBJS) + $(E) "[AR] Creating $@" + $(Q) mkdir -p `dirname $@` + $(Q) rm -f $(LIBDIR)/$(CONFIG)/libqps.a + $(Q) $(AR) rcs $(LIBDIR)/$(CONFIG)/libqps.a $(LIBQPS_OBJS) +ifeq ($(SYSTEM),Darwin) + $(Q) ranlib $(LIBDIR)/$(CONFIG)/libqps.a +endif + + + + +endif + +endif + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(LIBQPS_OBJS:.o=.dep) +endif +endif + + +$(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc +$(OBJDIR)/$(CONFIG)/test/cpp/qps/timer.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc + + LIBGRPC_CSHARP_EXT_SRC = \ src/csharp/ext/grpc_csharp_ext.c \ @@ -3387,15 +3616,15 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc_csharp_ext.$(SHARED_EXT): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP)$(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT)$(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext.def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext-imp.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext.$(SHARED_EXT) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr-imp -lgrpc-imp + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext.def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext-imp.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext.$(SHARED_EXT) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) -lgpr-imp -lgrpc-imp else $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr -lgrpc + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) -lgpr -lgrpc else - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr -lgrpc + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.0 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) -lgpr -lgrpc $(Q) ln -sf libgrpc_csharp_ext.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.so.0 $(Q) ln -sf libgrpc_csharp_ext.$(SHARED_EXT) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.so endif @@ -3734,6 +3963,31 @@ endif $(OBJDIR)/$(CONFIG)/test/core/end2end/fixtures/chttp2_socket_pair_one_byte_at_a_time.o: +LIBEND2END_TEST_BAD_HOSTNAME_SRC = \ + test/core/end2end/tests/bad_hostname.c \ + + +LIBEND2END_TEST_BAD_HOSTNAME_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBEND2END_TEST_BAD_HOSTNAME_SRC)))) + +$(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a: $(ZLIB_DEP) $(LIBEND2END_TEST_BAD_HOSTNAME_OBJS) + $(E) "[AR] Creating $@" + $(Q) mkdir -p `dirname $@` + $(Q) rm -f $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a + $(Q) $(AR) rcs $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBEND2END_TEST_BAD_HOSTNAME_OBJS) +ifeq ($(SYSTEM),Darwin) + $(Q) ranlib $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a +endif + + + + +ifneq ($(NO_DEPS),true) +-include $(LIBEND2END_TEST_BAD_HOSTNAME_OBJS:.o=.dep) +endif + +$(OBJDIR)/$(CONFIG)/test/core/end2end/tests/bad_hostname.o: + + LIBEND2END_TEST_CANCEL_AFTER_ACCEPT_SRC = \ test/core/end2end/tests/cancel_after_accept.c \ @@ -7925,16 +8179,16 @@ $(BINDIR)/$(CONFIG)/pubsub_client: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/pubsub_client: $(PROTOBUF_DEP) $(PUBSUB_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.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)/pubsub_client: $(PROTOBUF_DEP) $(PUBSUB_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.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) $(PUBSUB_CLIENT_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.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) -o $(BINDIR)/$(CONFIG)/pubsub_client + $(Q) $(LDXX) $(LDFLAGS) $(PUBSUB_CLIENT_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.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) -o $(BINDIR)/$(CONFIG)/pubsub_client endif endif -$(OBJDIR)/$(CONFIG)/examples/pubsub/main.o: $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.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)/examples/pubsub/main.o: $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.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_pubsub_client: $(PUBSUB_CLIENT_OBJS:.o=.dep) @@ -8029,17 +8283,16 @@ endif endif -QPS_CLIENT_SRC = \ - $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ - test/cpp/qps/client.cc \ +QPS_DRIVER_SRC = \ + test/cpp/qps/qps_driver.cc \ -QPS_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_CLIENT_SRC)))) +QPS_DRIVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_DRIVER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL with ALPN. -$(BINDIR)/$(CONFIG)/qps_client: openssl_dep_error +$(BINDIR)/$(CONFIG)/qps_driver: openssl_dep_error else @@ -8048,86 +8301,44 @@ ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. -$(BINDIR)/$(CONFIG)/qps_client: protobuf_dep_error +$(BINDIR)/$(CONFIG)/qps_driver: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/qps_client: $(PROTOBUF_DEP) $(QPS_CLIENT_OBJS) $(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)/qps_driver: $(PROTOBUF_DEP) $(QPS_DRIVER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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) $(QPS_CLIENT_OBJS) $(GTEST_LIB) $(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) -o $(BINDIR)/$(CONFIG)/qps_client + $(Q) $(LDXX) $(LDFLAGS) $(QPS_DRIVER_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libqps.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) -o $(BINDIR)/$(CONFIG)/qps_driver endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/qps/qpstest.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -$(OBJDIR)/$(CONFIG)/test/cpp/qps/client.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_driver.o: $(LIBDIR)/$(CONFIG)/libqps.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_qps_client: $(QPS_CLIENT_OBJS:.o=.dep) +deps_qps_driver: $(QPS_DRIVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(QPS_CLIENT_OBJS:.o=.dep) +-include $(QPS_DRIVER_OBJS:.o=.dep) endif endif -QPS_CLIENT_ASYNC_SRC = \ - $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ +QPS_WORKER_SRC = \ test/cpp/qps/client_async.cc \ + test/cpp/qps/client_sync.cc \ + test/cpp/qps/server_async.cc \ + test/cpp/qps/server_sync.cc \ + test/cpp/qps/worker.cc \ -QPS_CLIENT_ASYNC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_CLIENT_ASYNC_SRC)))) - -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/qps_client_async: openssl_dep_error - -else - - -ifeq ($(NO_PROTOBUF),true) - -# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. - -$(BINDIR)/$(CONFIG)/qps_client_async: protobuf_dep_error - -else - -$(BINDIR)/$(CONFIG)/qps_client_async: $(PROTOBUF_DEP) $(QPS_CLIENT_ASYNC_OBJS) $(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) $(QPS_CLIENT_ASYNC_OBJS) $(GTEST_LIB) $(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) -o $(BINDIR)/$(CONFIG)/qps_client_async - -endif - -endif - -$(OBJDIR)/$(CONFIG)/test/cpp/qps/qpstest.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - -deps_qps_client_async: $(QPS_CLIENT_ASYNC_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(QPS_CLIENT_ASYNC_OBJS:.o=.dep) -endif -endif - - -QPS_SERVER_SRC = \ - $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ - test/cpp/qps/server.cc \ - -QPS_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_SERVER_SRC)))) +QPS_WORKER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_WORKER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL with ALPN. -$(BINDIR)/$(CONFIG)/qps_server: openssl_dep_error +$(BINDIR)/$(CONFIG)/qps_worker: openssl_dep_error else @@ -8136,42 +8347,44 @@ ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. -$(BINDIR)/$(CONFIG)/qps_server: protobuf_dep_error +$(BINDIR)/$(CONFIG)/qps_worker: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/qps_server: $(PROTOBUF_DEP) $(QPS_SERVER_OBJS) $(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)/qps_worker: $(PROTOBUF_DEP) $(QPS_WORKER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.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) $(QPS_SERVER_OBJS) $(GTEST_LIB) $(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) -o $(BINDIR)/$(CONFIG)/qps_server + $(Q) $(LDXX) $(LDFLAGS) $(QPS_WORKER_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libqps.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) -o $(BINDIR)/$(CONFIG)/qps_worker endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/qps/qpstest.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -$(OBJDIR)/$(CONFIG)/test/cpp/qps/server.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(LIBDIR)/$(CONFIG)/libqps.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/qps/client_sync.o: $(LIBDIR)/$(CONFIG)/libqps.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/qps/server_async.o: $(LIBDIR)/$(CONFIG)/libqps.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/qps/server_sync.o: $(LIBDIR)/$(CONFIG)/libqps.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/qps/worker.o: $(LIBDIR)/$(CONFIG)/libqps.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_qps_server: $(QPS_SERVER_OBJS:.o=.dep) +deps_qps_worker: $(QPS_WORKER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(QPS_SERVER_OBJS:.o=.dep) +-include $(QPS_WORKER_OBJS:.o=.dep) endif endif -QPS_SERVER_ASYNC_SRC = \ - $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ - test/cpp/qps/server_async.cc \ +STATUS_TEST_SRC = \ + test/cpp/util/status_test.cc \ -QPS_SERVER_ASYNC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_SERVER_ASYNC_SRC)))) +STATUS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STATUS_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL with ALPN. -$(BINDIR)/$(CONFIG)/qps_server_async: openssl_dep_error +$(BINDIR)/$(CONFIG)/status_test: openssl_dep_error else @@ -8180,41 +8393,40 @@ ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. -$(BINDIR)/$(CONFIG)/qps_server_async: protobuf_dep_error +$(BINDIR)/$(CONFIG)/status_test: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/qps_server_async: $(PROTOBUF_DEP) $(QPS_SERVER_ASYNC_OBJS) $(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)/status_test: $(PROTOBUF_DEP) $(STATUS_TEST_OBJS) $(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) $(QPS_SERVER_ASYNC_OBJS) $(GTEST_LIB) $(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) -o $(BINDIR)/$(CONFIG)/qps_server_async + $(Q) $(LDXX) $(LDFLAGS) $(STATUS_TEST_OBJS) $(GTEST_LIB) $(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) -o $(BINDIR)/$(CONFIG)/status_test endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/qps/qpstest.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/util/status_test.o: $(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_qps_server_async: $(QPS_SERVER_ASYNC_OBJS:.o=.dep) +deps_status_test: $(STATUS_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(QPS_SERVER_ASYNC_OBJS:.o=.dep) +-include $(STATUS_TEST_OBJS:.o=.dep) endif endif -STATUS_TEST_SRC = \ - test/cpp/util/status_test.cc \ +THREAD_POOL_TEST_SRC = \ + test/cpp/server/thread_pool_test.cc \ -STATUS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(STATUS_TEST_SRC)))) +THREAD_POOL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(THREAD_POOL_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL with ALPN. -$(BINDIR)/$(CONFIG)/status_test: openssl_dep_error +$(BINDIR)/$(CONFIG)/thread_pool_test: openssl_dep_error else @@ -8223,68 +8435,55 @@ ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. -$(BINDIR)/$(CONFIG)/status_test: protobuf_dep_error +$(BINDIR)/$(CONFIG)/thread_pool_test: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/status_test: $(PROTOBUF_DEP) $(STATUS_TEST_OBJS) $(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)/thread_pool_test: $(PROTOBUF_DEP) $(THREAD_POOL_TEST_OBJS) $(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) $(STATUS_TEST_OBJS) $(GTEST_LIB) $(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) -o $(BINDIR)/$(CONFIG)/status_test + $(Q) $(LDXX) $(LDFLAGS) $(THREAD_POOL_TEST_OBJS) $(GTEST_LIB) $(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) -o $(BINDIR)/$(CONFIG)/thread_pool_test endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/util/status_test.o: $(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/server/thread_pool_test.o: $(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_status_test: $(STATUS_TEST_OBJS:.o=.dep) +deps_thread_pool_test: $(THREAD_POOL_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(STATUS_TEST_OBJS:.o=.dep) +-include $(THREAD_POOL_TEST_OBJS:.o=.dep) endif endif -THREAD_POOL_TEST_SRC = \ - test/cpp/server/thread_pool_test.cc \ +CHTTP2_FAKE_SECURITY_BAD_HOSTNAME_TEST_SRC = \ -THREAD_POOL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(THREAD_POOL_TEST_SRC)))) +CHTTP2_FAKE_SECURITY_BAD_HOSTNAME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FAKE_SECURITY_BAD_HOSTNAME_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL with ALPN. -$(BINDIR)/$(CONFIG)/thread_pool_test: openssl_dep_error +$(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test: openssl_dep_error else - -ifeq ($(NO_PROTOBUF),true) - -# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. - -$(BINDIR)/$(CONFIG)/thread_pool_test: protobuf_dep_error - -else - -$(BINDIR)/$(CONFIG)/thread_pool_test: $(PROTOBUF_DEP) $(THREAD_POOL_TEST_OBJS) $(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)/chttp2_fake_security_bad_hostname_test: $(CHTTP2_FAKE_SECURITY_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(THREAD_POOL_TEST_OBJS) $(GTEST_LIB) $(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) -o $(BINDIR)/$(CONFIG)/thread_pool_test - -endif + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_FAKE_SECURITY_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/chttp2_fake_security_bad_hostname_test endif -$(OBJDIR)/$(CONFIG)/test/cpp/server/thread_pool_test.o: $(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_thread_pool_test: $(THREAD_POOL_TEST_OBJS:.o=.dep) +deps_chttp2_fake_security_bad_hostname_test: $(CHTTP2_FAKE_SECURITY_BAD_HOSTNAME_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(THREAD_POOL_TEST_OBJS:.o=.dep) +-include $(CHTTP2_FAKE_SECURITY_BAD_HOSTNAME_TEST_OBJS:.o=.dep) endif endif @@ -9681,6 +9880,35 @@ endif endif +CHTTP2_FULLSTACK_BAD_HOSTNAME_TEST_SRC = \ + +CHTTP2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FULLSTACK_BAD_HOSTNAME_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test: $(CHTTP2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/chttp2_fullstack_bad_hostname_test + +endif + + +deps_chttp2_fullstack_bad_hostname_test: $(CHTTP2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS:.o=.dep) +endif +endif + + CHTTP2_FULLSTACK_CANCEL_AFTER_ACCEPT_TEST_SRC = \ CHTTP2_FULLSTACK_CANCEL_AFTER_ACCEPT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FULLSTACK_CANCEL_AFTER_ACCEPT_TEST_SRC)))) @@ -11073,6 +11301,35 @@ endif endif +CHTTP2_FULLSTACK_UDS_BAD_HOSTNAME_TEST_SRC = \ + +CHTTP2_FULLSTACK_UDS_BAD_HOSTNAME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FULLSTACK_UDS_BAD_HOSTNAME_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_bad_hostname_test: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_bad_hostname_test: $(CHTTP2_FULLSTACK_UDS_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack_uds.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_FULLSTACK_UDS_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack_uds.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_bad_hostname_test + +endif + + +deps_chttp2_fullstack_uds_bad_hostname_test: $(CHTTP2_FULLSTACK_UDS_BAD_HOSTNAME_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_FULLSTACK_UDS_BAD_HOSTNAME_TEST_OBJS:.o=.dep) +endif +endif + + CHTTP2_FULLSTACK_UDS_CANCEL_AFTER_ACCEPT_TEST_SRC = \ CHTTP2_FULLSTACK_UDS_CANCEL_AFTER_ACCEPT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FULLSTACK_UDS_CANCEL_AFTER_ACCEPT_TEST_SRC)))) @@ -12465,6 +12722,35 @@ endif endif +CHTTP2_SIMPLE_SSL_FULLSTACK_BAD_HOSTNAME_TEST_SRC = \ + +CHTTP2_SIMPLE_SSL_FULLSTACK_BAD_HOSTNAME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SIMPLE_SSL_FULLSTACK_BAD_HOSTNAME_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test: $(CHTTP2_SIMPLE_SSL_FULLSTACK_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_SIMPLE_SSL_FULLSTACK_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_bad_hostname_test + +endif + + +deps_chttp2_simple_ssl_fullstack_bad_hostname_test: $(CHTTP2_SIMPLE_SSL_FULLSTACK_BAD_HOSTNAME_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_SIMPLE_SSL_FULLSTACK_BAD_HOSTNAME_TEST_OBJS:.o=.dep) +endif +endif + + CHTTP2_SIMPLE_SSL_FULLSTACK_CANCEL_AFTER_ACCEPT_TEST_SRC = \ CHTTP2_SIMPLE_SSL_FULLSTACK_CANCEL_AFTER_ACCEPT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SIMPLE_SSL_FULLSTACK_CANCEL_AFTER_ACCEPT_TEST_SRC)))) @@ -13857,6 +14143,35 @@ endif endif +CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_BAD_HOSTNAME_TEST_SRC = \ + +CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_BAD_HOSTNAME_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test: $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test + +endif + + +deps_chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test: $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_BAD_HOSTNAME_TEST_OBJS:.o=.dep) +endif +endif + + CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CANCEL_AFTER_ACCEPT_TEST_SRC = \ CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CANCEL_AFTER_ACCEPT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SIMPLE_SSL_WITH_OAUTH2_FULLSTACK_CANCEL_AFTER_ACCEPT_TEST_SRC)))) @@ -15249,6 +15564,35 @@ endif endif +CHTTP2_SOCKET_PAIR_BAD_HOSTNAME_TEST_SRC = \ + +CHTTP2_SOCKET_PAIR_BAD_HOSTNAME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SOCKET_PAIR_BAD_HOSTNAME_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test: $(CHTTP2_SOCKET_PAIR_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_SOCKET_PAIR_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/chttp2_socket_pair_bad_hostname_test + +endif + + +deps_chttp2_socket_pair_bad_hostname_test: $(CHTTP2_SOCKET_PAIR_BAD_HOSTNAME_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_SOCKET_PAIR_BAD_HOSTNAME_TEST_OBJS:.o=.dep) +endif +endif + + CHTTP2_SOCKET_PAIR_CANCEL_AFTER_ACCEPT_TEST_SRC = \ CHTTP2_SOCKET_PAIR_CANCEL_AFTER_ACCEPT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SOCKET_PAIR_CANCEL_AFTER_ACCEPT_TEST_SRC)))) @@ -16641,6 +16985,35 @@ endif endif +CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_BAD_HOSTNAME_TEST_SRC = \ + +CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_BAD_HOSTNAME_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_BAD_HOSTNAME_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test: $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_BAD_HOSTNAME_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a $(LIBDIR)/$(CONFIG)/libend2end_test_bad_hostname.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test + +endif + + +deps_chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test: $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_BAD_HOSTNAME_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_BAD_HOSTNAME_TEST_OBJS:.o=.dep) +endif +endif + + CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CANCEL_AFTER_ACCEPT_TEST_SRC = \ CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CANCEL_AFTER_ACCEPT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_SOCKET_PAIR_ONE_BYTE_AT_A_TIME_CANCEL_AFTER_ACCEPT_TEST_SRC)))) diff --git a/README.md b/README.md index 8fa9fa4956e36f809fdc8741ef87e208d23c2093..fa60b83d1620c70a49c340ee9517b8b2b2f76caa 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[](https://travis-ci.org/grpc/grpc) + [gRPC - An RPC library and framework](http://github.com/grpc/grpc) =================================== diff --git a/build.json b/build.json index cfba96180f095f0663de96a32b9ff6da22d0ad90..c9500ebe1bd781a9b3249d3a284e27a34172e491 100644 --- a/build.json +++ b/build.json @@ -9,6 +9,61 @@ } }, "filegroups": [ + { + "name": "grpc++_base", + "public_headers": [ + "include/grpc++/async_unary_call.h", + "include/grpc++/channel_arguments.h", + "include/grpc++/channel_interface.h", + "include/grpc++/client_context.h", + "include/grpc++/completion_queue.h", + "include/grpc++/config.h", + "include/grpc++/create_channel.h", + "include/grpc++/credentials.h", + "include/grpc++/impl/call.h", + "include/grpc++/impl/client_unary_call.h", + "include/grpc++/impl/internal_stub.h", + "include/grpc++/impl/rpc_method.h", + "include/grpc++/impl/rpc_service_method.h", + "include/grpc++/impl/service_type.h", + "include/grpc++/server.h", + "include/grpc++/server_builder.h", + "include/grpc++/server_context.h", + "include/grpc++/server_credentials.h", + "include/grpc++/status.h", + "include/grpc++/status_code_enum.h", + "include/grpc++/stream.h", + "include/grpc++/thread_pool_interface.h" + ], + "headers": [ + "src/cpp/client/channel.h", + "src/cpp/proto/proto_utils.h", + "src/cpp/server/thread_pool.h", + "src/cpp/util/time.h" + ], + "src": [ + "src/cpp/client/channel.cc", + "src/cpp/client/channel_arguments.cc", + "src/cpp/client/client_context.cc", + "src/cpp/client/client_unary_call.cc", + "src/cpp/client/create_channel.cc", + "src/cpp/client/credentials.cc", + "src/cpp/client/insecure_credentials.cc", + "src/cpp/client/internal_stub.cc", + "src/cpp/common/call.cc", + "src/cpp/common/completion_queue.cc", + "src/cpp/common/rpc_method.cc", + "src/cpp/proto/proto_utils.cc", + "src/cpp/server/insecure_server_credentials.cc", + "src/cpp/server/server.cc", + "src/cpp/server/server_builder.cc", + "src/cpp/server/server_context.cc", + "src/cpp/server/server_credentials.cc", + "src/cpp/server/thread_pool.cc", + "src/cpp/util/status.cc", + "src/cpp/util/time.cc" + ] + }, { "name": "grpc_base", "public_headers": [ @@ -80,7 +135,6 @@ "src/core/surface/completion_queue.h", "src/core/surface/event_string.h", "src/core/surface/init.h", - "src/core/surface/lame_client.h", "src/core/surface/server.h", "src/core/surface/surface_trace.h", "src/core/transport/chttp2/bin_encoder.h", @@ -276,7 +330,7 @@ "src/core/support/time_posix.c", "src/core/support/time_win32.c" ], - "secure": false, + "secure": "no", "vs_project_guid": "{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}" }, { @@ -333,7 +387,6 @@ "src/core/security/server_secure_chttp2.c", "src/core/surface/init_secure.c", "src/core/surface/secure_channel_create.c", - "src/core/surface/secure_server_create.c", "src/core/tsi/fake_transport_security.c", "src/core/tsi/ssl_transport_security.c", "src/core/tsi/transport_security.c" @@ -345,7 +398,7 @@ "filegroups": [ "grpc_base" ], - "secure": true, + "secure": "yes", "vs_project_guid": "{29D16885-7228-4C31-81ED-5F9187C7F2A9}" }, { @@ -385,68 +438,26 @@ "filegroups": [ "grpc_base" ], - "secure": false, + "secure": "no", "vs_project_guid": "{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}" }, { "name": "grpc++", "build": "all", "language": "c++", - "public_headers": [ - "include/grpc++/async_unary_call.h", - "include/grpc++/channel_arguments.h", - "include/grpc++/channel_interface.h", - "include/grpc++/client_context.h", - "include/grpc++/completion_queue.h", - "include/grpc++/config.h", - "include/grpc++/create_channel.h", - "include/grpc++/credentials.h", - "include/grpc++/impl/call.h", - "include/grpc++/impl/client_unary_call.h", - "include/grpc++/impl/internal_stub.h", - "include/grpc++/impl/rpc_method.h", - "include/grpc++/impl/rpc_service_method.h", - "include/grpc++/impl/service_type.h", - "include/grpc++/server.h", - "include/grpc++/server_builder.h", - "include/grpc++/server_context.h", - "include/grpc++/server_credentials.h", - "include/grpc++/status.h", - "include/grpc++/status_code_enum.h", - "include/grpc++/stream.h", - "include/grpc++/thread_pool_interface.h" - ], - "headers": [ - "src/cpp/client/channel.h", - "src/cpp/proto/proto_utils.h", - "src/cpp/server/thread_pool.h", - "src/cpp/util/time.h" - ], "src": [ - "src/cpp/client/channel.cc", - "src/cpp/client/channel_arguments.cc", - "src/cpp/client/client_context.cc", - "src/cpp/client/client_unary_call.cc", - "src/cpp/client/create_channel.cc", - "src/cpp/client/credentials.cc", - "src/cpp/client/internal_stub.cc", - "src/cpp/common/call.cc", - "src/cpp/common/completion_queue.cc", - "src/cpp/common/rpc_method.cc", - "src/cpp/proto/proto_utils.cc", - "src/cpp/server/server.cc", - "src/cpp/server/server_builder.cc", - "src/cpp/server/server_context.cc", - "src/cpp/server/server_credentials.cc", - "src/cpp/server/thread_pool.cc", - "src/cpp/util/status.cc", - "src/cpp/util/time.cc" + "src/cpp/client/secure_credentials.cc", + "src/cpp/server/secure_server_credentials.cc" ], "deps": [ "gpr", "grpc" ], - "secure": true, + "baselib": true, + "filegroups": [ + "grpc++_base" + ], + "secure": "check", "vs_project_guid": "{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}" }, { @@ -460,6 +471,20 @@ "test/cpp/util/create_test_channel.cc" ] }, + { + "name": "grpc++_unsecure", + "build": "all", + "language": "c++", + "deps": [ + "gpr", + "grpc_unsecure" + ], + "baselib": true, + "filegroups": [ + "grpc++_base" + ], + "secure": "no" + }, { "name": "pubsub_client_lib", "build": "private", @@ -477,6 +502,20 @@ "gpr" ] }, + { + "name": "qps", + "build": "private", + "language": "c++", + "headers": [ + "test/cpp/qps/driver.h", + "test/cpp/qps/timer.h" + ], + "src": [ + "test/cpp/qps/qpstest.proto", + "test/cpp/qps/driver.cc", + "test/cpp/qps/timer.cc" + ] + }, { "name": "grpc_csharp_ext", "build": "all", @@ -1672,7 +1711,7 @@ "src/compiler/cpp_plugin.cc" ], "deps": [], - "secure": false + "secure": "no" }, { "name": "grpc_python_plugin", @@ -1686,7 +1725,7 @@ "src/compiler/python_plugin.cc" ], "deps": [], - "secure": false + "secure": "no" }, { "name": "grpc_ruby_plugin", @@ -1697,7 +1736,7 @@ "src/compiler/ruby_plugin.cc" ], "deps": [], - "secure": false + "secure": "no" }, { "name": "interop_client", @@ -1763,7 +1802,6 @@ ], "deps": [ "pubsub_client_lib", - "grpc++_test_util", "grpc_test_util", "grpc++", "grpc", @@ -1806,15 +1844,15 @@ ] }, { - "name": "qps_client", + "name": "qps_driver", "build": "test", "run": false, "language": "c++", "src": [ - "test/cpp/qps/qpstest.proto", - "test/cpp/qps/client.cc" + "test/cpp/qps/qps_driver.cc" ], "deps": [ + "qps", "grpc++_test_util", "grpc_test_util", "grpc++", @@ -1824,51 +1862,23 @@ ] }, { - "name": "qps_client_async", + "name": "qps_worker", "build": "test", "run": false, "language": "c++", - "src": [ - "test/cpp/qps/qpstest.proto", - "test/cpp/qps/client_async.cc" - ], - "deps": [ - "grpc++_test_util", - "grpc_test_util", - "grpc++", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "qps_server", - "build": "test", - "run": false, - "language": "c++", - "src": [ - "test/cpp/qps/qpstest.proto", - "test/cpp/qps/server.cc" + "headers": [ + "test/cpp/qps/client.h", + "test/cpp/qps/server.h" ], - "deps": [ - "grpc++_test_util", - "grpc_test_util", - "grpc++", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "qps_server_async", - "build": "test", - "run": false, - "language": "c++", "src": [ - "test/cpp/qps/qpstest.proto", - "test/cpp/qps/server_async.cc" + "test/cpp/qps/client_async.cc", + "test/cpp/qps/client_sync.cc", + "test/cpp/qps/server_async.cc", + "test/cpp/qps/server_sync.cc", + "test/cpp/qps/worker.cc" ], "deps": [ + "qps", "grpc++_test_util", "grpc_test_util", "grpc++", diff --git a/examples/pubsub/main.cc b/examples/pubsub/main.cc index 39fb8aea15c8cf5355bf841c5cdba410aede88ff..6f7737e2476ffa04088321e39210bcf7a486182e 100644 --- a/examples/pubsub/main.cc +++ b/examples/pubsub/main.cc @@ -41,6 +41,7 @@ #include <grpc/grpc.h> #include <grpc/support/log.h> #include <gflags/gflags.h> +#include <grpc++/channel_arguments.h> #include <grpc++/channel_interface.h> #include <grpc++/create_channel.h> #include <grpc++/credentials.h> @@ -48,17 +49,11 @@ #include "examples/pubsub/publisher.h" #include "examples/pubsub/subscriber.h" -#include "test/cpp/util/create_test_channel.h" DEFINE_int32(server_port, 443, "Server port."); DEFINE_string(server_host, "pubsub-staging.googleapis.com", "Server host to connect to"); DEFINE_string(project_id, "", "GCE project id such as stoked-keyword-656"); -DEFINE_string(service_account_key_file, "", - "Path to service account json key file."); -DEFINE_string(oauth_scope, - "https://www.googleapis.com/auth/cloud-platform", - "Scope for OAuth tokens."); // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. @@ -75,17 +70,6 @@ const char kMessageData[] = "Test Data"; } // namespace -grpc::string GetServiceAccountJsonKey() { - grpc::string json_key; - if (json_key.empty()) { - std::ifstream json_key_file(FLAGS_service_account_key_file); - std::stringstream key_stream; - key_stream << json_key_file.rdbuf(); - json_key = key_stream.str(); - } - return json_key; -} - int main(int argc, char** argv) { grpc_init(); ParseCommandLineFlags(&argc, &argv, true); @@ -93,23 +77,11 @@ int main(int argc, char** argv) { std::ostringstream ss; - std::unique_ptr<grpc::Credentials> creds; - if (FLAGS_service_account_key_file != "") { - grpc::string json_key = GetServiceAccountJsonKey(); - creds = grpc::CredentialsFactory::ServiceAccountCredentials( - json_key, FLAGS_oauth_scope, std::chrono::hours(1)); - } else { - creds = grpc::CredentialsFactory::ComputeEngineCredentials(); - } - ss << FLAGS_server_host << ":" << FLAGS_server_port; - std::shared_ptr<grpc::ChannelInterface> channel( - grpc::CreateTestChannel( - ss.str(), - FLAGS_server_host, - true, // enable SSL - true, // use prod roots - creds)); + + std::unique_ptr<grpc::Credentials> creds = grpc::GoogleDefaultCredentials(); + std::shared_ptr<grpc::ChannelInterface> channel = + grpc::CreateChannel(ss.str(), creds, grpc::ChannelArguments()); grpc::examples::pubsub::Publisher publisher(channel); grpc::examples::pubsub::Subscriber subscriber(channel); @@ -129,6 +101,7 @@ int main(int argc, char** argv) { subscription_name, &subscription_topic).IsOk()) { subscriber.DeleteSubscription(subscription_name); } + if (publisher.GetTopic(topic).IsOk()) publisher.DeleteTopic(topic); grpc::Status s = publisher.CreateTopic(topic); diff --git a/examples/pubsub/publisher_test.cc b/examples/pubsub/publisher_test.cc index c988b4802ebacc3fc658a2c348607f7fafb33640..f9b6bb3418d21fcfcc7db4a5af343bb25ff540dd 100644 --- a/examples/pubsub/publisher_test.cc +++ b/examples/pubsub/publisher_test.cc @@ -40,6 +40,7 @@ #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> #include <grpc++/status.h> #include <gtest/gtest.h> @@ -106,12 +107,11 @@ class PublisherTest : public ::testing::Test { int port = grpc_pick_unused_port_or_die(); server_address_ << "localhost:" << port; ServerBuilder builder; - builder.AddPort(server_address_.str()); + builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials()); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - channel_ = - CreateChannelDeprecated(server_address_.str(), ChannelArguments()); + channel_ = CreateChannel(server_address_.str(), grpc::InsecureCredentials(), ChannelArguments()); publisher_.reset(new grpc::examples::pubsub::Publisher(channel_)); } diff --git a/examples/pubsub/subscriber_test.cc b/examples/pubsub/subscriber_test.cc index 4ff125f4b3ae9d0dd068f39d8e72a7c898455602..2d606336adde9177fd040256bff9909c2dddb36a 100644 --- a/examples/pubsub/subscriber_test.cc +++ b/examples/pubsub/subscriber_test.cc @@ -40,6 +40,7 @@ #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> #include <grpc++/status.h> #include <gtest/gtest.h> @@ -104,12 +105,11 @@ class SubscriberTest : public ::testing::Test { int port = grpc_pick_unused_port_or_die(); server_address_ << "localhost:" << port; ServerBuilder builder; - builder.AddPort(server_address_.str()); + builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials()); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - channel_ = - CreateChannelDeprecated(server_address_.str(), ChannelArguments()); + channel_ = CreateChannel(server_address_.str(), grpc::InsecureCredentials(), ChannelArguments()); subscriber_.reset(new grpc::examples::pubsub::Subscriber(channel_)); } diff --git a/include/grpc++/async_unary_call.h b/include/grpc++/async_unary_call.h index 71b7d3ff85831da36a1222cf89d118f2def628e5..658941bb6d47ed78b5e4d8f8508367bb19490aea 100644 --- a/include/grpc++/async_unary_call.h +++ b/include/grpc++/async_unary_call.h @@ -49,7 +49,7 @@ class ClientAsyncResponseReader GRPC_FINAL { public: ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, - const google::protobuf::Message& request, void* tag) + const grpc::protobuf::Message& request, void* tag) : context_(context), call_(channel->CreateCall(method, context, cq)) { init_buf_.Reset(tag); @@ -77,7 +77,6 @@ class ClientAsyncResponseReader GRPC_FINAL { call_.PerformOps(&finish_buf_); } - private: ClientContext* context_; Call call_; @@ -93,7 +92,7 @@ class ServerAsyncResponseWriter GRPC_FINAL explicit ServerAsyncResponseWriter(ServerContext* ctx) : call_(nullptr, nullptr, nullptr), ctx_(ctx) {} - void SendInitialMetadata(void* tag) { + void SendInitialMetadata(void* tag) GRPC_OVERRIDE { GPR_ASSERT(!ctx_->sent_initial_metadata_); meta_buf_.Reset(tag); diff --git a/include/grpc++/channel_arguments.h b/include/grpc++/channel_arguments.h index ad96ef14ae3ed6832be58adbdc7c7782418726ec..8d338c654ec5ae171e914ce36ddba04db561031d 100644 --- a/include/grpc++/channel_arguments.h +++ b/include/grpc++/channel_arguments.h @@ -62,8 +62,11 @@ class ChannelArguments { void SetInt(const grpc::string& key, int value); void SetString(const grpc::string& key, const grpc::string& value); + // Populates given channel_args with args_, does not take ownership. + void SetChannelArgs(grpc_channel_args* channel_args) const; + private: - friend class Channel; + friend class SecureCredentials; friend class testing::ChannelArgumentsTest; // TODO(yangg) implement copy and assign @@ -73,9 +76,6 @@ class ChannelArguments { // Returns empty string when it is not set. grpc::string GetSslTargetNameOverride() const; - // Populates given channel_args with args_, does not take ownership. - void SetChannelArgs(grpc_channel_args* channel_args) const; - std::vector<grpc_arg> args_; std::list<grpc::string> strings_; }; diff --git a/include/grpc++/channel_interface.h b/include/grpc++/channel_interface.h index 77d1363618424736fd2edf00add1d9c8e4a94159..51260aed3d708f1e1cb2d9bac07f142ada4df13d 100644 --- a/include/grpc++/channel_interface.h +++ b/include/grpc++/channel_interface.h @@ -37,12 +37,6 @@ #include <grpc++/status.h> #include <grpc++/impl/call.h> -namespace google { -namespace protobuf { -class Message; -} // namespace protobuf -} // namespace google - struct grpc_call; namespace grpc { diff --git a/include/grpc++/client_context.h b/include/grpc++/client_context.h index 87e5e9ad6c47c2a1bef39b4b46aa4de7a535a6d5..c55d7c2d5860fb2c602066549cff1354e7c4a8f4 100644 --- a/include/grpc++/client_context.h +++ b/include/grpc++/client_context.h @@ -47,12 +47,6 @@ using std::chrono::system_clock; struct grpc_call; struct grpc_completion_queue; -namespace google { -namespace protobuf { -class Message; -} // namespace protobuf -} // namespace google - namespace grpc { class CallOpBuffer; diff --git a/include/grpc++/completion_queue.h b/include/grpc++/completion_queue.h index 0ca12604038932792d746a17e61d66eecff21bd5..f741e3c36bbce44e3aa29c29f25e1962b694096d 100644 --- a/include/grpc++/completion_queue.h +++ b/include/grpc++/completion_queue.h @@ -106,8 +106,8 @@ class CompletionQueue { friend Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method, ClientContext *context, - const google::protobuf::Message &request, - google::protobuf::Message *result); + const grpc::protobuf::Message &request, + grpc::protobuf::Message *result); // Wraps grpc_completion_queue_pluck. // Cannot be mixed with calls to Next(). diff --git a/include/grpc++/config.h b/include/grpc++/config.h index cfa8d3be9f11317c009aade97e2a6834f17b1554..327ed7a549a4dbf1c1d988a62fe015c5a4f21e1c 100644 --- a/include/grpc++/config.h +++ b/include/grpc++/config.h @@ -34,8 +34,6 @@ #ifndef GRPCXX_CONFIG_H #define GRPCXX_CONFIG_H -#include <string> - #ifdef GRPC_OLD_CXX #define GRPC_FINAL #define GRPC_OVERRIDE @@ -44,9 +42,23 @@ #define GRPC_OVERRIDE override #endif +#ifndef GRPC_CUSTOM_STRING +#include <string> +#define GRPC_CUSTOM_STRING std::string +#endif + +#ifndef GRPC_CUSTOM_MESSAGE +#include <google/protobuf/message.h> +#define GRPC_CUSTOM_MESSAGE ::google::protobuf::Message +#endif + namespace grpc { -typedef std::string string; +typedef GRPC_CUSTOM_STRING string; + +namespace protobuf { +typedef GRPC_CUSTOM_MESSAGE Message; +} // namespace protobuf } // namespace grpc diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h index 3f13188365cd126ee36868331263c4751e93a124..da375b97db457f1edf225e7934da734efb96b1ff 100644 --- a/include/grpc++/create_channel.h +++ b/include/grpc++/create_channel.h @@ -43,11 +43,6 @@ namespace grpc { class ChannelArguments; class ChannelInterface; -// Deprecation warning: This function will soon be deleted -// (See pull request #711) -std::shared_ptr<ChannelInterface> CreateChannelDeprecated( - const grpc::string& target, const ChannelArguments& args); - // If creds does not hold an object or is invalid, a lame channel is returned. std::shared_ptr<ChannelInterface> CreateChannel( const grpc::string& target, const std::unique_ptr<Credentials>& creds, diff --git a/include/grpc++/credentials.h b/include/grpc++/credentials.h index 12c1a2fc98a6eaa1d0bc3ca62e5b0eb7142d19e5..c677cc3e0a3edd8bc01f3d0805ece638e5213760 100644 --- a/include/grpc++/credentials.h +++ b/include/grpc++/credentials.h @@ -39,29 +39,29 @@ #include <grpc++/config.h> -struct grpc_credentials; - namespace grpc { +class ChannelArguments; +class ChannelInterface; +class SecureCredentials; -// grpc_credentials wrapper class. Typical use in C++ applications is limited -// to creating an instance using CredentialsFactory, and passing it down -// during channel construction. - -class Credentials GRPC_FINAL { +class Credentials { public: - ~Credentials(); + virtual ~Credentials(); - // TODO(abhikumar): Specify a plugin API here to be implemented by - // credentials that do not have a corresponding implementation in C. + protected: + friend std::unique_ptr<Credentials> CompositeCredentials( + const std::unique_ptr<Credentials>& creds1, + const std::unique_ptr<Credentials>& creds2); - private: - explicit Credentials(grpc_credentials*); - grpc_credentials* GetRawCreds(); + virtual SecureCredentials* AsSecureCredentials() = 0; - friend class Channel; - friend class CredentialsFactory; + private: + friend std::shared_ptr<ChannelInterface> CreateChannel( + const grpc::string& target, const std::unique_ptr<Credentials>& creds, + const ChannelArguments& args); - grpc_credentials* creds_; + virtual std::shared_ptr<ChannelInterface> CreateChannel( + const grpc::string& target, const ChannelArguments& args) = 0; }; // Options used to build SslCredentials @@ -79,57 +79,44 @@ struct SslCredentialsOptions { grpc::string pem_cert_chain; }; -// Factory for building different types of Credentials -// The methods may return empty unique_ptr when credentials cannot be created. +// Factories for building different types of Credentials +// The functions may return empty unique_ptr when credentials cannot be created. // If a Credentials pointer is returned, it can still be invalid when used to // create a channel. A lame channel will be created then and all rpcs will // fail on it. -class CredentialsFactory { - public: - // Builds google credentials with reasonable defaults. - // WARNING: Do NOT use this credentials to connect to a non-google service as - // this could result in an oauth2 token leak. - static std::unique_ptr<Credentials> GoogleDefaultCredentials(); - - // Builds SSL Credentials given SSL specific options - static std::unique_ptr<Credentials> SslCredentials( - const SslCredentialsOptions& options); - - // Builds credentials for use when running in GCE - // WARNING: Do NOT use this credentials to connect to a non-google service as - // this could result in an oauth2 token leak. - static std::unique_ptr<Credentials> ComputeEngineCredentials(); - - // Builds service account credentials. - // WARNING: Do NOT use this credentials to connect to a non-google service as - // this could result in an oauth2 token leak. - // json_key is the JSON key string containing the client's private key. - // scope is a space-delimited list of the requested permissions. - // token_lifetime is the lifetime of each token acquired through this service - // account credentials. It should be positive and should not exceed - // grpc_max_auth_token_lifetime or will be cropped to this value. - static std::unique_ptr<Credentials> ServiceAccountCredentials( - const grpc::string& json_key, const grpc::string& scope, - std::chrono::seconds token_lifetime); - - // Builds JWT credentials. - // json_key is the JSON key string containing the client's private key. - // token_lifetime is the lifetime of each Json Web Token (JWT) created with - // this credentials. It should not exceed grpc_max_auth_token_lifetime or - // will be cropped to this value. - static std::unique_ptr<Credentials> JWTCredentials( - const grpc::string& json_key, std::chrono::seconds token_lifetime); - - // Builds IAM credentials. - static std::unique_ptr<Credentials> IAMCredentials( - const grpc::string& authorization_token, - const grpc::string& authority_selector); - - // Combines two credentials objects into a composite credentials - static std::unique_ptr<Credentials> CompositeCredentials( - const std::unique_ptr<Credentials>& creds1, - const std::unique_ptr<Credentials>& creds2); -}; + +// Builds credentials with reasonable defaults. +std::unique_ptr<Credentials> GoogleDefaultCredentials(); + +// Builds SSL Credentials given SSL specific options +std::unique_ptr<Credentials> SslCredentials( + const SslCredentialsOptions& options); + +// Builds credentials for use when running in GCE +std::unique_ptr<Credentials> ComputeEngineCredentials(); + +// Builds service account credentials. +// json_key is the JSON key string containing the client's private key. +// scope is a space-delimited list of the requested permissions. +// token_lifetime is the lifetime of each token acquired through this service +// account credentials. It should be positive and should not exceed +// grpc_max_auth_token_lifetime or will be cropped to this value. +std::unique_ptr<Credentials> ServiceAccountCredentials( + const grpc::string& json_key, const grpc::string& scope, + std::chrono::seconds token_lifetime); + +// Builds IAM credentials. +std::unique_ptr<Credentials> IAMCredentials( + const grpc::string& authorization_token, + const grpc::string& authority_selector); + +// Combines two credentials objects into a composite credentials +std::unique_ptr<Credentials> CompositeCredentials( + const std::unique_ptr<Credentials>& creds1, + const std::unique_ptr<Credentials>& creds2); + +// Credentials for an unencrypted, unauthenticated channel +std::unique_ptr<Credentials> InsecureCredentials(); } // namespace grpc diff --git a/include/grpc++/impl/call.h b/include/grpc++/impl/call.h index 3e199e3eaefdb70f3f42ecc9c81df6a2708b75e5..5de56629735f617ff8442f1529bfa853d299a79a 100644 --- a/include/grpc++/impl/call.h +++ b/include/grpc++/impl/call.h @@ -42,12 +42,6 @@ #include <memory> #include <map> -namespace google { -namespace protobuf { -class Message; -} // namespace protobuf -} // namespace google - struct grpc_call; struct grpc_op; @@ -67,8 +61,8 @@ class CallOpBuffer : public CompletionQueueTag { std::multimap<grpc::string, grpc::string> *metadata); void AddSendInitialMetadata(ClientContext *ctx); void AddRecvInitialMetadata(ClientContext *ctx); - void AddSendMessage(const google::protobuf::Message &message); - void AddRecvMessage(google::protobuf::Message *message); + void AddSendMessage(const grpc::protobuf::Message &message); + void AddRecvMessage(grpc::protobuf::Message *message); void AddClientSendClose(); void AddClientRecvStatus(ClientContext *ctx, Status *status); void AddServerSendStatus(std::multimap<grpc::string, grpc::string> *metadata, @@ -95,10 +89,10 @@ class CallOpBuffer : public CompletionQueueTag { std::multimap<grpc::string, grpc::string> *recv_initial_metadata_; grpc_metadata_array recv_initial_metadata_arr_; // Send message - const google::protobuf::Message *send_message_; + const grpc::protobuf::Message *send_message_; grpc_byte_buffer *send_message_buf_; // Recv message - google::protobuf::Message *recv_message_; + grpc::protobuf::Message *recv_message_; grpc_byte_buffer *recv_message_buf_; // Client send close bool client_send_close_; diff --git a/include/grpc++/impl/client_unary_call.h b/include/grpc++/impl/client_unary_call.h index d8703264e60327c65abf2331c099f3d3f58a8e7c..fd9715da504f9d29bbccd29ed0fde2cfbfb64ee4 100644 --- a/include/grpc++/impl/client_unary_call.h +++ b/include/grpc++/impl/client_unary_call.h @@ -34,11 +34,7 @@ #ifndef GRPCXX_IMPL_CLIENT_UNARY_CALL_H #define GRPCXX_IMPL_CLIENT_UNARY_CALL_H -namespace google { -namespace protobuf { -class Message; -} // namespace protobuf -} // namespace google +#include <grpc++/config.h> namespace grpc { @@ -51,8 +47,8 @@ class Status; // Wrapper that performs a blocking unary call Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method, ClientContext *context, - const google::protobuf::Message &request, - google::protobuf::Message *result); + const grpc::protobuf::Message &request, + grpc::protobuf::Message *result); } // namespace grpc diff --git a/include/grpc++/impl/rpc_method.h b/include/grpc++/impl/rpc_method.h index ab407f5c4682e66d1c0408d956a5cd326507c676..e8909ac1846516ba0e7093bdc16a526c8b9666fd 100644 --- a/include/grpc++/impl/rpc_method.h +++ b/include/grpc++/impl/rpc_method.h @@ -34,12 +34,6 @@ #ifndef GRPCXX_IMPL_RPC_METHOD_H #define GRPCXX_IMPL_RPC_METHOD_H -namespace google { -namespace protobuf { -class Message; -} // namespace protobuf -} // namespace google - namespace grpc { class RpcMethod { diff --git a/include/grpc++/impl/rpc_service_method.h b/include/grpc++/impl/rpc_service_method.h index ff94c7e6c001260352379c12adc2245e04423e2f..097667827a133a75eaadb402df58211284155222 100644 --- a/include/grpc++/impl/rpc_service_method.h +++ b/include/grpc++/impl/rpc_service_method.h @@ -39,10 +39,10 @@ #include <memory> #include <vector> +#include <grpc++/config.h> #include <grpc++/impl/rpc_method.h> #include <grpc++/status.h> #include <grpc++/stream.h> -#include <google/protobuf/message.h> namespace grpc { class ServerContext; @@ -56,13 +56,13 @@ class MethodHandler { virtual ~MethodHandler() {} struct HandlerParameter { HandlerParameter(Call* c, ServerContext* context, - const google::protobuf::Message* req, - google::protobuf::Message* resp) + const grpc::protobuf::Message* req, + grpc::protobuf::Message* resp) : call(c), server_context(context), request(req), response(resp) {} Call* call; ServerContext* server_context; - const google::protobuf::Message* request; - google::protobuf::Message* response; + const grpc::protobuf::Message* request; + grpc::protobuf::Message* response; }; virtual Status RunHandler(const HandlerParameter& param) = 0; }; @@ -165,8 +165,8 @@ class RpcServiceMethod : public RpcMethod { // Takes ownership of the handler and two prototype objects. RpcServiceMethod(const char* name, RpcMethod::RpcType type, MethodHandler* handler, - google::protobuf::Message* request_prototype, - google::protobuf::Message* response_prototype) + grpc::protobuf::Message* request_prototype, + grpc::protobuf::Message* response_prototype) : RpcMethod(name, type), handler_(handler), request_prototype_(request_prototype), @@ -174,17 +174,17 @@ class RpcServiceMethod : public RpcMethod { MethodHandler* handler() { return handler_.get(); } - google::protobuf::Message* AllocateRequestProto() { + grpc::protobuf::Message* AllocateRequestProto() { return request_prototype_->New(); } - google::protobuf::Message* AllocateResponseProto() { + grpc::protobuf::Message* AllocateResponseProto() { return response_prototype_->New(); } private: std::unique_ptr<MethodHandler> handler_; - std::unique_ptr<google::protobuf::Message> request_prototype_; - std::unique_ptr<google::protobuf::Message> response_prototype_; + std::unique_ptr<grpc::protobuf::Message> request_prototype_; + std::unique_ptr<grpc::protobuf::Message> response_prototype_; }; // This class contains all the method information for an rpc service. It is diff --git a/include/grpc++/impl/service_type.h b/include/grpc++/impl/service_type.h index 7481d64d6af58168a73d91d1f47a39b722498ea8..7cd3ddad6b7a9f594805869938c2ec5160b6c4fa 100644 --- a/include/grpc++/impl/service_type.h +++ b/include/grpc++/impl/service_type.h @@ -34,11 +34,7 @@ #ifndef GRPCXX_IMPL_SERVICE_TYPE_H #define GRPCXX_IMPL_SERVICE_TYPE_H -namespace google { -namespace protobuf { -class Message; -} // namespace protobuf -} // namespace google +#include <grpc++/config.h> namespace grpc { @@ -72,7 +68,7 @@ class AsynchronousService { public: virtual void RequestAsyncCall(void* registered_method, ServerContext* context, - ::google::protobuf::Message* request, + ::grpc::protobuf::Message* request, ServerAsyncStreamingInterface* stream, CompletionQueue* cq, void* tag) = 0; }; @@ -91,7 +87,7 @@ class AsynchronousService { protected: void RequestAsyncUnary(int index, ServerContext* context, - ::google::protobuf::Message* request, + grpc::protobuf::Message* request, ServerAsyncStreamingInterface* stream, CompletionQueue* cq, void* tag) { dispatch_impl_->RequestAsyncCall(request_args_[index], context, request, @@ -104,7 +100,7 @@ class AsynchronousService { stream, cq, tag); } void RequestServerStreaming(int index, ServerContext* context, - ::google::protobuf::Message* request, + grpc::protobuf::Message* request, ServerAsyncStreamingInterface* stream, CompletionQueue* cq, void* tag) { dispatch_impl_->RequestAsyncCall(request_args_[index], context, request, diff --git a/include/grpc++/server.h b/include/grpc++/server.h index 3282b82d04eade3549a72928073dcb9d477a74b5..43c8432caf5fda06f98c338ee757acc23483f544 100644 --- a/include/grpc++/server.h +++ b/include/grpc++/server.h @@ -47,12 +47,6 @@ struct grpc_server; -namespace google { -namespace protobuf { -class Message; -} // namespace protobuf -} // namespace google - namespace grpc { class AsynchronousService; class RpcService; @@ -81,15 +75,14 @@ class Server GRPC_FINAL : private CallHook, class AsyncRequest; // ServerBuilder use only - Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned, - ServerCredentials* creds); - Server(); + Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned); + Server() = delete; // Register a service. This call does not take ownership of the service. // The service must exist for the lifetime of the Server instance. bool RegisterService(RpcService* service); bool RegisterAsyncService(AsynchronousService* service); // Add a listening port. Can be called multiple times. - int AddPort(const grpc::string& addr); + int AddPort(const grpc::string& addr, ServerCredentials* creds); // Start the server. bool Start(); @@ -101,9 +94,9 @@ class Server GRPC_FINAL : private CallHook, // DispatchImpl void RequestAsyncCall(void* registered_method, ServerContext* context, - ::google::protobuf::Message* request, + grpc::protobuf::Message* request, ServerAsyncStreamingInterface* stream, - CompletionQueue* cq, void* tag); + CompletionQueue* cq, void* tag) GRPC_OVERRIDE; // Completion queue. CompletionQueue cq_; @@ -119,13 +112,11 @@ class Server GRPC_FINAL : private CallHook, std::list<SyncRequest> sync_methods_; // Pointer to the c grpc server. - grpc_server* server_; + grpc_server* const server_; ThreadPoolInterface* thread_pool_; // Whether the thread pool is created and owned by the server. bool thread_pool_owned_; - // Whether the server is created with credentials. - bool secure_; }; } // namespace grpc diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index 5566002dc22c5127adf19117ef82a7c369442bb7..a3270775637ce064bf052dadb3e978c68aaa93be 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -65,11 +65,9 @@ class ServerBuilder { void RegisterAsyncService(AsynchronousService* service); // Add a listening port. Can be called multiple times. - void AddPort(const grpc::string& addr); - - // Set a ServerCredentials. Can only be called once. - // TODO(yangg) move this to be part of AddPort - void SetCredentials(const std::shared_ptr<ServerCredentials>& creds); + void AddPort(const grpc::string& addr, + std::shared_ptr<ServerCredentials> creds, + int* selected_port = nullptr); // Set the thread pool used for running appliation rpc handlers. // Does not take ownership. @@ -79,9 +77,15 @@ class ServerBuilder { std::unique_ptr<Server> BuildAndStart(); private: + struct Port { + grpc::string addr; + std::shared_ptr<ServerCredentials> creds; + int* selected_port; + }; + std::vector<RpcService*> services_; std::vector<AsynchronousService*> async_services_; - std::vector<grpc::string> ports_; + std::vector<Port> ports_; std::shared_ptr<ServerCredentials> creds_; ThreadPoolInterface* thread_pool_; }; diff --git a/include/grpc++/server_context.h b/include/grpc++/server_context.h index 9387f4a7e267a6bc6cf2765b7ae4b48943ff9b4a..a986fff46bf1a28787f00c6d22f2f60ff65f5f98 100644 --- a/include/grpc++/server_context.h +++ b/include/grpc++/server_context.h @@ -37,7 +37,7 @@ #include <chrono> #include <map> -#include "config.h" +#include <grpc++/config.h> struct gpr_timespec; struct grpc_metadata; diff --git a/include/grpc++/server_credentials.h b/include/grpc++/server_credentials.h index 45cd279e0b03413757bdd8be739ba5c1d00e1684..83ae9fd1eb0fd0c773580d8f56f638f97c3f4bf1 100644 --- a/include/grpc++/server_credentials.h +++ b/include/grpc++/server_credentials.h @@ -39,24 +39,21 @@ #include <grpc++/config.h> -struct grpc_server_credentials; +struct grpc_server; namespace grpc { +class Server; // grpc_server_credentials wrapper class. -class ServerCredentials GRPC_FINAL { +class ServerCredentials { public: - ~ServerCredentials(); + virtual ~ServerCredentials(); private: - explicit ServerCredentials(grpc_server_credentials* c_creds); + friend class ::grpc::Server; - grpc_server_credentials* GetRawCreds(); - - friend class ServerCredentialsFactory; - friend class Server; - - grpc_server_credentials* creds_; + virtual int AddPortToServer(const grpc::string& addr, + grpc_server* server) = 0; }; // Options to create ServerCredentials with SSL @@ -69,13 +66,11 @@ struct SslServerCredentialsOptions { std::vector<PemKeyCertPair> pem_key_cert_pairs; }; -// Factory for building different types of ServerCredentials -class ServerCredentialsFactory { - public: - // Builds SSL ServerCredentials given SSL specific options - static std::shared_ptr<ServerCredentials> SslCredentials( - const SslServerCredentialsOptions& options); -}; +// Builds SSL ServerCredentials given SSL specific options +std::shared_ptr<ServerCredentials> SslServerCredentials( + const SslServerCredentialsOptions& options); + +std::shared_ptr<ServerCredentials> InsecureServerCredentials(); } // namespace grpc diff --git a/include/grpc++/stream.h b/include/grpc++/stream.h index d95a379757e4d684789930a9f4b68ebf7faaea73..7625bcc38d314896e4eaaf4cd729bf7ec2259f07 100644 --- a/include/grpc++/stream.h +++ b/include/grpc++/stream.h @@ -88,7 +88,7 @@ class ClientReader GRPC_FINAL : public ClientStreamingInterface, public: // Blocking create a stream and write the first request out. ClientReader(ChannelInterface* channel, const RpcMethod& method, - ClientContext* context, const google::protobuf::Message& request) + ClientContext* context, const grpc::protobuf::Message& request) : context_(context), call_(channel->CreateCall(method, context, &cq_)) { CallOpBuffer buf; buf.AddSendInitialMetadata(&context->send_initial_metadata_); @@ -142,7 +142,7 @@ class ClientWriter GRPC_FINAL : public ClientStreamingInterface, public: // Blocking create a stream. ClientWriter(ChannelInterface* channel, const RpcMethod& method, - ClientContext* context, google::protobuf::Message* response) + ClientContext* context, grpc::protobuf::Message* response) : context_(context), response_(response), call_(channel->CreateCall(method, context, &cq_)) { @@ -179,7 +179,7 @@ class ClientWriter GRPC_FINAL : public ClientStreamingInterface, private: ClientContext* context_; - google::protobuf::Message* const response_; + grpc::protobuf::Message* const response_; CompletionQueue cq_; Call call_; }; @@ -386,7 +386,7 @@ class ClientAsyncReader GRPC_FINAL : public ClientAsyncStreamingInterface, // Create a stream and write the first request out. ClientAsyncReader(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, - const google::protobuf::Message& request, void* tag) + const grpc::protobuf::Message& request, void* tag) : context_(context), call_(channel->CreateCall(method, context, cq)) { init_buf_.Reset(tag); init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_); @@ -436,7 +436,7 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncStreamingInterface, public: ClientAsyncWriter(ChannelInterface* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, - google::protobuf::Message* response, void* tag) + grpc::protobuf::Message* response, void* tag) : context_(context), response_(response), call_(channel->CreateCall(method, context, cq)) { @@ -477,7 +477,7 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncStreamingInterface, private: ClientContext* context_; - google::protobuf::Message* const response_; + grpc::protobuf::Message* const response_; Call call_; CallOpBuffer init_buf_; CallOpBuffer meta_buf_; diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index bb1653101f4e529917f385dedbc6c5cad7822c90..e401da873bb034b82f4ed9ab152c2884c3481318 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -436,6 +436,9 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops, grpc_channel *grpc_channel_create(const char *target, const grpc_channel_args *args); +/* Create a lame client: this client fails every operation attempted on it. */ +grpc_channel *grpc_lame_client_channel_create(void); + /* Close and destroy a grpc channel */ void grpc_channel_destroy(grpc_channel *channel); diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 577f03e85fee2a03817e813722769dc5cf9cb4af..ab2cc08489ddd7629648dc6071874b2a3c220b5d 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -169,17 +169,12 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( /* --- Secure server creation. --- */ -/* Creates a secure server using the passed-in server credentials. */ -grpc_server *grpc_secure_server_create(grpc_server_credentials *creds, - grpc_completion_queue *cq, - const grpc_channel_args *args); - /* Add a HTTP2 over an encrypted link over tcp listener. Server must have been created with grpc_secure_server_create. Returns bound port number on success, 0 on failure. REQUIRES: server not started */ -int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr); - +int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, + grpc_server_credentials *creds); #ifdef __cplusplus } diff --git a/include/grpc/support/histogram.h b/include/grpc/support/histogram.h index 31f7fedfd5dd072305a76496731f273afece36d6..64d08f0bf1f9aa63b558f7fb2be751d18df308f4 100644 --- a/include/grpc/support/histogram.h +++ b/include/grpc/support/histogram.h @@ -34,6 +34,9 @@ #ifndef GRPC_SUPPORT_HISTOGRAM_H #define GRPC_SUPPORT_HISTOGRAM_H +#include <grpc/support/port_platform.h> +#include <stddef.h> + #ifdef __cplusplus extern "C" { #endif @@ -59,6 +62,13 @@ double gpr_histogram_count(gpr_histogram *histogram); double gpr_histogram_sum(gpr_histogram *histogram); double gpr_histogram_sum_of_squares(gpr_histogram *histogram); +const gpr_uint32 *gpr_histogram_get_contents(gpr_histogram *histogram, + size_t *count); +void gpr_histogram_merge_contents(gpr_histogram *histogram, + const gpr_uint32 *data, size_t data_count, + double min_seen, double max_seen, double sum, + double sum_of_squares, double count); + #ifdef __cplusplus } #endif diff --git a/include/grpc/support/slice_buffer.h b/include/grpc/support/slice_buffer.h index 56f71ef2349c711507c9f92b1b2f3a7c55ca6d0e..c7e5dbc64708449c0a3ef0c17ab2d8562b1c957e 100644 --- a/include/grpc/support/slice_buffer.h +++ b/include/grpc/support/slice_buffer.h @@ -74,6 +74,8 @@ void gpr_slice_buffer_addn(gpr_slice_buffer *sb, gpr_slice *slices, size_t n); /* add a very small (less than 8 bytes) amount of data to the end of a slice buffer: returns a pointer into which to add the data */ gpr_uint8 *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, unsigned len); +/* pop the last buffer, but don't unref it */ +void gpr_slice_buffer_pop(gpr_slice_buffer *sb); /* clear a slice buffer, unref all elements */ void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb); diff --git a/src/compiler/python_plugin.cc b/src/compiler/python_plugin.cc index 0dd2c5b834416488c6ddbec0e4782b83b055e7a9..825f15a5c787ba775d7d36380f914f0aa4564816 100644 --- a/src/compiler/python_plugin.cc +++ b/src/compiler/python_plugin.cc @@ -36,6 +36,7 @@ #include <cstring> #include <memory> #include <string> +#include <tuple> #include "src/compiler/python_generator.h" #include <google/protobuf/compiler/code_generator.h> diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index f0a8453fd77a1609519e3fa17709a9c0ead990df..0bb722e2b12c44748d089f68e66cd200c522f2f0 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -66,7 +66,7 @@ static void backup_poller(void *p) { gpr_timespec next_poll = gpr_time_add(last_poll, delta); grpc_pollset_work(&g_backup_pollset, gpr_time_add(gpr_now(), gpr_time_from_seconds(1))); gpr_mu_unlock(&g_backup_pollset.mu); - /*gpr_sleep_until(next_poll);*/ + gpr_sleep_until(next_poll); gpr_mu_lock(&g_backup_pollset.mu); last_poll = next_poll; } @@ -267,7 +267,6 @@ static void unary_poll_do_promote(void *args, int success) { * and we don't have any mechanism to unbecome multipoller. */ pollset->in_flight_cbs--; if (pollset->shutting_down) { - gpr_log(GPR_INFO, "Shutting down"); /* We don't care about this pollset anymore. */ if (pollset->in_flight_cbs == 0) { do_shutdown_cb = 1; @@ -275,7 +274,6 @@ static void unary_poll_do_promote(void *args, int success) { } else if (grpc_fd_is_orphaned(fd)) { /* Don't try to add it to anything, we'll drop our ref on it below */ } else if (pollset->vtable != original_vtable) { - gpr_log(GPR_INFO, "Not original vtable"); pollset->vtable->add_fd(pollset, fd); } else if (fd != pollset->data.ptr) { grpc_fd *fds[2]; diff --git a/src/core/iomgr/resolve_address_posix.c b/src/core/iomgr/resolve_address_posix.c index 989b968ae27267a88887a21c21bda31046401009..9a9283c93c386cd7319d599774cbf722a02201b4 100644 --- a/src/core/iomgr/resolve_address_posix.c +++ b/src/core/iomgr/resolve_address_posix.c @@ -101,6 +101,21 @@ grpc_resolved_addresses *grpc_blocking_resolve_address( hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */ s = getaddrinfo(host, port, &hints, &result); + if (s != 0) { + /* Retry if well-known service name is recognized */ + char *svc[][2] = { + {"http", "80"}, + {"https", "443"} + }; + int i; + for (i = 0; i < (int)(sizeof(svc) / sizeof(svc[0])); i++) { + if (strcmp(port, svc[i][0]) == 0) { + s = getaddrinfo(host, svc[i][1], &hints, &result); + break; + } + } + } + if (s != 0) { gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s)); goto done; diff --git a/src/core/security/auth.c b/src/core/security/auth.c index 9b67d59cb8e6c282c31fb0a14d58a60d8b49077d..5fc6d2717f7dfe0f4d68ef474fa7b4334464a61c 100644 --- a/src/core/security/auth.c +++ b/src/core/security/auth.c @@ -59,6 +59,7 @@ typedef struct { grpc_mdstr *authority_string; grpc_mdstr *path_string; grpc_mdstr *error_msg_key; + grpc_mdstr *status_key; } channel_data; static void do_nothing(void *ignored, grpc_op_error error) {} @@ -66,17 +67,25 @@ static void do_nothing(void *ignored, grpc_op_error error) {} static void bubbleup_error(grpc_call_element *elem, const char *error_msg) { grpc_call_op finish_op; channel_data *channeld = elem->channel_data; + char status[GPR_LTOA_MIN_BUFSIZE]; gpr_log(GPR_ERROR, "%s", error_msg); finish_op.type = GRPC_RECV_METADATA; finish_op.dir = GRPC_CALL_UP; finish_op.flags = 0; finish_op.data.metadata = grpc_mdelem_from_metadata_strings( - channeld->md_ctx, channeld->error_msg_key, + channeld->md_ctx, grpc_mdstr_ref(channeld->error_msg_key), grpc_mdstr_from_string(channeld->md_ctx, error_msg)); finish_op.done_cb = do_nothing; finish_op.user_data = NULL; grpc_call_next_op(elem, &finish_op); + + gpr_ltoa(GRPC_STATUS_UNAUTHENTICATED, status); + finish_op.data.metadata = grpc_mdelem_from_metadata_strings( + channeld->md_ctx, grpc_mdstr_ref(channeld->status_key), + grpc_mdstr_from_string(channeld->md_ctx, status)); + grpc_call_next_op(elem, &finish_op); + grpc_call_element_send_cancel(elem); } @@ -151,6 +160,7 @@ static void on_host_checked(void *user_data, grpc_security_status status) { grpc_mdstr_as_c_string(calld->host)); bubbleup_error(elem, error_msg); gpr_free(error_msg); + calld->op.done_cb(calld->op.user_data, GRPC_OP_ERROR); } } @@ -193,6 +203,7 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, call_host); bubbleup_error(elem, error_msg); gpr_free(error_msg); + op->done_cb(op->user_data, GRPC_OP_ERROR); } break; } @@ -265,6 +276,7 @@ static void init_channel_elem(grpc_channel_element *elem, channeld->path_string = grpc_mdstr_from_string(channeld->md_ctx, ":path"); channeld->error_msg_key = grpc_mdstr_from_string(channeld->md_ctx, "grpc-message"); + channeld->status_key = grpc_mdstr_from_string(channeld->md_ctx, "grpc-status"); } /* Destructor for channel data */ @@ -279,6 +291,9 @@ static void destroy_channel_elem(grpc_channel_element *elem) { if (channeld->error_msg_key != NULL) { grpc_mdstr_unref(channeld->error_msg_key); } + if (channeld->status_key != NULL) { + grpc_mdstr_unref(channeld->status_key); + } if (channeld->path_string != NULL) { grpc_mdstr_unref(channeld->path_string); } diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 7e72b238c80ed28747f53816aab8c3cf404bf1fd..3ad1e7edd7617b7274ac19041ac694b64e704547 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -348,7 +348,7 @@ static void jwt_get_request_metadata(grpc_credentials *creds, { gpr_mu_lock(&c->cache_mu); if (c->cached.service_url != NULL && - !strcmp(c->cached.service_url, service_url) && + strcmp(c->cached.service_url, service_url) == 0 && c->cached.jwt_md != NULL && (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()), refresh_threshold) > 0)) { @@ -957,7 +957,7 @@ static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) { grpc_credentials *creds = *creds_addr; result.creds_array = creds_addr; result.num_creds = 1; - if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)) { + if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) { result = *grpc_composite_credentials_get_credentials(creds); } return result; @@ -995,7 +995,7 @@ const grpc_credentials_array *grpc_composite_credentials_get_credentials( grpc_credentials *creds) { const grpc_composite_credentials *c = (const grpc_composite_credentials *)creds; - GPR_ASSERT(!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)); + GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0); return &c->inner; } @@ -1003,14 +1003,14 @@ grpc_credentials *grpc_credentials_contains_type( grpc_credentials *creds, const char *type, grpc_credentials **composite_creds) { size_t i; - if (!strcmp(creds->type, type)) { + if (strcmp(creds->type, type) == 0) { if (composite_creds != NULL) *composite_creds = NULL; return creds; - } else if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)) { + } else if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) { const grpc_credentials_array *inner_creds_array = grpc_composite_credentials_get_credentials(creds); for (i = 0; i < inner_creds_array->num_creds; i++) { - if (!strcmp(type, inner_creds_array->creds_array[i]->type)) { + if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) { if (composite_creds != NULL) *composite_creds = creds; return inner_creds_array->creds_array[i]; } diff --git a/src/core/security/factories.c b/src/core/security/factories.c index c9701b9080db47e6e5a8bf2e9daa9310f49318fd..02267d55457c5f0563dd5b2a3275721a761352b6 100644 --- a/src/core/security/factories.c +++ b/src/core/security/factories.c @@ -33,9 +33,9 @@ #include <string.h> +#include <grpc/grpc.h> #include "src/core/security/credentials.h" #include "src/core/security/security_context.h" -#include "src/core/surface/lame_client.h" #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/useful.h> @@ -50,31 +50,3 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, return grpc_secure_channel_create_with_factories( factories, GPR_ARRAY_SIZE(factories), creds, target, args); } - -grpc_server *grpc_secure_server_create(grpc_server_credentials *creds, - grpc_completion_queue *cq, - const grpc_channel_args *args) { - grpc_security_status status = GRPC_SECURITY_ERROR; - grpc_security_context *ctx = NULL; - grpc_server *server = NULL; - if (creds == NULL) return NULL; /* TODO(ctiller): Return lame server. */ - - if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_SSL)) { - status = grpc_ssl_server_security_context_create( - grpc_ssl_server_credentials_get_config(creds), &ctx); - } else if (!strcmp(creds->type, - GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY)) { - ctx = grpc_fake_server_security_context_create(); - status = GRPC_SECURITY_OK; - } - - if (status != GRPC_SECURITY_OK) { - gpr_log(GPR_ERROR, - "Unable to create secure server with credentials of type %s.", - creds->type); - return NULL; /* TODO(ctiller): Return lame server. */ - } - server = grpc_secure_server_create_internal(cq, args, ctx); - grpc_security_context_unref(ctx); - return server; -} diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c index dc0e453b8781851f31b022f6873efb95ed460400..bdc907e7b33ada137d4af315799ac63db8f669ac 100644 --- a/src/core/security/google_default_credentials.c +++ b/src/core/security/google_default_credentials.c @@ -75,8 +75,8 @@ static void on_compute_engine_detection_http_response( size_t i; for (i = 0; i < response->hdr_count; i++) { grpc_httpcli_header *header = &response->hdrs[i]; - if (!strcmp(header->key, "Metadata-Flavor") && - !strcmp(header->value, "Google")) { + if (strcmp(header->key, "Metadata-Flavor") == 0 && + strcmp(header->value, "Google") == 0) { detector->success = 1; break; } diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c index 26d57036a6d58d66b968faf499960fdf0f14ac0a..40b612b2065e11213f82a33834407a6a452376b9 100644 --- a/src/core/security/json_token.c +++ b/src/core/security/json_token.c @@ -257,7 +257,7 @@ static char *dot_concat_and_free_strings(char *str1, char *str2) { } const EVP_MD *openssl_digest_from_algorithm(const char *algorithm) { - if (!strcmp(algorithm, GRPC_JWT_RSA_SHA256_ALGORITHM)) { + if (strcmp(algorithm, GRPC_JWT_RSA_SHA256_ALGORITHM) == 0) { return EVP_sha256(); } else { gpr_log(GPR_ERROR, "Unknown algorithm %s.", algorithm); diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index 0dc37fa73c0e33d9cec0458cf8e4013b647763f4..e180cad52b26ea74dda96aae4ba3cdd546e72936 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -42,7 +42,6 @@ #include "src/core/support/env.h" #include "src/core/support/file.h" #include "src/core/support/string.h" -#include "src/core/surface/lame_client.h" #include "src/core/transport/chttp2/alpn.h" #include <grpc/support/alloc.h> @@ -422,7 +421,7 @@ static grpc_security_status ssl_channel_check_call_host( /* If the target name was overridden, then the original target_name was 'checked' transitively during the previous peer check at the end of the handshake. */ - if (c->overridden_target_name != NULL && !strcmp(host, c->target_name)) { + if (c->overridden_target_name != NULL && strcmp(host, c->target_name) == 0) { return GRPC_SECURITY_OK; } else { return GRPC_SECURITY_ERROR; @@ -611,7 +610,7 @@ grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds, for (i = 0; args && i < args->num_args; i++) { grpc_arg *arg = &args->args[i]; - if (!strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) && + if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 && arg->type == GRPC_ARG_STRING) { overridden_target_name = arg->value.string; break; diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c index c88f0726bb7a8d17efd05f2022f58a0766b0408a..c155b80b7e6aa0b10f6f001daf73100a4dca0325 100644 --- a/src/core/security/server_secure_chttp2.c +++ b/src/core/security/server_secure_chttp2.c @@ -33,8 +33,11 @@ #include <grpc/grpc.h> +#include <string.h> + #include "src/core/channel/http_filter.h" #include "src/core/channel/http_server_filter.h" +#include "src/core/iomgr/endpoint.h" #include "src/core/iomgr/resolve_address.h" #include "src/core/iomgr/tcp_server.h" #include "src/core/security/security_context.h" @@ -43,8 +46,29 @@ #include "src/core/transport/chttp2_transport.h" #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include <grpc/support/sync.h> #include <grpc/support/useful.h> +typedef struct grpc_server_secure_state { + grpc_server *server; + grpc_tcp_server *tcp; + grpc_security_context *ctx; + int is_shutdown; + gpr_mu mu; + gpr_refcount refcount; +} grpc_server_secure_state; + +static void state_ref(grpc_server_secure_state *state) { + gpr_ref(&state->refcount); +} + +static void state_unref(grpc_server_secure_state *state) { + if (gpr_unref(&state->refcount)) { + grpc_security_context_unref(state->ctx); + gpr_free(state); + } +} + static grpc_transport_setup_result setup_transport(void *server, grpc_transport *transport, grpc_mdctx *mdctx) { @@ -54,49 +78,84 @@ static grpc_transport_setup_result setup_transport(void *server, GPR_ARRAY_SIZE(extra_filters), mdctx); } -static void on_secure_transport_setup_done(void *server, +static void on_secure_transport_setup_done(void *statep, grpc_security_status status, grpc_endpoint *secure_endpoint) { + grpc_server_secure_state *state = statep; if (status == GRPC_SECURITY_OK) { - grpc_create_chttp2_transport( - setup_transport, server, grpc_server_get_channel_args(server), - secure_endpoint, NULL, 0, grpc_mdctx_create(), 0); + gpr_mu_lock(&state->mu); + if (!state->is_shutdown) { + grpc_create_chttp2_transport( + setup_transport, state->server, + grpc_server_get_channel_args(state->server), + secure_endpoint, NULL, 0, grpc_mdctx_create(), 0); + } else { + /* We need to consume this here, because the server may already have gone + * away. */ + grpc_endpoint_destroy(secure_endpoint); + } + gpr_mu_unlock(&state->mu); } else { gpr_log(GPR_ERROR, "Secure transport failed with error %d", status); } + state_unref(state); } -static void on_accept(void *server, grpc_endpoint *tcp) { - const grpc_channel_args *args = grpc_server_get_channel_args(server); - grpc_security_context *ctx = grpc_find_security_context_in_args(args); - GPR_ASSERT(ctx); - grpc_setup_secure_transport(ctx, tcp, on_secure_transport_setup_done, server); +static void on_accept(void *statep, grpc_endpoint *tcp) { + grpc_server_secure_state *state = statep; + state_ref(state); + grpc_setup_secure_transport(state->ctx, tcp, on_secure_transport_setup_done, state); } -/* Note: the following code is the same with server_chttp2.c */ - /* Server callback: start listening on our ports */ -static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets, +static void start(grpc_server *server, void *statep, grpc_pollset **pollsets, size_t pollset_count) { - grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_start(tcp, pollsets, pollset_count, on_accept, server); + grpc_server_secure_state *state = statep; + grpc_tcp_server_start(state->tcp, pollsets, pollset_count, on_accept, state); } /* Server callback: destroy the tcp listener (so we don't generate further callbacks) */ -static void destroy(grpc_server *server, void *tcpp) { - grpc_tcp_server *tcp = tcpp; - grpc_tcp_server_destroy(tcp); +static void destroy(grpc_server *server, void *statep) { + grpc_server_secure_state *state = statep; + gpr_mu_lock(&state->mu); + state->is_shutdown = 1; + grpc_tcp_server_destroy(state->tcp); + gpr_mu_unlock(&state->mu); + state_unref(state); } -int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr) { +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; + grpc_server_secure_state *state = NULL; size_t i; unsigned count = 0; int port_num = -1; int port_temp; + grpc_security_status status = GRPC_SECURITY_ERROR; + grpc_security_context *ctx = NULL; + /* create security context */ + if (creds == NULL) goto error; + + if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_SSL) == 0) { + status = grpc_ssl_server_security_context_create( + grpc_ssl_server_credentials_get_config(creds), &ctx); + } else if (strcmp(creds->type, + GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY) == 0) { + ctx = grpc_fake_server_security_context_create(); + status = GRPC_SECURITY_OK; + } + + if (status != GRPC_SECURITY_OK) { + gpr_log(GPR_ERROR, + "Unable to create secure server with credentials of type %s.", + creds->type); + goto error; + } + + /* resolve address */ resolved = grpc_blocking_resolve_address(addr, "https"); if (!resolved) { goto error; @@ -132,18 +191,32 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr) { } grpc_resolved_addresses_destroy(resolved); + state = gpr_malloc(sizeof(*state)); + state->server = server; + state->tcp = tcp; + state->ctx = ctx; + state->is_shutdown = 0; + gpr_mu_init(&state->mu); + gpr_ref_init(&state->refcount, 1); + /* Register with the server only upon success */ - grpc_server_add_listener(server, tcp, start, destroy); + grpc_server_add_listener(server, state, start, destroy); return port_num; /* Error path: cleanup and return */ error: + if (ctx) { + grpc_security_context_unref(ctx); + } if (resolved) { grpc_resolved_addresses_destroy(resolved); } if (tcp) { grpc_tcp_server_destroy(tcp); } + if (state) { + gpr_free(state); + } return 0; } diff --git a/src/core/support/histogram.c b/src/core/support/histogram.c index eacb77082f971fcbf75ebd552fb67efaf7734c34..ed344b43e8d0f9fc4a6c0eb9d98e2df5042f4e3b 100644 --- a/src/core/support/histogram.c +++ b/src/core/support/histogram.c @@ -126,25 +126,35 @@ void gpr_histogram_add(gpr_histogram *h, double x) { } int gpr_histogram_merge(gpr_histogram *dst, gpr_histogram *src) { - size_t i; if ((dst->num_buckets != src->num_buckets) || (dst->multiplier != src->multiplier)) { /* Fail because these histograms don't match */ return 0; } - dst->sum += src->sum; - dst->sum_of_squares += src->sum_of_squares; - dst->count += src->count; - if (src->min_seen < dst->min_seen) { - dst->min_seen = src->min_seen; + gpr_histogram_merge_contents(dst, src->buckets, src->num_buckets, + src->min_seen, src->max_seen, src->sum, + src->sum_of_squares, src->count); + return 1; +} + +void gpr_histogram_merge_contents(gpr_histogram *dst, const gpr_uint32 *data, + size_t data_count, double min_seen, + double max_seen, double sum, + double sum_of_squares, double count) { + size_t i; + GPR_ASSERT(dst->num_buckets == data_count); + dst->sum += sum; + dst->sum_of_squares += sum_of_squares; + dst->count += count; + if (min_seen < dst->min_seen) { + dst->min_seen = min_seen; } - if (src->max_seen > dst->max_seen) { - dst->max_seen = src->max_seen; + if (max_seen > dst->max_seen) { + dst->max_seen = max_seen; } for (i = 0; i < dst->num_buckets; i++) { - dst->buckets[i] += src->buckets[i]; + dst->buckets[i] += data[i]; } - return 1; } static double threshold_for_count_below(gpr_histogram *h, double count_below) { @@ -222,3 +232,8 @@ double gpr_histogram_sum(gpr_histogram *h) { return h->sum; } double gpr_histogram_sum_of_squares(gpr_histogram *h) { return h->sum_of_squares; } + +const gpr_uint32 *gpr_histogram_get_contents(gpr_histogram *h, size_t *size) { + *size = h->num_buckets; + return h->buckets; +} diff --git a/src/core/support/slice_buffer.c b/src/core/support/slice_buffer.c index 6cd51f925c3b46b083dddc19ad4d8a3b360b14e5..b280e4bd020014b26f08de866fa75a2ddb460566 100644 --- a/src/core/support/slice_buffer.c +++ b/src/core/support/slice_buffer.c @@ -143,6 +143,13 @@ void gpr_slice_buffer_addn(gpr_slice_buffer *sb, gpr_slice *s, size_t n) { } } +void gpr_slice_buffer_pop(gpr_slice_buffer *sb) { + if (sb->count != 0) { + size_t count = --sb->count; + sb->length -= GPR_SLICE_LENGTH(sb->slices[count]); + } +} + void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb) { size_t i; diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 7cf3c0e4fd6c4032d48e02ebcd8b457a32f423dc..cfce943794072f8ffa04e9af4880a1f8ebe856f8 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -140,6 +140,8 @@ struct grpc_call { gpr_uint8 have_alarm; /* are we currently performing a send operation */ gpr_uint8 sending; + /* are we currently completing requests */ + gpr_uint8 completing; /* pairs with completed_requests */ gpr_uint8 num_completed_requests; /* flag that we need to request more data */ @@ -357,7 +359,7 @@ static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); } static void unlock(grpc_call *call) { send_action sa = SEND_NOTHING; completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; - int num_completed_requests = call->num_completed_requests; + int completing_requests = 0; int need_more_data = call->need_more_data && (call->write_state >= WRITE_STATE_STARTED || !call->is_client); @@ -367,10 +369,13 @@ static void unlock(grpc_call *call) { call->need_more_data = 0; } - if (num_completed_requests != 0) { + if (!call->completing && call->num_completed_requests != 0) { + completing_requests = call->num_completed_requests; memcpy(completed_requests, call->completed_requests, sizeof(completed_requests)); call->num_completed_requests = 0; + call->completing = 1; + grpc_call_internal_ref(call); } if (!call->sending) { @@ -391,9 +396,15 @@ static void unlock(grpc_call *call) { enact_send_action(call, sa); } - for (i = 0; i < num_completed_requests; i++) { - completed_requests[i].on_complete(call, completed_requests[i].status, - completed_requests[i].user_data); + if (completing_requests > 0) { + for (i = 0; i < completing_requests; i++) { + completed_requests[i].on_complete(call, completed_requests[i].status, + completed_requests[i].user_data); + } + lock(call); + call->completing = 0; + unlock(call); + grpc_call_internal_unref(call, 0); } } diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index e38734c6a4921fb4e7e63a6d247262b13637e1c9..e764a3b9af0a82666137eecbf22a83eef2f66edb 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -39,6 +39,7 @@ #include "src/core/iomgr/iomgr.h" #include "src/core/surface/call.h" #include "src/core/surface/client.h" +#include "src/core/surface/init.h" #include <grpc/support/alloc.h> #include <grpc/support/log.h> @@ -63,6 +64,7 @@ grpc_channel *grpc_channel_create_from_filters( size_t size = sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters); grpc_channel *channel = gpr_malloc(size); + GPR_ASSERT(grpc_is_initialized() && "call grpc_init()"); channel->is_client = is_client; /* decremented by grpc_channel_destroy, and grpc_client_channel_closed if is_client */ gpr_ref_init(&channel->refs, 1 + is_client); diff --git a/src/core/surface/init.c b/src/core/surface/init.c index 4db66fb66eb05b485a428f35113df0a775664d95..e48c4202e5831004453791d7004a0756879048de 100644 --- a/src/core/surface/init.c +++ b/src/core/surface/init.c @@ -40,17 +40,17 @@ #include "src/core/surface/surface_trace.h" #include "src/core/transport/chttp2_transport.h" -static gpr_once g_init = GPR_ONCE_INIT; +static gpr_once g_basic_init = GPR_ONCE_INIT; static gpr_mu g_init_mu; static int g_initializations; -static void do_init(void) { +static void do_basic_init(void) { gpr_mu_init(&g_init_mu); g_initializations = 0; } void grpc_init(void) { - gpr_once_init(&g_init, do_init); + gpr_once_init(&g_basic_init, do_basic_init); gpr_mu_lock(&g_init_mu); if (++g_initializations == 1) { @@ -73,3 +73,13 @@ void grpc_shutdown(void) { } gpr_mu_unlock(&g_init_mu); } + +int grpc_is_initialized(void) { + int r; + gpr_once_init(&g_basic_init, do_basic_init); + gpr_mu_lock(&g_init_mu); + r = g_initializations > 0; + gpr_mu_unlock(&g_init_mu); + return r; +} + diff --git a/src/core/surface/init.h b/src/core/surface/init.h index ab40bedf8754918fd965d52e5dfa4c2bcc1872c7..416874020d7c79b090b2e66487d443b15febd93a 100644 --- a/src/core/surface/init.h +++ b/src/core/surface/init.h @@ -35,5 +35,6 @@ #define GRPC_INTERNAL_CORE_SURFACE_INIT_H void grpc_security_pre_init(void); +int grpc_is_initialized(void); #endif /* GRPC_INTERNAL_CORE_SURFACE_INIT_H */ diff --git a/src/core/surface/lame_client.c b/src/core/surface/lame_client.c index 57f6ddf0f7ff6bca8b82e02946dd7cbb8a3e1bb9..b40c48381f4296da467ce53df4cd9ac9b8420258 100644 --- a/src/core/surface/lame_client.c +++ b/src/core/surface/lame_client.c @@ -31,7 +31,7 @@ * */ -#include "src/core/surface/lame_client.h" +#include <grpc/grpc.h> #include <string.h> diff --git a/src/core/surface/server.c b/src/core/surface/server.c index c99a1b4cc9c9c72c3c144607890f6a143b69ba39..424734c54ce5615fcbe700bb22bd834803004d82 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -44,6 +44,7 @@ #include "src/core/surface/call.h" #include "src/core/surface/channel.h" #include "src/core/surface/completion_queue.h" +#include "src/core/surface/init.h" #include "src/core/transport/metadata.h" #include <grpc/support/alloc.h> #include <grpc/support/log.h> @@ -612,6 +613,9 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq, int census_enabled = grpc_channel_args_is_census_enabled(args); grpc_server *server = gpr_malloc(sizeof(grpc_server)); + + GPR_ASSERT(grpc_is_initialized() && "call grpc_init()"); + memset(server, 0, sizeof(grpc_server)); if (cq) addcq(server, cq); diff --git a/src/core/surface/server_chttp2.c b/src/core/surface/server_chttp2.c index fd702593b89dfdcef593f5061003ef21320070ce..27434b39e2d21695a09a2500e10bcdaf65c0f0fd 100644 --- a/src/core/surface/server_chttp2.c +++ b/src/core/surface/server_chttp2.c @@ -53,6 +53,13 @@ static grpc_transport_setup_result setup_transport(void *server, } static void new_transport(void *server, grpc_endpoint *tcp) { + /* + * 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_create_chttp2_transport(setup_transport, server, grpc_server_get_channel_args(server), tcp, NULL, 0, grpc_mdctx_create(), 0); diff --git a/src/core/tsi/fake_transport_security.c b/src/core/tsi/fake_transport_security.c index f58f04ea20b8ebe17b92c43d4c8970bdd997b024..9ce1ddb95e2676353caced21e8eeb6c6dc991228 100644 --- a/src/core/tsi/fake_transport_security.c +++ b/src/core/tsi/fake_transport_security.c @@ -102,8 +102,8 @@ static tsi_result tsi_fake_handshake_message_from_string( const char* msg_string, tsi_fake_handshake_message* msg) { int i; for (i = 0; i < TSI_FAKE_HANDSHAKE_MESSAGE_MAX; i++) { - if (!strncmp(msg_string, tsi_fake_handshake_message_strings[i], - strlen(tsi_fake_handshake_message_strings[i]))) { + if (strncmp(msg_string, tsi_fake_handshake_message_strings[i], + strlen(tsi_fake_handshake_message_strings[i])) == 0) { *msg = i; return TSI_OK; } diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c index dc43f7e270cf52ccc6d803a986f14311f6d583e4..33645ca8b866193c5f0f82c9654eb794eae989c1 100644 --- a/src/core/tsi/ssl_transport_security.c +++ b/src/core/tsi/ssl_transport_security.c @@ -1083,7 +1083,8 @@ static int does_entry_match_name(const char* entry, size_t entry_length, if (entry_length == 0) return 0; } - if ((name_length == entry_length) && !strncmp(name, entry, entry_length)) { + if ((name_length == entry_length) && + strncmp(name, entry, entry_length) == 0) { return 1; /* Perfect match. */ } if (entry[0] != '*') return 0; @@ -1110,7 +1111,7 @@ static int does_entry_match_name(const char* entry, size_t entry_length, name_subdomain_length--; } return ((entry_length > 0) && (name_subdomain_length == entry_length) && - !strncmp(entry, name_subdomain, entry_length)); + strncmp(entry, name_subdomain, entry_length) == 0); } static int ssl_server_handshaker_factory_servername_callback(SSL* ssl, int* ap, diff --git a/src/core/tsi/transport_security.c b/src/core/tsi/transport_security.c index c8c74c5de5998739bd6b20501ba17e9d72f1f577..f4ab9d2bc6d12feab4e4b5554e2bc0aa6605ea58 100644 --- a/src/core/tsi/transport_security.c +++ b/src/core/tsi/transport_security.c @@ -208,7 +208,7 @@ const tsi_peer_property* tsi_peer_get_property_by_name(const tsi_peer* self, return property; } if (name != NULL && property->name != NULL && - !strcmp(property->name, name)) { + strcmp(property->name, name) == 0) { return property; } } diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc index ca69d66cbbfcf541e7e0bdfde03b77052c74d929..5380d3a232c3739ef634e4922311faa18ee8e204 100644 --- a/src/cpp/client/channel.cc +++ b/src/cpp/client/channel.cc @@ -50,47 +50,26 @@ #include <grpc++/impl/call.h> #include <grpc++/impl/rpc_method.h> #include <grpc++/status.h> -#include <google/protobuf/message.h> namespace grpc { -Channel::Channel(const grpc::string &target, const ChannelArguments &args) - : target_(target) { - grpc_channel_args channel_args; - args.SetChannelArgs(&channel_args); - c_channel_ = grpc_channel_create( - target_.c_str(), channel_args.num_args > 0 ? &channel_args : nullptr); -} - -Channel::Channel(const grpc::string &target, - const std::unique_ptr<Credentials> &creds, - const ChannelArguments &args) - : target_(args.GetSslTargetNameOverride().empty() - ? target - : args.GetSslTargetNameOverride()) { - grpc_channel_args channel_args; - args.SetChannelArgs(&channel_args); - grpc_credentials *c_creds = creds ? creds->GetRawCreds() : nullptr; - c_channel_ = grpc_secure_channel_create( - c_creds, target.c_str(), - channel_args.num_args > 0 ? &channel_args : nullptr); -} +Channel::Channel(const grpc::string& target, grpc_channel* channel) + : target_(target), c_channel_(channel) {} Channel::~Channel() { grpc_channel_destroy(c_channel_); } -Call Channel::CreateCall(const RpcMethod &method, ClientContext *context, - CompletionQueue *cq) { - auto c_call = - grpc_channel_create_call( - c_channel_, cq->cq(), method.name(), - context->authority().empty() ? target_.c_str() - : context->authority().c_str(), - context->RawDeadline()); +Call Channel::CreateCall(const RpcMethod& method, ClientContext* context, + CompletionQueue* cq) { + auto c_call = grpc_channel_create_call(c_channel_, cq->cq(), method.name(), + context->authority().empty() + ? target_.c_str() + : context->authority().c_str(), + context->RawDeadline()); context->set_call(c_call); return Call(c_call, this, cq); } -void Channel::PerformOpsOnCall(CallOpBuffer *buf, Call *call) { +void Channel::PerformOpsOnCall(CallOpBuffer* buf, Call* call) { static const size_t MAX_OPS = 8; size_t nops = MAX_OPS; grpc_op ops[MAX_OPS]; diff --git a/src/cpp/client/channel.h b/src/cpp/client/channel.h index 63c6e2bde6d4fc9c0cb286ad37fe526c86dd74d2..a1de3817e6947773dbdff3d9c534f094d2132420 100644 --- a/src/cpp/client/channel.h +++ b/src/cpp/client/channel.h @@ -51,10 +51,7 @@ class StreamContextInterface; class Channel GRPC_FINAL : public ChannelInterface { public: - Channel(const grpc::string &target, const ChannelArguments &args); - Channel(const grpc::string &target, const std::unique_ptr<Credentials> &creds, - const ChannelArguments &args); - + Channel(const grpc::string &target, grpc_channel *c_channel); ~Channel() GRPC_OVERRIDE; virtual Call CreateCall(const RpcMethod &method, ClientContext *context, @@ -63,7 +60,7 @@ class Channel GRPC_FINAL : public ChannelInterface { private: const grpc::string target_; - grpc_channel *c_channel_; // owned + grpc_channel *const c_channel_; // owned }; } // namespace grpc diff --git a/src/cpp/client/client_unary_call.cc b/src/cpp/client/client_unary_call.cc index 684b3cbadb49a6c33fa029fd296e1dac2b91b3cf..5c179de9d8feffeba5834811321aed6df71c4cdd 100644 --- a/src/cpp/client/client_unary_call.cc +++ b/src/cpp/client/client_unary_call.cc @@ -44,8 +44,8 @@ namespace grpc { // Wrapper that performs a blocking unary call Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method, ClientContext *context, - const google::protobuf::Message &request, - google::protobuf::Message *result) { + const grpc::protobuf::Message &request, + grpc::protobuf::Message *result) { CompletionQueue cq; Call call(channel->CreateCall(method, context, &cq)); CallOpBuffer buf; diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 583e072799bfd4a379772de76b07555f9c3d2397..57d215d0f333a8a91c1bfe4755fe45eb17cc9098 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -40,14 +40,10 @@ namespace grpc { class ChannelArguments; -std::shared_ptr<ChannelInterface> CreateChannelDeprecated( - const grpc::string &target, const ChannelArguments &args) { - return std::shared_ptr<ChannelInterface>(new Channel(target, args)); -} - std::shared_ptr<ChannelInterface> CreateChannel( const grpc::string &target, const std::unique_ptr<Credentials> &creds, const ChannelArguments &args) { - return std::shared_ptr<ChannelInterface>(new Channel(target, creds, args)); + return creds ? creds->CreateChannel(target, args) : + std::shared_ptr<ChannelInterface>(new Channel(target, grpc_lame_client_channel_create())); } } // namespace grpc diff --git a/src/cpp/client/credentials.cc b/src/cpp/client/credentials.cc index a140f551e0dffc918223cf4deb3b8fd2ee9f9238..e8062849887c0582f713b8fca79f1a6ab6923383 100644 --- a/src/cpp/client/credentials.cc +++ b/src/cpp/client/credentials.cc @@ -31,97 +31,10 @@ * */ -#include <string> - -#include <grpc/grpc_security.h> -#include <grpc/support/log.h> - #include <grpc++/credentials.h> namespace grpc { -Credentials::Credentials(grpc_credentials *c_creds) : creds_(c_creds) {} - -Credentials::~Credentials() { grpc_credentials_release(creds_); } -grpc_credentials *Credentials::GetRawCreds() { return creds_; } - -std::unique_ptr<Credentials> CredentialsFactory::GoogleDefaultCredentials() { - grpc_credentials *c_creds = grpc_google_default_credentials_create(); - std::unique_ptr<Credentials> cpp_creds(new Credentials(c_creds)); - return cpp_creds; -} - -// Builds SSL Credentials given SSL specific options -std::unique_ptr<Credentials> CredentialsFactory::SslCredentials( - const SslCredentialsOptions &options) { - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = { - options.pem_private_key.c_str(), options.pem_cert_chain.c_str()}; - - grpc_credentials *c_creds = grpc_ssl_credentials_create( - options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(), - options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair); - std::unique_ptr<Credentials> cpp_creds( - c_creds == nullptr ? nullptr : new Credentials(c_creds)); - return cpp_creds; -} - -// Builds credentials for use when running in GCE -std::unique_ptr<Credentials> CredentialsFactory::ComputeEngineCredentials() { - grpc_credentials *c_creds = grpc_compute_engine_credentials_create(); - std::unique_ptr<Credentials> cpp_creds( - c_creds == nullptr ? nullptr : new Credentials(c_creds)); - return cpp_creds; -} - -// Builds service account credentials. -std::unique_ptr<Credentials> CredentialsFactory::ServiceAccountCredentials( - const grpc::string &json_key, const grpc::string &scope, - std::chrono::seconds token_lifetime) { - gpr_timespec lifetime = gpr_time_from_seconds( - token_lifetime.count() > 0 ? token_lifetime.count() : 0); - grpc_credentials *c_creds = grpc_service_account_credentials_create( - json_key.c_str(), scope.c_str(), lifetime); - std::unique_ptr<Credentials> cpp_creds( - c_creds == nullptr ? nullptr : new Credentials(c_creds)); - return cpp_creds; -} - -// Builds JWT credentials. -std::unique_ptr<Credentials> CredentialsFactory::JWTCredentials( - const grpc::string &json_key, std::chrono::seconds token_lifetime) { - gpr_timespec lifetime = gpr_time_from_seconds( - token_lifetime.count() > 0 ? token_lifetime.count() : 0); - grpc_credentials *c_creds = - grpc_jwt_credentials_create(json_key.c_str(), lifetime); - std::unique_ptr<Credentials> cpp_creds( - c_creds == nullptr ? nullptr : new Credentials(c_creds)); - return cpp_creds; -} - -// Builds IAM credentials. -std::unique_ptr<Credentials> CredentialsFactory::IAMCredentials( - const grpc::string &authorization_token, - const grpc::string &authority_selector) { - grpc_credentials *c_creds = grpc_iam_credentials_create( - authorization_token.c_str(), authority_selector.c_str()); - std::unique_ptr<Credentials> cpp_creds( - c_creds == nullptr ? nullptr : new Credentials(c_creds)); - return cpp_creds; -} - -// Combines two credentials objects into a composite credentials. -std::unique_ptr<Credentials> CredentialsFactory::CompositeCredentials( - const std::unique_ptr<Credentials> &creds1, - const std::unique_ptr<Credentials> &creds2) { - // Note that we are not saving unique_ptrs to the two credentials - // passed in here. This is OK because the underlying C objects (i.e., - // creds1 and creds2) into grpc_composite_credentials_create will see their - // refcounts incremented. - grpc_credentials *c_creds = grpc_composite_credentials_create( - creds1->GetRawCreds(), creds2->GetRawCreds()); - std::unique_ptr<Credentials> cpp_creds( - c_creds == nullptr ? nullptr : new Credentials(c_creds)); - return cpp_creds; -} +Credentials::~Credentials() {} } // namespace grpc diff --git a/src/core/surface/secure_server_create.c b/src/cpp/client/insecure_credentials.cc similarity index 66% rename from src/core/surface/secure_server_create.c rename to src/cpp/client/insecure_credentials.cc index 1d5b9279977cbe2bd40da3082905b564d5ef9eaa..2dcfe69591aef588056d20a5e172210bed97d808 100644 --- a/src/core/surface/secure_server_create.c +++ b/src/cpp/client/insecure_credentials.cc @@ -31,27 +31,35 @@ * */ -#include <grpc/grpc.h> +#include <string> -#include "src/core/channel/channel_args.h" -#include "src/core/security/security_context.h" -#include "src/core/surface/completion_queue.h" -#include "src/core/surface/server.h" +#include <grpc/grpc.h> #include <grpc/support/log.h> -grpc_server *grpc_secure_server_create_internal( - grpc_completion_queue *cq, const grpc_channel_args *args, - grpc_security_context *context) { - grpc_arg context_arg; - grpc_channel_args *args_copy; - grpc_server *server; - if (grpc_find_security_context_in_args(args) != NULL) { - gpr_log(GPR_ERROR, "Cannot set security context in channel args."); +#include <grpc++/channel_arguments.h> +#include <grpc++/config.h> +#include <grpc++/credentials.h> +#include "src/cpp/client/channel.h" + +namespace grpc { + +namespace { +class InsecureCredentialsImpl GRPC_FINAL : public Credentials { + public: + std::shared_ptr<grpc::ChannelInterface> CreateChannel( + const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE { + grpc_channel_args channel_args; + args.SetChannelArgs(&channel_args); + return std::shared_ptr<ChannelInterface>(new Channel( + target, grpc_channel_create(target.c_str(), &channel_args))); } - context_arg = grpc_security_context_to_arg(context); - args_copy = grpc_channel_args_copy_and_add(args, &context_arg); - server = grpc_server_create_from_filters(cq, NULL, 0, args_copy); - grpc_channel_args_destroy(args_copy); - return server; + SecureCredentials* AsSecureCredentials() { return nullptr; } +}; +} // namespace + +std::unique_ptr<Credentials> InsecureCredentials() { + return std::unique_ptr<Credentials>(new InsecureCredentialsImpl()); } + +} // namespace grpc diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc new file mode 100644 index 0000000000000000000000000000000000000000..47f645c1b6366d9698470a5f79ce974df588648a --- /dev/null +++ b/src/cpp/client/secure_credentials.cc @@ -0,0 +1,132 @@ +/* + * + * 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 <string> + +#include <grpc/grpc_security.h> +#include <grpc/support/log.h> + +#include <grpc++/channel_arguments.h> +#include <grpc++/config.h> +#include <grpc++/credentials.h> +#include "src/cpp/client/channel.h" + +namespace grpc { + +class SecureCredentials GRPC_FINAL : public Credentials { + public: + explicit SecureCredentials(grpc_credentials* c_creds) : c_creds_(c_creds) {} + ~SecureCredentials() GRPC_OVERRIDE { grpc_credentials_release(c_creds_); } + grpc_credentials* GetRawCreds() { return c_creds_; } + + std::shared_ptr<grpc::ChannelInterface> CreateChannel( + const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE { + grpc_channel_args channel_args; + args.SetChannelArgs(&channel_args); + return std::shared_ptr<ChannelInterface>(new Channel( + args.GetSslTargetNameOverride().empty() + ? target : args.GetSslTargetNameOverride(), + grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args))); + } + + SecureCredentials* AsSecureCredentials() { return this; } + + private: + grpc_credentials* const c_creds_; +}; + +namespace { +std::unique_ptr<Credentials> WrapCredentials(grpc_credentials* creds) { + return creds == nullptr + ? nullptr + : std::unique_ptr<Credentials>(new SecureCredentials(creds)); +} +} // namespace + +std::unique_ptr<Credentials> GoogleDefaultCredentials() { + return WrapCredentials(grpc_google_default_credentials_create()); +} + +// Builds SSL Credentials given SSL specific options +std::unique_ptr<Credentials> SslCredentials( + const SslCredentialsOptions& options) { + grpc_ssl_pem_key_cert_pair pem_key_cert_pair = { + options.pem_private_key.c_str(), options.pem_cert_chain.c_str()}; + + grpc_credentials* c_creds = grpc_ssl_credentials_create( + options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(), + options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair); + return WrapCredentials(c_creds); +} + +// Builds credentials for use when running in GCE +std::unique_ptr<Credentials> ComputeEngineCredentials() { + return WrapCredentials(grpc_compute_engine_credentials_create()); +} + +// Builds service account credentials. +std::unique_ptr<Credentials> ServiceAccountCredentials( + const grpc::string& json_key, const grpc::string& scope, + std::chrono::seconds token_lifetime) { + gpr_timespec lifetime = gpr_time_from_seconds( + token_lifetime.count() > 0 ? token_lifetime.count() : 0); + return WrapCredentials(grpc_service_account_credentials_create( + json_key.c_str(), scope.c_str(), lifetime)); +} + +// Builds IAM credentials. +std::unique_ptr<Credentials> IAMCredentials( + const grpc::string& authorization_token, + const grpc::string& authority_selector) { + return WrapCredentials(grpc_iam_credentials_create( + authorization_token.c_str(), authority_selector.c_str())); +} + +// Combines two credentials objects into a composite credentials. +std::unique_ptr<Credentials> CompositeCredentials( + const std::unique_ptr<Credentials>& creds1, + const std::unique_ptr<Credentials>& creds2) { + // Note that we are not saving unique_ptrs to the two credentials + // passed in here. This is OK because the underlying C objects (i.e., + // creds1 and creds2) into grpc_composite_credentials_create will see their + // refcounts incremented. + SecureCredentials* s1 = creds1->AsSecureCredentials(); + SecureCredentials* s2 = creds2->AsSecureCredentials(); + if (s1 && s2) { + return WrapCredentials(grpc_composite_credentials_create( + s1->GetRawCreds(), s2->GetRawCreds())); + } + return nullptr; +} + +} // namespace grpc diff --git a/src/cpp/common/call.cc b/src/cpp/common/call.cc index f3a691114d2453a1a325277dedc04efbd28ac613..6ce1e8a7d580eb30eab36afce5e08af53737e854 100644 --- a/src/cpp/common/call.cc +++ b/src/cpp/common/call.cc @@ -31,7 +31,6 @@ * */ -#include <google/protobuf/message.h> #include <grpc/support/alloc.h> #include <grpc++/impl/call.h> #include <grpc++/client_context.h> @@ -163,11 +162,11 @@ void CallOpBuffer::AddSendInitialMetadata(ClientContext* ctx) { AddSendInitialMetadata(&ctx->send_initial_metadata_); } -void CallOpBuffer::AddSendMessage(const google::protobuf::Message& message) { +void CallOpBuffer::AddSendMessage(const grpc::protobuf::Message& message) { send_message_ = &message; } -void CallOpBuffer::AddRecvMessage(google::protobuf::Message* message) { +void CallOpBuffer::AddRecvMessage(grpc::protobuf::Message* message) { recv_message_ = message; recv_message_->Clear(); } diff --git a/src/cpp/proto/proto_utils.cc b/src/cpp/proto/proto_utils.cc index 69a6bb080e0abed0b637ab443118955528bf9dbb..e4e51bfebf5e78d048cf6ce447b105307dbc48b1 100644 --- a/src/cpp/proto/proto_utils.cc +++ b/src/cpp/proto/proto_utils.cc @@ -35,39 +35,135 @@ #include <grpc++/config.h> #include <grpc/grpc.h> +#include <grpc/byte_buffer.h> #include <grpc/support/slice.h> -#include <google/protobuf/message.h> +#include <grpc/support/slice_buffer.h> +#include <grpc/support/port_platform.h> +#include <google/protobuf/io/zero_copy_stream.h> -namespace grpc { +const int kMaxBufferLength = 8192; -bool SerializeProto(const google::protobuf::Message &msg, - grpc_byte_buffer **bp) { - grpc::string msg_str; - bool success = msg.SerializeToString(&msg_str); - if (success) { - gpr_slice slice = - gpr_slice_from_copied_buffer(msg_str.data(), msg_str.length()); - *bp = grpc_byte_buffer_create(&slice, 1); - gpr_slice_unref(slice); +class GrpcBufferWriter GRPC_FINAL + : public ::google::protobuf::io::ZeroCopyOutputStream { + public: + explicit GrpcBufferWriter(grpc_byte_buffer **bp, + int block_size = kMaxBufferLength) + : block_size_(block_size), byte_count_(0), have_backup_(false) { + *bp = grpc_byte_buffer_create(NULL, 0); + slice_buffer_ = &(*bp)->data.slice_buffer; + } + + ~GrpcBufferWriter() GRPC_OVERRIDE { + if (have_backup_) { + gpr_slice_unref(backup_slice_); + } + } + + bool Next(void **data, int *size) GRPC_OVERRIDE { + if (have_backup_) { + slice_ = backup_slice_; + have_backup_ = false; + } else { + slice_ = gpr_slice_malloc(block_size_); + } + *data = GPR_SLICE_START_PTR(slice_); + byte_count_ += *size = GPR_SLICE_LENGTH(slice_); + gpr_slice_buffer_add(slice_buffer_, slice_); + return true; + } + + void BackUp(int count) GRPC_OVERRIDE { + gpr_slice_buffer_pop(slice_buffer_); + if (count == block_size_) { + backup_slice_ = slice_; + } else { + backup_slice_ = + gpr_slice_split_tail(&slice_, GPR_SLICE_LENGTH(slice_) - count); + gpr_slice_buffer_add(slice_buffer_, slice_); + } + have_backup_ = true; + byte_count_ -= count; + } + + gpr_int64 ByteCount() const GRPC_OVERRIDE { return byte_count_; } + + private: + const int block_size_; + gpr_int64 byte_count_; + gpr_slice_buffer *slice_buffer_; + bool have_backup_; + gpr_slice backup_slice_; + gpr_slice slice_; +}; + +class GrpcBufferReader GRPC_FINAL + : public ::google::protobuf::io::ZeroCopyInputStream { + public: + explicit GrpcBufferReader(grpc_byte_buffer *buffer) + : byte_count_(0), backup_count_(0) { + reader_ = grpc_byte_buffer_reader_create(buffer); + } + ~GrpcBufferReader() GRPC_OVERRIDE { + grpc_byte_buffer_reader_destroy(reader_); } - return success; -} -bool DeserializeProto(grpc_byte_buffer *buffer, - google::protobuf::Message *msg) { - grpc::string msg_string; - grpc_byte_buffer_reader *reader = grpc_byte_buffer_reader_create(buffer); - gpr_slice slice; - while (grpc_byte_buffer_reader_next(reader, &slice)) { - const char *data = reinterpret_cast<const char *>( - slice.refcount ? slice.data.refcounted.bytes - : slice.data.inlined.bytes); - msg_string.append(data, slice.refcount ? slice.data.refcounted.length - : slice.data.inlined.length); - gpr_slice_unref(slice); + bool Next(const void **data, int *size) GRPC_OVERRIDE { + if (backup_count_ > 0) { + *data = GPR_SLICE_START_PTR(slice_) + GPR_SLICE_LENGTH(slice_) - + backup_count_; + *size = backup_count_; + backup_count_ = 0; + return true; + } + if (!grpc_byte_buffer_reader_next(reader_, &slice_)) { + return false; + } + gpr_slice_unref(slice_); + *data = GPR_SLICE_START_PTR(slice_); + byte_count_ += *size = GPR_SLICE_LENGTH(slice_); + return true; } - grpc_byte_buffer_reader_destroy(reader); - return msg->ParseFromString(msg_string); + + void BackUp(int count) GRPC_OVERRIDE { + backup_count_ = count; + } + + bool Skip(int count) GRPC_OVERRIDE { + const void *data; + int size; + while (Next(&data, &size)) { + if (size >= count) { + BackUp(size - count); + return true; + } + // size < count; + count -= size; + } + // error or we have too large count; + return false; + } + + gpr_int64 ByteCount() const GRPC_OVERRIDE { + return byte_count_ - backup_count_; + } + + private: + gpr_int64 byte_count_; + gpr_int64 backup_count_; + grpc_byte_buffer_reader *reader_; + gpr_slice slice_; +}; + +namespace grpc { + +bool SerializeProto(const grpc::protobuf::Message &msg, grpc_byte_buffer **bp) { + GrpcBufferWriter writer(bp); + return msg.SerializeToZeroCopyStream(&writer); +} + +bool DeserializeProto(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg) { + GrpcBufferReader reader(buffer); + return msg->ParseFromZeroCopyStream(&reader); } } // namespace grpc diff --git a/src/cpp/proto/proto_utils.h b/src/cpp/proto/proto_utils.h index a0af4d6465d6e0cac71008f3dbf63eb89b82b26b..7a1b1f8b7cb289776c681d72b6a1feca1234de39 100644 --- a/src/cpp/proto/proto_utils.h +++ b/src/cpp/proto/proto_utils.h @@ -34,23 +34,20 @@ #ifndef GRPC_INTERNAL_CPP_PROTO_PROTO_UTILS_H #define GRPC_INTERNAL_CPP_PROTO_PROTO_UTILS_H +#include <grpc++/config.h> + struct grpc_byte_buffer; -namespace google { -namespace protobuf { -class Message; -} -} namespace grpc { // Serialize the msg into a buffer created inside the function. The caller // should destroy the returned buffer when done with it. If serialization fails, // false is returned and buffer is left unchanged. -bool SerializeProto(const google::protobuf::Message &msg, +bool SerializeProto(const grpc::protobuf::Message &msg, grpc_byte_buffer **buffer); // The caller keeps ownership of buffer and msg. -bool DeserializeProto(grpc_byte_buffer *buffer, google::protobuf::Message *msg); +bool DeserializeProto(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg); } // namespace grpc diff --git a/src/cpp/server/async_server_context.cc b/src/cpp/server/async_server_context.cc index 5f8c2ba10f4cd5511d0a3216c2d920370f48622f..f21efcfb19ac2c0b82986ce88bfcf9127b093c76 100644 --- a/src/cpp/server/async_server_context.cc +++ b/src/cpp/server/async_server_context.cc @@ -36,7 +36,7 @@ #include <grpc/grpc.h> #include <grpc/support/log.h> #include "src/cpp/proto/proto_utils.h" -#include <google/protobuf/message.h> +#include <grpc++/config.h> #include <grpc++/status.h> namespace grpc { @@ -58,14 +58,14 @@ void AsyncServerContext::Accept(grpc_completion_queue *cq) { call_, GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); } -bool AsyncServerContext::StartRead(google::protobuf::Message *request) { +bool AsyncServerContext::StartRead(grpc::protobuf::Message *request) { GPR_ASSERT(request); request_ = request; grpc_call_error err = grpc_call_start_read_old(call_, this); return err == GRPC_CALL_OK; } -bool AsyncServerContext::StartWrite(const google::protobuf::Message &response, +bool AsyncServerContext::StartWrite(const grpc::protobuf::Message &response, int flags) { grpc_byte_buffer *buffer = nullptr; if (!SerializeProto(response, &buffer)) { diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc new file mode 100644 index 0000000000000000000000000000000000000000..f5e4732f73050bcf9db1b78655db2ed7a6c68cc4 --- /dev/null +++ b/src/cpp/server/insecure_server_credentials.cc @@ -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. + * + */ + +#include <grpc/grpc_security.h> +#include <grpc++/server_credentials.h> + +namespace grpc { +namespace { +class InsecureServerCredentialsImpl GRPC_FINAL : public ServerCredentials { + public: + int AddPortToServer(const grpc::string& addr, + grpc_server* server) GRPC_OVERRIDE { + return grpc_server_add_http2_port(server, addr.c_str()); + } +}; +} // namespace + +std::shared_ptr<ServerCredentials> InsecureServerCredentials() { + return std::shared_ptr<ServerCredentials>(new InsecureServerCredentialsImpl()); +} + +} // namespace grpc diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc new file mode 100644 index 0000000000000000000000000000000000000000..ff356385034e7a4a10a43b8134e151abf115ad1d --- /dev/null +++ b/src/cpp/server/secure_server_credentials.cc @@ -0,0 +1,71 @@ +/* + * + * 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 <grpc/grpc_security.h> + +#include <grpc++/server_credentials.h> + +namespace grpc { + +namespace { +class SecureServerCredentials GRPC_FINAL : public ServerCredentials { + public: + explicit SecureServerCredentials(grpc_server_credentials* creds) : creds_(creds) {} + ~SecureServerCredentials() GRPC_OVERRIDE { + grpc_server_credentials_release(creds_); + } + + int AddPortToServer(const grpc::string& addr, + grpc_server* server) GRPC_OVERRIDE { + return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_); + } + + private: + grpc_server_credentials* const creds_; +}; +} // namespace + +std::shared_ptr<ServerCredentials> SslServerCredentials( + const SslServerCredentialsOptions &options) { + std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs; + for (const auto &key_cert_pair : options.pem_key_cert_pairs) { + pem_key_cert_pairs.push_back( + {key_cert_pair.private_key.c_str(), key_cert_pair.cert_chain.c_str()}); + } + grpc_server_credentials *c_creds = grpc_ssl_server_credentials_create( + options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(), + &pem_key_cert_pairs[0], pem_key_cert_pairs.size()); + return std::shared_ptr<ServerCredentials>(new SecureServerCredentials(c_creds)); +} + +} // namespace grpc diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index 97bf0f1a6ea8ce9a15a6fb901770a6b197fa6fa7..e69032a657d27f4c200c69bf422ae50f692aac47 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -117,8 +117,8 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag { } void Run() { - std::unique_ptr<google::protobuf::Message> req; - std::unique_ptr<google::protobuf::Message> res; + std::unique_ptr<grpc::protobuf::Message> req; + std::unique_ptr<grpc::protobuf::Message> res; if (has_request_payload_) { req.reset(method_->AllocateRequestProto()); if (!DeserializeProto(request_payload_, req.get())) { @@ -170,26 +170,13 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag { grpc_completion_queue* cq_; }; -Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned, - ServerCredentials* creds) +Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned) : started_(false), shutdown_(false), num_running_cb_(0), + server_(grpc_server_create(cq_.cq(), nullptr)), thread_pool_(thread_pool), - thread_pool_owned_(thread_pool_owned), - secure_(creds != nullptr) { - if (creds) { - server_ = - grpc_secure_server_create(creds->GetRawCreds(), cq_.cq(), nullptr); - } else { - server_ = grpc_server_create(cq_.cq(), nullptr); - } -} - -Server::Server() { - // Should not be called. - GPR_ASSERT(false); -} + thread_pool_owned_(thread_pool_owned) {} Server::~Server() { std::unique_lock<std::mutex> lock(mu_); @@ -239,13 +226,9 @@ bool Server::RegisterAsyncService(AsynchronousService* service) { return true; } -int Server::AddPort(const grpc::string& addr) { +int Server::AddPort(const grpc::string& addr, ServerCredentials* creds) { GPR_ASSERT(!started_); - if (secure_) { - return grpc_server_add_secure_http2_port(server_, addr.c_str()); - } else { - return grpc_server_add_http2_port(server_, addr.c_str()); - } + return creds->AddPortToServer(addr, server_); } bool Server::Start() { @@ -298,7 +281,7 @@ void Server::PerformOpsOnCall(CallOpBuffer* buf, Call* call) { class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag { public: AsyncRequest(Server* server, void* registered_method, ServerContext* ctx, - ::google::protobuf::Message* request, + grpc::protobuf::Message* request, ServerAsyncStreamingInterface* stream, CompletionQueue* cq, void* tag) : tag_(tag), @@ -324,6 +307,7 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag { bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE { *tag = tag_; + bool orig_status = *status; if (*status && request_) { if (payload_) { *status = DeserializeProto(payload_, request_); @@ -343,7 +327,9 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag { } ctx_->call_ = call_; Call call(call_, server_, cq_); - ctx_->BeginCompletionOp(&call); + if (orig_status && call_) { + ctx_->BeginCompletionOp(&call); + } // just the pointers inside call are copied here stream_->BindCall(&call); delete this; @@ -352,7 +338,7 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag { private: void* const tag_; - ::google::protobuf::Message* const request_; + grpc::protobuf::Message* const request_; ServerAsyncStreamingInterface* const stream_; CompletionQueue* const cq_; ServerContext* const ctx_; @@ -364,7 +350,7 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag { }; void Server::RequestAsyncCall(void* registered_method, ServerContext* context, - ::google::protobuf::Message* request, + grpc::protobuf::Message* request, ServerAsyncStreamingInterface* stream, CompletionQueue* cq, void* tag) { new AsyncRequest(this, registered_method, context, request, stream, cq, tag); diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index ae60f3d8b6743b0fdaec55b144aad75321d748e8..5de592334d76c66ddeaf5dc759e8869486ac1e63 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -51,14 +51,10 @@ void ServerBuilder::RegisterAsyncService(AsynchronousService* service) { async_services_.push_back(service); } -void ServerBuilder::AddPort(const grpc::string& addr) { - ports_.push_back(addr); -} - -void ServerBuilder::SetCredentials( - const std::shared_ptr<ServerCredentials>& creds) { - GPR_ASSERT(!creds_); - creds_ = creds; +void ServerBuilder::AddPort(const grpc::string& addr, + std::shared_ptr<ServerCredentials> creds, + int* selected_port) { + ports_.push_back(Port{addr, creds, selected_port}); } void ServerBuilder::SetThreadPool(ThreadPoolInterface* thread_pool) { @@ -71,14 +67,13 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() { gpr_log(GPR_ERROR, "Mixing async and sync services is unsupported for now"); return nullptr; } - if (!thread_pool_ && services_.size()) { + if (!thread_pool_ && !services_.empty()) { int cores = gpr_cpu_num_cores(); if (!cores) cores = 4; thread_pool_ = new ThreadPool(cores); thread_pool_owned = true; } - std::unique_ptr<Server> server( - new Server(thread_pool_, thread_pool_owned, creds_.get())); + std::unique_ptr<Server> server(new Server(thread_pool_, thread_pool_owned)); for (auto* service : services_) { if (!server->RegisterService(service)) { return nullptr; @@ -90,8 +85,10 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() { } } for (auto& port : ports_) { - if (!server->AddPort(port)) { - return nullptr; + int r = server->AddPort(port.addr, port.creds.get()); + if (!r) return nullptr; + if (port.selected_port != nullptr) { + *port.selected_port = r; } } if (!server->Start()) { diff --git a/src/cpp/server/server_credentials.cc b/src/cpp/server/server_credentials.cc index 69ad000ccc69f2d433910c52dc421466b6e193f4..6bdb465baaa5cd4e3b808f3ea3724c84eb6f7922 100644 --- a/src/cpp/server/server_credentials.cc +++ b/src/cpp/server/server_credentials.cc @@ -37,26 +37,6 @@ namespace grpc { -ServerCredentials::ServerCredentials(grpc_server_credentials *c_creds) - : creds_(c_creds) {} - -ServerCredentials::~ServerCredentials() { - grpc_server_credentials_release(creds_); -} - -grpc_server_credentials *ServerCredentials::GetRawCreds() { return creds_; } - -std::shared_ptr<ServerCredentials> ServerCredentialsFactory::SslCredentials( - const SslServerCredentialsOptions &options) { - std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs; - for (const auto &key_cert_pair : options.pem_key_cert_pairs) { - pem_key_cert_pairs.push_back( - {key_cert_pair.private_key.c_str(), key_cert_pair.cert_chain.c_str()}); - } - grpc_server_credentials *c_creds = grpc_ssl_server_credentials_create( - options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(), - &pem_key_cert_pairs[0], pem_key_cert_pairs.size()); - return std::shared_ptr<ServerCredentials>(new ServerCredentials(c_creds)); -} +ServerCredentials::~ServerCredentials() {} } // namespace grpc diff --git a/src/csharp/.gitignore b/src/csharp/.gitignore index d35ff63f6ef4756198b8e7fe344fa50fa03788ee..dbaf60de0cf6dfbeb27fa4948a42a70982b10ef6 100644 --- a/src/csharp/.gitignore +++ b/src/csharp/.gitignore @@ -1,4 +1,6 @@ *.userprefs +StyleCop.Cache test-results packages Grpc.v12.suo +TestResult.xml diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs index 282d521ba3798004837e5c593d268c1103cd39f0..9db08d2f02f7ba5042a694cdd30ef065eedf1c9a 100644 --- a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs +++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs @@ -127,8 +127,6 @@ namespace Grpc.Core.Tests [Test] public void NopPInvokeBenchmark() { - CompletionCallbackDelegate handler = Handler; - BenchmarkUtil.RunBenchmark( 1000000, 100000000, () => { diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs index 942651cf3935a3cf3a567573e5c87aa5c35fd64a..83d965debf12a097874e97f026195f91e5605a01 100644 --- a/src/csharp/Grpc.Core/Channel.cs +++ b/src/csharp/Grpc.Core/Channel.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -28,9 +27,7 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - #endregion - using System; using System.Runtime.InteropServices; using System.Threading; @@ -39,18 +36,32 @@ using Grpc.Core.Internal; namespace Grpc.Core { - public class Channel : IDisposable - { + public class Channel : IDisposable + { readonly ChannelSafeHandle handle; readonly String target; - // TODO: add way how to create grpc_secure_channel.... - // TODO: add support for channel args... - public Channel(string target) - { - this.handle = ChannelSafeHandle.Create(target, IntPtr.Zero); - this.target = target; - } + /// <summary> + /// Creates a channel. + /// </summary> + public Channel(string target, Credentials credentials = null, ChannelArgs channelArgs = null) + { + using (ChannelArgsSafeHandle nativeChannelArgs = CreateNativeChannelArgs(channelArgs)) + { + if (credentials != null) + { + using (CredentialsSafeHandle nativeCredentials = credentials.ToNativeCredentials()) + { + this.handle = ChannelSafeHandle.CreateSecure(nativeCredentials, target, nativeChannelArgs); + } + } + else + { + this.handle = ChannelSafeHandle.Create(target, nativeChannelArgs); + } + } + this.target = GetOverridenTarget(target, channelArgs); + } internal ChannelSafeHandle Handle { @@ -81,5 +92,23 @@ namespace Grpc.Core handle.Dispose(); } } - } + + private static string GetOverridenTarget(string target, ChannelArgs args) + { + if (args != null && !string.IsNullOrEmpty(args.GetSslTargetNameOverride())) + { + return args.GetSslTargetNameOverride(); + } + return target; + } + + private static ChannelArgsSafeHandle CreateNativeChannelArgs(ChannelArgs args) + { + if (args == null) + { + return ChannelArgsSafeHandle.CreateNull(); + } + return args.ToNativeChannelArgs(); + } + } } diff --git a/src/csharp/Grpc.Core/ChannelArgs.cs b/src/csharp/Grpc.Core/ChannelArgs.cs new file mode 100644 index 0000000000000000000000000000000000000000..298b6edf2066f78e031ea6ca990a10bd47961364 --- /dev/null +++ b/src/csharp/Grpc.Core/ChannelArgs.cs @@ -0,0 +1,112 @@ +#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.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Internal; + +namespace Grpc.Core +{ + // TODO: should we be using the builder pattern? + public class ChannelArgs + { + public const string SslTargetNameOverrideKey = "grpc.ssl_target_name_override"; + + public class Builder + { + Dictionary<string,string> stringArgs = new Dictionary<string,string>(); + // TODO: AddInteger not supported yet. + public Builder AddString(string key, string value) + { + stringArgs.Add(key, value); + return this; + } + + public ChannelArgs Build() + { + return new ChannelArgs(stringArgs); + } + } + + Dictionary<string,string> stringArgs; + + private ChannelArgs(Dictionary<string, string> stringArgs) + { + // TODO: use immutable dict? + this.stringArgs = new Dictionary<string, string>(stringArgs); + } + + public string GetSslTargetNameOverride() + { + string result; + if (stringArgs.TryGetValue(SslTargetNameOverrideKey, out result)) + { + return result; + } + return null; + } + + public static Builder NewBuilder() + { + return new Builder(); + } + + /// <summary> + /// Creates native object for the channel arguments. + /// </summary> + /// <returns>The native channel arguments.</returns> + internal ChannelArgsSafeHandle ToNativeChannelArgs() + { + ChannelArgsSafeHandle nativeArgs = null; + try + { + nativeArgs = ChannelArgsSafeHandle.Create(stringArgs.Count); + int i = 0; + foreach (var entry in stringArgs) + { + nativeArgs.SetString(i, entry.Key, entry.Value); + i++; + } + return nativeArgs; + } + catch (Exception) + { + if (nativeArgs != null) + { + nativeArgs.Dispose(); + } + throw; + } + } + } +} diff --git a/src/csharp/Grpc.Core/Credentials.cs b/src/csharp/Grpc.Core/Credentials.cs new file mode 100644 index 0000000000000000000000000000000000000000..5116c277f72a6880abb56a142b5876c1e16c9914 --- /dev/null +++ b/src/csharp/Grpc.Core/Credentials.cs @@ -0,0 +1,77 @@ +#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 Grpc.Core.Internal; + +namespace Grpc.Core +{ + public abstract class Credentials + { + /// <summary> + /// Creates native object for the credentials. + /// </summary> + /// <returns>The native credentials.</returns> + internal abstract CredentialsSafeHandle ToNativeCredentials(); + } + + /// <summary> + /// Client-side SSL credentials. + /// </summary> + public class SslCredentials : Credentials + { + string pemRootCerts; + + public SslCredentials(string pemRootCerts) + { + this.pemRootCerts = pemRootCerts; + } + + /// <summary> + /// PEM encoding of the server root certificates. + /// </summary> + public string RootCerts + { + get + { + return this.pemRootCerts; + } + } + + internal override CredentialsSafeHandle ToNativeCredentials() + { + return CredentialsSafeHandle.CreateSslCredentials(pemRootCerts); + } + } +} + diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 05d40d45a6e4c6614cbd728d55cf86caaa5d13b6..78b6cdde59bc11f7052a290d3d15c04e8141b310 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -51,7 +51,6 @@ <Compile Include="Internal\SafeHandleZeroIsInvalid.cs" /> <Compile Include="Internal\Timespec.cs" /> <Compile Include="Internal\GrpcThreadPool.cs" /> - <Compile Include="Internal\AsyncCall.cs" /> <Compile Include="Internal\ServerSafeHandle.cs" /> <Compile Include="Method.cs" /> <Compile Include="ServerCalls.cs" /> @@ -65,6 +64,16 @@ <Compile Include="Internal\BatchContextSafeHandleNotOwned.cs" /> <Compile Include="Utils\BenchmarkUtil.cs" /> <Compile Include="Utils\ExceptionHelper.cs" /> + <Compile Include="Internal\CredentialsSafeHandle.cs" /> + <Compile Include="Credentials.cs" /> + <Compile Include="Internal\ChannelArgsSafeHandle.cs" /> + <Compile Include="ChannelArgs.cs" /> + <Compile Include="Internal\AsyncCompletion.cs" /> + <Compile Include="Internal\AsyncCallBase.cs" /> + <Compile Include="Internal\AsyncCallServer.cs" /> + <Compile Include="OperationFailedException.cs" /> + <Compile Include="Internal\AsyncCall.cs" /> + <Compile Include="Utils\Preconditions.cs" /> </ItemGroup> <Choose> <!-- Under older versions of Monodevelop, Choose is not supported and is just diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index 6f37b059f75dcc22b1d85b0dbf85ef7d95d68f38..5ae036298b00c16f032dc6832f1ba7bf91b76d7f 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -43,84 +43,47 @@ using Grpc.Core.Utils; namespace Grpc.Core.Internal { /// <summary> - /// Handles native call lifecycle and provides convenience methods. + /// Handles client side native call lifecycle. /// </summary> - internal class AsyncCall<TWrite, TRead> + internal class AsyncCall<TRequest, TResponse> : AsyncCallBase<TRequest, TResponse> { - readonly Func<TWrite, byte[]> serializer; - readonly Func<byte[], TRead> deserializer; - readonly CompletionCallbackDelegate unaryResponseHandler; readonly CompletionCallbackDelegate finishedHandler; - readonly CompletionCallbackDelegate writeFinishedHandler; - readonly CompletionCallbackDelegate readFinishedHandler; - readonly CompletionCallbackDelegate halfclosedHandler; - readonly CompletionCallbackDelegate finishedServersideHandler; - - object myLock = new object(); - GCHandle gchandle; - CallSafeHandle call; - bool disposed; - - bool server; - - bool started; - bool errorOccured; - bool cancelRequested; - bool readingDone; - bool halfcloseRequested; - bool halfclosed; - bool finished; - - // Completion of a pending write if not null. - TaskCompletionSource<object> writeTcs; - - // Completion of a pending read if not null. - TaskCompletionSource<TRead> readTcs; - - // Completion of a pending halfclose if not null. - TaskCompletionSource<object> halfcloseTcs; // Completion of a pending unary response if not null. - TaskCompletionSource<TRead> unaryResponseTcs; + TaskCompletionSource<TResponse> unaryResponseTcs; - // Set after status is received on client. Only used for server streaming and duplex streaming calls. + // Set after status is received. Only used for streaming response calls. Nullable<Status> finishedStatus; - TaskCompletionSource<object> finishedServersideTcs = new TaskCompletionSource<object>(); - // For streaming, the reads will be delivered to this observer. - IObserver<TRead> readObserver; + bool readObserverCompleted; // True if readObserver has already been completed. - public AsyncCall(Func<TWrite, byte[]> serializer, Func<byte[], TRead> deserializer) + public AsyncCall(Func<TRequest, byte[]> serializer, Func<byte[], TResponse> deserializer) : base(serializer, deserializer) { - this.serializer = serializer; - this.deserializer = deserializer; - this.unaryResponseHandler = HandleUnaryResponse; - this.finishedHandler = HandleFinished; - this.writeFinishedHandler = HandleWriteFinished; - this.readFinishedHandler = HandleReadFinished; - this.halfclosedHandler = HandleHalfclosed; - this.finishedServersideHandler = HandleFinishedServerside; + this.unaryResponseHandler = CreateBatchCompletionCallback(HandleUnaryResponse); + this.finishedHandler = CreateBatchCompletionCallback(HandleFinished); } public void Initialize(Channel channel, CompletionQueueSafeHandle cq, String methodName) { - InitializeInternal(CallSafeHandle.Create(channel.Handle, cq, methodName, channel.Target, Timespec.InfFuture), false); + var call = CallSafeHandle.Create(channel.Handle, cq, methodName, channel.Target, Timespec.InfFuture); + InitializeInternal(call); } - public void InitializeServer(CallSafeHandle call) - { - InitializeInternal(call, true); - } - - public TRead UnaryCall(Channel channel, String methodName, TWrite msg) + // TODO: this method is not Async, so it shouldn't be in AsyncCall class, but + // it is reusing fair amount of code in this class, so we are leaving it here. + // TODO: for other calls, you need to call Initialize, this methods calls initialize + // on its own, so there's a usage inconsistency. + /// <summary> + /// Blocking unary request - unary response call. + /// </summary> + public TResponse UnaryCall(Channel channel, String methodName, TRequest msg) { using(CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create()) { - // TODO: handle serialization error... - byte[] payload = serializer(msg); + byte[] payload = UnsafeSerialize(msg); - unaryResponseTcs = new TaskCompletionSource<TRead>(); + unaryResponseTcs = new TaskCompletionSource<TResponse>(); lock (myLock) { @@ -143,508 +106,200 @@ namespace Grpc.Core.Internal } } - public Task<TRead> UnaryCallAsync(TWrite msg) + /// <summary> + /// Starts a unary request - unary response call. + /// </summary> + public Task<TResponse> UnaryCallAsync(TRequest msg) { lock (myLock) { + Preconditions.CheckNotNull(call); + started = true; halfcloseRequested = true; readingDone = true; - // TODO: handle serialization error... - byte[] payload = serializer(msg); + byte[] payload = UnsafeSerialize(msg); - unaryResponseTcs = new TaskCompletionSource<TRead>(); + unaryResponseTcs = new TaskCompletionSource<TResponse>(); call.StartUnary(payload, unaryResponseHandler); return unaryResponseTcs.Task; } } - public Task<TRead> ClientStreamingCallAsync() + /// <summary> + /// Starts a streamed request - unary response call. + /// Use StartSendMessage and StartSendCloseFromClient to stream requests. + /// </summary> + public Task<TResponse> ClientStreamingCallAsync() { lock (myLock) { + Preconditions.CheckNotNull(call); + started = true; readingDone = true; - unaryResponseTcs = new TaskCompletionSource<TRead>(); + unaryResponseTcs = new TaskCompletionSource<TResponse>(); call.StartClientStreaming(unaryResponseHandler); return unaryResponseTcs.Task; } } - public void StartServerStreamingCall(TWrite msg, IObserver<TRead> readObserver) + /// <summary> + /// Starts a unary request - streamed response call. + /// </summary> + public void StartServerStreamingCall(TRequest msg, IObserver<TResponse> readObserver) { lock (myLock) { + Preconditions.CheckNotNull(call); + started = true; halfcloseRequested = true; halfclosed = true; // halfclose not confirmed yet, but it will be once finishedHandler is called. this.readObserver = readObserver; - // TODO: handle serialization error... - byte[] payload = serializer(msg); + byte[] payload = UnsafeSerialize(msg); call.StartServerStreaming(payload, finishedHandler); - ReceiveMessageAsync(); + StartReceiveMessage(); } } - public void StartDuplexStreamingCall(IObserver<TRead> readObserver) + /// <summary> + /// Starts a streaming request - streaming response call. + /// Use StartSendMessage and StartSendCloseFromClient to stream requests. + /// </summary> + public void StartDuplexStreamingCall(IObserver<TResponse> readObserver) { lock (myLock) { + Preconditions.CheckNotNull(call); + started = true; this.readObserver = readObserver; call.StartDuplexStreaming(finishedHandler); - ReceiveMessageAsync(); + StartReceiveMessage(); } } - public Task ServerSideUnaryRequestCallAsync() - { - lock (myLock) - { - started = true; - call.StartServerSide(finishedServersideHandler); - return finishedServersideTcs.Task; - } - } - - public Task ServerSideStreamingRequestCallAsync(IObserver<TRead> readObserver) - { - lock (myLock) - { - started = true; - call.StartServerSide(finishedServersideHandler); - - if (this.readObserver != null) - { - throw new InvalidOperationException("Already registered an observer."); - } - this.readObserver = readObserver; - ReceiveMessageAsync(); - - return finishedServersideTcs.Task; - } - } - - public Task SendMessageAsync(TWrite msg) + /// <summary> + /// Sends a streaming request. Only one pending send action is allowed at any given time. + /// completionDelegate is called when the operation finishes. + /// </summary> + public void StartSendMessage(TRequest msg, AsyncCompletionDelegate completionDelegate) { - lock (myLock) - { - CheckNotDisposed(); - CheckStarted(); - CheckNoError(); - - if (halfcloseRequested) - { - throw new InvalidOperationException("Already halfclosed."); - } - - if (writeTcs != null) - { - throw new InvalidOperationException("Only one write can be pending at a time"); - } - - // TODO: wrap serialization... - byte[] payload = serializer(msg); - - call.StartSendMessage(payload, writeFinishedHandler); - writeTcs = new TaskCompletionSource<object>(); - return writeTcs.Task; - } + StartSendMessageInternal(msg, completionDelegate); } - public Task SendCloseFromClientAsync() + /// <summary> + /// Sends halfclose, indicating client is done with streaming requests. + /// Only one pending send action is allowed at any given time. + /// completionDelegate is called when the operation finishes. + /// </summary> + public void StartSendCloseFromClient(AsyncCompletionDelegate completionDelegate) { lock (myLock) { - CheckNotDisposed(); - CheckStarted(); - CheckNoError(); - - if (halfcloseRequested) - { - throw new InvalidOperationException("Already halfclosed."); - } + Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null"); + CheckSendingAllowed(); call.StartSendCloseFromClient(halfclosedHandler); halfcloseRequested = true; - halfcloseTcs = new TaskCompletionSource<object>(); - return halfcloseTcs.Task; - } - } - - public Task SendStatusFromServerAsync(Status status) - { - lock (myLock) - { - CheckNotDisposed(); - CheckStarted(); - CheckNoError(); - - if (halfcloseRequested) - { - throw new InvalidOperationException("Already halfclosed."); - } - - call.StartSendStatusFromServer(status, halfclosedHandler); - halfcloseRequested = true; - halfcloseTcs = new TaskCompletionSource<object>(); - return halfcloseTcs.Task; + sendCompletionDelegate = completionDelegate; } } - public Task<TRead> ReceiveMessageAsync() + /// <summary> + /// On client-side, we only fire readObserver.OnCompleted once all messages have been read + /// and status has been received. + /// </summary> + protected override void CompleteReadObserver() { - lock (myLock) + if (readingDone && finishedStatus.HasValue) { - CheckNotDisposed(); - CheckStarted(); - CheckNoError(); - - if (readingDone) - { - throw new InvalidOperationException("Already read the last message."); - } - - if (readTcs != null) + bool shouldComplete; + lock (myLock) { - throw new InvalidOperationException("Only one read can be pending at a time"); + shouldComplete = !readObserverCompleted; + readObserverCompleted = true; } - call.StartReceiveMessage(readFinishedHandler); - - readTcs = new TaskCompletionSource<TRead>(); - return readTcs.Task; - } - } - - public void Cancel() - { - lock (myLock) - { - CheckNotDisposed(); - CheckStarted(); - cancelRequested = true; - } - // grpc_call_cancel is threadsafe - call.Cancel(); - } - - public void CancelWithStatus(Status status) - { - lock (myLock) - { - CheckNotDisposed(); - CheckStarted(); - cancelRequested = true; - } - // grpc_call_cancel_with_status is threadsafe - call.CancelWithStatus(status); - } - - private void InitializeInternal(CallSafeHandle call, bool server) - { - lock (myLock) - { - // Make sure this object and the delegated held by it will not be garbage collected - // before we release this handle. - gchandle = GCHandle.Alloc(this); - this.call = call; - this.server = server; - } - } - - private void CheckStarted() - { - if (!started) - { - throw new InvalidOperationException("Call not started"); - } - } - - private void CheckNotDisposed() - { - if (disposed) - { - throw new InvalidOperationException("Call has already been disposed."); - } - } - - private void CheckNoError() - { - if (errorOccured) - { - throw new InvalidOperationException("Error occured when processing call."); - } - } - - private bool ReleaseResourcesIfPossible() - { - if (!disposed && call != null) - { - if (halfclosed && readingDone && finished) + if (shouldComplete) { - ReleaseResources(); - return true; + var status = finishedStatus.Value; + if (status.StatusCode != StatusCode.OK) + { + FireReadObserverOnError(new RpcException(status)); + } + else + { + FireReadObserverOnCompleted(); + } } } - return false; - } - - private void ReleaseResources() - { - if (call != null) { - call.Dispose(); - } - gchandle.Free(); - disposed = true; - } - - private void CompleteStreamObserver(Status status) - { - if (status.StatusCode != StatusCode.OK) - { - // TODO: wrap to handle exceptions; - readObserver.OnError(new RpcException(status)); - } else { - // TODO: wrap to handle exceptions; - readObserver.OnCompleted(); - } } /// <summary> /// Handler for unary response completion. /// </summary> - private void HandleUnaryResponse(GRPCOpError error, IntPtr batchContextPtr) + private void HandleUnaryResponse(bool wasError, BatchContextSafeHandleNotOwned ctx) { - try + lock(myLock) { - TaskCompletionSource<TRead> tcs; - lock(myLock) - { - finished = true; - halfclosed = true; - tcs = unaryResponseTcs; - - ReleaseResourcesIfPossible(); - } - - var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr); + finished = true; + halfclosed = true; - if (error != GRPCOpError.GRPC_OP_OK) - { - tcs.SetException(new RpcException( - new Status(StatusCode.Internal, "Internal error occured.") - )); - return; - } - - var status = ctx.GetReceivedStatus(); - if (status.StatusCode != StatusCode.OK) - { - tcs.SetException(new RpcException(status)); - return; - } - - // TODO: handle deserialize error... - var msg = deserializer(ctx.GetReceivedMessage()); - tcs.SetResult(msg); - } - catch(Exception e) - { - Console.WriteLine("Caught exception in a native handler: " + e); + ReleaseResourcesIfPossible(); } - } - - private void HandleWriteFinished(GRPCOpError error, IntPtr batchContextPtr) - { - try - { - TaskCompletionSource<object> oldTcs = null; - lock (myLock) - { - oldTcs = writeTcs; - writeTcs = null; - } - - if (errorOccured) - { - // TODO: use the right type of exception... - oldTcs.SetException(new Exception("Write failed")); - } - else - { - // TODO: where does the continuation run? - oldTcs.SetResult(null); - } - } - catch(Exception e) + if (wasError) { - Console.WriteLine("Caught exception in a native handler: " + e); + unaryResponseTcs.SetException(new RpcException( + new Status(StatusCode.Internal, "Internal error occured.") + )); + return; } - } - - private void HandleHalfclosed(GRPCOpError error, IntPtr batchContextPtr) - { - try - { - lock (myLock) - { - halfclosed = true; - ReleaseResourcesIfPossible(); - } - - if (error != GRPCOpError.GRPC_OP_OK) - { - halfcloseTcs.SetException(new Exception("Halfclose failed")); - - } - else - { - halfcloseTcs.SetResult(null); - } - } - catch(Exception e) + var status = ctx.GetReceivedStatus(); + if (status.StatusCode != StatusCode.OK) { - Console.WriteLine("Caught exception in a native handler: " + e); + unaryResponseTcs.SetException(new RpcException(status)); + return; } - } - - private void HandleReadFinished(GRPCOpError error, IntPtr batchContextPtr) - { - try - { - var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr); - var payload = ctx.GetReceivedMessage(); - - TaskCompletionSource<TRead> oldTcs = null; - IObserver<TRead> observer = null; - - Nullable<Status> status = null; - - lock (myLock) - { - oldTcs = readTcs; - readTcs = null; - if (payload == null) - { - readingDone = true; - } - observer = readObserver; - status = finishedStatus; - - ReleaseResourcesIfPossible(); - } - - // TODO: wrap deserialization... - TRead msg = payload != null ? deserializer(payload) : default(TRead); - oldTcs.SetResult(msg); + // TODO: handle deserialization error + TResponse msg; + TryDeserialize(ctx.GetReceivedMessage(), out msg); - // TODO: make sure we deliver reads in the right order. - - if (observer != null) - { - if (payload != null) - { - // TODO: wrap to handle exceptions - observer.OnNext(msg); - - // start a new read - ReceiveMessageAsync(); - } - else - { - if (!server) - { - if (status.HasValue) - { - CompleteStreamObserver(status.Value); - } - } - else - { - // TODO: wrap to handle exceptions.. - observer.OnCompleted(); - } - // TODO: completeStreamObserver serverside... - } - } - } - catch(Exception e) - { - Console.WriteLine("Caught exception in a native handler: " + e); - } + unaryResponseTcs.SetResult(msg); } - private void HandleFinished(GRPCOpError error, IntPtr batchContextPtr) + /// <summary> + /// Handles receive status completion for calls with streaming response. + /// </summary> + private void HandleFinished(bool wasError, BatchContextSafeHandleNotOwned ctx) { - try - { - var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr); - var status = ctx.GetReceivedStatus(); - - bool wasReadingDone; - - lock (myLock) - { - finished = true; - finishedStatus = status; - - wasReadingDone = readingDone; - - ReleaseResourcesIfPossible(); - } - - if (wasReadingDone) { - CompleteStreamObserver(status); - } - - } - catch(Exception e) - { - Console.WriteLine("Caught exception in a native handler: " + e); - } - } + var status = ctx.GetReceivedStatus(); - private void HandleFinishedServerside(GRPCOpError error, IntPtr batchContextPtr) - { - try + lock (myLock) { - var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr); - - lock(myLock) - { - finished = true; - - // TODO: because of the way server calls are implemented, we need to set - // reading done to true here. Should be fixed in the future. - readingDone = true; - - ReleaseResourcesIfPossible(); - } - // TODO: handle error ... - - finishedServersideTcs.SetResult(null); + finished = true; + finishedStatus = status; + ReleaseResourcesIfPossible(); } - catch(Exception e) - { - Console.WriteLine("Caught exception in a native handler: " + e); - } + + CompleteReadObserver(); } } } \ No newline at end of file diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs new file mode 100644 index 0000000000000000000000000000000000000000..44d66b394ca6929bc1fea07c0bf85e0de5e0fcf7 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs @@ -0,0 +1,407 @@ +#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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// Base for handling both client side and server side calls. + /// Handles native call lifecycle and provides convenience methods. + /// </summary> + internal abstract class AsyncCallBase<TWrite, TRead> + { + readonly Func<TWrite, byte[]> serializer; + readonly Func<byte[], TRead> deserializer; + + protected readonly CompletionCallbackDelegate sendFinishedHandler; + protected readonly CompletionCallbackDelegate readFinishedHandler; + protected readonly CompletionCallbackDelegate halfclosedHandler; + + protected readonly object myLock = new object(); + + protected GCHandle gchandle; + protected CallSafeHandle call; + protected bool disposed; + + protected bool started; + protected bool errorOccured; + protected bool cancelRequested; + + protected AsyncCompletionDelegate sendCompletionDelegate; // Completion of a pending send or sendclose if not null. + protected bool readPending; // True if there is a read in progress. + protected bool readingDone; + protected bool halfcloseRequested; + protected bool halfclosed; + protected bool finished; // True if close has been received from the peer. + + // Streaming reads will be delivered to this observer. For a call that only does unary read it may remain null. + protected IObserver<TRead> readObserver; + + public AsyncCallBase(Func<TWrite, byte[]> serializer, Func<byte[], TRead> deserializer) + { + this.serializer = Preconditions.CheckNotNull(serializer); + this.deserializer = Preconditions.CheckNotNull(deserializer); + + this.sendFinishedHandler = CreateBatchCompletionCallback(HandleSendFinished); + this.readFinishedHandler = CreateBatchCompletionCallback(HandleReadFinished); + this.halfclosedHandler = CreateBatchCompletionCallback(HandleHalfclosed); + } + + /// <summary> + /// Requests cancelling the call. + /// </summary> + public void Cancel() + { + lock (myLock) + { + Preconditions.CheckState(started); + cancelRequested = true; + + if (!disposed) + { + call.Cancel(); + } + } + } + + /// <summary> + /// Requests cancelling the call with given status. + /// </summary> + public void CancelWithStatus(Status status) + { + lock (myLock) + { + Preconditions.CheckState(started); + cancelRequested = true; + + if (!disposed) + { + call.CancelWithStatus(status); + } + } + } + + protected void InitializeInternal(CallSafeHandle call) + { + lock (myLock) + { + // Make sure this object and the delegated held by it will not be garbage collected + // before we release this handle. + gchandle = GCHandle.Alloc(this); + this.call = call; + } + } + + /// <summary> + /// Initiates sending a message. Only once send operation can be active at a time. + /// completionDelegate is invoked upon completion. + /// </summary> + protected void StartSendMessageInternal(TWrite msg, AsyncCompletionDelegate completionDelegate) + { + byte[] payload = UnsafeSerialize(msg); + + lock (myLock) + { + Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null"); + CheckSendingAllowed(); + + call.StartSendMessage(payload, sendFinishedHandler); + sendCompletionDelegate = completionDelegate; + } + } + + /// <summary> + /// Requests receiving a next message. + /// </summary> + protected void StartReceiveMessage() + { + lock (myLock) + { + Preconditions.CheckState(started); + Preconditions.CheckState(!disposed); + Preconditions.CheckState(!errorOccured); + + Preconditions.CheckState(!readingDone); + Preconditions.CheckState(!readPending); + + call.StartReceiveMessage(readFinishedHandler); + readPending = true; + } + } + + /// <summary> + /// Default behavior just completes the read observer, but more sofisticated behavior might be required + /// by subclasses. + /// </summary> + protected virtual void CompleteReadObserver() + { + FireReadObserverOnCompleted(); + } + + /// <summary> + /// If there are no more pending actions and no new actions can be started, releases + /// the underlying native resources. + /// </summary> + protected bool ReleaseResourcesIfPossible() + { + if (!disposed && call != null) + { + if (halfclosed && readingDone && finished) + { + ReleaseResources(); + return true; + } + } + return false; + } + + private void ReleaseResources() + { + if (call != null) + { + call.Dispose(); + } + gchandle.Free(); + disposed = true; + } + + protected void CheckSendingAllowed() + { + Preconditions.CheckState(started); + Preconditions.CheckState(!disposed); + Preconditions.CheckState(!errorOccured); + + Preconditions.CheckState(!halfcloseRequested, "Already halfclosed."); + Preconditions.CheckState(sendCompletionDelegate == null, "Only one write can be pending at a time"); + } + + protected byte[] UnsafeSerialize(TWrite msg) + { + return serializer(msg); + } + + protected bool TrySerialize(TWrite msg, out byte[] payload) + { + try + { + payload = serializer(msg); + return true; + } + catch(Exception) + { + Console.WriteLine("Exception occured while trying to serialize message"); + payload = null; + return false; + } + } + + protected bool TryDeserialize(byte[] payload, out TRead msg) + { + try + { + msg = deserializer(payload); + return true; + } + catch(Exception) + { + Console.WriteLine("Exception occured while trying to deserialize message"); + msg = default(TRead); + return false; + } + } + + protected void FireReadObserverOnNext(TRead value) + { + try + { + readObserver.OnNext(value); + } + catch(Exception e) + { + Console.WriteLine("Exception occured while invoking readObserver.OnNext: " + e); + } + } + + protected void FireReadObserverOnCompleted() + { + try + { + readObserver.OnCompleted(); + } + catch(Exception e) + { + Console.WriteLine("Exception occured while invoking readObserver.OnCompleted: " + e); + } + } + + protected void FireReadObserverOnError(Exception error) + { + try + { + readObserver.OnError(error); + } + catch(Exception e) + { + Console.WriteLine("Exception occured while invoking readObserver.OnError: " + e); + } + } + + protected void FireCompletion(AsyncCompletionDelegate completionDelegate, Exception error) + { + try + { + completionDelegate(error); + } + catch(Exception e) + { + Console.WriteLine("Exception occured while invoking completion delegate: " + e); + } + } + + /// <summary> + /// Creates completion callback delegate that wraps the batch completion handler in a try catch block to + /// prevent propagating exceptions accross managed/unmanaged boundary. + /// </summary> + protected CompletionCallbackDelegate CreateBatchCompletionCallback(Action<bool, BatchContextSafeHandleNotOwned> handler) + { + return new CompletionCallbackDelegate( (error, batchContextPtr) => { + try + { + var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr); + bool wasError = (error != GRPCOpError.GRPC_OP_OK); + handler(wasError, ctx); + } + catch(Exception e) + { + Console.WriteLine("Caught exception in a native handler: " + e); + } + }); + } + + /// <summary> + /// Handles send completion. + /// </summary> + private void HandleSendFinished(bool wasError, BatchContextSafeHandleNotOwned ctx) + { + AsyncCompletionDelegate origCompletionDelegate = null; + lock (myLock) + { + origCompletionDelegate = sendCompletionDelegate; + sendCompletionDelegate = null; + + ReleaseResourcesIfPossible(); + } + + if (wasError) + { + FireCompletion(origCompletionDelegate, new OperationFailedException("Send failed")); + } + else + { + FireCompletion(origCompletionDelegate, null); + } + } + + /// <summary> + /// Handles halfclose completion. + /// </summary> + private void HandleHalfclosed(bool wasError, BatchContextSafeHandleNotOwned ctx) + { + AsyncCompletionDelegate origCompletionDelegate = null; + lock (myLock) + { + halfclosed = true; + origCompletionDelegate = sendCompletionDelegate; + sendCompletionDelegate = null; + + ReleaseResourcesIfPossible(); + } + + if (wasError) + { + FireCompletion(origCompletionDelegate, new OperationFailedException("Halfclose failed")); + } + else + { + FireCompletion(origCompletionDelegate, null); + } + + } + + /// <summary> + /// Handles streaming read completion. + /// </summary> + private void HandleReadFinished(bool wasError, BatchContextSafeHandleNotOwned ctx) + { + var payload = ctx.GetReceivedMessage(); + + lock (myLock) + { + readPending = false; + if (payload == null) + { + readingDone = true; + } + + ReleaseResourcesIfPossible(); + } + + // TODO: handle the case when error occured... + + if (payload != null) + { + // TODO: handle deserialization error + TRead msg; + TryDeserialize(payload, out msg); + + FireReadObserverOnNext(msg); + + // Start a new read. The current one has already been delivered, + // so correct ordering of reads is assured. + StartReceiveMessage(); + } + else + { + CompleteReadObserver(); + } + } + } +} \ No newline at end of file diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs new file mode 100644 index 0000000000000000000000000000000000000000..d3a2be553fc6ac21cc1f476c5d7f16d9692be0d3 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs @@ -0,0 +1,125 @@ +#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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// Handles server side native call lifecycle. + /// </summary> + internal class AsyncCallServer<TRequest, TResponse> : AsyncCallBase<TResponse, TRequest> + { + readonly CompletionCallbackDelegate finishedServersideHandler; + readonly TaskCompletionSource<object> finishedServersideTcs = new TaskCompletionSource<object>(); + + public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer) : base(serializer, deserializer) + { + this.finishedServersideHandler = CreateBatchCompletionCallback(HandleFinishedServerside); + } + + public void Initialize(CallSafeHandle call) + { + InitializeInternal(call); + } + + /// <summary> + /// Starts a server side call. Currently, all server side calls are implemented as duplex + /// streaming call and they are adapted to the appropriate streaming arity. + /// </summary> + public Task ServerSideCallAsync(IObserver<TRequest> readObserver) + { + lock (myLock) + { + Preconditions.CheckNotNull(call); + + started = true; + this.readObserver = readObserver; + + call.StartServerSide(finishedServersideHandler); + StartReceiveMessage(); + return finishedServersideTcs.Task; + } + } + + /// <summary> + /// Sends a streaming response. Only one pending send action is allowed at any given time. + /// completionDelegate is called when the operation finishes. + /// </summary> + public void StartSendMessage(TResponse msg, AsyncCompletionDelegate completionDelegate) + { + StartSendMessageInternal(msg, completionDelegate); + } + + /// <summary> + /// Sends call result status, also indicating server is done with streaming responses. + /// Only one pending send action is allowed at any given time. + /// completionDelegate is called when the operation finishes. + /// </summary> + public void StartSendStatusFromServer(Status status, AsyncCompletionDelegate completionDelegate) + { + lock (myLock) + { + Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null"); + CheckSendingAllowed(); + + call.StartSendStatusFromServer(status, halfclosedHandler); + halfcloseRequested = true; + sendCompletionDelegate = completionDelegate; + } + } + + /// <summary> + /// Handles the server side close completion. + /// </summary> + private void HandleFinishedServerside(bool wasError, BatchContextSafeHandleNotOwned ctx) + { + lock (myLock) + { + finished = true; + + ReleaseResourcesIfPossible(); + } + // TODO: handle error ... + + finishedServersideTcs.SetResult(null); + } + } +} \ No newline at end of file diff --git a/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs b/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs new file mode 100644 index 0000000000000000000000000000000000000000..b78bb497fa71efdc0a01340f50bc990a8c454ecd --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs @@ -0,0 +1,95 @@ +#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.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// If error != null, there's been an error or operation has been cancelled. + /// </summary> + internal delegate void AsyncCompletionDelegate(Exception error); + + /// <summary> + /// Helper for transforming AsyncCompletionDelegate into full-fledged Task. + /// </summary> + internal class AsyncCompletionTaskSource + { + readonly TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(); + readonly AsyncCompletionDelegate completionDelegate; + + public AsyncCompletionTaskSource() + { + completionDelegate = new AsyncCompletionDelegate(HandleCompletion); + } + + public Task Task + { + get + { + return tcs.Task; + } + } + + public AsyncCompletionDelegate CompletionDelegate + { + get + { + return completionDelegate; + } + } + + private void HandleCompletion(Exception error) + { + if (error == null) + { + tcs.SetResult(null); + return; + } + if (error is OperationCanceledException) + { + tcs.SetCanceled(); + return; + } + tcs.SetException(error); + } + } + +} \ No newline at end of file diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index 1c0bc98f062db57fd27bca50e8ade5d966e32047..61566b54072bbb8ab11f9bde2240d4b3760bd0a9 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -30,7 +29,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endregion - using System; using System.Diagnostics; using System.Runtime.InteropServices; @@ -38,14 +36,12 @@ using Grpc.Core; namespace Grpc.Core.Internal { - //TODO: rename the delegate - internal delegate void CompletionCallbackDelegate(GRPCOpError error, IntPtr batchContextPtr); - + internal delegate void CompletionCallbackDelegate(GRPCOpError error,IntPtr batchContextPtr); /// <summary> /// grpc_call from <grpc/grpc.h> /// </summary> - internal class CallSafeHandle : SafeHandleZeroIsInvalid - { + internal class CallSafeHandle : SafeHandleZeroIsInvalid + { const UInt32 GRPC_WRITE_BUFFER_HINT = 1; [DllImport("grpc_csharp_ext.dll")] @@ -59,22 +55,22 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_unary(CallSafeHandle call, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, - byte[] send_buffer, UIntPtr send_buffer_len); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, + byte[] send_buffer, UIntPtr send_buffer_len); [DllImport("grpc_csharp_ext.dll")] static extern void grpcsharp_call_blocking_unary(CallSafeHandle call, CompletionQueueSafeHandle dedicatedCq, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, - byte[] send_buffer, UIntPtr send_buffer_len); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, + byte[] send_buffer, UIntPtr send_buffer_len); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_server_streaming(CallSafeHandle call, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, - byte[] send_buffer, UIntPtr send_buffer_len); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, + byte[] send_buffer, UIntPtr send_buffer_len); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, @@ -82,28 +78,27 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_send_message(CallSafeHandle call, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, - byte[] send_buffer, UIntPtr send_buffer_len); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, + byte[] send_buffer, UIntPtr send_buffer_len); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_send_close_from_client(CallSafeHandle call, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_send_status_from_server(CallSafeHandle call, [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, StatusCode statusCode, string statusMessage); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_recv_message(CallSafeHandle call, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_serverside(CallSafeHandle call, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); [DllImport("grpc_csharp_ext.dll")] static extern void grpcsharp_call_destroy(IntPtr call); - private CallSafeHandle() { } @@ -115,12 +110,12 @@ namespace Grpc.Core.Internal public void StartUnary(byte[] payload, CompletionCallbackDelegate callback) { - AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong) payload.Length))); + AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong)payload.Length))); } public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback) { - grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong) payload.Length)); + grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong)payload.Length)); } public void StartClientStreaming(CompletionCallbackDelegate callback) @@ -130,7 +125,7 @@ namespace Grpc.Core.Internal public void StartServerStreaming(byte[] payload, CompletionCallbackDelegate callback) { - AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong) payload.Length))); + AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong)payload.Length))); } public void StartDuplexStreaming(CompletionCallbackDelegate callback) @@ -140,7 +135,7 @@ namespace Grpc.Core.Internal public void StartSendMessage(byte[] payload, CompletionCallbackDelegate callback) { - AssertCallOk(grpcsharp_call_send_message(this, callback, payload, new UIntPtr((ulong) payload.Length))); + AssertCallOk(grpcsharp_call_send_message(this, callback, payload, new UIntPtr((ulong)payload.Length))); } public void StartSendCloseFromClient(CompletionCallbackDelegate callback) @@ -173,19 +168,20 @@ namespace Grpc.Core.Internal AssertCallOk(grpcsharp_call_cancel_with_status(this, status.StatusCode, status.Detail)); } - protected override bool ReleaseHandle() - { + protected override bool ReleaseHandle() + { grpcsharp_call_destroy(handle); - return true; - } + return true; + } private static void AssertCallOk(GRPCCallError callError) { Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK"); } - private static UInt32 GetFlags(bool buffered) { + private static UInt32 GetFlags(bool buffered) + { return buffered ? 0 : GRPC_WRITE_BUFFER_HINT; } - } + } } \ No newline at end of file diff --git a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs new file mode 100644 index 0000000000000000000000000000000000000000..ca3c21d84ce83261ca76f8cc941d5d5c05730e71 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs @@ -0,0 +1,77 @@ +#region Copyright notice and license +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// grpc_channel_args from <grpc/grpc.h> + /// </summary> + internal class ChannelArgsSafeHandle : SafeHandleZeroIsInvalid + { + [DllImport("grpc_csharp_ext.dll")] + static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport("grpc_csharp_ext.dll")] + static extern void grpcsharp_channel_args_destroy(IntPtr args); + + private ChannelArgsSafeHandle() + { + } + + public static ChannelArgsSafeHandle CreateNull() + { + return new ChannelArgsSafeHandle(); + } + + public static ChannelArgsSafeHandle Create(int size) + { + return grpcsharp_channel_args_create(new UIntPtr((uint)size)); + } + + public void SetString(int index, string key, string value) + { + grpcsharp_channel_args_set_string(this, new UIntPtr((uint)index), key, value); + } + + protected override bool ReleaseHandle() + { + grpcsharp_channel_args_destroy(handle); + return true; + } + } +} + diff --git a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs index f15ead35724d94ee4bc6b11b71543d7afa46bf5a..f046f4c6d0d4b0ee32b869ee2d09aea6d1c32aeb 100644 --- a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -28,9 +27,7 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - #endregion - using System; using System.Runtime.InteropServices; using System.Threading; @@ -41,27 +38,35 @@ namespace Grpc.Core.Internal /// <summary> /// grpc_channel from <grpc/grpc.h> /// </summary> - internal class ChannelSafeHandle : SafeHandleZeroIsInvalid - { + internal class ChannelSafeHandle : SafeHandleZeroIsInvalid + { [DllImport("grpc_csharp_ext.dll")] - static extern ChannelSafeHandle grpcsharp_channel_create(string target, IntPtr channelArgs); + static extern ChannelSafeHandle grpcsharp_channel_create(string target, ChannelArgsSafeHandle channelArgs); - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_channel_destroy(IntPtr channel); + [DllImport("grpc_csharp_ext.dll")] + static extern ChannelSafeHandle grpcsharp_secure_channel_create(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport("grpc_csharp_ext.dll")] + static extern void grpcsharp_channel_destroy(IntPtr channel); private ChannelSafeHandle() { } - public static ChannelSafeHandle Create(string target, IntPtr channelArgs) + public static ChannelSafeHandle Create(string target, ChannelArgsSafeHandle channelArgs) { return grpcsharp_channel_create(target, channelArgs); } - protected override bool ReleaseHandle() - { - grpcsharp_channel_destroy(handle); - return true; - } - } + public static ChannelSafeHandle CreateSecure(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs) + { + return grpcsharp_secure_channel_create(credentials, target, channelArgs); + } + + protected override bool ReleaseHandle() + { + grpcsharp_channel_destroy(handle); + return true; + } + } } diff --git a/src/csharp/Grpc.Core/Internal/ClientStreamingInputObserver.cs b/src/csharp/Grpc.Core/Internal/ClientStreamingInputObserver.cs index fb59e86e2d7f8e0d017abc4b26910ac8cc2fcb65..286c54f2c47811f458d4b1543b06007e7b836378 100644 --- a/src/csharp/Grpc.Core/Internal/ClientStreamingInputObserver.cs +++ b/src/csharp/Grpc.Core/Internal/ClientStreamingInputObserver.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -28,40 +27,40 @@ // 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 Grpc.Core.Internal; namespace Grpc.Core.Internal { internal class ClientStreamingInputObserver<TWrite, TRead> : IObserver<TWrite> - { + { readonly AsyncCall<TWrite, TRead> call; public ClientStreamingInputObserver(AsyncCall<TWrite, TRead> call) - { + { this.call = call; - } - - public void OnCompleted() - { + } + public void OnCompleted() + { + var taskSource = new AsyncCompletionTaskSource(); + call.StartSendCloseFromClient(taskSource.CompletionDelegate); // TODO: how bad is the Wait here? - call.SendCloseFromClientAsync().Wait(); - } + taskSource.Task.Wait(); + } - public void OnError(Exception error) - { - throw new InvalidOperationException("This should never be called."); - } + public void OnError(Exception error) + { + throw new InvalidOperationException("This should never be called."); + } - public void OnNext(TWrite value) - { + public void OnNext(TWrite value) + { + var taskSource = new AsyncCompletionTaskSource(); + call.StartSendMessage(value, taskSource.CompletionDelegate); // TODO: how bad is the Wait here? - call.SendMessageAsync(value).Wait(); - } - } + taskSource.Task.Wait(); + } + } } - diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs index 3f01fdbfd05c70d4ac130681d6af1ab91a6530c7..6bff923c55229166189b497d666b797436dc5d3b 100644 --- a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -28,9 +27,7 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - #endregion - using System; using System.Runtime.InteropServices; using System.Threading.Tasks; @@ -40,8 +37,8 @@ namespace Grpc.Core.Internal /// <summary> /// grpc_completion_queue from <grpc/grpc.h> /// </summary> - internal class CompletionQueueSafeHandle : SafeHandleZeroIsInvalid - { + internal class CompletionQueueSafeHandle : SafeHandleZeroIsInvalid + { [DllImport("grpc_csharp_ext.dll")] static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create(); @@ -73,11 +70,11 @@ namespace Grpc.Core.Internal grpcsharp_completion_queue_shutdown(this); } - protected override bool ReleaseHandle() + protected override bool ReleaseHandle() { grpcsharp_completion_queue_destroy(handle); - return true; - } - } + return true; + } + } } diff --git a/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs new file mode 100644 index 0000000000000000000000000000000000000000..f361199068eb5da2bb917f732b13bd94ba4a18c0 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs @@ -0,0 +1,64 @@ +#region Copyright notice and license +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// grpc_credentials from <grpc/grpc_security.h> + /// </summary> + internal class CredentialsSafeHandle : SafeHandleZeroIsInvalid + { + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + static extern CredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + + [DllImport("grpc_csharp_ext.dll")] + static extern void grpcsharp_credentials_release(IntPtr credentials); + + private CredentialsSafeHandle() + { + } + + public static CredentialsSafeHandle CreateSslCredentials(string pemRootCerts) + { + return grpcsharp_ssl_credentials_create(pemRootCerts, null, null); + } + + protected override bool ReleaseHandle() + { + grpcsharp_credentials_release(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs b/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs index 08d99214754bd9316a75f5a252fc0861694bbe7a..9873dc9c71077b0d8650199e288e743f8f348896 100644 --- a/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs +++ b/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -28,9 +27,7 @@ // 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 Grpc.Core.Internal; @@ -40,32 +37,36 @@ namespace Grpc.Core.Internal /// Observer that writes all arriving messages to a call abstraction (in blocking fashion) /// and then halfcloses the call. Used for server-side call handling. /// </summary> - internal class ServerStreamingOutputObserver<TWrite, TRead> : IObserver<TWrite> - { - readonly AsyncCall<TWrite, TRead> call; + internal class ServerStreamingOutputObserver<TRequest, TResponse> : IObserver<TResponse> + { + readonly AsyncCallServer<TRequest, TResponse> call; - public ServerStreamingOutputObserver(AsyncCall<TWrite, TRead> call) - { + public ServerStreamingOutputObserver(AsyncCallServer<TRequest, TResponse> call) + { this.call = call; - } + } - public void OnCompleted() - { + public void OnCompleted() + { + var taskSource = new AsyncCompletionTaskSource(); + call.StartSendStatusFromServer(new Status(StatusCode.OK, ""), taskSource.CompletionDelegate); // TODO: how bad is the Wait here? - call.SendStatusFromServerAsync(new Status(StatusCode.OK, "")).Wait(); - } + taskSource.Task.Wait(); + } - public void OnError(Exception error) - { + public void OnError(Exception error) + { // TODO: implement this... - throw new InvalidOperationException("This should never be called."); - } + throw new InvalidOperationException("This should never be called."); + } - public void OnNext(TWrite value) - { + public void OnNext(TResponse value) + { + var taskSource = new AsyncCompletionTaskSource(); + call.StartSendMessage(value, taskSource.CompletionDelegate); // TODO: how bad is the Wait here? - call.SendMessageAsync(value).Wait(); - } - } + taskSource.Task.Wait(); + } + } } diff --git a/src/csharp/Grpc.Core/Internal/Timespec.cs b/src/csharp/Grpc.Core/Internal/Timespec.cs index b191ecde94cc6e3e96cf966de8fe6813ab5b2628..e6efd66f13b9eb717d573f4469927d56c749d9f7 100644 --- a/src/csharp/Grpc.Core/Internal/Timespec.cs +++ b/src/csharp/Grpc.Core/Internal/Timespec.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -28,21 +27,19 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - #endregion - using System; using System.Runtime.InteropServices; using System.Threading; namespace Grpc.Core.Internal { - /// <summary> - /// gpr_timespec from grpc/support/time.h - /// </summary> - [StructLayout(LayoutKind.Sequential)] - internal struct Timespec - { + /// <summary> + /// gpr_timespec from grpc/support/time.h + /// </summary> + [StructLayout(LayoutKind.Sequential)] + internal struct Timespec + { const int nanosPerSecond = 1000 * 1000 * 1000; const int nanosPerTick = 100; @@ -54,23 +51,22 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] static extern int gprsharp_sizeof_timespec(); - // TODO: revisit this. - // NOTE: on linux 64bit sizeof(gpr_timespec) = 16, on windows 32bit sizeof(gpr_timespec) = 8 + // NOTE: on linux 64bit sizeof(gpr_timespec) = 16, on windows 32bit sizeof(gpr_timespec) = 8 // so IntPtr seems to have the right size to work on both. - public System.IntPtr tv_sec; - public System.IntPtr tv_nsec; + public System.IntPtr tv_sec; + public System.IntPtr tv_nsec; - /// <summary> - /// Timespec a long time in the future. - /// </summary> - public static Timespec InfFuture - { - get - { + /// <summary> + /// Timespec a long time in the future. + /// </summary> + public static Timespec InfFuture + { + get + { return gprsharp_inf_future(); - } - } + } + } public static Timespec Now { @@ -92,7 +88,8 @@ namespace Grpc.Core.Internal /// Creates a GPR deadline from current instant and given timeout. /// </summary> /// <returns>The from timeout.</returns> - public static Timespec DeadlineFromTimeout(TimeSpan timeout) { + public static Timespec DeadlineFromTimeout(TimeSpan timeout) + { if (timeout == Timeout.InfiniteTimeSpan) { return Timespec.InfFuture; @@ -100,7 +97,8 @@ namespace Grpc.Core.Internal return Timespec.Now.Add(timeout); } - public Timespec Add(TimeSpan timeSpan) { + public Timespec Add(TimeSpan timeSpan) + { long nanos = tv_nsec.ToInt64() + (timeSpan.Ticks % TimeSpan.TicksPerSecond) * nanosPerTick; long overflow_sec = (nanos > nanosPerSecond) ? 1 : 0; @@ -109,6 +107,6 @@ namespace Grpc.Core.Internal result.tv_sec = new IntPtr(tv_sec.ToInt64() + (timeSpan.Ticks / TimeSpan.TicksPerSecond) + overflow_sec); return result; } - } + } } diff --git a/src/csharp/Grpc.Core/OperationFailedException.cs b/src/csharp/Grpc.Core/OperationFailedException.cs new file mode 100644 index 0000000000000000000000000000000000000000..34a8c95a85c3790f49582bdcd0e1d627e837a4c7 --- /dev/null +++ b/src/csharp/Grpc.Core/OperationFailedException.cs @@ -0,0 +1,48 @@ +#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 +{ + /// <summary> + /// Thrown when gRPC operation fails. + /// </summary> + public class OperationFailedException : Exception + { + public OperationFailedException(string message) : base(message) + { + } + } +} + diff --git a/src/csharp/Grpc.Core/ServerCallHandler.cs b/src/csharp/Grpc.Core/ServerCallHandler.cs index 289f97aecee2777f6a7718bed807d1cacb3278c4..3eb8422f575e3b4f745e03f13856c254d76de10b 100644 --- a/src/csharp/Grpc.Core/ServerCallHandler.cs +++ b/src/csharp/Grpc.Core/ServerCallHandler.cs @@ -32,7 +32,9 @@ #endregion using System; +using System.Linq; using Grpc.Core.Internal; +using Grpc.Core.Utils; namespace Grpc.Core { @@ -54,17 +56,17 @@ namespace Grpc.Core public void StartCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq) { - var asyncCall = new AsyncCall<TResponse, TRequest>( + var asyncCall = new AsyncCallServer<TRequest, TResponse>( method.ResponseMarshaller.Serializer, method.RequestMarshaller.Deserializer); - asyncCall.InitializeServer(call); + asyncCall.Initialize(call); - var finishedTask = asyncCall.ServerSideUnaryRequestCallAsync(); + var requestObserver = new RecordingObserver<TRequest>(); + var finishedTask = asyncCall.ServerSideCallAsync(requestObserver); - var request = asyncCall.ReceiveMessageAsync().Result; - - var responseObserver = new ServerStreamingOutputObserver<TResponse, TRequest>(asyncCall); + var request = requestObserver.ToList().Result.Single(); + var responseObserver = new ServerStreamingOutputObserver<TRequest, TResponse>(asyncCall); handler(request, responseObserver); finishedTask.Wait(); @@ -85,15 +87,15 @@ namespace Grpc.Core public void StartCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq) { - var asyncCall = new AsyncCall<TResponse, TRequest>( + var asyncCall = new AsyncCallServer<TRequest, TResponse>( method.ResponseMarshaller.Serializer, method.RequestMarshaller.Deserializer); - asyncCall.InitializeServer(call); + asyncCall.Initialize(call); - var responseObserver = new ServerStreamingOutputObserver<TResponse, TRequest>(asyncCall); + var responseObserver = new ServerStreamingOutputObserver<TRequest,TResponse>(asyncCall); var requestObserver = handler(responseObserver); - var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(requestObserver); + var finishedTask = asyncCall.ServerSideCallAsync(requestObserver); finishedTask.Wait(); } } @@ -103,17 +105,15 @@ namespace Grpc.Core public void StartCall(string methodName, CallSafeHandle call, CompletionQueueSafeHandle cq) { // We don't care about the payload type here. - AsyncCall<byte[], byte[]> asyncCall = new AsyncCall<byte[], byte[]>( + var asyncCall = new AsyncCallServer<byte[], byte[]>( (payload) => payload, (payload) => payload); + asyncCall.Initialize(call); - asyncCall.InitializeServer(call); - - var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(new NullObserver<byte[]>()); + var finishedTask = asyncCall.ServerSideCallAsync(new NullObserver<byte[]>()); - // TODO: this makes the call finish before all reads can be done which causes trouble - // in AsyncCall.HandleReadFinished callback. Revisit this. - asyncCall.SendStatusFromServerAsync(new Status(StatusCode.Unimplemented, "No such method.")).Wait(); + // TODO: check result of the completion status. + asyncCall.StartSendStatusFromServer(new Status(StatusCode.Unimplemented, "No such method."), new AsyncCompletionDelegate((error) => {})); finishedTask.Wait(); } diff --git a/src/csharp/Grpc.Core/Status.cs b/src/csharp/Grpc.Core/Status.cs index 5ea1df7b481c2bec149fb0550f04b152a427b336..080bbdc2f5b3544b5917126837490732ae1a3f9f 100644 --- a/src/csharp/Grpc.Core/Status.cs +++ b/src/csharp/Grpc.Core/Status.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -28,7 +27,6 @@ // 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; @@ -36,34 +34,40 @@ using System.Runtime.InteropServices; namespace Grpc.Core { - /// <summary> - /// Represents RPC result. - /// </summary> - public struct Status - { - readonly StatusCode statusCode; - readonly string detail; + /// <summary> + /// Represents RPC result. + /// </summary> + public struct Status + { + readonly StatusCode statusCode; + readonly string detail; - public Status(StatusCode statusCode, string detail) - { - this.statusCode = statusCode; - this.detail = detail; - } + public Status(StatusCode statusCode, string detail) + { + this.statusCode = statusCode; + this.detail = detail; + } - public StatusCode StatusCode - { - get - { - return statusCode; - } - } + /// <summary> + /// Gets the gRPC status code. OK indicates success, all other values indicate an error. + /// </summary> + public StatusCode StatusCode + { + get + { + return statusCode; + } + } - public string Detail - { - get - { - return detail; - } - } - } + /// <summary> + /// Gets the detail. + /// </summary> + public string Detail + { + get + { + return detail; + } + } + } } diff --git a/src/csharp/Grpc.Core/Utils/Preconditions.cs b/src/csharp/Grpc.Core/Utils/Preconditions.cs new file mode 100644 index 0000000000000000000000000000000000000000..b17ce4211783701b6b4ab8d6e9fb84057fe0fc75 --- /dev/null +++ b/src/csharp/Grpc.Core/Utils/Preconditions.cs @@ -0,0 +1,113 @@ +#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.Threading.Tasks; +using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Diagnostics; + +namespace Grpc.Core.Utils +{ + public static class Preconditions + { + /// <summary> + /// Throws ArgumentException if condition is false. + /// </summary> + public static void CheckArgument(bool condition) + { + if (!condition) + { + throw new ArgumentException(); + } + } + + /// <summary> + /// Throws ArgumentException with given message if condition is false. + /// </summary> + public static void CheckArgument(bool condition, string errorMessage) + { + if (!condition) + { + throw new ArgumentException(errorMessage); + } + } + + /// <summary> + /// Throws NullReferenceException if reference is null. + /// </summary> + public static T CheckNotNull<T> (T reference) + { + if (reference == null) + { + throw new NullReferenceException(); + } + return reference; + } + + /// <summary> + /// Throws NullReferenceException with given message if reference is null. + /// </summary> + public static T CheckNotNull<T> (T reference, string errorMessage) + { + if (reference == null) + { + throw new NullReferenceException(errorMessage); + } + return reference; + } + + /// <summary> + /// Throws InvalidOperationException if condition is false. + /// </summary> + public static void CheckState(bool condition) + { + if (!condition) + { + throw new InvalidOperationException(); + } + } + + /// <summary> + /// Throws InvalidOperationException with given message if condition is false. + /// </summary> + public static void CheckState(bool condition, string errorMessage) + { + if (!condition) + { + throw new InvalidOperationException(errorMessage); + } + } + } +} + diff --git a/src/csharp/Grpc.Examples.MathClient/MathClient.cs b/src/csharp/Grpc.Examples.MathClient/MathClient.cs index 95a4678bb8f63e623bd0c3a3c78688922fe7e07a..f5956bd33e008cdafe2e0116d76640645e793570 100644 --- a/src/csharp/Grpc.Examples.MathClient/MathClient.cs +++ b/src/csharp/Grpc.Examples.MathClient/MathClient.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -28,9 +27,7 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - #endregion - using System; using System.Runtime.InteropServices; using System.Threading; @@ -38,25 +35,25 @@ using Grpc.Core; namespace math { - class MathClient + class MathClient { - public static void Main (string[] args) - { + public static void Main(string[] args) + { GrpcEnvironment.Initialize(); - using (Channel channel = new Channel("127.0.0.1:23456")) - { - MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel); - MathExamples.DivExample(stub); + using (Channel channel = new Channel("127.0.0.1:23456")) + { + MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel); + MathExamples.DivExample(stub); MathExamples.FibExample(stub); - MathExamples.SumExample(stub); + MathExamples.SumExample(stub); - MathExamples.DivManyExample(stub); - } + MathExamples.DivManyExample(stub); + } GrpcEnvironment.Shutdown(); - } - } + } + } } diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs index 97c91b1b1b586248b03e4d94200e7a9629627fef..134270f6f76c8e20c367d132c9e5bffe009df3db 100644 --- a/src/csharp/Grpc.Examples/MathExamples.cs +++ b/src/csharp/Grpc.Examples/MathExamples.cs @@ -1,5 +1,4 @@ #region Copyright notice and license - // Copyright 2015, Google Inc. // All rights reserved. // @@ -28,7 +27,6 @@ // 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; @@ -39,59 +37,63 @@ using Grpc.Core.Utils; namespace math { - public static class MathExamples - { - public static void DivExample(MathGrpc.IMathServiceClient stub) - { - DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build()); - Console.WriteLine("Div Result: " + result); - } - - public static void DivAsyncExample(MathGrpc.IMathServiceClient stub) - { - Task<DivReply> call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build()); - DivReply result = call.Result; - Console.WriteLine(result); - } - - public static void DivAsyncWithCancellationExample(MathGrpc.IMathServiceClient stub) - { - Task<DivReply> call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build()); - DivReply result = call.Result; - Console.WriteLine(result); - } - - public static void FibExample(MathGrpc.IMathServiceClient stub) - { + public static class MathExamples + { + public static void DivExample(MathGrpc.IMathServiceClient stub) + { + DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build()); + Console.WriteLine("Div Result: " + result); + } + + public static void DivAsyncExample(MathGrpc.IMathServiceClient stub) + { + Task<DivReply> call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build()); + DivReply result = call.Result; + Console.WriteLine(result); + } + + public static void DivAsyncWithCancellationExample(MathGrpc.IMathServiceClient stub) + { + Task<DivReply> call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build()); + DivReply result = call.Result; + Console.WriteLine(result); + } + + public static void FibExample(MathGrpc.IMathServiceClient stub) + { var recorder = new RecordingObserver<Num>(); stub.Fib(new FibArgs.Builder { Limit = 5 }.Build(), recorder); - List<Num> numbers = recorder.ToList().Result; + List<Num> numbers = recorder.ToList().Result; Console.WriteLine("Fib Result: " + string.Join("|", recorder.ToList().Result)); - } + } - public static void SumExample(MathGrpc.IMathServiceClient stub) - { - List<Num> numbers = new List<Num>{new Num.Builder { Num_ = 1 }.Build(), - new Num.Builder { Num_ = 2 }.Build(), - new Num.Builder { Num_ = 3 }.Build()}; + public static void SumExample(MathGrpc.IMathServiceClient stub) + { + List<Num> numbers = new List<Num> + {new Num.Builder { Num_ = 1 }.Build(), + new Num.Builder { Num_ = 2 }.Build(), + new Num.Builder { Num_ = 3 }.Build() + }; var res = stub.Sum(); - foreach (var num in numbers) { + foreach (var num in numbers) + { res.Inputs.OnNext(num); } res.Inputs.OnCompleted(); - Console.WriteLine("Sum Result: " + res.Task.Result); - } + Console.WriteLine("Sum Result: " + res.Task.Result); + } - public static void DivManyExample(MathGrpc.IMathServiceClient stub) - { - List<DivArgs> divArgsList = new List<DivArgs>{ - new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(), - new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(), - new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build() - }; + public static void DivManyExample(MathGrpc.IMathServiceClient stub) + { + List<DivArgs> divArgsList = new List<DivArgs> + { + new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(), + new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(), + new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build() + }; var recorder = new RecordingObserver<DivReply>(); @@ -102,30 +104,30 @@ namespace math } inputs.OnCompleted(); - Console.WriteLine("DivMany Result: " + string.Join("|", recorder.ToList().Result)); - } + Console.WriteLine("DivMany Result: " + string.Join("|", recorder.ToList().Result)); + } - public static void DependendRequestsExample(MathGrpc.IMathServiceClient stub) - { - var numberList = new List<Num> - { new Num.Builder{ Num_ = 1 }.Build(), - new Num.Builder{ Num_ = 2 }.Build(), new Num.Builder{ Num_ = 3 }.Build() - }; + public static void DependendRequestsExample(MathGrpc.IMathServiceClient stub) + { + var numberList = new List<Num> + { new Num.Builder{ Num_ = 1 }.Build(), + new Num.Builder{ Num_ = 2 }.Build(), new Num.Builder{ Num_ = 3 }.Build() + }; - numberList.ToObservable(); + numberList.ToObservable(); - //IObserver<Num> numbers; - //Task<Num> call = stub.Sum(out numbers); - //foreach (var num in numberList) - //{ - // numbers.OnNext(num); - //} - //numbers.OnCompleted(); + //IObserver<Num> numbers; + //Task<Num> call = stub.Sum(out numbers); + //foreach (var num in numberList) + //{ + // numbers.OnNext(num); + //} + //numbers.OnCompleted(); - //Num sum = call.Result; + //Num sum = call.Result; - //DivReply result = stub.Div(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numberList.Count }.Build()); - } - } + //DivReply result = stub.Div(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numberList.Count }.Build()); + } + } } diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 6d6aaf57473b547f5beb72fdb95bd795ed619b7a..8f7a17efcb187be00ac1163e0185dc46b6b7066f 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -62,8 +62,21 @@ <None Include="proto\test.proto" /> <None Include="proto\empty.proto" /> <None Include="proto\messages.proto" /> + <None Include="data\README"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="data\ca.pem"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="data\server1.key"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="data\server1.pem"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> </ItemGroup> <ItemGroup> <Folder Include="proto\" /> + <Folder Include="data\" /> </ItemGroup> </Project> diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index a7a3c63e03296a3890a3f49c5994c1932879e2a1..30301f165baddff97bafac6a351798453b770e84 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -34,6 +34,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; using Google.ProtocolBuffers; @@ -49,10 +50,10 @@ namespace Grpc.IntegrationTesting private class ClientOptions { public bool help; - public string serverHost; - public string serverHostOverride; + public string serverHost= "127.0.0.1"; + public string serverHostOverride = "foo.test.google.fr"; public int? serverPort; - public string testCase; + public string testCase = "large_unary"; public bool useTls; public bool useTestCa; } @@ -98,10 +99,32 @@ namespace Grpc.IntegrationTesting GrpcEnvironment.Initialize(); string addr = string.Format("{0}:{1}", options.serverHost, options.serverPort); - using (Channel channel = new Channel(addr)) + + Credentials credentials = null; + if (options.useTls) { - TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel); + string caPath = "data/ca.pem"; // Default testing CA + if (!options.useTestCa) + { + caPath = Environment.GetEnvironmentVariable("SSL_CERT_FILE"); + if (string.IsNullOrEmpty(caPath)) + { + throw new ArgumentException("CA path environment variable is not set."); + } + } + credentials = new SslCredentials(File.ReadAllText(caPath)); + } + ChannelArgs channelArgs = null; + if (!string.IsNullOrEmpty(options.serverHostOverride)) + { + channelArgs = ChannelArgs.NewBuilder() + .AddString(ChannelArgs.SslTargetNameOverrideKey, options.serverHostOverride).Build(); + } + + using (Channel channel = new Channel(addr, credentials, channelArgs)) + { + TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel); RunTestCase(options.testCase, client); } diff --git a/src/csharp/Grpc.IntegrationTesting/data/README b/src/csharp/Grpc.IntegrationTesting/data/README new file mode 100644 index 0000000000000000000000000000000000000000..888d95b9004f9d2aa72ac62d86233fa2e0a8ba8f --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/data/README @@ -0,0 +1 @@ +CONFIRMEDTESTKEY diff --git a/src/csharp/Grpc.IntegrationTesting/data/ca.pem b/src/csharp/Grpc.IntegrationTesting/data/ca.pem new file mode 100644 index 0000000000000000000000000000000000000000..6c8511a73c68ac6afa6f0cb0b25c05ca8318e2a8 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/data/ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla +Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT +BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 ++L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu +g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd +Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau +sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m +oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG +Dfcog5wrJytaQ6UA0wE= +-----END CERTIFICATE----- diff --git a/src/csharp/Grpc.IntegrationTesting/data/server1.key b/src/csharp/Grpc.IntegrationTesting/data/server1.key new file mode 100644 index 0000000000000000000000000000000000000000..143a5b87658d5c3519de970f37efd1c32a98223d --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/data/server1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD +M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf +3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY +AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm +V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY +tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p +dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q +K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR +81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff +DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd +aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 +ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 +XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe +F98XJ7tIFfJq +-----END PRIVATE KEY----- diff --git a/src/csharp/Grpc.IntegrationTesting/data/server1.pem b/src/csharp/Grpc.IntegrationTesting/data/server1.pem new file mode 100644 index 0000000000000000000000000000000000000000..8e582e571f643ca3fb6042a786c709a53f5afcf3 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/data/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5 +MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl +c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs +JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO +RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30 +3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL +BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6 +b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ +KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS +wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e +aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s= +-----END CERTIFICATE----- diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 8f5a414187273b34250d1a8ad423e2efda6bee3d..e24438704cfb0fc5085318e323ee622027bbbfbd 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -39,6 +39,7 @@ #include <grpc/support/slice.h> #include <grpc/support/thd.h> #include <grpc/grpc.h> +#include <grpc/grpc_security.h> #include <string.h> @@ -266,6 +267,45 @@ grpcsharp_channel_create_call(grpc_channel *channel, grpc_completion_queue *cq, return grpc_channel_create_call(channel, cq, method, host, deadline); } +/* Channel args */ + +GPR_EXPORT grpc_channel_args *GPR_CALLTYPE +grpcsharp_channel_args_create(size_t num_args) { + grpc_channel_args *args = + (grpc_channel_args *)gpr_malloc(sizeof(grpc_channel_args)); + memset(args, 0, sizeof(grpc_channel_args)); + + args->num_args = num_args; + args->args = (grpc_arg *)gpr_malloc(sizeof(grpc_arg) * num_args); + memset(args->args, 0, sizeof(grpc_arg) * num_args); + return args; +} + +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_channel_args_set_string(grpc_channel_args *args, size_t index, + const char *key, const char *value) { + GPR_ASSERT(args); + GPR_ASSERT(index < args->num_args); + args->args[index].type = GRPC_ARG_STRING; + args->args[index].key = gpr_strdup(key); + args->args[index].value.string = gpr_strdup(value); +} + +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_channel_args_destroy(grpc_channel_args *args) { + size_t i; + if (args) { + for (i = 0; i < args->num_args; i++) { + gpr_free(args->args[i].key); + if (args->args[i].type == GRPC_ARG_STRING) { + gpr_free(args->args[i].value.string); + } + } + gpr_free(args->args); + gpr_free(args); + } +} + /* Timespec */ GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(void) { return gpr_now(); } @@ -585,6 +625,34 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq, &(ctx->server_rpc_new.request_metadata), cq, ctx); } +/* Security */ + +GPR_EXPORT grpc_credentials *GPR_CALLTYPE +grpcsharp_ssl_credentials_create(const char *pem_root_certs, + const char *key_cert_pair_cert_chain, + const char *key_cert_pair_private_key) { + grpc_ssl_pem_key_cert_pair key_cert_pair; + if (key_cert_pair_cert_chain || key_cert_pair_private_key) { + key_cert_pair.cert_chain = key_cert_pair_cert_chain; + key_cert_pair.private_key = key_cert_pair_private_key; + return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair); + } else { + GPR_ASSERT(!key_cert_pair_cert_chain); + GPR_ASSERT(!key_cert_pair_private_key); + return grpc_ssl_credentials_create(pem_root_certs, NULL); + } +} + +GPR_EXPORT void grpcsharp_credentials_release(grpc_credentials *creds) { + grpc_credentials_release(creds); +} + +GPR_EXPORT grpc_channel *GPR_CALLTYPE +grpcsharp_secure_channel_create(grpc_credentials *creds, const char *target, + const grpc_channel_args *args) { + return grpc_secure_channel_create(creds, target, args); +} + /* Logging */ typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, gpr_int32 line, diff --git a/src/node/binding.gyp b/src/node/binding.gyp index 10afaf696271f120ce1ef2fb10e80a36ee3d72e8..7ef3bdf4bdedaf150aaa75d8ef0b4f290d3d877d 100644 --- a/src/node/binding.gyp +++ b/src/node/binding.gyp @@ -1,9 +1,4 @@ { - "variables" : { - 'no_install': "<!(echo $GRPC_NO_INSTALL)", - 'grpc_root': "<!(echo $GRPC_ROOT)", - 'grpc_lib_subdir': "<!(echo $GRPC_LIB_SUBDIR)" - }, "targets" : [ { 'include_dirs': [ @@ -24,7 +19,9 @@ 'link_settings': { 'libraries': [ '-lrt', - '-lpthread' + '-lpthread', + '-lgrpc', + '-lgpr' ], }, "target_name": "grpc", @@ -38,27 +35,6 @@ "ext/server.cc", "ext/server_credentials.cc", "ext/timeval.cc" - ], - 'conditions' : [ - ['no_install=="yes"', { - 'include_dirs': [ - "<(grpc_root)/include" - ], - 'link_settings': { - 'libraries': [ - '<(grpc_root)/<(grpc_lib_subdir)/libgrpc.a', - '<(grpc_root)/<(grpc_lib_subdir)/libgpr.a' - ] - } - }], - ['no_install!="yes"', { - 'link_settings': { - 'libraries': [ - '-lgrpc', - '-lgpr' - ] - } - }] ] } ] diff --git a/src/node/ext/byte_buffer.cc b/src/node/ext/byte_buffer.cc index c165d26e47e1161a48cdc9b45ab43d7ebba7acf8..82b54b518c0e1c1221e632a9e783f8d74d1baa41 100644 --- a/src/node/ext/byte_buffer.cc +++ b/src/node/ext/byte_buffer.cc @@ -44,7 +44,6 @@ namespace grpc { namespace node { -using ::node::Buffer; using v8::Context; using v8::Function; using v8::Handle; @@ -54,8 +53,8 @@ using v8::Value; grpc_byte_buffer *BufferToByteBuffer(Handle<Value> buffer) { NanScope(); - int length = Buffer::Length(buffer); - char *data = Buffer::Data(buffer); + int length = ::node::Buffer::Length(buffer); + char *data = ::node::Buffer::Data(buffer); gpr_slice slice = gpr_slice_malloc(length); memcpy(GPR_SLICE_START_PTR(slice), data, length); grpc_byte_buffer *byte_buffer(grpc_byte_buffer_create(&slice, 1)); @@ -66,7 +65,7 @@ grpc_byte_buffer *BufferToByteBuffer(Handle<Value> buffer) { Handle<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) { NanEscapableScope(); if (buffer == NULL) { - NanReturnNull(); + return NanEscapeScope(NanNull()); } size_t length = grpc_byte_buffer_length(buffer); char *result = reinterpret_cast<char *>(calloc(length, sizeof(char))); @@ -82,12 +81,14 @@ Handle<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) { Handle<Value> MakeFastBuffer(Handle<Value> slowBuffer) { NanEscapableScope(); - Handle<Object> globalObj = Context::GetCurrent()->Global(); + Handle<Object> globalObj = NanGetCurrentContext()->Global(); Handle<Function> bufferConstructor = Handle<Function>::Cast( globalObj->Get(NanNew("Buffer"))); - Handle<Value> consArgs[3] = { slowBuffer, - NanNew<Number>(Buffer::Length(slowBuffer)), - NanNew<Number>(0) }; + Handle<Value> consArgs[3] = { + slowBuffer, + NanNew<Number>(::node::Buffer::Length(slowBuffer)), + NanNew<Number>(0) + }; Handle<Object> fastBuffer = bufferConstructor->NewInstance(3, consArgs); return NanEscapeScope(fastBuffer); } diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 9ed389f3bc5faa410ae0e84e0d1bd4d69c2a44ff..afb654178318127ec38b454cc2379fd41ddf1eae 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -54,8 +54,6 @@ using std::vector; namespace grpc { namespace node { -using ::node::Buffer; -using v8::Arguments; using v8::Array; using v8::Boolean; using v8::Exception; @@ -74,7 +72,7 @@ using v8::Uint32; using v8::String; using v8::Value; -Persistent<Function> Call::constructor; +NanCallback *Call::constructor; Persistent<FunctionTemplate> Call::fun_tpl; @@ -101,11 +99,11 @@ bool CreateMetadataArray(Handle<Object> metadata, grpc_metadata_array *array, Handle<Value> value = values->Get(j); grpc_metadata *current = &array->metadata[array->count]; current->key = **utf8_key; - if (Buffer::HasInstance(value)) { - current->value = Buffer::Data(value); - current->value_length = Buffer::Length(value); - Persistent<Value> handle; - NanAssignPersistent(handle, value); + if (::node::Buffer::HasInstance(value)) { + current->value = ::node::Buffer::Data(value); + current->value_length = ::node::Buffer::Length(value); + Persistent<Value> *handle = new Persistent<Value>(); + NanAssignPersistent(*handle, value); resources->handles.push_back(unique_ptr<PersistentHolder>( new PersistentHolder(handle))); } else if (value->IsString()) { @@ -140,7 +138,7 @@ Handle<Value> ParseMetadata(const grpc_metadata_array *metadata_array) { Handle<Object> metadata_object = NanNew<Object>(); for (unsigned int i = 0; i < length; i++) { grpc_metadata* elem = &metadata_elements[i]; - Handle<String> key_string = String::New(elem->key); + Handle<String> key_string = NanNew(elem->key); Handle<Array> array; if (metadata_object->Has(key_string)) { array = Handle<Array>::Cast(metadata_object->Get(key_string)); @@ -194,12 +192,12 @@ class SendMessageOp : public Op { } bool ParseOp(Handle<Value> value, grpc_op *out, shared_ptr<Resources> resources) { - if (!Buffer::HasInstance(value)) { + if (!::node::Buffer::HasInstance(value)) { return false; } out->data.send_message = BufferToByteBuffer(value); - Persistent<Value> handle; - NanAssignPersistent(handle, value); + Persistent<Value> *handle = new Persistent<Value>(); + NanAssignPersistent(*handle, value); resources->handles.push_back(unique_ptr<PersistentHolder>( new PersistentHolder(handle))); return true; @@ -357,7 +355,7 @@ class ClientStatusOp : public Op { Handle<Object> status_obj = NanNew<Object>(); status_obj->Set(NanNew("code"), NanNew<Number>(status)); if (status_details != NULL) { - status_obj->Set(NanNew("details"), String::New(status_details)); + status_obj->Set(NanNew("details"), NanNew(status_details)); } status_obj->Set(NanNew("metadata"), ParseMetadata(&metadata_array)); return NanEscapeScope(status_obj); @@ -436,20 +434,21 @@ Call::~Call() { void Call::Init(Handle<Object> exports) { NanScope(); - Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); tpl->SetClassName(NanNew("Call")); tpl->InstanceTemplate()->SetInternalFieldCount(1); NanSetPrototypeTemplate(tpl, "startBatch", - FunctionTemplate::New(StartBatch)->GetFunction()); + NanNew<FunctionTemplate>(StartBatch)->GetFunction()); NanSetPrototypeTemplate(tpl, "cancel", - FunctionTemplate::New(Cancel)->GetFunction()); + NanNew<FunctionTemplate>(Cancel)->GetFunction()); NanAssignPersistent(fun_tpl, tpl); - NanAssignPersistent(constructor, tpl->GetFunction()); - constructor->Set(NanNew("WRITE_BUFFER_HINT"), - NanNew<Uint32, uint32_t>(GRPC_WRITE_BUFFER_HINT)); - constructor->Set(NanNew("WRITE_NO_COMPRESS"), - NanNew<Uint32, uint32_t>(GRPC_WRITE_NO_COMPRESS)); - exports->Set(String::NewSymbol("Call"), constructor); + Handle<Function> ctr = tpl->GetFunction(); + ctr->Set(NanNew("WRITE_BUFFER_HINT"), + NanNew<Uint32, uint32_t>(GRPC_WRITE_BUFFER_HINT)); + ctr->Set(NanNew("WRITE_NO_COMPRESS"), + NanNew<Uint32, uint32_t>(GRPC_WRITE_NO_COMPRESS)); + exports->Set(NanNew("Call"), ctr); + constructor = new NanCallback(ctr); } bool Call::HasInstance(Handle<Value> val) { @@ -463,8 +462,8 @@ Handle<Value> Call::WrapStruct(grpc_call *call) { return NanEscapeScope(NanNull()); } const int argc = 1; - Handle<Value> argv[argc] = {External::New(reinterpret_cast<void *>(call))}; - return NanEscapeScope(constructor->NewInstance(argc, argv)); + Handle<Value> argv[argc] = {NanNew<External>(reinterpret_cast<void *>(call))}; + return NanEscapeScope(constructor->GetFunction()->NewInstance(argc, argv)); } NAN_METHOD(Call::New) { @@ -473,9 +472,10 @@ NAN_METHOD(Call::New) { if (args.IsConstructCall()) { Call *call; if (args[0]->IsExternal()) { + Handle<External> ext = args[0].As<External>(); // This option is used for wrapping an existing call grpc_call *call_value = - reinterpret_cast<grpc_call *>(External::Unwrap(args[0])); + reinterpret_cast<grpc_call *>(ext->Value()); call = new Call(call_value); } else { if (!Channel::HasInstance(args[0])) { @@ -500,15 +500,14 @@ NAN_METHOD(Call::New) { wrapped_channel, CompletionQueueAsyncWorker::GetQueue(), *method, channel->GetHost(), MillisecondsToTimespec(deadline)); call = new Call(wrapped_call); - args.This()->SetHiddenValue(String::NewSymbol("channel_"), - channel_object); + args.This()->SetHiddenValue(NanNew("channel_"), channel_object); } call->Wrap(args.This()); NanReturnValue(args.This()); } else { const int argc = 4; Local<Value> argv[argc] = {args[0], args[1], args[2], args[3]}; - NanReturnValue(constructor->NewInstance(argc, argv)); + NanReturnValue(constructor->GetFunction()->NewInstance(argc, argv)); } } diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 933541ce5b654aed5bfedd9a91ae373f4d6e2ef1..43142c7091fe6c30b434a03d413c22f844853771 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -40,6 +40,7 @@ #include <node.h> #include <nan.h> #include "grpc/grpc.h" +#include "grpc/support/log.h" #include "channel.h" @@ -54,16 +55,17 @@ v8::Handle<v8::Value> ParseMetadata(const grpc_metadata_array *metadata_array); class PersistentHolder { public: - explicit PersistentHolder(v8::Persistent<v8::Value> persist) : + explicit PersistentHolder(v8::Persistent<v8::Value> *persist) : persist(persist) { } ~PersistentHolder() { - NanDisposePersistent(persist); + NanDisposePersistent(*persist); + delete persist; } private: - v8::Persistent<v8::Value> persist; + v8::Persistent<v8::Value> *persist; }; struct Resources { @@ -118,7 +120,7 @@ class Call : public ::node::ObjectWrap { static NAN_METHOD(New); static NAN_METHOD(StartBatch); static NAN_METHOD(Cancel); - static v8::Persistent<v8::Function> constructor; + static NanCallback *constructor; // Used for typechecking instances of this javascript class static v8::Persistent<v8::FunctionTemplate> fun_tpl; diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc index bc9461d7dfd39535c287c8246a3fe1010855edab..787e274973fdf7b9cd248a7090c0f08041a3caa3 100644 --- a/src/node/ext/channel.cc +++ b/src/node/ext/channel.cc @@ -45,7 +45,6 @@ namespace grpc { namespace node { -using v8::Arguments; using v8::Array; using v8::Exception; using v8::Function; @@ -59,7 +58,7 @@ using v8::Persistent; using v8::String; using v8::Value; -Persistent<Function> Channel::constructor; +NanCallback *Channel::constructor; Persistent<FunctionTemplate> Channel::fun_tpl; Channel::Channel(grpc_channel *channel, NanUtf8String *host) @@ -74,14 +73,15 @@ Channel::~Channel() { void Channel::Init(Handle<Object> exports) { NanScope(); - Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); tpl->SetClassName(NanNew("Channel")); tpl->InstanceTemplate()->SetInternalFieldCount(1); NanSetPrototypeTemplate(tpl, "close", - FunctionTemplate::New(Close)->GetFunction()); + NanNew<FunctionTemplate>(Close)->GetFunction()); NanAssignPersistent(fun_tpl, tpl); - NanAssignPersistent(constructor, tpl->GetFunction()); - exports->Set(NanNew("Channel"), constructor); + Handle<Function> ctr = tpl->GetFunction(); + constructor = new NanCallback(ctr); + exports->Set(NanNew("Channel"), ctr); } bool Channel::HasInstance(Handle<Value> val) { @@ -170,7 +170,7 @@ NAN_METHOD(Channel::New) { } else { const int argc = 2; Local<Value> argv[argc] = {args[0], args[1]}; - NanReturnValue(constructor->NewInstance(argc, argv)); + NanReturnValue(constructor->GetFunction()->NewInstance(argc, argv)); } } diff --git a/src/node/ext/channel.h b/src/node/ext/channel.h index bf793194d9a7ff1cb91bd90b5d15f043f83d983e..b3aa0f700fa98b16f47a4fa6bd4834b0f550a600 100644 --- a/src/node/ext/channel.h +++ b/src/node/ext/channel.h @@ -66,7 +66,7 @@ class Channel : public ::node::ObjectWrap { static NAN_METHOD(New); static NAN_METHOD(Close); - static v8::Persistent<v8::Function> constructor; + static NanCallback *constructor; static v8::Persistent<v8::FunctionTemplate> fun_tpl; grpc_channel *wrapped_channel; diff --git a/src/node/ext/completion_queue_async_worker.cc b/src/node/ext/completion_queue_async_worker.cc index ca22527e6f547a776d49cda075f88ca0272e97a5..cd7acd1d1b11d4ebdcebc8d3c392211d8f645928 100644 --- a/src/node/ext/completion_queue_async_worker.cc +++ b/src/node/ext/completion_queue_async_worker.cc @@ -80,7 +80,6 @@ void CompletionQueueAsyncWorker::HandleOKCallback() { NanScope(); NanCallback *callback = GetTagCallback(result->tag); Handle<Value> argv[] = {NanNull(), GetTagNodeValue(result->tag)}; - callback->Call(2, argv); DestroyTag(result->tag); diff --git a/src/node/ext/credentials.cc b/src/node/ext/credentials.cc index 3f65d59c766be9641fefb804b4e1f26baf2fccd0..34872017ea186eb76e3f24a2f95f003f8e8e7f71 100644 --- a/src/node/ext/credentials.cc +++ b/src/node/ext/credentials.cc @@ -41,8 +41,6 @@ namespace grpc { namespace node { -using ::node::Buffer; -using v8::Arguments; using v8::Exception; using v8::External; using v8::Function; @@ -56,7 +54,7 @@ using v8::ObjectTemplate; using v8::Persistent; using v8::Value; -Persistent<Function> Credentials::constructor; +NanCallback *Credentials::constructor; Persistent<FunctionTemplate> Credentials::fun_tpl; Credentials::Credentials(grpc_credentials *credentials) @@ -68,24 +66,25 @@ Credentials::~Credentials() { void Credentials::Init(Handle<Object> exports) { NanScope(); - Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); tpl->SetClassName(NanNew("Credentials")); tpl->InstanceTemplate()->SetInternalFieldCount(1); NanAssignPersistent(fun_tpl, tpl); - NanAssignPersistent(constructor, tpl->GetFunction()); - constructor->Set(NanNew("createDefault"), - FunctionTemplate::New(CreateDefault)->GetFunction()); - constructor->Set(NanNew("createSsl"), - FunctionTemplate::New(CreateSsl)->GetFunction()); - constructor->Set(NanNew("createComposite"), - FunctionTemplate::New(CreateComposite)->GetFunction()); - constructor->Set(NanNew("createGce"), - FunctionTemplate::New(CreateGce)->GetFunction()); - constructor->Set(NanNew("createFake"), - FunctionTemplate::New(CreateFake)->GetFunction()); - constructor->Set(NanNew("createIam"), - FunctionTemplate::New(CreateIam)->GetFunction()); - exports->Set(NanNew("Credentials"), constructor); + Handle<Function> ctr = tpl->GetFunction(); + ctr->Set(NanNew("createDefault"), + NanNew<FunctionTemplate>(CreateDefault)->GetFunction()); + ctr->Set(NanNew("createSsl"), + NanNew<FunctionTemplate>(CreateSsl)->GetFunction()); + ctr->Set(NanNew("createComposite"), + NanNew<FunctionTemplate>(CreateComposite)->GetFunction()); + ctr->Set(NanNew("createGce"), + NanNew<FunctionTemplate>(CreateGce)->GetFunction()); + ctr->Set(NanNew("createFake"), + NanNew<FunctionTemplate>(CreateFake)->GetFunction()); + ctr->Set(NanNew("createIam"), + NanNew<FunctionTemplate>(CreateIam)->GetFunction()); + constructor = new NanCallback(ctr); + exports->Set(NanNew("Credentials"), ctr); } bool Credentials::HasInstance(Handle<Value> val) { @@ -100,8 +99,8 @@ Handle<Value> Credentials::WrapStruct(grpc_credentials *credentials) { } const int argc = 1; Handle<Value> argv[argc] = { - External::New(reinterpret_cast<void *>(credentials))}; - return NanEscapeScope(constructor->NewInstance(argc, argv)); + NanNew<External>(reinterpret_cast<void *>(credentials))}; + return NanEscapeScope(constructor->GetFunction()->NewInstance(argc, argv)); } grpc_credentials *Credentials::GetWrappedCredentials() { @@ -116,15 +115,16 @@ NAN_METHOD(Credentials::New) { return NanThrowTypeError( "Credentials can only be created with the provided functions"); } + Handle<External> ext = args[0].As<External>(); grpc_credentials *creds_value = - reinterpret_cast<grpc_credentials *>(External::Unwrap(args[0])); + reinterpret_cast<grpc_credentials *>(ext->Value()); Credentials *credentials = new Credentials(creds_value); credentials->Wrap(args.This()); NanReturnValue(args.This()); } else { const int argc = 1; Local<Value> argv[argc] = {args[0]}; - NanReturnValue(constructor->NewInstance(argc, argv)); + NanReturnValue(constructor->GetFunction()->NewInstance(argc, argv)); } } @@ -137,19 +137,19 @@ NAN_METHOD(Credentials::CreateSsl) { NanScope(); char *root_certs = NULL; grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL}; - if (Buffer::HasInstance(args[0])) { - root_certs = Buffer::Data(args[0]); + if (::node::Buffer::HasInstance(args[0])) { + root_certs = ::node::Buffer::Data(args[0]); } else if (!(args[0]->IsNull() || args[0]->IsUndefined())) { return NanThrowTypeError("createSsl's first argument must be a Buffer"); } - if (Buffer::HasInstance(args[1])) { - key_cert_pair.private_key = Buffer::Data(args[1]); + if (::node::Buffer::HasInstance(args[1])) { + key_cert_pair.private_key = ::node::Buffer::Data(args[1]); } else if (!(args[1]->IsNull() || args[1]->IsUndefined())) { return NanThrowTypeError( "createSSl's second argument must be a Buffer if provided"); } - if (Buffer::HasInstance(args[2])) { - key_cert_pair.cert_chain = Buffer::Data(args[2]); + if (::node::Buffer::HasInstance(args[2])) { + key_cert_pair.cert_chain = ::node::Buffer::Data(args[2]); } else if (!(args[2]->IsNull() || args[2]->IsUndefined())) { return NanThrowTypeError( "createSSl's third argument must be a Buffer if provided"); diff --git a/src/node/ext/credentials.h b/src/node/ext/credentials.h index e60be3d4e155b7581ff55e2649402cf2bf8e5b45..794736fe1ab51d74c5555a77a88f4ba21be2032f 100644 --- a/src/node/ext/credentials.h +++ b/src/node/ext/credentials.h @@ -68,7 +68,7 @@ class Credentials : public ::node::ObjectWrap { static NAN_METHOD(CreateGce); static NAN_METHOD(CreateFake); static NAN_METHOD(CreateIam); - static v8::Persistent<v8::Function> constructor; + static NanCallback *constructor; // Used for typechecking instances of this javascript class static v8::Persistent<v8::FunctionTemplate> fun_tpl; diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc index 9f5095839cb7404ffe21a5ee320a11049d1292b2..4e31cbaa277bc6c164787b661b3d04aa3d5f87f9 100644 --- a/src/node/ext/node_grpc.cc +++ b/src/node/ext/node_grpc.cc @@ -51,7 +51,7 @@ using v8::String; void InitStatusConstants(Handle<Object> exports) { NanScope(); - Handle<Object> status = Object::New(); + Handle<Object> status = NanNew<Object>(); exports->Set(NanNew("status"), status); Handle<Value> OK(NanNew<Uint32, uint32_t>(GRPC_STATUS_OK)); status->Set(NanNew("OK"), OK); @@ -100,7 +100,7 @@ void InitStatusConstants(Handle<Object> exports) { void InitCallErrorConstants(Handle<Object> exports) { NanScope(); - Handle<Object> call_error = Object::New(); + Handle<Object> call_error = NanNew<Object>(); exports->Set(NanNew("callError"), call_error); Handle<Value> OK(NanNew<Uint32, uint32_t>(GRPC_CALL_OK)); call_error->Set(NanNew("OK"), OK); @@ -131,7 +131,7 @@ void InitCallErrorConstants(Handle<Object> exports) { void InitOpTypeConstants(Handle<Object> exports) { NanScope(); - Handle<Object> op_type = Object::New(); + Handle<Object> op_type = NanNew<Object>(); exports->Set(NanNew("opType"), op_type); Handle<Value> SEND_INITIAL_METADATA( NanNew<Uint32, uint32_t>(GRPC_OP_SEND_INITIAL_METADATA)); diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index ab45da8d199692f0c90ebbcd55d65d76e697639b..e47bac833bd24c31cb58e965d700f2ccfb20faaf 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -53,7 +53,6 @@ namespace grpc { namespace node { using std::unique_ptr; -using v8::Arguments; using v8::Array; using v8::Boolean; using v8::Date; @@ -69,7 +68,7 @@ using v8::Persistent; using v8::String; using v8::Value; -Persistent<Function> Server::constructor; +NanCallback *Server::constructor; Persistent<FunctionTemplate> Server::fun_tpl; class NewCallOp : public Op { @@ -121,28 +120,30 @@ Server::~Server() { grpc_server_destroy(wrapped_server); } void Server::Init(Handle<Object> exports) { NanScope(); - Local<FunctionTemplate> tpl = FunctionTemplate::New(New); - tpl->SetClassName(String::NewSymbol("Server")); + Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); + tpl->SetClassName(NanNew("Server")); tpl->InstanceTemplate()->SetInternalFieldCount(1); NanSetPrototypeTemplate(tpl, "requestCall", - FunctionTemplate::New(RequestCall)->GetFunction()); + NanNew<FunctionTemplate>(RequestCall)->GetFunction()); - NanSetPrototypeTemplate(tpl, "addHttp2Port", - FunctionTemplate::New(AddHttp2Port)->GetFunction()); + NanSetPrototypeTemplate( + tpl, "addHttp2Port", + NanNew<FunctionTemplate>(AddHttp2Port)->GetFunction()); NanSetPrototypeTemplate( tpl, "addSecureHttp2Port", - FunctionTemplate::New(AddSecureHttp2Port)->GetFunction()); + NanNew<FunctionTemplate>(AddSecureHttp2Port)->GetFunction()); NanSetPrototypeTemplate(tpl, "start", - FunctionTemplate::New(Start)->GetFunction()); + NanNew<FunctionTemplate>(Start)->GetFunction()); NanSetPrototypeTemplate(tpl, "shutdown", - FunctionTemplate::New(Shutdown)->GetFunction()); + NanNew<FunctionTemplate>(Shutdown)->GetFunction()); NanAssignPersistent(fun_tpl, tpl); - NanAssignPersistent(constructor, tpl->GetFunction()); - exports->Set(String::NewSymbol("Server"), constructor); + Handle<Function> ctr = tpl->GetFunction(); + constructor = new NanCallback(ctr); + exports->Set(NanNew("Server"), ctr); } bool Server::HasInstance(Handle<Value> val) { @@ -157,26 +158,14 @@ NAN_METHOD(Server::New) { if (!args.IsConstructCall()) { const int argc = 1; Local<Value> argv[argc] = {args[0]}; - NanReturnValue(constructor->NewInstance(argc, argv)); + NanReturnValue(constructor->GetFunction()->NewInstance(argc, argv)); } grpc_server *wrapped_server; grpc_completion_queue *queue = CompletionQueueAsyncWorker::GetQueue(); if (args[0]->IsUndefined()) { wrapped_server = grpc_server_create(queue, NULL); } else if (args[0]->IsObject()) { - grpc_server_credentials *creds = NULL; - Handle<Object> args_hash(args[0]->ToObject()->Clone()); - if (args_hash->HasOwnProperty(NanNew("credentials"))) { - Handle<Value> creds_value = args_hash->Get(NanNew("credentials")); - if (!ServerCredentials::HasInstance(creds_value)) { - return NanThrowTypeError( - "credentials arg must be a ServerCredentials object"); - } - ServerCredentials *creds_object = - ObjectWrap::Unwrap<ServerCredentials>(creds_value->ToObject()); - creds = creds_object->GetWrappedServerCredentials(); - args_hash->Delete(NanNew("credentials")); - } + Handle<Object> args_hash(args[0]->ToObject()); Handle<Array> keys(args_hash->GetOwnPropertyNames()); grpc_channel_args channel_args; channel_args.num_args = keys->Length(); @@ -203,11 +192,7 @@ NAN_METHOD(Server::New) { return NanThrowTypeError("Arg values must be strings"); } } - if (creds == NULL) { - wrapped_server = grpc_server_create(queue, &channel_args); - } else { - wrapped_server = grpc_secure_server_create(creds, queue, &channel_args); - } + wrapped_server = grpc_server_create(queue, &channel_args); free(channel_args.args); } else { return NanThrowTypeError("Server expects an object"); @@ -258,11 +243,19 @@ NAN_METHOD(Server::AddSecureHttp2Port) { "addSecureHttp2Port can only be called on a Server"); } if (!args[0]->IsString()) { - return NanThrowTypeError("addSecureHttp2Port's argument must be a String"); + return NanThrowTypeError( + "addSecureHttp2Port's first argument must be a String"); + } + if (!ServerCredentials::HasInstance(args[1])) { + return NanThrowTypeError( + "addSecureHttp2Port's second argument must be ServerCredentials"); } Server *server = ObjectWrap::Unwrap<Server>(args.This()); + ServerCredentials *creds = ObjectWrap::Unwrap<ServerCredentials>( + args[1]->ToObject()); NanReturnValue(NanNew<Number>(grpc_server_add_secure_http2_port( - server->wrapped_server, *NanUtf8String(args[0])))); + server->wrapped_server, *NanUtf8String(args[0]), + creds->GetWrappedServerCredentials()))); } NAN_METHOD(Server::Start) { diff --git a/src/node/ext/server.h b/src/node/ext/server.h index 2056fe7d3f8a5b14ff2ae948493c089175ee4c12..641d5ccb3e4f7cc5acaba05e22f946336f04e801 100644 --- a/src/node/ext/server.h +++ b/src/node/ext/server.h @@ -67,7 +67,7 @@ class Server : public ::node::ObjectWrap { static NAN_METHOD(AddSecureHttp2Port); static NAN_METHOD(Start); static NAN_METHOD(Shutdown); - static v8::Persistent<v8::Function> constructor; + static NanCallback *constructor; static v8::Persistent<v8::FunctionTemplate> fun_tpl; grpc_server *wrapped_server; diff --git a/src/node/ext/server_credentials.cc b/src/node/ext/server_credentials.cc index f75a2bf79c8f2cd2ec03e3e69311c43d530a654c..d2b63cdc4ec26b1983164b44c39f3899209a1fac 100644 --- a/src/node/ext/server_credentials.cc +++ b/src/node/ext/server_credentials.cc @@ -41,8 +41,6 @@ namespace grpc { namespace node { -using ::node::Buffer; -using v8::Arguments; using v8::Exception; using v8::External; using v8::Function; @@ -56,7 +54,7 @@ using v8::ObjectTemplate; using v8::Persistent; using v8::Value; -Persistent<Function> ServerCredentials::constructor; +NanCallback *ServerCredentials::constructor; Persistent<FunctionTemplate> ServerCredentials::fun_tpl; ServerCredentials::ServerCredentials(grpc_server_credentials *credentials) @@ -68,16 +66,17 @@ ServerCredentials::~ServerCredentials() { void ServerCredentials::Init(Handle<Object> exports) { NanScope(); - Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); tpl->SetClassName(NanNew("ServerCredentials")); tpl->InstanceTemplate()->SetInternalFieldCount(1); NanAssignPersistent(fun_tpl, tpl); - NanAssignPersistent(constructor, tpl->GetFunction()); - constructor->Set(NanNew("createSsl"), - FunctionTemplate::New(CreateSsl)->GetFunction()); - constructor->Set(NanNew("createFake"), - FunctionTemplate::New(CreateFake)->GetFunction()); - exports->Set(NanNew("ServerCredentials"), constructor); + Handle<Function> ctr = tpl->GetFunction(); + ctr->Set(NanNew("createSsl"), + NanNew<FunctionTemplate>(CreateSsl)->GetFunction()); + ctr->Set(NanNew("createFake"), + NanNew<FunctionTemplate>(CreateFake)->GetFunction()); + constructor = new NanCallback(ctr); + exports->Set(NanNew("ServerCredentials"), ctr); } bool ServerCredentials::HasInstance(Handle<Value> val) { @@ -93,8 +92,8 @@ Handle<Value> ServerCredentials::WrapStruct( } const int argc = 1; Handle<Value> argv[argc] = { - External::New(reinterpret_cast<void *>(credentials))}; - return NanEscapeScope(constructor->NewInstance(argc, argv)); + NanNew<External>(reinterpret_cast<void *>(credentials))}; + return NanEscapeScope(constructor->GetFunction()->NewInstance(argc, argv)); } grpc_server_credentials *ServerCredentials::GetWrappedServerCredentials() { @@ -109,15 +108,16 @@ NAN_METHOD(ServerCredentials::New) { return NanThrowTypeError( "ServerCredentials can only be created with the provide functions"); } + Handle<External> ext = args[0].As<External>(); grpc_server_credentials *creds_value = - reinterpret_cast<grpc_server_credentials *>(External::Unwrap(args[0])); + reinterpret_cast<grpc_server_credentials *>(ext->Value()); ServerCredentials *credentials = new ServerCredentials(creds_value); credentials->Wrap(args.This()); NanReturnValue(args.This()); } else { const int argc = 1; Local<Value> argv[argc] = {args[0]}; - NanReturnValue(constructor->NewInstance(argc, argv)); + NanReturnValue(constructor->GetFunction()->NewInstance(argc, argv)); } } @@ -126,20 +126,20 @@ NAN_METHOD(ServerCredentials::CreateSsl) { NanScope(); char *root_certs = NULL; grpc_ssl_pem_key_cert_pair key_cert_pair; - if (Buffer::HasInstance(args[0])) { - root_certs = Buffer::Data(args[0]); + if (::node::Buffer::HasInstance(args[0])) { + root_certs = ::node::Buffer::Data(args[0]); } else if (!(args[0]->IsNull() || args[0]->IsUndefined())) { return NanThrowTypeError( "createSSl's first argument must be a Buffer if provided"); } - if (!Buffer::HasInstance(args[1])) { + if (!::node::Buffer::HasInstance(args[1])) { return NanThrowTypeError("createSsl's second argument must be a Buffer"); } - key_cert_pair.private_key = Buffer::Data(args[1]); - if (!Buffer::HasInstance(args[2])) { + key_cert_pair.private_key = ::node::Buffer::Data(args[1]); + if (!::node::Buffer::HasInstance(args[2])) { return NanThrowTypeError("createSsl's third argument must be a Buffer"); } - key_cert_pair.cert_chain = Buffer::Data(args[2]); + key_cert_pair.cert_chain = ::node::Buffer::Data(args[2]); NanReturnValue(WrapStruct( grpc_ssl_server_credentials_create(root_certs, &key_cert_pair, 1))); } diff --git a/src/node/ext/server_credentials.h b/src/node/ext/server_credentials.h index f09902420c6e6413f02f4bfa086d4827294a66e6..aaa7ef297a40cc9f4d868429b0c08e42cc52a5aa 100644 --- a/src/node/ext/server_credentials.h +++ b/src/node/ext/server_credentials.h @@ -64,7 +64,7 @@ class ServerCredentials : public ::node::ObjectWrap { static NAN_METHOD(New); static NAN_METHOD(CreateSsl); static NAN_METHOD(CreateFake); - static v8::Persistent<v8::Function> constructor; + static NanCallback *constructor; // Used for typechecking instances of this javascript class static v8::Persistent<v8::FunctionTemplate> fun_tpl; diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js index 125ede174642f05bb0ee5f3d0831f5b69b797d7c..8e5c03666fa3b7ddcfb02ae9bd77a9856af52351 100644 --- a/src/node/interop/interop_server.js +++ b/src/node/interop/interop_server.js @@ -165,16 +165,16 @@ function handleHalfDuplex(call) { function getServer(port, tls) { // TODO(mlumish): enable TLS functionality var options = {}; + var server_creds = null; if (tls) { var key_path = path.join(__dirname, '../test/data/server1.key'); var pem_path = path.join(__dirname, '../test/data/server1.pem'); var key_data = fs.readFileSync(key_path); var pem_data = fs.readFileSync(pem_path); - var server_creds = grpc.ServerCredentials.createSsl(null, - key_data, - pem_data); - options.credentials = server_creds; + server_creds = grpc.ServerCredentials.createSsl(null, + key_data, + pem_data); } var server = new Server({ 'grpc.testing.TestService' : { @@ -186,7 +186,7 @@ function getServer(port, tls) { halfDuplexCall: handleHalfDuplex } }, null, options); - var port_num = server.bind('0.0.0.0:' + port, tls); + var port_num = server.bind('0.0.0.0:' + port, server_creds); return {server: server, port: port_num}; } diff --git a/src/node/package.json b/src/node/package.json index 0ef1c990b1ee27001f8b14b0c5dff24f901e937d..f8c3ab079d9ef599b45c10249a7e7e517ecf28a2 100644 --- a/src/node/package.json +++ b/src/node/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "0.5.1", + "version": "0.5.3", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", @@ -24,20 +24,23 @@ "test": "node ./node_modules/mocha/bin/mocha && npm run-script lint" }, "dependencies": { - "bindings": "^1.2.1", - "jshint": "^2.5.5", - "nan": "~1.3.0", + "bindings": "^1.2.0", + "nan": "^1.5.0", "protobufjs": "murgatroid99/ProtoBuf.js", - "underscore": "^1.7.0", + "underscore": "^1.6.0", "underscore.string": "^3.0.0" }, "devDependencies": { "async": "^0.9.0", "google-auth-library": "^0.9.2", + "jshint": "^2.5.0", "minimist": "^1.1.0", "mocha": "~1.21.0", "strftime": "^0.8.2" }, + "engines": { + "node": ">=0.10.13" + }, "files": [ "LICENSE", "README.md", diff --git a/src/node/src/server.js b/src/node/src/server.js index 91dde0225181cc9341fd454bbab111723493c313..b72d110666e833518ec60d889a2c6805b8c1a36c 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -517,14 +517,15 @@ Server.prototype.register = function(name, handler, serialize, deserialize, }; /** - * Binds the server to the given port, with SSL enabled if secure is specified + * Binds the server to the given port, with SSL enabled if creds is given * @param {string} port The port that the server should bind on, in the format * "address:port" - * @param {boolean=} secure Whether the server should open a secure port + * @param {boolean=} creds Server credential object to be used for SSL. Pass + * nothing for an insecure port */ -Server.prototype.bind = function(port, secure) { - if (secure) { - return this._server.addSecureHttp2Port(port); +Server.prototype.bind = function(port, creds) { + if (creds) { + return this._server.addSecureHttp2Port(port, creds); } else { return this._server.addHttp2Port(port); } @@ -604,14 +605,14 @@ function makeServerConstructor(services) { } /** - * Binds the server to the given port, with SSL enabled if secure is specified + * Binds the server to the given port, with SSL enabled if creds is supplied * @param {string} port The port that the server should bind on, in the format * "address:port" - * @param {boolean=} secure Whether the server should open a secure port + * @param {boolean=} creds Credentials to use for SSL * @return {SurfaceServer} this */ - SurfaceServer.prototype.bind = function(port, secure) { - return this.inner_server.bind(port, secure); + SurfaceServer.prototype.bind = function(port, creds) { + return this.inner_server.bind(port, creds); }; /** diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js index 1cc192869175032399f334a501dc84f6ba0e2ad0..c39364d410ef863b37988fd3581bdd2a416e13a5 100644 --- a/src/node/test/end_to_end_test.js +++ b/src/node/test/end_to_end_test.js @@ -235,4 +235,73 @@ describe('end-to-end', function() { }); }); }); + it('should send multiple messages', function(complete) { + var done = multiDone(complete, 2); + var requests = ['req1', 'req2']; + var deadline = new Date(); + deadline.setSeconds(deadline.getSeconds() + 3); + var status_text = 'xyz'; + var call = new grpc.Call(channel, + 'dummy_method', + Infinity); + var client_batch = {}; + client_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + client_batch[grpc.opType.SEND_MESSAGE] = new Buffer(requests[0]); + client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + call.startBatch(client_batch, function(err, response) { + assert.ifError(err); + assert.deepEqual(response, { + 'send metadata': true, + 'send message': true, + 'metadata': {} + }); + var req2_batch = {}; + req2_batch[grpc.opType.SEND_MESSAGE] = new Buffer(requests[1]); + req2_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + req2_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(req2_batch, function(err, resp) { + assert.ifError(err); + assert.deepEqual(resp, { + 'send message': true, + 'client close': true, + 'status': { + 'code': grpc.status.OK, + 'details': status_text, + 'metadata': {} + } + }); + done(); + }); + }); + + server.requestCall(function(err, call_details) { + var new_call = call_details['new call']; + assert.notEqual(new_call, null); + var server_call = new_call.call; + assert.notEqual(server_call, null); + var server_batch = {}; + server_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + server_batch[grpc.opType.RECV_MESSAGE] = true; + server_call.startBatch(server_batch, function(err, response) { + assert.ifError(err); + assert(response['send metadata']); + assert.strictEqual(response.read.toString(), requests[0]); + var end_batch = {}; + end_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; + end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { + 'metadata': {}, + 'code': grpc.status.OK, + 'details': status_text + }; + end_batch[grpc.opType.RECV_MESSAGE] = true; + server_call.startBatch(end_batch, function(err, response) { + assert.ifError(err); + assert(response['send status']); + assert(!response.cancelled); + assert.strictEqual(response.read.toString(), requests[1]); + done(); + }); + }); + }); + }); }); diff --git a/src/node/test/server_test.js b/src/node/test/server_test.js new file mode 100644 index 0000000000000000000000000000000000000000..7cb34fa0cb5d24cf29918b779f3bdde9bc0149d5 --- /dev/null +++ b/src/node/test/server_test.js @@ -0,0 +1,94 @@ +/* + * + * 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. + * + */ + +'use strict'; + +var assert = require('assert'); +var grpc = require('bindings')('grpc.node'); + +describe('server', function() { + describe('constructor', function() { + it('should work with no arguments', function() { + assert.doesNotThrow(function() { + new grpc.Server(); + }); + }); + it('should work with an empty list argument', function() { + assert.doesNotThrow(function() { + new grpc.Server([]); + }); + }); + }); + describe('addHttp2Port', function() { + var server; + before(function() { + server = new grpc.Server(); + }); + it('should bind to an unused port', function() { + var port; + assert.doesNotThrow(function() { + port = server.addHttp2Port('0.0.0.0:0'); + }); + assert(port > 0); + }); + }); + describe('addSecureHttp2Port', function() { + var server; + before(function() { + server = new grpc.Server(); + }); + it('should bind to an unused port with fake credentials', function() { + var port; + var creds = grpc.ServerCredentials.createFake(); + assert.doesNotThrow(function() { + port = server.addSecureHttp2Port('0.0.0.0:0', creds); + }); + assert(port > 0); + }); + }); + describe('listen', function() { + var server; + before(function() { + server = new grpc.Server(); + server.addHttp2Port('0.0.0.0:0'); + }); + after(function() { + server.shutdown(); + }); + it('should listen without error', function() { + assert.doesNotThrow(function() { + server.start(); + }); + }); + }); +}); diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c index d1362c8b51a8bf580b9b4880f5d6fd04caf57e5b..055a7263b9b1a35b061643d2357cdc07d4530494 100644 --- a/src/php/ext/grpc/server.c +++ b/src/php/ext/grpc/server.c @@ -107,9 +107,6 @@ PHP_METHOD(Server, __construct) { (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); zval *args_array = NULL; grpc_channel_args args; - HashTable *array_hash; - zval **creds_obj = NULL; - wrapped_grpc_server_credentials *creds = NULL; /* "a" == 1 optional array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &args_array) == FAILURE) { @@ -122,28 +119,8 @@ PHP_METHOD(Server, __construct) { if (args_array == NULL) { server->wrapped = grpc_server_create(server->queue, NULL); } else { - array_hash = Z_ARRVAL_P(args_array); - if (zend_hash_find(array_hash, "credentials", sizeof("credentials"), - (void **)&creds_obj) == SUCCESS) { - if (zend_get_class_entry(*creds_obj TSRMLS_CC) != - grpc_ce_server_credentials) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "credentials must be a ServerCredentials object", - 1 TSRMLS_CC); - return; - } - creds = (wrapped_grpc_server_credentials *)zend_object_store_get_object( - *creds_obj TSRMLS_CC); - zend_hash_del(array_hash, "credentials", sizeof("credentials")); - } php_grpc_read_args_array(args_array, &args); - if (creds == NULL) { - server->wrapped = grpc_server_create(server->queue, &args); - } else { - gpr_log(GPR_DEBUG, "Initialized secure server"); - server->wrapped = - grpc_secure_server_create(creds->wrapped, server->queue, &args); - } + server->wrapped = grpc_server_create(server->queue, &args); efree(args.args); } } @@ -219,14 +196,21 @@ PHP_METHOD(Server, add_secure_http2_port) { (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); const char *addr; int addr_len; - /* "s" == 1 string */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len) == + zval *creds_obj; + /* "sO" == 1 string, 1 object */ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len, + &creds_obj, grpc_ce_server_credentials) == FAILURE) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "add_http2_port expects a string", 1 TSRMLS_CC); + zend_throw_exception( + spl_ce_InvalidArgumentException, + "add_http2_port expects a string and a ServerCredentials", 1 TSRMLS_CC); return; } - RETURN_LONG(grpc_server_add_secure_http2_port(server->wrapped, addr)); + wrapped_grpc_server_credentials *creds = + (wrapped_grpc_server_credentials *)zend_object_store_get_object( + creds_obj TSRMLS_CC); + RETURN_LONG(grpc_server_add_secure_http2_port(server->wrapped, addr, + creds->wrapped)); } /** diff --git a/src/php/tests/unit_tests/SecureEndToEndTest.php b/src/php/tests/unit_tests/SecureEndToEndTest.php index c23dd791acf979aba0d2fdf798166dfc87a4b6ca..896afeac49ad7fa656eb3f8e7f9dfa221bf0ce25 100755 --- a/src/php/tests/unit_tests/SecureEndToEndTest.php +++ b/src/php/tests/unit_tests/SecureEndToEndTest.php @@ -41,9 +41,9 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase{ null, file_get_contents(dirname(__FILE__) . '/../data/server1.key'), file_get_contents(dirname(__FILE__) . '/../data/server1.pem')); - $this->server = new Grpc\Server($this->server_queue, - ['credentials' => $server_credentials]); - $port = $this->server->add_secure_http2_port('0.0.0.0:0'); + $this->server = new Grpc\Server($this->server_queue); + $port = $this->server->add_secure_http2_port('0.0.0.0:0', + $server_credentials); $this->channel = new Grpc\Channel( 'localhost:' . $port, [ diff --git a/src/python/README.md b/src/python/README.md index 490a229d1d776a6f24c924f29a3d0759b3233e9a..c8057be38b380a86956d6fb8fc8819ebaf7eb4ed 100644 --- a/src/python/README.md +++ b/src/python/README.md @@ -46,7 +46,7 @@ Installing - Install gRPC Python's dependencies ``` -$ pip install -r requirements.txt +$ pip install -r src/python/requirements.txt ``` - Install gRPC Python diff --git a/src/python/interop/interop/_insecure_interop_test.py b/src/python/interop/interop/_insecure_interop_test.py new file mode 100644 index 0000000000000000000000000000000000000000..1fa6b8b3f8f80a177dad0685dd2f4023351a4a9e --- /dev/null +++ b/src/python/interop/interop/_insecure_interop_test.py @@ -0,0 +1,56 @@ +# 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. + +"""Insecure client-server interoperability as a unit test.""" + +import unittest + +from grpc.early_adopter import implementations + +from interop import _interop_test_case +from interop import methods + + +class InsecureInteropTest( + _interop_test_case.InteropTestCase, + unittest.TestCase): + + def setUp(self): + self.server = implementations.insecure_server(methods.SERVER_METHODS, 0) + self.server.start() + port = self.server.port() + self.stub = implementations.insecure_stub( + methods.CLIENT_METHODS, 'localhost', port) + + def tearDown(self): + self.server.stop() + + +if __name__ == '__main__': + unittest.main() diff --git a/src/python/interop/interop/_interop_test_case.py b/src/python/interop/interop/_interop_test_case.py new file mode 100644 index 0000000000000000000000000000000000000000..fec8f1915d53972d5abe126900636f776275ffe9 --- /dev/null +++ b/src/python/interop/interop/_interop_test_case.py @@ -0,0 +1,55 @@ +# 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. + +"""Common code for unit tests of the interoperability test code.""" + +from interop import methods + + +class InteropTestCase(object): + """Unit test methods. + + This class must be mixed in with unittest.TestCase and a class that defines + setUp and tearDown methods that manage a stub attribute. + """ + + def testEmptyUnary(self): + methods.TestCase.EMPTY_UNARY.test_interoperability(self.stub) + + def testLargeUnary(self): + methods.TestCase.LARGE_UNARY.test_interoperability(self.stub) + + def testServerStreaming(self): + methods.TestCase.SERVER_STREAMING.test_interoperability(self.stub) + + def testClientStreaming(self): + methods.TestCase.CLIENT_STREAMING.test_interoperability(self.stub) + + def testPingPong(self): + methods.TestCase.PING_PONG.test_interoperability(self.stub) diff --git a/src/python/interop/interop/_secure_interop_test.py b/src/python/interop/interop/_secure_interop_test.py new file mode 100644 index 0000000000000000000000000000000000000000..cc9e93821ad1693e8b72d8e4f1aa21608761a70a --- /dev/null +++ b/src/python/interop/interop/_secure_interop_test.py @@ -0,0 +1,63 @@ +# 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. + +"""Secure client-server interoperability as a unit test.""" + +import unittest + +from grpc.early_adopter import implementations + +from interop import _interop_test_case +from interop import methods +from interop import resources + +_SERVER_HOST_OVERRIDE = 'foo.test.google.fr' + + +class SecureInteropTest( + _interop_test_case.InteropTestCase, + unittest.TestCase): + + def setUp(self): + self.server = implementations.secure_server( + methods.SERVER_METHODS, 0, resources.private_key(), + resources.certificate_chain()) + self.server.start() + port = self.server.port() + self.stub = implementations.secure_stub( + methods.CLIENT_METHODS, 'localhost', port, + resources.test_root_certificates(), None, None, + server_host_override=_SERVER_HOST_OVERRIDE) + + def tearDown(self): + self.server.stop() + + +if __name__ == '__main__': + unittest.main() diff --git a/src/python/interop/interop/client.py b/src/python/interop/interop/client.py index f4a449ef9e7ebab13c904289cc77965112979d56..b674a64f9d8583b9c5a435747c6f90ac0a6c98ff 100644 --- a/src/python/interop/interop/client.py +++ b/src/python/interop/interop/client.py @@ -65,21 +65,30 @@ def _stub(args): root_certificates = resources.test_root_certificates() else: root_certificates = resources.prod_root_certificates() - # TODO(nathaniel): server host override. stub = implementations.secure_stub( methods.CLIENT_METHODS, args.server_host, args.server_port, - root_certificates, None, None) + root_certificates, None, None, + server_host_override=args.server_host_override) else: stub = implementations.insecure_stub( methods.CLIENT_METHODS, args.server_host, args.server_port) return stub +def _test_case_from_arg(test_case_arg): + for test_case in methods.TestCase: + if test_case_arg == test_case.value: + return test_case + else: + raise ValueError('No test case "%s"!' % test_case_arg) + + def _test_interoperability(): args = _args() stub = _stub(args) - methods.test_interoperability(args.test_case, stub) + test_case = _test_case_from_arg(args.test_case) + test_case.test_interoperability(stub) if __name__ == '__main__': diff --git a/src/python/interop/interop/methods.py b/src/python/interop/interop/methods.py index 4da28ee7759b83e07d7653da717cdb38a49d3fec..2e15fac91573052ca385d2de1e9e1a9c6094948f 100644 --- a/src/python/interop/interop/methods.py +++ b/src/python/interop/interop/methods.py @@ -29,6 +29,7 @@ """Implementations of interoperability test methods.""" +import enum import threading from grpc.early_adopter import utilities @@ -265,16 +266,24 @@ def _ping_pong(stub): pipe.close() -def test_interoperability(test_case, stub): - if test_case == 'empty_unary': - _empty_unary(stub) - elif test_case == 'large_unary': - _large_unary(stub) - elif test_case == 'server_streaming': - _server_streaming(stub) - elif test_case == 'client_streaming': - _client_streaming(stub) - elif test_case == 'ping_pong': - _ping_pong(stub) - else: - raise NotImplementedError('Test case "%s" not implemented!') +@enum.unique +class TestCase(enum.Enum): + EMPTY_UNARY = 'empty_unary' + LARGE_UNARY = 'large_unary' + SERVER_STREAMING = 'server_streaming' + CLIENT_STREAMING = 'client_streaming' + PING_PONG = 'ping_pong' + + def test_interoperability(self, stub): + if self is TestCase.EMPTY_UNARY: + _empty_unary(stub) + elif self is TestCase.LARGE_UNARY: + _large_unary(stub) + elif self is TestCase.SERVER_STREAMING: + _server_streaming(stub) + elif self is TestCase.CLIENT_STREAMING: + _client_streaming(stub) + elif self is TestCase.PING_PONG: + _ping_pong(stub) + else: + raise NotImplementedError('Test case "%s" not implemented!' % self.name) diff --git a/src/python/src/grpc/_adapter/_c_test.py b/src/python/src/grpc/_adapter/_c_test.py index d81c63e3469643bcc1da143c97b1836ddf8e89c5..437a6730cd294560d483fed26b38aacbde97f7b9 100644 --- a/src/python/src/grpc/_adapter/_c_test.py +++ b/src/python/src/grpc/_adapter/_c_test.py @@ -70,7 +70,8 @@ class _CTest(unittest.TestCase): def testChannel(self): _c.init() - channel = _c.Channel('test host:12345', None) + channel = _c.Channel( + 'test host:12345', None, server_host_override='ignored') del channel _c.shut_down() @@ -92,7 +93,7 @@ class _CTest(unittest.TestCase): _c.init() completion_queue = _c.CompletionQueue() - server = _c.Server(completion_queue, None) + server = _c.Server(completion_queue) server.add_http2_addr('[::]:0') server.start() server.stop() @@ -102,7 +103,7 @@ class _CTest(unittest.TestCase): service_tag = object() completion_queue = _c.CompletionQueue() - server = _c.Server(completion_queue, None) + server = _c.Server(completion_queue) server.add_http2_addr('[::]:0') server.start() server.service(service_tag) @@ -119,7 +120,7 @@ class _CTest(unittest.TestCase): del completion_queue completion_queue = _c.CompletionQueue() - server = _c.Server(completion_queue, None) + server = _c.Server(completion_queue) server.add_http2_addr('[::]:0') server.start() thread = threading.Thread(target=completion_queue.get, args=(_FUTURE,)) diff --git a/src/python/src/grpc/_adapter/_channel.c b/src/python/src/grpc/_adapter/_channel.c index 9cf580bcfb591e123f1571856d3c6cddd2ec5c1c..6be8f1c364330b56ab3a7988684c59427a9bdaf3 100644 --- a/src/python/src/grpc/_adapter/_channel.c +++ b/src/python/src/grpc/_adapter/_channel.c @@ -42,19 +42,35 @@ static int pygrpc_channel_init(Channel *self, PyObject *args, PyObject *kwds) { const char *hostport; PyObject *client_credentials; - static char *kwlist[] = {"hostport", "client_credentials", NULL}; + char *server_host_override = NULL; + static char *kwlist[] = {"hostport", "client_credentials", + "server_host_override", NULL}; + grpc_arg server_host_override_arg; + grpc_channel_args channel_args; - if (!(PyArg_ParseTupleAndKeywords(args, kwds, "sO:Channel", kwlist, - &hostport, &client_credentials))) { + if (!(PyArg_ParseTupleAndKeywords(args, kwds, "sO|z:Channel", kwlist, + &hostport, &client_credentials, + &server_host_override))) { return -1; } if (client_credentials == Py_None) { self->c_channel = grpc_channel_create(hostport, NULL); return 0; } else { - self->c_channel = grpc_secure_channel_create( - ((ClientCredentials *)client_credentials)->c_client_credentials, - hostport, NULL); + if (server_host_override == NULL) { + self->c_channel = grpc_secure_channel_create( + ((ClientCredentials *)client_credentials)->c_client_credentials, + hostport, NULL); + } else { + server_host_override_arg.type = GRPC_ARG_STRING; + server_host_override_arg.key = GRPC_SSL_TARGET_NAME_OVERRIDE_ARG; + server_host_override_arg.value.string = server_host_override; + channel_args.num_args = 1; + channel_args.args = &server_host_override_arg; + self->c_channel = grpc_secure_channel_create( + ((ClientCredentials *)client_credentials)->c_client_credentials, + hostport, &channel_args); + } return 0; } } diff --git a/src/python/src/grpc/_adapter/_face_test_case.py b/src/python/src/grpc/_adapter/_face_test_case.py index 475d780c950d1913e0671247f61f5239717315f8..2542eb6da4d794e5b4636e4e8723e130a3e2ca44 100644 --- a/src/python/src/grpc/_adapter/_face_test_case.py +++ b/src/python/src/grpc/_adapter/_face_test_case.py @@ -50,31 +50,12 @@ class FaceTestCase(test_case.FaceTestCase, coverage.BlockingCoverage): """Provides abstract Face-layer tests a GRPC-backed implementation.""" def set_up_implementation( - self, - name, - methods, - inline_value_in_value_out_methods, - inline_value_in_stream_out_methods, - inline_stream_in_value_out_methods, - inline_stream_in_stream_out_methods, - event_value_in_value_out_methods, - event_value_in_stream_out_methods, - event_stream_in_value_out_methods, - event_stream_in_stream_out_methods, - multi_method): + self, name, methods, method_implementations, + multi_method_implementation): pool = logging_pool.pool(_MAXIMUM_POOL_SIZE) servicer = face_implementations.servicer( - pool, - inline_value_in_value_out_methods=inline_value_in_value_out_methods, - inline_value_in_stream_out_methods=inline_value_in_stream_out_methods, - inline_stream_in_value_out_methods=inline_stream_in_value_out_methods, - inline_stream_in_stream_out_methods=inline_stream_in_stream_out_methods, - event_value_in_value_out_methods=event_value_in_value_out_methods, - event_value_in_stream_out_methods=event_value_in_stream_out_methods, - event_stream_in_value_out_methods=event_stream_in_value_out_methods, - event_stream_in_stream_out_methods=event_stream_in_stream_out_methods, - multi_method=multi_method) + pool, method_implementations, multi_method_implementation) serialization = serial.serialization(methods) @@ -96,9 +77,8 @@ class FaceTestCase(test_case.FaceTestCase, coverage.BlockingCoverage): rear_link.join_fore_link(front) front.join_rear_link(rear_link) - server = face_implementations.server() - stub = face_implementations.stub(front, pool) - return server, stub, (rear_link, fore_link, front, back) + stub = face_implementations.generic_stub(front, pool) + return stub, (rear_link, fore_link, front, back) def tear_down_implementation(self, memo): rear_link, fore_link, front, back = memo diff --git a/src/python/src/grpc/_adapter/_low_test.py b/src/python/src/grpc/_adapter/_low_test.py index 03e3f473a3ec0cfd708581386b93e1b7eb43d757..b04ac1c95098a0cf23b89ce304223ccb3ebec89d 100644 --- a/src/python/src/grpc/_adapter/_low_test.py +++ b/src/python/src/grpc/_adapter/_low_test.py @@ -82,7 +82,7 @@ class EchoTest(unittest.TestCase): self.host = 'localhost' self.server_completion_queue = _low.CompletionQueue() - self.server = _low.Server(self.server_completion_queue, None) + self.server = _low.Server(self.server_completion_queue) port = self.server.add_http2_addr('[::]:0') self.server.start() @@ -260,7 +260,7 @@ class CancellationTest(unittest.TestCase): self.host = 'localhost' self.server_completion_queue = _low.CompletionQueue() - self.server = _low.Server(self.server_completion_queue, None) + self.server = _low.Server(self.server_completion_queue) port = self.server.add_http2_addr('[::]:0') self.server.start() diff --git a/src/python/src/grpc/_adapter/_server.c b/src/python/src/grpc/_adapter/_server.c index ae7ae5b5d23e9e99c7be78d4da4345fe682614ca..181b6c21fcf1470cb56ae4168ab74e5c0cadaea2 100644 --- a/src/python/src/grpc/_adapter/_server.c +++ b/src/python/src/grpc/_adapter/_server.c @@ -42,30 +42,16 @@ static int pygrpc_server_init(Server *self, PyObject *args, PyObject *kwds) { const PyObject *completion_queue; - PyObject *server_credentials; - static char *kwlist[] = {"completion_queue", "server_credentials", NULL}; + static char *kwlist[] = {"completion_queue", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O:Server", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!:Server", kwlist, &pygrpc_CompletionQueueType, - &completion_queue, &server_credentials)) { - return -1; - } - if (server_credentials == Py_None) { - self->c_server = grpc_server_create( - ((CompletionQueue *)completion_queue)->c_completion_queue, NULL); - return 0; - } else if (PyObject_TypeCheck(server_credentials, - &pygrpc_ServerCredentialsType)) { - self->c_server = grpc_secure_server_create( - ((ServerCredentials *)server_credentials)->c_server_credentials, - ((CompletionQueue *)completion_queue)->c_completion_queue, NULL); - return 0; - } else { - PyErr_Format(PyExc_TypeError, - "server_credentials must be _grpc.ServerCredentials, not %s", - Py_TYPE(server_credentials)->tp_name); + &completion_queue)) { return -1; } + self->c_server = grpc_server_create( + ((CompletionQueue *)completion_queue)->c_completion_queue, NULL); + return 0; } static void pygrpc_server_dealloc(Server *self) { @@ -92,13 +78,21 @@ static PyObject *pygrpc_server_add_http2_addr(Server *self, PyObject *args) { } static PyObject *pygrpc_server_add_secure_http2_addr(Server *self, - PyObject *args) { + PyObject *args, + PyObject *kwargs) { const char *addr; + PyObject *server_credentials; + static char *kwlist[] = {"addr", "server_credentials", NULL}; int port; - if (!PyArg_ParseTuple(args, "s:add_secure_http2_addr", &addr)) { + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!:add_secure_http2_addr", + kwlist, &addr, &pygrpc_ServerCredentialsType, + &server_credentials)) { return NULL; } - port = grpc_server_add_secure_http2_port(self->c_server, addr); + port = grpc_server_add_secure_http2_port( + self->c_server, addr, + ((ServerCredentials *)server_credentials)->c_server_credentials); if (port == 0) { PyErr_SetString(PyExc_RuntimeError, "Couldn't add port to server!"); return NULL; @@ -138,8 +132,7 @@ static PyMethodDef methods[] = { METH_VARARGS, "Add a secure HTTP2 address."}, {"start", (PyCFunction)pygrpc_server_start, METH_NOARGS, "Starts the server."}, - {"service", (PyCFunction)pygrpc_server_service, METH_O, - "Services a call."}, + {"service", (PyCFunction)pygrpc_server_service, METH_O, "Services a call."}, {"stop", (PyCFunction)pygrpc_server_stop, METH_NOARGS, "Stops the server."}, {NULL}}; diff --git a/src/python/src/grpc/_adapter/fore.py b/src/python/src/grpc/_adapter/fore.py index b08b9f48bc6b891ae2452b7a3ab9981093e347f7..339c0ef216cf54167fe1897429b8fa9d0c011a99 100644 --- a/src/python/src/grpc/_adapter/fore.py +++ b/src/python/src/grpc/_adapter/fore.py @@ -280,13 +280,14 @@ class ForeLink(ticket_interfaces.ForeLink, activated.Activated): 0 if self._requested_port is None else self._requested_port) self._completion_queue = _low.CompletionQueue() if self._root_certificates is None and not self._key_chain_pairs: - self._server = _low.Server(self._completion_queue, None) + self._server = _low.Server(self._completion_queue) self._port = self._server.add_http2_addr(address) else: server_credentials = _low.ServerCredentials( self._root_certificates, self._key_chain_pairs) - self._server = _low.Server(self._completion_queue, server_credentials) - self._port = self._server.add_secure_http2_addr(address) + self._server = _low.Server(self._completion_queue) + self._port = self._server.add_secure_http2_addr( + address, server_credentials) self._server.start() self._server.service(None) @@ -356,90 +357,3 @@ class ForeLink(ticket_interfaces.ForeLink, activated.Activated): self._complete(ticket.operation_id, ticket.payload) else: self._cancel(ticket.operation_id) - - -class _ActivatedForeLink(ticket_interfaces.ForeLink, activated.Activated): - - def __init__( - self, port, request_deserializers, response_serializers, - root_certificates, key_chain_pairs): - self._port = port - self._request_deserializers = request_deserializers - self._response_serializers = response_serializers - self._root_certificates = root_certificates - self._key_chain_pairs = key_chain_pairs - - self._lock = threading.Lock() - self._pool = None - self._fore_link = None - self._rear_link = null.NULL_REAR_LINK - - def join_rear_link(self, rear_link): - with self._lock: - self._rear_link = null.NULL_REAR_LINK if rear_link is None else rear_link - if self._fore_link is not None: - self._fore_link.join_rear_link(rear_link) - - def _start(self): - with self._lock: - self._pool = logging_pool.pool(_THREAD_POOL_SIZE) - self._fore_link = ForeLink( - self._pool, self._request_deserializers, self._response_serializers, - self._root_certificates, self._key_chain_pairs, port=self._port) - self._fore_link.join_rear_link(self._rear_link) - self._fore_link.start() - return self - - def _stop(self): - with self._lock: - self._fore_link.stop() - self._fore_link = None - self._pool.shutdown(wait=True) - self._pool = None - - def __enter__(self): - return self._start() - - def __exit__(self, exc_type, exc_val, exc_tb): - self._stop() - return False - - def start(self): - return self._start() - - def stop(self): - self._stop() - - def port(self): - with self._lock: - return None if self._fore_link is None else self._fore_link.port() - - def accept_back_to_front_ticket(self, ticket): - with self._lock: - if self._fore_link is not None: - self._fore_link.accept_back_to_front_ticket(ticket) - - -def activated_fore_link( - port, request_deserializers, response_serializers, root_certificates, - key_chain_pairs): - """Creates a ForeLink that is also an activated.Activated. - - The returned object is only valid for use between calls to its start and stop - methods (or in context when used as a context manager). - - Args: - port: The port on which to serve RPCs, or None for a port to be - automatically selected. - request_deserializers: A dictionary from RPC method names to request object - deserializer behaviors. - response_serializers: A dictionary from RPC method names to response object - serializer behaviors. - root_certificates: The PEM-encoded client root certificates as a bytestring - or None. - key_chain_pairs: A sequence of PEM-encoded private key-certificate chain - pairs. - """ - return _ActivatedForeLink( - port, request_deserializers, response_serializers, root_certificates, - key_chain_pairs) diff --git a/src/python/src/grpc/_adapter/rear.py b/src/python/src/grpc/_adapter/rear.py index bfde5f5c577571208de1e722aab78d6e44896dca..62703fab30e49d3d7b2b50daeb1e8fb8c8ea792c 100644 --- a/src/python/src/grpc/_adapter/rear.py +++ b/src/python/src/grpc/_adapter/rear.py @@ -93,7 +93,8 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated): def __init__( self, host, port, pool, request_serializers, response_deserializers, - secure, root_certificates, private_key, certificate_chain): + secure, root_certificates, private_key, certificate_chain, + server_host_override=None): """Constructor. Args: @@ -111,6 +112,8 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated): key should be used. certificate_chain: The PEM-encoded certificate chain to use or None if no certificate chain should be used. + server_host_override: (For testing only) the target name used for SSL + host name checking. """ self._condition = threading.Condition() self._host = host @@ -132,6 +135,7 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated): self._root_certificates = root_certificates self._private_key = private_key self._certificate_chain = certificate_chain + self._server_host_override = server_host_override def _on_write_event(self, operation_id, event, rpc_state): if event.write_accepted: @@ -327,7 +331,8 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated): with self._condition: self._completion_queue = _low.CompletionQueue() self._channel = _low.Channel( - '%s:%d' % (self._host, self._port), self._client_credentials) + '%s:%d' % (self._host, self._port), self._client_credentials, + server_host_override=self._server_host_override) return self def _stop(self): @@ -382,121 +387,3 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated): else: # NOTE(nathaniel): All other categories are treated as cancellation. self._cancel(ticket.operation_id) - - -class _ActivatedRearLink(ticket_interfaces.RearLink, activated.Activated): - - def __init__( - self, host, port, request_serializers, response_deserializers, secure, - root_certificates, private_key, certificate_chain): - self._host = host - self._port = port - self._request_serializers = request_serializers - self._response_deserializers = response_deserializers - self._secure = secure - self._root_certificates = root_certificates - self._private_key = private_key - self._certificate_chain = certificate_chain - - self._lock = threading.Lock() - self._pool = None - self._rear_link = None - self._fore_link = null.NULL_FORE_LINK - - def join_fore_link(self, fore_link): - with self._lock: - self._fore_link = null.NULL_FORE_LINK if fore_link is None else fore_link - if self._rear_link is not None: - self._rear_link.join_fore_link(self._fore_link) - - def _start(self): - with self._lock: - self._pool = logging_pool.pool(_THREAD_POOL_SIZE) - self._rear_link = RearLink( - self._host, self._port, self._pool, self._request_serializers, - self._response_deserializers, self._secure, self._root_certificates, - self._private_key, self._certificate_chain) - self._rear_link.join_fore_link(self._fore_link) - self._rear_link.start() - return self - - def _stop(self): - with self._lock: - self._rear_link.stop() - self._rear_link = None - self._pool.shutdown(wait=True) - self._pool = None - - def __enter__(self): - return self._start() - - def __exit__(self, exc_type, exc_val, exc_tb): - self._stop() - return False - - def start(self): - return self._start() - - def stop(self): - self._stop() - - def accept_front_to_back_ticket(self, ticket): - with self._lock: - if self._rear_link is not None: - self._rear_link.accept_front_to_back_ticket(ticket) - - -# TODO(issue 726): reconcile these two creation functions. -def activated_rear_link( - host, port, request_serializers, response_deserializers): - """Creates a RearLink that is also an activated.Activated. - - The returned object is only valid for use between calls to its start and stop - methods (or in context when used as a context manager). - - Args: - host: The host to which to connect for RPC service. - port: The port to which to connect for RPC service. - request_serializers: A dictionary from RPC method name to request object - serializer behavior. - response_deserializers: A dictionary from RPC method name to response - object deserializer behavior. - secure: A boolean indicating whether or not to use a secure connection. - root_certificates: The PEM-encoded root certificates or None to ask for - them to be retrieved from a default location. - private_key: The PEM-encoded private key to use or None if no private key - should be used. - certificate_chain: The PEM-encoded certificate chain to use or None if no - certificate chain should be used. - """ - return _ActivatedRearLink( - host, port, request_serializers, response_deserializers, False, None, - None, None) - - - -def secure_activated_rear_link( - host, port, request_serializers, response_deserializers, root_certificates, - private_key, certificate_chain): - """Creates a RearLink that is also an activated.Activated. - - The returned object is only valid for use between calls to its start and stop - methods (or in context when used as a context manager). - - Args: - host: The host to which to connect for RPC service. - port: The port to which to connect for RPC service. - request_serializers: A dictionary from RPC method name to request object - serializer behavior. - response_deserializers: A dictionary from RPC method name to response - object deserializer behavior. - root_certificates: The PEM-encoded root certificates or None to ask for - them to be retrieved from a default location. - private_key: The PEM-encoded private key to use or None if no private key - should be used. - certificate_chain: The PEM-encoded certificate chain to use or None if no - certificate chain should be used. - """ - return _ActivatedRearLink( - host, port, request_serializers, response_deserializers, True, - root_certificates, private_key, certificate_chain) diff --git a/src/python/src/grpc/early_adopter/_assembly_utilities.py b/src/python/src/grpc/early_adopter/_face_utilities.py similarity index 76% rename from src/python/src/grpc/early_adopter/_assembly_utilities.py rename to src/python/src/grpc/early_adopter/_face_utilities.py index facfc2bf0e647a6fa581da08caeb89e4b217a72a..2cf576018d4cf521db7ad78555b35b78d19a234e 100644 --- a/src/python/src/grpc/early_adopter/_assembly_utilities.py +++ b/src/python/src/grpc/early_adopter/_face_utilities.py @@ -30,23 +30,20 @@ import abc import collections -# assembly_interfaces is referenced from specification in this module. -from grpc.framework.assembly import interfaces as assembly_interfaces # pylint: disable=unused-import -from grpc.framework.assembly import utilities as assembly_utilities +# face_interfaces is referenced from specification in this module. +from grpc.framework.common import cardinality +from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import +from grpc.framework.face import utilities as face_utilities from grpc.early_adopter import _reexport from grpc.early_adopter import interfaces -# TODO(issue 726): Kill the "implementations" attribute of this in favor -# of the same-information-less-bogusly-represented "cardinalities". class InvocationBreakdown(object): """An intermediate representation of invocation-side views of RPC methods. Attributes: cardinalities: A dictionary from RPC method name to interfaces.Cardinality value. - implementations: A dictionary from RPC method name to - assembly_interfaces.MethodImplementation describing the method. request_serializers: A dictionary from RPC method name to callable behavior to be used serializing request values for the RPC. response_deserializers: A dictionary from RPC method name to callable @@ -59,8 +56,7 @@ class _EasyInvocationBreakdown( InvocationBreakdown, collections.namedtuple( '_EasyInvocationBreakdown', - ('cardinalities', 'implementations', 'request_serializers', - 'response_deserializers'))): + ('cardinalities', 'request_serializers', 'response_deserializers'))): pass @@ -68,8 +64,8 @@ class ServiceBreakdown(object): """An intermediate representation of service-side views of RPC methods. Attributes: - implementations: A dictionary from RPC method name - assembly_interfaces.MethodImplementation implementing the RPC method. + implementations: A dictionary from RPC method name to + face_interfaces.MethodImplementation implementing the RPC method. request_deserializers: A dictionary from RPC method name to callable behavior to be used deserializing request values for the RPC. response_serializers: A dictionary from RPC method name to callable @@ -97,25 +93,14 @@ def break_down_invocation(method_descriptions): An InvocationBreakdown corresponding to the given method descriptions. """ cardinalities = {} - implementations = {} request_serializers = {} response_deserializers = {} for name, method_description in method_descriptions.iteritems(): - cardinality = method_description.cardinality() - cardinalities[name] = cardinality - if cardinality is interfaces.Cardinality.UNARY_UNARY: - implementations[name] = assembly_utilities.unary_unary_inline(None) - elif cardinality is interfaces.Cardinality.UNARY_STREAM: - implementations[name] = assembly_utilities.unary_stream_inline(None) - elif cardinality is interfaces.Cardinality.STREAM_UNARY: - implementations[name] = assembly_utilities.stream_unary_inline(None) - elif cardinality is interfaces.Cardinality.STREAM_STREAM: - implementations[name] = assembly_utilities.stream_stream_inline(None) + cardinalities[name] = method_description.cardinality() request_serializers[name] = method_description.serialize_request response_deserializers[name] = method_description.deserialize_response return _EasyInvocationBreakdown( - cardinalities, implementations, request_serializers, - response_deserializers) + cardinalities, request_serializers, response_deserializers) def break_down_service(method_descriptions): @@ -139,28 +124,28 @@ def break_down_service(method_descriptions): service_behavior=method_description.service_unary_unary): return service_behavior( request, _reexport.rpc_context(face_rpc_context)) - implementations[name] = assembly_utilities.unary_unary_inline(service) + implementations[name] = face_utilities.unary_unary_inline(service) elif cardinality is interfaces.Cardinality.UNARY_STREAM: def service( request, face_rpc_context, service_behavior=method_description.service_unary_stream): return service_behavior( request, _reexport.rpc_context(face_rpc_context)) - implementations[name] = assembly_utilities.unary_stream_inline(service) + implementations[name] = face_utilities.unary_stream_inline(service) elif cardinality is interfaces.Cardinality.STREAM_UNARY: def service( request_iterator, face_rpc_context, service_behavior=method_description.service_stream_unary): return service_behavior( request_iterator, _reexport.rpc_context(face_rpc_context)) - implementations[name] = assembly_utilities.stream_unary_inline(service) + implementations[name] = face_utilities.stream_unary_inline(service) elif cardinality is interfaces.Cardinality.STREAM_STREAM: def service( request_iterator, face_rpc_context, service_behavior=method_description.service_stream_stream): return service_behavior( request_iterator, _reexport.rpc_context(face_rpc_context)) - implementations[name] = assembly_utilities.stream_stream_inline(service) + implementations[name] = face_utilities.stream_stream_inline(service) request_deserializers[name] = method_description.deserialize_request response_serializers[name] = method_description.serialize_response diff --git a/src/python/src/grpc/early_adopter/_reexport.py b/src/python/src/grpc/early_adopter/_reexport.py index 35f4e85a7287bf94d88be6230a829d953a5a4ea0..f3416028e8c6fa8bb7fa64df8589b4ef52e97696 100644 --- a/src/python/src/grpc/early_adopter/_reexport.py +++ b/src/python/src/grpc/early_adopter/_reexport.py @@ -27,12 +27,20 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from grpc.framework.common import cardinality from grpc.framework.face import exceptions as face_exceptions from grpc.framework.face import interfaces as face_interfaces from grpc.framework.foundation import future from grpc.early_adopter import exceptions from grpc.early_adopter import interfaces +_EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY = { + interfaces.Cardinality.UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, + interfaces.Cardinality.UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, + interfaces.Cardinality.STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, + interfaces.Cardinality.STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, +} + _ABORTION_REEXPORT = { face_interfaces.Abortion.CANCELLED: interfaces.Abortion.CANCELLED, face_interfaces.Abortion.EXPIRED: interfaces.Abortion.EXPIRED, @@ -142,71 +150,49 @@ class _RpcContext(interfaces.RpcContext): class _UnaryUnarySyncAsync(interfaces.UnaryUnarySyncAsync): - def __init__(self, face_unary_unary_sync_async): - self._underlying = face_unary_unary_sync_async + def __init__(self, face_unary_unary_multi_callable): + self._underlying = face_unary_unary_multi_callable def __call__(self, request, timeout): return _call_reexporting_errors( self._underlying, request, timeout) def async(self, request, timeout): - return _ReexportedFuture(self._underlying.async(request, timeout)) + return _ReexportedFuture(self._underlying.future(request, timeout)) class _StreamUnarySyncAsync(interfaces.StreamUnarySyncAsync): - def __init__(self, face_stream_unary_sync_async): - self._underlying = face_stream_unary_sync_async + def __init__(self, face_stream_unary_multi_callable): + self._underlying = face_stream_unary_multi_callable def __call__(self, request_iterator, timeout): return _call_reexporting_errors( self._underlying, request_iterator, timeout) def async(self, request_iterator, timeout): - return _ReexportedFuture(self._underlying.async(request_iterator, timeout)) - + return _ReexportedFuture(self._underlying.future(request_iterator, timeout)) -class _Stub(interfaces.Stub): - def __init__(self, assembly_stub, cardinalities): - self._assembly_stub = assembly_stub - self._cardinalities = cardinalities - - def __enter__(self): - self._assembly_stub.__enter__() - return self +def common_cardinalities(early_adopter_cardinalities): + common_cardinalities = {} + for name, early_adopter_cardinality in early_adopter_cardinalities.iteritems(): + common_cardinalities[name] = _EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY[ + early_adopter_cardinality] + return common_cardinalities - def __exit__(self, exc_type, exc_val, exc_tb): - self._assembly_stub.__exit__(exc_type, exc_val, exc_tb) - return False - - def __getattr__(self, attr): - underlying_attr = self._assembly_stub.__getattr__(attr) - cardinality = self._cardinalities.get(attr) - # TODO(nathaniel): unify this trick with its other occurrence in the code. - if cardinality is None: - for name, cardinality in self._cardinalities.iteritems(): - last_slash_index = name.rfind('/') - if 0 <= last_slash_index and name[last_slash_index + 1:] == attr: - break - else: - raise AttributeError(attr) - if cardinality is interfaces.Cardinality.UNARY_UNARY: - return _UnaryUnarySyncAsync(underlying_attr) - elif cardinality is interfaces.Cardinality.UNARY_STREAM: - return lambda request, timeout: _CancellableIterator( - underlying_attr(request, timeout)) - elif cardinality is interfaces.Cardinality.STREAM_UNARY: - return _StreamUnarySyncAsync(underlying_attr) - elif cardinality is interfaces.Cardinality.STREAM_STREAM: - return lambda request_iterator, timeout: _CancellableIterator( - underlying_attr(request_iterator, timeout)) - else: - raise AttributeError(attr) def rpc_context(face_rpc_context): return _RpcContext(face_rpc_context) -def stub(assembly_stub, cardinalities): - return _Stub(assembly_stub, cardinalities) +def cancellable_iterator(face_cancellable_iterator): + return _CancellableIterator(face_cancellable_iterator) + + +def unary_unary_sync_async(face_unary_unary_multi_callable): + return _UnaryUnarySyncAsync(face_unary_unary_multi_callable) + + +def stream_unary_sync_async(face_stream_unary_multi_callable): + return _StreamUnarySyncAsync(face_stream_unary_multi_callable) diff --git a/src/python/src/grpc/early_adopter/implementations.py b/src/python/src/grpc/early_adopter/implementations.py index 619595862400bd731b52b915704ae3321dd01447..1c02f9e4d63f510a109f00e4a66f5e98f69ca7a3 100644 --- a/src/python/src/grpc/early_adopter/implementations.py +++ b/src/python/src/grpc/early_adopter/implementations.py @@ -33,10 +33,16 @@ import threading from grpc._adapter import fore as _fore from grpc._adapter import rear as _rear -from grpc.early_adopter import _assembly_utilities +from grpc.early_adopter import _face_utilities from grpc.early_adopter import _reexport from grpc.early_adopter import interfaces -from grpc.framework.assembly import implementations as _assembly_implementations +from grpc.framework.base import util as _base_utilities +from grpc.framework.base.packets import implementations as _tickets_implementations +from grpc.framework.face import implementations as _face_implementations +from grpc.framework.foundation import logging_pool + +_THREAD_POOL_SIZE = 80 +_ONE_DAY_IN_SECONDS = 24 * 60 * 60 class _Server(interfaces.Server): @@ -50,30 +56,39 @@ class _Server(interfaces.Server): else: self._key_chain_pairs = ((private_key, certificate_chain),) + self._pool = None + self._back = None self._fore_link = None - self._server = None def _start(self): with self._lock: - if self._server is None: - self._fore_link = _fore.activated_fore_link( - self._port, self._breakdown.request_deserializers, + if self._pool is None: + self._pool = logging_pool.pool(_THREAD_POOL_SIZE) + servicer = _face_implementations.servicer( + self._pool, self._breakdown.implementations, None) + self._back = _tickets_implementations.back( + servicer, self._pool, self._pool, self._pool, _ONE_DAY_IN_SECONDS, + _ONE_DAY_IN_SECONDS) + self._fore_link = _fore.ForeLink( + self._pool, self._breakdown.request_deserializers, self._breakdown.response_serializers, None, self._key_chain_pairs) - - self._server = _assembly_implementations.assemble_service( - self._breakdown.implementations, self._fore_link) - self._server.start() + self._back.join_fore_link(self._fore_link) + self._fore_link.join_rear_link(self._back) + self._fore_link.start() else: raise ValueError('Server currently running!') def _stop(self): with self._lock: - if self._server is None: + if self._pool is None: raise ValueError('Server not running!') else: - self._server.stop() - self._server = None + self._fore_link.stop() + _base_utilities.wait_for_idle(self._back) + self._pool.shutdown(wait=True) self._fore_link = None + self._back = None + self._pool = None def __enter__(self): self._start() @@ -93,14 +108,105 @@ class _Server(interfaces.Server): with self._lock: return self._fore_link.port() -def _build_stub(breakdown, activated_rear_link): - assembly_stub = _assembly_implementations.assemble_dynamic_inline_stub( - breakdown.implementations, activated_rear_link) - return _reexport.stub(assembly_stub, breakdown.cardinalities) + +class _Stub(interfaces.Stub): + + def __init__( + self, breakdown, host, port, secure, root_certificates, private_key, + certificate_chain, server_host_override=None): + self._lock = threading.Lock() + self._breakdown = breakdown + self._host = host + self._port = port + self._secure = secure + self._root_certificates = root_certificates + self._private_key = private_key + self._certificate_chain = certificate_chain + self._server_host_override = server_host_override + + self._pool = None + self._front = None + self._rear_link = None + self._understub = None + + def __enter__(self): + with self._lock: + if self._pool is None: + self._pool = logging_pool.pool(_THREAD_POOL_SIZE) + self._front = _tickets_implementations.front( + self._pool, self._pool, self._pool) + self._rear_link = _rear.RearLink( + self._host, self._port, self._pool, + self._breakdown.request_serializers, + self._breakdown.response_deserializers, self._secure, + self._root_certificates, self._private_key, self._certificate_chain, + server_host_override=self._server_host_override) + self._front.join_rear_link(self._rear_link) + self._rear_link.join_fore_link(self._front) + self._rear_link.start() + self._understub = _face_implementations.dynamic_stub( + _reexport.common_cardinalities(self._breakdown.cardinalities), + self._front, self._pool, '') + else: + raise ValueError('Tried to __enter__ already-__enter__ed Stub!') + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + with self._lock: + if self._pool is None: + raise ValueError('Tried to __exit__ non-__enter__ed Stub!') + else: + self._rear_link.stop() + _base_utilities.wait_for_idle(self._front) + self._pool.shutdown(wait=True) + self._rear_link = None + self._front = None + self._pool = None + self._understub = None + return False + + def __getattr__(self, attr): + with self._lock: + if self._pool is None: + raise ValueError('Tried to __getattr__ non-__enter__ed Stub!') + else: + underlying_attr = getattr(self._understub, attr, None) + method_cardinality = self._breakdown.cardinalities.get(attr) + # TODO(nathaniel): Eliminate this trick. + if underlying_attr is None: + for method_name, method_cardinality in self._breakdown.cardinalities.iteritems(): + last_slash_index = method_name.rfind('/') + if 0 <= last_slash_index and method_name[last_slash_index + 1:] == attr: + underlying_attr = getattr(self._understub, method_name) + break + else: + raise AttributeError(attr) + if method_cardinality is interfaces.Cardinality.UNARY_UNARY: + return _reexport.unary_unary_sync_async(underlying_attr) + elif method_cardinality is interfaces.Cardinality.UNARY_STREAM: + return lambda request, timeout: _reexport.cancellable_iterator( + underlying_attr(request, timeout)) + elif method_cardinality is interfaces.Cardinality.STREAM_UNARY: + return _reexport.stream_unary_sync_async(underlying_attr) + elif method_cardinality is interfaces.Cardinality.STREAM_STREAM: + return lambda request_iterator, timeout: ( + _reexport.cancellable_iterator(underlying_attr( + request_iterator, timeout))) + else: + raise AttributeError(attr) + + +def _build_stub( + methods, host, port, secure, root_certificates, private_key, + certificate_chain, server_host_override=None): + breakdown = _face_utilities.break_down_invocation(methods) + return _Stub( + breakdown, host, port, secure, root_certificates, private_key, + certificate_chain, server_host_override=server_host_override) def _build_server(methods, port, private_key, certificate_chain): - breakdown = _assembly_utilities.break_down_service(methods) + breakdown = _face_utilities.break_down_service(methods) return _Server(breakdown, port, private_key, certificate_chain) @@ -117,15 +223,12 @@ def insecure_stub(methods, host, port): Returns: An interfaces.Stub affording RPC invocation. """ - breakdown = _assembly_utilities.break_down_invocation(methods) - activated_rear_link = _rear.activated_rear_link( - host, port, breakdown.request_serializers, - breakdown.response_deserializers) - return _build_stub(breakdown, activated_rear_link) + return _build_stub(methods, host, port, False, None, None, None) def secure_stub( - methods, host, port, root_certificates, private_key, certificate_chain): + methods, host, port, root_certificates, private_key, certificate_chain, + server_host_override=None): """Constructs an insecure interfaces.Stub. Args: @@ -140,16 +243,15 @@ def secure_stub( should be used. certificate_chain: The PEM-encoded certificate chain to use or None if no certificate chain should be used. + server_host_override: (For testing only) the target name used for SSL + host name checking. Returns: An interfaces.Stub affording RPC invocation. """ - breakdown = _assembly_utilities.break_down_invocation(methods) - activated_rear_link = _rear.secure_activated_rear_link( - host, port, breakdown.request_serializers, - breakdown.response_deserializers, root_certificates, private_key, - certificate_chain) - return _build_stub(breakdown, activated_rear_link) + return _build_stub( + methods, host, port, True, root_certificates, private_key, + certificate_chain, server_host_override=server_host_override) def insecure_server(methods, port): diff --git a/src/python/src/grpc/framework/assembly/implementations.py b/src/python/src/grpc/framework/assembly/implementations.py deleted file mode 100644 index f7166ed99d1178bc1af8dfbf95b904d906ba4586..0000000000000000000000000000000000000000 --- a/src/python/src/grpc/framework/assembly/implementations.py +++ /dev/null @@ -1,317 +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. - -"""Implementations for assembling RPC framework values.""" - -import threading - -# tickets_interfaces, face_interfaces, and activated are referenced from -# specification in this module. -from grpc.framework.assembly import interfaces -from grpc.framework.base import util as base_utilities -from grpc.framework.base.packets import implementations as tickets_implementations -from grpc.framework.base.packets import interfaces as tickets_interfaces # pylint: disable=unused-import -from grpc.framework.common import cardinality -from grpc.framework.common import style -from grpc.framework.face import implementations as face_implementations -from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import -from grpc.framework.face import utilities as face_utilities -from grpc.framework.foundation import activated # pylint: disable=unused-import -from grpc.framework.foundation import logging_pool - -_ONE_DAY_IN_SECONDS = 60 * 60 * 24 -_THREAD_POOL_SIZE = 100 - - -class _FaceStub(object): - - def __init__(self, rear_link): - self._rear_link = rear_link - self._lock = threading.Lock() - self._pool = None - self._front = None - self._under_stub = None - - def __enter__(self): - with self._lock: - self._pool = logging_pool.pool(_THREAD_POOL_SIZE) - self._front = tickets_implementations.front( - self._pool, self._pool, self._pool) - self._rear_link.start() - self._rear_link.join_fore_link(self._front) - self._front.join_rear_link(self._rear_link) - self._under_stub = face_implementations.stub(self._front, self._pool) - - def __exit__(self, exc_type, exc_val, exc_tb): - with self._lock: - self._under_stub = None - self._rear_link.stop() - base_utilities.wait_for_idle(self._front) - self._front = None - self._pool.shutdown(wait=True) - self._pool = None - return False - - def __getattr__(self, attr): - with self._lock: - if self._under_stub is None: - raise ValueError('Called out of context!') - else: - return getattr(self._under_stub, attr) - - -def _behaviors(implementations, front, pool): - behaviors = {} - stub = face_implementations.stub(front, pool) - for name, implementation in implementations.iteritems(): - if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: - behaviors[name] = stub.unary_unary_sync_async(name) - elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: - behaviors[name] = lambda request, context, bound_name=name: ( - stub.inline_value_in_stream_out(bound_name, request, context)) - elif implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: - behaviors[name] = stub.stream_unary_sync_async(name) - elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: - behaviors[name] = lambda request_iterator, context, bound_name=name: ( - stub.inline_stream_in_stream_out( - bound_name, request_iterator, context)) - return behaviors - - -class _DynamicInlineStub(object): - - def __init__(self, implementations, rear_link): - self._implementations = implementations - self._rear_link = rear_link - self._lock = threading.Lock() - self._pool = None - self._front = None - self._behaviors = None - - def __enter__(self): - with self._lock: - self._pool = logging_pool.pool(_THREAD_POOL_SIZE) - self._front = tickets_implementations.front( - self._pool, self._pool, self._pool) - self._rear_link.start() - self._rear_link.join_fore_link(self._front) - self._front.join_rear_link(self._rear_link) - self._behaviors = _behaviors( - self._implementations, self._front, self._pool) - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - with self._lock: - self._behaviors = None - self._rear_link.stop() - base_utilities.wait_for_idle(self._front) - self._front = None - self._pool.shutdown(wait=True) - self._pool = None - return False - - def __getattr__(self, attr): - with self._lock: - behavior = self._behaviors.get(attr) - if behavior is None: - for name, behavior in self._behaviors.iteritems(): - last_slash_index = name.rfind('/') - if 0 <= last_slash_index and name[last_slash_index + 1:] == attr: - return behavior - else: - raise AttributeError( - '_DynamicInlineStub instance has no attribute "%s"!' % attr) - else: - return behavior - - -def _servicer(implementations, pool): - inline_value_in_value_out_methods = {} - inline_value_in_stream_out_methods = {} - inline_stream_in_value_out_methods = {} - inline_stream_in_stream_out_methods = {} - event_value_in_value_out_methods = {} - event_value_in_stream_out_methods = {} - event_stream_in_value_out_methods = {} - event_stream_in_stream_out_methods = {} - - for name, implementation in implementations.iteritems(): - if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: - if implementation.style is style.Service.INLINE: - inline_value_in_value_out_methods[name] = ( - face_utilities.inline_unary_unary_method(implementation.unary_unary_inline)) - elif implementation.style is style.Service.EVENT: - event_value_in_value_out_methods[name] = ( - face_utilities.event_unary_unary_method(implementation.unary_unary_event)) - elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: - if implementation.style is style.Service.INLINE: - inline_value_in_stream_out_methods[name] = ( - face_utilities.inline_unary_stream_method(implementation.unary_stream_inline)) - elif implementation.style is style.Service.EVENT: - event_value_in_stream_out_methods[name] = ( - face_utilities.event_unary_stream_method(implementation.unary_stream_event)) - if implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: - if implementation.style is style.Service.INLINE: - inline_stream_in_value_out_methods[name] = ( - face_utilities.inline_stream_unary_method(implementation.stream_unary_inline)) - elif implementation.style is style.Service.EVENT: - event_stream_in_value_out_methods[name] = ( - face_utilities.event_stream_unary_method(implementation.stream_unary_event)) - elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: - if implementation.style is style.Service.INLINE: - inline_stream_in_stream_out_methods[name] = ( - face_utilities.inline_stream_stream_method(implementation.stream_stream_inline)) - elif implementation.style is style.Service.EVENT: - event_stream_in_stream_out_methods[name] = ( - face_utilities.event_stream_stream_method(implementation.stream_stream_event)) - - return face_implementations.servicer( - pool, - inline_value_in_value_out_methods=inline_value_in_value_out_methods, - inline_value_in_stream_out_methods=inline_value_in_stream_out_methods, - inline_stream_in_value_out_methods=inline_stream_in_value_out_methods, - inline_stream_in_stream_out_methods=inline_stream_in_stream_out_methods, - event_value_in_value_out_methods=event_value_in_value_out_methods, - event_value_in_stream_out_methods=event_value_in_stream_out_methods, - event_stream_in_value_out_methods=event_stream_in_value_out_methods, - event_stream_in_stream_out_methods=event_stream_in_stream_out_methods) - - -class _ServiceAssembly(interfaces.Server): - - def __init__(self, implementations, fore_link): - self._implementations = implementations - self._fore_link = fore_link - self._lock = threading.Lock() - self._pool = None - self._back = None - - def _start(self): - with self._lock: - self._pool = logging_pool.pool(_THREAD_POOL_SIZE) - servicer = _servicer(self._implementations, self._pool) - self._back = tickets_implementations.back( - servicer, self._pool, self._pool, self._pool, _ONE_DAY_IN_SECONDS, - _ONE_DAY_IN_SECONDS) - self._fore_link.start() - self._fore_link.join_rear_link(self._back) - self._back.join_fore_link(self._fore_link) - - def _stop(self): - with self._lock: - self._fore_link.stop() - base_utilities.wait_for_idle(self._back) - self._back = None - self._pool.shutdown(wait=True) - self._pool = None - - def __enter__(self): - self._start() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self._stop() - return False - - def start(self): - return self._start() - - def stop(self): - self._stop() - - def port(self): - with self._lock: - return self._fore_link.port() - - -def assemble_face_stub(activated_rear_link): - """Assembles a face_interfaces.Stub. - - The returned object is a context manager and may only be used in context to - invoke RPCs. - - Args: - activated_rear_link: An object that is both a tickets_interfaces.RearLink - and an activated.Activated. The object should be in the inactive state - when passed to this method. - - Returns: - A face_interfaces.Stub on which, in context, RPCs can be invoked. - """ - return _FaceStub(activated_rear_link) - - -def assemble_dynamic_inline_stub(implementations, activated_rear_link): - """Assembles a stub with method names for attributes. - - The returned object is a context manager and may only be used in context to - invoke RPCs. - - The returned object, when used in context, will respond to attribute access - as follows: if the requested attribute is the name of a unary-unary RPC - method, the value of the attribute will be a - face_interfaces.UnaryUnarySyncAsync with which to invoke the RPC method. If - the requested attribute is the name of a unary-stream RPC method, the value - of the attribute will be a callable with the semantics of - face_interfaces.Stub.inline_value_in_stream_out, minus the "name" parameter, - with which to invoke the RPC method. If the requested attribute is the name - of a stream-unary RPC method, the value of the attribute will be a - face_interfaces.StreamUnarySyncAsync with which to invoke the RPC method. If - the requested attribute is the name of a stream-stream RPC method, the value - of the attribute will be a callable with the semantics of - face_interfaces.Stub.inline_stream_in_stream_out, minus the "name" parameter, - with which to invoke the RPC method. - - Args: - implementations: A dictionary from RPC method name to - interfaces.MethodImplementation. - activated_rear_link: An object that is both a tickets_interfaces.RearLink - and an activated.Activated. The object should be in the inactive state - when passed to this method. - - Returns: - A stub on which, in context, RPCs can be invoked. - """ - return _DynamicInlineStub(implementations, activated_rear_link) - - -def assemble_service(implementations, activated_fore_link): - """Assembles the service-side of the RPC Framework stack. - - Args: - implementations: A dictionary from RPC method name to - interfaces.MethodImplementation. - activated_fore_link: An object that is both a tickets_interfaces.ForeLink - and an activated.Activated. The object should be in the inactive state - when passed to this method. - - Returns: - An interfaces.Server encapsulating RPC service. - """ - return _ServiceAssembly(implementations, activated_fore_link) diff --git a/src/python/src/grpc/framework/assembly/implementations_test.py b/src/python/src/grpc/framework/assembly/implementations_test.py deleted file mode 100644 index 74dc02ed83ddba887111be86668e193f8c1ea638..0000000000000000000000000000000000000000 --- a/src/python/src/grpc/framework/assembly/implementations_test.py +++ /dev/null @@ -1,284 +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. - -# TODO(nathaniel): Expand this test coverage. - -"""Test of the GRPC-backed ForeLink and RearLink.""" - -import threading -import unittest - -from grpc.framework.assembly import implementations -from grpc.framework.assembly import utilities -from grpc.framework.base import interfaces -from grpc.framework.base.packets import packets as tickets -from grpc.framework.base.packets import interfaces as tickets_interfaces -from grpc.framework.base.packets import null -from grpc.framework.foundation import logging_pool -from grpc._junkdrawer import math_pb2 - -DIV = 'Div' -DIV_MANY = 'DivMany' -FIB = 'Fib' -SUM = 'Sum' - -def _fibbonacci(limit): - left, right = 0, 1 - for _ in xrange(limit): - yield left - left, right = right, left + right - - -def _div(request, unused_context): - return math_pb2.DivReply( - quotient=request.dividend / request.divisor, - remainder=request.dividend % request.divisor) - - -def _div_many(request_iterator, unused_context): - for request in request_iterator: - yield math_pb2.DivReply( - quotient=request.dividend / request.divisor, - remainder=request.dividend % request.divisor) - - -def _fib(request, unused_context): - for number in _fibbonacci(request.limit): - yield math_pb2.Num(num=number) - - -def _sum(request_iterator, unused_context): - accumulation = 0 - for request in request_iterator: - accumulation += request.num - return math_pb2.Num(num=accumulation) - - -_IMPLEMENTATIONS = { - DIV: utilities.unary_unary_inline(_div), - DIV_MANY: utilities.stream_stream_inline(_div_many), - FIB: utilities.unary_stream_inline(_fib), - SUM: utilities.stream_unary_inline(_sum), -} - -_TIMEOUT = 10 - - -class PipeLink(tickets_interfaces.ForeLink, tickets_interfaces.RearLink): - - def __init__(self): - self._fore_lock = threading.Lock() - self._fore_link = null.NULL_FORE_LINK - self._rear_lock = threading.Lock() - self._rear_link = null.NULL_REAR_LINK - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - return False - - def start(self): - pass - - def stop(self): - pass - - def accept_back_to_front_ticket(self, ticket): - with self._fore_lock: - self._fore_link.accept_back_to_front_ticket(ticket) - - def join_rear_link(self, rear_link): - with self._rear_lock: - self._rear_link = null.NULL_REAR_LINK if rear_link is None else rear_link - - def accept_front_to_back_ticket(self, ticket): - with self._rear_lock: - self._rear_link.accept_front_to_back_ticket(ticket) - - def join_fore_link(self, fore_link): - with self._fore_lock: - self._fore_link = null.NULL_FORE_LINK if fore_link is None else fore_link - - -class FaceStubTest(unittest.TestCase): - - def testUnaryUnary(self): - divisor = 7 - dividend = 13 - expected_quotient = 1 - expected_remainder = 6 - pipe = PipeLink() - service = implementations.assemble_service(_IMPLEMENTATIONS, pipe) - face_stub = implementations.assemble_face_stub(pipe) - - service.start() - try: - with face_stub: - response = face_stub.blocking_value_in_value_out( - DIV, math_pb2.DivArgs(divisor=divisor, dividend=dividend), - _TIMEOUT) - self.assertEqual(expected_quotient, response.quotient) - self.assertEqual(expected_remainder, response.remainder) - finally: - service.stop() - - def testUnaryStream(self): - stream_length = 29 - pipe = PipeLink() - service = implementations.assemble_service(_IMPLEMENTATIONS, pipe) - face_stub = implementations.assemble_face_stub(pipe) - - with service, face_stub: - responses = list( - face_stub.inline_value_in_stream_out( - FIB, math_pb2.FibArgs(limit=stream_length), _TIMEOUT)) - numbers = [response.num for response in responses] - for early, middle, later in zip(numbers, numbers[1:], numbers[2:]): - self.assertEqual(early + middle, later) - - def testStreamUnary(self): - stream_length = 13 - pipe = PipeLink() - service = implementations.assemble_service(_IMPLEMENTATIONS, pipe) - face_stub = implementations.assemble_face_stub(pipe) - - with service, face_stub: - sync_async = face_stub.stream_unary_sync_async(SUM) - response_future = sync_async.async( - (math_pb2.Num(num=index) for index in range(stream_length)), - _TIMEOUT) - self.assertEqual( - (stream_length * (stream_length - 1)) / 2, - response_future.result().num) - - def testStreamStream(self): - stream_length = 17 - divisor_offset = 7 - dividend_offset = 17 - pipe = PipeLink() - service = implementations.assemble_service(_IMPLEMENTATIONS, pipe) - face_stub = implementations.assemble_face_stub(pipe) - - with service, face_stub: - response_iterator = face_stub.inline_stream_in_stream_out( - DIV_MANY, - (math_pb2.DivArgs( - divisor=divisor_offset + index, - dividend=dividend_offset + index) - for index in range(stream_length)), - _TIMEOUT) - for index, response in enumerate(response_iterator): - self.assertEqual( - (dividend_offset + index) / (divisor_offset + index), - response.quotient) - self.assertEqual( - (dividend_offset + index) % (divisor_offset + index), - response.remainder) - self.assertEqual(stream_length, index + 1) - - -class DynamicInlineStubTest(unittest.TestCase): - - def testUnaryUnary(self): - divisor = 59 - dividend = 973 - expected_quotient = dividend / divisor - expected_remainder = dividend % divisor - pipe = PipeLink() - service = implementations.assemble_service(_IMPLEMENTATIONS, pipe) - dynamic_stub = implementations.assemble_dynamic_inline_stub( - _IMPLEMENTATIONS, pipe) - - service.start() - with dynamic_stub: - response = dynamic_stub.Div( - math_pb2.DivArgs(divisor=divisor, dividend=dividend), _TIMEOUT) - self.assertEqual(expected_quotient, response.quotient) - self.assertEqual(expected_remainder, response.remainder) - service.stop() - - def testUnaryStream(self): - stream_length = 43 - pipe = PipeLink() - service = implementations.assemble_service(_IMPLEMENTATIONS, pipe) - dynamic_stub = implementations.assemble_dynamic_inline_stub( - _IMPLEMENTATIONS, pipe) - - with service, dynamic_stub: - response_iterator = dynamic_stub.Fib( - math_pb2.FibArgs(limit=stream_length), _TIMEOUT) - numbers = tuple(response.num for response in response_iterator) - for early, middle, later in zip(numbers, numbers[:1], numbers[:2]): - self.assertEqual(early + middle, later) - self.assertEqual(stream_length, len(numbers)) - - def testStreamUnary(self): - stream_length = 127 - pipe = PipeLink() - service = implementations.assemble_service(_IMPLEMENTATIONS, pipe) - dynamic_stub = implementations.assemble_dynamic_inline_stub( - _IMPLEMENTATIONS, pipe) - - with service, dynamic_stub: - response_future = dynamic_stub.Sum.async( - (math_pb2.Num(num=index) for index in range(stream_length)), - _TIMEOUT) - self.assertEqual( - (stream_length * (stream_length - 1)) / 2, - response_future.result().num) - - def testStreamStream(self): - stream_length = 179 - divisor_offset = 71 - dividend_offset = 1763 - pipe = PipeLink() - service = implementations.assemble_service(_IMPLEMENTATIONS, pipe) - dynamic_stub = implementations.assemble_dynamic_inline_stub( - _IMPLEMENTATIONS, pipe) - - with service, dynamic_stub: - response_iterator = dynamic_stub.DivMany( - (math_pb2.DivArgs( - divisor=divisor_offset + index, - dividend=dividend_offset + index) - for index in range(stream_length)), - _TIMEOUT) - for index, response in enumerate(response_iterator): - self.assertEqual( - (dividend_offset + index) / (divisor_offset + index), - response.quotient) - self.assertEqual( - (dividend_offset + index) % (divisor_offset + index), - response.remainder) - self.assertEqual(stream_length, index + 1) - - -if __name__ == '__main__': - unittest.main() diff --git a/src/python/src/grpc/framework/assembly/interfaces.py b/src/python/src/grpc/framework/assembly/interfaces.py deleted file mode 100644 index d1a6aad29e767e07f03795c6b3bc2f6abaab666e..0000000000000000000000000000000000000000 --- a/src/python/src/grpc/framework/assembly/interfaces.py +++ /dev/null @@ -1,114 +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. - -# TODO(nathaniel): The assembly layer only exists to smooth out wrinkles in -# the face layer. The two should be squashed together as soon as manageable. -"""Interfaces for assembling RPC Framework values.""" - -import abc - -# cardinality, style, and stream are referenced from specification in this -# module. -from grpc.framework.common import cardinality # pylint: disable=unused-import -from grpc.framework.common import style # pylint: disable=unused-import -from grpc.framework.foundation import activated -from grpc.framework.foundation import stream # pylint: disable=unused-import - - -class MethodImplementation(object): - """A sum type that describes an RPC method implementation. - - Attributes: - cardinality: A cardinality.Cardinality value. - style: A style.Service value. - unary_unary_inline: The implementation of the RPC method as a callable - value that takes a request value and a face_interfaces.RpcContext object - and returns a response value. Only non-None if cardinality is - cardinality.Cardinality.UNARY_UNARY and style is style.Service.INLINE. - unary_stream_inline: The implementation of the RPC method as a callable - value that takes a request value and a face_interfaces.RpcContext object - and returns an iterator of response values. Only non-None if cardinality - is cardinality.Cardinality.UNARY_STREAM and style is - style.Service.INLINE. - stream_unary_inline: The implementation of the RPC method as a callable - value that takes an iterator of request values and a - face_interfaces.RpcContext object and returns a response value. Only - non-None if cardinality is cardinality.Cardinality.STREAM_UNARY and style - is style.Service.INLINE. - stream_stream_inline: The implementation of the RPC method as a callable - value that takes an iterator of request values and a - face_interfaces.RpcContext object and returns an iterator of response - values. Only non-None if cardinality is - cardinality.Cardinality.STREAM_STREAM and style is style.Service.INLINE. - unary_unary_event: The implementation of the RPC method as a callable value - that takes a request value, a response callback to which to pass the - response value of the RPC, and a face_interfaces.RpcContext. Only - non-None if cardinality is cardinality.Cardinality.UNARY_UNARY and style - is style.Service.EVENT. - unary_stream_event: The implementation of the RPC method as a callable - value that takes a request value, a stream.Consumer to which to pass the - the response values of the RPC, and a face_interfaces.RpcContext. Only - non-None if cardinality is cardinality.Cardinality.UNARY_STREAM and style - is style.Service.EVENT. - stream_unary_event: The implementation of the RPC method as a callable - value that takes a response callback to which to pass the response value - of the RPC and a face_interfaces.RpcContext and returns a stream.Consumer - to which the request values of the RPC should be passed. Only non-None if - cardinality is cardinality.Cardinality.STREAM_UNARY and style is - style.Service.EVENT. - stream_stream_event: The implementation of the RPC method as a callable - value that takes a stream.Consumer to which to pass the response values - of the RPC and a face_interfaces.RpcContext and returns a stream.Consumer - to which the request values of the RPC should be passed. Only non-None if - cardinality is cardinality.Cardinality.STREAM_STREAM and style is - style.Service.EVENT. - """ - __metaclass__ = abc.ABCMeta - - -class Server(activated.Activated): - """The server interface. - - Aside from being able to be activated and deactivated, objects of this type - are able to report the port on which they are servicing RPCs. - """ - __metaclass__ = abc.ABCMeta - - # TODO(issue 726): This is an abstraction violation; not every Server is - # necessarily serving over a network at all. - @abc.abstractmethod - def port(self): - """Identifies the port on which this Server is servicing RPCs. - - This method may only be called while the server is active. - - Returns: - The number of the port on which this Server is servicing RPCs. - """ - raise NotImplementedError() diff --git a/src/python/src/grpc/framework/assembly/utilities.py b/src/python/src/grpc/framework/assembly/utilities.py deleted file mode 100644 index 80e7f59c03c5f8b49696f2fffefe2827b2803f86..0000000000000000000000000000000000000000 --- a/src/python/src/grpc/framework/assembly/utilities.py +++ /dev/null @@ -1,179 +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. - -"""Utilities for assembling RPC framework values.""" - -import collections - -from grpc.framework.assembly import interfaces -from grpc.framework.common import cardinality -from grpc.framework.common import style -from grpc.framework.face import interfaces as face_interfaces -from grpc.framework.foundation import stream - - -class _MethodImplementation( - interfaces.MethodImplementation, - collections.namedtuple( - '_MethodImplementation', - ['cardinality', 'style', 'unary_unary_inline', 'unary_stream_inline', - 'stream_unary_inline', 'stream_stream_inline', 'unary_unary_event', - 'unary_stream_event', 'stream_unary_event', 'stream_stream_event',])): - pass - - -def unary_unary_inline(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a unary-unary RPC method as a callable value - that takes a request value and a face_interfaces.RpcContext object and - returns a response value. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_UNARY, style.Service.INLINE, behavior, - None, None, None, None, None, None, None) - - -def unary_stream_inline(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a unary-stream RPC method as a callable - value that takes a request value and a face_interfaces.RpcContext object - and returns an iterator of response values. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_STREAM, style.Service.INLINE, None, - behavior, None, None, None, None, None, None) - - -def stream_unary_inline(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a stream-unary RPC method as a callable - value that takes an iterator of request values and a - face_interfaces.RpcContext object and returns a response value. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_UNARY, style.Service.INLINE, None, None, - behavior, None, None, None, None, None) - - -def stream_stream_inline(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a stream-stream RPC method as a callable - value that takes an iterator of request values and a - face_interfaces.RpcContext object and returns an iterator of response - values. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_STREAM, style.Service.INLINE, None, None, - None, behavior, None, None, None, None) - - -def unary_unary_event(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a unary-unary RPC method as a callable - value that takes a request value, a response callback to which to pass - the response value of the RPC, and a face_interfaces.RpcContext. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_UNARY, style.Service.EVENT, None, None, - None, None, behavior, None, None, None) - - -def unary_stream_event(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a unary-stream RPC method as a callable - value that takes a request value, a stream.Consumer to which to pass the - the response values of the RPC, and a face_interfaces.RpcContext. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_STREAM, style.Service.EVENT, None, None, - None, None, None, behavior, None, None) - - -def stream_unary_event(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a stream-unary RPC method as a callable - value that takes a response callback to which to pass the response value - of the RPC and a face_interfaces.RpcContext and returns a stream.Consumer - to which the request values of the RPC should be passed. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_UNARY, style.Service.EVENT, None, None, - None, None, None, None, behavior, None) - - -def stream_stream_event(behavior): - """Creates an interfaces.MethodImplementation for the given behavior. - - Args: - behavior: The implementation of a stream-stream RPC method as a callable - value that takes a stream.Consumer to which to pass the response values - of the RPC and a face_interfaces.RpcContext and returns a stream.Consumer - to which the request values of the RPC should be passed. - - Returns: - An interfaces.MethodImplementation derived from the given behavior. - """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_STREAM, style.Service.EVENT, None, None, - None, None, None, None, None, behavior) diff --git a/src/python/src/grpc/framework/face/_service.py b/src/python/src/grpc/framework/face/_service.py index 26bde129687a5b48b6bb7ad849665b10ab19e722..cdf413356ad716e33bd45cdc9accda28202d50a6 100644 --- a/src/python/src/grpc/framework/face/_service.py +++ b/src/python/src/grpc/framework/face/_service.py @@ -105,15 +105,14 @@ def adapt_inline_value_in_value_out(method): def adaptation(response_consumer, operation_context): rpc_context = _control.RpcContext(operation_context) return stream_util.TransformingConsumer( - lambda request: method.service(request, rpc_context), response_consumer) + lambda request: method(request, rpc_context), response_consumer) return adaptation def adapt_inline_value_in_stream_out(method): def adaptation(response_consumer, operation_context): rpc_context = _control.RpcContext(operation_context) - return _ValueInStreamOutConsumer( - method.service, rpc_context, response_consumer) + return _ValueInStreamOutConsumer(method, rpc_context, response_consumer) return adaptation @@ -123,7 +122,7 @@ def adapt_inline_stream_in_value_out(method, pool): operation_context.add_termination_callback(rendezvous.set_outcome) def in_pool_thread(): response_consumer.consume_and_terminate( - method.service(rendezvous, _control.RpcContext(operation_context))) + method(rendezvous, _control.RpcContext(operation_context))) pool.submit(_pool_wrap(in_pool_thread, operation_context)) return rendezvous return adaptation @@ -149,7 +148,7 @@ def adapt_inline_stream_in_stream_out(method, pool): operation_context.add_termination_callback(rendezvous.set_outcome) def in_pool_thread(): _control.pipe_iterator_to_consumer( - method.service(rendezvous, _control.RpcContext(operation_context)), + method(rendezvous, _control.RpcContext(operation_context)), response_consumer, operation_context.is_active, True) pool.submit(_pool_wrap(in_pool_thread, operation_context)) return rendezvous @@ -159,7 +158,7 @@ def adapt_inline_stream_in_stream_out(method, pool): def adapt_event_value_in_value_out(method): def adaptation(response_consumer, operation_context): def on_payload(payload): - method.service( + method( payload, response_consumer.consume_and_terminate, _control.RpcContext(operation_context)) return _control.UnaryConsumer(on_payload) @@ -169,7 +168,7 @@ def adapt_event_value_in_value_out(method): def adapt_event_value_in_stream_out(method): def adaptation(response_consumer, operation_context): def on_payload(payload): - method.service( + method( payload, response_consumer, _control.RpcContext(operation_context)) return _control.UnaryConsumer(on_payload) return adaptation @@ -178,12 +177,11 @@ def adapt_event_value_in_stream_out(method): def adapt_event_stream_in_value_out(method): def adaptation(response_consumer, operation_context): rpc_context = _control.RpcContext(operation_context) - return method.service(response_consumer.consume_and_terminate, rpc_context) + return method(response_consumer.consume_and_terminate, rpc_context) return adaptation def adapt_event_stream_in_stream_out(method): def adaptation(response_consumer, operation_context): - return method.service( - response_consumer, _control.RpcContext(operation_context)) + return method(response_consumer, _control.RpcContext(operation_context)) return adaptation diff --git a/src/python/src/grpc/framework/face/_test_case.py b/src/python/src/grpc/framework/face/_test_case.py index a4e17c464ce75bcca7e81f792aa34a2022f3e12d..b3a012db001ef44046ff13ee6247129f1bf7a62f 100644 --- a/src/python/src/grpc/framework/face/_test_case.py +++ b/src/python/src/grpc/framework/face/_test_case.py @@ -42,37 +42,17 @@ class FaceTestCase(test_case.FaceTestCase): """Provides abstract Face-layer tests an in-memory implementation.""" def set_up_implementation( - self, - name, - methods, - inline_value_in_value_out_methods, - inline_value_in_stream_out_methods, - inline_stream_in_value_out_methods, - inline_stream_in_stream_out_methods, - event_value_in_value_out_methods, - event_value_in_stream_out_methods, - event_stream_in_value_out_methods, - event_stream_in_stream_out_methods, - multi_method): + self, name, methods, method_implementations, + multi_method_implementation): servicer_pool = logging_pool.pool(_MAXIMUM_POOL_SIZE) stub_pool = logging_pool.pool(_MAXIMUM_POOL_SIZE) servicer = implementations.servicer( - servicer_pool, - inline_value_in_value_out_methods=inline_value_in_value_out_methods, - inline_value_in_stream_out_methods=inline_value_in_stream_out_methods, - inline_stream_in_value_out_methods=inline_stream_in_value_out_methods, - inline_stream_in_stream_out_methods=inline_stream_in_stream_out_methods, - event_value_in_value_out_methods=event_value_in_value_out_methods, - event_value_in_stream_out_methods=event_value_in_stream_out_methods, - event_stream_in_value_out_methods=event_stream_in_value_out_methods, - event_stream_in_stream_out_methods=event_stream_in_stream_out_methods, - multi_method=multi_method) + servicer_pool, method_implementations, multi_method_implementation) linked_pair = base_util.linked_pair(servicer, _TIMEOUT) - server = implementations.server() - stub = implementations.stub(linked_pair.front, stub_pool) - return server, stub, (servicer_pool, stub_pool, linked_pair) + stub = implementations.generic_stub(linked_pair.front, stub_pool) + return stub, (servicer_pool, stub_pool, linked_pair) def tear_down_implementation(self, memo): servicer_pool, stub_pool, linked_pair = memo diff --git a/src/python/src/grpc/framework/face/implementations.py b/src/python/src/grpc/framework/face/implementations.py index 86948b386faf6f8d62bbb4fc88cf7ca6bfca244e..4a6de52974ed623ce557c15282971d56bfdb4dfe 100644 --- a/src/python/src/grpc/framework/face/implementations.py +++ b/src/python/src/grpc/framework/face/implementations.py @@ -29,6 +29,8 @@ """Entry points into the Face layer of RPC Framework.""" +from grpc.framework.common import cardinality +from grpc.framework.common import style from grpc.framework.base import exceptions as _base_exceptions from grpc.framework.base import interfaces as base_interfaces from grpc.framework.face import _calls @@ -56,7 +58,7 @@ class _BaseServicer(base_interfaces.Servicer): raise _base_exceptions.NoSuchMethodError() -class _UnaryUnarySyncAsync(interfaces.UnaryUnarySyncAsync): +class _UnaryUnaryMultiCallable(interfaces.UnaryUnaryMultiCallable): def __init__(self, front, name): self._front = front @@ -66,12 +68,33 @@ class _UnaryUnarySyncAsync(interfaces.UnaryUnarySyncAsync): return _calls.blocking_value_in_value_out( self._front, self._name, request, timeout, 'unused trace ID') - def async(self, request, timeout): + def future(self, request, timeout): return _calls.future_value_in_value_out( self._front, self._name, request, timeout, 'unused trace ID') + def event(self, request, response_callback, abortion_callback, timeout): + return _calls.event_value_in_value_out( + self._front, self._name, request, response_callback, abortion_callback, + timeout, 'unused trace ID') + + +class _UnaryStreamMultiCallable(interfaces.UnaryStreamMultiCallable): + + def __init__(self, front, name): + self._front = front + self._name = name -class _StreamUnarySyncAsync(interfaces.StreamUnarySyncAsync): + def __call__(self, request, timeout): + return _calls.inline_value_in_stream_out( + self._front, self._name, request, timeout, 'unused trace ID') + + def event(self, request, response_consumer, abortion_callback, timeout): + return _calls.event_value_in_stream_out( + self._front, self._name, request, response_consumer, abortion_callback, + timeout, 'unused trace ID') + + +class _StreamUnaryMultiCallable(interfaces.StreamUnaryMultiCallable): def __init__(self, front, name, pool): self._front = front @@ -82,18 +105,37 @@ class _StreamUnarySyncAsync(interfaces.StreamUnarySyncAsync): return _calls.blocking_stream_in_value_out( self._front, self._name, request_iterator, timeout, 'unused trace ID') - def async(self, request_iterator, timeout): + def future(self, request_iterator, timeout): return _calls.future_stream_in_value_out( self._front, self._name, request_iterator, timeout, 'unused trace ID', self._pool) + def event(self, response_callback, abortion_callback, timeout): + return _calls.event_stream_in_value_out( + self._front, self._name, response_callback, abortion_callback, timeout, + 'unused trace ID') -class _Server(interfaces.Server): - """An interfaces.Server implementation.""" +class _StreamStreamMultiCallable(interfaces.StreamStreamMultiCallable): -class _Stub(interfaces.Stub): - """An interfaces.Stub implementation.""" + def __init__(self, front, name, pool): + self._front = front + self._name = name + self._pool = pool + + def __call__(self, request_iterator, timeout): + return _calls.inline_stream_in_stream_out( + self._front, self._name, request_iterator, timeout, 'unused trace ID', + self._pool) + + def event(self, response_consumer, abortion_callback, timeout): + return _calls.event_stream_in_stream_out( + self._front, self._name, response_consumer, abortion_callback, timeout, + 'unused trace ID') + + +class _GenericStub(interfaces.GenericStub): + """An interfaces.GenericStub implementation.""" def __init__(self, front, pool): self._front = front @@ -149,136 +191,128 @@ class _Stub(interfaces.Stub): self._front, name, response_consumer, abortion_callback, timeout, 'unused trace ID') - def unary_unary_sync_async(self, name): - return _UnaryUnarySyncAsync(self._front, name) - - def stream_unary_sync_async(self, name): - return _StreamUnarySyncAsync(self._front, name, self._pool) - - -def _aggregate_methods( - pool, - inline_value_in_value_out_methods, - inline_value_in_stream_out_methods, - inline_stream_in_value_out_methods, - inline_stream_in_stream_out_methods, - event_value_in_value_out_methods, - event_value_in_stream_out_methods, - event_stream_in_value_out_methods, - event_stream_in_stream_out_methods): - """Aggregates methods coded in according to different interfaces.""" - methods = {} - - def adapt_unpooled_methods(adapted_methods, unadapted_methods, adaptation): - if unadapted_methods is not None: - for name, unadapted_method in unadapted_methods.iteritems(): - adapted_methods[name] = adaptation(unadapted_method) - - def adapt_pooled_methods(adapted_methods, unadapted_methods, adaptation): - if unadapted_methods is not None: - for name, unadapted_method in unadapted_methods.iteritems(): - adapted_methods[name] = adaptation(unadapted_method, pool) - - adapt_unpooled_methods( - methods, inline_value_in_value_out_methods, - _service.adapt_inline_value_in_value_out) - adapt_unpooled_methods( - methods, inline_value_in_stream_out_methods, - _service.adapt_inline_value_in_stream_out) - adapt_pooled_methods( - methods, inline_stream_in_value_out_methods, - _service.adapt_inline_stream_in_value_out) - adapt_pooled_methods( - methods, inline_stream_in_stream_out_methods, - _service.adapt_inline_stream_in_stream_out) - adapt_unpooled_methods( - methods, event_value_in_value_out_methods, - _service.adapt_event_value_in_value_out) - adapt_unpooled_methods( - methods, event_value_in_stream_out_methods, - _service.adapt_event_value_in_stream_out) - adapt_unpooled_methods( - methods, event_stream_in_value_out_methods, - _service.adapt_event_stream_in_value_out) - adapt_unpooled_methods( - methods, event_stream_in_stream_out_methods, - _service.adapt_event_stream_in_stream_out) - - return methods - - -def servicer( - pool, - inline_value_in_value_out_methods=None, - inline_value_in_stream_out_methods=None, - inline_stream_in_value_out_methods=None, - inline_stream_in_stream_out_methods=None, - event_value_in_value_out_methods=None, - event_value_in_stream_out_methods=None, - event_stream_in_value_out_methods=None, - event_stream_in_stream_out_methods=None, - multi_method=None): + def unary_unary_multi_callable(self, name): + return _UnaryUnaryMultiCallable(self._front, name) + + def unary_stream_multi_callable(self, name): + return _UnaryStreamMultiCallable(self._front, name) + + def stream_unary_multi_callable(self, name): + return _StreamUnaryMultiCallable(self._front, name, self._pool) + + def stream_stream_multi_callable(self, name): + return _StreamStreamMultiCallable(self._front, name, self._pool) + + +class _DynamicStub(interfaces.DynamicStub): + """An interfaces.DynamicStub implementation.""" + + def __init__(self, cardinalities, front, pool): + self._cardinalities = cardinalities + self._front = front + self._pool = pool + + def __getattr__(self, attr): + method_cardinality = self._cardinalities.get(attr) + if method_cardinality is cardinality.Cardinality.UNARY_UNARY: + return _UnaryUnaryMultiCallable(self._front, attr) + elif method_cardinality is cardinality.Cardinality.UNARY_STREAM: + return _UnaryStreamMultiCallable(self._front, attr) + elif method_cardinality is cardinality.Cardinality.STREAM_UNARY: + return _StreamUnaryMultiCallable(self._front, attr, self._pool) + elif method_cardinality is cardinality.Cardinality.STREAM_STREAM: + return _StreamStreamMultiCallable(self._front, attr, self._pool) + else: + raise AttributeError('_DynamicStub object has no attribute "%s"!' % attr) + + +def _adapt_method_implementations(method_implementations, pool): + adapted_implementations = {} + for name, method_implementation in method_implementations.iteritems(): + if method_implementation.style is style.Service.INLINE: + if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: + adapted_implementations[name] = _service.adapt_inline_value_in_value_out( + method_implementation.unary_unary_inline) + elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: + adapted_implementations[name] = _service.adapt_inline_value_in_stream_out( + method_implementation.unary_stream_inline) + elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: + adapted_implementations[name] = _service.adapt_inline_stream_in_value_out( + method_implementation.stream_unary_inline, pool) + elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: + adapted_implementations[name] = _service.adapt_inline_stream_in_stream_out( + method_implementation.stream_stream_inline, pool) + elif method_implementation.style is style.Service.EVENT: + if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: + adapted_implementations[name] = _service.adapt_event_value_in_value_out( + method_implementation.unary_unary_event) + elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: + adapted_implementations[name] = _service.adapt_event_value_in_stream_out( + method_implementation.unary_stream_event) + elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: + adapted_implementations[name] = _service.adapt_event_stream_in_value_out( + method_implementation.stream_unary_event) + elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: + adapted_implementations[name] = _service.adapt_event_stream_in_stream_out( + method_implementation.stream_stream_event) + return adapted_implementations + + +def servicer(pool, method_implementations, multi_method_implementation): """Creates a base_interfaces.Servicer. - The key sets of the passed dictionaries must be disjoint. It is guaranteed - that any passed MultiMethod implementation will only be called to service an - RPC if the RPC method name is not present in the key sets of the passed - dictionaries. + It is guaranteed that any passed interfaces.MultiMethodImplementation will + only be called to service an RPC if there is no + interfaces.MethodImplementation for the RPC method in the passed + method_implementations dictionary. Args: pool: A thread pool. - inline_value_in_value_out_methods: A dictionary mapping method names to - interfaces.InlineValueInValueOutMethod implementations. - inline_value_in_stream_out_methods: A dictionary mapping method names to - interfaces.InlineValueInStreamOutMethod implementations. - inline_stream_in_value_out_methods: A dictionary mapping method names to - interfaces.InlineStreamInValueOutMethod implementations. - inline_stream_in_stream_out_methods: A dictionary mapping method names to - interfaces.InlineStreamInStreamOutMethod implementations. - event_value_in_value_out_methods: A dictionary mapping method names to - interfaces.EventValueInValueOutMethod implementations. - event_value_in_stream_out_methods: A dictionary mapping method names to - interfaces.EventValueInStreamOutMethod implementations. - event_stream_in_value_out_methods: A dictionary mapping method names to - interfaces.EventStreamInValueOutMethod implementations. - event_stream_in_stream_out_methods: A dictionary mapping method names to - interfaces.EventStreamInStreamOutMethod implementations. - multi_method: An implementation of interfaces.MultiMethod. + method_implementations: A dictionary from RPC method name to + interfaces.MethodImplementation object to be used to service the named + RPC method. + multi_method_implementation: An interfaces.MultiMethodImplementation to be + used to service any RPCs not serviced by the + interfaces.MethodImplementations given in the method_implementations + dictionary, or None. Returns: A base_interfaces.Servicer that services RPCs via the given implementations. """ - methods = _aggregate_methods( - pool, - inline_value_in_value_out_methods, - inline_value_in_stream_out_methods, - inline_stream_in_value_out_methods, - inline_stream_in_stream_out_methods, - event_value_in_value_out_methods, - event_value_in_stream_out_methods, - event_stream_in_value_out_methods, - event_stream_in_stream_out_methods) + adapted_implementations = _adapt_method_implementations( + method_implementations, pool) + return _BaseServicer(adapted_implementations, multi_method_implementation) - return _BaseServicer(methods, multi_method) +def generic_stub(front, pool): + """Creates an interfaces.GenericStub. -def server(): - """Creates an interfaces.Server. + Args: + front: A base_interfaces.Front. + pool: A futures.ThreadPoolExecutor. Returns: - An interfaces.Server. + An interfaces.GenericStub that performs RPCs via the given + base_interfaces.Front. """ - return _Server() + return _GenericStub(front, pool) -def stub(front, pool): - """Creates an interfaces.Stub. +def dynamic_stub(cardinalities, front, pool, prefix): + """Creates an interfaces.DynamicStub. Args: + cardinalities: A dict from RPC method name to cardinality.Cardinality + value identifying the cardinality of every RPC method to be supported by + the created interfaces.DynamicStub. front: A base_interfaces.Front. pool: A futures.ThreadPoolExecutor. + prefix: A string to prepend when mapping requested attribute name to RPC + method name during attribute access on the created + interfaces.DynamicStub. Returns: - An interfaces.Stub that performs RPCs via the given base_interfaces.Front. + An interfaces.DynamicStub that performs RPCs via the given + base_interfaces.Front. """ - return _Stub(front, pool) + return _DynamicStub(cardinalities, front, pool) diff --git a/src/python/src/grpc/framework/face/interfaces.py b/src/python/src/grpc/framework/face/interfaces.py index 9e19106e6f342f1e93060a4ca439d9ae56c81a75..b7cc4c1169ab9e87ca29511105f8a227699c870f 100644 --- a/src/python/src/grpc/framework/face/interfaces.py +++ b/src/python/src/grpc/framework/face/interfaces.py @@ -32,11 +32,24 @@ import abc import enum -# exceptions, abandonment, and future are referenced from specification in this -# module. +# cardinality, style, exceptions, abandonment, future, and stream are +# referenced from specification in this module. +from grpc.framework.common import cardinality # pylint: disable=unused-import +from grpc.framework.common import style # pylint: disable=unused-import from grpc.framework.face import exceptions # pylint: disable=unused-import from grpc.framework.foundation import abandonment # pylint: disable=unused-import from grpc.framework.foundation import future # pylint: disable=unused-import +from grpc.framework.foundation import stream # pylint: disable=unused-import + + +@enum.unique +class Abortion(enum.Enum): + """Categories of RPC abortion.""" + CANCELLED = 'cancelled' + EXPIRED = 'expired' + NETWORK_FAILURE = 'network failure' + SERVICED_FAILURE = 'serviced failure' + SERVICER_FAILURE = 'servicer failure' class CancellableIterator(object): @@ -59,69 +72,61 @@ class CancellableIterator(object): raise NotImplementedError() -class UnaryUnarySyncAsync(object): - """Affords invoking a unary-unary RPC synchronously or asynchronously. - - Values implementing this interface are directly callable and present an - "async" method. Both calls take a request value and a numeric timeout. - Direct invocation of a value of this type invokes its associated RPC and - blocks until the RPC's response is available. Calling the "async" method - of a value of this type invokes its associated RPC and immediately returns a - future.Future bound to the asynchronous execution of the RPC. - """ +class RpcContext(object): + """Provides RPC-related information and action.""" __metaclass__ = abc.ABCMeta @abc.abstractmethod - def __call__(self, request, timeout): - """Synchronously invokes the underlying RPC. + def is_active(self): + """Describes whether the RPC is active or has terminated.""" + raise NotImplementedError() - Args: - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. + @abc.abstractmethod + def time_remaining(self): + """Describes the length of allowed time remaining for the RPC. Returns: - The response value for the RPC. - - Raises: - exceptions.RpcError: Indicating that the RPC was aborted. + A nonnegative float indicating the length of allowed time in seconds + remaining for the RPC to complete before it is considered to have timed + out. """ raise NotImplementedError() @abc.abstractmethod - def async(self, request, timeout): - """Asynchronously invokes the underlying RPC. + def add_abortion_callback(self, abortion_callback): + """Registers a callback to be called if the RPC is aborted. Args: - request: The request value for the RPC. - timeout: A duration of time in seconds to allow for the RPC. - - Returns: - A future.Future representing the RPC. In the event of RPC completion, the - returned Future's result value will be the response value of the RPC. - In the event of RPC abortion, the returned Future's exception value - will be an exceptions.RpcError. + abortion_callback: A callable to be called and passed an Abortion value + in the event of RPC abortion. """ raise NotImplementedError() -class StreamUnarySyncAsync(object): - """Affords invoking a stream-unary RPC synchronously or asynchronously. +class Call(object): + """Invocation-side representation of an RPC. - Values implementing this interface are directly callable and present an - "async" method. Both calls take an iterator of request values and a numeric - timeout. Direct invocation of a value of this type invokes its associated RPC - and blocks until the RPC's response is available. Calling the "async" method - of a value of this type invokes its associated RPC and immediately returns a - future.Future bound to the asynchronous execution of the RPC. + Attributes: + context: An RpcContext affording information about the RPC. """ __metaclass__ = abc.ABCMeta @abc.abstractmethod - def __call__(self, request_iterator, timeout): + def cancel(self): + """Requests cancellation of the RPC.""" + raise NotImplementedError() + + +class UnaryUnaryMultiCallable(object): + """Affords invoking a unary-unary RPC in any call style.""" + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def __call__(self, request, timeout): """Synchronously invokes the underlying RPC. Args: - request_iterator: An iterator that yields request values for the RPC. + request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. Returns: @@ -133,11 +138,11 @@ class StreamUnarySyncAsync(object): raise NotImplementedError() @abc.abstractmethod - def async(self, request, timeout): + def future(self, request, timeout): """Asynchronously invokes the underlying RPC. Args: - request_iterator: An iterator that yields request values for the RPC. + request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. Returns: @@ -148,248 +153,204 @@ class StreamUnarySyncAsync(object): """ raise NotImplementedError() - -@enum.unique -class Abortion(enum.Enum): - """Categories of RPC abortion.""" - - CANCELLED = 'cancelled' - EXPIRED = 'expired' - NETWORK_FAILURE = 'network failure' - SERVICED_FAILURE = 'serviced failure' - SERVICER_FAILURE = 'servicer failure' - - -class RpcContext(object): - """Provides RPC-related information and action.""" - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def is_active(self): - """Describes whether the RPC is active or has terminated.""" - raise NotImplementedError() - - @abc.abstractmethod - def time_remaining(self): - """Describes the length of allowed time remaining for the RPC. - - Returns: - A nonnegative float indicating the length of allowed time in seconds - remaining for the RPC to complete before it is considered to have timed - out. - """ - raise NotImplementedError() - @abc.abstractmethod - def add_abortion_callback(self, abortion_callback): - """Registers a callback to be called if the RPC is aborted. + def event(self, request, response_callback, abortion_callback, timeout): + """Asynchronously invokes the underlying RPC. Args: - abortion_callback: A callable to be called and passed an Abortion value + request: The request value for the RPC. + response_callback: A callback to be called to accept the restponse value + of the RPC. + abortion_callback: A callback to be called and passed an Abortion value in the event of RPC abortion. - """ - raise NotImplementedError() - - -class InlineValueInValueOutMethod(object): - """A type for inline unary-request-unary-response RPC methods.""" - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def service(self, request, context): - """Services an RPC that accepts one value and produces one value. - - Args: - request: The single request value for the RPC. - context: An RpcContext object. + timeout: A duration of time in seconds to allow for the RPC. Returns: - The single response value for the RPC. - - Raises: - abandonment.Abandoned: If no response is necessary because the RPC has - been aborted. + A Call object for the RPC. """ raise NotImplementedError() -class InlineValueInStreamOutMethod(object): - """A type for inline unary-request-stream-response RPC methods.""" +class UnaryStreamMultiCallable(object): + """Affords invoking a unary-stream RPC in any call style.""" __metaclass__ = abc.ABCMeta @abc.abstractmethod - def service(self, request, context): - """Services an RPC that accepts one value and produces a stream of values. + def __call__(self, request, timeout): + """Synchronously invokes the underlying RPC. Args: - request: The single request value for the RPC. - context: An RpcContext object. - - Yields: - The values that comprise the response stream of the RPC. + request: The request value for the RPC. + timeout: A duration of time in seconds to allow for the RPC. - Raises: - abandonment.Abandoned: If completing the response stream is not necessary - because the RPC has been aborted. + Returns: + A CancellableIterator that yields the response values of the RPC and + affords RPC cancellation. Drawing response values from the returned + CancellableIterator may raise exceptions.RpcError indicating abortion + of the RPC. """ raise NotImplementedError() - -class InlineStreamInValueOutMethod(object): - """A type for inline stream-request-unary-response RPC methods.""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def service(self, request_iterator, context): - """Services an RPC that accepts a stream of values and produces one value. + def event(self, request, response_consumer, abortion_callback, timeout): + """Asynchronously invokes the underlying RPC. Args: - request_iterator: An iterator that yields the request values of the RPC. - Drawing values from this iterator may also raise exceptions.RpcError to - indicate abortion of the RPC. - context: An RpcContext object. - - Yields: - The values that comprise the response stream of the RPC. + request: The request value for the RPC. + response_consumer: A stream.Consumer to be called to accept the restponse + values of the RPC. + abortion_callback: A callback to be called and passed an Abortion value + in the event of RPC abortion. + timeout: A duration of time in seconds to allow for the RPC. - Raises: - abandonment.Abandoned: If no response is necessary because the RPC has - been aborted. - exceptions.RpcError: Implementations of this method must not deliberately - raise exceptions.RpcError but may allow such errors raised by the - request_iterator passed to them to propagate through their bodies - uncaught. + Returns: + A Call object for the RPC. """ raise NotImplementedError() -class InlineStreamInStreamOutMethod(object): - """A type for inline stream-request-stream-response RPC methods.""" +class StreamUnaryMultiCallable(object): + """Affords invoking a stream-unary RPC in any call style.""" __metaclass__ = abc.ABCMeta @abc.abstractmethod - def service(self, request_iterator, context): - """Services an RPC that accepts and produces streams of values. + def __call__(self, request_iterator, timeout): + """Synchronously invokes the underlying RPC. Args: - request_iterator: An iterator that yields the request values of the RPC. - Drawing values from this iterator may also raise exceptions.RpcError to - indicate abortion of the RPC. - context: An RpcContext object. + request_iterator: An iterator that yields request values for the RPC. + timeout: A duration of time in seconds to allow for the RPC. - Yields: - The values that comprise the response stream of the RPC. + Returns: + The response value for the RPC. Raises: - abandonment.Abandoned: If completing the response stream is not necessary - because the RPC has been aborted. - exceptions.RpcError: Implementations of this method must not deliberately - raise exceptions.RpcError but may allow such errors raised by the - request_iterator passed to them to propagate through their bodies - uncaught. + exceptions.RpcError: Indicating that the RPC was aborted. """ raise NotImplementedError() - -class EventValueInValueOutMethod(object): - """A type for event-driven unary-request-unary-response RPC methods.""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def service(self, request, response_callback, context): - """Services an RPC that accepts one value and produces one value. + def future(self, request_iterator, timeout): + """Asynchronously invokes the underlying RPC. Args: - request: The single request value for the RPC. - response_callback: A callback to be called to accept the response value of - the RPC. - context: An RpcContext object. + request_iterator: An iterator that yields request values for the RPC. + timeout: A duration of time in seconds to allow for the RPC. - Raises: - abandonment.Abandoned: May or may not be raised when the RPC has been - aborted. + Returns: + A future.Future representing the RPC. In the event of RPC completion, the + returned Future's result value will be the response value of the RPC. + In the event of RPC abortion, the returned Future's exception value + will be an exceptions.RpcError. """ raise NotImplementedError() - -class EventValueInStreamOutMethod(object): - """A type for event-driven unary-request-stream-response RPC methods.""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def service(self, request, response_consumer, context): - """Services an RPC that accepts one value and produces a stream of values. + def event(self, response_callback, abortion_callback, timeout): + """Asynchronously invokes the underlying RPC. Args: - request: The single request value for the RPC. - response_consumer: A stream.Consumer to be called to accept the response - values of the RPC. - context: An RpcContext object. + request: The request value for the RPC. + response_callback: A callback to be called to accept the restponse value + of the RPC. + abortion_callback: A callback to be called and passed an Abortion value + in the event of RPC abortion. + timeout: A duration of time in seconds to allow for the RPC. - Raises: - abandonment.Abandoned: May or may not be raised when the RPC has been - aborted. + Returns: + A pair of a Call object for the RPC and a stream.Consumer to which the + request values of the RPC should be passed. """ raise NotImplementedError() -class EventStreamInValueOutMethod(object): - """A type for event-driven stream-request-unary-response RPC methods.""" +class StreamStreamMultiCallable(object): + """Affords invoking a stream-stream RPC in any call style.""" __metaclass__ = abc.ABCMeta @abc.abstractmethod - def service(self, response_callback, context): - """Services an RPC that accepts a stream of values and produces one value. + def __call__(self, request_iterator, timeout): + """Synchronously invokes the underlying RPC. Args: - response_callback: A callback to be called to accept the response value of - the RPC. - context: An RpcContext object. + request_iterator: An iterator that yields request values for the RPC. + timeout: A duration of time in seconds to allow for the RPC. Returns: - A stream.Consumer with which to accept the request values of the RPC. The - consumer returned from this method may or may not be invoked to - completion: in the case of RPC abortion, RPC Framework will simply stop - passing values to this object. Implementations must not assume that this - object will be called to completion of the request stream or even called - at all. - - Raises: - abandonment.Abandoned: May or may not be raised when the RPC has been - aborted. + A CancellableIterator that yields the response values of the RPC and + affords RPC cancellation. Drawing response values from the returned + CancellableIterator may raise exceptions.RpcError indicating abortion + of the RPC. """ raise NotImplementedError() - -class EventStreamInStreamOutMethod(object): - """A type for event-driven stream-request-stream-response RPC methods.""" - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def service(self, response_consumer, context): - """Services an RPC that accepts and produces streams of values. + def event(self, response_consumer, abortion_callback, timeout): + """Asynchronously invokes the underlying RPC. - Args: - response_consumer: A stream.Consumer to be called to accept the response +l Args: + response_consumer: A stream.Consumer to be called to accept the restponse values of the RPC. - context: An RpcContext object. + abortion_callback: A callback to be called and passed an Abortion value + in the event of RPC abortion. + timeout: A duration of time in seconds to allow for the RPC. Returns: - A stream.Consumer with which to accept the request values of the RPC. The - consumer returned from this method may or may not be invoked to - completion: in the case of RPC abortion, RPC Framework will simply stop - passing values to this object. Implementations must not assume that this - object will be called to completion of the request stream or even called - at all. - - Raises: - abandonment.Abandoned: May or may not be raised when the RPC has been - aborted. + A pair of a Call object for the RPC and a stream.Consumer to which the + request values of the RPC should be passed. """ raise NotImplementedError() -class MultiMethod(object): +class MethodImplementation(object): + """A sum type that describes an RPC method implementation. + + Attributes: + cardinality: A cardinality.Cardinality value. + style: A style.Service value. + unary_unary_inline: The implementation of the RPC method as a callable + value that takes a request value and an RpcContext object and returns a + response value. Only non-None if cardinality is + cardinality.Cardinality.UNARY_UNARY and style is style.Service.INLINE. + unary_stream_inline: The implementation of the RPC method as a callable + value that takes a request value and an RpcContext object and returns an + iterator of response values. Only non-None if cardinality is + cardinality.Cardinality.UNARY_STREAM and style is style.Service.INLINE. + stream_unary_inline: The implementation of the RPC method as a callable + value that takes an iterator of request values and an RpcContext object + and returns a response value. Only non-None if cardinality is + cardinality.Cardinality.STREAM_UNARY and style is style.Service.INLINE. + stream_stream_inline: The implementation of the RPC method as a callable + value that takes an iterator of request values and an RpcContext object + and returns an iterator of response values. Only non-None if cardinality + is cardinality.Cardinality.STREAM_STREAM and style is + style.Service.INLINE. + unary_unary_event: The implementation of the RPC method as a callable value + that takes a request value, a response callback to which to pass the + response value of the RPC, and an RpcContext. Only non-None if + cardinality is cardinality.Cardinality.UNARY_UNARY and style is + style.Service.EVENT. + unary_stream_event: The implementation of the RPC method as a callable + value that takes a request value, a stream.Consumer to which to pass the + the response values of the RPC, and an RpcContext. Only non-None if + cardinality is cardinality.Cardinality.UNARY_STREAM and style is + style.Service.EVENT. + stream_unary_event: The implementation of the RPC method as a callable + value that takes a response callback to which to pass the response value + of the RPC and an RpcContext and returns a stream.Consumer to which the + request values of the RPC should be passed. Only non-None if cardinality + is cardinality.Cardinality.STREAM_UNARY and style is style.Service.EVENT. + stream_stream_event: The implementation of the RPC method as a callable + value that takes a stream.Consumer to which to pass the response values + of the RPC and an RpcContext and returns a stream.Consumer to which the + request values of the RPC should be passed. Only non-None if cardinality + is cardinality.Cardinality.STREAM_STREAM and style is + style.Service.EVENT. + """ + __metaclass__ = abc.ABCMeta + + +class MultiMethodImplementation(object): """A general type able to service many RPC methods.""" __metaclass__ = abc.ABCMeta @@ -420,26 +381,7 @@ class MultiMethod(object): raise NotImplementedError() -class Server(object): - """Specification of a running server that services RPCs.""" - __metaclass__ = abc.ABCMeta - - -class Call(object): - """Invocation-side representation of an RPC. - - Attributes: - context: An RpcContext affording information about the RPC. - """ - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def cancel(self): - """Requests cancellation of the RPC.""" - raise NotImplementedError() - - -class Stub(object): +class GenericStub(object): """Affords RPC methods to callers.""" __metaclass__ = abc.ABCMeta @@ -632,25 +574,67 @@ class Stub(object): raise NotImplementedError() @abc.abstractmethod - def unary_unary_sync_async(self, name): - """Creates a UnaryUnarySyncAsync value for a unary-unary RPC method. + def unary_unary_multi_callable(self, name): + """Creates a UnaryUnaryMultiCallable for a unary-unary RPC method. + + Args: + name: The RPC method name. + + Returns: + A UnaryUnaryMultiCallable value for the named unary-unary RPC method. + """ + raise NotImplementedError() + + @abc.abstractmethod + def unary_stream_multi_callable(self, name): + """Creates a UnaryStreamMultiCallable for a unary-stream RPC method. Args: name: The RPC method name. Returns: - A UnaryUnarySyncAsync value for the named unary-unary RPC method. + A UnaryStreamMultiCallable value for the name unary-stream RPC method. """ raise NotImplementedError() @abc.abstractmethod - def stream_unary_sync_async(self, name): - """Creates a StreamUnarySyncAsync value for a stream-unary RPC method. + def stream_unary_multi_callable(self, name): + """Creates a StreamUnaryMultiCallable for a stream-unary RPC method. Args: name: The RPC method name. Returns: - A StreamUnarySyncAsync value for the named stream-unary RPC method. + A StreamUnaryMultiCallable value for the named stream-unary RPC method. """ raise NotImplementedError() + + @abc.abstractmethod + def stream_stream_multi_callable(self, name): + """Creates a StreamStreamMultiCallable for a stream-stream RPC method. + + Args: + name: The RPC method name. + + Returns: + A StreamStreamMultiCallable value for the named stream-stream RPC method. + """ + raise NotImplementedError() + + +class DynamicStub(object): + """A stub with RPC-method-bound multi-callable attributes. + + Instances of this type responsd to attribute access as follows: if the + requested attribute is the name of a unary-unary RPC method, the value of the + attribute will be a UnaryUnaryMultiCallable with which to invoke the RPC + method; if the requested attribute is the name of a unary-stream RPC method, + the value of the attribute will be a UnaryStreamMultiCallable with which to + invoke the RPC method; if the requested attribute is the name of a + stream-unary RPC method, the value of the attribute will be a + StreamUnaryMultiCallable with which to invoke the RPC method; and if the + requested attribute is the name of a stream-stream RPC method, the value of + the attribute will be a StreamStreamMultiCallable with which to invoke the + RPC method. + """ + __metaclass__ = abc.ABCMeta diff --git a/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py b/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py index 233486f2110368ca95f56f00dabb4e05965f0729..e57ee001045a487b0359e2401c2ffe83724ade2f 100644 --- a/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py +++ b/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py @@ -61,13 +61,9 @@ class BlockingInvocationInlineServiceTestCase( self.digest = digest.digest( stock_service.STOCK_TEST_SERVICE, self.control, None) - self.server, self.stub, self.memo = self.set_up_implementation( + self.stub, self.memo = self.set_up_implementation( self.digest.name, self.digest.methods, - self.digest.inline_unary_unary_methods, - self.digest.inline_unary_stream_methods, - self.digest.inline_stream_unary_methods, - self.digest.inline_stream_stream_methods, - {}, {}, {}, {}, None) + self.digest.inline_method_implementations, None) def tearDown(self): """See unittest.TestCase.tearDown for full specification. @@ -147,8 +143,8 @@ class BlockingInvocationInlineServiceTestCase( with self.control.pause(), self.assertRaises( exceptions.ExpirationError): - sync_async = self.stub.unary_unary_sync_async(name) - sync_async(request, _TIMEOUT) + multi_callable = self.stub.unary_unary_multi_callable(name) + multi_callable(request, _TIMEOUT) def testExpiredUnaryRequestStreamResponse(self): for name, test_messages_sequence in ( @@ -170,8 +166,8 @@ class BlockingInvocationInlineServiceTestCase( with self.control.pause(), self.assertRaises( exceptions.ExpirationError): - sync_async = self.stub.stream_unary_sync_async(name) - sync_async(iter(requests), _TIMEOUT) + multi_callable = self.stub.stream_unary_multi_callable(name) + multi_callable(iter(requests), _TIMEOUT) def testExpiredStreamRequestStreamResponse(self): for name, test_messages_sequence in ( diff --git a/src/python/src/grpc/framework/face/testing/digest.py b/src/python/src/grpc/framework/face/testing/digest.py index b8fb573301370e0e5556065bde548ed071169662..db8fcbb0184efaca4d239a1436b788d49712e9d2 100644 --- a/src/python/src/grpc/framework/face/testing/digest.py +++ b/src/python/src/grpc/framework/face/testing/digest.py @@ -34,6 +34,8 @@ import threading # testing_control, interfaces, and testing_service are referenced from # specification in this module. +from grpc.framework.common import cardinality +from grpc.framework.common import style from grpc.framework.face import exceptions from grpc.framework.face import interfaces as face_interfaces from grpc.framework.face.testing import control as testing_control # pylint: disable=unused-import @@ -50,15 +52,9 @@ class TestServiceDigest( 'TestServiceDigest', ['name', 'methods', - 'inline_unary_unary_methods', - 'inline_unary_stream_methods', - 'inline_stream_unary_methods', - 'inline_stream_stream_methods', - 'event_unary_unary_methods', - 'event_unary_stream_methods', - 'event_stream_unary_methods', - 'event_stream_stream_methods', - 'multi_method', + 'inline_method_implementations', + 'event_method_implementations', + 'multi_method_implementation', 'unary_unary_messages_sequences', 'unary_stream_messages_sequences', 'stream_unary_messages_sequences', @@ -69,32 +65,14 @@ class TestServiceDigest( name: The RPC service name to be used in the test. methods: A sequence of interfaces.Method objects describing the RPC methods that will be called during the test. - inline_unary_unary_methods: A dict from method name to - face_interfaces.InlineValueInValueOutMethod object to be used in tests of + inline_method_implementations: A dict from RPC method name to + face_interfaces.MethodImplementation object to be used in tests of in-line calls to behaviors under test. - inline_unary_stream_methods: A dict from method name to - face_interfaces.InlineValueInStreamOutMethod object to be used in tests of - in-line calls to behaviors under test. - inline_stream_unary_methods: A dict from method name to - face_interfaces.InlineStreamInValueOutMethod object to be used in tests of - in-line calls to behaviors under test. - inline_stream_stream_methods: A dict from method name to - face_interfaces.InlineStreamInStreamOutMethod object to be used in tests - of in-line calls to behaviors under test. - event_unary_unary_methods: A dict from method name to - face_interfaces.EventValueInValueOutMethod object to be used in tests of - event-driven calls to behaviors under test. - event_unary_stream_methods: A dict from method name to - face_interfaces.EventValueInStreamOutMethod object to be used in tests of - event-driven calls to behaviors under test. - event_stream_unary_methods: A dict from method name to - face_interfaces.EventStreamInValueOutMethod object to be used in tests of + event_method_implementations: A dict from RPC method name to + face_interfaces.MethodImplementation object to be used in tests of event-driven calls to behaviors under test. - event_stream_stream_methods: A dict from method name to - face_interfaces.EventStreamInStreamOutMethod object to be used in tests of - event-driven calls to behaviors under test. - multi_method: A face_interfaces.MultiMethod to be used in tests of generic - calls to behaviors under test. + multi_method_implementation: A face_interfaces.MultiMethodImplementation to + be used in tests of generic calls to behaviors under test. unary_unary_messages_sequences: A dict from method name to sequence of service.UnaryUnaryTestMessages objects to be used to test the method with the given name. @@ -130,27 +108,33 @@ class _BufferingConsumer(stream.Consumer): self.terminated = True -class _InlineUnaryUnaryMethod(face_interfaces.InlineValueInValueOutMethod): +class _InlineUnaryUnaryMethod(face_interfaces.MethodImplementation): def __init__(self, unary_unary_test_method, control): self._test_method = unary_unary_test_method self._control = control - def service(self, request, context): + self.cardinality = cardinality.Cardinality.UNARY_UNARY + self.style = style.Service.INLINE + + def unary_unary_inline(self, request, context): response_list = [] self._test_method.service( request, response_list.append, context, self._control) return response_list.pop(0) -class _EventUnaryUnaryMethod(face_interfaces.EventValueInValueOutMethod): +class _EventUnaryUnaryMethod(face_interfaces.MethodImplementation): def __init__(self, unary_unary_test_method, control, pool): self._test_method = unary_unary_test_method self._control = control self._pool = pool - def service(self, request, response_callback, context): + self.cardinality = cardinality.Cardinality.UNARY_UNARY + self.style = style.Service.EVENT + + def unary_unary_event(self, request, response_callback, context): if self._pool is None: self._test_method.service( request, response_callback, context, self._control) @@ -160,13 +144,16 @@ class _EventUnaryUnaryMethod(face_interfaces.EventValueInValueOutMethod): self._control) -class _InlineUnaryStreamMethod(face_interfaces.InlineValueInStreamOutMethod): +class _InlineUnaryStreamMethod(face_interfaces.MethodImplementation): def __init__(self, unary_stream_test_method, control): self._test_method = unary_stream_test_method self._control = control - def service(self, request, context): + self.cardinality = cardinality.Cardinality.UNARY_STREAM + self.style = style.Service.INLINE + + def unary_stream_inline(self, request, context): response_consumer = _BufferingConsumer() self._test_method.service( request, response_consumer, context, self._control) @@ -174,14 +161,17 @@ class _InlineUnaryStreamMethod(face_interfaces.InlineValueInStreamOutMethod): yield response -class _EventUnaryStreamMethod(face_interfaces.EventValueInStreamOutMethod): +class _EventUnaryStreamMethod(face_interfaces.MethodImplementation): def __init__(self, unary_stream_test_method, control, pool): self._test_method = unary_stream_test_method self._control = control self._pool = pool - def service(self, request, response_consumer, context): + self.cardinality = cardinality.Cardinality.UNARY_STREAM + self.style = style.Service.EVENT + + def unary_stream_event(self, request, response_consumer, context): if self._pool is None: self._test_method.service( request, response_consumer, context, self._control) @@ -191,13 +181,16 @@ class _EventUnaryStreamMethod(face_interfaces.EventValueInStreamOutMethod): self._control) -class _InlineStreamUnaryMethod(face_interfaces.InlineStreamInValueOutMethod): +class _InlineStreamUnaryMethod(face_interfaces.MethodImplementation): def __init__(self, stream_unary_test_method, control): self._test_method = stream_unary_test_method self._control = control - def service(self, request_iterator, context): + self.cardinality = cardinality.Cardinality.STREAM_UNARY + self.style = style.Service.INLINE + + def stream_unary_inline(self, request_iterator, context): response_list = [] request_consumer = self._test_method.service( response_list.append, context, self._control) @@ -207,14 +200,17 @@ class _InlineStreamUnaryMethod(face_interfaces.InlineStreamInValueOutMethod): return response_list.pop(0) -class _EventStreamUnaryMethod(face_interfaces.EventStreamInValueOutMethod): +class _EventStreamUnaryMethod(face_interfaces.MethodImplementation): def __init__(self, stream_unary_test_method, control, pool): self._test_method = stream_unary_test_method self._control = control self._pool = pool - def service(self, response_callback, context): + self.cardinality = cardinality.Cardinality.STREAM_UNARY + self.style = style.Service.EVENT + + def stream_unary_event(self, response_callback, context): request_consumer = self._test_method.service( response_callback, context, self._control) if self._pool is None: @@ -223,13 +219,16 @@ class _EventStreamUnaryMethod(face_interfaces.EventStreamInValueOutMethod): return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) -class _InlineStreamStreamMethod(face_interfaces.InlineStreamInStreamOutMethod): +class _InlineStreamStreamMethod(face_interfaces.MethodImplementation): def __init__(self, stream_stream_test_method, control): self._test_method = stream_stream_test_method self._control = control - def service(self, request_iterator, context): + self.cardinality = cardinality.Cardinality.STREAM_STREAM + self.style = style.Service.INLINE + + def stream_stream_inline(self, request_iterator, context): response_consumer = _BufferingConsumer() request_consumer = self._test_method.service( response_consumer, context, self._control) @@ -241,14 +240,17 @@ class _InlineStreamStreamMethod(face_interfaces.InlineStreamInStreamOutMethod): response_consumer.terminate() -class _EventStreamStreamMethod(face_interfaces.EventStreamInStreamOutMethod): +class _EventStreamStreamMethod(face_interfaces.MethodImplementation): def __init__(self, stream_stream_test_method, control, pool): self._test_method = stream_stream_test_method self._control = control self._pool = pool - def service(self, response_consumer, context): + self.cardinality = cardinality.Cardinality.STREAM_STREAM + self.style = style.Service.EVENT + + def stream_stream_event(self, response_consumer, context): request_consumer = self._test_method.service( response_consumer, context, self._control) if self._pool is None: @@ -332,7 +334,7 @@ class _StreamUnaryAdaptation(object): response_consumer.consume_and_terminate, context, control) -class _MultiMethod(face_interfaces.MultiMethod): +class _MultiMethodImplementation(face_interfaces.MultiMethodImplementation): def __init__(self, methods, control, pool): self._methods = methods @@ -427,19 +429,21 @@ def digest(service, control, pool): adaptations.update(unary_stream.adaptations) adaptations.update(stream_unary.adaptations) adaptations.update(stream_stream.adaptations) + inlines = dict(unary_unary.inlines) + inlines.update(unary_stream.inlines) + inlines.update(stream_unary.inlines) + inlines.update(stream_stream.inlines) + events = dict(unary_unary.events) + events.update(unary_stream.events) + events.update(stream_unary.events) + events.update(stream_stream.events) return TestServiceDigest( service.name(), methods, - unary_unary.inlines, - unary_stream.inlines, - stream_unary.inlines, - stream_stream.inlines, - unary_unary.events, - unary_stream.events, - stream_unary.events, - stream_stream.events, - _MultiMethod(adaptations, control, pool), + inlines, + events, + _MultiMethodImplementation(adaptations, control, pool), unary_unary.messages, unary_stream.messages, stream_unary.messages, diff --git a/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py b/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py index 21e669b9080fb138101718c0e7ffebdda96c4566..0f0b0e3d5232a7014fc8be7e6861a516750d7485 100644 --- a/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py +++ b/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py @@ -60,14 +60,9 @@ class EventInvocationSynchronousEventServiceTestCase( self.digest = digest.digest( stock_service.STOCK_TEST_SERVICE, self.control, None) - self.server, self.stub, self.memo = self.set_up_implementation( + self.stub, self.memo = self.set_up_implementation( self.digest.name, self.digest.methods, - {}, {}, {}, {}, - self.digest.event_unary_unary_methods, - self.digest.event_unary_stream_methods, - self.digest.event_stream_unary_methods, - self.digest.event_stream_stream_methods, - None) + self.digest.event_method_implementations, None) def tearDown(self): """See unittest.TestCase.tearDown for full specification. diff --git a/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py b/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py index c87846f2ef67280aab8c1cc243d75a7c260c8076..0d51b64f1b3b51f4ac0275b83967a68be9e57edf 100644 --- a/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py +++ b/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py @@ -91,14 +91,9 @@ class FutureInvocationAsynchronousEventServiceTestCase( self.digest = digest.digest( stock_service.STOCK_TEST_SERVICE, self.control, self.digest_pool) - self.server, self.stub, self.memo = self.set_up_implementation( + self.stub, self.memo = self.set_up_implementation( self.digest.name, self.digest.methods, - {}, {}, {}, {}, - self.digest.event_unary_unary_methods, - self.digest.event_unary_stream_methods, - self.digest.event_stream_unary_methods, - self.digest.event_stream_stream_methods, - None) + self.digest.event_method_implementations, None) def tearDown(self): """See unittest.TestCase.tearDown for full specification. @@ -190,8 +185,8 @@ class FutureInvocationAsynchronousEventServiceTestCase( request = test_messages.request() with self.control.pause(): - sync_async = self.stub.unary_unary_sync_async(name) - response_future = sync_async.async(request, _TIMEOUT) + multi_callable = self.stub.unary_unary_multi_callable(name) + response_future = multi_callable.future(request, _TIMEOUT) self.assertIsInstance( response_future.exception(), exceptions.ExpirationError) with self.assertRaises(exceptions.ExpirationError): @@ -216,8 +211,8 @@ class FutureInvocationAsynchronousEventServiceTestCase( requests = test_messages.requests() with self.control.pause(): - sync_async = self.stub.stream_unary_sync_async(name) - response_future = sync_async.async(iter(requests), _TIMEOUT) + multi_callable = self.stub.stream_unary_multi_callable(name) + response_future = multi_callable.future(iter(requests), _TIMEOUT) self.assertIsInstance( response_future.exception(), exceptions.ExpirationError) with self.assertRaises(exceptions.ExpirationError): diff --git a/src/python/src/grpc/framework/face/testing/service.py b/src/python/src/grpc/framework/face/testing/service.py index a58e2ee42e41ed30be3f88e972942e85fa74f7d1..bf54d41d6643f66222c884419e50b2ca9066d440 100644 --- a/src/python/src/grpc/framework/face/testing/service.py +++ b/src/python/src/grpc/framework/face/testing/service.py @@ -36,8 +36,8 @@ from grpc.framework.face import interfaces as face_interfaces # pylint: disable from grpc.framework.face.testing import interfaces -class UnaryUnaryTestMethod(interfaces.Method): - """Like face_interfaces.EventValueInValueOutMethod but with a control.""" +class UnaryUnaryTestMethodImplementation(interfaces.Method): + """A controllable implementation of a unary-unary RPC method.""" __metaclass__ = abc.ABCMeta @@ -93,8 +93,8 @@ class UnaryUnaryTestMessages(object): raise NotImplementedError() -class UnaryStreamTestMethod(interfaces.Method): - """Like face_interfaces.EventValueInStreamOutMethod but with a control.""" +class UnaryStreamTestMethodImplementation(interfaces.Method): + """A controllable implementation of a unary-stream RPC method.""" __metaclass__ = abc.ABCMeta @@ -106,7 +106,7 @@ class UnaryStreamTestMethod(interfaces.Method): request: The single request message for the RPC. response_consumer: A stream.Consumer to be called to accept the response messages of the RPC. - context: An RpcContext object. + context: A face_interfaces.RpcContext object. control: A test_control.Control to control execution of this method. Raises: @@ -150,8 +150,8 @@ class UnaryStreamTestMessages(object): raise NotImplementedError() -class StreamUnaryTestMethod(interfaces.Method): - """Like face_interfaces.EventStreamInValueOutMethod but with a control.""" +class StreamUnaryTestMethodImplementation(interfaces.Method): + """A controllable implementation of a stream-unary RPC method.""" __metaclass__ = abc.ABCMeta @@ -162,7 +162,7 @@ class StreamUnaryTestMethod(interfaces.Method): Args: response_callback: A callback to be called to accept the response message of the RPC. - context: An RpcContext object. + context: A face_interfaces.RpcContext object. control: A test_control.Control to control execution of this method. Returns: @@ -214,8 +214,8 @@ class StreamUnaryTestMessages(object): raise NotImplementedError() -class StreamStreamTestMethod(interfaces.Method): - """Like face_interfaces.EventStreamInStreamOutMethod but with a control.""" +class StreamStreamTestMethodImplementation(interfaces.Method): + """A controllable implementation of a stream-stream RPC method.""" __metaclass__ = abc.ABCMeta @@ -226,7 +226,7 @@ class StreamStreamTestMethod(interfaces.Method): Args: response_consumer: A stream.Consumer to be called to accept the response messages of the RPC. - context: An RpcContext object. + context: A face_interfaces.RpcContext object. control: A test_control.Control to control execution of this method. Returns: @@ -298,8 +298,8 @@ class TestService(object): Returns: A dict from method name to pair. The first element of the pair - is a UnaryUnaryTestMethod object and the second element is a sequence - of UnaryUnaryTestMethodMessages objects. + is a UnaryUnaryTestMethodImplementation object and the second element + is a sequence of UnaryUnaryTestMethodMessages objects. """ raise NotImplementedError() @@ -309,8 +309,8 @@ class TestService(object): Returns: A dict from method name to pair. The first element of the pair is a - UnaryStreamTestMethod object and the second element is a sequence of - UnaryStreamTestMethodMessages objects. + UnaryStreamTestMethodImplementation object and the second element is a + sequence of UnaryStreamTestMethodMessages objects. """ raise NotImplementedError() @@ -320,8 +320,8 @@ class TestService(object): Returns: A dict from method name to pair. The first element of the pair is a - StreamUnaryTestMethod object and the second element is a sequence of - StreamUnaryTestMethodMessages objects. + StreamUnaryTestMethodImplementation object and the second element is a + sequence of StreamUnaryTestMethodMessages objects. """ raise NotImplementedError() @@ -331,7 +331,7 @@ class TestService(object): Returns: A dict from method name to pair. The first element of the pair is a - StreamStreamTestMethod object and the second element is a sequence of - StreamStreamTestMethodMessages objects. + StreamStreamTestMethodImplementation object and the second element is a + sequence of StreamStreamTestMethodMessages objects. """ raise NotImplementedError() diff --git a/src/python/src/grpc/framework/face/testing/stock_service.py b/src/python/src/grpc/framework/face/testing/stock_service.py index 83c9418b074a3eadeaf3980487a2dc380a77b7f3..61aaf444a00fd42232053276f4da819b00ef297e 100644 --- a/src/python/src/grpc/framework/face/testing/stock_service.py +++ b/src/python/src/grpc/framework/face/testing/stock_service.py @@ -139,7 +139,7 @@ def _get_highest_trade_price(stock_reply_callback, control, active): return StockRequestConsumer() -class GetLastTradePrice(service.UnaryUnaryTestMethod): +class GetLastTradePrice(service.UnaryUnaryTestMethodImplementation): """GetLastTradePrice for use in tests.""" def name(self): @@ -186,7 +186,7 @@ class GetLastTradePriceMessages(service.UnaryUnaryTestMessages): test_case.assertEqual(_price(request.symbol), response.price) -class GetLastTradePriceMultiple(service.StreamStreamTestMethod): +class GetLastTradePriceMultiple(service.StreamStreamTestMethodImplementation): """GetLastTradePriceMultiple for use in tests.""" def name(self): @@ -238,7 +238,7 @@ class GetLastTradePriceMultipleMessages(service.StreamStreamTestMessages): test_case.assertEqual(_price(stock_request.symbol), stock_reply.price) -class WatchFutureTrades(service.UnaryStreamTestMethod): +class WatchFutureTrades(service.UnaryStreamTestMethodImplementation): """WatchFutureTrades for use in tests.""" def name(self): @@ -288,7 +288,7 @@ class WatchFutureTradesMessages(service.UnaryStreamTestMessages): test_case.assertEqual(base_price + index, response.price) -class GetHighestTradePrice(service.StreamUnaryTestMethod): +class GetHighestTradePrice(service.StreamUnaryTestMethodImplementation): """GetHighestTradePrice for use in tests.""" def name(self): diff --git a/src/python/src/grpc/framework/face/testing/test_case.py b/src/python/src/grpc/framework/face/testing/test_case.py index 218a2a8549bebd91b90825b16faebff79f4d98bb..e60e3d1d405c2960f1423bf88132dc71376dad49 100644 --- a/src/python/src/grpc/framework/face/testing/test_case.py +++ b/src/python/src/grpc/framework/face/testing/test_case.py @@ -46,55 +46,24 @@ class FaceTestCase(object): @abc.abstractmethod def set_up_implementation( - self, - name, - methods, - inline_value_in_value_out_methods, - inline_value_in_stream_out_methods, - inline_stream_in_value_out_methods, - inline_stream_in_stream_out_methods, - event_value_in_value_out_methods, - event_value_in_stream_out_methods, - event_stream_in_value_out_methods, - event_stream_in_stream_out_methods, - multi_method): + self, name, methods, method_implementations, + multi_method_implementation): """Instantiates the Face Layer implementation under test. Args: name: The service name to be used in the test. methods: A sequence of interfaces.Method objects describing the RPC methods that will be called during the test. - inline_value_in_value_out_methods: A dictionary from string method names - to face_interfaces.InlineValueInValueOutMethod implementations of those - methods. - inline_value_in_stream_out_methods: A dictionary from string method names - to face_interfaces.InlineValueInStreamOutMethod implementations of those - methods. - inline_stream_in_value_out_methods: A dictionary from string method names - to face_interfaces.InlineStreamInValueOutMethod implementations of those - methods. - inline_stream_in_stream_out_methods: A dictionary from string method names - to face_interfaces.InlineStreamInStreamOutMethod implementations of - those methods. - event_value_in_value_out_methods: A dictionary from string method names - to face_interfaces.EventValueInValueOutMethod implementations of those - methods. - event_value_in_stream_out_methods: A dictionary from string method names - to face_interfaces.EventValueInStreamOutMethod implementations of those - methods. - event_stream_in_value_out_methods: A dictionary from string method names - to face_interfaces.EventStreamInValueOutMethod implementations of those - methods. - event_stream_in_stream_out_methods: A dictionary from string method names - to face_interfaces.EventStreamInStreamOutMethod implementations of those - methods. - multi_method: An face_interfaces.MultiMethod, or None. + method_implementations: A dictionary from string RPC method name to + face_interfaces.MethodImplementation object specifying + implementation of an RPC method. + multi_method_implementation: An face_interfaces.MultiMethodImplementation + or None. Returns: - A sequence of length three the first element of which is a - face_interfaces.Server, the second element of which is a - face_interfaces.Stub, (both of which are backed by the given method - implementations), and the third element of which is an arbitrary memo + A sequence of length two the first element of which is a + face_interfaces.GenericStub (backed by the given method + implementations), and the second element of which is an arbitrary memo object to be kept and passed to tearDownImplementation at the conclusion of the test. """ @@ -105,7 +74,7 @@ class FaceTestCase(object): """Destroys the Face layer implementation under test. Args: - memo: The object from the third position of the return value of + memo: The object from the second position of the return value of set_up_implementation. """ raise NotImplementedError() diff --git a/src/python/src/grpc/framework/face/utilities.py b/src/python/src/grpc/framework/face/utilities.py index 5e34be37da7a5e9c537db9f280b609bd6d649ece..a63fe8c60dfbb9d365625168a1b5a4075881edf2 100644 --- a/src/python/src/grpc/framework/face/utilities.py +++ b/src/python/src/grpc/framework/face/utilities.py @@ -27,101 +27,44 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Utilities for the face layer of RPC Framework.""" +"""Utilities for RPC framework's face layer.""" -# stream is referenced from specification in this module. -from grpc.framework.face import interfaces -from grpc.framework.foundation import stream # pylint: disable=unused-import - - -class _InlineUnaryUnaryMethod(interfaces.InlineValueInValueOutMethod): - - def __init__(self, behavior): - self._behavior = behavior - - def service(self, request, context): - return self._behavior(request, context) - - -class _InlineUnaryStreamMethod(interfaces.InlineValueInStreamOutMethod): - - def __init__(self, behavior): - self._behavior = behavior - - def service(self, request, context): - return self._behavior(request, context) - - -class _InlineStreamUnaryMethod(interfaces.InlineStreamInValueOutMethod): - - def __init__(self, behavior): - self._behavior = behavior - - def service(self, request_iterator, context): - return self._behavior(request_iterator, context) - - -class _InlineStreamStreamMethod(interfaces.InlineStreamInStreamOutMethod): - - def __init__(self, behavior): - self._behavior = behavior - - def service(self, request_iterator, context): - return self._behavior(request_iterator, context) +import collections +from grpc.framework.common import cardinality +from grpc.framework.common import style +from grpc.framework.face import interfaces +from grpc.framework.foundation import stream -class _EventUnaryUnaryMethod(interfaces.EventValueInValueOutMethod): - - def __init__(self, behavior): - self._behavior = behavior - - def service(self, request, response_callback, context): - return self._behavior(request, response_callback, context) - - -class _EventUnaryStreamMethod(interfaces.EventValueInStreamOutMethod): - - def __init__(self, behavior): - self._behavior = behavior - - def service(self, request, response_consumer, context): - return self._behavior(request, response_consumer, context) - - -class _EventStreamUnaryMethod(interfaces.EventStreamInValueOutMethod): - - def __init__(self, behavior): - self._behavior = behavior - - def service(self, response_callback, context): - return self._behavior(response_callback, context) - - -class _EventStreamStreamMethod(interfaces.EventStreamInStreamOutMethod): - - def __init__(self, behavior): - self._behavior = behavior - def service(self, response_consumer, context): - return self._behavior(response_consumer, context) +class _MethodImplementation( + interfaces.MethodImplementation, + collections.namedtuple( + '_MethodImplementation', + ['cardinality', 'style', 'unary_unary_inline', 'unary_stream_inline', + 'stream_unary_inline', 'stream_stream_inline', 'unary_unary_event', + 'unary_stream_event', 'stream_unary_event', 'stream_stream_event',])): + pass -def inline_unary_unary_method(behavior): - """Creates an interfaces.InlineValueInValueOutMethod from a behavior. +def unary_unary_inline(behavior): + """Creates an interfaces.MethodImplementation for the given behavior. Args: - behavior: The implementation of a unary-unary RPC method as a callable - value that takes a request value and an interfaces.RpcContext object and + behavior: The implementation of a unary-unary RPC method as a callable value + that takes a request value and an interfaces.RpcContext object and returns a response value. Returns: - An interfaces.InlineValueInValueOutMethod derived from the given behavior. + An interfaces.MethodImplementation derived from the given behavior. """ - return _InlineUnaryUnaryMethod(behavior) + return _MethodImplementation( + cardinality.Cardinality.UNARY_UNARY, style.Service.INLINE, behavior, + None, None, None, None, None, None, None) -def inline_unary_stream_method(behavior): - """Creates an interfaces.InlineValueInStreamOutMethod from a behavior. +def unary_stream_inline(behavior): + """Creates an interfaces.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-stream RPC method as a callable @@ -129,13 +72,15 @@ def inline_unary_stream_method(behavior): returns an iterator of response values. Returns: - An interfaces.InlineValueInStreamOutMethod derived from the given behavior. + An interfaces.MethodImplementation derived from the given behavior. """ - return _InlineUnaryStreamMethod(behavior) + return _MethodImplementation( + cardinality.Cardinality.UNARY_STREAM, style.Service.INLINE, None, + behavior, None, None, None, None, None, None) -def inline_stream_unary_method(behavior): - """Creates an interfaces.InlineStreamInValueOutMethod from a behavior. +def stream_unary_inline(behavior): + """Creates an interfaces.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-unary RPC method as a callable @@ -143,13 +88,15 @@ def inline_stream_unary_method(behavior): interfaces.RpcContext object and returns a response value. Returns: - An interfaces.InlineStreamInValueOutMethod derived from the given behavior. + An interfaces.MethodImplementation derived from the given behavior. """ - return _InlineStreamUnaryMethod(behavior) + return _MethodImplementation( + cardinality.Cardinality.STREAM_UNARY, style.Service.INLINE, None, None, + behavior, None, None, None, None, None) -def inline_stream_stream_method(behavior): - """Creates an interfaces.InlineStreamInStreamOutMethod from a behavior. +def stream_stream_inline(behavior): + """Creates an interfaces.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-stream RPC method as a callable @@ -157,14 +104,15 @@ def inline_stream_stream_method(behavior): interfaces.RpcContext object and returns an iterator of response values. Returns: - An interfaces.InlineStreamInStreamOutMethod derived from the given - behavior. + An interfaces.MethodImplementation derived from the given behavior. """ - return _InlineStreamStreamMethod(behavior) + return _MethodImplementation( + cardinality.Cardinality.STREAM_STREAM, style.Service.INLINE, None, None, + None, behavior, None, None, None, None) -def event_unary_unary_method(behavior): - """Creates an interfaces.EventValueInValueOutMethod from a behavior. +def unary_unary_event(behavior): + """Creates an interfaces.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-unary RPC method as a callable @@ -172,27 +120,31 @@ def event_unary_unary_method(behavior): the response value of the RPC, and an interfaces.RpcContext. Returns: - An interfaces.EventValueInValueOutMethod derived from the given behavior. + An interfaces.MethodImplementation derived from the given behavior. """ - return _EventUnaryUnaryMethod(behavior) + return _MethodImplementation( + cardinality.Cardinality.UNARY_UNARY, style.Service.EVENT, None, None, + None, None, behavior, None, None, None) -def event_unary_stream_method(behavior): - """Creates an interfaces.EventValueInStreamOutMethod from a behavior. +def unary_stream_event(behavior): + """Creates an interfaces.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-stream RPC method as a callable value that takes a request value, a stream.Consumer to which to pass the - response values of the RPC, and an interfaces.RpcContext. + the response values of the RPC, and an interfaces.RpcContext. Returns: - An interfaces.EventValueInStreamOutMethod derived from the given behavior. + An interfaces.MethodImplementation derived from the given behavior. """ - return _EventUnaryStreamMethod(behavior) + return _MethodImplementation( + cardinality.Cardinality.UNARY_STREAM, style.Service.EVENT, None, None, + None, None, None, behavior, None, None) -def event_stream_unary_method(behavior): - """Creates an interfaces.EventStreamInValueOutMethod from a behavior. +def stream_unary_event(behavior): + """Creates an interfaces.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-unary RPC method as a callable @@ -201,13 +153,15 @@ def event_stream_unary_method(behavior): which the request values of the RPC should be passed. Returns: - An interfaces.EventStreamInValueOutMethod derived from the given behavior. + An interfaces.MethodImplementation derived from the given behavior. """ - return _EventStreamUnaryMethod(behavior) + return _MethodImplementation( + cardinality.Cardinality.STREAM_UNARY, style.Service.EVENT, None, None, + None, None, None, None, behavior, None) -def event_stream_stream_method(behavior): - """Creates an interfaces.EventStreamInStreamOutMethod from a behavior. +def stream_stream_event(behavior): + """Creates an interfaces.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-stream RPC method as a callable @@ -216,6 +170,8 @@ def event_stream_stream_method(behavior): which the request values of the RPC should be passed. Returns: - An interfaces.EventStreamInStreamOutMethod derived from the given behavior. + An interfaces.MethodImplementation derived from the given behavior. """ - return _EventStreamStreamMethod(behavior) + return _MethodImplementation( + cardinality.Cardinality.STREAM_STREAM, style.Service.EVENT, None, None, + None, None, None, None, None, behavior) diff --git a/src/python/src/setup.py b/src/python/src/setup.py index cdb82a9dc35208c03aa86c04edef50b5c260f6c2..a513a2811bdc25c52999784653df7800a44028fe 100644 --- a/src/python/src/setup.py +++ b/src/python/src/setup.py @@ -64,7 +64,6 @@ _PACKAGES = ( 'grpc._junkdrawer', 'grpc.early_adopter', 'grpc.framework', - 'grpc.framework.assembly', 'grpc.framework.base', 'grpc.framework.base.packets', 'grpc.framework.common', diff --git a/src/ruby/bin/interop/interop_server.rb b/src/ruby/bin/interop/interop_server.rb index b3b7d0c5a3a90f3eca27fac7ae34673f6197e6a6..0819ba9bbcc1d791091a7a9de38514e0e296d434 100755 --- a/src/ruby/bin/interop/interop_server.rb +++ b/src/ruby/bin/interop/interop_server.rb @@ -176,12 +176,11 @@ end def main opts = parse_options host = "0.0.0.0:#{opts['port']}" + s = GRPC::RpcServer.new if opts['secure'] - s = GRPC::RpcServer.new(creds: test_server_creds) - s.add_http2_port(host, true) + s.add_http2_port(host, test_server_creds) logger.info("... running securely on #{host}") else - s = GRPC::RpcServer.new s.add_http2_port(host) logger.info("... running insecurely on #{host}") end diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb index 93277e39320c4948cdd5fc46815da2feab4716ad..5cc76134893c225f12e5f22d9feb5f18da64a525 100755 --- a/src/ruby/bin/math_server.rb +++ b/src/ruby/bin/math_server.rb @@ -173,12 +173,11 @@ def main end end.parse! + s = GRPC::RpcServer.new if options['secure'] - s = GRPC::RpcServer.new(creds: test_server_creds) - s.add_http2_port(options['host'], true) + s.add_http2_port(options['host'], test_server_creds) logger.info("... running securely on #{options['host']}") else - s = GRPC::RpcServer.new s.add_http2_port(options['host']) logger.info("... running insecurely on #{options['host']}") end diff --git a/src/ruby/bin/noproto_server.rb b/src/ruby/bin/noproto_server.rb index 435f8f4ebf495aec964d271a1a609a47fc532014..9979cb7ebbdd693e08f730d281f6213f316331b8 100755 --- a/src/ruby/bin/noproto_server.rb +++ b/src/ruby/bin/noproto_server.rb @@ -95,12 +95,11 @@ def main end end.parse! + s = GRPC::RpcServer.new if options['secure'] - s = GRPC::RpcServer.new(creds: test_server_creds) - s.add_http2_port(options['host'], true) + s.add_http2_port(options['host'], test_server_creds) logger.info("... running securely on #{options['host']}") else - s = GRPC::RpcServer.new s.add_http2_port(options['host']) logger.info("... running insecurely on #{options['host']}") end diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb index 483a31f60cce5df7f0bc4a58c312534444ff1d26..f15f85bf56dca4b52e0ac57fa11fb3085df46448 100644 --- a/src/ruby/ext/grpc/extconf.rb +++ b/src/ruby/ext/grpc/extconf.rb @@ -77,7 +77,6 @@ end dir_config('grpc', HEADER_DIRS, LIB_DIRS) -$CFLAGS << ' -std=c89 ' $CFLAGS << ' -Wno-implicit-function-declaration ' $CFLAGS << ' -Wno-pointer-sign ' $CFLAGS << ' -Wno-return-type ' diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c index c7671c8a775098597e4f8b752d001de4c4d274cc..400efd0dfad8d3909e7fe4049a3e6ebef235f351 100644 --- a/src/ruby/ext/grpc/rb_grpc.c +++ b/src/ruby/ext/grpc/rb_grpc.c @@ -119,12 +119,12 @@ gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) { break; case T_FLOAT: - if (interval && RFLOAT(time)->float_value < 0.0) + if (interval && RFLOAT_VALUE(time) < 0.0) rb_raise(rb_eArgError, "%s must be positive", tstr); else { double f, d; - d = modf(RFLOAT(time)->float_value, &f); + d = modf(RFLOAT_VALUE(time), &f); if (d < 0) { d += 1; f -= 1; @@ -132,7 +132,7 @@ gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) { t.tv_sec = (time_t)f; if (f != t.tv_sec) { rb_raise(rb_eRangeError, "%f out of Time range", - RFLOAT(time)->float_value); + RFLOAT_VALUE(time)); } t.tv_nsec = (time_t)(d * 1e9 + 0.5); } diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 5954e27d0249e8315f67553dc2aeadf4b0cf396a..c54f02e87afac11a2ea8f3c4a28406a460fe51dd 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -97,35 +97,19 @@ static VALUE grpc_rb_server_alloc(VALUE cls) { /* call-seq: cq = CompletionQueue.new - insecure_server = Server.new(cq, {'arg1': 'value1'}) - server_creds = ... - secure_server = Server.new(cq, {'arg1': 'value1'}, server_creds) + server = Server.new(cq, {'arg1': 'value1'}) Initializes server instances. */ -static VALUE grpc_rb_server_init(int argc, VALUE *argv, VALUE self) { - VALUE cqueue = Qnil; - VALUE credentials = Qnil; - VALUE channel_args = Qnil; +static VALUE grpc_rb_server_init(VALUE self, VALUE cqueue, VALUE channel_args) { grpc_completion_queue *cq = NULL; - grpc_server_credentials *creds = NULL; grpc_rb_server *wrapper = NULL; grpc_server *srv = NULL; grpc_channel_args args; MEMZERO(&args, grpc_channel_args, 1); - - /* "21" == 2 mandatory args, 1 (credentials) is optional */ - rb_scan_args(argc, argv, "21", &cqueue, &channel_args, &credentials); cq = grpc_rb_get_wrapped_completion_queue(cqueue); - Data_Get_Struct(self, grpc_rb_server, wrapper); grpc_rb_hash_convert_to_channel_args(channel_args, &args); srv = grpc_server_create(cq, &args); - if (credentials == Qnil) { - srv = grpc_server_create(cq, &args); - } else { - creds = grpc_rb_get_wrapped_server_credentials(credentials); - srv = grpc_secure_server_create(creds, cq, &args); - } if (args.args != NULL) { xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */ @@ -215,33 +199,36 @@ static VALUE grpc_rb_server_destroy(VALUE self) { // secure port server_creds = ... - secure_server = Server.new(cq, {'arg1': 'value1'}, creds) - secure_server.add_http_port('mydomain:7575', True) + secure_server = Server.new(cq, {'arg1': 'value1'}) + secure_server.add_http_port('mydomain:7575', server_creds) Adds a http2 port to server */ static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) { VALUE port = Qnil; - VALUE is_secure = Qnil; + VALUE rb_creds = Qnil; grpc_rb_server *s = NULL; + grpc_server_credentials *creds = NULL; int recvd_port = 0; - /* "11" == 1 mandatory args, 1 (is_secure) is optional */ - rb_scan_args(argc, argv, "11", &port, &is_secure); + /* "11" == 1 mandatory args, 1 (rb_creds) is optional */ + rb_scan_args(argc, argv, "11", &port, &rb_creds); Data_Get_Struct(self, grpc_rb_server, s); if (s->wrapped == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; - } else if (is_secure == Qnil || TYPE(is_secure) != T_TRUE) { + } else if (rb_creds == Qnil) { recvd_port = grpc_server_add_http2_port(s->wrapped, StringValueCStr(port)); if (recvd_port == 0) { rb_raise(rb_eRuntimeError, "could not add port %s to server, not sure why", StringValueCStr(port)); } - } else if (TYPE(is_secure) != T_FALSE) { + } else { + creds = grpc_rb_get_wrapped_server_credentials(rb_creds); recvd_port = - grpc_server_add_secure_http2_port(s->wrapped, StringValueCStr(port)); + grpc_server_add_secure_http2_port(s->wrapped, StringValueCStr(port), + creds); if (recvd_port == 0) { rb_raise(rb_eRuntimeError, "could not add secure port %s to server, not sure why", @@ -258,7 +245,7 @@ void Init_grpc_server() { rb_define_alloc_func(rb_cServer, grpc_rb_server_alloc); /* Provides a ruby constructor and support for dup/clone. */ - rb_define_method(rb_cServer, "initialize", grpc_rb_server_init, -1); + rb_define_method(rb_cServer, "initialize", grpc_rb_server_init, 2); rb_define_method(rb_cServer, "initialize_copy", grpc_rb_server_init_copy, 1); /* Add the server methods. */ diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec index ed26fef4a97a3e381d30cf9503dc62f2a240b34e..45cbacfeb04de3cf6ca43bbf2ee227cf1861e4e4 100755 --- a/src/ruby/grpc.gemspec +++ b/src/ruby/grpc.gemspec @@ -21,14 +21,10 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.platform = Gem::Platform::RUBY - s.add_dependency 'faraday', '~> 0.9' s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1' s.add_dependency 'googleauth', '~> 0.1' s.add_dependency 'logging', '~> 1.8' - s.add_dependency 'jwt', '~> 1.2.1' s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests - s.add_dependency 'multi_json', '1.10.1' - s.add_dependency 'signet', '~> 0.6.0' s.add_dependency 'xray', '~> 1.1' s.add_development_dependency 'bundler', '~> 1.7' diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb index f234984eec3a4f4bde3d0d7cfe5528e56c1fcd65..01328d4a5bc68895716942b1f360ed0c9b911d7e 100644 --- a/src/ruby/lib/grpc/generic/client_stub.rb +++ b/src/ruby/lib/grpc/generic/client_stub.rb @@ -39,6 +39,25 @@ module GRPC # Default deadline is 5 seconds. DEFAULT_DEADLINE = 5 + # setup_channel is used by #initialize to constuct a channel from its + # arguments. + def self.setup_channel(alt_chan, host, creds, **kw) + unless alt_chan.nil? + fail(TypeError, '!Channel') unless alt_chan.is_a?(Core::Channel) + return alt_chan + end + return Core::Channel.new(host, kw) if creds.nil? + fail(TypeError, '!Credentials') unless creds.is_a?(Core::Credentials) + Core::Channel.new(host, kw, creds) + end + + # check_update_metadata is used by #initialize verify that it's a Proc. + def self.check_update_metadata(update_metadata) + return update_metadata if update_metadata.nil? + fail(TypeError, '!is_a?Proc') unless update_metadata.is_a?(Proc) + update_metadata + end + # Creates a new ClientStub. # # Minimally, a stub is created with the just the host of the gRPC service @@ -73,40 +92,17 @@ module GRPC # @param update_metadata a func that updates metadata as described above # @param kw [KeywordArgs]the channel arguments def initialize(host, q, - channel_override:nil, + channel_override: nil, deadline: DEFAULT_DEADLINE, creds: nil, update_metadata: nil, **kw) - unless q.is_a? Core::CompletionQueue - fail(ArgumentError, 'not a CompletionQueue') - end + fail(TypeError, '!CompletionQueue') unless q.is_a?(Core::CompletionQueue) @queue = q - - # set the channel instance - if !channel_override.nil? - ch = channel_override - fail(ArgumentError, 'not a Channel') unless ch.is_a? Core::Channel - else - if creds.nil? - ch = Core::Channel.new(host, kw) - elsif !creds.is_a?(Core::Credentials) - fail(ArgumentError, 'not a Credentials') - else - ch = Core::Channel.new(host, kw, creds) - end - end - @ch = ch - - @update_metadata = nil - unless update_metadata.nil? - unless update_metadata.is_a? Proc - fail(ArgumentError, 'update_metadata is not a Proc') - end - @update_metadata = update_metadata - end - - @host = host + @ch = ClientStub.setup_channel(channel_override, host, creds, **kw) + @update_metadata = ClientStub.check_update_metadata(update_metadata) + alt_host = kw[Core::Channel::SSL_TARGET] + @host = alt_host.nil? ? host : alt_host @deadline = deadline end @@ -400,12 +396,7 @@ module GRPC # @param deadline [TimeConst] def new_active_call(ch, marshal, unmarshal, deadline = nil) absolute_deadline = Core::TimeConsts.from_relative_time(deadline) - # It should be OK to to pass the hostname:port to create_call, but at - # the moment this fails a security check. This will be corrected. - # - # TODO: # remove this after create_call is updated - host = @host.split(':')[0] - call = @ch.create_call(ch, host, absolute_deadline) + call = @ch.create_call(ch, @host, absolute_deadline) ActiveCall.new(call, @queue, marshal, unmarshal, absolute_deadline, started: false) end diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 6938f718922cfc21b463b2cbf8aa70f12218d038..35e84023be952df4fa5e846a14a8d26d4c166e26 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -81,7 +81,6 @@ module GRPC max_waiting_requests:DEFAULT_MAX_WAITING_REQUESTS, poll_period:INFINITE_FUTURE, completion_queue_override:nil, - creds:nil, server_override:nil, **kw) if completion_queue_override.nil? @@ -95,13 +94,7 @@ module GRPC @cq = cq if server_override.nil? - if creds.nil? - srv = Core::Server.new(@cq, kw) - elsif !creds.is_a? Core::ServerCredentials - fail(ArgumentError, 'not a ServerCredentials') - else - srv = Core::Server.new(@cq, kw, creds) - end + srv = Core::Server.new(@cq, kw) else srv = server_override fail(ArgumentError, 'not a Server') unless srv.is_a? Core::Server diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb index 030ff328f217db820f857ed2619cc9da11a679ca..49a2d3bb4df9fd00b7f5955b3fb70f66bba77e6d 100644 --- a/src/ruby/spec/client_server_spec.rb +++ b/src/ruby/spec/client_server_spec.rb @@ -95,7 +95,7 @@ shared_context 'setup: tags' do end def new_client_call - @ch.create_call('/method', 'localhost', deadline) + @ch.create_call('/method', 'foo.test.google.fr', deadline) end end @@ -346,12 +346,12 @@ end describe 'the secure http client/server' do before(:example) do certs = load_test_certs - server_host = 'localhost:0' + server_host = '0.0.0.0:0' @client_queue = GRPC::Core::CompletionQueue.new @server_queue = GRPC::Core::CompletionQueue.new server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) - @server = GRPC::Core::Server.new(@server_queue, nil, server_creds) - server_port = @server.add_http2_port(server_host, true) + @server = GRPC::Core::Server.new(@server_queue, nil) + server_port = @server.add_http2_port(server_host, server_creds) @server.start args = { Channel::SSL_TARGET => 'foo.test.google.fr' } @ch = Channel.new("0.0.0.0:#{server_port}", args, @@ -362,11 +362,9 @@ describe 'the secure http client/server' do @server.close end - # TODO: uncomment after updating the to the new c api - # it_behaves_like 'basic GRPC message delivery is OK' do - # end + it_behaves_like 'basic GRPC message delivery is OK' do + end - # TODO: uncomment after updating the to the new c api - # it_behaves_like 'GRPC metadata delivery works OK' do - # end + it_behaves_like 'GRPC metadata delivery works OK' do + end end diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb index e8c706044617a7775d84ce65f5bb448438dc4b92..d5421d400c99c9f14ae2c6c0609760ee623abe45 100644 --- a/src/ruby/spec/generic/rpc_server_spec.rb +++ b/src/ruby/spec/generic/rpc_server_spec.rb @@ -164,19 +164,6 @@ describe GRPC::RpcServer do expect(&blk).to raise_error end - it 'can be created with the creds as valid ServerCedentials' do - certs = load_test_certs - server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) - blk = proc do - opts = { - a_channel_arg: 'an_arg', - creds: server_creds - } - RpcServer.new(**opts) - end - expect(&blk).to_not raise_error - end - it 'can be created with a server override' do opts = { a_channel_arg: 'an_arg', server_override: @server } blk = proc do diff --git a/src/ruby/spec/server_spec.rb b/src/ruby/spec/server_spec.rb index 5b81f195371d9b8a3b2301cc335b8bf160d7f63b..a47e484f9719c28c27fd4c6c485c74e08942bc45 100644 --- a/src/ruby/spec/server_spec.rb +++ b/src/ruby/spec/server_spec.rb @@ -118,10 +118,11 @@ describe Server do end describe 'for secure servers' do + let(:cert) { create_test_cert } it 'runs without failing' do blk = proc do s = Server.new(@cq, nil) - s.add_http2_port('localhost:0', true) + s.add_http2_port('localhost:0', cert) s.close end expect(&blk).to_not raise_error @@ -130,7 +131,7 @@ describe Server do it 'fails if the server is closed' do s = Server.new(@cq, nil) s.close - blk = proc { s.add_http2_port('localhost:0', true) } + blk = proc { s.add_http2_port('localhost:0', cert) } expect(&blk).to raise_error(RuntimeError) end end @@ -138,7 +139,7 @@ describe Server do shared_examples '#new' do it 'takes a completion queue with nil channel args' do - expect { Server.new(@cq, nil, create_test_cert) }.to_not raise_error + expect { Server.new(@cq, nil) }.to_not raise_error end it 'does not take a hash with bad keys as channel args' do @@ -195,14 +196,6 @@ describe Server do it_behaves_like '#new' end - describe '#new with a secure channel' do - def construct_with_args(a) - proc { Server.new(@cq, a, create_test_cert) } - end - - it_behaves_like '#new' - end - def start_a_server s = Server.new(@cq, nil) s.add_http2_port('0.0.0.0:0') diff --git a/templates/Makefile.template b/templates/Makefile.template index 24fd450dff58d3bad204d37e6980a53fade756d5..6573e03f7f55746d73cc48d8fdcd9e1fd4236ada 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -917,7 +917,7 @@ PUBLIC_HEADERS_C += \\ LIB${lib.name.upper()}_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIB${lib.name.upper()}_SRC)))) ## If the library requires OpenSSL with ALPN, let's add some restrictions. -% if lib.get('secure', True): +% if lib.get('secure', 'check') == 'yes' or lib.get('secure', 'check') == 'check': ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL with ALPN. @@ -993,14 +993,14 @@ $(LIBDIR)/$(CONFIG)/lib${lib.name}.a: $(ZLIB_DEP)\ $(Q) rm -f $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(Q) $(AR) rcs $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(LIB${lib.name.upper()}_OBJS) % if lib.get('baselib', False): -% if lib.get('secure', True): - $(Q) rm -rf tmp-merge - $(Q) mkdir tmp-merge - $(Q) ( cd tmp-merge ; $(AR) x ../$(LIBDIR)/$(CONFIG)/lib${lib.name}.a ) - $(Q) for l in $(OPENSSL_MERGE_LIBS) ; do ( cd tmp-merge ; <%text>ar x ../$${l}</%text> ) ; done - $(Q) rm -f $(LIBDIR)/$(CONFIG)/lib${lib.name}.a tmp-merge/__.SYMDEF* - $(Q) ar rcs $(LIBDIR)/$(CONFIG)/lib${lib.name}.a tmp-merge/* - $(Q) rm -rf tmp-merge +% if lib.get('secure', 'check') == 'yes': + $(Q) rm -rf tmp-merge-${lib.name} + $(Q) mkdir tmp-merge-${lib.name} + $(Q) ( cd tmp-merge-${lib.name} ; $(AR) x ../$(LIBDIR)/$(CONFIG)/lib${lib.name}.a ) + $(Q) for l in $(OPENSSL_MERGE_LIBS) ; do ( cd tmp-merge-${lib.name} ; <%text>ar x ../$${l}</%text> ) ; done + $(Q) rm -f $(LIBDIR)/$(CONFIG)/lib${lib.name}.a tmp-merge-${lib.name}/__.SYMDEF* + $(Q) ar rcs $(LIBDIR)/$(CONFIG)/lib${lib.name}.a tmp-merge-${lib.name}/* + $(Q) rm -rf tmp-merge-${lib.name} % endif % endif ifeq ($(SYSTEM),Darwin) @@ -1028,8 +1028,10 @@ endif mingw_libs = mingw_libs + ' -l' + dep + '-imp' mingw_lib_deps = mingw_lib_deps + '$(LIBDIR)/$(CONFIG)/' + dep + '.$(SHARED_EXT)' - if lib.get('secure', True): + if lib.get('secure', 'check') == 'yes': common = common + ' $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS)' + + if lib.get('secure', 'check') == 'yes' or lib.get('secure', 'check') == 'check': lib_deps = lib_deps + ' $(OPENSSL_DEP)' mingw_lib_deps = mingw_lib_deps + ' $(OPENSSL_DEP)' @@ -1056,7 +1058,7 @@ else endif endif % endif -% if lib.get('secure', True): +% if lib.get('secure', 'check') == 'yes' or lib.get('secure', 'check') == 'check': ## If the lib was secure, we have to close the Makefile's if that tested ## the presence of an ALPN-capable OpenSSL. @@ -1069,13 +1071,13 @@ endif endif % endif -% if lib.get('secure', True): +% if lib.get('secure', 'check') == 'yes' or lib.get('secure', 'check') == 'check': ifneq ($(NO_SECURE),true) % endif ifneq ($(NO_DEPS),true) -include $(LIB${lib.name.upper()}_OBJS:.o=.dep) endif -% if lib.get('secure', True): +% if lib.get('secure', 'check') == 'yes' or lib.get('secure', 'check') == 'check': endif % endif @@ -1102,7 +1104,7 @@ ${tgt.name.upper()}_SRC = \\ ${tgt.name.upper()}_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(${tgt.name.upper()}_SRC)))) -% if tgt.get('secure', True): +% if tgt.get('secure', 'check') == 'yes' or tgt.get('secure', 'check') == 'check': ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL with ALPN. @@ -1176,7 +1178,7 @@ $(BINDIR)/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\ % endif % if tgt.build == 'protoc': $(HOST_LDLIBS_PROTOC)\ -% elif tgt.get('secure', True): +% elif tgt.get('secure', 'check') == 'yes' or tgt.get('secure', 'check') == 'check': $(LDLIBS_SECURE)\ % endif -o $(BINDIR)/$(CONFIG)/${tgt.name} @@ -1184,7 +1186,7 @@ $(BINDIR)/$(CONFIG)/${tgt.name}: $(${tgt.name.upper()}_OBJS)\ endif % endif -% if tgt.get('secure', True): +% if tgt.get('secure', 'check') == 'yes' or tgt.get('secure', 'check') == 'check': endif % endif @@ -1199,13 +1201,13 @@ $(OBJDIR)/$(CONFIG)/${os.path.splitext(src)[0]}.o: \ deps_${tgt.name}: $(${tgt.name.upper()}_OBJS:.o=.dep) -% if tgt.get('secure', True): +% if tgt.get('secure', 'check') == 'yes' or tgt.get('secure', 'check') == 'check': ifneq ($(NO_SECURE),true) % endif ifneq ($(NO_DEPS),true) -include $(${tgt.name.upper()}_OBJS:.o=.dep) endif -% if tgt.get('secure', True): +% if tgt.get('secure', 'check') == 'yes' or tgt.get('secure', 'check') == 'check': endif % endif </%def> diff --git a/test/compiler/python_plugin_test.py b/test/compiler/python_plugin_test.py index f16682862c32a76ac635f2e95390dede819140f3..9cf3c624c05d3be3731bc1c60f164971b0da7a8c 100644 --- a/test/compiler/python_plugin_test.py +++ b/test/compiler/python_plugin_test.py @@ -32,8 +32,10 @@ import contextlib import errno import itertools import os +import shutil import subprocess import sys +import tempfile import time import unittest @@ -55,8 +57,8 @@ DOES_NOT_MATTER_DELAY = 0 NO_DELAY = 0 LONG_DELAY = 1 -# Assigned in __main__. -_build_mode = None +# Build mode environment variable set by tools/run_tests/run_tests.py. +_build_mode = os.environ['CONFIG'] class _ServicerMethods(object): @@ -227,24 +229,26 @@ class PythonPluginTest(unittest.TestCase): protoc_command = 'protoc' # Ensure that the output directory exists. - outdir = '../../gens/test/compiler/python' - try: - os.makedirs(outdir) - except OSError as exception: - if exception.errno != errno.EEXIST: - raise + self.outdir = tempfile.mkdtemp() # Invoke protoc with the plugin. cmd = [ protoc_command, '--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename, '-I %s' % os.path.dirname(test_proto_filename), - '--python_out=%s' % outdir, - '--python-grpc_out=%s' % outdir, + '--python_out=%s' % self.outdir, + '--python-grpc_out=%s' % self.outdir, os.path.basename(test_proto_filename), ] subprocess.call(' '.join(cmd), shell=True) - sys.path.append(outdir) + sys.path.append(self.outdir) + + def tearDown(self): + try: + shutil.rmtree(self.outdir) + except OSError as exc: + if exc.errno != errno.ENOENT: + raise # TODO(atash): Figure out which of theses tests is hanging flakily with small # probability. @@ -296,6 +300,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ExpirationError): response_future.result() + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testUnaryCallAsyncCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top request = test_pb2.SimpleRequest(response_size=13) @@ -325,6 +331,8 @@ class PythonPluginTest(unittest.TestCase): expected_response, response = check self.assertEqual(expected_response, response) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testStreamingOutputCallExpired(self): import test_pb2 # pylint: disable=g-import-not-at-top request = StreamingOutputRequest(test_pb2) @@ -335,6 +343,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ExpirationError): list(responses) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testStreamingOutputCallCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top request = StreamingOutputRequest(test_pb2) @@ -359,6 +369,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ServicerError): next(responses) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testStreamingInputCall(self): import test_pb2 # pylint: disable=g-import-not-at-top with _CreateService(test_pb2, NO_DELAY) as (servicer, stub, unused_server): @@ -426,6 +438,8 @@ class PythonPluginTest(unittest.TestCase): expected_response, response = check self.assertEqual(expected_response, response) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testFullDuplexCallExpired(self): import test_pb2 # pylint: disable=g-import-not-at-top request = FullDuplexRequest(test_pb2) @@ -436,6 +450,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ExpirationError): list(responses) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testFullDuplexCallCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top with _CreateService(test_pb2, NO_DELAY) as (servicer, stub, unused_server): @@ -459,6 +475,8 @@ class PythonPluginTest(unittest.TestCase): with self.assertRaises(exceptions.ServicerError): next(responses) + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') def testHalfDuplexCall(self): import test_pb2 # pylint: disable=g-import-not-at-top with _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) as ( @@ -502,14 +520,4 @@ class PythonPluginTest(unittest.TestCase): if __name__ == '__main__': os.chdir(os.path.dirname(sys.argv[0])) - parser = argparse.ArgumentParser( - description='Run Python compiler plugin test.') - parser.add_argument( - '--build_mode', dest='build_mode', type=str, default='dbg', - help='The build mode of the targets to test, e.g. "dbg", "opt", "asan", ' - 'etc.') - parser.add_argument('--port', dest='port', type=int, default=0) - args, remainder = parser.parse_known_args() - _build_mode = args.build_mode - sys.argv[1:] = remainder unittest.main() diff --git a/test/core/echo/server.c b/test/core/echo/server.c index bc84645a0405572d4a9a122a42c761095a614797..e888a0c8770984b2242d2ef1af9aa89f1a0908da 100644 --- a/test/core/echo/server.c +++ b/test/core/echo/server.c @@ -143,8 +143,8 @@ int main(int argc, char **argv) { test_server1_cert}; grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1); - server = grpc_secure_server_create(ssl_creds, cq, &args); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr)); + server = grpc_server_create(cq, &args); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); grpc_server_credentials_release(ssl_creds); } else { server = grpc_server_create(cq, &args); diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h index b6d93252eb282cddce9cf115a21055e7f65c31a1..41c6e2ee0c63f1aabd08d894eeec9a8c97c30ea4 100644 --- a/test/core/end2end/end2end_tests.h +++ b/test/core/end2end/end2end_tests.h @@ -40,6 +40,7 @@ typedef struct grpc_end2end_test_fixture grpc_end2end_test_fixture; typedef struct grpc_end2end_test_config grpc_end2end_test_config; #define FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION 1 +#define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION 2 struct grpc_end2end_test_fixture { grpc_completion_queue *server_cq; diff --git a/test/core/end2end/fixtures/chttp2_fake_security.c b/test/core/end2end/fixtures/chttp2_fake_security.c index 247d1fd32232d2a2183e91764004e3c53d9051f6..047d482be340f75da8495a6941471f12c112240d 100644 --- a/test/core/end2end/fixtures/chttp2_fake_security.c +++ b/test/core/end2end/fixtures/chttp2_fake_security.c @@ -84,9 +84,9 @@ static void chttp2_init_server_secure_fullstack( grpc_server_destroy(f->server); } f->server = - grpc_secure_server_create(server_creds, f->server_cq, server_args); + grpc_server_create(f->server_cq, server_args); + GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, server_creds)); grpc_server_credentials_release(server_creds); - GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr)); grpc_server_start(f->server); } diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c index 16946d5f97eef828367cd319d230457bad167db3..16433f5f87cdfee694bccf088c0b4865b05ef428 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c @@ -87,9 +87,9 @@ static void chttp2_init_server_secure_fullstack( grpc_server_destroy(f->server); } f->server = - grpc_secure_server_create(server_creds, f->server_cq, server_args); + grpc_server_create(f->server_cq, server_args); + GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, server_creds)); grpc_server_credentials_release(server_creds); - GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr)); grpc_server_start(f->server); } @@ -123,7 +123,9 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( /* All test configurations */ static grpc_end2end_test_config configs[] = { - {"chttp2/simple_ssl_fullstack", FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, + {"chttp2/simple_ssl_fullstack", + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION, chttp2_create_fixture_secure_fullstack, chttp2_init_client_simple_ssl_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack, diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c index c451e01024a412f3d7a44856f3b05a9f67d0bd03..99031df8e5459b996314626607511e06d7982e2a 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c @@ -85,9 +85,9 @@ static void chttp2_init_server_secure_fullstack( grpc_server_destroy(f->server); } f->server = - grpc_secure_server_create(server_creds, f->server_cq, server_args); + grpc_server_create(f->server_cq, server_args); + GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, server_creds)); grpc_server_credentials_release(server_creds); - GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr)); grpc_server_start(f->server); } @@ -129,7 +129,8 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( static grpc_end2end_test_config configs[] = { {"chttp2/simple_ssl_with_oauth2_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION, + FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | + FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION, chttp2_create_fixture_secure_fullstack, chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack, chttp2_init_server_simple_ssl_secure_fullstack, diff --git a/test/core/end2end/gen_build_json.py b/test/core/end2end/gen_build_json.py index 4e297b30becb793c606fb43f8c5050619142abdb..67fc0a6e539457c4a914d6a24b028b0db187c0ac 100755 --- a/test/core/end2end/gen_build_json.py +++ b/test/core/end2end/gen_build_json.py @@ -46,6 +46,7 @@ END2END_FIXTURES = [ END2END_TESTS = [ + 'bad_hostname', 'cancel_after_accept', 'cancel_after_accept_and_writes_closed', 'cancel_after_invoke', @@ -106,7 +107,7 @@ def main(): 'name': 'end2end_fixture_%s' % f, 'build': 'private', 'language': 'c', - 'secure': True, + 'secure': 'check', 'src': ['test/core/end2end/fixtures/%s.c' % f] } for f in END2END_FIXTURES] + [ @@ -114,7 +115,7 @@ def main(): 'name': 'end2end_test_%s' % t, 'build': 'private', 'language': 'c', - 'secure': False, + 'secure': 'no', 'src': ['test/core/end2end/tests/%s.c' % t], 'headers': ['test/core/end2end/tests/cancel_test_helpers.h'] } diff --git a/test/core/end2end/tests/bad_hostname.c b/test/core/end2end/tests/bad_hostname.c new file mode 100644 index 0000000000000000000000000000000000000000..80922f3b6f9e390180acde425887608d0fb5715d --- /dev/null +++ b/test/core/end2end/tests/bad_hostname.c @@ -0,0 +1,176 @@ +/* + * + * 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 "test/core/end2end/end2end_tests.h" + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "src/core/support/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 "test/core/end2end/cq_verifier.h" + +enum { TIMEOUT = 200000 }; + +static void *tag(gpr_intptr 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_client(&f, client_args); + config.init_server(&f, server_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; + grpc_completion_type type; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time()); + GPR_ASSERT(ev); + type = ev->type; + grpc_event_finish(ev); + } while (type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown(f->server); + 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->server_cq); + drain_cq(f->server_cq); + grpc_completion_queue_destroy(f->server_cq); + grpc_completion_queue_shutdown(f->client_cq); + drain_cq(f->client_cq); + grpc_completion_queue_destroy(f->client_cq); +} + +static void simple_request_body(grpc_end2end_test_fixture f) { + grpc_call *c; + gpr_timespec deadline = five_seconds_time(); + cq_verifier *v_client = cq_verifier_create(f.client_cq); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_call_details call_details; + grpc_status_code status; + char *details = NULL; + size_t details_capacity = 0; + + c = grpc_channel_create_call(f.client, f.client_cq, "/foo", + "slartibartfast.local", deadline); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->data.recv_status_on_client.status_details_capacity = &details_capacity; + op++; + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1))); + + cq_expect_completion(v_client, tag(1), GRPC_OP_OK); + cq_verify(v_client); + + GPR_ASSERT(status == GRPC_STATUS_UNAUTHENTICATED); + + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_destroy(c); + + cq_verifier_destroy(v_client); +} + +static void test_invoke_simple_request(grpc_end2end_test_config config) { + grpc_end2end_test_fixture f; + + f = begin_test(config, __FUNCTION__, NULL, NULL); + simple_request_body(f); + end_test(&f); + config.tear_down_data(&f); +} + +void grpc_end2end_tests(grpc_end2end_test_config config) { + if (config.feature_mask & FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION) { + test_invoke_simple_request(config); + } +} diff --git a/test/core/fling/server.c b/test/core/fling/server.c index 5c1ab14d03477cced84afb85cd07cc1d2408e73b..ca39cd84b13407d0d6c01c5b7a5f3d4737f26fd6 100644 --- a/test/core/fling/server.c +++ b/test/core/fling/server.c @@ -205,8 +205,8 @@ int main(int argc, char **argv) { test_server1_cert}; grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1); - server = grpc_secure_server_create(ssl_creds, cq, NULL); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr)); + server = grpc_server_create(cq, NULL); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); grpc_server_credentials_release(ssl_creds); } else { server = grpc_server_create(cq, NULL); diff --git a/test/core/network_benchmarks/low_level_ping_pong.c b/test/core/network_benchmarks/low_level_ping_pong.c index f0a3e26c4eeb82bf6aa794de3ee9d4e3f0b779d0..7d74d0e0781f015c8c219ee756eb23067251a762 100644 --- a/test/core/network_benchmarks/low_level_ping_pong.c +++ b/test/core/network_benchmarks/low_level_ping_pong.c @@ -81,7 +81,7 @@ typedef struct thread_args { /* Basic call to read() */ static int read_bytes(int fd, char *buf, size_t read_size, int spin) { - int bytes_read = 0; + size_t bytes_read = 0; int err; do { err = read(fd, buf + bytes_read, read_size - bytes_read); @@ -198,7 +198,7 @@ static int epoll_read_bytes_spin(struct thread_args *args, char *buf) { writes go directly out to the kernel. */ static int blocking_write_bytes(struct thread_args *args, char *buf) { - int bytes_written = 0; + size_t bytes_written = 0; int err; size_t write_size = args->msg_size; do { @@ -586,10 +586,10 @@ static int run_benchmark(char *socket_type, thread_args *client_args, static int run_all_benchmarks(int msg_size) { int error = 0; - int i; + size_t i; for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) { test_strategy *test_strategy = &test_strategies[i]; - int j; + size_t j; for (j = 0; j < GPR_ARRAY_SIZE(socket_types); ++j) { thread_args *client_args = malloc(sizeof(thread_args)); thread_args *server_args = malloc(sizeof(thread_args)); @@ -620,7 +620,7 @@ int main(int argc, char **argv) { int msg_size = -1; char *read_strategy = NULL; char *socket_type = NULL; - int i; + size_t i; const test_strategy *test_strategy = NULL; int error = 0; @@ -654,7 +654,7 @@ int main(int argc, char **argv) { } for (i = 0; i < GPR_ARRAY_SIZE(test_strategies); ++i) { - if (!strcmp(test_strategies[i].name, read_strategy)) { + if (strcmp(test_strategies[i].name, read_strategy) == 0) { test_strategy = &test_strategies[i]; } } diff --git a/test/core/security/base64_test.c b/test/core/security/base64_test.c index bfd5c4877728f5c363aef374d1976dea9ae50315..a922896bc3d59d2019706e623b2e050d7b4c0e03 100644 --- a/test/core/security/base64_test.c +++ b/test/core/security/base64_test.c @@ -58,8 +58,8 @@ static void test_simple_encode_decode_b64(int url_safe, int multiline) { grpc_base64_encode(hello, strlen(hello), url_safe, multiline); gpr_slice hello_slice = grpc_base64_decode(hello_b64, url_safe); GPR_ASSERT(GPR_SLICE_LENGTH(hello_slice) == strlen(hello)); - GPR_ASSERT(!strncmp((const char *)GPR_SLICE_START_PTR(hello_slice), hello, - GPR_SLICE_LENGTH(hello_slice))); + GPR_ASSERT(strncmp((const char *)GPR_SLICE_START_PTR(hello_slice), hello, + GPR_SLICE_LENGTH(hello_slice)) == 0); gpr_slice_unref(hello_slice); gpr_free(hello_b64); @@ -141,31 +141,31 @@ static void test_rfc4648_test_vectors(void) { char *b64; b64 = grpc_base64_encode("", 0, 0, 0); - GPR_ASSERT(!strcmp("", b64)); + GPR_ASSERT(strcmp("", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("f", 1, 0, 0); - GPR_ASSERT(!strcmp("Zg==", b64)); + GPR_ASSERT(strcmp("Zg==", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("fo", 2, 0, 0); - GPR_ASSERT(!strcmp("Zm8=", b64)); + GPR_ASSERT(strcmp("Zm8=", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("foo", 3, 0, 0); - GPR_ASSERT(!strcmp("Zm9v", b64)); + GPR_ASSERT(strcmp("Zm9v", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("foob", 4, 0, 0); - GPR_ASSERT(!strcmp("Zm9vYg==", b64)); + GPR_ASSERT(strcmp("Zm9vYg==", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("fooba", 5, 0, 0); - GPR_ASSERT(!strcmp("Zm9vYmE=", b64)); + GPR_ASSERT(strcmp("Zm9vYmE=", b64) == 0); gpr_free(b64); b64 = grpc_base64_encode("foobar", 6, 0, 0); - GPR_ASSERT(!strcmp("Zm9vYmFy", b64)); + GPR_ASSERT(strcmp("Zm9vYmFy", b64) == 0); gpr_free(b64); } diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 50ef2d7657e3ee2a907e49e97dd0744ed2dfe40a..078462410ad6df115e3efc064e763561f7c3f818 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -143,9 +143,10 @@ static void test_oauth2_token_fetcher_creds_parsing_ok(void) { GRPC_CREDENTIALS_OK); GPR_ASSERT(token_lifetime.tv_sec == 3599); GPR_ASSERT(token_lifetime.tv_nsec == 0); - GPR_ASSERT(!strcmp(grpc_mdstr_as_c_string(token_elem->key), "Authorization")); - GPR_ASSERT(!strcmp(grpc_mdstr_as_c_string(token_elem->value), - "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_")); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(token_elem->key), + "Authorization") == 0); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(token_elem->value), + "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == 0); grpc_mdelem_unref(token_elem); grpc_mdctx_unref(ctx); } @@ -294,15 +295,16 @@ static void test_ssl_oauth2_composite_creds(void) { grpc_composite_credentials_create(ssl_creds, oauth2_creds); grpc_credentials_unref(ssl_creds); grpc_credentials_unref(oauth2_creds); - GPR_ASSERT(!strcmp(composite_creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)); + GPR_ASSERT(strcmp(composite_creds->type, + GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0); GPR_ASSERT(grpc_credentials_has_request_metadata(composite_creds)); GPR_ASSERT(!grpc_credentials_has_request_metadata_only(composite_creds)); creds_array = grpc_composite_credentials_get_credentials(composite_creds); GPR_ASSERT(creds_array->num_creds == 2); - GPR_ASSERT( - !strcmp(creds_array->creds_array[0]->type, GRPC_CREDENTIALS_TYPE_SSL)); - GPR_ASSERT( - !strcmp(creds_array->creds_array[1]->type, GRPC_CREDENTIALS_TYPE_OAUTH2)); + GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, + GRPC_CREDENTIALS_TYPE_SSL) == 0); + GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, + GRPC_CREDENTIALS_TYPE_OAUTH2) == 0); grpc_credentials_get_request_metadata(composite_creds, test_service_url, check_ssl_oauth2_composite_metadata, composite_creds); @@ -338,17 +340,18 @@ static void test_ssl_oauth2_iam_composite_creds(void) { grpc_credentials_unref(oauth2_creds); grpc_credentials_unref(aux_creds); grpc_credentials_unref(iam_creds); - GPR_ASSERT(!strcmp(composite_creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)); + GPR_ASSERT(strcmp(composite_creds->type, + GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0); GPR_ASSERT(grpc_credentials_has_request_metadata(composite_creds)); GPR_ASSERT(!grpc_credentials_has_request_metadata_only(composite_creds)); creds_array = grpc_composite_credentials_get_credentials(composite_creds); GPR_ASSERT(creds_array->num_creds == 3); - GPR_ASSERT( - !strcmp(creds_array->creds_array[0]->type, GRPC_CREDENTIALS_TYPE_SSL)); - GPR_ASSERT( - !strcmp(creds_array->creds_array[1]->type, GRPC_CREDENTIALS_TYPE_OAUTH2)); - GPR_ASSERT( - !strcmp(creds_array->creds_array[2]->type, GRPC_CREDENTIALS_TYPE_IAM)); + GPR_ASSERT(strcmp(creds_array->creds_array[0]->type, + GRPC_CREDENTIALS_TYPE_SSL) == 0); + GPR_ASSERT(strcmp(creds_array->creds_array[1]->type, + GRPC_CREDENTIALS_TYPE_OAUTH2) == 0); + GPR_ASSERT(strcmp(creds_array->creds_array[2]->type, + GRPC_CREDENTIALS_TYPE_IAM) == 0); grpc_credentials_get_request_metadata(composite_creds, test_service_url, check_ssl_oauth2_iam_composite_metadata, composite_creds); @@ -359,12 +362,12 @@ static void on_oauth2_creds_get_metadata_success( grpc_credentials_status status) { GPR_ASSERT(status == GRPC_CREDENTIALS_OK); GPR_ASSERT(num_md == 1); - GPR_ASSERT( - !strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), "Authorization")); - GPR_ASSERT(!strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), - "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_")); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), + "Authorization") == 0); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), + "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_") == 0); GPR_ASSERT(user_data != NULL); - GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); + GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); } static void on_oauth2_creds_get_metadata_failure( @@ -373,19 +376,19 @@ static void on_oauth2_creds_get_metadata_failure( GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); GPR_ASSERT(num_md == 0); GPR_ASSERT(user_data != NULL); - GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); + GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); } static void validate_compute_engine_http_request( const grpc_httpcli_request *request) { GPR_ASSERT(!request->use_ssl); - GPR_ASSERT(!strcmp(request->host, "metadata")); - GPR_ASSERT( - !strcmp(request->path, - "/computeMetadata/v1/instance/service-accounts/default/token")); + GPR_ASSERT(strcmp(request->host, "metadata") == 0); + GPR_ASSERT(strcmp(request->path, + "/computeMetadata/v1/instance/service-accounts/default/token") + == 0); GPR_ASSERT(request->hdr_count == 1); - GPR_ASSERT(!strcmp(request->hdrs[0].key, "Metadata-Flavor")); - GPR_ASSERT(!strcmp(request->hdrs[0].value, "Google")); + GPR_ASSERT(strcmp(request->hdrs[0].key, "Metadata-Flavor") == 0); + GPR_ASSERT(strcmp(request->hdrs[0].value, "Google") == 0); } static int compute_engine_httpcli_get_success_override( @@ -467,19 +470,19 @@ static void validate_jwt_encode_and_sign_params( GPR_ASSERT(json_key->private_key != NULL); GPR_ASSERT(RSA_check_key(json_key->private_key)); GPR_ASSERT(json_key->type != NULL && - !(strcmp(json_key->type, "service_account"))); + strcmp(json_key->type, "service_account") == 0); GPR_ASSERT(json_key->private_key_id != NULL && - !strcmp(json_key->private_key_id, - "e6b5137873db8d2ef81e06a47289e6434ec8a165")); + strcmp(json_key->private_key_id, + "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); GPR_ASSERT(json_key->client_id != NULL && - !strcmp(json_key->client_id, - "777-abaslkan11hlb6nmim3bpspl31ud.apps." - "googleusercontent.com")); + strcmp(json_key->client_id, + "777-abaslkan11hlb6nmim3bpspl31ud.apps." + "googleusercontent.com") == 0); GPR_ASSERT(json_key->client_email != NULL && - !strcmp(json_key->client_email, - "777-abaslkan11hlb6nmim3bpspl31ud@developer." - "gserviceaccount.com")); - if (scope != NULL) GPR_ASSERT(!strcmp(scope, test_scope)); + strcmp(json_key->client_email, + "777-abaslkan11hlb6nmim3bpspl31ud@developer." + "gserviceaccount.com") == 0); + if (scope != NULL) GPR_ASSERT(strcmp(scope, test_scope) == 0); GPR_ASSERT(!gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime)); } @@ -517,12 +520,12 @@ static void validate_service_account_http_request( GPR_ASSERT(!memcmp(expected_body, body, body_size)); gpr_free(expected_body); GPR_ASSERT(request->use_ssl); - GPR_ASSERT(!strcmp(request->host, "www.googleapis.com")); - GPR_ASSERT(!strcmp(request->path, "/oauth2/v3/token")); + GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0); + GPR_ASSERT(strcmp(request->path, "/oauth2/v3/token") == 0); GPR_ASSERT(request->hdr_count == 1); - GPR_ASSERT(!strcmp(request->hdrs[0].key, "Content-Type")); - GPR_ASSERT( - !strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded")); + GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0); + GPR_ASSERT(strcmp(request->hdrs[0].value, + "application/x-www-form-urlencoded") == 0); } static int service_account_httpcli_post_success( @@ -626,12 +629,12 @@ static void on_jwt_creds_get_metadata_success(void *user_data, gpr_asprintf(&expected_md_value, "Bearer %s", test_signed_jwt); GPR_ASSERT(status == GRPC_CREDENTIALS_OK); GPR_ASSERT(num_md == 1); - GPR_ASSERT( - !strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), "Authorization")); - GPR_ASSERT( - !strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), expected_md_value)); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->key), + "Authorization") == 0); + GPR_ASSERT(strcmp(grpc_mdstr_as_c_string(md_elems[0]->value), + expected_md_value) == 0); GPR_ASSERT(user_data != NULL); - GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); + GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); gpr_free(expected_md_value); } @@ -642,7 +645,7 @@ static void on_jwt_creds_get_metadata_failure(void *user_data, GPR_ASSERT(status == GRPC_CREDENTIALS_ERROR); GPR_ASSERT(num_md == 0); GPR_ASSERT(user_data != NULL); - GPR_ASSERT(!strcmp((const char *)user_data, test_user_data)); + GPR_ASSERT(strcmp((const char *)user_data, test_user_data) == 0); } static void test_jwt_creds_success(void) { diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c index fae911721adf8b6063ab13bc1441084628d7abf3..ca5b8891023e7e216e5aea9d5eccbd5ccdb68dda 100644 --- a/test/core/security/json_token_test.c +++ b/test/core/security/json_token_test.c @@ -102,18 +102,18 @@ static void test_parse_json_key_success(void) { grpc_auth_json_key_create_from_string(json_string); GPR_ASSERT(grpc_auth_json_key_is_valid(&json_key)); GPR_ASSERT(json_key.type != NULL && - !(strcmp(json_key.type, "service_account"))); + strcmp(json_key.type, "service_account") == 0); GPR_ASSERT(json_key.private_key_id != NULL && - !strcmp(json_key.private_key_id, - "e6b5137873db8d2ef81e06a47289e6434ec8a165")); + strcmp(json_key.private_key_id, + "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); GPR_ASSERT(json_key.client_id != NULL && - !strcmp(json_key.client_id, - "777-abaslkan11hlb6nmim3bpspl31ud.apps." - "googleusercontent.com")); + strcmp(json_key.client_id, + "777-abaslkan11hlb6nmim3bpspl31ud.apps." + "googleusercontent.com") == 0); GPR_ASSERT(json_key.client_email != NULL && - !strcmp(json_key.client_email, - "777-abaslkan11hlb6nmim3bpspl31ud@developer." - "gserviceaccount.com")); + strcmp(json_key.client_email, + "777-abaslkan11hlb6nmim3bpspl31ud@developer." + "gserviceaccount.com") == 0); GPR_ASSERT(json_key.private_key != NULL); gpr_free(json_string); grpc_auth_json_key_destruct(&json_key); @@ -248,15 +248,16 @@ static void check_jwt_header(grpc_json *header) { } GPR_ASSERT(alg != NULL); GPR_ASSERT(alg->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(alg->value, "RS256")); + GPR_ASSERT(strcmp(alg->value, "RS256") == 0); GPR_ASSERT(typ != NULL); GPR_ASSERT(typ->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(typ->value, "JWT")); + GPR_ASSERT(strcmp(typ->value, "JWT") == 0); GPR_ASSERT(kid != NULL); GPR_ASSERT(kid->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(kid->value, "e6b5137873db8d2ef81e06a47289e6434ec8a165")); + GPR_ASSERT(strcmp(kid->value, + "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0); } static void check_jwt_claim(grpc_json *claim, const char *expected_audience, @@ -290,27 +291,26 @@ static void check_jwt_claim(grpc_json *claim, const char *expected_audience, GPR_ASSERT(iss != NULL); GPR_ASSERT(iss->type == GRPC_JSON_STRING); - GPR_ASSERT( - !strcmp( - iss->value, - "777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount.com")); + GPR_ASSERT(strcmp(iss->value, + "777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount.com") + ==0); if (expected_scope != NULL) { GPR_ASSERT(scope != NULL); GPR_ASSERT(sub == NULL); GPR_ASSERT(scope->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(scope->value, expected_scope)); + GPR_ASSERT(strcmp(scope->value, expected_scope) == 0); } else { /* Claims without scope must have a sub. */ GPR_ASSERT(scope == NULL); GPR_ASSERT(sub != NULL); GPR_ASSERT(sub->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(iss->value, sub->value)); + GPR_ASSERT(strcmp(iss->value, sub->value) == 0); } GPR_ASSERT(aud != NULL); GPR_ASSERT(aud->type == GRPC_JSON_STRING); - GPR_ASSERT(!strcmp(aud->value, expected_audience)); + GPR_ASSERT(strcmp(aud->value, expected_audience) == 0); GPR_ASSERT(exp != NULL); GPR_ASSERT(exp->type == GRPC_JSON_NUMBER); diff --git a/test/core/support/env_test.c b/test/core/support/env_test.c index 1f16af87a5a6973ec01e58965404d5e9973b0596..aedf9313f3222f28e5ac7bc855ae1deba18cfa43 100644 --- a/test/core/support/env_test.c +++ b/test/core/support/env_test.c @@ -53,7 +53,7 @@ static void test_setenv_getenv(void) { gpr_setenv(name, value); retrieved_value = gpr_getenv(name); GPR_ASSERT(retrieved_value != NULL); - GPR_ASSERT(!strcmp(value, retrieved_value)); + GPR_ASSERT(strcmp(value, retrieved_value) == 0); gpr_free(retrieved_value); } diff --git a/test/core/support/slice_buffer_test.c b/test/core/support/slice_buffer_test.c index 8301795dbfda7b275785c8a71e8f9f4c728b73d5..a48278434f1be3e0a81ebbb403a3c807c8f0b37a 100644 --- a/test/core/support/slice_buffer_test.c +++ b/test/core/support/slice_buffer_test.c @@ -62,8 +62,13 @@ int main(int argc, char **argv) { } GPR_ASSERT(buf.count > 0); GPR_ASSERT(buf.length == 50); - gpr_slice_unref(aaa); - gpr_slice_unref(bb); + for (i = 0; i < 10; i++) { + gpr_slice_buffer_pop(&buf); + gpr_slice_unref(aaa); + gpr_slice_unref(bb); + } + GPR_ASSERT(buf.count == 0); + GPR_ASSERT(buf.length == 0); gpr_slice_buffer_destroy(&buf); return 0; diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index 3653c5a1b0d48ba2a9298422fec8ade3e096a98e..f0420896eeb2754c7c89e2a1c1fdbc774ee8f790 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -31,7 +31,7 @@ * */ -#include "src/core/surface/lame_client.h" +#include <grpc/grpc.h> #include "test/core/end2end/cq_verifier.h" #include "test/core/util/test_config.h" diff --git a/test/core/util/grpc_profiler.c b/test/core/util/grpc_profiler.c index 35b9361c70c981bba4b03a107c079e76310ed78c..d5b6cfeef10da8408dc6c8d06c5dbe9629c28d8d 100644 --- a/test/core/util/grpc_profiler.c +++ b/test/core/util/grpc_profiler.c @@ -44,7 +44,7 @@ void grpc_profiler_stop() { ProfilerStop(); } void grpc_profiler_start(const char *filename) { gpr_log(GPR_DEBUG, - "You do not have google-perftools installed, profiling is disabled"); + "You do not have google-perftools installed, profiling is disabled [for %s]", filename); gpr_log(GPR_DEBUG, "To install on ubuntu: sudo apt-get install google-perftools " "libgoogle-perftools-dev"); diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc index dc8d76d7eff5a920e4564120b982d79e9dafe21b..59ca33cc2979f33eb88a676ced1c305c99ba6c1e 100644 --- a/test/cpp/client/credentials_test.cc +++ b/test/cpp/client/credentials_test.cc @@ -47,8 +47,7 @@ class CredentialsTest : public ::testing::Test { TEST_F(CredentialsTest, InvalidServiceAccountCreds) { std::unique_ptr<Credentials> bad1 = - CredentialsFactory::ServiceAccountCredentials("", "", - std::chrono::seconds(1)); + ServiceAccountCredentials("", "", std::chrono::seconds(1)); EXPECT_EQ(nullptr, bad1.get()); } diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 331a5ef8a02238692800fdb7075ea79121a5ccbb..70df9e14b21941206fa2cf92be65cf565c73e6d3 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -47,6 +47,7 @@ #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> #include <grpc++/status.h> #include <grpc++/stream.h> #include "test/core/util/port.h" @@ -84,7 +85,7 @@ class AsyncEnd2endTest : public ::testing::Test { server_address_ << "localhost:" << port; // Setup server ServerBuilder builder; - builder.AddPort(server_address_.str()); + builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials()); builder.RegisterAsyncService(&service_); server_ = builder.BuildAndStart(); } @@ -102,8 +103,8 @@ class AsyncEnd2endTest : public ::testing::Test { } void ResetStub() { - std::shared_ptr<ChannelInterface> channel = - CreateChannelDeprecated(server_address_.str(), ChannelArguments()); + std::shared_ptr<ChannelInterface> channel = CreateChannel( + server_address_.str(), InsecureCredentials(), ChannelArguments()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel)); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 1d5dfc4e34263c25a18c1476586717aa4b49f202..c586849349cbfa7237f5a1d373c0bb3eb5b74e16 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -47,6 +47,7 @@ #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> #include <grpc++/status.h> #include <grpc++/stream.h> #include "test/core/util/port.h" @@ -150,7 +151,7 @@ class End2endTest : public ::testing::Test { server_address_ << "localhost:" << port; // Setup server ServerBuilder builder; - builder.AddPort(server_address_.str()); + builder.AddPort(server_address_.str(), InsecureServerCredentials()); builder.RegisterService(&service_); builder.RegisterService(&dup_pkg_service_); builder.SetThreadPool(&thread_pool_); @@ -160,8 +161,8 @@ class End2endTest : public ::testing::Test { void TearDown() GRPC_OVERRIDE { server_->Shutdown(); } void ResetStub() { - std::shared_ptr<ChannelInterface> channel = - CreateChannelDeprecated(server_address_.str(), ChannelArguments()); + std::shared_ptr<ChannelInterface> channel = CreateChannel( + server_address_.str(), InsecureCredentials(), ChannelArguments()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel)); } @@ -371,8 +372,8 @@ TEST_F(End2endTest, BidiStream) { // Talk to the two services with the same name but different package names. // The two stubs are created on the same channel. TEST_F(End2endTest, DiffPackageServices) { - std::shared_ptr<ChannelInterface> channel = - CreateChannelDeprecated(server_address_.str(), ChannelArguments()); + std::shared_ptr<ChannelInterface> channel = CreateChannel( + server_address_.str(), InsecureCredentials(), ChannelArguments()); EchoRequest request; EchoResponse response; @@ -397,8 +398,7 @@ TEST_F(End2endTest, DiffPackageServices) { // rpc and stream should fail on bad credentials. TEST_F(End2endTest, BadCredentials) { std::unique_ptr<Credentials> bad_creds = - CredentialsFactory::ServiceAccountCredentials("", "", - std::chrono::seconds(1)); + ServiceAccountCredentials("", "", std::chrono::seconds(1)); EXPECT_EQ(nullptr, bad_creds.get()); std::shared_ptr<ChannelInterface> channel = CreateChannel(server_address_.str(), bad_creds, ChannelArguments()); diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index f7537c2d7b2ebaa53715364dfa21a797baaa1dc2..ae68f7a55649b79be08f46123f690c0058a98c8e 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -82,9 +82,10 @@ DEFINE_string(oauth_scope, "", "Scope for OAuth tokens."); using grpc::ChannelInterface; using grpc::ClientContext; +using grpc::ComputeEngineCredentials; using grpc::CreateTestChannel; using grpc::Credentials; -using grpc::CredentialsFactory; +using grpc::ServiceAccountCredentials; using grpc::testing::ResponseParameters; using grpc::testing::SimpleRequest; using grpc::testing::SimpleResponse; @@ -96,8 +97,8 @@ using grpc::testing::TestService; // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } +namespace google {} +namespace gflags {} using namespace google; using namespace gflags; @@ -135,14 +136,14 @@ std::shared_ptr<ChannelInterface> CreateChannelForTestCase( std::unique_ptr<Credentials> creds; GPR_ASSERT(FLAGS_enable_ssl); grpc::string json_key = GetServiceAccountJsonKey(); - creds = CredentialsFactory::ServiceAccountCredentials( - json_key, FLAGS_oauth_scope, std::chrono::hours(1)); + creds = ServiceAccountCredentials(json_key, FLAGS_oauth_scope, + std::chrono::hours(1)); return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_enable_ssl, FLAGS_use_prod_roots, creds); } else if (test_case == "compute_engine_creds") { std::unique_ptr<Credentials> creds; GPR_ASSERT(FLAGS_enable_ssl); - creds = CredentialsFactory::ComputeEngineCredentials(); + creds = ComputeEngineCredentials(); return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_enable_ssl, FLAGS_use_prod_roots, creds); } else { @@ -202,7 +203,7 @@ void DoComputeEngineCreds() { GPR_ASSERT(!response.username().empty()); GPR_ASSERT(response.username().c_str() == FLAGS_default_service_account); GPR_ASSERT(!response.oauth_scope().empty()); - const char *oauth_scope_str = response.oauth_scope().c_str(); + const char* oauth_scope_str = response.oauth_scope().c_str(); GPR_ASSERT(FLAGS_oauth_scope.find(oauth_scope_str) != grpc::string::npos); gpr_log(GPR_INFO, "Large unary with compute engine creds done."); } @@ -221,7 +222,7 @@ void DoServiceAccountCreds() { GPR_ASSERT(!response.oauth_scope().empty()); grpc::string json_key = GetServiceAccountJsonKey(); GPR_ASSERT(json_key.find(response.username()) != grpc::string::npos); - const char *oauth_scope_str = response.oauth_scope().c_str(); + const char* oauth_scope_str = response.oauth_scope().c_str(); GPR_ASSERT(FLAGS_oauth_scope.find(oauth_scope_str) != grpc::string::npos); gpr_log(GPR_INFO, "Large unary with service account creds done."); } diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc index 9810ff6622b2bb920ed09c1a98b2937c9b929ed7..743482e967103d291f151f391179ccab735152f3 100644 --- a/test/cpp/interop/server.cc +++ b/test/cpp/interop/server.cc @@ -60,7 +60,6 @@ using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::ServerCredentials; -using grpc::ServerCredentialsFactory; using grpc::ServerReader; using grpc::ServerReaderWriter; using grpc::ServerWriter; @@ -78,8 +77,8 @@ using grpc::Status; // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } +namespace google {} +namespace gflags {} using namespace google; using namespace gflags; @@ -211,15 +210,14 @@ void RunServer() { SimpleResponse response; ServerBuilder builder; - builder.AddPort(server_address.str()); builder.RegisterService(&service); + std::shared_ptr<ServerCredentials> creds = grpc::InsecureServerCredentials(); if (FLAGS_enable_ssl) { SslServerCredentialsOptions ssl_opts = { "", {{test_server1_key, test_server1_cert}}}; - std::shared_ptr<ServerCredentials> creds = - ServerCredentialsFactory::SslCredentials(ssl_opts); - builder.SetCredentials(creds); + creds = grpc::SslServerCredentials(ssl_opts); } + builder.AddPort(server_address.str(), creds); std::unique_ptr<Server> server(builder.BuildAndStart()); gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str()); while (!got_sigint) { diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client.cc deleted file mode 100644 index 11c39eb4f52619a9695c1dedc391cf196b8219fa..0000000000000000000000000000000000000000 --- a/test/cpp/qps/client.cc +++ /dev/null @@ -1,252 +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 <cassert> -#include <memory> -#include <string> -#include <thread> -#include <vector> -#include <sstream> - -#include <grpc/grpc.h> -#include <grpc/support/histogram.h> -#include <grpc/support/log.h> -#include <gflags/gflags.h> -#include <grpc++/client_context.h> -#include <grpc++/status.h> -#include "test/core/util/grpc_profiler.h" -#include "test/cpp/util/create_test_channel.h" -#include "test/cpp/qps/qpstest.pb.h" - -DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); -DEFINE_int32(server_port, 0, "Server port."); -DEFINE_string(server_host, "127.0.0.1", "Server host."); -DEFINE_int32(client_threads, 4, "Number of client threads."); - -// We have a configurable number of channels for sending RPCs. -// RPCs are sent round-robin on the available channels by the -// various threads. Interesting cases are 1 global channel or -// 1 per-thread channel, but we can support any number. -// The channels are assigned round-robin on an RPC by RPC basis -// rather than just at initialization time in order to also measure the -// impact of cache thrashing caused by channel changes. This is an issue -// if you are not in one of the above "interesting cases" -DEFINE_int32(client_channels, 4, "Number of client channels."); - -DEFINE_int32(num_rpcs, 1000, "Number of RPCs per thread."); -DEFINE_int32(payload_size, 1, "Payload size in bytes"); - -// Alternatively, specify parameters for test as a workload so that multiple -// tests are initiated back-to-back. This is convenient for keeping a borg -// allocation consistent. This is a space-separated list of -// [threads channels num_rpcs payload_size ]* -DEFINE_string(workload, "", "Workload parameters"); - -using grpc::ChannelInterface; -using grpc::CreateTestChannel; -using grpc::testing::ServerStats; -using grpc::testing::SimpleRequest; -using grpc::testing::SimpleResponse; -using grpc::testing::StatsRequest; -using grpc::testing::TestService; - -// In some distros, gflags is in the namespace google, and in some others, -// in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } -using namespace google; -using namespace gflags; - -static double now() { - gpr_timespec tv = gpr_now(); - return 1e9 * tv.tv_sec + tv.tv_nsec; -} - -void RunTest(const int client_threads, const int client_channels, - const int num_rpcs, const int payload_size) { - gpr_log(GPR_INFO, - "QPS test with parameters\n" - "enable_ssl = %d\n" - "client_channels = %d\n" - "client_threads = %d\n" - "num_rpcs = %d\n" - "payload_size = %d\n" - "server_host:server_port = %s:%d\n\n", - FLAGS_enable_ssl, client_channels, client_threads, num_rpcs, - payload_size, FLAGS_server_host.c_str(), FLAGS_server_port); - - std::ostringstream oss; - oss << FLAGS_server_host << ":" << FLAGS_server_port; - - class ClientChannelInfo { - public: - explicit ClientChannelInfo(const grpc::string &server) - : channel_(CreateTestChannel(server, FLAGS_enable_ssl)), - stub_(TestService::NewStub(channel_)) {} - ChannelInterface *get_channel() { return channel_.get(); } - TestService::Stub *get_stub() { return stub_.get(); } - - private: - std::shared_ptr<ChannelInterface> channel_; - std::unique_ptr<TestService::Stub> stub_; - }; - - std::vector<ClientChannelInfo> channels; - for (int i = 0; i < client_channels; i++) { - channels.push_back(ClientChannelInfo(oss.str())); - } - - std::vector<std::thread> threads; // Will add threads when ready to execute - std::vector< ::gpr_histogram *> thread_stats(client_threads); - - TestService::Stub *stub_stats = channels[0].get_stub(); - grpc::ClientContext context_stats_begin; - StatsRequest stats_request; - ServerStats server_stats_begin; - stats_request.set_test_num(0); - grpc::Status status_beg = stub_stats->CollectServerStats( - &context_stats_begin, stats_request, &server_stats_begin); - - grpc_profiler_start("qps_client.prof"); - - for (int i = 0; i < client_threads; i++) { - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - thread_stats[i] = hist; - - threads.push_back( - std::thread([hist, client_threads, client_channels, num_rpcs, - payload_size, &channels](int channel_num) { - SimpleRequest request; - SimpleResponse response; - request.set_response_type( - grpc::testing::PayloadType::COMPRESSABLE); - request.set_response_size(payload_size); - - for (int j = 0; j < num_rpcs; j++) { - TestService::Stub *stub = - channels[channel_num].get_stub(); - double start = now(); - grpc::ClientContext context; - grpc::Status s = - stub->UnaryCall(&context, request, &response); - gpr_histogram_add(hist, now() - start); - - GPR_ASSERT((s.code() == grpc::StatusCode::OK) && - (response.payload().type() == - grpc::testing::PayloadType::COMPRESSABLE) && - (response.payload().body().length() == - static_cast<size_t>(payload_size))); - - // Now do runtime round-robin assignment of the next - // channel number - channel_num += client_threads; - channel_num %= client_channels; - } - }, - i % client_channels)); - } - - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - for (auto &t : threads) { - t.join(); - } - - grpc_profiler_stop(); - - for (int i = 0; i < client_threads; i++) { - gpr_histogram *h = thread_stats[i]; - gpr_log(GPR_INFO, "latency at thread %d (50/90/95/99/99.9): %f/%f/%f/%f/%f", - i, gpr_histogram_percentile(h, 50), gpr_histogram_percentile(h, 90), - gpr_histogram_percentile(h, 95), gpr_histogram_percentile(h, 99), - gpr_histogram_percentile(h, 99.9)); - gpr_histogram_merge(hist, h); - gpr_histogram_destroy(h); - } - - gpr_log( - GPR_INFO, - "latency across %d threads with %d channels and %d payload " - "(50/90/95/99/99.9): %f / %f / %f / %f / %f", - client_threads, client_channels, payload_size, - gpr_histogram_percentile(hist, 50), gpr_histogram_percentile(hist, 90), - gpr_histogram_percentile(hist, 95), gpr_histogram_percentile(hist, 99), - gpr_histogram_percentile(hist, 99.9)); - gpr_histogram_destroy(hist); - - grpc::ClientContext context_stats_end; - ServerStats server_stats_end; - grpc::Status status_end = stub_stats->CollectServerStats( - &context_stats_end, stats_request, &server_stats_end); - - double elapsed = server_stats_end.time_now() - server_stats_begin.time_now(); - int total_rpcs = client_threads * num_rpcs; - double utime = server_stats_end.time_user() - server_stats_begin.time_user(); - double stime = - server_stats_end.time_system() - server_stats_begin.time_system(); - gpr_log(GPR_INFO, - "Elapsed time: %.3f\n" - "RPC Count: %d\n" - "QPS: %.3f\n" - "System time: %.3f\n" - "User time: %.3f\n" - "Resource usage: %.1f%%\n", - elapsed, total_rpcs, total_rpcs / elapsed, stime, utime, - (stime + utime) / elapsed * 100.0); -} - -int main(int argc, char **argv) { - grpc_init(); - ParseCommandLineFlags(&argc, &argv, true); - - GPR_ASSERT(FLAGS_server_port); - - if (FLAGS_workload.length() == 0) { - RunTest(FLAGS_client_threads, FLAGS_client_channels, FLAGS_num_rpcs, - FLAGS_payload_size); - } else { - std::istringstream workload(FLAGS_workload); - int client_threads, client_channels, num_rpcs, payload_size; - workload >> client_threads; - while (!workload.eof()) { - workload >> client_channels >> num_rpcs >> payload_size; - RunTest(client_threads, client_channels, num_rpcs, payload_size); - workload >> client_threads; - } - gpr_log(GPR_INFO, "Done with specified workload."); - } - - grpc_shutdown(); - return 0; -} diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h new file mode 100644 index 0000000000000000000000000000000000000000..221fb30fc59deac0a8c664baa99160fbe00f1c00 --- /dev/null +++ b/test/cpp/qps/client.h @@ -0,0 +1,173 @@ +/* + * + * 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 TEST_QPS_CLIENT_H +#define TEST_QPS_CLIENT_H + +#include "test/cpp/qps/histogram.h" +#include "test/cpp/qps/timer.h" +#include "test/cpp/qps/qpstest.pb.h" + +#include <condition_variable> +#include <mutex> + +namespace grpc { +namespace testing { + +class Client { + public: + explicit Client(const ClientConfig& config) : timer_(new Timer) { + for (int i = 0; i < config.client_channels(); i++) { + channels_.push_back(ClientChannelInfo( + config.server_targets(i % config.server_targets_size()), config)); + } + request_.set_response_type(grpc::testing::PayloadType::COMPRESSABLE); + request_.set_response_size(config.payload_size()); + } + virtual ~Client() {} + + ClientStats Mark() { + Histogram latencies; + std::vector<Histogram> to_merge(threads_.size()); + for (size_t i = 0; i < threads_.size(); i++) { + threads_[i]->BeginSwap(&to_merge[i]); + } + std::unique_ptr<Timer> timer(new Timer); + timer_.swap(timer); + for (size_t i = 0; i < threads_.size(); i++) { + threads_[i]->EndSwap(); + latencies.Merge(&to_merge[i]); + } + + auto timer_result = timer->Mark(); + + ClientStats stats; + latencies.FillProto(stats.mutable_latencies()); + stats.set_time_elapsed(timer_result.wall); + stats.set_time_system(timer_result.system); + stats.set_time_user(timer_result.user); + return stats; + } + + protected: + SimpleRequest request_; + + class ClientChannelInfo { + public: + ClientChannelInfo(const grpc::string& target, const ClientConfig& config) + : channel_(CreateTestChannel(target, config.enable_ssl())), + stub_(TestService::NewStub(channel_)) {} + ChannelInterface* get_channel() { return channel_.get(); } + TestService::Stub* get_stub() { return stub_.get(); } + + private: + std::shared_ptr<ChannelInterface> channel_; + std::unique_ptr<TestService::Stub> stub_; + }; + std::vector<ClientChannelInfo> channels_; + + void StartThreads(size_t num_threads) { + for (size_t i = 0; i < num_threads; i++) { + threads_.emplace_back(new Thread(this, i)); + } + } + + void EndThreads() { threads_.clear(); } + + virtual void ThreadFunc(Histogram* histogram, size_t thread_idx) = 0; + + private: + class Thread { + public: + Thread(Client* client, size_t idx) + : done_(false), + new_(nullptr), + impl_([this, idx, client]() { + for (;;) { + // run the loop body + client->ThreadFunc(&histogram_, idx); + // lock, see if we're done + std::lock_guard<std::mutex> g(mu_); + if (done_) return; + // also check if we're marking, and swap out the histogram if so + if (new_) { + new_->Swap(&histogram_); + new_ = nullptr; + cv_.notify_one(); + } + } + }) {} + + ~Thread() { + { + std::lock_guard<std::mutex> g(mu_); + done_ = true; + } + impl_.join(); + } + + void BeginSwap(Histogram* n) { + std::lock_guard<std::mutex> g(mu_); + new_ = n; + } + + void EndSwap() { + std::unique_lock<std::mutex> g(mu_); + cv_.wait(g, [this]() { return new_ == nullptr; }); + } + + private: + Thread(const Thread&); + Thread& operator=(const Thread&); + + TestService::Stub* stub_; + ClientConfig config_; + std::mutex mu_; + std::condition_variable cv_; + bool done_; + Histogram* new_; + Histogram histogram_; + std::thread impl_; + }; + + std::vector<std::unique_ptr<Thread>> threads_; + std::unique_ptr<Timer> timer_; +}; + +std::unique_ptr<Client> CreateSynchronousClient(const ClientConfig& args); +std::unique_ptr<Client> CreateAsyncClient(const ClientConfig& args); + +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index 9ea9cfe8b9b8a8ccbdae16f0b33cd1e5ba2905b7..c6535bebf8856cb02fb5b89270f689f123114109 100644 --- a/test/cpp/qps/client_async.cc +++ b/test/cpp/qps/client_async.cc @@ -49,86 +49,53 @@ #include "test/core/util/grpc_profiler.h" #include "test/cpp/util/create_test_channel.h" #include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/timer.h" +#include "test/cpp/qps/client.h" -DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); -DEFINE_int32(server_port, 0, "Server port."); -DEFINE_string(server_host, "127.0.0.1", "Server host."); -DEFINE_int32(client_threads, 4, "Number of client threads."); - -// We have a configurable number of channels for sending RPCs. -// RPCs are sent round-robin on the available channels by the -// various threads. Interesting cases are 1 global channel or -// 1 per-thread channel, but we can support any number. -// The channels are assigned round-robin on an RPC by RPC basis -// rather than just at initialization time in order to also measure the -// impact of cache thrashing caused by channel changes. This is an issue -// if you are not in one of the above "interesting cases" -DEFINE_int32(client_channels, 4, "Number of client channels."); - -DEFINE_int32(num_rpcs, 1000, "Number of RPCs per thread."); -DEFINE_int32(payload_size, 1, "Payload size in bytes"); - -// Alternatively, specify parameters for test as a workload so that multiple -// tests are initiated back-to-back. This is convenient for keeping a borg -// allocation consistent. This is a space-separated list of -// [threads channels num_rpcs payload_size ]* -DEFINE_string(workload, "", "Workload parameters"); - -using grpc::ChannelInterface; -using grpc::CreateTestChannel; -using grpc::testing::ServerStats; -using grpc::testing::SimpleRequest; -using grpc::testing::SimpleResponse; -using grpc::testing::StatsRequest; -using grpc::testing::TestService; - -// In some distros, gflags is in the namespace google, and in some others, -// in gflags. This hack is enabling us to find both. -namespace google {} -namespace gflags {} -using namespace google; -using namespace gflags; - -static double now() { - gpr_timespec tv = gpr_now(); - return 1e9 * tv.tv_sec + tv.tv_nsec; -} +namespace grpc { +namespace testing { class ClientRpcContext { public: ClientRpcContext() {} virtual ~ClientRpcContext() {} virtual bool RunNextState() = 0; // do next state, return false if steps done + virtual void StartNewClone() = 0; static void *tag(ClientRpcContext *c) { return reinterpret_cast<void *>(c); } static ClientRpcContext *detag(void *t) { return reinterpret_cast<ClientRpcContext *>(t); } - virtual void report_stats(gpr_histogram *hist) = 0; + virtual void report_stats(Histogram *hist) = 0; }; + template <class RequestType, class ResponseType> class ClientRpcContextUnaryImpl : public ClientRpcContext { public: ClientRpcContextUnaryImpl( - TestService::Stub *stub, - const RequestType &req, + TestService::Stub *stub, const RequestType &req, std::function< std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>( - TestService::Stub *, grpc::ClientContext *, const RequestType &, - void *)> start_req, + TestService::Stub *, grpc::ClientContext *, const RequestType &, + void *)> start_req, std::function<void(grpc::Status, ResponseType *)> on_done) : context_(), - stub_(stub), + stub_(stub), req_(req), response_(), next_state_(&ClientRpcContextUnaryImpl::ReqSent), callback_(on_done), - start_(now()), + start_req_(start_req), + start_(Timer::Now()), response_reader_( - start_req(stub_, &context_, req_, ClientRpcContext::tag(this))) {} + start_req(stub_, &context_, req_, ClientRpcContext::tag(this))) {} ~ClientRpcContextUnaryImpl() GRPC_OVERRIDE {} bool RunNextState() GRPC_OVERRIDE { return (this->*next_state_)(); } - void report_stats(gpr_histogram *hist) GRPC_OVERRIDE { - gpr_histogram_add(hist, now() - start_); + void report_stats(Histogram *hist) GRPC_OVERRIDE { + hist->Add((Timer::Now() - start_) * 1e9); + } + + void StartNewClone() GRPC_OVERRIDE { + new ClientRpcContextUnaryImpl(stub_, req_, start_req_, callback_); } private: @@ -151,191 +118,84 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { ResponseType response_; bool (ClientRpcContextUnaryImpl::*next_state_)(); std::function<void(grpc::Status, ResponseType *)> callback_; + std::function<std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>( + TestService::Stub *, grpc::ClientContext *, const RequestType &, void *)> + start_req_; grpc::Status status_; double start_; std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>> response_reader_; }; -static void RunTest(const int client_threads, const int client_channels, - const int num_rpcs, const int payload_size) { - gpr_log(GPR_INFO, - "QPS test with parameters\n" - "enable_ssl = %d\n" - "client_channels = %d\n" - "client_threads = %d\n" - "num_rpcs = %d\n" - "payload_size = %d\n" - "server_host:server_port = %s:%d\n\n", - FLAGS_enable_ssl, client_channels, client_threads, num_rpcs, - payload_size, FLAGS_server_host.c_str(), FLAGS_server_port); - - std::ostringstream oss; - oss << FLAGS_server_host << ":" << FLAGS_server_port; - - class ClientChannelInfo { - public: - explicit ClientChannelInfo(const grpc::string &server) - : channel_(CreateTestChannel(server, FLAGS_enable_ssl)), - stub_(TestService::NewStub(channel_)) {} - ChannelInterface *get_channel() { return channel_.get(); } - TestService::Stub *get_stub() { return stub_.get(); } +class AsyncClient GRPC_FINAL : public Client { + public: + explicit AsyncClient(const ClientConfig &config) : Client(config) { + for (int i = 0; i < config.async_client_threads(); i++) { + cli_cqs_.emplace_back(new CompletionQueue); + } - private: - std::shared_ptr<ChannelInterface> channel_; - std::unique_ptr<TestService::Stub> stub_; - }; + auto payload_size = config.payload_size(); + auto check_done = [payload_size](grpc::Status s, SimpleResponse *response) { + GPR_ASSERT(s.IsOk() && (response->payload().type() == + grpc::testing::PayloadType::COMPRESSABLE) && + (response->payload().body().length() == + static_cast<size_t>(payload_size))); + }; + + int t = 0; + for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) { + for (auto &channel : channels_) { + auto *cq = cli_cqs_[t].get(); + t = (t + 1) % cli_cqs_.size(); + auto start_req = [cq](TestService::Stub *stub, grpc::ClientContext *ctx, + const SimpleRequest &request, void *tag) { + return stub->AsyncUnaryCall(ctx, request, cq, tag); + }; + + TestService::Stub *stub = channel.get_stub(); + const SimpleRequest &request = request_; + new ClientRpcContextUnaryImpl<SimpleRequest, SimpleResponse>( + stub, request, start_req, check_done); + } + } - std::vector<ClientChannelInfo> channels; - for (int i = 0; i < client_channels; i++) { - channels.push_back(ClientChannelInfo(oss.str())); + StartThreads(config.async_client_threads()); } - std::vector<std::thread> threads; // Will add threads when ready to execute - std::vector< ::gpr_histogram *> thread_stats(client_threads); - - TestService::Stub *stub_stats = channels[0].get_stub(); - grpc::ClientContext context_stats_begin; - StatsRequest stats_request; - ServerStats server_stats_begin; - stats_request.set_test_num(0); - grpc::Status status_beg = stub_stats->CollectServerStats( - &context_stats_begin, stats_request, &server_stats_begin); - - grpc_profiler_start("qps_client_async.prof"); - - auto CheckDone = [=](grpc::Status s, SimpleResponse *response) { - GPR_ASSERT(s.IsOk() && (response->payload().type() == - grpc::testing::PayloadType::COMPRESSABLE) && - (response->payload().body().length() == - static_cast<size_t>(payload_size))); - }; + ~AsyncClient() GRPC_OVERRIDE { + EndThreads(); - for (int i = 0; i < client_threads; i++) { - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - thread_stats[i] = hist; - - threads.push_back(std::thread( - [hist, client_threads, client_channels, num_rpcs, payload_size, - &channels, &CheckDone](int channel_num) { - using namespace std::placeholders; - SimpleRequest request; - request.set_response_type(grpc::testing::PayloadType::COMPRESSABLE); - request.set_response_size(payload_size); - - grpc::CompletionQueue cli_cq; - auto start_req = std::bind(&TestService::Stub::AsyncUnaryCall, _1, - _2, _3, &cli_cq, _4); - - int rpcs_sent = 0; - while (rpcs_sent < num_rpcs) { - rpcs_sent++; - TestService::Stub *stub = channels[channel_num].get_stub(); - new ClientRpcContextUnaryImpl<SimpleRequest, SimpleResponse>(stub, - request, start_req, CheckDone); - void *got_tag; - bool ok; - - // Need to call 2 next for every 1 RPC (1 for req done, 1 for resp - // done) - cli_cq.Next(&got_tag, &ok); - if (!ok) break; - ClientRpcContext *ctx = ClientRpcContext::detag(got_tag); - if (ctx->RunNextState() == false) { - // call the callback and then delete it - ctx->report_stats(hist); - ctx->RunNextState(); - delete ctx; - } - cli_cq.Next(&got_tag, &ok); - if (!ok) break; - ctx = ClientRpcContext::detag(got_tag); - if (ctx->RunNextState() == false) { - // call the callback and then delete it - ctx->report_stats(hist); - ctx->RunNextState(); - delete ctx; - } - // Now do runtime round-robin assignment of the next - // channel number - channel_num += client_threads; - channel_num %= client_channels; - } - }, - i % client_channels)); - } - - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - for (auto &t : threads) { - t.join(); + for (auto &cq : cli_cqs_) { + cq->Shutdown(); + void *got_tag; + bool ok; + while (cq->Next(&got_tag, &ok)) { + delete ClientRpcContext::detag(got_tag); + } + } } - grpc_profiler_stop(); - - for (int i = 0; i < client_threads; i++) { - gpr_histogram *h = thread_stats[i]; - gpr_log(GPR_INFO, "latency at thread %d (50/90/95/99/99.9): %f/%f/%f/%f/%f", - i, gpr_histogram_percentile(h, 50), gpr_histogram_percentile(h, 90), - gpr_histogram_percentile(h, 95), gpr_histogram_percentile(h, 99), - gpr_histogram_percentile(h, 99.9)); - gpr_histogram_merge(hist, h); - gpr_histogram_destroy(h); + void ThreadFunc(Histogram *histogram, size_t thread_idx) GRPC_OVERRIDE { + void *got_tag; + bool ok; + cli_cqs_[thread_idx]->Next(&got_tag, &ok); + + ClientRpcContext *ctx = ClientRpcContext::detag(got_tag); + if (ctx->RunNextState() == false) { + // call the callback and then delete it + ctx->report_stats(histogram); + ctx->RunNextState(); + ctx->StartNewClone(); + delete ctx; + } } - gpr_log( - GPR_INFO, - "latency across %d threads with %d channels and %d payload " - "(50/90/95/99/99.9): %f / %f / %f / %f / %f", - client_threads, client_channels, payload_size, - gpr_histogram_percentile(hist, 50), gpr_histogram_percentile(hist, 90), - gpr_histogram_percentile(hist, 95), gpr_histogram_percentile(hist, 99), - gpr_histogram_percentile(hist, 99.9)); - gpr_histogram_destroy(hist); - - grpc::ClientContext context_stats_end; - ServerStats server_stats_end; - grpc::Status status_end = stub_stats->CollectServerStats( - &context_stats_end, stats_request, &server_stats_end); + std::vector<std::unique_ptr<CompletionQueue>> cli_cqs_; +}; - double elapsed = server_stats_end.time_now() - server_stats_begin.time_now(); - int total_rpcs = client_threads * num_rpcs; - double utime = server_stats_end.time_user() - server_stats_begin.time_user(); - double stime = - server_stats_end.time_system() - server_stats_begin.time_system(); - gpr_log(GPR_INFO, - "Elapsed time: %.3f\n" - "RPC Count: %d\n" - "QPS: %.3f\n" - "System time: %.3f\n" - "User time: %.3f\n" - "Resource usage: %.1f%%\n", - elapsed, total_rpcs, total_rpcs / elapsed, stime, utime, - (stime + utime) / elapsed * 100.0); +std::unique_ptr<Client> CreateAsyncClient(const ClientConfig &args) { + return std::unique_ptr<Client>(new AsyncClient(args)); } -int main(int argc, char **argv) { - grpc_init(); - ParseCommandLineFlags(&argc, &argv, true); - - GPR_ASSERT(FLAGS_server_port); - - if (FLAGS_workload.length() == 0) { - RunTest(FLAGS_client_threads, FLAGS_client_channels, FLAGS_num_rpcs, - FLAGS_payload_size); - } else { - std::istringstream workload(FLAGS_workload); - int client_threads, client_channels, num_rpcs, payload_size; - workload >> client_threads; - while (!workload.eof()) { - workload >> client_channels >> num_rpcs >> payload_size; - RunTest(client_threads, client_channels, num_rpcs, payload_size); - workload >> client_threads; - } - gpr_log(GPR_INFO, "Done with specified workload."); - } - - grpc_shutdown(); - return 0; -} +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc new file mode 100644 index 0000000000000000000000000000000000000000..7bb7231c6f6538bee9542d014a671e12c9c4fc84 --- /dev/null +++ b/test/cpp/qps/client_sync.cc @@ -0,0 +1,93 @@ +/* + * + * 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 <cassert> +#include <memory> +#include <mutex> +#include <string> +#include <thread> +#include <vector> +#include <sstream> + +#include <sys/signal.h> + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/histogram.h> +#include <grpc/support/log.h> +#include <grpc/support/host_port.h> +#include <gflags/gflags.h> +#include <grpc++/client_context.h> +#include <grpc++/status.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include "test/core/util/grpc_profiler.h" +#include "test/cpp/util/create_test_channel.h" +#include "test/cpp/qps/client.h" +#include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/histogram.h" +#include "test/cpp/qps/timer.h" + +namespace grpc { +namespace testing { + +class SynchronousClient GRPC_FINAL : public Client { + public: + SynchronousClient(const ClientConfig& config) : Client(config) { + size_t num_threads = + config.outstanding_rpcs_per_channel() * config.client_channels(); + responses_.resize(num_threads); + StartThreads(num_threads); + } + + ~SynchronousClient() { EndThreads(); } + + void ThreadFunc(Histogram* histogram, size_t thread_idx) { + auto* stub = channels_[thread_idx % channels_.size()].get_stub(); + double start = Timer::Now(); + grpc::ClientContext context; + grpc::Status s = + stub->UnaryCall(&context, request_, &responses_[thread_idx]); + histogram->Add((Timer::Now() - start) * 1e9); + } + + private: + std::vector<SimpleResponse> responses_; +}; + +std::unique_ptr<Client> CreateSynchronousClient(const ClientConfig& config) { + return std::unique_ptr<Client>(new SynchronousClient(config)); +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc new file mode 100644 index 0000000000000000000000000000000000000000..d29ca1de94776b60efc1b5502b9b373a78c98c25 --- /dev/null +++ b/test/cpp/qps/driver.cc @@ -0,0 +1,210 @@ +/* + * + * 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 "test/cpp/qps/driver.h" +#include "src/core/support/env.h" +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/host_port.h> +#include <grpc++/channel_arguments.h> +#include <grpc++/client_context.h> +#include <grpc++/create_channel.h> +#include <grpc++/stream.h> +#include <list> +#include <thread> +#include <vector> +#include "test/cpp/qps/histogram.h" + +using std::list; +using std::thread; +using std::unique_ptr; +using std::vector; + +namespace grpc { +namespace testing { +static vector<string> get_hosts(const string& name) { + char* env = gpr_getenv(name.c_str()); + if (!env) return vector<string>(); + + vector<string> out; + char* p = env; + for (;;) { + char* comma = strchr(p, ','); + if (comma) { + out.emplace_back(p, comma); + p = comma + 1; + } else { + out.emplace_back(p); + gpr_free(env); + return out; + } + } +} + +ScenarioResult RunScenario(const ClientConfig& initial_client_config, + size_t num_clients, + const ServerConfig& server_config, + size_t num_servers) { + // ClientContext allocator (all are destroyed at scope exit) + list<ClientContext> contexts; + auto alloc_context = [&contexts]() { + contexts.emplace_back(); + return &contexts.back(); + }; + + // Get client, server lists + auto workers = get_hosts("QPS_WORKERS"); + ClientConfig client_config = initial_client_config; + + // TODO(ctiller): support running multiple configurations, and binpack + // client/server pairs + // to available workers + GPR_ASSERT(workers.size() >= num_clients + num_servers); + + // Trim to just what we need + workers.resize(num_clients + num_servers); + + // Start servers + struct ServerData { + unique_ptr<Worker::Stub> stub; + unique_ptr<ClientReaderWriter<ServerArgs, ServerStatus>> stream; + }; + vector<ServerData> servers; + for (size_t i = 0; i < num_servers; i++) { + ServerData sd; + sd.stub = std::move(Worker::NewStub( + CreateChannel(workers[i], InsecureCredentials(), ChannelArguments()))); + ServerArgs args; + *args.mutable_setup() = server_config; + sd.stream = std::move(sd.stub->RunServer(alloc_context())); + GPR_ASSERT(sd.stream->Write(args)); + ServerStatus init_status; + GPR_ASSERT(sd.stream->Read(&init_status)); + char* host; + char* driver_port; + char* cli_target; + gpr_split_host_port(workers[i].c_str(), &host, &driver_port); + gpr_join_host_port(&cli_target, host, init_status.port()); + client_config.add_server_targets(cli_target); + gpr_free(host); + gpr_free(driver_port); + gpr_free(cli_target); + + servers.push_back(std::move(sd)); + } + + // Start clients + struct ClientData { + unique_ptr<Worker::Stub> stub; + unique_ptr<ClientReaderWriter<ClientArgs, ClientStatus>> stream; + }; + vector<ClientData> clients; + for (size_t i = 0; i < num_clients; i++) { + ClientData cd; + cd.stub = std::move(Worker::NewStub(CreateChannel( + workers[i + num_servers], InsecureCredentials(), ChannelArguments()))); + ClientArgs args; + *args.mutable_setup() = client_config; + cd.stream = std::move(cd.stub->RunTest(alloc_context())); + GPR_ASSERT(cd.stream->Write(args)); + ClientStatus init_status; + GPR_ASSERT(cd.stream->Read(&init_status)); + + clients.push_back(std::move(cd)); + } + + // Let everything warmup + gpr_log(GPR_INFO, "Warming up"); + gpr_timespec start = gpr_now(); + gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(5))); + + // Start a run + gpr_log(GPR_INFO, "Starting"); + ServerArgs server_mark; + server_mark.mutable_mark(); + ClientArgs client_mark; + client_mark.mutable_mark(); + for (auto& server : servers) { + GPR_ASSERT(server.stream->Write(server_mark)); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Write(client_mark)); + } + ServerStatus server_status; + ClientStatus client_status; + for (auto& server : servers) { + GPR_ASSERT(server.stream->Read(&server_status)); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Read(&client_status)); + } + + // Wait some time + gpr_log(GPR_INFO, "Running"); + gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(15))); + + // Finish a run + ScenarioResult result; + gpr_log(GPR_INFO, "Finishing"); + for (auto& server : servers) { + GPR_ASSERT(server.stream->Write(server_mark)); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Write(client_mark)); + } + for (auto& server : servers) { + GPR_ASSERT(server.stream->Read(&server_status)); + const auto& stats = server_status.stats(); + result.server_resources.push_back(ResourceUsage{ + stats.time_elapsed(), stats.time_user(), stats.time_system()}); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Read(&client_status)); + const auto& stats = client_status.stats(); + result.latencies.MergeProto(stats.latencies()); + result.client_resources.push_back(ResourceUsage{ + stats.time_elapsed(), stats.time_user(), stats.time_system()}); + } + + for (auto& client : clients) { + GPR_ASSERT(client.stream->WritesDone()); + GPR_ASSERT(client.stream->Finish().IsOk()); + } + for (auto& server : servers) { + GPR_ASSERT(server.stream->WritesDone()); + GPR_ASSERT(server.stream->Finish().IsOk()); + } + return result; +} +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h new file mode 100644 index 0000000000000000000000000000000000000000..d87e80dc552a593a7b5230e34eaece33e1e19c04 --- /dev/null +++ b/test/cpp/qps/driver.h @@ -0,0 +1,61 @@ +/* + * + * 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 TEST_QPS_DRIVER_H +#define TEST_QPS_DRIVER_H + +#include "test/cpp/qps/histogram.h" +#include "test/cpp/qps/qpstest.pb.h" + +namespace grpc { +namespace testing { +struct ResourceUsage { + double wall_time; + double user_time; + double system_time; +}; + +struct ScenarioResult { + Histogram latencies; + std::vector<ResourceUsage> client_resources; + std::vector<ResourceUsage> server_resources; +}; + +ScenarioResult RunScenario(const grpc::testing::ClientConfig& client_config, + size_t num_clients, + const grpc::testing::ServerConfig& server_config, + size_t num_servers); +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h new file mode 100644 index 0000000000000000000000000000000000000000..7ba00e94c3947423e9f39ca721742437f9cee622 --- /dev/null +++ b/test/cpp/qps/histogram.h @@ -0,0 +1,85 @@ +/* + * + * 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 TEST_QPS_HISTOGRAM_H +#define TEST_QPS_HISTOGRAM_H + +#include <grpc/support/histogram.h> +#include "test/cpp/qps/qpstest.pb.h" + +namespace grpc { +namespace testing { + +class Histogram { + public: + Histogram() : impl_(gpr_histogram_create(0.01, 60e9)) {} + ~Histogram() { + if (impl_) gpr_histogram_destroy(impl_); + } + Histogram(Histogram&& other) : impl_(other.impl_) { other.impl_ = nullptr; } + + void Merge(Histogram* h) { gpr_histogram_merge(impl_, h->impl_); } + void Add(double value) { gpr_histogram_add(impl_, value); } + double Percentile(double pctile) { + return gpr_histogram_percentile(impl_, pctile); + } + double Count() { return gpr_histogram_count(impl_); } + void Swap(Histogram* other) { std::swap(impl_, other->impl_); } + void FillProto(HistogramData* p) { + size_t n; + const auto* data = gpr_histogram_get_contents(impl_, &n); + for (size_t i = 0; i < n; i++) { + p->add_bucket(data[i]); + } + p->set_min_seen(gpr_histogram_minimum(impl_)); + p->set_max_seen(gpr_histogram_maximum(impl_)); + p->set_sum(gpr_histogram_sum(impl_)); + p->set_sum_of_squares(gpr_histogram_sum_of_squares(impl_)); + p->set_count(gpr_histogram_count(impl_)); + } + void MergeProto(const HistogramData& p) { + gpr_histogram_merge_contents(impl_, &*p.bucket().begin(), p.bucket_size(), + p.min_seen(), p.max_seen(), p.sum(), + p.sum_of_squares(), p.count()); + } + + private: + Histogram(const Histogram&); + Histogram& operator=(const Histogram&); + + gpr_histogram* impl_; +}; +} +} + +#endif /* TEST_QPS_HISTOGRAM_H */ diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc new file mode 100644 index 0000000000000000000000000000000000000000..bf51e7408e9f6f0ae382f6f752f4e3e585e833df --- /dev/null +++ b/test/cpp/qps/qps_driver.cc @@ -0,0 +1,132 @@ +/* + * + * 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 <gflags/gflags.h> +#include <grpc/support/log.h> + +#include "test/cpp/qps/driver.h" +#include "test/cpp/qps/stats.h" + +DEFINE_int32(num_clients, 1, "Number of client binaries"); +DEFINE_int32(num_servers, 1, "Number of server binaries"); + +// Common config +DEFINE_bool(enable_ssl, false, "Use SSL"); + +// Server config +DEFINE_int32(server_threads, 1, "Number of server threads"); +DEFINE_string(server_type, "SYNCHRONOUS_SERVER", "Server type"); + +// Client config +DEFINE_int32(outstanding_rpcs_per_channel, 1, + "Number of outstanding rpcs per channel"); +DEFINE_int32(client_channels, 1, "Number of client channels"); +DEFINE_int32(payload_size, 1, "Payload size"); +DEFINE_string(client_type, "SYNCHRONOUS_CLIENT", "Client type"); +DEFINE_int32(async_client_threads, 1, "Async client threads"); + +using grpc::testing::ClientConfig; +using grpc::testing::ServerConfig; +using grpc::testing::ClientType; +using grpc::testing::ServerType; +using grpc::testing::ResourceUsage; +using grpc::testing::sum; + +// In some distros, gflags is in the namespace google, and in some others, +// in gflags. This hack is enabling us to find both. +namespace google {} +namespace gflags {} +using namespace google; +using namespace gflags; + +int main(int argc, char **argv) { + grpc_init(); + ParseCommandLineFlags(&argc, &argv, true); + + ClientType client_type; + ServerType server_type; + GPR_ASSERT(ClientType_Parse(FLAGS_client_type, &client_type)); + GPR_ASSERT(ServerType_Parse(FLAGS_server_type, &server_type)); + + ClientConfig client_config; + client_config.set_client_type(client_type); + client_config.set_enable_ssl(FLAGS_enable_ssl); + client_config.set_outstanding_rpcs_per_channel( + FLAGS_outstanding_rpcs_per_channel); + client_config.set_client_channels(FLAGS_client_channels); + client_config.set_payload_size(FLAGS_payload_size); + client_config.set_async_client_threads(FLAGS_async_client_threads); + + ServerConfig server_config; + server_config.set_server_type(server_type); + server_config.set_threads(FLAGS_server_threads); + server_config.set_enable_ssl(FLAGS_enable_ssl); + + auto result = RunScenario(client_config, FLAGS_num_clients, server_config, + FLAGS_num_servers); + + gpr_log(GPR_INFO, "QPS: %.1f", + result.latencies.Count() / + average(result.client_resources, + [](ResourceUsage u) { return u.wall_time; })); + + gpr_log(GPR_INFO, "Latencies (50/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f us", + result.latencies.Percentile(50) / 1000, + result.latencies.Percentile(95) / 1000, + result.latencies.Percentile(99) / 1000, + result.latencies.Percentile(99.9) / 1000); + + gpr_log(GPR_INFO, "Server system time: %.2f%%", + 100.0 * sum(result.server_resources, + [](ResourceUsage u) { return u.system_time; }) / + sum(result.server_resources, + [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Server user time: %.2f%%", + 100.0 * sum(result.server_resources, + [](ResourceUsage u) { return u.user_time; }) / + sum(result.server_resources, + [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Client system time: %.2f%%", + 100.0 * sum(result.client_resources, + [](ResourceUsage u) { return u.system_time; }) / + sum(result.client_resources, + [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Client user time: %.2f%%", + 100.0 * sum(result.client_resources, + [](ResourceUsage u) { return u.user_time; }) / + sum(result.client_resources, + [](ResourceUsage u) { return u.wall_time; })); + + grpc_shutdown(); + return 0; +} diff --git a/test/cpp/qps/qpstest.proto b/test/cpp/qps/qpstest.proto index 68ec6149f59669954b03bbe6425c6de271604a1c..6a7170bf5807630fb1fdf4958ddf024b0d94094f 100644 --- a/test/cpp/qps/qpstest.proto +++ b/test/cpp/qps/qpstest.proto @@ -51,17 +51,14 @@ message StatsRequest { } message ServerStats { - // wall clock time for timestamp - required double time_now = 1; + // wall clock time + required double time_elapsed = 1; // user time used by the server process and threads required double time_user = 2; // server time used by the server process and all threads required double time_system = 3; - - // RPC count so far - optional int32 num_rpcs = 4; } message Payload { @@ -71,31 +68,75 @@ message Payload { optional bytes body = 2; } -message Latencies { - required double l_50 = 1; - required double l_90 = 2; - required double l_99 = 3; - required double l_999 = 4; +message HistogramData { + repeated uint32 bucket = 1; + required double min_seen = 2; + required double max_seen = 3; + required double sum = 4; + required double sum_of_squares = 5; + required double count = 6; +} + +enum ClientType { + SYNCHRONOUS_CLIENT = 1; + ASYNC_CLIENT = 2; +} + +enum ServerType { + SYNCHRONOUS_SERVER = 1; + ASYNC_SERVER = 2; +} + +message ClientConfig { + repeated string server_targets = 1; + required ClientType client_type = 2; + required bool enable_ssl = 3; + required int32 outstanding_rpcs_per_channel = 4; + required int32 client_channels = 5; + required int32 payload_size = 6; + // only for async client: + optional int32 async_client_threads = 7; } -message StartArgs { - required string server_host = 1; - required int32 server_port = 2; - optional bool enable_ssl = 3 [default = false]; - optional int32 client_threads = 4 [default = 1]; - optional int32 client_channels = 5 [default = -1]; - optional int32 num_rpcs = 6 [default = 1]; - optional int32 payload_size = 7 [default = 1]; +// Request current stats +message Mark {} + +message ClientArgs { + oneof argtype { + ClientConfig setup = 1; + Mark mark = 2; + } } -message StartResult { - required Latencies latencies = 1; - required int32 num_rpcs = 2; +message ClientStats { + required HistogramData latencies = 1; required double time_elapsed = 3; required double time_user = 4; required double time_system = 5; } +message ClientStatus { + optional ClientStats stats = 1; +} + +message ServerConfig { + required ServerType server_type = 1; + required int32 threads = 2; + required bool enable_ssl = 3; +} + +message ServerArgs { + oneof argtype { + ServerConfig setup = 1; + Mark mark = 2; + } +} + +message ServerStatus { + optional ServerStats stats = 1; + required int32 port = 2; +} + message SimpleRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, server randomly chooses one from other formats. @@ -153,12 +194,6 @@ message StreamingOutputCallResponse { } service TestService { - // Start test with specified workload - rpc StartTest(StartArgs) returns (Latencies); - - // Collect stats from server, ignore request content - rpc CollectServerStats(StatsRequest) returns (ServerStats); - // One request followed by one response. // The server returns the client payload as-is. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); @@ -186,3 +221,10 @@ service TestService { rpc HalfDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); } + +service Worker { + // Start test with specified workload + rpc RunTest(stream ClientArgs) returns (stream ClientStatus); + // Start test with specified workload + rpc RunServer(stream ServerArgs) returns (stream ServerStatus); +} diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server.cc index be27c12b30a701b1c2537df3ad56ffdb49e6ac1b..005f0f9c5e2d78f440480a7e0440fdb94dc5d739 100644 --- a/test/cpp/qps/server.cc +++ b/test/cpp/qps/server.cc @@ -45,6 +45,7 @@ #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> #include <grpc++/status.h> #include "src/cpp/server/thread_pool.h" #include "test/core/util/grpc_profiler.h" @@ -136,7 +137,7 @@ static void RunServer() { SimpleResponse response; ServerBuilder builder; - builder.AddPort(server_address); + builder.AddPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr<ThreadPool> pool(new ThreadPool(FLAGS_server_threads)); diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h new file mode 100644 index 0000000000000000000000000000000000000000..ef71cb94d00a379e47ec1c9233105a24ad80b69d --- /dev/null +++ b/test/cpp/qps/server.h @@ -0,0 +1,84 @@ +/* + * + * 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 TEST_QPS_SERVER_H +#define TEST_QPS_SERVER_H + +#include "test/cpp/qps/timer.h" +#include "test/cpp/qps/qpstest.pb.h" + +namespace grpc { +namespace testing { + +class Server { + public: + Server() : timer_(new Timer) {} + virtual ~Server() {} + + ServerStats Mark() { + std::unique_ptr<Timer> timer(new Timer); + timer.swap(timer_); + + auto timer_result = timer->Mark(); + + ServerStats stats; + stats.set_time_elapsed(timer_result.wall); + stats.set_time_system(timer_result.system); + stats.set_time_user(timer_result.user); + return stats; + } + + static bool SetPayload(PayloadType type, int size, Payload* payload) { + PayloadType response_type = type; + // TODO(yangg): Support UNCOMPRESSABLE payload. + if (type != PayloadType::COMPRESSABLE) { + return false; + } + payload->set_type(response_type); + std::unique_ptr<char[]> body(new char[size]()); + payload->set_body(body.get(), size); + return true; + } + + private: + std::unique_ptr<Timer> timer_; +}; + +std::unique_ptr<Server> CreateSynchronousServer(const ServerConfig& config, + int port); +std::unique_ptr<Server> CreateAsyncServer(const ServerConfig& config, int port); + +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index c797d8af9630bf4fdddee06c838b1e3ef39a5d94..19778e5a7cd09c6c231c17aa09d5e8c4458f59bc 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -46,125 +46,71 @@ #include <grpc++/server.h> #include <grpc++/server_builder.h> #include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> #include <grpc++/status.h> #include <gtest/gtest.h> #include "src/cpp/server/thread_pool.h" #include "test/core/util/grpc_profiler.h" #include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/server.h" #include <grpc/grpc.h> #include <grpc/support/log.h> -DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); -DEFINE_int32(port, 0, "Server port."); -DEFINE_int32(server_threads, 4, "Number of server threads."); +namespace grpc { +namespace testing { -using grpc::CompletionQueue; -using grpc::Server; -using grpc::ServerBuilder; -using grpc::ServerContext; -using grpc::ThreadPool; -using grpc::testing::Payload; -using grpc::testing::PayloadType; -using grpc::testing::ServerStats; -using grpc::testing::SimpleRequest; -using grpc::testing::SimpleResponse; -using grpc::testing::StatsRequest; -using grpc::testing::TestService; -using grpc::Status; - -// In some distros, gflags is in the namespace google, and in some others, -// in gflags. This hack is enabling us to find both. -namespace google {} -namespace gflags {} -using namespace google; -using namespace gflags; - -static bool got_sigint = false; - -static void sigint_handler(int x) { got_sigint = 1; } - -static double time_double(struct timeval *tv) { - return tv->tv_sec + 1e-6 * tv->tv_usec; -} - -static bool SetPayload(PayloadType type, int size, Payload *payload) { - PayloadType response_type = type; - // TODO(yangg): Support UNCOMPRESSABLE payload. - if (type != PayloadType::COMPRESSABLE) { - return false; - } - payload->set_type(response_type); - std::unique_ptr<char[]> body(new char[size]()); - payload->set_body(body.get(), size); - return true; -} - -namespace { - -class AsyncQpsServerTest { +class AsyncQpsServerTest : public Server { public: - AsyncQpsServerTest() : srv_cq_(), async_service_(&srv_cq_), server_(nullptr) { + AsyncQpsServerTest(const ServerConfig &config, int port) + : srv_cq_(), async_service_(&srv_cq_), server_(nullptr) { char *server_address = NULL; - gpr_join_host_port(&server_address, "::", FLAGS_port); + gpr_join_host_port(&server_address, "::", port); ServerBuilder builder; - builder.AddPort(server_address); + builder.AddPort(server_address, InsecureServerCredentials()); + gpr_free(server_address); builder.RegisterAsyncService(&async_service_); server_ = builder.BuildAndStart(); - gpr_log(GPR_INFO, "Server listening on %s\n", server_address); - gpr_free(server_address); using namespace std::placeholders; request_unary_ = std::bind(&TestService::AsyncService::RequestUnaryCall, &async_service_, _1, _2, _3, &srv_cq_, _4); - request_stats_ = - std::bind(&TestService::AsyncService::RequestCollectServerStats, - &async_service_, _1, _2, _3, &srv_cq_, _4); for (int i = 0; i < 100; i++) { contexts_.push_front( new ServerRpcContextUnaryImpl<SimpleRequest, SimpleResponse>( request_unary_, UnaryCall)); - contexts_.push_front( - new ServerRpcContextUnaryImpl<StatsRequest, ServerStats>( - request_stats_, CollectServerStats)); - } - } - ~AsyncQpsServerTest() { - server_->Shutdown(); - void *ignored_tag; - bool ignored_ok; - srv_cq_.Shutdown(); - while (srv_cq_.Next(&ignored_tag, &ignored_ok)) { - } - while (!contexts_.empty()) { - delete contexts_.front(); - contexts_.pop_front(); } - } - void ServeRpcs(int num_threads) { - std::vector<std::thread> threads; - for (int i = 0; i < num_threads; i++) { - threads.push_back(std::thread([=]() { + for (int i = 0; i < config.threads(); i++) { + threads_.push_back(std::thread([=]() { // Wait until work is available or we are shutting down bool ok; void *got_tag; while (srv_cq_.Next(&got_tag, &ok)) { - EXPECT_EQ(ok, true); - ServerRpcContext *ctx = detag(got_tag); - // The tag is a pointer to an RPC context to invoke - if (ctx->RunNextState() == false) { - // this RPC context is done, so refresh it - ctx->Reset(); + if (ok) { + ServerRpcContext *ctx = detag(got_tag); + // The tag is a pointer to an RPC context to invoke + if (ctx->RunNextState() == false) { + // this RPC context is done, so refresh it + ctx->Reset(); + } } } return; })); } - while (!got_sigint) { - std::this_thread::sleep_for(std::chrono::seconds(5)); + } + ~AsyncQpsServerTest() { + server_->Shutdown(); + srv_cq_.Shutdown(); + for (auto &thr : threads_) { + thr.join(); + } + while (!contexts_.empty()) { + delete contexts_.front(); + contexts_.pop_front(); } } @@ -173,8 +119,8 @@ class AsyncQpsServerTest { public: ServerRpcContext() {} virtual ~ServerRpcContext(){}; - virtual bool RunNextState() = 0;// do next state, return false if all done - virtual void Reset() = 0; // start this back at a clean state + virtual bool RunNextState() = 0; // do next state, return false if all done + virtual void Reset() = 0; // start this back at a clean state }; static void *tag(ServerRpcContext *func) { return reinterpret_cast<void *>(func); @@ -237,17 +183,6 @@ class AsyncQpsServerTest { grpc::ServerAsyncResponseWriter<ResponseType> response_writer_; }; - static Status CollectServerStats(const StatsRequest *, - ServerStats *response) { - struct rusage usage; - struct timeval tv; - gettimeofday(&tv, NULL); - getrusage(RUSAGE_SELF, &usage); - response->set_time_now(time_double(&tv)); - response->set_time_user(time_double(&usage.ru_utime)); - response->set_time_system(time_double(&usage.ru_stime)); - return Status::OK; - } static Status UnaryCall(const SimpleRequest *request, SimpleResponse *response) { if (request->has_response_size() && request->response_size() > 0) { @@ -260,40 +195,18 @@ class AsyncQpsServerTest { } CompletionQueue srv_cq_; TestService::AsyncService async_service_; - std::unique_ptr<Server> server_; + std::vector<std::thread> threads_; + std::unique_ptr<grpc::Server> server_; std::function<void(ServerContext *, SimpleRequest *, grpc::ServerAsyncResponseWriter<SimpleResponse> *, void *)> request_unary_; - std::function<void(ServerContext *, StatsRequest *, - grpc::ServerAsyncResponseWriter<ServerStats> *, void *)> - request_stats_; std::forward_list<ServerRpcContext *> contexts_; }; -} // namespace - -static void RunServer() { - AsyncQpsServerTest server; - - grpc_profiler_start("qps_server_async.prof"); - - server.ServeRpcs(FLAGS_server_threads); - - grpc_profiler_stop(); +std::unique_ptr<Server> CreateAsyncServer(const ServerConfig &config, + int port) { + return std::unique_ptr<Server>(new AsyncQpsServerTest(config, port)); } -int main(int argc, char **argv) { - grpc_init(); - ParseCommandLineFlags(&argc, &argv, true); - GPR_ASSERT(FLAGS_port != 0); - GPR_ASSERT(!FLAGS_enable_ssl); - - signal(SIGINT, sigint_handler); - - RunServer(); - - grpc_shutdown(); - google::protobuf::ShutdownProtobufLibrary(); - - return 0; -} +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc new file mode 100644 index 0000000000000000000000000000000000000000..5c6541989c6bd164b5a11a2c83af36461e1aaa5c --- /dev/null +++ b/test/cpp/qps/server_sync.cc @@ -0,0 +1,108 @@ +/* + * + * 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 <sys/signal.h> +#include <thread> + +#include <unistd.h> + +#include <gflags/gflags.h> +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc++/config.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include <grpc++/server_context.h> +#include <grpc++/server_credentials.h> +#include <grpc++/status.h> +#include <grpc++/stream.h> +#include "src/cpp/server/thread_pool.h" +#include "test/core/util/grpc_profiler.h" +#include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/server.h" +#include "test/cpp/qps/timer.h" + +#include <grpc/grpc.h> +#include <grpc/support/log.h> + +namespace grpc { +namespace testing { + +class TestServiceImpl GRPC_FINAL : public TestService::Service { + public: + Status UnaryCall(ServerContext* context, const SimpleRequest* request, + SimpleResponse* response) GRPC_OVERRIDE { + if (request->has_response_size() && request->response_size() > 0) { + if (!Server::SetPayload(request->response_type(), + request->response_size(), + response->mutable_payload())) { + return Status(grpc::StatusCode::INTERNAL, "Error creating payload."); + } + } + return Status::OK; + } +}; + +class SynchronousServer GRPC_FINAL : public grpc::testing::Server { + public: + SynchronousServer(const ServerConfig& config, int port) + : thread_pool_(config.threads()), impl_(MakeImpl(port)) {} + + private: + std::unique_ptr<grpc::Server> MakeImpl(int port) { + ServerBuilder builder; + + char* server_address = NULL; + gpr_join_host_port(&server_address, "::", port); + builder.AddPort(server_address, InsecureServerCredentials()); + gpr_free(server_address); + + builder.RegisterService(&service_); + + builder.SetThreadPool(&thread_pool_); + + return builder.BuildAndStart(); + } + + TestServiceImpl service_; + ThreadPool thread_pool_; + std::unique_ptr<grpc::Server> impl_; +}; + +std::unique_ptr<grpc::testing::Server> CreateSynchronousServer( + const ServerConfig& config, int port) { + return std::unique_ptr<Server>(new SynchronousServer(config, port)); +} + +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh new file mode 100755 index 0000000000000000000000000000000000000000..2f60b4e49dec55a36bc11cd6c8aa5963e9a5c702 --- /dev/null +++ b/test/cpp/qps/single_run_localhost.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# performs a single qps run with one client and one server + +set -ex + +cd $(dirname $0)/../../.. + +killall qps_worker || true + +config=opt + +NUMCPUS=`python2.7 -c 'import multiprocessing; print multiprocessing.cpu_count()'` + +make CONFIG=$config qps_worker qps_driver -j$NUMCPUS + +bins/$config/qps_worker -driver_port 10000 -server_port 10001 & +PID1=$! +bins/$config/qps_worker -driver_port 10010 -server_port 10011 & +PID2=$! + +export QPS_WORKERS="localhost:10000,localhost:10010" + +bins/$config/qps_driver $* + +kill -2 $PID1 $PID2 +wait + diff --git a/test/cpp/qps/stats.h b/test/cpp/qps/stats.h new file mode 100644 index 0000000000000000000000000000000000000000..ca59390ad79958a371dec9dda4747d8f5ebc65d9 --- /dev/null +++ b/test/cpp/qps/stats.h @@ -0,0 +1,60 @@ +/* + * + * 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 TEST_QPS_STATS_UTILS_H +#define TEST_QPS_STATS_UTILS_H + +#include "test/cpp/qps/histogram.h" +#include <string> + +namespace grpc { +namespace testing { + +template <class T, class F> +double sum(const T& container, F functor) { + double r = 0; + for (auto v : container) { + r += functor(v); + } + return r; +} + +template <class T, class F> +double average(const T& container, F functor) { + return sum(container, functor) / container.size(); +} + +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/timer.cc b/test/cpp/qps/timer.cc new file mode 100644 index 0000000000000000000000000000000000000000..3c1342041cf1f01b6c8ef077a010554c1a7ce2e1 --- /dev/null +++ b/test/cpp/qps/timer.cc @@ -0,0 +1,71 @@ +/* + * + * 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 "test/cpp/qps/timer.h" + +#include <sys/time.h> +#include <sys/resource.h> +#include <grpc/support/time.h> + +Timer::Timer() : start_(Sample()) {} + +double Timer::Now() { + auto ts = gpr_now(); + return ts.tv_sec + 1e-9 * ts.tv_nsec; +} + +static double time_double(struct timeval* tv) { + return tv->tv_sec + 1e-6 * tv->tv_usec; +} + +Timer::Result Timer::Sample() { + struct rusage usage; + struct timeval tv; + gettimeofday(&tv, nullptr); + getrusage(RUSAGE_SELF, &usage); + + Result r; + r.wall = time_double(&tv); + r.user = time_double(&usage.ru_utime); + r.system = time_double(&usage.ru_stime); + return r; +} + +Timer::Result Timer::Mark() { + Result s = Sample(); + Result r; + r.wall = s.wall - start_.wall; + r.user = s.user - start_.user; + r.system = s.system - start_.system; + return r; +} diff --git a/src/core/surface/lame_client.h b/test/cpp/qps/timer.h similarity index 83% rename from src/core/surface/lame_client.h rename to test/cpp/qps/timer.h index b13e8cb6efe690d437c60effc5667d9d809c305e..30dbd7e7d50dd6c5cdeefafc15f4f45c08696857 100644 --- a/src/core/surface/lame_client.h +++ b/test/cpp/qps/timer.h @@ -31,12 +31,27 @@ * */ -#ifndef GRPC_INTERNAL_CORE_SURFACE_LAME_CLIENT_H -#define GRPC_INTERNAL_CORE_SURFACE_LAME_CLIENT_H +#ifndef TEST_QPS_TIMER_H +#define TEST_QPS_TIMER_H -#include <grpc/grpc.h> +class Timer { + public: + Timer(); -/* Create a lame client: this client fails every operation attempted on it. */ -grpc_channel *grpc_lame_client_channel_create(void); + struct Result { + double wall; + double user; + double system; + }; -#endif /* GRPC_INTERNAL_CORE_SURFACE_LAME_CLIENT_H */ + Result Mark(); + + static double Now(); + + private: + static Result Sample(); + + const Result start_; +}; + +#endif // TEST_QPS_TIMER_H diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc new file mode 100644 index 0000000000000000000000000000000000000000..faabfd1147796149e127fcc4df0abc875f307a45 --- /dev/null +++ b/test/cpp/qps/worker.cc @@ -0,0 +1,236 @@ +/* + * + * 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 <cassert> +#include <memory> +#include <mutex> +#include <string> +#include <thread> +#include <vector> +#include <sstream> + +#include <sys/signal.h> + +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/histogram.h> +#include <grpc/support/log.h> +#include <grpc/support/host_port.h> +#include <gflags/gflags.h> +#include <grpc++/client_context.h> +#include <grpc++/status.h> +#include <grpc++/server.h> +#include <grpc++/server_builder.h> +#include <grpc++/server_credentials.h> +#include <grpc++/stream.h> +#include "test/core/util/grpc_profiler.h" +#include "test/cpp/util/create_test_channel.h" +#include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/client.h" +#include "test/cpp/qps/server.h" + +DEFINE_int32(driver_port, 0, "Driver server port."); +DEFINE_int32(server_port, 0, "Spawned server port."); + +// In some distros, gflags is in the namespace google, and in some others, +// in gflags. This hack is enabling us to find both. +namespace google {} +namespace gflags {} +using namespace google; +using namespace gflags; + +static bool got_sigint = false; + +namespace grpc { +namespace testing { + +std::unique_ptr<Client> CreateClient(const ClientConfig& config) { + switch (config.client_type()) { + case ClientType::SYNCHRONOUS_CLIENT: + return CreateSynchronousClient(config); + case ClientType::ASYNC_CLIENT: + return CreateAsyncClient(config); + } + abort(); +} + +std::unique_ptr<Server> CreateServer(const ServerConfig& config) { + switch (config.server_type()) { + case ServerType::SYNCHRONOUS_SERVER: + return CreateSynchronousServer(config, FLAGS_server_port); + case ServerType::ASYNC_SERVER: + return CreateAsyncServer(config, FLAGS_server_port); + } + abort(); +} + +class WorkerImpl GRPC_FINAL : public Worker::Service { + public: + WorkerImpl() : acquired_(false) {} + + Status RunTest(ServerContext* ctx, + ServerReaderWriter<ClientStatus, ClientArgs>* stream) + GRPC_OVERRIDE { + InstanceGuard g(this); + if (!g.Acquired()) { + return Status(RESOURCE_EXHAUSTED); + } + + ClientArgs args; + if (!stream->Read(&args)) { + return Status(INVALID_ARGUMENT); + } + if (!args.has_setup()) { + return Status(INVALID_ARGUMENT); + } + auto client = CreateClient(args.setup()); + if (!client) { + return Status(INVALID_ARGUMENT); + } + ClientStatus status; + if (!stream->Write(status)) { + return Status(UNKNOWN); + } + while (stream->Read(&args)) { + if (!args.has_mark()) { + return Status(INVALID_ARGUMENT); + } + *status.mutable_stats() = client->Mark(); + stream->Write(status); + } + + return Status::OK; + } + + Status RunServer(ServerContext* ctx, + ServerReaderWriter<ServerStatus, ServerArgs>* stream) + GRPC_OVERRIDE { + InstanceGuard g(this); + if (!g.Acquired()) { + return Status(RESOURCE_EXHAUSTED); + } + + ServerArgs args; + if (!stream->Read(&args)) { + return Status(INVALID_ARGUMENT); + } + if (!args.has_setup()) { + return Status(INVALID_ARGUMENT); + } + auto server = CreateServer(args.setup()); + if (!server) { + return Status(INVALID_ARGUMENT); + } + ServerStatus status; + status.set_port(FLAGS_server_port); + if (!stream->Write(status)) { + return Status(UNKNOWN); + } + while (stream->Read(&args)) { + if (!args.has_mark()) { + return Status(INVALID_ARGUMENT); + } + *status.mutable_stats() = server->Mark(); + stream->Write(status); + } + + return Status::OK; + } + + private: + // Protect against multiple clients using this worker at once. + class InstanceGuard { + public: + InstanceGuard(WorkerImpl* impl) + : impl_(impl), acquired_(impl->TryAcquireInstance()) {} + ~InstanceGuard() { + if (acquired_) { + impl_->ReleaseInstance(); + } + } + + bool Acquired() const { return acquired_; } + + private: + WorkerImpl* const impl_; + const bool acquired_; + }; + + bool TryAcquireInstance() { + std::lock_guard<std::mutex> g(mu_); + if (acquired_) return false; + acquired_ = true; + return true; + } + + void ReleaseInstance() { + std::lock_guard<std::mutex> g(mu_); + GPR_ASSERT(acquired_); + acquired_ = false; + } + + std::mutex mu_; + bool acquired_; +}; + +static void RunServer() { + char* server_address = NULL; + gpr_join_host_port(&server_address, "::", FLAGS_driver_port); + + WorkerImpl service; + + ServerBuilder builder; + builder.AddPort(server_address, InsecureServerCredentials()); + builder.RegisterService(&service); + + gpr_free(server_address); + + auto server = builder.BuildAndStart(); + + while (!got_sigint) { + std::this_thread::sleep_for(std::chrono::seconds(5)); + } +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc_init(); + ParseCommandLineFlags(&argc, &argv, true); + + grpc::testing::RunServer(); + + grpc_shutdown(); + return 0; +} diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc index 745496f463013dac0b106192a9ba59f94e2cd599..d3b84b29653631133dbc2070d24a5d75f6620fd5 100644 --- a/test/cpp/util/create_test_channel.cc +++ b/test/cpp/util/create_test_channel.cc @@ -61,12 +61,10 @@ std::shared_ptr<ChannelInterface> CreateTestChannel( const std::unique_ptr<Credentials>& creds) { ChannelArguments channel_args; if (enable_ssl) { - const char* roots_certs = - use_prod_roots ? "" : test_root_cert; + const char* roots_certs = use_prod_roots ? "" : test_root_cert; SslCredentialsOptions ssl_opts = {roots_certs, "", ""}; - std::unique_ptr<Credentials> channel_creds = - CredentialsFactory::SslCredentials(ssl_opts); + std::unique_ptr<Credentials> channel_creds = SslCredentials(ssl_opts); if (!server.empty() && !override_hostname.empty()) { channel_args.SetSslTargetNameOverride(override_hostname); @@ -75,11 +73,11 @@ std::shared_ptr<ChannelInterface> CreateTestChannel( server.empty() ? override_hostname : server; if (creds.get()) { channel_creds = - CredentialsFactory::CompositeCredentials(creds, channel_creds); + CompositeCredentials(creds, channel_creds); } return CreateChannel(connect_to, channel_creds, channel_args); } else { - return CreateChannelDeprecated(server, channel_args); + return CreateChannel(server, InsecureCredentials(), channel_args); } } diff --git a/tools/dockerfile/grpc_csharp_mono/Dockerfile b/tools/dockerfile/grpc_csharp_mono/Dockerfile index d0e2d2be7e44f9123d91737491290f498b881076..8f8636656062640c47f79a5a476ba7a63db711fa 100644 --- a/tools/dockerfile/grpc_csharp_mono/Dockerfile +++ b/tools/dockerfile/grpc_csharp_mono/Dockerfile @@ -38,12 +38,8 @@ RUN cd /var/local/git/grpc \ # Install the gRPC C# extension library RUN make install_grpc_csharp_ext -j12 -C /var/local/git/grpc -# TODO: download NuGet from web. The problem is there seems to be no direct link -# we could use :-) -ADD NuGet.exe NuGet.exe - # Restore the NuGet dependencies -RUN cd /var/local/git/grpc/src/csharp && mono /NuGet.exe restore Grpc.sln +RUN cd /var/local/git/grpc/src/csharp && mono /var/local/NuGet.exe restore Grpc.sln # Build gRPC solution RUN cd /var/local/git/grpc/src/csharp && xbuild Grpc.sln diff --git a/tools/dockerfile/grpc_csharp_mono_base/Dockerfile b/tools/dockerfile/grpc_csharp_mono_base/Dockerfile index 74919a7fdb5786a4a27433112c98949cb6f0c8e2..88766a4545a526e40daab1fa17c6b754092134cc 100644 --- a/tools/dockerfile/grpc_csharp_mono_base/Dockerfile +++ b/tools/dockerfile/grpc_csharp_mono_base/Dockerfile @@ -43,6 +43,9 @@ RUN apt-get update && apt-get install -y \ nunit-console \ monodevelop +# Download NuGet +RUN cd /var/local && wget www.nuget.org/NuGet.exe + # Get the source from GitHub RUN git clone git@github.com:grpc/grpc.git /var/local/git/grpc RUN cd /var/local/git/grpc && \ diff --git a/tools/dockerfile/grpc_python/Dockerfile b/tools/dockerfile/grpc_python/Dockerfile index 2e72752cdd78e7769c9f903acbe350f3e53041bd..58a3d8c14f1c2aa6c5bdb1d913f750dd361865a4 100644 --- a/tools/dockerfile/grpc_python/Dockerfile +++ b/tools/dockerfile/grpc_python/Dockerfile @@ -44,21 +44,21 @@ RUN cd /var/local/git/grpc \ && pip install src/python/interop # Run Python GRPC's tests +# TODO(nathaniel): It would be nice for these to be auto-discoverable? RUN cd /var/local/git/grpc \ - # TODO(nathaniel): It would be nice for these to be auto-discoverable? - && python2.7 -B -m grpc._adapter._blocking_invocation_inline_service_test - && python2.7 -B -m grpc._adapter._c_test - && python2.7 -B -m grpc._adapter._event_invocation_synchronous_event_service_test - && python2.7 -B -m grpc._adapter._future_invocation_asynchronous_event_service_test - && python2.7 -B -m grpc._adapter._links_test - && python2.7 -B -m grpc._adapter._lonely_rear_link_test - && python2.7 -B -m grpc._adapter._low_test - && python2.7 -B -m grpc.framework.assembly.implementations_test - && python2.7 -B -m grpc.framework.base.packets.implementations_test - && python2.7 -B -m grpc.framework.face.blocking_invocation_inline_service_test - && python2.7 -B -m grpc.framework.face.event_invocation_synchronous_event_service_test - && python2.7 -B -m grpc.framework.face.future_invocation_asynchronous_event_service_test - && python2.7 -B -m grpc.framework.foundation._later_test + && python2.7 -B -m grpc._adapter._blocking_invocation_inline_service_test \ + && python2.7 -B -m grpc._adapter._c_test \ + && python2.7 -B -m grpc._adapter._event_invocation_synchronous_event_service_test \ + && python2.7 -B -m grpc._adapter._future_invocation_asynchronous_event_service_test \ + && python2.7 -B -m grpc._adapter._links_test \ + && python2.7 -B -m grpc._adapter._lonely_rear_link_test \ + && python2.7 -B -m grpc._adapter._low_test \ + && python2.7 -B -m grpc.framework.assembly.implementations_test \ + && python2.7 -B -m grpc.framework.base.packets.implementations_test \ + && python2.7 -B -m grpc.framework.face.blocking_invocation_inline_service_test \ + && python2.7 -B -m grpc.framework.face.event_invocation_synchronous_event_service_test \ + && python2.7 -B -m grpc.framework.face.future_invocation_asynchronous_event_service_test \ + && python2.7 -B -m grpc.framework.foundation._later_test \ && python2.7 -B -m grpc.framework.foundation._logging_pool_test # Add a cacerts directory containing the Google root pem file, allowing the interop client to access the production test instance diff --git a/tools/gce_setup/build_images.sh b/tools/gce_setup/build_images.sh new file mode 100755 index 0000000000000000000000000000000000000000..0b1c32b7d6dc9cda37a080be81de5e736d4b5950 --- /dev/null +++ b/tools/gce_setup/build_images.sh @@ -0,0 +1,46 @@ +#!/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. + + +main() { + # rebuild images on all languages on existing builder vm. + source grpc_docker.sh + cd ../../ + + # build images for all languages + languages=(cxx java go ruby node python csharp_mono) + for lan in "${languages[@]}" + do + grpc_update_image $lan + done +} + +set -x +main "$@" diff --git a/tools/gce_setup/builder.sh b/tools/gce_setup/builder.sh index d4dbd75426cf22e13610477b54ef51f1827e0a67..8815d082da7931de19404824305728eb69339bfa 100755 --- a/tools/gce_setup/builder.sh +++ b/tools/gce_setup/builder.sh @@ -37,7 +37,7 @@ main() { sleep 3600 # build images for all languages - languages=(cxx java go ruby node) + languages=(cxx java go ruby node python csharp_mono) for lan in "${languages[@]}" do grpc_update_image $lan diff --git a/tools/gce_setup/cloud_prod_runner.sh b/tools/gce_setup/cloud_prod_runner.sh index e11185c226b3e100f703774d000c4008f6ba2bcc..3a9ae51b769572239b4475e57afd3bd6d483ea0f 100755 --- a/tools/gce_setup/cloud_prod_runner.sh +++ b/tools/gce_setup/cloud_prod_runner.sh @@ -28,21 +28,25 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +thisfile=$(readlink -ne "${BASH_SOURCE[0]}") +current_time=$(date "+%Y-%m-%d-%H-%M-%S") +result_file_name=cloud_prod_result.$current_time.html +echo $result_file_name main() { source grpc_docker.sh test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response) auth_test_cases=(service_account_creds compute_engine_creds) - clients=(cxx java go ruby node) + clients=(cxx java go ruby node csharp_mono) for test_case in "${test_cases[@]}" do for client in "${clients[@]}" do if grpc_cloud_prod_test $test_case grpc-docker-testclients $client then - echo "$test_case $client $server passed" >> /tmp/cloud_prod_result.txt + echo " ['$test_case', '$client', 'prod', true]," >> /tmp/cloud_prod_result.txt else - echo "$test_case $client $server failed" >> /tmp/cloud_prod_result.txt + echo " ['$test_case', '$client', 'prod', false]," >> /tmp/cloud_prod_result.txt fi done done @@ -52,14 +56,20 @@ main() { do if grpc_cloud_prod_auth_test $test_case grpc-docker-testclients $client then - echo "$test_case $client $server passed" >> /tmp/cloud_prod_result.txt + echo " ['$test_case', '$client', 'prod', true]," >> /tmp/cloud_prod_result.txt else - echo "$test_case $client $server failed" >> /tmp/cloud_prod_result.txt + echo " ['$test_case', '$client', 'prod', false]," >> /tmp/cloud_prod_result.txt fi done done - gsutil cp /tmp/cloud_prod_result.txt gs://stoked-keyword-656-output/cloud_prod_result.txt - rm /tmp/cloud_prod_result.txt + if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + cat pre.html /tmp/cloud_prod_result.txt post.html > /tmp/cloud_prod_result.html + gsutil cp /tmp/cloud_prod_result.txt gs://stoked-keyword-656-output/cloud_prod_result.txt + gsutil cp /tmp/cloud_prod_result.html gs://stoked-keyword-656-output/cloud_prod_result.html + gsutil cp /tmp/cloud_prod_result.html gs://stoked-keyword-656-output/result_history/$result_file_name + rm /tmp/cloud_prod_result.txt + rm /tmp/cloud_prod_result.html + fi } set -x diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh index 02039261a35a9bfe6f9b30edcb22453a0ecbf523..3deef05ef35d888c6ff8c81f70d6968b6c72b693 100755 --- a/tools/gce_setup/grpc_docker.sh +++ b/tools/gce_setup/grpc_docker.sh @@ -383,7 +383,7 @@ grpc_interop_test_args() { [[ -n $1 ]] && { # client_type case $1 in - cxx|go|java|node|php|python|ruby) + cxx|go|java|node|php|python|ruby|csharp_mono) grpc_gen_test_cmd="grpc_interop_gen_$1_cmd" declare -F $grpc_gen_test_cmd >> /dev/null || { echo "-f: test_func for $1 => $grpc_gen_test_cmd is not defined" 1>&2 @@ -411,12 +411,13 @@ grpc_interop_test_args() { [[ -n $1 ]] && { # server_type case $1 in - cxx) grpc_port=8010 ;; - go) grpc_port=8020 ;; - java) grpc_port=8030 ;; - node) grpc_port=8040 ;; - python) grpc_port=8050 ;; - ruby) grpc_port=8060 ;; + cxx) grpc_port=8010 ;; + go) grpc_port=8020 ;; + java) grpc_port=8030 ;; + node) grpc_port=8040 ;; + python) grpc_port=8050 ;; + ruby) grpc_port=8060 ;; + csharp_mono) grpc_port=8070 ;; *) echo "bad server_type: $1" 1>&2; return 1 ;; esac shift @@ -454,7 +455,7 @@ grpc_cloud_prod_test_args() { [[ -n $1 ]] && { # client_type case $1 in - cxx|go|java|node|php|python|ruby) + cxx|go|java|node|php|python|ruby|csharp_mono) grpc_gen_test_cmd="grpc_cloud_prod_gen_$1_cmd" declare -F $grpc_gen_test_cmd >> /dev/null || { echo "-f: test_func for $1 => $grpc_gen_test_cmd is not defined" 1>&2 @@ -673,7 +674,7 @@ _grpc_launch_servers_args() { [[ -n $1 ]] && { servers="$@" } || { - servers="cxx java go node ruby python" + servers="cxx java go node ruby python csharp_mono" echo "$FUNCNAME: no servers specified, will launch defaults '$servers'" } } @@ -709,6 +710,7 @@ grpc_launch_servers() { node) grpc_port=8040 ;; python) grpc_port=8050 ;; ruby) grpc_port=8060 ;; + csharp_mono) grpc_port=8070 ;; *) echo "bad server_type: $1" 1>&2; return 1 ;; esac local docker_label="grpc/$server" @@ -729,6 +731,44 @@ grpc_launch_servers() { done } +# Runs a test command on a docker instance +# +# The test command is issued via gcloud compute +# +# There are 3 possible results: +# 1. successful return code and finished within 60 seconds +# 2. failure return code and finished within 60 seconds +# 3. command does not return within 60 seconds, in which case it will be killed. +test_runner() { + local project_opt="--project $grpc_project" + local zone_opt="--zone $grpc_zone" + local ssh_cmd="bash -l -c \"$cmd\"" + echo "will run:" + echo " $ssh_cmd" + echo "on $host" + [[ $dry_run == 1 ]] && return 0 # don't run the command on a dry run + gcloud compute $project_opt ssh $zone_opt $host --command "$cmd" & + PID=$! + echo "pid is $PID" + for x in {0..5} + do + if ps -p $PID + then + # test command has not returned and 60 seconds timeout has not reached + sleep 10 + else + # test command has returned, return the return code from the test command + wait $PID + local ret=$? + echo " test runner return $ret before timeout" + return $ret + fi + done + kill $PID + echo "test got killed by timeout return as failure" + return 1 +} + # Runs a test command on a docker instance. # # call-seq: @@ -788,14 +828,7 @@ grpc_interop_test() { cmd=$($grpc_gen_test_cmd $flags) [[ -n $cmd ]] || return 1 - local project_opt="--project $grpc_project" - local zone_opt="--zone $grpc_zone" - local ssh_cmd="bash -l -c \"$cmd\"" - echo "will run:" - echo " $ssh_cmd" - echo "on $host" - [[ $dry_run == 1 ]] && return 0 # don't run the command on a dry run - gcloud compute $project_opt ssh $zone_opt $host --command "$cmd" + test_runner } # Runs a test command on a docker instance. @@ -834,14 +867,7 @@ grpc_cloud_prod_test() { cmd=$($grpc_gen_test_cmd $test_case_flag) [[ -n $cmd ]] || return 1 - local project_opt="--project $grpc_project" - local zone_opt="--zone $grpc_zone" - local ssh_cmd="bash -l -c \"$cmd\"" - echo "will run:" - echo " $ssh_cmd" - echo "on $host" - [[ $dry_run == 1 ]] && return 0 # don't run the command on a dry run - gcloud compute $project_opt ssh $zone_opt $host --command "$cmd" + test_runner } # Runs a test command on a docker instance. @@ -880,14 +906,7 @@ grpc_cloud_prod_auth_test() { cmd=$($grpc_gen_test_cmd $test_case_flag) [[ -n $cmd ]] || return 1 - local project_opt="--project $grpc_project" - local zone_opt="--zone $grpc_zone" - local ssh_cmd="bash -l -c \"$cmd\"" - echo "will run:" - echo " $ssh_cmd" - echo "on $host" - [[ $dry_run == 1 ]] && return 0 # don't run the command on a dry run - gcloud compute $project_opt ssh $zone_opt $host --command "$cmd" + test_runner } # constructs the full dockerized ruby interop test cmd. @@ -902,6 +921,17 @@ grpc_interop_gen_ruby_cmd() { echo $the_cmd } +# constructs the full dockerized python interop test cmd. +# +# call-seq: +# flags= .... # generic flags to include the command +# cmd=$($grpc_gen_test_cmd $flags) +grpc_interop_gen_python_cmd() { + local cmd_prefix="sudo docker run grpc/python bin/bash -l -c" + local the_cmd="$cmd_prefix 'python -B -m interop.client --use_test_ca --use_tls $@'" + echo $the_cmd +} + # constructs the full dockerized java interop test cmd. # # call-seq: @@ -1162,6 +1192,34 @@ grpc_cloud_prod_auth_compute_engine_creds_gen_cxx_cmd() { echo $the_cmd } +# constructs the full dockerized csharp-mono interop test cmd. +# +# call-seq: +# flags= .... # generic flags to include the command +# cmd=$($grpc_gen_test_cmd $flags) +grpc_interop_gen_csharp_mono_cmd() { + local workdir_flag="-w /var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug" + local cmd_prefix="sudo docker run $workdir_flag grpc/csharp_mono"; + local test_script="mono Grpc.IntegrationTesting.Client.exe --use_tls=true --use_test_ca=true"; + local the_cmd="$cmd_prefix $test_script $@"; + echo $the_cmd +} + +# constructs the full dockerized csharp-mono gce=>prod interop test cmd. +# +# call-seq: +# flags= .... # generic flags to include the command +# cmd=$($grpc_gen_test_cmd $flags) +grpc_cloud_prod_gen_csharp_mono_cmd() { + local env_flag="-e SSL_CERT_FILE=/cacerts/roots.pem " + local workdir_flag="-w /var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Client/bin/Debug" + local cmd_prefix="sudo docker run $env_flag $workdir_flag grpc/csharp_mono"; + local test_script="mono Grpc.IntegrationTesting.Client.exe --use_tls=true"; + local gfe_flags=$(_grpc_prod_gfe_flags); + local the_cmd="$cmd_prefix $test_script $gfe_flags $@"; + echo $the_cmd +} + # outputs the flags passed to gfe tests _grpc_prod_gfe_flags() { echo " --server_port=443 --server_host=grpc-test.sandbox.google.com --server_host_override=grpc-test.sandbox.google.com" diff --git a/tools/gce_setup/interop_test_runner.sh b/tools/gce_setup/interop_test_runner.sh index 5f8c0e70645aba5e597f1fbdd4eb603e60047013..430ad09b8c6308ffd952b083171a8c5b2b64d9e0 100755 --- a/tools/gce_setup/interop_test_runner.sh +++ b/tools/gce_setup/interop_test_runner.sh @@ -36,7 +36,7 @@ echo $result_file_name main() { source grpc_docker.sh test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response) - clients=(cxx java go ruby node) + clients=(cxx java go ruby node python csharp_mono) servers=(cxx java go ruby node python) for test_case in "${test_cases[@]}" do diff --git a/tools/gce_setup/shared_startup_funcs.sh b/tools/gce_setup/shared_startup_funcs.sh index 195f8f28a886f982a242de516c3ca79253ba74f2..e6eecc56db62de9e92aafb60eaeed2700449c3b4 100755 --- a/tools/gce_setup/shared_startup_funcs.sh +++ b/tools/gce_setup/shared_startup_funcs.sh @@ -364,7 +364,7 @@ grpc_docker_launch_registry() { grpc_docker_pull_known() { local addr=$1 [[ -n $addr ]] || addr="0.0.0.0:5000" - local known="base cxx php_base php ruby_base ruby java_base java go node_base node python_base python" + local known="base cxx php_base php ruby_base ruby java_base java go node_base node python_base python csharp_mono_base csharp_mono" echo "... pulling docker images for '$known'" for i in $known do @@ -429,7 +429,10 @@ grpc_dockerfile_install() { grpc_docker_sync_roots_pem $dockerfile_dir/cacerts || return 1; grpc_docker_sync_service_account $dockerfile_dir/service_account || return 1; } - + [[ $image_label == "grpc/csharp_mono" ]] && { + grpc_docker_sync_roots_pem $dockerfile_dir/cacerts || return 1; + grpc_docker_sync_service_account $dockerfile_dir/service_account || return 1; + } # TODO(temiola): maybe make cache/no-cache a func option? sudo docker build $cache_opt -t $image_label $dockerfile_dir || { diff --git a/src/python/src/grpc/framework/assembly/__init__.py b/tools/run_tests/build_csharp.sh old mode 100644 new mode 100755 similarity index 93% rename from src/python/src/grpc/framework/assembly/__init__.py rename to tools/run_tests/build_csharp.sh index 708651910607ffb686d781713f6893567821b9fd..8227ad37bca5cd5f4ce06c32876106d4292f5df8 --- a/src/python/src/grpc/framework/assembly/__init__.py +++ b/tools/run_tests/build_csharp.sh @@ -1,3 +1,4 @@ +#!/bin/bash # Copyright 2015, Google Inc. # All rights reserved. # @@ -27,4 +28,11 @@ # (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)/../.. + +root=`pwd` + +xbuild src/csharp/Grpc.sln diff --git a/tools/run_tests/build_node.sh b/tools/run_tests/build_node.sh index c3e88c565d276cac7f804d545f215a417541e443..c85ecf1b2595c6fc594539400a383690c76bd08f 100755 --- a/tools/run_tests/build_node.sh +++ b/tools/run_tests/build_node.sh @@ -36,12 +36,8 @@ CONFIG=${CONFIG:-opt} # change to grpc repo root cd $(dirname $0)/../.. -# tells npm install to look for files in that directory -export GRPC_ROOT=`pwd` -# tells npm install the subdirectory with library files -export GRPC_LIB_SUBDIR=libs/$CONFIG -# tells npm install not to use default locations -export GRPC_NO_INSTALL=yes +export CXXFLAGS=-I`pwd`/include +export LDFLAGS=-L`pwd`/libs/$CONFIG cd src/node diff --git a/tools/run_tests/build_python.sh b/tools/run_tests/build_python.sh index de633083c352649acddb96e34e591f2003c106c4..0eba1c637798a4e17b0624a2810829eac03eaa69 100755 --- a/tools/run_tests/build_python.sh +++ b/tools/run_tests/build_python.sh @@ -39,3 +39,4 @@ virtualenv -p /usr/bin/python2.7 python2.7_virtual_environment source python2.7_virtual_environment/bin/activate pip install enum34==1.0.4 futures==2.2.0 protobuf==3.0.0-alpha-1 CFLAGS=-I$root/include LDFLAGS=-L$root/libs/opt pip install src/python/src +pip install src/python/interop diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py index ad65da535b42bccf7ff642b61b092b27ecf808d4..26caf031c3a5f8b5d6a71371e58e270734824f88 100755 --- a/tools/run_tests/jobset.py +++ b/tools/run_tests/jobset.py @@ -136,7 +136,7 @@ def which(filename): class JobSpec(object): """Specifies what to run for a job.""" - def __init__(self, cmdline, shortname=None, environ={}, hash_targets=[]): + def __init__(self, cmdline, shortname=None, environ=None, hash_targets=None): """ Arguments: cmdline: a list of arguments to pass as the command line @@ -144,6 +144,10 @@ class JobSpec(object): hash_targets: which files to include in the hash representing the jobs version (or empty, indicating the job should not be hashed) """ + if environ is None: + environ = {} + if hash_targets is None: + hash_targets = [] self.cmdline = cmdline self.environ = environ self.shortname = cmdline[0] if shortname is None else shortname diff --git a/tools/run_tests/python_tests.json b/tools/run_tests/python_tests.json new file mode 100755 index 0000000000000000000000000000000000000000..ef483d9799c38a96ad8707d9bc37245cd46ca014 --- /dev/null +++ b/tools/run_tests/python_tests.json @@ -0,0 +1,53 @@ +[ + { + "file": "test/compiler/python_plugin_test.py" + }, + { + "module": "grpc._adapter._blocking_invocation_inline_service_test" + }, + { + "module": "grpc._adapter._c_test" + }, + { + "module": "grpc._adapter._event_invocation_synchronous_event_service_test" + }, + { + "module": "grpc._adapter._future_invocation_asynchronous_event_service_test" + }, + { + "module": "grpc._adapter._links_test" + }, + { + "module": "grpc._adapter._lonely_rear_link_test" + }, + { + "module": "grpc._adapter._low_test" + }, + { + "module": "grpc.early_adopter.implementations_test" + }, + { + "module": "grpc.framework.base.packets.implementations_test" + }, + { + "module": "grpc.framework.face.blocking_invocation_inline_service_test" + }, + { + "module": "grpc.framework.face.event_invocation_synchronous_event_service_test" + }, + { + "module": "grpc.framework.face.future_invocation_asynchronous_event_service_test" + }, + { + "module": "grpc.framework.foundation._later_test" + }, + { + "module": "grpc.framework.foundation._logging_pool_test" + }, + { + "module": "interop._insecure_interop_test" + }, + { + "module": "interop._secure_interop_test" + } +] diff --git a/tools/run_tests/run_csharp.sh b/tools/run_tests/run_csharp.sh new file mode 100755 index 0000000000000000000000000000000000000000..d10a41ae9f4858bd5d2bcd410cf79b2d1e8a2d4c --- /dev/null +++ b/tools/run_tests/run_csharp.sh @@ -0,0 +1,46 @@ +#!/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. + +set -ex + +# change to gRPC repo root +cd $(dirname $0)/../.. + +root=`pwd` +cd src/csharp + +# TODO: All the tests run pretty fast. In the future, we might need to teach +# run_tests.py about separate tests to make them run in parallel. +for assembly_name in Grpc.Core.Tests Grpc.Examples.Tests Grpc.IntegrationTesting +do + LD_LIBRARY_PATH=$root/libs/dbg nunit-console -labels $assembly_name/bin/Debug/$assembly_name.dll +done + + diff --git a/tools/run_tests/run_node.sh b/tools/run_tests/run_node.sh index ccf1b9d6f54918d9dd713f95ee1c516a5884a9d8..3a82c04a8ef2f961fbd831ddbff42536f082ffd0 100755 --- a/tools/run_tests/run_node.sh +++ b/tools/run_tests/run_node.sh @@ -30,9 +30,13 @@ set -ex +CONFIG=${CONFIG:-opt} + # change to grpc repo root cd $(dirname $0)/../.. root=`pwd` +export LD_LIBRARY_PATH=$root/libs/$CONFIG + $root/src/node/node_modules/mocha/bin/mocha $root/src/node/test diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh index 9c7dea008dba914fe873ee2cbd28df8ff053bcce..fa1497aee478a8e2b262effc1f729a03704eb517 100755 --- a/tools/run_tests/run_python.sh +++ b/tools/run_tests/run_python.sh @@ -36,24 +36,4 @@ cd $(dirname $0)/../.. root=`pwd` export LD_LIBRARY_PATH=$root/libs/opt source python2.7_virtual_environment/bin/activate -# TODO(issue 215): Properly itemize these in run_tests.py so that they can be parallelized. -# TODO(atash): Enable dynamic unused port discovery for this test. -# TODO(mlumish): Re-enable this test when we can install protoc -# python2.7 -B test/compiler/python_plugin_test.py --build_mode=opt -python2.7 -B -m grpc._adapter._blocking_invocation_inline_service_test -python2.7 -B -m grpc._adapter._c_test -python2.7 -B -m grpc._adapter._event_invocation_synchronous_event_service_test -python2.7 -B -m grpc._adapter._future_invocation_asynchronous_event_service_test -python2.7 -B -m grpc._adapter._links_test -python2.7 -B -m grpc._adapter._lonely_rear_link_test -python2.7 -B -m grpc._adapter._low_test -python2.7 -B -m grpc.early_adopter.implementations_test -python2.7 -B -m grpc.framework.assembly.implementations_test -python2.7 -B -m grpc.framework.base.packets.implementations_test -python2.7 -B -m grpc.framework.face.blocking_invocation_inline_service_test -python2.7 -B -m grpc.framework.face.event_invocation_synchronous_event_service_test -python2.7 -B -m grpc.framework.face.future_invocation_asynchronous_event_service_test -python2.7 -B -m grpc.framework.foundation._later_test -python2.7 -B -m grpc.framework.foundation._logging_pool_test -# TODO(nathaniel): Get tests working under 3.4 (requires 3.X-friendly protobuf) -# python3.4 -B -m unittest discover -s src/python -p '*.py' +python2.7 -B $* diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index e949670b8c9de1b0e84d3fadb490eca84040b8b4..aee19cdc42d6ec9b106ce39d045dc679922584a7 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -51,14 +51,28 @@ os.chdir(ROOT) # SimpleConfig: just compile with CONFIG=config, and run the binary to test class SimpleConfig(object): - def __init__(self, config, environ={}): + def __init__(self, config, environ=None): + if environ is None: + environ = {} self.build_config = config self.maxjobs = 2 * multiprocessing.cpu_count() self.allow_hashing = (config != 'gcov') self.environ = environ - - def job_spec(self, binary, hash_targets): - return jobset.JobSpec(cmdline=[binary], + self.environ['CONFIG'] = config + + def job_spec(self, cmdline, hash_targets): + """Construct a jobset.JobSpec for a test under this config + + Args: + cmdline: a list of strings specifying the command line the test + would like to run + hash_targets: either None (don't do caching of test results), or + a list of strings specifying files to include in a + binary hash to check if a test has changed + -- if used, all artifacts needed to run the test must + be listed + """ + return jobset.JobSpec(cmdline=cmdline, environ=self.environ, hash_targets=hash_targets if self.allow_hashing else None) @@ -67,16 +81,18 @@ class SimpleConfig(object): # ValgrindConfig: compile with some CONFIG=config, but use valgrind to run class ValgrindConfig(object): - def __init__(self, config, tool, args=[]): + def __init__(self, config, tool, args=None): + if args is None: + args = [] self.build_config = config self.tool = tool self.args = args self.maxjobs = 2 * multiprocessing.cpu_count() self.allow_hashing = False - def job_spec(self, binary, hash_targets): + def job_spec(self, cmdline, hash_targets): return jobset.JobSpec(cmdline=['valgrind', '--tool=%s' % self.tool] + - self.args + [binary], + self.args + cmdline, shortname='valgrind %s' % binary, hash_targets=None) @@ -95,7 +111,7 @@ class CLanguage(object): if travis and target['flaky']: continue binary = 'bins/%s/%s' % (config.build_config, target['name']) - out.append(config.job_spec(binary, [binary])) + out.append(config.job_spec([binary], [binary])) return out def make_targets(self): @@ -104,11 +120,17 @@ class CLanguage(object): def build_steps(self): return [] + def supports_multi_config(self): + return True + + def __str__(self): + return self.make_target + class NodeLanguage(object): def test_specs(self, config, travis): - return [config.job_spec('tools/run_tests/run_node.sh', None)] + return [config.job_spec(['tools/run_tests/run_node.sh'], None)] def make_targets(self): return ['static_c'] @@ -116,11 +138,17 @@ class NodeLanguage(object): def build_steps(self): return [['tools/run_tests/build_node.sh']] + def supports_multi_config(self): + return False + + def __str__(self): + return 'node' + class PhpLanguage(object): def test_specs(self, config, travis): - return [config.job_spec('src/php/bin/run_tests.sh', None)] + return [config.job_spec(['src/php/bin/run_tests.sh'], None)] def make_targets(self): return ['static_c'] @@ -128,22 +156,44 @@ class PhpLanguage(object): def build_steps(self): return [['tools/run_tests/build_php.sh']] + def supports_multi_config(self): + return False + + def __str__(self): + return 'php' + class PythonLanguage(object): + def __init__(self): + with open('tools/run_tests/python_tests.json') as f: + self._tests = json.load(f) + def test_specs(self, config, travis): - return [config.job_spec('tools/run_tests/run_python.sh', None)] + modules = [config.job_spec(['tools/run_tests/run_python.sh', '-m', + test['module']], None) + for test in self._tests if 'module' in test] + files = [config.job_spec(['tools/run_tests/run_python.sh', + test['file']], None) + for test in self._tests if 'file' in test] + return files + modules def make_targets(self): - return ['static_c'] + return ['static_c', 'grpc_python_plugin'] def build_steps(self): return [['tools/run_tests/build_python.sh']] + def supports_multi_config(self): + return False + + def __str__(self): + return 'python' + class RubyLanguage(object): def test_specs(self, config, travis): - return [config.job_spec('tools/run_tests/run_ruby.sh', None)] + return [config.job_spec(['tools/run_tests/run_ruby.sh'], None)] def make_targets(self): return ['static_c'] @@ -151,6 +201,28 @@ class RubyLanguage(object): def build_steps(self): return [['tools/run_tests/build_ruby.sh']] + def supports_multi_config(self): + return False + + def __str__(self): + return 'ruby' + +class CSharpLanguage(object): + + def test_specs(self, config, travis): + return [config.job_spec('tools/run_tests/run_csharp.sh', None)] + + def make_targets(self): + return ['grpc_csharp_ext'] + + def build_steps(self): + return [['tools/run_tests/build_csharp.sh']] + + def supports_multi_config(self): + return False + + def __str__(self): + return 'csharp' # different configurations we can run under _CONFIGS = { @@ -175,7 +247,8 @@ _LANGUAGES = { 'node': NodeLanguage(), 'php': PhpLanguage(), 'python': PythonLanguage(), - 'ruby': RubyLanguage() + 'ruby': RubyLanguage(), + 'csharp': CSharpLanguage() } # parse command line @@ -215,6 +288,13 @@ build_configs = set(cfg.build_config for cfg in run_configs) make_targets = [] languages = set(_LANGUAGES[l] for l in args.language) + +if len(build_configs) > 1: + for language in languages: + if not language.supports_multi_config(): + print language, 'does not support multiple build configurations' + sys.exit(1) + build_steps = [jobset.JobSpec(['make', '-j', '%d' % (multiprocessing.cpu_count() + 1), 'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' % args.slowdown, @@ -222,7 +302,8 @@ build_steps = [jobset.JobSpec(['make', itertools.chain.from_iterable( l.make_targets() for l in languages)))) for cfg in build_configs] + list(set( - jobset.JobSpec(cmdline) + jobset.JobSpec(cmdline, environ={'CONFIG': cfg}) + for cfg in build_configs for l in languages for cmdline in l.build_steps())) one_run = set( @@ -298,7 +379,7 @@ test_cache.maybe_load() if forever: success = True while True: - dw = watch_dirs.DirWatcher(['src', 'include', 'test']) + dw = watch_dirs.DirWatcher(['src', 'include', 'test', 'examples']) initial_time = dw.most_recent_change() have_files_changed = lambda: dw.most_recent_change() != initial_time previous_success = success diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index 06bf58f93e8f8655bb23b50b9711c861eada67d9..6f354452aa509d5c7d6e102d50bc44ea9e981e51 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -381,6 +381,11 @@ "language": "c++", "name": "thread_pool_test" }, + { + "flaky": false, + "language": "c", + "name": "chttp2_fake_security_bad_hostname_test" + }, { "flaky": false, "language": "c", @@ -621,6 +626,11 @@ "language": "c", "name": "chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test" }, + { + "flaky": false, + "language": "c", + "name": "chttp2_fullstack_bad_hostname_test" + }, { "flaky": false, "language": "c", @@ -861,6 +871,11 @@ "language": "c", "name": "chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test" }, + { + "flaky": false, + "language": "c", + "name": "chttp2_fullstack_uds_bad_hostname_test" + }, { "flaky": false, "language": "c", @@ -1101,6 +1116,11 @@ "language": "c", "name": "chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test" }, + { + "flaky": false, + "language": "c", + "name": "chttp2_simple_ssl_fullstack_bad_hostname_test" + }, { "flaky": false, "language": "c", @@ -1341,6 +1361,11 @@ "language": "c", "name": "chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test" }, + { + "flaky": false, + "language": "c", + "name": "chttp2_simple_ssl_with_oauth2_fullstack_bad_hostname_test" + }, { "flaky": false, "language": "c", @@ -1581,6 +1606,11 @@ "language": "c", "name": "chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test" }, + { + "flaky": false, + "language": "c", + "name": "chttp2_socket_pair_bad_hostname_test" + }, { "flaky": false, "language": "c", @@ -1821,6 +1851,11 @@ "language": "c", "name": "chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test" }, + { + "flaky": false, + "language": "c", + "name": "chttp2_socket_pair_one_byte_at_a_time_bad_hostname_test" + }, { "flaky": false, "language": "c", diff --git a/vsprojects/vs2013/grpc.vcxproj b/vsprojects/vs2013/grpc.vcxproj index 60dc98024204664be8b8776949deb42c01e05c38..9d0bcb327163f30a4e6899b08b7c7974763a4315 100644 --- a/vsprojects/vs2013/grpc.vcxproj +++ b/vsprojects/vs2013/grpc.vcxproj @@ -161,7 +161,6 @@ <ClInclude Include="..\..\src\core\surface\completion_queue.h" /> <ClInclude Include="..\..\src\core\surface\event_string.h" /> <ClInclude Include="..\..\src\core\surface\init.h" /> - <ClInclude Include="..\..\src\core\surface\lame_client.h" /> <ClInclude Include="..\..\src\core\surface\server.h" /> <ClInclude Include="..\..\src\core\surface\surface_trace.h" /> <ClInclude Include="..\..\src\core\transport\chttp2\bin_encoder.h" /> @@ -224,8 +223,6 @@ </ClCompile> <ClCompile Include="..\..\src\core\surface\secure_channel_create.c"> </ClCompile> - <ClCompile Include="..\..\src\core\surface\secure_server_create.c"> - </ClCompile> <ClCompile Include="..\..\src\core\tsi\fake_transport_security.c"> </ClCompile> <ClCompile Include="..\..\src\core\tsi\ssl_transport_security.c"> diff --git a/vsprojects/vs2013/grpc.vcxproj.filters b/vsprojects/vs2013/grpc.vcxproj.filters index 9fc70e74d9de6dbd3573a6984f14b83e384a9677..af38d8de35ad2d37df2b247db721290a646fb91b 100644 --- a/vsprojects/vs2013/grpc.vcxproj.filters +++ b/vsprojects/vs2013/grpc.vcxproj.filters @@ -55,9 +55,6 @@ <ClCompile Include="..\..\src\core\surface\secure_channel_create.c"> <Filter>src\core\surface</Filter> </ClCompile> - <ClCompile Include="..\..\src\core\surface\secure_server_create.c"> - <Filter>src\core\surface</Filter> - </ClCompile> <ClCompile Include="..\..\src\core\tsi\fake_transport_security.c"> <Filter>src\core\tsi</Filter> </ClCompile> @@ -599,9 +596,6 @@ <ClInclude Include="..\..\src\core\surface\init.h"> <Filter>src\core\surface</Filter> </ClInclude> - <ClInclude Include="..\..\src\core\surface\lame_client.h"> - <Filter>src\core\surface</Filter> - </ClInclude> <ClInclude Include="..\..\src\core\surface\server.h"> <Filter>src\core\surface</Filter> </ClInclude> diff --git a/vsprojects/vs2013/grpc_shared.vcxproj b/vsprojects/vs2013/grpc_shared.vcxproj index 5c2e23b51398b81cd3a051c40813b376ecc8091c..f5575dc3f12db5abf050bdf6d44168443c848b47 100644 --- a/vsprojects/vs2013/grpc_shared.vcxproj +++ b/vsprojects/vs2013/grpc_shared.vcxproj @@ -165,7 +165,6 @@ <ClInclude Include="..\..\src\core\surface\completion_queue.h" /> <ClInclude Include="..\..\src\core\surface\event_string.h" /> <ClInclude Include="..\..\src\core\surface\init.h" /> - <ClInclude Include="..\..\src\core\surface\lame_client.h" /> <ClInclude Include="..\..\src\core\surface\server.h" /> <ClInclude Include="..\..\src\core\surface\surface_trace.h" /> <ClInclude Include="..\..\src\core\transport\chttp2\bin_encoder.h" /> @@ -228,8 +227,6 @@ </ClCompile> <ClCompile Include="..\..\src\core\surface\secure_channel_create.c"> </ClCompile> - <ClCompile Include="..\..\src\core\surface\secure_server_create.c"> - </ClCompile> <ClCompile Include="..\..\src\core\tsi\fake_transport_security.c"> </ClCompile> <ClCompile Include="..\..\src\core\tsi\ssl_transport_security.c"> diff --git a/vsprojects/vs2013/grpc_shared.vcxproj.filters b/vsprojects/vs2013/grpc_shared.vcxproj.filters index 9fc70e74d9de6dbd3573a6984f14b83e384a9677..af38d8de35ad2d37df2b247db721290a646fb91b 100644 --- a/vsprojects/vs2013/grpc_shared.vcxproj.filters +++ b/vsprojects/vs2013/grpc_shared.vcxproj.filters @@ -55,9 +55,6 @@ <ClCompile Include="..\..\src\core\surface\secure_channel_create.c"> <Filter>src\core\surface</Filter> </ClCompile> - <ClCompile Include="..\..\src\core\surface\secure_server_create.c"> - <Filter>src\core\surface</Filter> - </ClCompile> <ClCompile Include="..\..\src\core\tsi\fake_transport_security.c"> <Filter>src\core\tsi</Filter> </ClCompile> @@ -599,9 +596,6 @@ <ClInclude Include="..\..\src\core\surface\init.h"> <Filter>src\core\surface</Filter> </ClInclude> - <ClInclude Include="..\..\src\core\surface\lame_client.h"> - <Filter>src\core\surface</Filter> - </ClInclude> <ClInclude Include="..\..\src\core\surface\server.h"> <Filter>src\core\surface</Filter> </ClInclude> diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj b/vsprojects/vs2013/grpc_unsecure.vcxproj index 9181db0b4e126f3e7d6caf919d45068ebfae4adc..ad7bf4762f57d451709e44349da6105c1276bef2 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj @@ -146,7 +146,6 @@ <ClInclude Include="..\..\src\core\surface\completion_queue.h" /> <ClInclude Include="..\..\src\core\surface\event_string.h" /> <ClInclude Include="..\..\src\core\surface\init.h" /> - <ClInclude Include="..\..\src\core\surface\lame_client.h" /> <ClInclude Include="..\..\src\core\surface\server.h" /> <ClInclude Include="..\..\src\core\surface\surface_trace.h" /> <ClInclude Include="..\..\src\core\transport\chttp2\bin_encoder.h" /> diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj.filters b/vsprojects/vs2013/grpc_unsecure.vcxproj.filters index 4583fa41eab8a2baeb584cde59c31e8162bfed42..205942a45099d7d05ab7db874c5f6ef7edf102f4 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj.filters @@ -491,9 +491,6 @@ <ClInclude Include="..\..\src\core\surface\init.h"> <Filter>src\core\surface</Filter> </ClInclude> - <ClInclude Include="..\..\src\core\surface\lame_client.h"> - <Filter>src\core\surface</Filter> - </ClInclude> <ClInclude Include="..\..\src\core\surface\server.h"> <Filter>src\core\surface</Filter> </ClInclude>