Merge branch 'master' of github.com:grpc/grpc into sanity
Conflicts: tools/run_tests/run_tests.py
This commit is contained in:
commit
a9ef765bfc
|
|
@ -11,4 +11,4 @@
|
|||
branch = v3.0.0-alpha-1
|
||||
[submodule "third_party/gflags"]
|
||||
path = third_party/gflags
|
||||
url = https://code.google.com/p/gflags
|
||||
url = https://github.com/gflags/gflags.git
|
||||
|
|
|
|||
|
|
@ -20,9 +20,12 @@ env:
|
|||
- CONFIG=opt TEST=python
|
||||
- CONFIG=gcov TEST=c
|
||||
- CONFIG=gcov TEST=c++
|
||||
- USE_GCC=4.4 CONFIG=opt TEST=build
|
||||
- USE_GCC=4.5 CONFIG=opt TEST=build
|
||||
script:
|
||||
- rvm use $RUBY_VERSION
|
||||
- gem install bundler
|
||||
- if [ ! -z "$USE_GCC" ] ; then export CC=gcc-$USE_GCC ; export CXX=g++-$USE_GCC ; fi
|
||||
- ./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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,566 @@
|
|||
# GRPC Bazel BUILD file.
|
||||
# This currently builds C and C++ code.
|
||||
|
||||
# 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.
|
||||
|
||||
licenses(["notice"]) # 3-clause BSD
|
||||
|
||||
|
||||
|
||||
cc_library(
|
||||
name = "gpr",
|
||||
srcs = [
|
||||
"src/core/support/env.h",
|
||||
"src/core/support/file.h",
|
||||
"src/core/support/murmur_hash.h",
|
||||
"src/core/support/string.h",
|
||||
"src/core/support/string_win32.h",
|
||||
"src/core/support/thd_internal.h",
|
||||
"src/core/support/alloc.c",
|
||||
"src/core/support/cancellable.c",
|
||||
"src/core/support/cmdline.c",
|
||||
"src/core/support/cpu_iphone.c",
|
||||
"src/core/support/cpu_linux.c",
|
||||
"src/core/support/cpu_posix.c",
|
||||
"src/core/support/cpu_windows.c",
|
||||
"src/core/support/env_linux.c",
|
||||
"src/core/support/env_posix.c",
|
||||
"src/core/support/env_win32.c",
|
||||
"src/core/support/file.c",
|
||||
"src/core/support/file_posix.c",
|
||||
"src/core/support/file_win32.c",
|
||||
"src/core/support/histogram.c",
|
||||
"src/core/support/host_port.c",
|
||||
"src/core/support/log.c",
|
||||
"src/core/support/log_android.c",
|
||||
"src/core/support/log_linux.c",
|
||||
"src/core/support/log_posix.c",
|
||||
"src/core/support/log_win32.c",
|
||||
"src/core/support/murmur_hash.c",
|
||||
"src/core/support/slice.c",
|
||||
"src/core/support/slice_buffer.c",
|
||||
"src/core/support/string.c",
|
||||
"src/core/support/string_posix.c",
|
||||
"src/core/support/string_win32.c",
|
||||
"src/core/support/sync.c",
|
||||
"src/core/support/sync_posix.c",
|
||||
"src/core/support/sync_win32.c",
|
||||
"src/core/support/thd.c",
|
||||
"src/core/support/thd_posix.c",
|
||||
"src/core/support/thd_win32.c",
|
||||
"src/core/support/time.c",
|
||||
"src/core/support/time_posix.c",
|
||||
"src/core/support/time_win32.c",
|
||||
],
|
||||
hdrs = [
|
||||
"include/grpc/support/alloc.h",
|
||||
"include/grpc/support/atm.h",
|
||||
"include/grpc/support/atm_gcc_atomic.h",
|
||||
"include/grpc/support/atm_gcc_sync.h",
|
||||
"include/grpc/support/atm_win32.h",
|
||||
"include/grpc/support/cancellable_platform.h",
|
||||
"include/grpc/support/cmdline.h",
|
||||
"include/grpc/support/cpu.h",
|
||||
"include/grpc/support/histogram.h",
|
||||
"include/grpc/support/host_port.h",
|
||||
"include/grpc/support/log.h",
|
||||
"include/grpc/support/log_win32.h",
|
||||
"include/grpc/support/port_platform.h",
|
||||
"include/grpc/support/slice.h",
|
||||
"include/grpc/support/slice_buffer.h",
|
||||
"include/grpc/support/sync.h",
|
||||
"include/grpc/support/sync_generic.h",
|
||||
"include/grpc/support/sync_posix.h",
|
||||
"include/grpc/support/sync_win32.h",
|
||||
"include/grpc/support/thd.h",
|
||||
"include/grpc/support/time.h",
|
||||
"include/grpc/support/useful.h",
|
||||
],
|
||||
includes = [
|
||||
"include",
|
||||
".",
|
||||
],
|
||||
deps = [
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
cc_library(
|
||||
name = "grpc",
|
||||
srcs = [
|
||||
"src/core/httpcli/format_request.h",
|
||||
"src/core/httpcli/httpcli.h",
|
||||
"src/core/httpcli/httpcli_security_context.h",
|
||||
"src/core/httpcli/parser.h",
|
||||
"src/core/security/auth.h",
|
||||
"src/core/security/base64.h",
|
||||
"src/core/security/credentials.h",
|
||||
"src/core/security/json_token.h",
|
||||
"src/core/security/secure_endpoint.h",
|
||||
"src/core/security/secure_transport_setup.h",
|
||||
"src/core/security/security_context.h",
|
||||
"src/core/tsi/fake_transport_security.h",
|
||||
"src/core/tsi/ssl_transport_security.h",
|
||||
"src/core/tsi/transport_security.h",
|
||||
"src/core/tsi/transport_security_interface.h",
|
||||
"src/core/channel/census_filter.h",
|
||||
"src/core/channel/channel_args.h",
|
||||
"src/core/channel/channel_stack.h",
|
||||
"src/core/channel/child_channel.h",
|
||||
"src/core/channel/client_channel.h",
|
||||
"src/core/channel/client_setup.h",
|
||||
"src/core/channel/connected_channel.h",
|
||||
"src/core/channel/http_client_filter.h",
|
||||
"src/core/channel/http_filter.h",
|
||||
"src/core/channel/http_server_filter.h",
|
||||
"src/core/channel/metadata_buffer.h",
|
||||
"src/core/channel/noop_filter.h",
|
||||
"src/core/compression/algorithm.h",
|
||||
"src/core/compression/message_compress.h",
|
||||
"src/core/debug/trace.h",
|
||||
"src/core/iomgr/alarm.h",
|
||||
"src/core/iomgr/alarm_heap.h",
|
||||
"src/core/iomgr/alarm_internal.h",
|
||||
"src/core/iomgr/endpoint.h",
|
||||
"src/core/iomgr/endpoint_pair.h",
|
||||
"src/core/iomgr/fd_posix.h",
|
||||
"src/core/iomgr/iocp_windows.h",
|
||||
"src/core/iomgr/iomgr.h",
|
||||
"src/core/iomgr/iomgr_internal.h",
|
||||
"src/core/iomgr/iomgr_posix.h",
|
||||
"src/core/iomgr/pollset.h",
|
||||
"src/core/iomgr/pollset_kick.h",
|
||||
"src/core/iomgr/pollset_kick_posix.h",
|
||||
"src/core/iomgr/pollset_kick_windows.h",
|
||||
"src/core/iomgr/pollset_posix.h",
|
||||
"src/core/iomgr/pollset_windows.h",
|
||||
"src/core/iomgr/resolve_address.h",
|
||||
"src/core/iomgr/sockaddr.h",
|
||||
"src/core/iomgr/sockaddr_posix.h",
|
||||
"src/core/iomgr/sockaddr_utils.h",
|
||||
"src/core/iomgr/sockaddr_win32.h",
|
||||
"src/core/iomgr/socket_utils_posix.h",
|
||||
"src/core/iomgr/socket_windows.h",
|
||||
"src/core/iomgr/tcp_client.h",
|
||||
"src/core/iomgr/tcp_posix.h",
|
||||
"src/core/iomgr/tcp_server.h",
|
||||
"src/core/iomgr/tcp_windows.h",
|
||||
"src/core/iomgr/time_averaged_stats.h",
|
||||
"src/core/iomgr/wakeup_fd_pipe.h",
|
||||
"src/core/iomgr/wakeup_fd_posix.h",
|
||||
"src/core/json/json.h",
|
||||
"src/core/json/json_common.h",
|
||||
"src/core/json/json_reader.h",
|
||||
"src/core/json/json_writer.h",
|
||||
"src/core/statistics/census_interface.h",
|
||||
"src/core/statistics/census_log.h",
|
||||
"src/core/statistics/census_rpc_stats.h",
|
||||
"src/core/statistics/census_tracing.h",
|
||||
"src/core/statistics/hash_table.h",
|
||||
"src/core/statistics/window_stats.h",
|
||||
"src/core/surface/byte_buffer_queue.h",
|
||||
"src/core/surface/call.h",
|
||||
"src/core/surface/channel.h",
|
||||
"src/core/surface/client.h",
|
||||
"src/core/surface/completion_queue.h",
|
||||
"src/core/surface/event_string.h",
|
||||
"src/core/surface/init.h",
|
||||
"src/core/surface/server.h",
|
||||
"src/core/surface/surface_trace.h",
|
||||
"src/core/transport/chttp2/alpn.h",
|
||||
"src/core/transport/chttp2/bin_encoder.h",
|
||||
"src/core/transport/chttp2/frame.h",
|
||||
"src/core/transport/chttp2/frame_data.h",
|
||||
"src/core/transport/chttp2/frame_goaway.h",
|
||||
"src/core/transport/chttp2/frame_ping.h",
|
||||
"src/core/transport/chttp2/frame_rst_stream.h",
|
||||
"src/core/transport/chttp2/frame_settings.h",
|
||||
"src/core/transport/chttp2/frame_window_update.h",
|
||||
"src/core/transport/chttp2/hpack_parser.h",
|
||||
"src/core/transport/chttp2/hpack_table.h",
|
||||
"src/core/transport/chttp2/http2_errors.h",
|
||||
"src/core/transport/chttp2/huffsyms.h",
|
||||
"src/core/transport/chttp2/status_conversion.h",
|
||||
"src/core/transport/chttp2/stream_encoder.h",
|
||||
"src/core/transport/chttp2/stream_map.h",
|
||||
"src/core/transport/chttp2/timeout_encoding.h",
|
||||
"src/core/transport/chttp2/varint.h",
|
||||
"src/core/transport/chttp2_transport.h",
|
||||
"src/core/transport/metadata.h",
|
||||
"src/core/transport/stream_op.h",
|
||||
"src/core/transport/transport.h",
|
||||
"src/core/transport/transport_impl.h",
|
||||
"src/core/httpcli/format_request.c",
|
||||
"src/core/httpcli/httpcli.c",
|
||||
"src/core/httpcli/httpcli_security_context.c",
|
||||
"src/core/httpcli/parser.c",
|
||||
"src/core/security/auth.c",
|
||||
"src/core/security/base64.c",
|
||||
"src/core/security/credentials.c",
|
||||
"src/core/security/credentials_posix.c",
|
||||
"src/core/security/credentials_win32.c",
|
||||
"src/core/security/factories.c",
|
||||
"src/core/security/google_default_credentials.c",
|
||||
"src/core/security/json_token.c",
|
||||
"src/core/security/secure_endpoint.c",
|
||||
"src/core/security/secure_transport_setup.c",
|
||||
"src/core/security/security_context.c",
|
||||
"src/core/security/server_secure_chttp2.c",
|
||||
"src/core/surface/init_secure.c",
|
||||
"src/core/surface/secure_channel_create.c",
|
||||
"src/core/tsi/fake_transport_security.c",
|
||||
"src/core/tsi/ssl_transport_security.c",
|
||||
"src/core/tsi/transport_security.c",
|
||||
"src/core/channel/call_op_string.c",
|
||||
"src/core/channel/census_filter.c",
|
||||
"src/core/channel/channel_args.c",
|
||||
"src/core/channel/channel_stack.c",
|
||||
"src/core/channel/child_channel.c",
|
||||
"src/core/channel/client_channel.c",
|
||||
"src/core/channel/client_setup.c",
|
||||
"src/core/channel/connected_channel.c",
|
||||
"src/core/channel/http_client_filter.c",
|
||||
"src/core/channel/http_filter.c",
|
||||
"src/core/channel/http_server_filter.c",
|
||||
"src/core/channel/metadata_buffer.c",
|
||||
"src/core/channel/noop_filter.c",
|
||||
"src/core/compression/algorithm.c",
|
||||
"src/core/compression/message_compress.c",
|
||||
"src/core/debug/trace.c",
|
||||
"src/core/iomgr/alarm.c",
|
||||
"src/core/iomgr/alarm_heap.c",
|
||||
"src/core/iomgr/endpoint.c",
|
||||
"src/core/iomgr/endpoint_pair_posix.c",
|
||||
"src/core/iomgr/fd_posix.c",
|
||||
"src/core/iomgr/iocp_windows.c",
|
||||
"src/core/iomgr/iomgr.c",
|
||||
"src/core/iomgr/iomgr_posix.c",
|
||||
"src/core/iomgr/iomgr_windows.c",
|
||||
"src/core/iomgr/pollset_kick.c",
|
||||
"src/core/iomgr/pollset_multipoller_with_epoll.c",
|
||||
"src/core/iomgr/pollset_multipoller_with_poll_posix.c",
|
||||
"src/core/iomgr/pollset_posix.c",
|
||||
"src/core/iomgr/pollset_windows.c",
|
||||
"src/core/iomgr/resolve_address_posix.c",
|
||||
"src/core/iomgr/resolve_address_windows.c",
|
||||
"src/core/iomgr/sockaddr_utils.c",
|
||||
"src/core/iomgr/socket_utils_common_posix.c",
|
||||
"src/core/iomgr/socket_utils_linux.c",
|
||||
"src/core/iomgr/socket_utils_posix.c",
|
||||
"src/core/iomgr/socket_windows.c",
|
||||
"src/core/iomgr/tcp_client_posix.c",
|
||||
"src/core/iomgr/tcp_client_windows.c",
|
||||
"src/core/iomgr/tcp_posix.c",
|
||||
"src/core/iomgr/tcp_server_posix.c",
|
||||
"src/core/iomgr/tcp_server_windows.c",
|
||||
"src/core/iomgr/tcp_windows.c",
|
||||
"src/core/iomgr/time_averaged_stats.c",
|
||||
"src/core/iomgr/wakeup_fd_eventfd.c",
|
||||
"src/core/iomgr/wakeup_fd_nospecial.c",
|
||||
"src/core/iomgr/wakeup_fd_pipe.c",
|
||||
"src/core/iomgr/wakeup_fd_posix.c",
|
||||
"src/core/json/json.c",
|
||||
"src/core/json/json_reader.c",
|
||||
"src/core/json/json_string.c",
|
||||
"src/core/json/json_writer.c",
|
||||
"src/core/statistics/census_init.c",
|
||||
"src/core/statistics/census_log.c",
|
||||
"src/core/statistics/census_rpc_stats.c",
|
||||
"src/core/statistics/census_tracing.c",
|
||||
"src/core/statistics/hash_table.c",
|
||||
"src/core/statistics/window_stats.c",
|
||||
"src/core/surface/byte_buffer.c",
|
||||
"src/core/surface/byte_buffer_queue.c",
|
||||
"src/core/surface/byte_buffer_reader.c",
|
||||
"src/core/surface/call.c",
|
||||
"src/core/surface/call_details.c",
|
||||
"src/core/surface/call_log_batch.c",
|
||||
"src/core/surface/channel.c",
|
||||
"src/core/surface/channel_create.c",
|
||||
"src/core/surface/client.c",
|
||||
"src/core/surface/completion_queue.c",
|
||||
"src/core/surface/event_string.c",
|
||||
"src/core/surface/init.c",
|
||||
"src/core/surface/lame_client.c",
|
||||
"src/core/surface/metadata_array.c",
|
||||
"src/core/surface/server.c",
|
||||
"src/core/surface/server_chttp2.c",
|
||||
"src/core/surface/server_create.c",
|
||||
"src/core/surface/surface_trace.c",
|
||||
"src/core/transport/chttp2/alpn.c",
|
||||
"src/core/transport/chttp2/bin_encoder.c",
|
||||
"src/core/transport/chttp2/frame_data.c",
|
||||
"src/core/transport/chttp2/frame_goaway.c",
|
||||
"src/core/transport/chttp2/frame_ping.c",
|
||||
"src/core/transport/chttp2/frame_rst_stream.c",
|
||||
"src/core/transport/chttp2/frame_settings.c",
|
||||
"src/core/transport/chttp2/frame_window_update.c",
|
||||
"src/core/transport/chttp2/hpack_parser.c",
|
||||
"src/core/transport/chttp2/hpack_table.c",
|
||||
"src/core/transport/chttp2/huffsyms.c",
|
||||
"src/core/transport/chttp2/status_conversion.c",
|
||||
"src/core/transport/chttp2/stream_encoder.c",
|
||||
"src/core/transport/chttp2/stream_map.c",
|
||||
"src/core/transport/chttp2/timeout_encoding.c",
|
||||
"src/core/transport/chttp2/varint.c",
|
||||
"src/core/transport/chttp2_transport.c",
|
||||
"src/core/transport/metadata.c",
|
||||
"src/core/transport/stream_op.c",
|
||||
"src/core/transport/transport.c",
|
||||
],
|
||||
hdrs = [
|
||||
"include/grpc/grpc_security.h",
|
||||
"include/grpc/byte_buffer.h",
|
||||
"include/grpc/byte_buffer_reader.h",
|
||||
"include/grpc/grpc.h",
|
||||
"include/grpc/grpc_http.h",
|
||||
"include/grpc/status.h",
|
||||
],
|
||||
includes = [
|
||||
"include",
|
||||
".",
|
||||
],
|
||||
deps = [
|
||||
":gpr",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
cc_library(
|
||||
name = "grpc_unsecure",
|
||||
srcs = [
|
||||
"src/core/channel/census_filter.h",
|
||||
"src/core/channel/channel_args.h",
|
||||
"src/core/channel/channel_stack.h",
|
||||
"src/core/channel/child_channel.h",
|
||||
"src/core/channel/client_channel.h",
|
||||
"src/core/channel/client_setup.h",
|
||||
"src/core/channel/connected_channel.h",
|
||||
"src/core/channel/http_client_filter.h",
|
||||
"src/core/channel/http_filter.h",
|
||||
"src/core/channel/http_server_filter.h",
|
||||
"src/core/channel/metadata_buffer.h",
|
||||
"src/core/channel/noop_filter.h",
|
||||
"src/core/compression/algorithm.h",
|
||||
"src/core/compression/message_compress.h",
|
||||
"src/core/debug/trace.h",
|
||||
"src/core/iomgr/alarm.h",
|
||||
"src/core/iomgr/alarm_heap.h",
|
||||
"src/core/iomgr/alarm_internal.h",
|
||||
"src/core/iomgr/endpoint.h",
|
||||
"src/core/iomgr/endpoint_pair.h",
|
||||
"src/core/iomgr/fd_posix.h",
|
||||
"src/core/iomgr/iocp_windows.h",
|
||||
"src/core/iomgr/iomgr.h",
|
||||
"src/core/iomgr/iomgr_internal.h",
|
||||
"src/core/iomgr/iomgr_posix.h",
|
||||
"src/core/iomgr/pollset.h",
|
||||
"src/core/iomgr/pollset_kick.h",
|
||||
"src/core/iomgr/pollset_kick_posix.h",
|
||||
"src/core/iomgr/pollset_kick_windows.h",
|
||||
"src/core/iomgr/pollset_posix.h",
|
||||
"src/core/iomgr/pollset_windows.h",
|
||||
"src/core/iomgr/resolve_address.h",
|
||||
"src/core/iomgr/sockaddr.h",
|
||||
"src/core/iomgr/sockaddr_posix.h",
|
||||
"src/core/iomgr/sockaddr_utils.h",
|
||||
"src/core/iomgr/sockaddr_win32.h",
|
||||
"src/core/iomgr/socket_utils_posix.h",
|
||||
"src/core/iomgr/socket_windows.h",
|
||||
"src/core/iomgr/tcp_client.h",
|
||||
"src/core/iomgr/tcp_posix.h",
|
||||
"src/core/iomgr/tcp_server.h",
|
||||
"src/core/iomgr/tcp_windows.h",
|
||||
"src/core/iomgr/time_averaged_stats.h",
|
||||
"src/core/iomgr/wakeup_fd_pipe.h",
|
||||
"src/core/iomgr/wakeup_fd_posix.h",
|
||||
"src/core/json/json.h",
|
||||
"src/core/json/json_common.h",
|
||||
"src/core/json/json_reader.h",
|
||||
"src/core/json/json_writer.h",
|
||||
"src/core/statistics/census_interface.h",
|
||||
"src/core/statistics/census_log.h",
|
||||
"src/core/statistics/census_rpc_stats.h",
|
||||
"src/core/statistics/census_tracing.h",
|
||||
"src/core/statistics/hash_table.h",
|
||||
"src/core/statistics/window_stats.h",
|
||||
"src/core/surface/byte_buffer_queue.h",
|
||||
"src/core/surface/call.h",
|
||||
"src/core/surface/channel.h",
|
||||
"src/core/surface/client.h",
|
||||
"src/core/surface/completion_queue.h",
|
||||
"src/core/surface/event_string.h",
|
||||
"src/core/surface/init.h",
|
||||
"src/core/surface/server.h",
|
||||
"src/core/surface/surface_trace.h",
|
||||
"src/core/transport/chttp2/alpn.h",
|
||||
"src/core/transport/chttp2/bin_encoder.h",
|
||||
"src/core/transport/chttp2/frame.h",
|
||||
"src/core/transport/chttp2/frame_data.h",
|
||||
"src/core/transport/chttp2/frame_goaway.h",
|
||||
"src/core/transport/chttp2/frame_ping.h",
|
||||
"src/core/transport/chttp2/frame_rst_stream.h",
|
||||
"src/core/transport/chttp2/frame_settings.h",
|
||||
"src/core/transport/chttp2/frame_window_update.h",
|
||||
"src/core/transport/chttp2/hpack_parser.h",
|
||||
"src/core/transport/chttp2/hpack_table.h",
|
||||
"src/core/transport/chttp2/http2_errors.h",
|
||||
"src/core/transport/chttp2/huffsyms.h",
|
||||
"src/core/transport/chttp2/status_conversion.h",
|
||||
"src/core/transport/chttp2/stream_encoder.h",
|
||||
"src/core/transport/chttp2/stream_map.h",
|
||||
"src/core/transport/chttp2/timeout_encoding.h",
|
||||
"src/core/transport/chttp2/varint.h",
|
||||
"src/core/transport/chttp2_transport.h",
|
||||
"src/core/transport/metadata.h",
|
||||
"src/core/transport/stream_op.h",
|
||||
"src/core/transport/transport.h",
|
||||
"src/core/transport/transport_impl.h",
|
||||
"src/core/surface/init_unsecure.c",
|
||||
"src/core/channel/call_op_string.c",
|
||||
"src/core/channel/census_filter.c",
|
||||
"src/core/channel/channel_args.c",
|
||||
"src/core/channel/channel_stack.c",
|
||||
"src/core/channel/child_channel.c",
|
||||
"src/core/channel/client_channel.c",
|
||||
"src/core/channel/client_setup.c",
|
||||
"src/core/channel/connected_channel.c",
|
||||
"src/core/channel/http_client_filter.c",
|
||||
"src/core/channel/http_filter.c",
|
||||
"src/core/channel/http_server_filter.c",
|
||||
"src/core/channel/metadata_buffer.c",
|
||||
"src/core/channel/noop_filter.c",
|
||||
"src/core/compression/algorithm.c",
|
||||
"src/core/compression/message_compress.c",
|
||||
"src/core/debug/trace.c",
|
||||
"src/core/iomgr/alarm.c",
|
||||
"src/core/iomgr/alarm_heap.c",
|
||||
"src/core/iomgr/endpoint.c",
|
||||
"src/core/iomgr/endpoint_pair_posix.c",
|
||||
"src/core/iomgr/fd_posix.c",
|
||||
"src/core/iomgr/iocp_windows.c",
|
||||
"src/core/iomgr/iomgr.c",
|
||||
"src/core/iomgr/iomgr_posix.c",
|
||||
"src/core/iomgr/iomgr_windows.c",
|
||||
"src/core/iomgr/pollset_kick.c",
|
||||
"src/core/iomgr/pollset_multipoller_with_epoll.c",
|
||||
"src/core/iomgr/pollset_multipoller_with_poll_posix.c",
|
||||
"src/core/iomgr/pollset_posix.c",
|
||||
"src/core/iomgr/pollset_windows.c",
|
||||
"src/core/iomgr/resolve_address_posix.c",
|
||||
"src/core/iomgr/resolve_address_windows.c",
|
||||
"src/core/iomgr/sockaddr_utils.c",
|
||||
"src/core/iomgr/socket_utils_common_posix.c",
|
||||
"src/core/iomgr/socket_utils_linux.c",
|
||||
"src/core/iomgr/socket_utils_posix.c",
|
||||
"src/core/iomgr/socket_windows.c",
|
||||
"src/core/iomgr/tcp_client_posix.c",
|
||||
"src/core/iomgr/tcp_client_windows.c",
|
||||
"src/core/iomgr/tcp_posix.c",
|
||||
"src/core/iomgr/tcp_server_posix.c",
|
||||
"src/core/iomgr/tcp_server_windows.c",
|
||||
"src/core/iomgr/tcp_windows.c",
|
||||
"src/core/iomgr/time_averaged_stats.c",
|
||||
"src/core/iomgr/wakeup_fd_eventfd.c",
|
||||
"src/core/iomgr/wakeup_fd_nospecial.c",
|
||||
"src/core/iomgr/wakeup_fd_pipe.c",
|
||||
"src/core/iomgr/wakeup_fd_posix.c",
|
||||
"src/core/json/json.c",
|
||||
"src/core/json/json_reader.c",
|
||||
"src/core/json/json_string.c",
|
||||
"src/core/json/json_writer.c",
|
||||
"src/core/statistics/census_init.c",
|
||||
"src/core/statistics/census_log.c",
|
||||
"src/core/statistics/census_rpc_stats.c",
|
||||
"src/core/statistics/census_tracing.c",
|
||||
"src/core/statistics/hash_table.c",
|
||||
"src/core/statistics/window_stats.c",
|
||||
"src/core/surface/byte_buffer.c",
|
||||
"src/core/surface/byte_buffer_queue.c",
|
||||
"src/core/surface/byte_buffer_reader.c",
|
||||
"src/core/surface/call.c",
|
||||
"src/core/surface/call_details.c",
|
||||
"src/core/surface/call_log_batch.c",
|
||||
"src/core/surface/channel.c",
|
||||
"src/core/surface/channel_create.c",
|
||||
"src/core/surface/client.c",
|
||||
"src/core/surface/completion_queue.c",
|
||||
"src/core/surface/event_string.c",
|
||||
"src/core/surface/init.c",
|
||||
"src/core/surface/lame_client.c",
|
||||
"src/core/surface/metadata_array.c",
|
||||
"src/core/surface/server.c",
|
||||
"src/core/surface/server_chttp2.c",
|
||||
"src/core/surface/server_create.c",
|
||||
"src/core/surface/surface_trace.c",
|
||||
"src/core/transport/chttp2/alpn.c",
|
||||
"src/core/transport/chttp2/bin_encoder.c",
|
||||
"src/core/transport/chttp2/frame_data.c",
|
||||
"src/core/transport/chttp2/frame_goaway.c",
|
||||
"src/core/transport/chttp2/frame_ping.c",
|
||||
"src/core/transport/chttp2/frame_rst_stream.c",
|
||||
"src/core/transport/chttp2/frame_settings.c",
|
||||
"src/core/transport/chttp2/frame_window_update.c",
|
||||
"src/core/transport/chttp2/hpack_parser.c",
|
||||
"src/core/transport/chttp2/hpack_table.c",
|
||||
"src/core/transport/chttp2/huffsyms.c",
|
||||
"src/core/transport/chttp2/status_conversion.c",
|
||||
"src/core/transport/chttp2/stream_encoder.c",
|
||||
"src/core/transport/chttp2/stream_map.c",
|
||||
"src/core/transport/chttp2/timeout_encoding.c",
|
||||
"src/core/transport/chttp2/varint.c",
|
||||
"src/core/transport/chttp2_transport.c",
|
||||
"src/core/transport/metadata.c",
|
||||
"src/core/transport/stream_op.c",
|
||||
"src/core/transport/transport.c",
|
||||
],
|
||||
hdrs = [
|
||||
"include/grpc/byte_buffer.h",
|
||||
"include/grpc/byte_buffer_reader.h",
|
||||
"include/grpc/grpc.h",
|
||||
"include/grpc/grpc_http.h",
|
||||
"include/grpc/status.h",
|
||||
],
|
||||
includes = [
|
||||
"include",
|
||||
".",
|
||||
],
|
||||
deps = [
|
||||
":gpr",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -5,6 +5,10 @@
|
|||
|
||||
Copyright 2015 Google Inc.
|
||||
|
||||
#Documentation
|
||||
|
||||
You can find more detailed documentation and examples in the [grpc-common repository](http://github.com/grpc/grpc-common).
|
||||
|
||||
#Installation
|
||||
|
||||
See grpc/INSTALL for installation instructions for various platforms.
|
||||
|
|
@ -25,10 +29,6 @@ of shared C core library [src/core] (src/core).
|
|||
Java source code is in [grpc-java] (http://github.com/grpc/grpc-java) repository.
|
||||
Go source code is in [grpc-go] (http://github.com/grpc/grpc-go) repository.
|
||||
|
||||
#Documentation
|
||||
|
||||
You can find more detailed documentation and examples in the [grpc-common repository](http://github.com/grpc/grpc-common).
|
||||
|
||||
#Current Status of libraries
|
||||
|
||||
Libraries in different languages are in different state of development. We are seeking contributions for all of these libraries.
|
||||
|
|
|
|||
92
build.json
92
build.json
|
|
@ -3,7 +3,7 @@
|
|||
"#": "The public version number of the library.",
|
||||
"version": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"minor": 6,
|
||||
"micro": 0,
|
||||
"build": 0
|
||||
}
|
||||
|
|
@ -52,6 +52,7 @@
|
|||
"src/cpp/client/client_unary_call.cc",
|
||||
"src/cpp/client/create_channel.cc",
|
||||
"src/cpp/client/credentials.cc",
|
||||
"src/cpp/client/generic_stub.cc",
|
||||
"src/cpp/client/insecure_credentials.cc",
|
||||
"src/cpp/client/internal_stub.cc",
|
||||
"src/cpp/common/call.cc",
|
||||
|
|
@ -233,6 +234,7 @@
|
|||
"src/core/surface/byte_buffer_reader.c",
|
||||
"src/core/surface/call.c",
|
||||
"src/core/surface/call_details.c",
|
||||
"src/core/surface/call_log_batch.c",
|
||||
"src/core/surface/channel.c",
|
||||
"src/core/surface/channel_create.c",
|
||||
"src/core/surface/client.c",
|
||||
|
|
@ -335,6 +337,7 @@
|
|||
"src/core/support/sync.c",
|
||||
"src/core/support/sync_posix.c",
|
||||
"src/core/support/sync_win32.c",
|
||||
"src/core/support/thd.c",
|
||||
"src/core/support/thd_posix.c",
|
||||
"src/core/support/thd_win32.c",
|
||||
"src/core/support/time.c",
|
||||
|
|
@ -348,6 +351,9 @@
|
|||
"name": "gpr_test_util",
|
||||
"build": "private",
|
||||
"language": "c",
|
||||
"headers": [
|
||||
"test/core/util/test_config.h"
|
||||
],
|
||||
"src": [
|
||||
"test/core/util/test_config.c"
|
||||
],
|
||||
|
|
@ -432,6 +438,7 @@
|
|||
],
|
||||
"deps": [
|
||||
"gpr",
|
||||
"gpr_test_util",
|
||||
"grpc"
|
||||
],
|
||||
"vs_project_guid": "{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}"
|
||||
|
|
@ -480,6 +487,7 @@
|
|||
"test/cpp/util/messages.proto",
|
||||
"test/cpp/util/echo.proto",
|
||||
"test/cpp/util/echo_duplicate.proto",
|
||||
"test/cpp/util/cli_call.cc",
|
||||
"test/cpp/util/create_test_channel.cc"
|
||||
]
|
||||
},
|
||||
|
|
@ -498,14 +506,27 @@
|
|||
"secure": "no"
|
||||
},
|
||||
{
|
||||
"name": "grpc_python_plugin_support",
|
||||
"name": "grpc_plugin_support",
|
||||
"build": "protoc",
|
||||
"language": "c++",
|
||||
"public_headers": [
|
||||
"src/compiler/python_generator.h"
|
||||
"headers": [
|
||||
"src/compiler/config.h",
|
||||
"src/compiler/cpp_generator.h",
|
||||
"src/compiler/cpp_generator_helpers.h",
|
||||
"src/compiler/generator_helpers.h",
|
||||
"src/compiler/objective_c_generator.h",
|
||||
"src/compiler/objective_c_generator_helpers.h",
|
||||
"src/compiler/python_generator.h",
|
||||
"src/compiler/ruby_generator.h",
|
||||
"src/compiler/ruby_generator_helpers-inl.h",
|
||||
"src/compiler/ruby_generator_map-inl.h",
|
||||
"src/compiler/ruby_generator_string-inl.h"
|
||||
],
|
||||
"src": [
|
||||
"src/compiler/python_generator.cc"
|
||||
"src/compiler/cpp_generator.cc",
|
||||
"src/compiler/objective_c_generator.cc",
|
||||
"src/compiler/python_generator.cc",
|
||||
"src/compiler/ruby_generator.cc"
|
||||
],
|
||||
"deps": [],
|
||||
"secure": "no"
|
||||
|
|
@ -1694,6 +1715,22 @@
|
|||
"gpr"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "cli_call_test",
|
||||
"build": "test",
|
||||
"language": "c++",
|
||||
"src": [
|
||||
"test/cpp/util/cli_call_test.cc"
|
||||
],
|
||||
"deps": [
|
||||
"grpc++_test_util",
|
||||
"grpc_test_util",
|
||||
"grpc++",
|
||||
"grpc",
|
||||
"gpr_test_util",
|
||||
"gpr"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "credentials_test",
|
||||
"build": "test",
|
||||
|
|
@ -1754,19 +1791,45 @@
|
|||
"gpr"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "grpc_cli",
|
||||
"build": "test",
|
||||
"run": false,
|
||||
"language": "c++",
|
||||
"src": [
|
||||
"test/cpp/util/grpc_cli.cc"
|
||||
],
|
||||
"deps": [
|
||||
"grpc++_test_util",
|
||||
"grpc_test_util",
|
||||
"grpc++",
|
||||
"grpc",
|
||||
"gpr_test_util",
|
||||
"gpr"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "grpc_cpp_plugin",
|
||||
"build": "protoc",
|
||||
"language": "c++",
|
||||
"headers": [
|
||||
"src/compiler/cpp_generator.h",
|
||||
"src/compiler/cpp_generator_helpers.h"
|
||||
],
|
||||
"src": [
|
||||
"src/compiler/cpp_generator.cc",
|
||||
"src/compiler/cpp_plugin.cc"
|
||||
],
|
||||
"deps": [],
|
||||
"deps": [
|
||||
"grpc_plugin_support"
|
||||
],
|
||||
"secure": "no"
|
||||
},
|
||||
{
|
||||
"name": "grpc_objective_c_plugin",
|
||||
"build": "protoc",
|
||||
"language": "c++",
|
||||
"src": [
|
||||
"src/compiler/objective_c_plugin.cc"
|
||||
],
|
||||
"deps": [
|
||||
"grpc_plugin_support"
|
||||
],
|
||||
"secure": "no"
|
||||
},
|
||||
{
|
||||
|
|
@ -1777,7 +1840,7 @@
|
|||
"src/compiler/python_plugin.cc"
|
||||
],
|
||||
"deps": [
|
||||
"grpc_python_plugin_support"
|
||||
"grpc_plugin_support"
|
||||
],
|
||||
"secure": "no"
|
||||
},
|
||||
|
|
@ -1786,10 +1849,11 @@
|
|||
"build": "protoc",
|
||||
"language": "c++",
|
||||
"src": [
|
||||
"src/compiler/ruby_generator.cc",
|
||||
"src/compiler/ruby_plugin.cc"
|
||||
],
|
||||
"deps": [],
|
||||
"deps": [
|
||||
"grpc_plugin_support"
|
||||
],
|
||||
"secure": "no"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,685 @@
|
|||
Interoperability Test Case Descriptions
|
||||
=======================================
|
||||
|
||||
Client and server use
|
||||
[test.proto](https://github.com/grpc/grpc/blob/master/test/cpp/interop/test.proto)
|
||||
and the [gRPC over HTTP/2 v2
|
||||
protocol](https://github.com/grpc/grpc-common/blob/master/PROTOCOL-HTTP2.md).
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
Clients implement test cases that test certain functionally. Each client is
|
||||
provided the test case it is expected to run as a command-line parameter. Names
|
||||
should be lowercase and without spaces.
|
||||
|
||||
Clients should accept these arguments:
|
||||
* --server_host=HOSTNAME
|
||||
* The server host to connect to. For example, "localhost" or "127.0.0.1"
|
||||
* --server_host_override=HOSTNAME
|
||||
* The server host to claim to be connecting to, for use in TLS and HTTP/2
|
||||
:authority header. If unspecified, the value of --server_host will be
|
||||
used
|
||||
* --server_port=PORT
|
||||
* The server port to connect to. For example, "8080"
|
||||
* --test_case=TESTCASE
|
||||
* The name of the test case to execute. For example, "empty_unary"
|
||||
* --use_tls=BOOLEAN
|
||||
* Whether to use a plaintext or encrypted connection
|
||||
* --use_test_ca=BOOLEAN
|
||||
* Whether to replace platform root CAs with
|
||||
[ca.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/ca.pem)
|
||||
as the CA root
|
||||
|
||||
Clients must support TLS with ALPN. Clients must not disable certificate
|
||||
checking.
|
||||
|
||||
### empty_unary
|
||||
|
||||
This test verifies that implementations support zero-size messages. Ideally,
|
||||
client implementations would verify that the request and response were zero
|
||||
bytes serialized, but this is generally prohibitive to perform, so is not
|
||||
required.
|
||||
|
||||
Server features:
|
||||
* [EmptyCall][]
|
||||
|
||||
Procedure:
|
||||
1. Client calls EmptyCall with the default Empty message
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* response is non-null
|
||||
|
||||
*It may be possible to use UnaryCall instead of EmptyCall, but it is harder to
|
||||
ensure that the proto serialized to zero bytes.*
|
||||
|
||||
### large_unary
|
||||
|
||||
This test verifies unary calls succeed in sending messages, and touches on flow
|
||||
control (even if compression is enabled on the channel).
|
||||
|
||||
Server features:
|
||||
* [UnaryCall][]
|
||||
* [Compressable Payload][]
|
||||
|
||||
Procedure:
|
||||
1. Client calls UnaryCall with:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_size: 314159
|
||||
payload:{
|
||||
body: 271828 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* response payload type is COMPRESSABLE
|
||||
* response payload body is 314159 bytes in size
|
||||
* clients are free to assert that the response payload body contents are zero
|
||||
and comparing the entire response message against a golden response
|
||||
|
||||
### client_streaming
|
||||
|
||||
This test verifies that client-only streaming succeeds.
|
||||
|
||||
Server features:
|
||||
* [StreamingInputCall][]
|
||||
* [Compressable Payload][]
|
||||
|
||||
Procedure:
|
||||
1. Client calls StreamingInputCall
|
||||
2. Client sends:
|
||||
|
||||
```
|
||||
{
|
||||
payload:{
|
||||
body: 27182 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
3. Client then sends:
|
||||
|
||||
```
|
||||
{
|
||||
payload:{
|
||||
body: 8 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
4. Client then sends:
|
||||
|
||||
```
|
||||
{
|
||||
payload:{
|
||||
body: 1828 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
5. Client then sends:
|
||||
|
||||
```
|
||||
{
|
||||
payload:{
|
||||
body: 45904 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
6. Client halfCloses
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* response aggregated_payload_size is 74922
|
||||
|
||||
### server_streaming
|
||||
|
||||
This test verifies that server-only streaming succeeds.
|
||||
|
||||
Server features:
|
||||
* [StreamingOutputCall][]
|
||||
* [Compressable Payload][]
|
||||
|
||||
Procedure:
|
||||
1. Client calls StreamingOutputCall with:
|
||||
|
||||
```
|
||||
{
|
||||
response_type:COMPRESSABLE
|
||||
response_parameters:{
|
||||
size: 31415
|
||||
}
|
||||
response_parameters:{
|
||||
size: 9
|
||||
}
|
||||
response_parameters:{
|
||||
size: 2653
|
||||
}
|
||||
response_parameters:{
|
||||
size: 58979
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* exactly four responses
|
||||
* response payloads are COMPRESSABLE
|
||||
* response payload bodies are sized (in order): 31415, 9, 2653, 58979
|
||||
* clients are free to assert that the response payload body contents are zero
|
||||
and comparing the entire response messages against golden responses
|
||||
|
||||
### ping_pong
|
||||
|
||||
This test verifies that full duplex bidi is supported.
|
||||
|
||||
Server features:
|
||||
* [FullDuplexCall][]
|
||||
* [Compressable Payload][]
|
||||
|
||||
Procedure:
|
||||
1. Client calls FullDuplexCall with:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_parameters:{
|
||||
size: 31415
|
||||
}
|
||||
payload:{
|
||||
body: 27182 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
2. After getting a reply, it sends:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_parameters:{
|
||||
size: 9
|
||||
}
|
||||
payload:{
|
||||
body: 8 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
3. After getting a reply, it sends:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_parameters:{
|
||||
size: 2653
|
||||
}
|
||||
payload:{
|
||||
body: 1828 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
4. After getting a reply, it sends:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_parameters:{
|
||||
size: 58979
|
||||
}
|
||||
payload:{
|
||||
body: 45904 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* exactly four responses
|
||||
* response payloads are COMPRESSABLE
|
||||
* response payload bodies are sized (in order): 31415, 9, 2653, 58979
|
||||
* clients are free to assert that the response payload body contents are zero
|
||||
and comparing the entire response messages against golden responses
|
||||
|
||||
### empty_stream
|
||||
|
||||
This test verifies that streams support having zero-messages in both
|
||||
directions.
|
||||
|
||||
Server features:
|
||||
* [FullDuplexCall][]
|
||||
|
||||
Procedure:
|
||||
1. Client calls FullDuplexCall and then half-closes
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* exactly zero responses
|
||||
|
||||
### compute_engine_creds
|
||||
|
||||
Status: Not yet implementable
|
||||
|
||||
This test is only for cloud-to-prod path.
|
||||
|
||||
This test verifies unary calls succeed in sending messages while using Service
|
||||
Credentials from GCE metadata server. The client instance needs to be created
|
||||
with desired oauth scope.
|
||||
|
||||
Server features:
|
||||
* [UnaryCall][]
|
||||
* [Compressable Payload][]
|
||||
* SimpeResponse.username
|
||||
* SimpleResponse.oauth_scope
|
||||
|
||||
Procedure:
|
||||
1. Client sets flags default_service_account with GCE service account name and
|
||||
oauth_scope with the oauth scope to use.
|
||||
2. Client configures channel to use GCECredentials
|
||||
3. Client calls UnaryCall on the channel with:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_size: 314159
|
||||
payload:{
|
||||
body: 271828 bytes of zeros
|
||||
}
|
||||
fill_username: true
|
||||
fill_oauth_scope: true
|
||||
}
|
||||
```
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* received SimpleResponse.username equals FLAGS_default_service_account
|
||||
* received SimpleResponse.oauth_scope is in FLAGS_oauth_scope
|
||||
* response payload body is 314159 bytes in size
|
||||
* clients are free to assert that the response payload body contents are zero
|
||||
and comparing the entire response message against a golden response
|
||||
|
||||
### service_account_creds
|
||||
|
||||
Status: Not yet implementable
|
||||
|
||||
This test is only for cloud-to-prod path.
|
||||
|
||||
This test verifies unary calls succeed in sending messages while using JWT
|
||||
signing keys (redeemed for OAuth2 access tokens by the auth implementation)
|
||||
|
||||
Server features:
|
||||
* [UnaryCall][]
|
||||
* [Compressable Payload][]
|
||||
* SimpleResponse.username
|
||||
* SimpleResponse.oauth_scope
|
||||
|
||||
Procedure:
|
||||
1. Client sets flags service_account_key_file with the path to json key file,
|
||||
oauth_scope to the oauth scope.
|
||||
2. Client configures the channel to use ServiceAccountCredentials.
|
||||
3. Client calls UnaryCall with:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_size: 314159
|
||||
payload:{
|
||||
body: 271828 bytes of zeros
|
||||
}
|
||||
fill_username: true
|
||||
fill_oauth_scope: true
|
||||
}
|
||||
```
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* received SimpleResponse.username is in the json key file read from
|
||||
FLAGS_service_account_key_file
|
||||
* received SimpleResponse.oauth_scope is in FLAGS_oauth_scope
|
||||
* response payload body is 314159 bytes in size
|
||||
* clients are free to assert that the response payload body contents are zero
|
||||
and comparing the entire response message against a golden response
|
||||
|
||||
### jwt_token_creds
|
||||
|
||||
Status: Not yet implementable
|
||||
|
||||
This test is only for cloud-to-prod path.
|
||||
|
||||
This test verifies unary calls succeed in sending messages while using JWT
|
||||
token (created by the project's key file)
|
||||
|
||||
Server features:
|
||||
* [UnaryCall][]
|
||||
* [Compressable Payload][]
|
||||
* SimpleResponse.username
|
||||
* SimpleResponse.oauth_scope
|
||||
|
||||
Procedure:
|
||||
1. Client sets flags service_account_key_file with the path to json key file
|
||||
2. Client configures the channel to use JWTTokenCredentials.
|
||||
3. Client calls UnaryCall with:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_size: 314159
|
||||
payload:{
|
||||
body: 271828 bytes of zeros
|
||||
}
|
||||
fill_username: true
|
||||
}
|
||||
```
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* received SimpleResponse.username is in the json key file read from
|
||||
FLAGS_service_account_key_file
|
||||
* response payload body is 314159 bytes in size
|
||||
* clients are free to assert that the response payload body contents are zero
|
||||
and comparing the entire response message against a golden response
|
||||
|
||||
### Metadata (TODO: fix name)
|
||||
|
||||
Status: Not yet implementable
|
||||
|
||||
This test verifies that custom metadata in either binary or ascii format can be
|
||||
sent in header and trailer.
|
||||
|
||||
Server features:
|
||||
* [UnaryCall][]
|
||||
* [Compressable Payload][]
|
||||
* Ability to receive custom metadata from client in header and send custom data
|
||||
back to client in both header and trailer. (TODO: this is not defined)
|
||||
|
||||
Procedure:
|
||||
1. While sending custom metadata (ascii + binary) in the header, client calls UnaryCall with:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_size: 314159
|
||||
payload:{
|
||||
body: 271828 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Asserts:
|
||||
* call was successful
|
||||
* custom metadata is echoed back in the response header.
|
||||
* custom metadata is echoed back in the response trailer.
|
||||
|
||||
### status_code_and_message
|
||||
|
||||
Status: Not yet implementable
|
||||
|
||||
This test verifies unary calls succeed in sending messages, and propagates back
|
||||
status code and message sent along with the messages.
|
||||
|
||||
Server features:
|
||||
* [UnaryCall][]
|
||||
|
||||
Procedure:
|
||||
1. Client calls UnaryCall with:
|
||||
|
||||
```
|
||||
{
|
||||
response_status:{
|
||||
code: 2
|
||||
message: "test status message"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Asserts:
|
||||
* received status code is the same with sent code
|
||||
* received status message is the same with sent message
|
||||
|
||||
### unimplemented_method
|
||||
|
||||
Status: Not yet implementable
|
||||
|
||||
This test verifies calling unimplemented RPC method returns unimplemented
|
||||
status.
|
||||
|
||||
Procedure:
|
||||
* Client calls UnimplementedCall with:
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_size: 314159
|
||||
payload:{
|
||||
body: 271828 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Asserts:
|
||||
* received status code is 12 (UNIMPLEMENTED)
|
||||
* received status message is empty or null/unset
|
||||
|
||||
### cancel_after_begin
|
||||
|
||||
This test verifies that a request can be cancelled after metadata has been sent
|
||||
but before payloads are sent.
|
||||
|
||||
Server features:
|
||||
* [StreamingInputCall][]
|
||||
|
||||
Procedure:
|
||||
1. Client starts StreamingInputCall
|
||||
2. Client immediately cancels request
|
||||
|
||||
Asserts:
|
||||
* Call completed with status CANCELLED
|
||||
|
||||
### cancel_after_first_response
|
||||
|
||||
This test verifies that a request can be cancelled after receiving a message
|
||||
from the server.
|
||||
|
||||
Server features:
|
||||
* [FullDuplexCall][]
|
||||
* [Compressable Payload][]
|
||||
|
||||
Procedure:
|
||||
1. Client starts FullDuplexCall with
|
||||
|
||||
```
|
||||
{
|
||||
response_type: COMPRESSABLE
|
||||
response_parameters:{
|
||||
size: 31415
|
||||
}
|
||||
payload:{
|
||||
body: 27182 bytes of zeros
|
||||
}
|
||||
}
|
||||
```
|
||||
2. After receiving a response, client cancels request
|
||||
|
||||
Asserts:
|
||||
* Call completed with status CANCELLED
|
||||
|
||||
### concurrent_large_unary
|
||||
|
||||
Status: TODO
|
||||
|
||||
Client performs 1000 large_unary tests in parallel on the same channel.
|
||||
|
||||
### Flow control. Pushback at client for large messages (TODO: fix name)
|
||||
|
||||
Status: TODO
|
||||
|
||||
This test verifies that a client sending faster than a server can drain sees
|
||||
pushback (i.e., attempts to send succeed only after appropriate delays).
|
||||
|
||||
### TODO Tests
|
||||
|
||||
High priority:
|
||||
|
||||
Propagation of status code and message (yangg)
|
||||
|
||||
Cancel after sent headers (ctiller - done)
|
||||
|
||||
Cancel after received first message (ctiller - done)
|
||||
|
||||
Timeout after expire (zhaoq)
|
||||
|
||||
Zero-message streams (ejona)
|
||||
|
||||
Multiple thousand simultaneous calls on same Channel (ctiller - done)
|
||||
|
||||
OAuth2 tokens + Service Credentials from GCE metadata server (GCE->prod only)
|
||||
(abhishek)
|
||||
|
||||
OAuth2 tokens + JWT signing key (GCE->prod only) (abhishek)
|
||||
|
||||
Metadata: client headers, server headers + trailers, binary+ascii (chenw)
|
||||
|
||||
Normal priority:
|
||||
|
||||
Cancel before start (ctiller)
|
||||
|
||||
Cancel after sent first message (ctiller)
|
||||
|
||||
Cancel after received headers (ctiller)
|
||||
|
||||
Timeout but completed before expire (zhaoq)
|
||||
|
||||
Multiple thousand simultaneous calls timeout on same Channel (ctiller)
|
||||
|
||||
Lower priority:
|
||||
|
||||
Flow control. Pushback at client for large messages (abhishek)
|
||||
|
||||
Flow control. Pushback at server for large messages (abhishek)
|
||||
|
||||
Going over max concurrent streams doesn't fail (client controls itself)
|
||||
(abhishek)
|
||||
|
||||
RPC method not implemented (yangg)
|
||||
|
||||
Multiple thousand simultaneous calls on different Channels (ctiller)
|
||||
|
||||
Failed TLS hostname verification (ejona?)
|
||||
|
||||
To priorize:
|
||||
|
||||
Start streaming RPC but don't send any requests, server responds
|
||||
|
||||
### Postponed Tests
|
||||
|
||||
Resilience to buggy servers: These tests would verify that a client application
|
||||
isn't affected negatively by the responses put on the wire by a buggy server
|
||||
(e.g. the client library won't make the application crash).
|
||||
|
||||
Reconnect after transport failure
|
||||
|
||||
Reconnect backoff
|
||||
|
||||
Fuzz testing
|
||||
|
||||
|
||||
Server
|
||||
------
|
||||
|
||||
Servers implement various named features for clients to test with. Server
|
||||
features are orthogonal. If a server implements a feature, it is always
|
||||
available for clients. Names are simple descriptions for developer
|
||||
communication and tracking.
|
||||
|
||||
Servers should accept these arguments:
|
||||
|
||||
* --port=PORT
|
||||
|
||||
* The port to listen on. For example, "8080"
|
||||
|
||||
* --use_tls=BOOLEAN
|
||||
|
||||
* Whether to use a plaintext or encrypted connection
|
||||
|
||||
Servers must support TLS with ALPN. They should use
|
||||
[server1.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/server1.pem)
|
||||
for their certificate.
|
||||
|
||||
### EmptyCall
|
||||
[EmptyCall]: #emptycall
|
||||
|
||||
Server implements EmptyCall which immediately returns the empty message.
|
||||
|
||||
### UnaryCall
|
||||
[UnaryCall]: #unarycall
|
||||
|
||||
Server implements UnaryCall which immediately returns a SimpleResponse with a
|
||||
payload body of size SimpleRequest.response_size bytes and type as appropriate
|
||||
for the SimpleRequest.response_type. If the server does not support the
|
||||
response_type, then it should fail the RPC with INVALID_ARGUMENT.
|
||||
|
||||
If the request sets fill_username, the server should return the client username
|
||||
it sees in field SimpleResponse.username. If the request sets fill_oauth_scope,
|
||||
the server should return the oauth scope of the rpc in the form of "xapi_zoo"
|
||||
in field SimpleResponse.oauth_scope.
|
||||
|
||||
### StreamingInputCall
|
||||
[StreamingInputCall]: #streaminginputcall
|
||||
|
||||
Server implements StreamingInputCall which upon half close immediately returns
|
||||
a StreamingInputCallResponse where aggregated_payload_size is the sum of all
|
||||
request payload bodies received.
|
||||
|
||||
### StreamingOutputCall
|
||||
[StreamingOutputCall]: #streamingoutputcall
|
||||
|
||||
Server implements StreamingOutputCall by replying, in order, with one
|
||||
StreamingOutputCallResponses for each ResponseParameters in
|
||||
StreamingOutputCallRequest. Each StreamingOutputCallResponses should have a
|
||||
payload body of size ResponseParameters.size bytes, as specified by its
|
||||
respective ResponseParameters. After sending all responses, it closes with OK.
|
||||
|
||||
### FullDuplexCall
|
||||
[FullDuplexCall]: #fullduplexcall
|
||||
|
||||
Server implements FullDuplexCall by replying, in order, with one
|
||||
StreamingOutputCallResponses for each ResponseParameters in each
|
||||
StreamingOutputCallRequest. Each StreamingOutputCallResponses should have a
|
||||
payload body of size ResponseParameters.size bytes, as specified by its
|
||||
respective ResponseParameters. After receiving half close and sending all
|
||||
responses, it closes with OK.
|
||||
|
||||
### Compressable Payload
|
||||
[Compressable Payload]: #compressable-payload
|
||||
|
||||
When the client requests COMPRESSABLE payload, the response includes a payload
|
||||
of the size requested containing all zeros and the payload type is
|
||||
COMPRESSABLE.
|
||||
|
||||
### Observe ResponseParameters.interval_us
|
||||
[Observe ResponseParameters.interval_us]: #observe-responseparametersinterval_us
|
||||
|
||||
In StreamingOutputCall and FullDuplexCall, server delays sending a
|
||||
StreamingOutputCallResponse by the ResponseParameters's interval_us for that
|
||||
particular response, relative to the last response sent. That is, interval_us
|
||||
acts like a sleep *before* sending the response and accumulates from one
|
||||
response to the next.
|
||||
|
||||
Interaction with flow control is unspecified.
|
||||
|
||||
### Echo Auth Information
|
||||
|
||||
Status: Pending
|
||||
|
||||
If a SimpleRequest has fill_username=true and that request was successfully
|
||||
authenticated, then the SimpleResponse should have username filled with the
|
||||
canonical form of the authenticated source. The canonical form is dependent on
|
||||
the authentication method, but is likely to be a base 10 integer identifier or
|
||||
an email address.
|
||||
|
||||
Discussion:
|
||||
|
||||
Ideally, this would be communicated via metadata and not in the
|
||||
request/response, but we want to use this test in code paths that don't yet
|
||||
fully communicate metadata.
|
||||
|
|
@ -51,14 +51,14 @@
|
|||
#include "examples/pubsub/subscriber.h"
|
||||
|
||||
DEFINE_int32(server_port, 443, "Server port.");
|
||||
DEFINE_string(server_host,
|
||||
"pubsub-staging.googleapis.com", "Server host to connect to");
|
||||
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");
|
||||
|
||||
// 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;
|
||||
|
||||
|
|
@ -92,32 +92,32 @@ int main(int argc, char** argv) {
|
|||
grpc::string topic = ss.str();
|
||||
|
||||
ss.str("");
|
||||
ss << FLAGS_project_id << "/" << kSubscriptionName;
|
||||
ss << FLAGS_project_id << "/" << kSubscriptionName;
|
||||
grpc::string subscription_name = ss.str();
|
||||
|
||||
// Clean up test topic and subcription if they exist before.
|
||||
grpc::string subscription_topic;
|
||||
if (subscriber.GetSubscription(
|
||||
subscription_name, &subscription_topic).IsOk()) {
|
||||
if (subscriber.GetSubscription(subscription_name, &subscription_topic)
|
||||
.IsOk()) {
|
||||
subscriber.DeleteSubscription(subscription_name);
|
||||
}
|
||||
|
||||
if (publisher.GetTopic(topic).IsOk()) publisher.DeleteTopic(topic);
|
||||
|
||||
grpc::Status s = publisher.CreateTopic(topic);
|
||||
gpr_log(GPR_INFO, "Create topic returns code %d, %s",
|
||||
s.code(), s.details().c_str());
|
||||
gpr_log(GPR_INFO, "Create topic returns code %d, %s", s.code(),
|
||||
s.details().c_str());
|
||||
GPR_ASSERT(s.IsOk());
|
||||
|
||||
s = publisher.GetTopic(topic);
|
||||
gpr_log(GPR_INFO, "Get topic returns code %d, %s",
|
||||
s.code(), s.details().c_str());
|
||||
gpr_log(GPR_INFO, "Get topic returns code %d, %s", s.code(),
|
||||
s.details().c_str());
|
||||
GPR_ASSERT(s.IsOk());
|
||||
|
||||
std::vector<grpc::string> topics;
|
||||
s = publisher.ListTopics(FLAGS_project_id, &topics);
|
||||
gpr_log(GPR_INFO, "List topic returns code %d, %s",
|
||||
s.code(), s.details().c_str());
|
||||
gpr_log(GPR_INFO, "List topic returns code %d, %s", s.code(),
|
||||
s.details().c_str());
|
||||
bool topic_found = false;
|
||||
for (unsigned int i = 0; i < topics.size(); i++) {
|
||||
if (topics[i] == topic) topic_found = true;
|
||||
|
|
@ -127,27 +127,27 @@ int main(int argc, char** argv) {
|
|||
GPR_ASSERT(topic_found);
|
||||
|
||||
s = subscriber.CreateSubscription(topic, subscription_name);
|
||||
gpr_log(GPR_INFO, "create subscrption returns code %d, %s",
|
||||
s.code(), s.details().c_str());
|
||||
gpr_log(GPR_INFO, "create subscrption returns code %d, %s", s.code(),
|
||||
s.details().c_str());
|
||||
GPR_ASSERT(s.IsOk());
|
||||
|
||||
s = publisher.Publish(topic, kMessageData);
|
||||
gpr_log(GPR_INFO, "Publish %s returns code %d, %s",
|
||||
kMessageData, s.code(), s.details().c_str());
|
||||
gpr_log(GPR_INFO, "Publish %s returns code %d, %s", kMessageData, s.code(),
|
||||
s.details().c_str());
|
||||
GPR_ASSERT(s.IsOk());
|
||||
|
||||
grpc::string data;
|
||||
s = subscriber.Pull(subscription_name, &data);
|
||||
gpr_log(GPR_INFO, "Pull %s", data.c_str());
|
||||
|
||||
s = subscriber.DeleteSubscription(subscription_name);
|
||||
gpr_log(GPR_INFO, "Delete subscription returns code %d, %s",
|
||||
s.code(), s.details().c_str());
|
||||
s = subscriber.DeleteSubscription(subscription_name);
|
||||
gpr_log(GPR_INFO, "Delete subscription returns code %d, %s", s.code(),
|
||||
s.details().c_str());
|
||||
GPR_ASSERT(s.IsOk());
|
||||
|
||||
s = publisher.DeleteTopic(topic);
|
||||
gpr_log(GPR_INFO, "Delete topic returns code %d, %s",
|
||||
s.code(), s.details().c_str());
|
||||
gpr_log(GPR_INFO, "Delete topic returns code %d, %s", s.code(),
|
||||
s.details().c_str());
|
||||
GPR_ASSERT(s.IsOk());
|
||||
|
||||
subscriber.Shutdown();
|
||||
|
|
|
|||
|
|
@ -51,12 +51,9 @@ namespace examples {
|
|||
namespace pubsub {
|
||||
|
||||
Publisher::Publisher(std::shared_ptr<ChannelInterface> channel)
|
||||
: stub_(PublisherService::NewStub(channel)) {
|
||||
}
|
||||
: stub_(PublisherService::NewStub(channel)) {}
|
||||
|
||||
void Publisher::Shutdown() {
|
||||
stub_.reset();
|
||||
}
|
||||
void Publisher::Shutdown() { stub_.reset(); }
|
||||
|
||||
Status Publisher::CreateTopic(const grpc::string& topic) {
|
||||
Topic request;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include <grpc++/channel_interface.h>
|
||||
#include <grpc++/status.h>
|
||||
|
||||
#include "examples/pubsub/pubsub.pb.h"
|
||||
#include "examples/pubsub/pubsub.grpc.pb.h"
|
||||
|
||||
namespace grpc {
|
||||
namespace examples {
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <grpc++/channel_arguments.h>
|
||||
#include <grpc++/channel_interface.h>
|
||||
#include <grpc++/client_context.h>
|
||||
|
|
@ -84,20 +82,19 @@ class PublisherServiceImpl : public tech::pubsub::PublisherService::Service {
|
|||
Status ListTopics(
|
||||
ServerContext* context, const ::tech::pubsub::ListTopicsRequest* request,
|
||||
::tech::pubsub::ListTopicsResponse* response) GRPC_OVERRIDE {
|
||||
std::ostringstream ss;
|
||||
ss << "cloud.googleapis.com/project in (/projects/" << kProjectId << ")";
|
||||
EXPECT_EQ(request->query(), ss.str());
|
||||
response->add_topic()->set_name(kTopic);
|
||||
return Status::OK;
|
||||
}
|
||||
std::ostringstream ss;
|
||||
ss << "cloud.googleapis.com/project in (/projects/" << kProjectId << ")";
|
||||
EXPECT_EQ(request->query(), ss.str());
|
||||
response->add_topic()->set_name(kTopic);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status DeleteTopic(ServerContext* context,
|
||||
const ::tech::pubsub::DeleteTopicRequest* request,
|
||||
::proto2::Empty* response) GRPC_OVERRIDE {
|
||||
Status DeleteTopic(ServerContext* context,
|
||||
const ::tech::pubsub::DeleteTopicRequest* request,
|
||||
::proto2::Empty* response) GRPC_OVERRIDE {
|
||||
EXPECT_EQ(request->topic(), kTopic);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class PublisherTest : public ::testing::Test {
|
||||
|
|
@ -107,11 +104,13 @@ class PublisherTest : public ::testing::Test {
|
|||
int port = grpc_pick_unused_port_or_die();
|
||||
server_address_ << "localhost:" << port;
|
||||
ServerBuilder builder;
|
||||
builder.AddListeningPort(server_address_.str(), grpc::InsecureServerCredentials());
|
||||
builder.AddListeningPort(server_address_.str(),
|
||||
grpc::InsecureServerCredentials());
|
||||
builder.RegisterService(&service_);
|
||||
server_ = builder.BuildAndStart();
|
||||
|
||||
channel_ = CreateChannel(server_address_.str(), grpc::InsecureCredentials(), ChannelArguments());
|
||||
channel_ = CreateChannel(server_address_.str(), grpc::InsecureCredentials(),
|
||||
ChannelArguments());
|
||||
|
||||
publisher_.reset(new grpc::examples::pubsub::Publisher(channel_));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,12 +49,9 @@ namespace examples {
|
|||
namespace pubsub {
|
||||
|
||||
Subscriber::Subscriber(std::shared_ptr<ChannelInterface> channel)
|
||||
: stub_(SubscriberService::NewStub(channel)) {
|
||||
}
|
||||
: stub_(SubscriberService::NewStub(channel)) {}
|
||||
|
||||
void Subscriber::Shutdown() {
|
||||
stub_.reset();
|
||||
}
|
||||
void Subscriber::Shutdown() { stub_.reset(); }
|
||||
|
||||
Status Subscriber::CreateSubscription(const grpc::string& topic,
|
||||
const grpc::string& name) {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include <grpc++/channel_interface.h>
|
||||
#include <grpc++/status.h>
|
||||
|
||||
#include "examples/pubsub/pubsub.pb.h"
|
||||
#include "examples/pubsub/pubsub.grpc.pb.h"
|
||||
|
||||
namespace grpc {
|
||||
namespace examples {
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
#include <grpc++/channel_arguments.h>
|
||||
#include <grpc++/channel_interface.h>
|
||||
#include <grpc++/client_context.h>
|
||||
|
|
@ -95,7 +93,6 @@ class SubscriberServiceImpl : public tech::pubsub::SubscriberService::Service {
|
|||
proto2::Empty* response) GRPC_OVERRIDE {
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class SubscriberTest : public ::testing::Test {
|
||||
|
|
@ -105,11 +102,13 @@ class SubscriberTest : public ::testing::Test {
|
|||
int port = grpc_pick_unused_port_or_die();
|
||||
server_address_ << "localhost:" << port;
|
||||
ServerBuilder builder;
|
||||
builder.AddListeningPort(server_address_.str(), grpc::InsecureServerCredentials());
|
||||
builder.AddListeningPort(server_address_.str(),
|
||||
grpc::InsecureServerCredentials());
|
||||
builder.RegisterService(&service_);
|
||||
server_ = builder.BuildAndStart();
|
||||
|
||||
channel_ = CreateChannel(server_address_.str(), grpc::InsecureCredentials(), ChannelArguments());
|
||||
channel_ = CreateChannel(server_address_.str(), grpc::InsecureCredentials(),
|
||||
ChannelArguments());
|
||||
|
||||
subscriber_.reset(new grpc::examples::pubsub::Subscriber(channel_));
|
||||
}
|
||||
|
|
@ -129,17 +128,15 @@ class SubscriberTest : public ::testing::Test {
|
|||
};
|
||||
|
||||
TEST_F(SubscriberTest, TestSubscriber) {
|
||||
EXPECT_TRUE(subscriber_->CreateSubscription(kTopic,
|
||||
kSubscriptionName).IsOk());
|
||||
EXPECT_TRUE(
|
||||
subscriber_->CreateSubscription(kTopic, kSubscriptionName).IsOk());
|
||||
|
||||
grpc::string topic;
|
||||
EXPECT_TRUE(subscriber_->GetSubscription(kSubscriptionName,
|
||||
&topic).IsOk());
|
||||
EXPECT_TRUE(subscriber_->GetSubscription(kSubscriptionName, &topic).IsOk());
|
||||
EXPECT_EQ(topic, kTopic);
|
||||
|
||||
grpc::string data;
|
||||
EXPECT_TRUE(subscriber_->Pull(kSubscriptionName,
|
||||
&data).IsOk());
|
||||
EXPECT_TRUE(subscriber_->Pull(kSubscriptionName, &data).IsOk());
|
||||
|
||||
EXPECT_TRUE(subscriber_->DeleteSubscription(kSubscriptionName).IsOk());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,11 +34,46 @@
|
|||
#ifndef GRPCXX_CONFIG_H
|
||||
#define GRPCXX_CONFIG_H
|
||||
|
||||
#ifdef GRPC_OLD_CXX
|
||||
#if !defined(GRPC_NO_AUTODETECT_PLATFORM)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Visual Studio 2010 is 1600.
|
||||
#if _MSC_VER < 1600
|
||||
#error "gRPC is only supported with Visual Studio starting at 2010"
|
||||
// Visual Studio 2013 is 1800.
|
||||
#elif _MSC_VER < 1800
|
||||
#define GRPC_CXX0X_NO_FINAL 1
|
||||
#define GRPC_CXX0X_NO_OVERRIDE 1
|
||||
#define GRPC_CXX0X_NO_CHRONO 1
|
||||
#define GRPC_CXX0X_NO_THREAD 1
|
||||
#endif
|
||||
#endif // Visual Studio
|
||||
|
||||
#ifndef __clang__
|
||||
#ifdef __GNUC__
|
||||
// nullptr was added in gcc 4.6
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__ < 406)
|
||||
#define GRPC_CXX0X_NO_NULLPTR 1
|
||||
#endif
|
||||
// final and override were added in gcc 4.7
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__ < 407)
|
||||
#define GRPC_CXX0X_NO_FINAL 1
|
||||
#define GRPC_CXX0X_NO_OVERRIDE 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GRPC_CXX0X_NO_FINAL
|
||||
#define GRPC_FINAL
|
||||
#define GRPC_OVERRIDE
|
||||
#else
|
||||
#define GRPC_FINAL final
|
||||
#endif
|
||||
|
||||
#ifdef GRPC_CXX0X_NO_OVERRIDE
|
||||
#define GRPC_OVERRIDE
|
||||
#else
|
||||
#define GRPC_OVERRIDE override
|
||||
#endif
|
||||
|
||||
|
|
@ -65,6 +100,20 @@
|
|||
::google::protobuf::io::ZeroCopyInputStream
|
||||
#endif
|
||||
|
||||
#ifdef GRPC_CXX0X_NO_NULLPTR
|
||||
#include <memory>
|
||||
const class {
|
||||
public:
|
||||
template <class T> operator T*() const {return static_cast<T *>(0);}
|
||||
template <class T> operator std::unique_ptr<T>() const {
|
||||
return std::unique_ptr<T>(static_cast<T *>(0));
|
||||
}
|
||||
operator bool() const {return false;}
|
||||
private:
|
||||
void operator&() const = delete;
|
||||
} nullptr = {};
|
||||
#endif
|
||||
|
||||
namespace grpc {
|
||||
|
||||
typedef GRPC_CUSTOM_STRING string;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
namespace grpc {
|
||||
|
||||
class CompletionQueue;
|
||||
typedef ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
|
||||
GenericClientAsyncReaderWriter;
|
||||
|
||||
|
|
@ -51,7 +52,8 @@ class GenericStub GRPC_FINAL {
|
|||
|
||||
// begin a call to a named method
|
||||
std::unique_ptr<GenericClientAsyncReaderWriter> Call(
|
||||
ClientContext* context, const grpc::string& method);
|
||||
ClientContext* context, const grpc::string& method,
|
||||
CompletionQueue* cq, void* tag);
|
||||
|
||||
private:
|
||||
std::shared_ptr<ChannelInterface> channel_;
|
||||
|
|
|
|||
|
|
@ -109,7 +109,9 @@ class CallOpBuffer : public CompletionQueueTag {
|
|||
char* status_details_;
|
||||
size_t status_details_capacity_;
|
||||
// Server send status
|
||||
const Status* send_status_;
|
||||
bool send_status_available_;
|
||||
grpc_status_code send_status_code_;
|
||||
grpc::string send_status_details_;
|
||||
size_t trailing_metadata_count_;
|
||||
grpc_metadata* trailing_metadata_;
|
||||
int cancelled_buf_;
|
||||
|
|
|
|||
|
|
@ -31,21 +31,15 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef NET_GRPC_PHP_GRPC_EVENT_H_
|
||||
#define NET_GRPC_PHP_GRPC_EVENT_H_
|
||||
#ifndef GRPCXX_IMPL_SYNC_H
|
||||
#define GRPCXX_IMPL_SYNC_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include <grpc++/config.h>
|
||||
|
||||
#ifdef GRPC_CXX0X_NO_THREAD
|
||||
#include <grpc++/impl/sync_no_cxx11.h>
|
||||
#else
|
||||
#include <grpc++/impl/sync_cxx11.h>
|
||||
#endif
|
||||
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_grpc.h"
|
||||
|
||||
#include "grpc/grpc.h"
|
||||
|
||||
/* Create a new Event object that wraps an existing grpc_event struct */
|
||||
zval *grpc_php_convert_event(grpc_event *event);
|
||||
|
||||
#endif /* NET_GRPC_PHP_GRPC_COMPLETION_CHANNEL_H */
|
||||
#endif // GRPCXX_IMPL_SYNC_H
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
<?php
|
||||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
|
|
@ -31,23 +30,20 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
function grpcAutoloader($class) {
|
||||
$prefix = 'Grpc\\';
|
||||
|
||||
$base_dir = __DIR__ . '/Grpc/';
|
||||
#ifndef GRPCXX_IMPL_SYNC_CXX11_H
|
||||
#define GRPCXX_IMPL_SYNC_CXX11_H
|
||||
|
||||
$len = strlen($prefix);
|
||||
if (strncmp($prefix, $class, $len) !== 0) {
|
||||
return;
|
||||
}
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
$relative_class = substr($class, $len);
|
||||
namespace grpc {
|
||||
|
||||
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
|
||||
using std::condition_variable;
|
||||
using std::mutex;
|
||||
using std::lock_guard;
|
||||
using std::unique_lock;
|
||||
|
||||
if (file_exists($file)) {
|
||||
include $file;
|
||||
}
|
||||
}
|
||||
} // namespace grpc
|
||||
|
||||
spl_autoload_register('grpcAutoloader');
|
||||
#endif // GRPCXX_IMPL_SYNC_CXX11_H
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
*
|
||||
* 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 GRPCXX_IMPL_SYNC_NO_CXX11_H
|
||||
#define GRPCXX_IMPL_SYNC_NO_CXX11_H
|
||||
|
||||
#include <grpc/support/sync.h>
|
||||
|
||||
namespace grpc {
|
||||
|
||||
template<class mutex>
|
||||
class lock_guard;
|
||||
class condition_variable;
|
||||
|
||||
class mutex {
|
||||
public:
|
||||
mutex() { gpr_mu_init(&mu_); }
|
||||
~mutex() { gpr_mu_destroy(&mu_); }
|
||||
private:
|
||||
::gpr_mu mu_;
|
||||
template <class mutex>
|
||||
friend class lock_guard;
|
||||
friend class condition_variable;
|
||||
};
|
||||
|
||||
template <class mutex>
|
||||
class lock_guard {
|
||||
public:
|
||||
lock_guard(mutex &mu) : mu_(mu), locked(true) { gpr_mu_lock(&mu.mu_); }
|
||||
~lock_guard() { unlock_internal(); }
|
||||
protected:
|
||||
void lock_internal() {
|
||||
if (!locked) gpr_mu_lock(&mu_.mu_);
|
||||
locked = true;
|
||||
}
|
||||
void unlock_internal() {
|
||||
if (locked) gpr_mu_unlock(&mu_.mu_);
|
||||
locked = false;
|
||||
}
|
||||
private:
|
||||
mutex &mu_;
|
||||
bool locked;
|
||||
friend class condition_variable;
|
||||
};
|
||||
|
||||
template <class mutex>
|
||||
class unique_lock : public lock_guard<mutex> {
|
||||
public:
|
||||
unique_lock(mutex &mu) : lock_guard(mu) { }
|
||||
void lock() { lock_internal(); }
|
||||
void unlock() { unlock_internal(); }
|
||||
};
|
||||
|
||||
class condition_variable {
|
||||
public:
|
||||
condition_variable() { gpr_cv_init(&cv_); }
|
||||
~condition_variable() { gpr_cv_destroy(&cv_); }
|
||||
void wait(lock_guard<mutex> &mu) {
|
||||
mu.locked = false;
|
||||
gpr_cv_wait(&cv_, &mu.mu_.mu_, gpr_inf_future);
|
||||
mu.locked = true;
|
||||
}
|
||||
void notify_one() { gpr_cv_signal(&cv_); }
|
||||
void notify_all() { gpr_cv_broadcast(&cv_); }
|
||||
private:
|
||||
gpr_cv cv_;
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCXX_IMPL_SYNC_NO_CXX11_H
|
||||
25
src/php/tests/unit_tests/CompletionQueueTest.php → include/grpc++/impl/thd.h
Executable file → Normal file
25
src/php/tests/unit_tests/CompletionQueueTest.php → include/grpc++/impl/thd.h
Executable file → Normal file
|
|
@ -1,4 +1,3 @@
|
|||
<?php
|
||||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
|
|
@ -31,16 +30,16 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
class CompletionQueueTest extends PHPUnit_Framework_TestCase{
|
||||
public function testNextReturnsNullWithNoCall() {
|
||||
$cq = new Grpc\CompletionQueue();
|
||||
$event = $cq->next(Grpc\Timeval::zero());
|
||||
$this->assertNull($event);
|
||||
}
|
||||
|
||||
public function testPluckReturnsNullWithNoCall() {
|
||||
$cq = new Grpc\CompletionQueue();
|
||||
$event = $cq->pluck(0, Grpc\Timeval::zero());
|
||||
$this->assertNull($event);
|
||||
}
|
||||
}
|
||||
#ifndef GRPCXX_IMPL_THD_H
|
||||
#define GRPCXX_IMPL_THD_H
|
||||
|
||||
#include <grpc++/config.h>
|
||||
|
||||
#ifdef GRPC_CXX0X_NO_THREAD
|
||||
#include <grpc++/impl/thd_no_cxx11.h>
|
||||
#else
|
||||
#include <grpc++/impl/thd_cxx11.h>
|
||||
#endif
|
||||
|
||||
#endif // GRPCXX_IMPL_THD_H
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
*
|
||||
* 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 GRPCXX_IMPL_THD_CXX11_H
|
||||
#define GRPCXX_IMPL_THD_CXX11_H
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace grpc {
|
||||
|
||||
using std::thread;
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCXX_IMPL_THD_CXX11_H
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
*
|
||||
* 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 GRPCXX_IMPL_THD_NO_CXX11_H
|
||||
#define GRPCXX_IMPL_THD_NO_CXX11_H
|
||||
|
||||
#include <grpc/support/thd.h>
|
||||
|
||||
namespace grpc {
|
||||
|
||||
class thread {
|
||||
public:
|
||||
template<class T> thread(void (T::*fptr)(), T *obj) {
|
||||
func_ = new thread_function<T>(fptr, obj);
|
||||
joined_ = false;
|
||||
start();
|
||||
}
|
||||
~thread() {
|
||||
if (!joined_) std::terminate();
|
||||
delete func_;
|
||||
}
|
||||
void join() {
|
||||
gpr_thd_join(thd_);
|
||||
joined_ = true;
|
||||
}
|
||||
private:
|
||||
void start() {
|
||||
gpr_thd_options options = gpr_thd_options_default();
|
||||
gpr_thd_options_set_joinable(&options);
|
||||
gpr_thd_new(&thd_, thread_func, (void *) func_, &options);
|
||||
}
|
||||
static void thread_func(void *arg) {
|
||||
thread_function_base *func = (thread_function_base *) arg;
|
||||
func->call();
|
||||
}
|
||||
class thread_function_base {
|
||||
public:
|
||||
virtual ~thread_function_base() { }
|
||||
virtual void call() = 0;
|
||||
};
|
||||
template<class T>
|
||||
class thread_function : public thread_function_base {
|
||||
public:
|
||||
thread_function(void (T::*fptr)(), T *obj)
|
||||
: fptr_(fptr)
|
||||
, obj_(obj) { }
|
||||
virtual void call() { (obj_->*fptr_)(); }
|
||||
private:
|
||||
void (T::*fptr_)();
|
||||
T *obj_;
|
||||
};
|
||||
thread_function_base *func_;
|
||||
gpr_thd_id thd_;
|
||||
bool joined_;
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCXX_IMPL_THD_NO_CXX11_H
|
||||
|
|
@ -34,15 +34,14 @@
|
|||
#ifndef GRPCXX_SERVER_H
|
||||
#define GRPCXX_SERVER_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include <grpc++/completion_queue.h>
|
||||
#include <grpc++/config.h>
|
||||
#include <grpc++/impl/call.h>
|
||||
#include <grpc++/impl/service_type.h>
|
||||
#include <grpc++/impl/sync.h>
|
||||
#include <grpc++/status.h>
|
||||
|
||||
struct grpc_server;
|
||||
|
|
@ -110,12 +109,12 @@ class Server GRPC_FINAL : private CallHook,
|
|||
CompletionQueue cq_;
|
||||
|
||||
// Sever status
|
||||
std::mutex mu_;
|
||||
grpc::mutex mu_;
|
||||
bool started_;
|
||||
bool shutdown_;
|
||||
// The number of threads which are running callbacks.
|
||||
int num_running_cb_;
|
||||
std::condition_variable callback_cv_;
|
||||
grpc::condition_variable callback_cv_;
|
||||
|
||||
std::list<SyncRequest> sync_methods_;
|
||||
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@
|
|||
#endif
|
||||
|
||||
#if defined(GPR_POSIX_SOCKET) + defined(GPR_WIN32) != 1
|
||||
#error Must define exactly one of GPR_POSIX_POLLSET, GPR_WIN32
|
||||
#error Must define exactly one of GPR_POSIX_SOCKET, GPR_WIN32
|
||||
#endif
|
||||
|
||||
typedef int16_t gpr_int16;
|
||||
|
|
|
|||
|
|
@ -52,9 +52,8 @@ typedef gpr_uint64 gpr_thd_id;
|
|||
|
||||
/* Thread creation options. */
|
||||
typedef struct {
|
||||
int flags; /* Flags below can be set here. Default value 0. */
|
||||
int flags; /* Opaque field. Get and set with accessors below. */
|
||||
} gpr_thd_options;
|
||||
/* No flags are currently defined. */
|
||||
|
||||
/* Create a new thread running (*thd_body)(arg) and place its thread identifier
|
||||
in *t, and return true. If there are insufficient resources, return false.
|
||||
|
|
@ -66,9 +65,25 @@ int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
|
|||
/* Return a gpr_thd_options struct with all fields set to defaults. */
|
||||
gpr_thd_options gpr_thd_options_default(void);
|
||||
|
||||
/* Set the thread to become detached on startup - this is the default. */
|
||||
void gpr_thd_options_set_detached(gpr_thd_options *options);
|
||||
|
||||
/* Set the thread to become joinable - mutually exclusive with detached. */
|
||||
void gpr_thd_options_set_joinable(gpr_thd_options *options);
|
||||
|
||||
/* Returns non-zero if the option detached is set. */
|
||||
int gpr_thd_options_is_detached(const gpr_thd_options *options);
|
||||
|
||||
/* Returns non-zero if the option joinable is set. */
|
||||
int gpr_thd_options_is_joinable(const gpr_thd_options *options);
|
||||
|
||||
/* Returns the identifier of the current thread. */
|
||||
gpr_thd_id gpr_thd_currentid(void);
|
||||
|
||||
/* Blocks until the specified thread properly terminates.
|
||||
Calling this on a detached thread has unpredictable results. */
|
||||
void gpr_thd_join(gpr_thd_id t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -109,9 +109,49 @@ bool HasBidiStreaming(const grpc::protobuf::FileDescriptor *file) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
grpc::string FilenameIdentifier(const grpc::string& filename) {
|
||||
grpc::string result;
|
||||
for (unsigned i = 0; i < filename.size(); i++) {
|
||||
char c = filename[i];
|
||||
if (isalnum(c)) {
|
||||
result.push_back(c);
|
||||
} else {
|
||||
static char hex[] = "0123456789abcdef";
|
||||
result.push_back('_');
|
||||
result.push_back(hex[(c >> 4) & 0xf]);
|
||||
result.push_back(hex[c & 0xf]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file) {
|
||||
grpc::string GetHeaderPrologue(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms) {
|
||||
grpc::string output;
|
||||
grpc::protobuf::io::StringOutputStream output_stream(&output);
|
||||
grpc::protobuf::io::Printer printer(&output_stream, '$');
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
|
||||
vars["filename"] = file->name();
|
||||
vars["filename_identifier"] = FilenameIdentifier(file->name());
|
||||
vars["filename_base"] = grpc_generator::StripProto(file->name());
|
||||
|
||||
printer.Print(vars, "// Generated by the gRPC protobuf plugin.\n");
|
||||
printer.Print(vars, "// If you make any local change, they will be lost.\n");
|
||||
printer.Print(vars, "// source: $filename$\n");
|
||||
printer.Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
|
||||
printer.Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
|
||||
printer.Print(vars, "\n");
|
||||
printer.Print(vars, "#include \"$filename_base$.pb.h\"\n");
|
||||
printer.Print(vars, "\n");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms) {
|
||||
grpc::string temp =
|
||||
"#include <grpc++/impl/internal_stub.h>\n"
|
||||
"#include <grpc++/impl/service_type.h>\n"
|
||||
|
|
@ -155,17 +195,21 @@ grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file) {
|
|||
"class ServerAsyncReaderWriter;\n");
|
||||
}
|
||||
temp.append("} // namespace grpc\n");
|
||||
return temp;
|
||||
}
|
||||
|
||||
grpc::string GetSourceIncludes() {
|
||||
return "#include <grpc++/async_unary_call.h>\n"
|
||||
"#include <grpc++/channel_interface.h>\n"
|
||||
"#include <grpc++/impl/client_unary_call.h>\n"
|
||||
"#include <grpc++/impl/rpc_method.h>\n"
|
||||
"#include <grpc++/impl/rpc_service_method.h>\n"
|
||||
"#include <grpc++/impl/service_type.h>\n"
|
||||
"#include <grpc++/stream.h>\n";
|
||||
temp.append("\n");
|
||||
|
||||
std::vector<grpc::string> parts =
|
||||
grpc_generator::tokenize(file->package(), ".");
|
||||
|
||||
for (auto part = parts.begin(); part != parts.end(); part++) {
|
||||
temp.append("namespace ");
|
||||
temp.append(*part);
|
||||
temp.append(" {\n");
|
||||
}
|
||||
|
||||
temp.append("\n");
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer,
|
||||
|
|
@ -353,16 +397,99 @@ void PrintHeaderService(grpc::protobuf::io::Printer *printer,
|
|||
printer->Print("};\n");
|
||||
}
|
||||
|
||||
grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file) {
|
||||
grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms) {
|
||||
grpc::string output;
|
||||
grpc::protobuf::io::StringOutputStream output_stream(&output);
|
||||
grpc::protobuf::io::Printer printer(&output_stream, '$');
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
|
||||
if (!params.services_namespace.empty()) {
|
||||
vars["services_namespace"] = params.services_namespace;
|
||||
printer.Print(vars, "\nnamespace $services_namespace$ {\n\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
PrintHeaderService(&printer, file->service(i), &vars);
|
||||
printer.Print("\n");
|
||||
}
|
||||
|
||||
if (!params.services_namespace.empty()) {
|
||||
printer.Print(vars, "} // namespace $services_namespace$\n\n");
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
grpc::string GetHeaderEpilogue(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms) {
|
||||
grpc::string output;
|
||||
grpc::protobuf::io::StringOutputStream output_stream(&output);
|
||||
grpc::protobuf::io::Printer printer(&output_stream, '$');
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
|
||||
vars["filename"] = file->name();
|
||||
vars["filename_identifier"] = FilenameIdentifier(file->name());
|
||||
|
||||
std::vector<grpc::string> parts =
|
||||
grpc_generator::tokenize(file->package(), ".");
|
||||
|
||||
for (auto part = parts.rbegin(); part != parts.rend(); part++) {
|
||||
vars["part"] = *part;
|
||||
printer.Print(vars, "} // namespace $part$\n");
|
||||
}
|
||||
|
||||
printer.Print(vars, "\n\n");
|
||||
printer.Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
grpc::string GetSourcePrologue(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms) {
|
||||
grpc::string output;
|
||||
grpc::protobuf::io::StringOutputStream output_stream(&output);
|
||||
grpc::protobuf::io::Printer printer(&output_stream, '$');
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
|
||||
vars["filename"] = file->name();
|
||||
vars["filename_base"] = grpc_generator::StripProto(file->name());
|
||||
|
||||
printer.Print(vars, "// Generated by the gRPC protobuf plugin.\n");
|
||||
printer.Print(vars, "// If you make any local change, they will be lost.\n");
|
||||
printer.Print(vars, "// source: $filename$\n\n");
|
||||
printer.Print(vars, "#include \"$filename_base$.pb.h\"\n");
|
||||
printer.Print(vars, "#include \"$filename_base$.grpc.pb.h\"\n");
|
||||
printer.Print(vars, "\n");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
grpc::string GetSourceIncludes(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶m) {
|
||||
grpc::string output;
|
||||
grpc::protobuf::io::StringOutputStream output_stream(&output);
|
||||
grpc::protobuf::io::Printer printer(&output_stream, '$');
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
|
||||
printer.Print(vars, "#include <grpc++/async_unary_call.h>\n");
|
||||
printer.Print(vars, "#include <grpc++/channel_interface.h>\n");
|
||||
printer.Print(vars, "#include <grpc++/impl/client_unary_call.h>\n");
|
||||
printer.Print(vars, "#include <grpc++/impl/rpc_method.h>\n");
|
||||
printer.Print(vars, "#include <grpc++/impl/rpc_service_method.h>\n");
|
||||
printer.Print(vars, "#include <grpc++/impl/service_type.h>\n");
|
||||
printer.Print(vars, "#include <grpc++/stream.h>\n");
|
||||
|
||||
std::vector<grpc::string> parts =
|
||||
grpc_generator::tokenize(file->package(), ".");
|
||||
|
||||
for (auto part = parts.begin(); part != parts.end(); part++) {
|
||||
vars["part"] = *part;
|
||||
printer.Print(vars, "namespace $part$ {\n");
|
||||
}
|
||||
|
||||
printer.Print(vars, "\n");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
@ -376,18 +503,18 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer,
|
|||
grpc_cpp_generator::ClassName(method->output_type(), true);
|
||||
if (NoStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"::grpc::Status $Service$::Stub::$Method$("
|
||||
"::grpc::Status $ns$$Service$::Stub::$Method$("
|
||||
"::grpc::ClientContext* context, "
|
||||
"const $Request$& request, $Response$* response) {\n");
|
||||
printer->Print(*vars,
|
||||
" return ::grpc::BlockingUnaryCall(channel(),"
|
||||
"::grpc::RpcMethod($Service$_method_names[$Idx$]), "
|
||||
"::grpc::RpcMethod($prefix$$Service$_method_names[$Idx$]), "
|
||||
"context, request, response);\n"
|
||||
"}\n\n");
|
||||
printer->Print(
|
||||
*vars,
|
||||
"std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
|
||||
"$Service$::Stub::Async$Method$(::grpc::ClientContext* context, "
|
||||
"$ns$$Service$::Stub::Async$Method$(::grpc::ClientContext* context, "
|
||||
"const $Request$& request, "
|
||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
||||
printer->Print(*vars,
|
||||
|
|
@ -395,32 +522,32 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer,
|
|||
"::grpc::ClientAsyncResponseReader< $Response$>>(new "
|
||||
"::grpc::ClientAsyncResponseReader< $Response$>("
|
||||
"channel(), cq, "
|
||||
"::grpc::RpcMethod($Service$_method_names[$Idx$]), "
|
||||
"::grpc::RpcMethod($prefix$$Service$_method_names[$Idx$]), "
|
||||
"context, request, tag));\n"
|
||||
"}\n\n");
|
||||
} else if (ClientOnlyStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"std::unique_ptr< ::grpc::ClientWriter< $Request$>> "
|
||||
"$Service$::Stub::$Method$("
|
||||
"$ns$$Service$::Stub::$Method$("
|
||||
"::grpc::ClientContext* context, $Response$* response) {\n");
|
||||
printer->Print(*vars,
|
||||
" return std::unique_ptr< ::grpc::ClientWriter< "
|
||||
"$Request$>>(new ::grpc::ClientWriter< $Request$>("
|
||||
"channel(),"
|
||||
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod($prefix$$Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "
|
||||
"context, response));\n"
|
||||
"}\n\n");
|
||||
printer->Print(*vars,
|
||||
"std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>> "
|
||||
"$Service$::Stub::Async$Method$("
|
||||
"$ns$$Service$::Stub::Async$Method$("
|
||||
"::grpc::ClientContext* context, $Response$* response, "
|
||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
||||
printer->Print(*vars,
|
||||
" return std::unique_ptr< ::grpc::ClientAsyncWriter< "
|
||||
"$Request$>>(new ::grpc::ClientAsyncWriter< $Request$>("
|
||||
"channel(), cq, "
|
||||
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod($prefix$$Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "
|
||||
"context, response, tag));\n"
|
||||
"}\n\n");
|
||||
|
|
@ -428,26 +555,26 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer,
|
|||
printer->Print(
|
||||
*vars,
|
||||
"std::unique_ptr< ::grpc::ClientReader< $Response$>> "
|
||||
"$Service$::Stub::$Method$("
|
||||
"$ns$$Service$::Stub::$Method$("
|
||||
"::grpc::ClientContext* context, const $Request$& request) {\n");
|
||||
printer->Print(*vars,
|
||||
" return std::unique_ptr< ::grpc::ClientReader< "
|
||||
"$Response$>>(new ::grpc::ClientReader< $Response$>("
|
||||
"channel(),"
|
||||
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod($prefix$$Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
|
||||
"context, request));\n"
|
||||
"}\n\n");
|
||||
printer->Print(*vars,
|
||||
"std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
|
||||
"$Service$::Stub::Async$Method$("
|
||||
"$ns$$Service$::Stub::Async$Method$("
|
||||
"::grpc::ClientContext* context, const $Request$& request, "
|
||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
||||
printer->Print(*vars,
|
||||
" return std::unique_ptr< ::grpc::ClientAsyncReader< "
|
||||
"$Response$>>(new ::grpc::ClientAsyncReader< $Response$>("
|
||||
"channel(), cq, "
|
||||
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod($prefix$$Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
|
||||
"context, request, tag));\n"
|
||||
"}\n\n");
|
||||
|
|
@ -455,27 +582,27 @@ void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer,
|
|||
printer->Print(
|
||||
*vars,
|
||||
"std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>> "
|
||||
"$Service$::Stub::$Method$(::grpc::ClientContext* context) {\n");
|
||||
"$ns$$Service$::Stub::$Method$(::grpc::ClientContext* context) {\n");
|
||||
printer->Print(*vars,
|
||||
" return std::unique_ptr< ::grpc::ClientReaderWriter< "
|
||||
"$Request$, $Response$>>(new ::grpc::ClientReaderWriter< "
|
||||
"$Request$, $Response$>("
|
||||
"channel(),"
|
||||
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod($prefix$$Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod::RpcType::BIDI_STREAMING), "
|
||||
"context));\n"
|
||||
"}\n\n");
|
||||
printer->Print(*vars,
|
||||
"std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
|
||||
"$Request$, $Response$>> "
|
||||
"$Service$::Stub::Async$Method$(::grpc::ClientContext* context, "
|
||||
"$ns$$Service$::Stub::Async$Method$(::grpc::ClientContext* context, "
|
||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
||||
printer->Print(*vars,
|
||||
" return std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
|
||||
"$Request$, $Response$>>(new "
|
||||
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>("
|
||||
"channel(), cq, "
|
||||
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod($prefix$$Service$_method_names[$Idx$], "
|
||||
"::grpc::RpcMethod::RpcType::BIDI_STREAMING), "
|
||||
"context, tag));\n"
|
||||
"}\n\n");
|
||||
|
|
@ -492,7 +619,7 @@ void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer,
|
|||
grpc_cpp_generator::ClassName(method->output_type(), true);
|
||||
if (NoStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"::grpc::Status $Service$::Service::$Method$("
|
||||
"::grpc::Status $ns$$Service$::Service::$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"const $Request$* request, $Response$* response) {\n");
|
||||
printer->Print(
|
||||
|
|
@ -501,7 +628,7 @@ void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer,
|
|||
printer->Print("}\n\n");
|
||||
} else if (ClientOnlyStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"::grpc::Status $Service$::Service::$Method$("
|
||||
"::grpc::Status $ns$$Service$::Service::$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerReader< $Request$>* reader, "
|
||||
"$Response$* response) {\n");
|
||||
|
|
@ -511,7 +638,7 @@ void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer,
|
|||
printer->Print("}\n\n");
|
||||
} else if (ServerOnlyStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"::grpc::Status $Service$::Service::$Method$("
|
||||
"::grpc::Status $ns$$Service$::Service::$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"const $Request$* request, "
|
||||
"::grpc::ServerWriter< $Response$>* writer) {\n");
|
||||
|
|
@ -521,7 +648,7 @@ void PrintSourceServerMethod(grpc::protobuf::io::Printer *printer,
|
|||
printer->Print("}\n\n");
|
||||
} else if (BidiStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"::grpc::Status $Service$::Service::$Method$("
|
||||
"::grpc::Status $ns$$Service$::Service::$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerReaderWriter< $Response$, $Request$>* "
|
||||
"stream) {\n");
|
||||
|
|
@ -543,7 +670,7 @@ void PrintSourceServerAsyncMethod(
|
|||
grpc_cpp_generator::ClassName(method->output_type(), true);
|
||||
if (NoStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"void $Service$::AsyncService::Request$Method$("
|
||||
"void $ns$$Service$::AsyncService::Request$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"$Request$* request, "
|
||||
"::grpc::ServerAsyncResponseWriter< $Response$>* response, "
|
||||
|
|
@ -554,7 +681,7 @@ void PrintSourceServerAsyncMethod(
|
|||
printer->Print("}\n\n");
|
||||
} else if (ClientOnlyStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"void $Service$::AsyncService::Request$Method$("
|
||||
"void $ns$$Service$::AsyncService::Request$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
|
||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
||||
|
|
@ -564,7 +691,7 @@ void PrintSourceServerAsyncMethod(
|
|||
printer->Print("}\n\n");
|
||||
} else if (ServerOnlyStreaming(method)) {
|
||||
printer->Print(*vars,
|
||||
"void $Service$::AsyncService::Request$Method$("
|
||||
"void $ns$$Service$::AsyncService::Request$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"$Request$* request, "
|
||||
"::grpc::ServerAsyncWriter< $Response$>* writer, "
|
||||
|
|
@ -576,7 +703,7 @@ void PrintSourceServerAsyncMethod(
|
|||
} else if (BidiStreaming(method)) {
|
||||
printer->Print(
|
||||
*vars,
|
||||
"void $Service$::AsyncService::Request$Method$("
|
||||
"void $ns$$Service$::AsyncService::Request$Method$("
|
||||
"::grpc::ServerContext* context, "
|
||||
"::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
|
||||
"::grpc::CompletionQueue* cq, void *tag) {\n");
|
||||
|
|
@ -592,7 +719,7 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer,
|
|||
std::map<grpc::string, grpc::string> *vars) {
|
||||
(*vars)["Service"] = service->name();
|
||||
|
||||
printer->Print(*vars, "static const char* $Service$_method_names[] = {\n");
|
||||
printer->Print(*vars, "static const char* $prefix$$Service$_method_names[] = {\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
(*vars)["Method"] = service->method(i)->name();
|
||||
printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
|
||||
|
|
@ -601,9 +728,9 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer,
|
|||
|
||||
printer->Print(
|
||||
*vars,
|
||||
"std::unique_ptr< $Service$::Stub> $Service$::NewStub("
|
||||
"std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
|
||||
"const std::shared_ptr< ::grpc::ChannelInterface>& channel) {\n"
|
||||
" std::unique_ptr< $Service$::Stub> stub(new $Service$::Stub());\n"
|
||||
" std::unique_ptr< $ns$$Service$::Stub> stub(new $ns$$Service$::Stub());\n"
|
||||
" stub->set_channel(channel);\n"
|
||||
" return stub;\n"
|
||||
"}\n\n");
|
||||
|
|
@ -615,12 +742,12 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer,
|
|||
(*vars)["MethodCount"] = as_string(service->method_count());
|
||||
printer->Print(
|
||||
*vars,
|
||||
"$Service$::AsyncService::AsyncService(::grpc::CompletionQueue* cq) : "
|
||||
"::grpc::AsynchronousService(cq, $Service$_method_names, $MethodCount$) "
|
||||
"$ns$$Service$::AsyncService::AsyncService(::grpc::CompletionQueue* cq) : "
|
||||
"::grpc::AsynchronousService(cq, $prefix$$Service$_method_names, $MethodCount$) "
|
||||
"{}\n\n");
|
||||
|
||||
printer->Print(*vars,
|
||||
"$Service$::Service::~Service() {\n"
|
||||
"$ns$$Service$::Service::~Service() {\n"
|
||||
" delete service_;\n"
|
||||
"}\n\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
|
|
@ -629,7 +756,7 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer,
|
|||
PrintSourceServerAsyncMethod(printer, service->method(i), vars);
|
||||
}
|
||||
printer->Print(*vars,
|
||||
"::grpc::RpcService* $Service$::Service::service() {\n");
|
||||
"::grpc::RpcService* $ns$$Service$::Service::service() {\n");
|
||||
printer->Indent();
|
||||
printer->Print(
|
||||
"if (service_ != nullptr) {\n"
|
||||
|
|
@ -648,52 +775,52 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer,
|
|||
printer->Print(
|
||||
*vars,
|
||||
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
|
||||
" $Service$_method_names[$Idx$],\n"
|
||||
" $prefix$$Service$_method_names[$Idx$],\n"
|
||||
" ::grpc::RpcMethod::NORMAL_RPC,\n"
|
||||
" new ::grpc::RpcMethodHandler< $Service$::Service, $Request$, "
|
||||
" new ::grpc::RpcMethodHandler< $ns$$Service$::Service, $Request$, "
|
||||
"$Response$>(\n"
|
||||
" std::function< ::grpc::Status($Service$::Service*, "
|
||||
" std::function< ::grpc::Status($ns$$Service$::Service*, "
|
||||
"::grpc::ServerContext*, const $Request$*, $Response$*)>("
|
||||
"&$Service$::Service::$Method$), this),\n"
|
||||
"&$ns$$Service$::Service::$Method$), this),\n"
|
||||
" new $Request$, new $Response$));\n");
|
||||
} else if (ClientOnlyStreaming(method)) {
|
||||
printer->Print(
|
||||
*vars,
|
||||
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
|
||||
" $Service$_method_names[$Idx$],\n"
|
||||
" $prefix$$Service$_method_names[$Idx$],\n"
|
||||
" ::grpc::RpcMethod::CLIENT_STREAMING,\n"
|
||||
" new ::grpc::ClientStreamingHandler< "
|
||||
"$Service$::Service, $Request$, $Response$>(\n"
|
||||
" std::function< ::grpc::Status($Service$::Service*, "
|
||||
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
||||
" std::function< ::grpc::Status($ns$$Service$::Service*, "
|
||||
"::grpc::ServerContext*, "
|
||||
"::grpc::ServerReader< $Request$>*, $Response$*)>("
|
||||
"&$Service$::Service::$Method$), this),\n"
|
||||
"&$ns$$Service$::Service::$Method$), this),\n"
|
||||
" new $Request$, new $Response$));\n");
|
||||
} else if (ServerOnlyStreaming(method)) {
|
||||
printer->Print(
|
||||
*vars,
|
||||
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
|
||||
" $Service$_method_names[$Idx$],\n"
|
||||
" $prefix$$Service$_method_names[$Idx$],\n"
|
||||
" ::grpc::RpcMethod::SERVER_STREAMING,\n"
|
||||
" new ::grpc::ServerStreamingHandler< "
|
||||
"$Service$::Service, $Request$, $Response$>(\n"
|
||||
" std::function< ::grpc::Status($Service$::Service*, "
|
||||
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
||||
" std::function< ::grpc::Status($ns$$Service$::Service*, "
|
||||
"::grpc::ServerContext*, "
|
||||
"const $Request$*, ::grpc::ServerWriter< $Response$>*)>("
|
||||
"&$Service$::Service::$Method$), this),\n"
|
||||
"&$ns$$Service$::Service::$Method$), this),\n"
|
||||
" new $Request$, new $Response$));\n");
|
||||
} else if (BidiStreaming(method)) {
|
||||
printer->Print(
|
||||
*vars,
|
||||
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
|
||||
" $Service$_method_names[$Idx$],\n"
|
||||
" $prefix$$Service$_method_names[$Idx$],\n"
|
||||
" ::grpc::RpcMethod::BIDI_STREAMING,\n"
|
||||
" new ::grpc::BidiStreamingHandler< "
|
||||
"$Service$::Service, $Request$, $Response$>(\n"
|
||||
" std::function< ::grpc::Status($Service$::Service*, "
|
||||
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
||||
" std::function< ::grpc::Status($ns$$Service$::Service*, "
|
||||
"::grpc::ServerContext*, "
|
||||
"::grpc::ServerReaderWriter< $Response$, $Request$>*)>("
|
||||
"&$Service$::Service::$Method$), this),\n"
|
||||
"&$ns$$Service$::Service::$Method$), this),\n"
|
||||
" new $Request$, new $Response$));\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -702,7 +829,8 @@ void PrintSourceService(grpc::protobuf::io::Printer *printer,
|
|||
printer->Print("}\n\n");
|
||||
}
|
||||
|
||||
grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file) {
|
||||
grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms) {
|
||||
grpc::string output;
|
||||
grpc::protobuf::io::StringOutputStream output_stream(&output);
|
||||
grpc::protobuf::io::Printer printer(&output_stream, '$');
|
||||
|
|
@ -713,6 +841,13 @@ grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file) {
|
|||
if (!file->package().empty()) {
|
||||
vars["Package"].append(".");
|
||||
}
|
||||
if (!params.services_namespace.empty()) {
|
||||
vars["ns"] = params.services_namespace + "::";
|
||||
vars["prefix"] = params.services_namespace;
|
||||
} else {
|
||||
vars["ns"] = "";
|
||||
vars["prefix"] = "";
|
||||
}
|
||||
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
PrintSourceService(&printer, file->service(i), &vars);
|
||||
|
|
@ -721,4 +856,22 @@ grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file) {
|
|||
return output;
|
||||
}
|
||||
|
||||
grpc::string GetSourceEpilogue(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms) {
|
||||
grpc::string temp;
|
||||
|
||||
std::vector<grpc::string> parts =
|
||||
grpc_generator::tokenize(file->package(), ".");
|
||||
|
||||
for (auto part = parts.begin(); part != parts.end(); part++) {
|
||||
temp.append("} // namespace ");
|
||||
temp.append(*part);
|
||||
temp.append("\n");
|
||||
}
|
||||
|
||||
temp.append("\n");
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
} // namespace grpc_cpp_generator
|
||||
|
|
|
|||
|
|
@ -38,17 +38,43 @@
|
|||
|
||||
namespace grpc_cpp_generator {
|
||||
|
||||
// Contains all the parameters that are parsed from the command line.
|
||||
struct Parameters {
|
||||
// Puts the service into a namespace
|
||||
grpc::string services_namespace;
|
||||
};
|
||||
|
||||
// Return the prologue of the generated header file.
|
||||
grpc::string GetHeaderPrologue(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the includes needed for generated header file.
|
||||
grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file);
|
||||
grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the includes needed for generated source file.
|
||||
grpc::string GetSourceIncludes();
|
||||
grpc::string GetSourceIncludes(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the epilogue of the generated header file.
|
||||
grpc::string GetHeaderEpilogue(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the prologue of the generated source file.
|
||||
grpc::string GetSourcePrologue(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the services for generated header file.
|
||||
grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file);
|
||||
grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the services for generated source file.
|
||||
grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file);
|
||||
grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the epilogue of the generated source file.
|
||||
grpc::string GetSourceEpilogue(const grpc::protobuf::FileDescriptor *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
} // namespace grpc_cpp_generator
|
||||
|
||||
|
|
|
|||
|
|
@ -58,18 +58,48 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
|
|||
return false;
|
||||
}
|
||||
|
||||
grpc_cpp_generator::Parameters generator_parameters;
|
||||
|
||||
if (!parameter.empty()) {
|
||||
std::vector<grpc::string> parameters_list =
|
||||
grpc_generator::tokenize(parameter, ",");
|
||||
for (auto parameter_string = parameters_list.begin();
|
||||
parameter_string != parameters_list.end();
|
||||
parameter_string++) {
|
||||
std::vector<grpc::string> param =
|
||||
grpc_generator::tokenize(*parameter_string, "=");
|
||||
if (param[0] == "services_namespace") {
|
||||
generator_parameters.services_namespace = param[1];
|
||||
} else {
|
||||
*error = grpc::string("Unknown parameter: ") + *parameter_string;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grpc::string file_name = grpc_generator::StripProto(file->name());
|
||||
|
||||
// Generate .pb.h
|
||||
Insert(context, file_name + ".pb.h", "includes",
|
||||
grpc_cpp_generator::GetHeaderIncludes(file));
|
||||
Insert(context, file_name + ".pb.h", "namespace_scope",
|
||||
grpc_cpp_generator::GetHeaderServices(file));
|
||||
// Generate .pb.cc
|
||||
Insert(context, file_name + ".pb.cc", "includes",
|
||||
grpc_cpp_generator::GetSourceIncludes());
|
||||
Insert(context, file_name + ".pb.cc", "namespace_scope",
|
||||
grpc_cpp_generator::GetSourceServices(file));
|
||||
grpc::string header_code =
|
||||
grpc_cpp_generator::GetHeaderPrologue(file, generator_parameters) +
|
||||
grpc_cpp_generator::GetHeaderIncludes(file, generator_parameters) +
|
||||
grpc_cpp_generator::GetHeaderServices(file, generator_parameters) +
|
||||
grpc_cpp_generator::GetHeaderEpilogue(file, generator_parameters);
|
||||
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> header_output(
|
||||
context->Open(file_name + ".grpc.pb.h"));
|
||||
grpc::protobuf::io::CodedOutputStream header_coded_out(
|
||||
header_output.get());
|
||||
header_coded_out.WriteRaw(header_code.data(), header_code.size());
|
||||
|
||||
grpc::string source_code =
|
||||
grpc_cpp_generator::GetSourcePrologue(file, generator_parameters) +
|
||||
grpc_cpp_generator::GetSourceIncludes(file, generator_parameters) +
|
||||
grpc_cpp_generator::GetSourceServices(file, generator_parameters) +
|
||||
grpc_cpp_generator::GetSourceEpilogue(file, generator_parameters);
|
||||
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> source_output(
|
||||
context->Open(file_name + ".grpc.pb.cc"));
|
||||
grpc::protobuf::io::CodedOutputStream source_coded_out(
|
||||
source_output.get());
|
||||
source_coded_out.WriteRaw(source_code.data(), source_code.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,47 @@ inline grpc::string StringReplace(grpc::string str, const grpc::string &from,
|
|||
return str;
|
||||
}
|
||||
|
||||
inline std::vector<grpc::string> tokenize(const grpc::string &input,
|
||||
const grpc::string &delimiters) {
|
||||
std::vector<grpc::string> tokens;
|
||||
size_t pos, last_pos = 0;
|
||||
|
||||
for (;;) {
|
||||
bool done = false;
|
||||
pos = input.find_first_of(delimiters, last_pos);
|
||||
if (pos == grpc::string::npos) {
|
||||
done = true;
|
||||
pos = input.length();
|
||||
}
|
||||
|
||||
tokens.push_back(input.substr(last_pos, pos - last_pos));
|
||||
if (done) return tokens;
|
||||
|
||||
last_pos = pos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline grpc::string CapitalizeFirstLetter(grpc::string s) {
|
||||
if (s.empty()) {
|
||||
return s;
|
||||
}
|
||||
s[0] = ::toupper(s[0]);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline grpc::string LowerUnderscoreToUpperCamel(grpc::string str) {
|
||||
std::vector<grpc::string> tokens = tokenize(str, "_");
|
||||
grpc::string result = "";
|
||||
for (unsigned int i = 0; i < tokens.size(); i++) {
|
||||
result += CapitalizeFirstLetter(tokens[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *file) {
|
||||
return LowerUnderscoreToUpperCamel(StripProto(file->name()));
|
||||
}
|
||||
|
||||
} // namespace grpc_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H
|
||||
|
|
|
|||
|
|
@ -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 <map>
|
||||
|
||||
#include "src/compiler/objective_c_generator.h"
|
||||
#include "src/compiler/objective_c_generator_helpers.h"
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace grpc_objective_c_generator {
|
||||
namespace {
|
||||
|
||||
void PrintSimpleBlockSignature(grpc::protobuf::io::Printer *printer,
|
||||
const grpc::protobuf::MethodDescriptor *method,
|
||||
std::map<grpc::string, grpc::string> *vars) {
|
||||
(*vars)["method_name"] = method->name();
|
||||
(*vars)["request_type"] = PrefixedName(method->input_type()->name());
|
||||
(*vars)["response_type"] = PrefixedName(method->output_type()->name());
|
||||
|
||||
if (method->server_streaming()) {
|
||||
printer->Print("// When the response stream finishes, the handler is "
|
||||
"called with nil for both arguments.\n\n");
|
||||
} else {
|
||||
printer->Print("// The handler is only called once.\n\n");
|
||||
}
|
||||
printer->Print(*vars, "- (id<GRXLiveSource>)$method_name$WithRequest:"
|
||||
"($request_type$)request completionHandler:(void(^)"
|
||||
"($response_type$ *, NSError *))handler");
|
||||
}
|
||||
|
||||
void PrintSimpleDelegateSignature(grpc::protobuf::io::Printer *printer,
|
||||
const grpc::protobuf::MethodDescriptor *method,
|
||||
std::map<grpc::string, grpc::string> *vars) {
|
||||
(*vars)["method_name"] = method->name();
|
||||
(*vars)["request_type"] = PrefixedName(method->input_type()->name());
|
||||
|
||||
printer->Print(*vars, "- (id<GRXLiveSource>)$method_name$WithRequest:"
|
||||
"($request_type$)request delegate:(id<GRXSink>)delegate");
|
||||
}
|
||||
|
||||
void PrintAdvancedSignature(grpc::protobuf::io::Printer *printer,
|
||||
const grpc::protobuf::MethodDescriptor *method,
|
||||
std::map<grpc::string, grpc::string> *vars) {
|
||||
(*vars)["method_name"] = method->name();
|
||||
printer->Print(*vars, "- (GRXSource *)$method_name$WithRequest:"
|
||||
"(id<GRXSource>)request");
|
||||
}
|
||||
|
||||
void PrintSourceMethodSimpleBlock(grpc::protobuf::io::Printer *printer,
|
||||
const grpc::protobuf::MethodDescriptor *method,
|
||||
std::map<grpc::string, grpc::string> *vars) {
|
||||
PrintSimpleBlockSignature(printer, method, vars);
|
||||
|
||||
(*vars)["method_name"] = method->name();
|
||||
printer->Print(" {\n");
|
||||
printer->Indent();
|
||||
printer->Print(*vars, "return [[self $method_name$WithRequest:request] "
|
||||
"connectHandler:^(id value, NSError *error) {\n");
|
||||
printer->Indent();
|
||||
printer->Print("handler(value, error);\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}];\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void PrintSourceMethodSimpleDelegate(grpc::protobuf::io::Printer *printer,
|
||||
const grpc::protobuf::MethodDescriptor *method,
|
||||
std::map<grpc::string, grpc::string> *vars) {
|
||||
PrintSimpleDelegateSignature(printer, method, vars);
|
||||
|
||||
(*vars)["method_name"] = method->name();
|
||||
printer->Print(" {\n");
|
||||
printer->Indent();
|
||||
printer->Print(*vars, "return [[self $method_name$WithRequest:request]"
|
||||
"connectToSink:delegate];\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void PrintSourceMethodAdvanced(grpc::protobuf::io::Printer *printer,
|
||||
const grpc::protobuf::MethodDescriptor *method,
|
||||
std::map<grpc::string, grpc::string> *vars) {
|
||||
PrintAdvancedSignature(printer, method, vars);
|
||||
|
||||
(*vars)["method_name"] = method->name();
|
||||
printer->Print(" {\n");
|
||||
printer->Indent();
|
||||
printer->Print(*vars, "return [self $method_name$WithRequest:request "
|
||||
"client:[self newClient]];\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void PrintSourceMethodHandler(grpc::protobuf::io::Printer *printer,
|
||||
const grpc::protobuf::MethodDescriptor *method,
|
||||
std::map<grpc::string, grpc::string> *vars) {
|
||||
(*vars)["method_name"] = method->name();
|
||||
(*vars)["response_type"] = PrefixedName(method->output_type()->name());
|
||||
(*vars)["caps_name"] = grpc_generator::CapitalizeFirstLetter(method->name());
|
||||
|
||||
printer->Print(*vars, "- (GRXSource *)$method_name$WithRequest:"
|
||||
"(id<GRXSource>)request client:(PBgRPCClient *)client {\n");
|
||||
printer->Indent();
|
||||
printer->Print(*vars,
|
||||
"return [self responseWithMethod:$@\"$caps_name\"\n");
|
||||
printer->Print(*vars,
|
||||
" class:[$response_type$ class]\n");
|
||||
printer->Print(" request:request\n");
|
||||
printer->Print(" client:client];\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service,
|
||||
const grpc::string message_header) {
|
||||
grpc::string output;
|
||||
grpc::protobuf::io::StringOutputStream output_stream(&output);
|
||||
grpc::protobuf::io::Printer printer(&output_stream, '$');
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
printer.Print("#import \"PBgRPCClient.h\"\n");
|
||||
printer.Print("#import \"PBStub.h\"\n");
|
||||
vars["message_header"] = message_header;
|
||||
printer.Print(vars, "#import \"$message_header$\"\n\n");
|
||||
printer.Print("@protocol GRXSource\n");
|
||||
printer.Print("@class GRXSource\n\n");
|
||||
vars["service_name"] = service->name();
|
||||
printer.Print("@protocol $service_name$Stub <NSObject>\n\n");
|
||||
printer.Print("#pragma mark Simple block handlers\n\n");
|
||||
for (int i = 0; i < service->method_count(); i++) {
|
||||
PrintSimpleBlockSignature(&printer, service->method(i), &vars);
|
||||
printer.Print(";\n");
|
||||
}
|
||||
printer.Print("\n");
|
||||
printer.Print("#pragma mark Simple delegate handlers.\n\n");
|
||||
printer.Print("# TODO(jcanizales): Use high-level snippets to remove this duplication.");
|
||||
for (int i = 0; i < service->method_count(); i++) {
|
||||
PrintSimpleDelegateSignature(&printer, service->method(i), &vars);
|
||||
printer.Print(";\n");
|
||||
}
|
||||
printer.Print("\n");
|
||||
printer.Print("#pragma mark Advanced handlers.\n\n");
|
||||
for (int i = 0; i < service->method_count(); i++) {
|
||||
PrintAdvancedSignature(&printer, service->method(i), &vars);
|
||||
printer.Print(";\n");
|
||||
}
|
||||
printer.Print("\n");
|
||||
printer.Print("@end\n\n");
|
||||
printer.Print("// Basic stub that only does marshalling and parsing\n");
|
||||
printer.Print(vars, "@interface $service_name$Stub :"
|
||||
" PBStub<$service_name$Stub>\n");
|
||||
printer.Print("- (instancetype)initWithHost:(NSString *)host;\n");
|
||||
printer.Print("@end\n");
|
||||
return output;
|
||||
}
|
||||
|
||||
grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service) {
|
||||
grpc::string output;
|
||||
grpc::protobuf::io::StringOutputStream output_stream(&output);
|
||||
grpc::protobuf::io::Printer printer(&output_stream, '$');
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
vars["service_name"] = service->name();
|
||||
printer.Print(vars, "#import \"$service_name$Stub.pb.h\"\n");
|
||||
printer.Print("#import \"PBGeneratedMessage+GRXSource.h\"\n\n");
|
||||
vars["full_name"] = service->full_name();
|
||||
printer.Print(vars,
|
||||
"static NSString *const kInterface = @\"$full_name$\";\n");
|
||||
printer.Print("@implementation $service_name$Stub\n\n");
|
||||
printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
|
||||
printer.Indent();
|
||||
printer.Print("if ((self = [super initWithHost:host "
|
||||
"interface:kInterface])) {\n");
|
||||
printer.Print("}\n");
|
||||
printer.Print("return self;\n");
|
||||
printer.Outdent();
|
||||
printer.Print("}\n\n");
|
||||
printer.Print("#pragma mark Simple block handlers.\n");
|
||||
for (int i = 0; i < service->method_count(); i++) {
|
||||
PrintSourceMethodSimpleBlock(&printer, service->method(i), &vars);
|
||||
}
|
||||
printer.Print("\n");
|
||||
printer.Print("#pragma mark Simple delegate handlers.\n");
|
||||
for (int i = 0; i < service->method_count(); i++) {
|
||||
PrintSourceMethodSimpleDelegate(&printer, service->method(i), &vars);
|
||||
}
|
||||
printer.Print("\n");
|
||||
printer.Print("#pragma mark Advanced handlers.\n");
|
||||
for (int i = 0; i < service->method_count(); i++) {
|
||||
PrintSourceMethodAdvanced(&printer, service->method(i), &vars);
|
||||
}
|
||||
printer.Print("\n");
|
||||
printer.Print("#pragma mark Handlers for subclasses "
|
||||
"(stub wrappers) to override.\n");
|
||||
for (int i = 0; i < service->method_count(); i++) {
|
||||
PrintSourceMethodHandler(&printer, service->method(i), &vars);
|
||||
}
|
||||
printer.Print("@end\n");
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace grpc_objective_c_generator
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H
|
||||
#define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
|
||||
namespace grpc_objective_c_generator {
|
||||
|
||||
grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service,
|
||||
const grpc::string message_header);
|
||||
|
||||
grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service);
|
||||
|
||||
} // namespace grpc_objective_c_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H
|
||||
40
src/php/ext/grpc/completion_queue.h → src/compiler/objective_c_generator_helpers.h
Executable file → Normal file
40
src/php/ext/grpc/completion_queue.h → src/compiler/objective_c_generator_helpers.h
Executable file → Normal file
|
|
@ -31,32 +31,28 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef NET_GRPC_PHP_GRPC_COMPLETION_QUEUE_H_
|
||||
#define NET_GRPC_PHP_GRPC_COMPLETION_QUEUE_H_
|
||||
#ifndef GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H
|
||||
#define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <map>
|
||||
#include "src/compiler/config.h"
|
||||
#include "src/compiler/generator_helpers.h"
|
||||
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_grpc.h"
|
||||
namespace grpc_objective_c_generator {
|
||||
|
||||
#include "grpc/grpc.h"
|
||||
const grpc::string prefix = "PBG";
|
||||
|
||||
/* Class entry for the PHP CompletionQueue class */
|
||||
extern zend_class_entry *grpc_ce_completion_queue;
|
||||
inline grpc::string MessageHeaderName(const grpc::protobuf::FileDescriptor *file) {
|
||||
return grpc_generator::FileNameInUpperCamel(file) + ".pb.h";
|
||||
}
|
||||
|
||||
/* Wrapper class for grpc_completion_queue that can be associated with a
|
||||
PHP object */
|
||||
typedef struct wrapped_grpc_completion_queue {
|
||||
zend_object std;
|
||||
inline grpc::string StubFileName(grpc::string service_name) {
|
||||
return prefix + service_name + "Stub";
|
||||
}
|
||||
|
||||
grpc_completion_queue *wrapped;
|
||||
} wrapped_grpc_completion_queue;
|
||||
inline grpc::string PrefixedName(grpc::string name) {
|
||||
return prefix + name;
|
||||
}
|
||||
|
||||
/* Initialize the CompletionQueue class */
|
||||
void grpc_init_completion_queue(TSRMLS_D);
|
||||
|
||||
#endif /* NET_GRPC_PHP_GRPC_COMPLETION_QUEUE_H_ */
|
||||
}
|
||||
#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// Generates Objective C gRPC service interface out of Protobuf IDL.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
#include "src/compiler/objective_c_generator.h"
|
||||
#include "src/compiler/objective_c_generator_helpers.h"
|
||||
|
||||
class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
|
||||
public:
|
||||
ObjectiveCGrpcGenerator() {}
|
||||
virtual ~ObjectiveCGrpcGenerator() {}
|
||||
|
||||
virtual bool Generate(const grpc::protobuf::FileDescriptor *file,
|
||||
const grpc::string ¶meter,
|
||||
grpc::protobuf::compiler::GeneratorContext *context,
|
||||
grpc::string *error) const {
|
||||
|
||||
if (file->service_count() == 0) {
|
||||
// No services. Do nothing.
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < file->service_count(); i++) {
|
||||
const grpc::protobuf::ServiceDescriptor *service = file->service(i);
|
||||
grpc::string file_name = grpc_objective_c_generator::StubFileName(
|
||||
service->name());
|
||||
|
||||
// Generate .pb.h
|
||||
grpc::string header_code = grpc_objective_c_generator::GetHeader(
|
||||
service, grpc_objective_c_generator::MessageHeaderName(file));
|
||||
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> header_output(
|
||||
context->Open(file_name + ".pb.h"));
|
||||
grpc::protobuf::io::CodedOutputStream header_coded_out(
|
||||
header_output.get());
|
||||
header_coded_out.WriteRaw(header_code.data(), header_code.size());
|
||||
|
||||
// Generate .pb.m
|
||||
grpc::string source_code = grpc_objective_c_generator::GetSource(service);
|
||||
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> source_output(
|
||||
context->Open(file_name + ".pb.m"));
|
||||
grpc::protobuf::io::CodedOutputStream source_coded_out(
|
||||
source_output.get());
|
||||
source_coded_out.WriteRaw(source_code.data(), source_code.size());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Insert the given code into the given file at the given insertion point.
|
||||
void Insert(grpc::protobuf::compiler::GeneratorContext *context,
|
||||
const grpc::string &filename, const grpc::string &insertion_point,
|
||||
const grpc::string &code) const {
|
||||
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
|
||||
context->OpenForInsert(filename, insertion_point));
|
||||
grpc::protobuf::io::CodedOutputStream coded_out(output.get());
|
||||
coded_out.WriteRaw(code.data(), code.size());
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ObjectiveCGrpcGenerator generator;
|
||||
return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
|
||||
}
|
||||
|
|
@ -271,7 +271,7 @@ bool GetModuleAndMessagePath(const Descriptor* type,
|
|||
bool PrintServerFactory(const grpc::string& package_qualified_service_name,
|
||||
const ServiceDescriptor* service, Printer* out) {
|
||||
out->Print("def early_adopter_create_$Service$_server(servicer, port, "
|
||||
"root_certificates, key_chain_pairs):\n",
|
||||
"private_key=None, certificate_chain=None):\n",
|
||||
"Service", service->name());
|
||||
{
|
||||
IndentScope raii_create_server_indent(out);
|
||||
|
|
@ -309,17 +309,20 @@ bool PrintServerFactory(const grpc::string& package_qualified_service_name,
|
|||
make_pair(method->name(), output_message_module_and_class));
|
||||
}
|
||||
out->Print("method_service_descriptions = {\n");
|
||||
for (auto& name_and_description_constructor :
|
||||
method_description_constructors) {
|
||||
for (auto name_and_description_constructor =
|
||||
method_description_constructors.begin();
|
||||
name_and_description_constructor !=
|
||||
method_description_constructors.end();
|
||||
name_and_description_constructor++) {
|
||||
IndentScope raii_descriptions_indent(out);
|
||||
const grpc::string method_name = name_and_description_constructor.first;
|
||||
const grpc::string method_name = name_and_description_constructor->first;
|
||||
auto input_message_module_and_class =
|
||||
input_message_modules_and_classes.find(method_name);
|
||||
auto output_message_module_and_class =
|
||||
output_message_modules_and_classes.find(method_name);
|
||||
out->Print("\"$Method$\": utilities.$Constructor$(\n", "Method",
|
||||
method_name, "Constructor",
|
||||
name_and_description_constructor.second);
|
||||
name_and_description_constructor->second);
|
||||
{
|
||||
IndentScope raii_description_arguments_indent(out);
|
||||
out->Print("servicer.$Method$,\n", "Method", method_name);
|
||||
|
|
@ -336,10 +339,10 @@ bool PrintServerFactory(const grpc::string& package_qualified_service_name,
|
|||
}
|
||||
out->Print("}\n");
|
||||
out->Print(
|
||||
"return implementations.secure_server("
|
||||
"return implementations.server("
|
||||
"\"$PackageQualifiedServiceName$\","
|
||||
" method_service_descriptions, port, root_certificates,"
|
||||
" key_chain_pairs)\n",
|
||||
" method_service_descriptions, port, private_key=private_key,"
|
||||
" certificate_chain=certificate_chain)\n",
|
||||
"PackageQualifiedServiceName", package_qualified_service_name);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -350,7 +353,10 @@ bool PrintStubFactory(const grpc::string& package_qualified_service_name,
|
|||
map<grpc::string, grpc::string> dict = ListToDict({
|
||||
"Service", service->name(),
|
||||
});
|
||||
out->Print(dict, "def early_adopter_create_$Service$_stub(host, port):\n");
|
||||
out->Print(dict, "def early_adopter_create_$Service$_stub(host, port,"
|
||||
" metadata_transformer=None,"
|
||||
" secure=False, root_certificates=None, private_key=None,"
|
||||
" certificate_chain=None, server_host_override=None):\n");
|
||||
{
|
||||
IndentScope raii_create_server_indent(out);
|
||||
map<grpc::string, grpc::string> method_description_constructors;
|
||||
|
|
@ -387,17 +393,20 @@ bool PrintStubFactory(const grpc::string& package_qualified_service_name,
|
|||
make_pair(method->name(), output_message_module_and_class));
|
||||
}
|
||||
out->Print("method_invocation_descriptions = {\n");
|
||||
for (auto& name_and_description_constructor :
|
||||
method_description_constructors) {
|
||||
for (auto name_and_description_constructor =
|
||||
method_description_constructors.begin();
|
||||
name_and_description_constructor !=
|
||||
method_description_constructors.end();
|
||||
name_and_description_constructor++) {
|
||||
IndentScope raii_descriptions_indent(out);
|
||||
const grpc::string method_name = name_and_description_constructor.first;
|
||||
const grpc::string method_name = name_and_description_constructor->first;
|
||||
auto input_message_module_and_class =
|
||||
input_message_modules_and_classes.find(method_name);
|
||||
auto output_message_module_and_class =
|
||||
output_message_modules_and_classes.find(method_name);
|
||||
out->Print("\"$Method$\": utilities.$Constructor$(\n", "Method",
|
||||
method_name, "Constructor",
|
||||
name_and_description_constructor.second);
|
||||
name_and_description_constructor->second);
|
||||
{
|
||||
IndentScope raii_description_arguments_indent(out);
|
||||
out->Print(
|
||||
|
|
@ -413,9 +422,13 @@ bool PrintStubFactory(const grpc::string& package_qualified_service_name,
|
|||
}
|
||||
out->Print("}\n");
|
||||
out->Print(
|
||||
"return implementations.insecure_stub("
|
||||
"return implementations.stub("
|
||||
"\"$PackageQualifiedServiceName$\","
|
||||
" method_invocation_descriptions, host, port)\n",
|
||||
" method_invocation_descriptions, host, port,"
|
||||
" metadata_transformer=metadata_transformer, secure=secure,"
|
||||
" root_certificates=root_certificates, private_key=private_key,"
|
||||
" certificate_chain=certificate_chain,"
|
||||
" server_host_override=server_host_override)\n",
|
||||
"PackageQualifiedServiceName", package_qualified_service_name);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -189,7 +189,8 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
|
|||
/* translate host to :authority since :authority may be
|
||||
omitted */
|
||||
grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
|
||||
channeld->mdctx, channeld->authority_key, op->data.metadata->value);
|
||||
channeld->mdctx, grpc_mdstr_ref(channeld->authority_key),
|
||||
grpc_mdstr_ref(op->data.metadata->value));
|
||||
grpc_mdelem_unref(op->data.metadata);
|
||||
op->data.metadata = authority;
|
||||
/* pass the event up */
|
||||
|
|
|
|||
|
|
@ -177,6 +177,8 @@ static int addbyte(grpc_httpcli_parser *parser, gpr_uint8 byte) {
|
|||
}
|
||||
gpr_log(GPR_ERROR, "should never reach here");
|
||||
abort();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void grpc_httpcli_parser_init(grpc_httpcli_parser *parser) {
|
||||
|
|
|
|||
|
|
@ -52,10 +52,11 @@ static OVERLAPPED g_iocp_custom_overlap;
|
|||
|
||||
static gpr_event g_shutdown_iocp;
|
||||
static gpr_event g_iocp_done;
|
||||
static gpr_atm g_orphans = 0;
|
||||
|
||||
static HANDLE g_iocp;
|
||||
|
||||
static int do_iocp_work() {
|
||||
static void do_iocp_work() {
|
||||
BOOL success;
|
||||
DWORD bytes = 0;
|
||||
DWORD flags = 0;
|
||||
|
|
@ -71,14 +72,14 @@ static int do_iocp_work() {
|
|||
gpr_time_to_millis(wait_time));
|
||||
if (!success && !overlapped) {
|
||||
/* The deadline got attained. */
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
GPR_ASSERT(completion_key && overlapped);
|
||||
if (overlapped == &g_iocp_custom_overlap) {
|
||||
if (completion_key == (ULONG_PTR) &g_iocp_kick_token) {
|
||||
/* We were awoken from a kick. */
|
||||
gpr_log(GPR_DEBUG, "do_iocp_work - got a kick");
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
gpr_log(GPR_ERROR, "Unknown custom completion key.");
|
||||
abort();
|
||||
|
|
@ -97,8 +98,13 @@ static int do_iocp_work() {
|
|||
}
|
||||
success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes,
|
||||
FALSE, &flags);
|
||||
gpr_log(GPR_DEBUG, "bytes: %u, flags: %u - op %s", bytes, flags,
|
||||
success ? "succeeded" : "failed");
|
||||
gpr_log(GPR_DEBUG, "bytes: %u, flags: %u - op %s %s", bytes, flags,
|
||||
success ? "succeeded" : "failed", socket->orphan ? "orphan" : "");
|
||||
if (socket->orphan) {
|
||||
grpc_winsocket_destroy(socket);
|
||||
gpr_atm_full_fetch_add(&g_orphans, -1);
|
||||
return;
|
||||
}
|
||||
info->bytes_transfered = bytes;
|
||||
info->wsa_error = success ? 0 : WSAGetLastError();
|
||||
GPR_ASSERT(overlapped == &info->overlapped);
|
||||
|
|
@ -113,12 +119,10 @@ static int do_iocp_work() {
|
|||
}
|
||||
gpr_mu_unlock(&socket->state_mu);
|
||||
if (f) f(opaque, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void iocp_loop(void *p) {
|
||||
while (!gpr_event_get(&g_shutdown_iocp)) {
|
||||
while (gpr_atm_acq_load(&g_orphans) || !gpr_event_get(&g_shutdown_iocp)) {
|
||||
grpc_maybe_call_delayed_callbacks(NULL, 1);
|
||||
do_iocp_work();
|
||||
}
|
||||
|
|
@ -138,13 +142,19 @@ void grpc_iocp_init(void) {
|
|||
gpr_thd_new(&id, iocp_loop, NULL, NULL);
|
||||
}
|
||||
|
||||
void grpc_iocp_shutdown(void) {
|
||||
void grpc_iocp_kick(void) {
|
||||
BOOL success;
|
||||
gpr_event_set(&g_shutdown_iocp, (void *)1);
|
||||
|
||||
success = PostQueuedCompletionStatus(g_iocp, 0,
|
||||
(ULONG_PTR) &g_iocp_kick_token,
|
||||
&g_iocp_custom_overlap);
|
||||
GPR_ASSERT(success);
|
||||
}
|
||||
|
||||
void grpc_iocp_shutdown(void) {
|
||||
BOOL success;
|
||||
gpr_event_set(&g_shutdown_iocp, (void *)1);
|
||||
grpc_iocp_kick();
|
||||
gpr_event_wait(&g_iocp_done, gpr_inf_future);
|
||||
success = CloseHandle(g_iocp);
|
||||
GPR_ASSERT(success);
|
||||
|
|
@ -166,6 +176,10 @@ void grpc_iocp_add_socket(grpc_winsocket *socket) {
|
|||
GPR_ASSERT(ret == g_iocp);
|
||||
}
|
||||
|
||||
void grpc_iocp_socket_orphan(grpc_winsocket *socket) {
|
||||
gpr_atm_full_fetch_add(&g_orphans, 1);
|
||||
}
|
||||
|
||||
static void socket_notify_on_iocp(grpc_winsocket *socket,
|
||||
void(*cb)(void *, int), void *opaque,
|
||||
grpc_winsocket_callback_info *info) {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
void grpc_iocp_init(void);
|
||||
void grpc_iocp_shutdown(void);
|
||||
void grpc_iocp_add_socket(grpc_winsocket *);
|
||||
void grpc_iocp_socket_orphan(grpc_winsocket *);
|
||||
|
||||
void grpc_socket_notify_on_write(grpc_winsocket *, void(*cb)(void *, int success),
|
||||
void *opaque);
|
||||
|
|
|
|||
|
|
@ -117,7 +117,16 @@ void grpc_iomgr_shutdown(void) {
|
|||
gpr_mu_lock(&g_mu);
|
||||
}
|
||||
if (g_refs) {
|
||||
if (gpr_cv_wait(&g_rcv, &g_mu, shutdown_deadline) && g_cbs_head == NULL) {
|
||||
int timeout = 0;
|
||||
gpr_timespec short_deadline = gpr_time_add(gpr_now(),
|
||||
gpr_time_from_millis(100));
|
||||
while (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) {
|
||||
if (gpr_time_cmp(gpr_now(), shutdown_deadline) > 0) {
|
||||
timeout = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (timeout) {
|
||||
gpr_log(GPR_DEBUG,
|
||||
"Failed to free %d iomgr objects before shutdown deadline: "
|
||||
"memory leaks are likely",
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ grpc_winsocket *grpc_winsocket_create(SOCKET socket) {
|
|||
return r;
|
||||
}
|
||||
|
||||
void shutdown_op(grpc_winsocket_callback_info *info) {
|
||||
static void shutdown_op(grpc_winsocket_callback_info *info) {
|
||||
if (!info->cb) return;
|
||||
grpc_iomgr_add_delayed_callback(info->cb, info->opaque, 0);
|
||||
}
|
||||
|
|
@ -68,8 +68,13 @@ void grpc_winsocket_shutdown(grpc_winsocket *socket) {
|
|||
|
||||
void grpc_winsocket_orphan(grpc_winsocket *socket) {
|
||||
gpr_log(GPR_DEBUG, "grpc_winsocket_orphan");
|
||||
grpc_iocp_socket_orphan(socket);
|
||||
socket->orphan = 1;
|
||||
grpc_iomgr_unref();
|
||||
closesocket(socket->socket);
|
||||
}
|
||||
|
||||
void grpc_winsocket_destroy(grpc_winsocket *socket) {
|
||||
gpr_mu_destroy(&socket->state_mu);
|
||||
gpr_free(socket);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,12 +57,13 @@ typedef struct grpc_winsocket_callback_info {
|
|||
typedef struct grpc_winsocket {
|
||||
SOCKET socket;
|
||||
|
||||
int added_to_iocp;
|
||||
|
||||
grpc_winsocket_callback_info write_info;
|
||||
grpc_winsocket_callback_info read_info;
|
||||
|
||||
gpr_mu state_mu;
|
||||
|
||||
int added_to_iocp;
|
||||
int orphan;
|
||||
} grpc_winsocket;
|
||||
|
||||
/* Create a wrapped windows handle.
|
||||
|
|
@ -71,5 +72,6 @@ grpc_winsocket *grpc_winsocket_create(SOCKET socket);
|
|||
|
||||
void grpc_winsocket_shutdown(grpc_winsocket *socket);
|
||||
void grpc_winsocket_orphan(grpc_winsocket *socket);
|
||||
void grpc_winsocket_destroy(grpc_winsocket *socket);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKET_WINDOWS_H */
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
|
|||
up when grpc_tcp_server_destroy is called. */
|
||||
int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned index);
|
||||
|
||||
void grpc_tcp_server_destroy(grpc_tcp_server *server);
|
||||
void grpc_tcp_server_destroy(grpc_tcp_server *server,
|
||||
void (*shutdown_done)(void *shutdown_done_arg),
|
||||
void *shutdown_done_arg);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H */
|
||||
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H */
|
||||
|
|
|
|||
|
|
@ -102,12 +102,18 @@ struct grpc_tcp_server {
|
|||
gpr_cv cv;
|
||||
|
||||
/* active port count: how many ports are actually still listening */
|
||||
int active_ports;
|
||||
size_t active_ports;
|
||||
/* destroyed port count: how many ports are completely destroyed */
|
||||
size_t destroyed_ports;
|
||||
|
||||
/* all listening ports */
|
||||
server_port *ports;
|
||||
size_t nports;
|
||||
size_t port_capacity;
|
||||
|
||||
/* shutdown callback */
|
||||
void (*shutdown_complete)(void *);
|
||||
void *shutdown_complete_arg;
|
||||
};
|
||||
|
||||
grpc_tcp_server *grpc_tcp_server_create(void) {
|
||||
|
|
@ -115,6 +121,7 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
|
|||
gpr_mu_init(&s->mu);
|
||||
gpr_cv_init(&s->cv);
|
||||
s->active_ports = 0;
|
||||
s->destroyed_ports = 0;
|
||||
s->cb = NULL;
|
||||
s->cb_arg = NULL;
|
||||
s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
|
||||
|
|
@ -123,29 +130,64 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
|
|||
return s;
|
||||
}
|
||||
|
||||
void grpc_tcp_server_destroy(grpc_tcp_server *s) {
|
||||
static void finish_shutdown(grpc_tcp_server *s) {
|
||||
s->shutdown_complete(s->shutdown_complete_arg);
|
||||
|
||||
gpr_mu_destroy(&s->mu);
|
||||
gpr_cv_destroy(&s->cv);
|
||||
|
||||
gpr_free(s->ports);
|
||||
gpr_free(s);
|
||||
}
|
||||
|
||||
static void destroyed_port(void *server, int success) {
|
||||
grpc_tcp_server *s = server;
|
||||
gpr_mu_lock(&s->mu);
|
||||
s->destroyed_ports++;
|
||||
if (s->destroyed_ports == s->nports) {
|
||||
gpr_mu_unlock(&s->mu);
|
||||
finish_shutdown(s);
|
||||
} else {
|
||||
gpr_mu_unlock(&s->mu);
|
||||
}
|
||||
}
|
||||
|
||||
static void dont_care_about_shutdown_completion(void *ignored) {}
|
||||
|
||||
void grpc_tcp_server_destroy(
|
||||
grpc_tcp_server *s, void (*shutdown_complete)(void *shutdown_complete_arg),
|
||||
void *shutdown_complete_arg) {
|
||||
size_t i;
|
||||
gpr_mu_lock(&s->mu);
|
||||
|
||||
s->shutdown_complete = shutdown_complete
|
||||
? shutdown_complete
|
||||
: dont_care_about_shutdown_completion;
|
||||
s->shutdown_complete_arg = shutdown_complete_arg;
|
||||
|
||||
/* shutdown all fd's */
|
||||
for (i = 0; i < s->nports; i++) {
|
||||
grpc_fd_shutdown(s->ports[i].emfd);
|
||||
}
|
||||
/* wait while that happens */
|
||||
/* TODO(ctiller): make this asynchronous also */
|
||||
while (s->active_ports) {
|
||||
gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
|
||||
}
|
||||
gpr_mu_unlock(&s->mu);
|
||||
|
||||
/* delete ALL the things */
|
||||
for (i = 0; i < s->nports; i++) {
|
||||
server_port *sp = &s->ports[i];
|
||||
if (sp->addr.sockaddr.sa_family == AF_UNIX) {
|
||||
unlink_if_unix_domain_socket(&sp->addr.un);
|
||||
if (s->nports) {
|
||||
for (i = 0; i < s->nports; i++) {
|
||||
server_port *sp = &s->ports[i];
|
||||
if (sp->addr.sockaddr.sa_family == AF_UNIX) {
|
||||
unlink_if_unix_domain_socket(&sp->addr.un);
|
||||
}
|
||||
grpc_fd_orphan(sp->emfd, destroyed_port, s);
|
||||
}
|
||||
grpc_fd_orphan(sp->emfd, NULL, NULL);
|
||||
} else {
|
||||
finish_shutdown(s);
|
||||
}
|
||||
gpr_free(s->ports);
|
||||
gpr_free(s);
|
||||
}
|
||||
|
||||
/* get max listen queue size on linux */
|
||||
|
|
|
|||
|
|
@ -92,7 +92,9 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
|
|||
return s;
|
||||
}
|
||||
|
||||
void grpc_tcp_server_destroy(grpc_tcp_server *s) {
|
||||
void grpc_tcp_server_destroy(grpc_tcp_server *s,
|
||||
void (*shutdown_done)(void *shutdown_done_arg),
|
||||
void *shutdown_done_arg) {
|
||||
size_t i;
|
||||
gpr_mu_lock(&s->mu);
|
||||
/* shutdown all fd's */
|
||||
|
|
@ -112,11 +114,15 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s) {
|
|||
}
|
||||
gpr_free(s->ports);
|
||||
gpr_free(s);
|
||||
|
||||
if (shutdown_done) {
|
||||
shutdown_done(shutdown_done_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare a recently-created socket for listening. */
|
||||
static int prepare_socket(SOCKET sock,
|
||||
const struct sockaddr *addr, int addr_len) {
|
||||
static int prepare_socket(SOCKET sock, const struct sockaddr *addr,
|
||||
int addr_len) {
|
||||
struct sockaddr_storage sockname_temp;
|
||||
socklen_t sockname_len;
|
||||
|
||||
|
|
@ -147,15 +153,15 @@ static int prepare_socket(SOCKET sock,
|
|||
}
|
||||
|
||||
sockname_len = sizeof(sockname_temp);
|
||||
if (getsockname(sock, (struct sockaddr *) &sockname_temp, &sockname_len)
|
||||
== SOCKET_ERROR) {
|
||||
if (getsockname(sock, (struct sockaddr *)&sockname_temp, &sockname_len) ==
|
||||
SOCKET_ERROR) {
|
||||
char *utf8_message = gpr_format_message(WSAGetLastError());
|
||||
gpr_log(GPR_ERROR, "getsockname: %s", utf8_message);
|
||||
gpr_free(utf8_message);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return grpc_sockaddr_get_port((struct sockaddr *) &sockname_temp);
|
||||
return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
|
||||
|
||||
error:
|
||||
if (sock != INVALID_SOCKET) closesocket(sock);
|
||||
|
|
@ -221,8 +227,7 @@ static void on_accept(void *arg, int success) {
|
|||
DWORD transfered_bytes = 0;
|
||||
DWORD flags;
|
||||
BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
|
||||
&transfered_bytes, FALSE,
|
||||
&flags);
|
||||
&transfered_bytes, FALSE, &flags);
|
||||
if (!wsa_success) {
|
||||
char *utf8_message = gpr_format_message(WSAGetLastError());
|
||||
gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message);
|
||||
|
|
@ -257,9 +262,9 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
|
|||
|
||||
if (sock == INVALID_SOCKET) return -1;
|
||||
|
||||
status = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
&guid, sizeof(guid), &AcceptEx, sizeof(AcceptEx),
|
||||
&ioctl_num_bytes, NULL, NULL);
|
||||
status =
|
||||
WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
|
||||
&AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL);
|
||||
|
||||
if (status != 0) {
|
||||
char *utf8_message = gpr_format_message(WSAGetLastError());
|
||||
|
|
@ -307,9 +312,8 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
|
|||
for (i = 0; i < s->nports; i++) {
|
||||
sockname_len = sizeof(sockname_temp);
|
||||
if (0 == getsockname(s->ports[i].socket->socket,
|
||||
(struct sockaddr *) &sockname_temp,
|
||||
&sockname_len)) {
|
||||
port = grpc_sockaddr_get_port((struct sockaddr *) &sockname_temp);
|
||||
(struct sockaddr *)&sockname_temp, &sockname_len)) {
|
||||
port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
|
||||
if (port > 0) {
|
||||
allocated_addr = malloc(addr_len);
|
||||
memcpy(allocated_addr, addr, addr_len);
|
||||
|
|
@ -330,7 +334,7 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
|
|||
if (grpc_sockaddr_is_wildcard(addr, &port)) {
|
||||
grpc_sockaddr_make_wildcard6(port, &wildcard);
|
||||
|
||||
addr = (struct sockaddr *) &wildcard;
|
||||
addr = (struct sockaddr *)&wildcard;
|
||||
addr_len = sizeof(wildcard);
|
||||
}
|
||||
|
||||
|
|
@ -369,4 +373,4 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollset,
|
|||
gpr_mu_unlock(&s->mu);
|
||||
}
|
||||
|
||||
#endif /* GPR_WINSOCK_SOCKET */
|
||||
#endif /* GPR_WINSOCK_SOCKET */
|
||||
|
|
|
|||
|
|
@ -85,10 +85,10 @@ static void on_secure_transport_setup_done(void *statep,
|
|||
if (status == GRPC_SECURITY_OK) {
|
||||
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);
|
||||
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. */
|
||||
|
|
@ -104,7 +104,8 @@ static void on_secure_transport_setup_done(void *statep,
|
|||
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);
|
||||
grpc_setup_secure_transport(state->ctx, tcp, on_secure_transport_setup_done,
|
||||
state);
|
||||
}
|
||||
|
||||
/* Server callback: start listening on our ports */
|
||||
|
|
@ -120,12 +121,14 @@ 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);
|
||||
grpc_tcp_server_destroy(state->tcp, grpc_server_listener_destroy_done,
|
||||
server);
|
||||
gpr_mu_unlock(&state->mu);
|
||||
state_unref(state);
|
||||
}
|
||||
|
||||
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) {
|
||||
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;
|
||||
|
|
@ -213,7 +216,7 @@ error:
|
|||
grpc_resolved_addresses_destroy(resolved);
|
||||
}
|
||||
if (tcp) {
|
||||
grpc_tcp_server_destroy(tcp);
|
||||
grpc_tcp_server_destroy(tcp, NULL, NULL);
|
||||
}
|
||||
if (state) {
|
||||
gpr_free(state);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Posix implementation for gpr threads. */
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
#include <grpc/support/thd.h>
|
||||
|
||||
enum {
|
||||
GPR_THD_JOINABLE = 1
|
||||
};
|
||||
|
||||
gpr_thd_options gpr_thd_options_default(void) {
|
||||
gpr_thd_options options;
|
||||
memset(&options, 0, sizeof(options));
|
||||
return options;
|
||||
}
|
||||
|
||||
void gpr_thd_options_set_detached(gpr_thd_options *options) {
|
||||
options->flags &= ~GPR_THD_JOINABLE;
|
||||
}
|
||||
|
||||
void gpr_thd_options_set_joinable(gpr_thd_options *options) {
|
||||
options->flags |= GPR_THD_JOINABLE;
|
||||
}
|
||||
|
||||
int gpr_thd_options_is_detached(const gpr_thd_options *options) {
|
||||
if (!options) return 1;
|
||||
return (options->flags & GPR_THD_JOINABLE) == 0;
|
||||
}
|
||||
|
||||
int gpr_thd_options_is_joinable(const gpr_thd_options *options) {
|
||||
if (!options) return 0;
|
||||
return (options->flags & GPR_THD_JOINABLE) == GPR_THD_JOINABLE;
|
||||
}
|
||||
|
|
@ -68,7 +68,11 @@ int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
|
|||
a->arg = arg;
|
||||
|
||||
GPR_ASSERT(pthread_attr_init(&attr) == 0);
|
||||
GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0);
|
||||
if (gpr_thd_options_is_detached(options)) {
|
||||
GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0);
|
||||
} else {
|
||||
GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) == 0);
|
||||
}
|
||||
thread_started = (pthread_create(&p, &attr, &thread_body, a) == 0);
|
||||
GPR_ASSERT(pthread_attr_destroy(&attr) == 0);
|
||||
if (!thread_started) {
|
||||
|
|
@ -78,14 +82,12 @@ int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
|
|||
return thread_started;
|
||||
}
|
||||
|
||||
gpr_thd_options gpr_thd_options_default(void) {
|
||||
gpr_thd_options options;
|
||||
memset(&options, 0, sizeof(options));
|
||||
return options;
|
||||
}
|
||||
|
||||
gpr_thd_id gpr_thd_currentid(void) {
|
||||
return (gpr_thd_id)pthread_self();
|
||||
}
|
||||
|
||||
void gpr_thd_join(gpr_thd_id t) {
|
||||
pthread_join((pthread_t)t, NULL);
|
||||
}
|
||||
|
||||
#endif /* GPR_POSIX_SYNC */
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/* Posix implementation for gpr threads. */
|
||||
/* Windows implementation for gpr threads. */
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
|
|
@ -40,47 +40,81 @@
|
|||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#include <grpc/support/alloc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpc/support/thd.h>
|
||||
|
||||
struct thd_arg {
|
||||
#if defined(_MSC_VER)
|
||||
#define thread_local __declspec(thread)
|
||||
#elif defined(__GNUC__)
|
||||
#define thread_local __thread
|
||||
#else
|
||||
#error "Unknown compiler - please file a bug report"
|
||||
#endif
|
||||
|
||||
struct thd_info {
|
||||
void (*body)(void *arg); /* body of a thread */
|
||||
void *arg; /* argument to a thread */
|
||||
HANDLE join_event; /* if joinable, the join event */
|
||||
int joinable; /* true if not detached */
|
||||
};
|
||||
|
||||
static thread_local struct thd_info *g_thd_info;
|
||||
|
||||
/* Destroys a thread info */
|
||||
static void destroy_thread(struct thd_info *t) {
|
||||
if (t->joinable) CloseHandle(t->join_event);
|
||||
gpr_free(t);
|
||||
}
|
||||
|
||||
/* Body of every thread started via gpr_thd_new. */
|
||||
static DWORD WINAPI thread_body(void *v) {
|
||||
struct thd_arg a = *(struct thd_arg *)v;
|
||||
gpr_free(v);
|
||||
(*a.body)(a.arg);
|
||||
g_thd_info = (struct thd_info *)v;
|
||||
g_thd_info->body(g_thd_info->arg);
|
||||
if (g_thd_info->joinable) {
|
||||
BOOL ret = SetEvent(g_thd_info->join_event);
|
||||
GPR_ASSERT(ret);
|
||||
} else {
|
||||
destroy_thread(g_thd_info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
|
||||
const gpr_thd_options *options) {
|
||||
HANDLE handle;
|
||||
DWORD thread_id;
|
||||
struct thd_arg *a = gpr_malloc(sizeof(*a));
|
||||
a->body = thd_body;
|
||||
a->arg = arg;
|
||||
struct thd_info *info = gpr_malloc(sizeof(*info));
|
||||
info->body = thd_body;
|
||||
info->arg = arg;
|
||||
*t = 0;
|
||||
handle = CreateThread(NULL, 64 * 1024, thread_body, a, 0, &thread_id);
|
||||
if (handle == NULL) {
|
||||
gpr_free(a);
|
||||
if (gpr_thd_options_is_joinable(options)) {
|
||||
info->joinable = 1;
|
||||
info->join_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (info->join_event == NULL) {
|
||||
gpr_free(info);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
CloseHandle(handle); /* threads are "detached" */
|
||||
info->joinable = 0;
|
||||
}
|
||||
handle = CreateThread(NULL, 64 * 1024, thread_body, info, 0, NULL);
|
||||
if (handle == NULL) {
|
||||
destroy_thread(info);
|
||||
} else {
|
||||
*t = (gpr_thd_id)info;
|
||||
CloseHandle(handle);
|
||||
}
|
||||
*t = (gpr_thd_id)thread_id;
|
||||
return handle != NULL;
|
||||
}
|
||||
|
||||
gpr_thd_options gpr_thd_options_default(void) {
|
||||
gpr_thd_options options;
|
||||
memset(&options, 0, sizeof(options));
|
||||
return options;
|
||||
gpr_thd_id gpr_thd_currentid(void) {
|
||||
return (gpr_thd_id)g_thd_info;
|
||||
}
|
||||
|
||||
gpr_thd_id gpr_thd_currentid(void) {
|
||||
return (gpr_thd_id)GetCurrentThreadId();
|
||||
void gpr_thd_join(gpr_thd_id t) {
|
||||
struct thd_info *info = (struct thd_info *)t;
|
||||
DWORD ret = WaitForSingleObject(info->join_event, INFINITE);
|
||||
GPR_ASSERT(ret == WAIT_OBJECT_0);
|
||||
destroy_thread(info);
|
||||
}
|
||||
|
||||
#endif /* GPR_WIN32 */
|
||||
|
|
|
|||
|
|
@ -1006,6 +1006,8 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
|
|||
const grpc_op *op;
|
||||
grpc_ioreq *req;
|
||||
|
||||
GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, tag);
|
||||
|
||||
if (nops == 0) {
|
||||
grpc_cq_begin_op(call->cq, call, GRPC_OP_COMPLETE);
|
||||
grpc_cq_end_op_complete(call->cq, tag, call, do_nothing, NULL, GRPC_OP_OK);
|
||||
|
|
|
|||
|
|
@ -119,4 +119,13 @@ grpc_call_stack *grpc_call_get_call_stack(grpc_call *call);
|
|||
/* Given the top call_element, get the call object. */
|
||||
grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element);
|
||||
|
||||
extern int grpc_trace_batch;
|
||||
|
||||
void grpc_call_log_batch(char *file, int line, gpr_log_severity severity,
|
||||
grpc_call *call, const grpc_op *ops, size_t nops,
|
||||
void *tag);
|
||||
|
||||
#define GRPC_CALL_LOG_BATCH(sev, call, ops, nops, tag) \
|
||||
if (grpc_trace_batch) grpc_call_log_batch(sev, call, ops, nops, tag)
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_SURFACE_CALL_H */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "src/core/surface/call.h"
|
||||
|
||||
#include "src/core/support/string.h"
|
||||
#include <grpc/support/alloc.h>
|
||||
|
||||
int grpc_trace_batch = 0;
|
||||
|
||||
static void add_metadata(gpr_strvec *b, const grpc_metadata *md, size_t count) {
|
||||
size_t i;
|
||||
for(i = 0; i < count; i++) {
|
||||
gpr_strvec_add(b, gpr_strdup("\nkey="));
|
||||
gpr_strvec_add(b, gpr_strdup(md[i].key));
|
||||
|
||||
gpr_strvec_add(b, gpr_strdup(" value="));
|
||||
gpr_strvec_add(b, gpr_hexdump(md[i].value, md[i].value_length,
|
||||
GPR_HEXDUMP_PLAINTEXT));
|
||||
}
|
||||
}
|
||||
|
||||
char *grpc_op_string(const grpc_op *op) {
|
||||
char *tmp;
|
||||
char *out;
|
||||
|
||||
gpr_strvec b;
|
||||
gpr_strvec_init(&b);
|
||||
|
||||
switch (op->op) {
|
||||
case GRPC_OP_SEND_INITIAL_METADATA:
|
||||
gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA"));
|
||||
add_metadata(&b, op->data.send_initial_metadata.metadata,
|
||||
op->data.send_initial_metadata.count);
|
||||
break;
|
||||
case GRPC_OP_SEND_MESSAGE:
|
||||
gpr_asprintf(&tmp, "SEND_MESSAGE ptr=%p", op->data.send_message);
|
||||
gpr_strvec_add(&b, tmp);
|
||||
break;
|
||||
case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
|
||||
gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT"));
|
||||
break;
|
||||
case GRPC_OP_SEND_STATUS_FROM_SERVER:
|
||||
gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=%s",
|
||||
op->data.send_status_from_server.status,
|
||||
op->data.send_status_from_server.status_details);
|
||||
gpr_strvec_add(&b, tmp);
|
||||
add_metadata(&b, op->data.send_status_from_server.trailing_metadata,
|
||||
op->data.send_status_from_server.trailing_metadata_count);
|
||||
break;
|
||||
case GRPC_OP_RECV_INITIAL_METADATA:
|
||||
gpr_asprintf(&tmp, "RECV_INITIAL_METADATA ptr=%p",
|
||||
op->data.recv_initial_metadata);
|
||||
gpr_strvec_add(&b, tmp);
|
||||
break;
|
||||
case GRPC_OP_RECV_MESSAGE:
|
||||
gpr_asprintf(&tmp, "RECV_MESSAGE ptr=%p", op->data.recv_message);
|
||||
gpr_strvec_add(&b, tmp);
|
||||
break;
|
||||
case GRPC_OP_RECV_STATUS_ON_CLIENT:
|
||||
gpr_asprintf(&tmp,
|
||||
"RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p",
|
||||
op->data.recv_status_on_client.trailing_metadata,
|
||||
op->data.recv_status_on_client.status,
|
||||
op->data.recv_status_on_client.status_details);
|
||||
gpr_strvec_add(&b, tmp);
|
||||
break;
|
||||
case GRPC_OP_RECV_CLOSE_ON_SERVER:
|
||||
gpr_asprintf(&tmp, "RECV_CLOSE_ON_SERVER cancelled=%p",
|
||||
op->data.recv_close_on_server.cancelled);
|
||||
gpr_strvec_add(&b, tmp);
|
||||
}
|
||||
out = gpr_strvec_flatten(&b, NULL);
|
||||
gpr_strvec_destroy(&b);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void grpc_call_log_batch(char *file, int line, gpr_log_severity severity,
|
||||
grpc_call *call, const grpc_op *ops, size_t nops,
|
||||
void *tag) {
|
||||
char *tmp;
|
||||
size_t i;
|
||||
gpr_log(file, line, severity,
|
||||
"grpc_call_start_batch(%p, %p, %d, 0x%x)", call, ops, nops, tag);
|
||||
for(i = 0; i < nops; i++) {
|
||||
tmp = grpc_op_string(&ops[i]);
|
||||
gpr_log(file, line, severity, "ops[%d]: %s", i, tmp);
|
||||
gpr_free(tmp);
|
||||
}
|
||||
}
|
||||
|
|
@ -432,3 +432,11 @@ void grpc_cq_dump_pending_ops(grpc_completion_queue *cc) {
|
|||
grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) {
|
||||
return &cc->pollset;
|
||||
}
|
||||
|
||||
void grpc_cq_hack_spin_pollset(grpc_completion_queue *cc) {
|
||||
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
|
||||
grpc_pollset_kick(&cc->pollset);
|
||||
grpc_pollset_work(&cc->pollset,
|
||||
gpr_time_add(gpr_now(), gpr_time_from_millis(100)));
|
||||
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,4 +114,6 @@ void grpc_cq_dump_pending_ops(grpc_completion_queue *cc);
|
|||
|
||||
grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H */
|
||||
void grpc_cq_hack_spin_pollset(grpc_completion_queue *cc);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H */
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "src/core/debug/trace.h"
|
||||
#include "src/core/statistics/census_interface.h"
|
||||
#include "src/core/channel/channel_stack.h"
|
||||
#include "src/core/surface/call.h"
|
||||
#include "src/core/surface/init.h"
|
||||
#include "src/core/surface/surface_trace.h"
|
||||
#include "src/core/transport/chttp2_transport.h"
|
||||
|
|
@ -57,6 +58,7 @@ void grpc_init(void) {
|
|||
grpc_register_tracer("channel", &grpc_trace_channel);
|
||||
grpc_register_tracer("surface", &grpc_surface_trace);
|
||||
grpc_register_tracer("http", &grpc_http_trace);
|
||||
grpc_register_tracer("batch", &grpc_trace_batch);
|
||||
grpc_security_pre_init();
|
||||
grpc_tracer_init("GRPC_TRACE");
|
||||
grpc_iomgr_init();
|
||||
|
|
@ -82,4 +84,3 @@ int grpc_is_initialized(void) {
|
|||
gpr_mu_unlock(&g_init_mu);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ struct grpc_server {
|
|||
size_t cq_count;
|
||||
|
||||
gpr_mu mu;
|
||||
gpr_cv cv;
|
||||
|
||||
registered_method *registered_methods;
|
||||
requested_call_array requested_calls;
|
||||
|
|
@ -149,6 +150,7 @@ struct grpc_server {
|
|||
channel_data root_channel_data;
|
||||
|
||||
listener *listeners;
|
||||
int listeners_destroyed;
|
||||
gpr_refcount internal_refcount;
|
||||
};
|
||||
|
||||
|
|
@ -263,6 +265,7 @@ static void server_unref(grpc_server *server) {
|
|||
if (gpr_unref(&server->internal_refcount)) {
|
||||
grpc_channel_args_destroy(server->channel_args);
|
||||
gpr_mu_destroy(&server->mu);
|
||||
gpr_cv_destroy(&server->cv);
|
||||
gpr_free(server->channel_filters);
|
||||
requested_call_array_destroy(&server->requested_calls);
|
||||
while ((rm = server->registered_methods) != NULL) {
|
||||
|
|
@ -589,9 +592,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
|
|||
}
|
||||
|
||||
static const grpc_channel_filter server_surface_filter = {
|
||||
call_op, channel_op, sizeof(call_data),
|
||||
init_call_elem, destroy_call_elem, sizeof(channel_data),
|
||||
init_channel_elem, destroy_channel_elem, "server",
|
||||
call_op, channel_op, sizeof(call_data), init_call_elem, destroy_call_elem,
|
||||
sizeof(channel_data), init_channel_elem, destroy_channel_elem, "server",
|
||||
};
|
||||
|
||||
static void addcq(grpc_server *server, grpc_completion_queue *cq) {
|
||||
|
|
@ -620,6 +622,7 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq,
|
|||
if (cq) addcq(server, cq);
|
||||
|
||||
gpr_mu_init(&server->mu);
|
||||
gpr_cv_init(&server->cv);
|
||||
|
||||
server->unregistered_cq = cq;
|
||||
/* decremented by grpc_server_destroy */
|
||||
|
|
@ -733,7 +736,8 @@ grpc_transport_setup_result grpc_server_setup_transport(
|
|||
channel = grpc_channel_create_from_filters(filters, num_filters,
|
||||
s->channel_args, mdctx, 0);
|
||||
chand = (channel_data *)grpc_channel_stack_element(
|
||||
grpc_channel_get_channel_stack(channel), 0)->channel_data;
|
||||
grpc_channel_get_channel_stack(channel), 0)
|
||||
->channel_data;
|
||||
chand->server = s;
|
||||
server_ref(s);
|
||||
chand->channel = channel;
|
||||
|
|
@ -754,7 +758,7 @@ grpc_transport_setup_result grpc_server_setup_transport(
|
|||
method = grpc_mdstr_from_string(mdctx, rm->method);
|
||||
hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
|
||||
for (probes = 0; chand->registered_methods[(hash + probes) % slots]
|
||||
.server_registered_method != NULL;
|
||||
.server_registered_method != NULL;
|
||||
probes++)
|
||||
;
|
||||
if (probes > max_probes) max_probes = probes;
|
||||
|
|
@ -781,6 +785,15 @@ grpc_transport_setup_result grpc_server_setup_transport(
|
|||
return result;
|
||||
}
|
||||
|
||||
static int num_listeners(grpc_server *server) {
|
||||
listener *l;
|
||||
int n = 0;
|
||||
for (l = server->listeners; l; l = l->next) {
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
|
||||
void *shutdown_tag) {
|
||||
listener *l;
|
||||
|
|
@ -878,11 +891,6 @@ static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
|
|||
for (l = server->listeners; l; l = l->next) {
|
||||
l->destroy(server, l->arg);
|
||||
}
|
||||
while (server->listeners) {
|
||||
l = server->listeners;
|
||||
server->listeners = l->next;
|
||||
gpr_free(l);
|
||||
}
|
||||
}
|
||||
|
||||
void grpc_server_shutdown(grpc_server *server) {
|
||||
|
|
@ -893,8 +901,18 @@ void grpc_server_shutdown_and_notify(grpc_server *server, void *tag) {
|
|||
shutdown_internal(server, 1, tag);
|
||||
}
|
||||
|
||||
void grpc_server_listener_destroy_done(void *s) {
|
||||
grpc_server *server = s;
|
||||
gpr_mu_lock(&server->mu);
|
||||
server->listeners_destroyed++;
|
||||
gpr_cv_signal(&server->cv);
|
||||
gpr_mu_unlock(&server->mu);
|
||||
}
|
||||
|
||||
void grpc_server_destroy(grpc_server *server) {
|
||||
channel_data *c;
|
||||
listener *l;
|
||||
size_t i;
|
||||
gpr_mu_lock(&server->mu);
|
||||
if (!server->shutdown) {
|
||||
gpr_mu_unlock(&server->mu);
|
||||
|
|
@ -902,6 +920,23 @@ void grpc_server_destroy(grpc_server *server) {
|
|||
gpr_mu_lock(&server->mu);
|
||||
}
|
||||
|
||||
while (server->listeners_destroyed != num_listeners(server)) {
|
||||
for (i = 0; i < server->cq_count; i++) {
|
||||
gpr_mu_unlock(&server->mu);
|
||||
grpc_cq_hack_spin_pollset(server->cqs[i]);
|
||||
gpr_mu_lock(&server->mu);
|
||||
}
|
||||
|
||||
gpr_cv_wait(&server->cv, &server->mu,
|
||||
gpr_time_add(gpr_now(), gpr_time_from_millis(100)));
|
||||
}
|
||||
|
||||
while (server->listeners) {
|
||||
l = server->listeners;
|
||||
server->listeners = l->next;
|
||||
gpr_free(l);
|
||||
}
|
||||
|
||||
for (c = server->root_channel_data.next; c != &server->root_channel_data;
|
||||
c = c->next) {
|
||||
shutdown_channel(c);
|
||||
|
|
|
|||
|
|
@ -48,9 +48,12 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq,
|
|||
and when it shuts down, it will call destroy */
|
||||
void grpc_server_add_listener(grpc_server *server, void *listener,
|
||||
void (*start)(grpc_server *server, void *arg,
|
||||
grpc_pollset **pollsets, size_t npollsets),
|
||||
grpc_pollset **pollsets,
|
||||
size_t npollsets),
|
||||
void (*destroy)(grpc_server *server, void *arg));
|
||||
|
||||
void grpc_server_listener_destroy_done(void *server);
|
||||
|
||||
/* Setup a transport - creates a channel stack, binds the transport to the
|
||||
server */
|
||||
grpc_transport_setup_result grpc_server_setup_transport(
|
||||
|
|
@ -60,4 +63,4 @@ grpc_transport_setup_result grpc_server_setup_transport(
|
|||
|
||||
const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server);
|
||||
|
||||
#endif /* GRPC_INTERNAL_CORE_SURFACE_SERVER_H */
|
||||
#endif /* GRPC_INTERNAL_CORE_SURFACE_SERVER_H */
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ static void new_transport(void *server, grpc_endpoint *tcp) {
|
|||
}
|
||||
|
||||
/* Server callback: start listening on our ports */
|
||||
static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets, size_t pollset_count) {
|
||||
static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets,
|
||||
size_t pollset_count) {
|
||||
grpc_tcp_server *tcp = tcpp;
|
||||
grpc_tcp_server_start(tcp, pollsets, pollset_count, new_transport, server);
|
||||
}
|
||||
|
|
@ -75,7 +76,7 @@ static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets, size
|
|||
callbacks) */
|
||||
static void destroy(grpc_server *server, void *tcpp) {
|
||||
grpc_tcp_server *tcp = tcpp;
|
||||
grpc_tcp_server_destroy(tcp);
|
||||
grpc_tcp_server_destroy(tcp, grpc_server_listener_destroy_done, server);
|
||||
}
|
||||
|
||||
int grpc_server_add_http2_port(grpc_server *server, const char *addr) {
|
||||
|
|
@ -131,7 +132,7 @@ error:
|
|||
grpc_resolved_addresses_destroy(resolved);
|
||||
}
|
||||
if (tcp) {
|
||||
grpc_tcp_server_destroy(tcp);
|
||||
grpc_tcp_server_destroy(tcp, NULL, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1710,6 +1710,8 @@ static int process_read(transport *t, gpr_slice slice) {
|
|||
|
||||
gpr_log(GPR_ERROR, "should never reach here");
|
||||
abort();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* tcp read callback */
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ static void internal_string_ref(internal_string *s);
|
|||
static void internal_string_unref(internal_string *s);
|
||||
static void discard_metadata(grpc_mdctx *ctx);
|
||||
static void gc_mdtab(grpc_mdctx *ctx);
|
||||
static void metadata_context_destroy(grpc_mdctx *ctx);
|
||||
static void metadata_context_destroy_locked(grpc_mdctx *ctx);
|
||||
|
||||
static void lock(grpc_mdctx *ctx) { gpr_mu_lock(&ctx->mu); }
|
||||
|
||||
|
|
@ -122,8 +122,7 @@ static void unlock(grpc_mdctx *ctx) {
|
|||
discard_metadata(ctx);
|
||||
}
|
||||
if (ctx->strtab_count == 0) {
|
||||
gpr_mu_unlock(&ctx->mu);
|
||||
metadata_context_destroy(ctx);
|
||||
metadata_context_destroy_locked(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -185,8 +184,7 @@ static void discard_metadata(grpc_mdctx *ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
static void metadata_context_destroy(grpc_mdctx *ctx) {
|
||||
gpr_mu_lock(&ctx->mu);
|
||||
static void metadata_context_destroy_locked(grpc_mdctx *ctx) {
|
||||
GPR_ASSERT(ctx->strtab_count == 0);
|
||||
GPR_ASSERT(ctx->mdtab_count == 0);
|
||||
GPR_ASSERT(ctx->mdtab_free == 0);
|
||||
|
|
|
|||
|
|
@ -567,7 +567,8 @@ static tsi_result populate_ssl_context(
|
|||
EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) {
|
||||
gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
|
||||
result = TSI_INTERNAL_ERROR;
|
||||
EC_KEY_free(ecdh);
|
||||
return TSI_INTERNAL_ERROR;
|
||||
}
|
||||
SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
|
||||
EC_KEY_free(ecdh);
|
||||
|
|
@ -604,6 +605,7 @@ static tsi_result build_alpn_protocol_name_list(
|
|||
unsigned char* current;
|
||||
*protocol_name_list = NULL;
|
||||
*protocol_name_list_length = 0;
|
||||
if (num_alpn_protocols == 0) return TSI_INVALID_ARGUMENT;
|
||||
for (i = 0; i < num_alpn_protocols; i++) {
|
||||
if (alpn_protocols_lengths[i] == 0) {
|
||||
gpr_log(GPR_ERROR, "Invalid 0-length protocol name.");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
*
|
||||
* 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++/generic_stub.h>
|
||||
|
||||
#include <grpc++/impl/rpc_method.h>
|
||||
|
||||
namespace grpc {
|
||||
|
||||
// begin a call to a named method
|
||||
std::unique_ptr<GenericClientAsyncReaderWriter> GenericStub::Call(
|
||||
ClientContext* context, const grpc::string& method,
|
||||
CompletionQueue* cq, void* tag) {
|
||||
return std::unique_ptr<GenericClientAsyncReaderWriter>(
|
||||
new GenericClientAsyncReaderWriter(
|
||||
channel_.get(), cq, RpcMethod(method.c_str()), context, tag));
|
||||
}
|
||||
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
|
|
@ -31,8 +31,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <grpc/grpc_security.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ CallOpBuffer::CallOpBuffer()
|
|||
status_code_(GRPC_STATUS_OK),
|
||||
status_details_(nullptr),
|
||||
status_details_capacity_(0),
|
||||
send_status_(nullptr),
|
||||
send_status_available_(false),
|
||||
send_status_code_(GRPC_STATUS_OK),
|
||||
trailing_metadata_count_(0),
|
||||
trailing_metadata_(nullptr),
|
||||
cancelled_buf_(0),
|
||||
|
|
@ -104,7 +105,9 @@ void CallOpBuffer::Reset(void* next_return_tag) {
|
|||
|
||||
status_code_ = GRPC_STATUS_OK;
|
||||
|
||||
send_status_ = nullptr;
|
||||
send_status_available_ = false;
|
||||
send_status_code_ = GRPC_STATUS_OK;
|
||||
send_status_details_.clear();
|
||||
trailing_metadata_count_ = 0;
|
||||
trailing_metadata_ = nullptr;
|
||||
|
||||
|
|
@ -148,7 +151,7 @@ void FillMetadataMap(grpc_metadata_array* arr,
|
|||
// TODO(yangg) handle duplicates?
|
||||
metadata->insert(std::pair<grpc::string, grpc::string>(
|
||||
arr->metadata[i].key,
|
||||
{arr->metadata[i].value, arr->metadata[i].value_length}));
|
||||
grpc::string(arr->metadata[i].value, arr->metadata[i].value_length)));
|
||||
}
|
||||
grpc_metadata_array_destroy(arr);
|
||||
grpc_metadata_array_init(arr);
|
||||
|
|
@ -186,6 +189,7 @@ void CallOpBuffer::AddRecvMessage(grpc::protobuf::Message* message) {
|
|||
|
||||
void CallOpBuffer::AddRecvMessage(ByteBuffer* message) {
|
||||
recv_message_buffer_ = message;
|
||||
recv_message_buffer_->Clear();
|
||||
}
|
||||
|
||||
void CallOpBuffer::AddClientSendClose() { client_send_close_ = true; }
|
||||
|
|
@ -207,7 +211,9 @@ void CallOpBuffer::AddServerSendStatus(
|
|||
} else {
|
||||
trailing_metadata_count_ = 0;
|
||||
}
|
||||
send_status_ = &status;
|
||||
send_status_available_ = true;
|
||||
send_status_code_ = static_cast<grpc_status_code>(status.code());
|
||||
send_status_details_ = status.details();
|
||||
}
|
||||
|
||||
void CallOpBuffer::FillOps(grpc_op* ops, size_t* nops) {
|
||||
|
|
@ -256,16 +262,15 @@ void CallOpBuffer::FillOps(grpc_op* ops, size_t* nops) {
|
|||
&status_details_capacity_;
|
||||
(*nops)++;
|
||||
}
|
||||
if (send_status_) {
|
||||
if (send_status_available_) {
|
||||
ops[*nops].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
|
||||
ops[*nops].data.send_status_from_server.trailing_metadata_count =
|
||||
trailing_metadata_count_;
|
||||
ops[*nops].data.send_status_from_server.trailing_metadata =
|
||||
trailing_metadata_;
|
||||
ops[*nops].data.send_status_from_server.status =
|
||||
static_cast<grpc_status_code>(send_status_->code());
|
||||
ops[*nops].data.send_status_from_server.status = send_status_code_;
|
||||
ops[*nops].data.send_status_from_server.status_details =
|
||||
send_status_->details().c_str();
|
||||
send_status_details_.empty() ? nullptr : send_status_details_.c_str();
|
||||
(*nops)++;
|
||||
}
|
||||
if (recv_closed_) {
|
||||
|
|
|
|||
|
|
@ -59,9 +59,12 @@ class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
|
|||
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()});
|
||||
for (auto key_cert_pair = options.pem_key_cert_pairs.begin();
|
||||
key_cert_pair != options.pem_key_cert_pairs.end();
|
||||
key_cert_pair++) {
|
||||
grpc_ssl_pem_key_cert_pair p = {key_cert_pair->private_key.c_str(),
|
||||
key_cert_pair->cert_chain.c_str()};
|
||||
pem_key_cert_pairs.push_back(p);
|
||||
}
|
||||
grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create(
|
||||
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
|
|||
request_payload_(mrd->request_payload_),
|
||||
method_(mrd->method_) {
|
||||
ctx_.call_ = mrd->call_;
|
||||
ctx_.cq_ = &cq_;
|
||||
GPR_ASSERT(mrd->in_flight_);
|
||||
mrd->in_flight_ = false;
|
||||
mrd->request_metadata_.count = 0;
|
||||
|
|
@ -182,7 +183,7 @@ Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned)
|
|||
|
||||
Server::~Server() {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
grpc::unique_lock<grpc::mutex> lock(mu_);
|
||||
if (started_ && !shutdown_) {
|
||||
lock.unlock();
|
||||
Shutdown();
|
||||
|
|
@ -247,8 +248,8 @@ bool Server::Start() {
|
|||
|
||||
// Start processing rpcs.
|
||||
if (!sync_methods_.empty()) {
|
||||
for (auto& m : sync_methods_) {
|
||||
m.Request(server_);
|
||||
for (auto m = sync_methods_.begin(); m != sync_methods_.end(); m++) {
|
||||
m->Request(server_);
|
||||
}
|
||||
|
||||
ScheduleCallback();
|
||||
|
|
@ -258,7 +259,7 @@ bool Server::Start() {
|
|||
}
|
||||
|
||||
void Server::Shutdown() {
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
grpc::unique_lock<grpc::mutex> lock(mu_);
|
||||
if (started_ && !shutdown_) {
|
||||
shutdown_ = true;
|
||||
grpc_server_shutdown(server_);
|
||||
|
|
@ -272,7 +273,7 @@ void Server::Shutdown() {
|
|||
}
|
||||
|
||||
void Server::Wait() {
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
grpc::unique_lock<grpc::mutex> lock(mu_);
|
||||
while (num_running_cb_ != 0) {
|
||||
callback_cv_.wait(lock);
|
||||
}
|
||||
|
|
@ -364,6 +365,7 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag {
|
|||
}
|
||||
}
|
||||
ctx->call_ = call_;
|
||||
ctx->cq_ = cq_;
|
||||
Call call(call_, server_, cq_);
|
||||
if (orig_status && call_) {
|
||||
ctx->BeginCompletionOp(&call);
|
||||
|
|
@ -403,7 +405,7 @@ void Server::RequestAsyncGenericCall(GenericServerContext* context,
|
|||
|
||||
void Server::ScheduleCallback() {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
grpc::unique_lock<grpc::mutex> lock(mu_);
|
||||
num_running_cb_++;
|
||||
}
|
||||
thread_pool_->ScheduleCallback(std::bind(&Server::RunRpc, this));
|
||||
|
|
@ -424,7 +426,7 @@ void Server::RunRpc() {
|
|||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
grpc::unique_lock<grpc::mutex> lock(mu_);
|
||||
num_running_cb_--;
|
||||
if (shutdown_) {
|
||||
callback_cv_.notify_all();
|
||||
|
|
|
|||
|
|
@ -86,24 +86,26 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
|
|||
thread_pool_owned = true;
|
||||
}
|
||||
std::unique_ptr<Server> server(new Server(thread_pool_, thread_pool_owned));
|
||||
for (auto* service : services_) {
|
||||
if (!server->RegisterService(service)) {
|
||||
for (auto service = services_.begin(); service != services_.end();
|
||||
service++) {
|
||||
if (!server->RegisterService(*service)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
for (auto* service : async_services_) {
|
||||
if (!server->RegisterAsyncService(service)) {
|
||||
for (auto service = async_services_.begin();
|
||||
service != async_services_.end(); service++) {
|
||||
if (!server->RegisterAsyncService(*service)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (generic_service_) {
|
||||
server->RegisterAsyncGenericService(generic_service_);
|
||||
}
|
||||
for (auto& port : ports_) {
|
||||
int r = server->AddListeningPort(port.addr, port.creds.get());
|
||||
for (auto port = ports_.begin(); port != ports_.end(); port++) {
|
||||
int r = server->AddListeningPort(port->addr, port->creds.get());
|
||||
if (!r) return nullptr;
|
||||
if (port.selected_port != nullptr) {
|
||||
*port.selected_port = r;
|
||||
if (port->selected_port != nullptr) {
|
||||
*port->selected_port = r;
|
||||
}
|
||||
}
|
||||
if (!server->Start()) {
|
||||
|
|
|
|||
|
|
@ -33,9 +33,8 @@
|
|||
|
||||
#include <grpc++/server_context.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <grpc++/impl/call.h>
|
||||
#include <grpc++/impl/sync.h>
|
||||
#include <grpc/grpc.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include "src/cpp/util/time.h"
|
||||
|
|
@ -57,14 +56,14 @@ class ServerContext::CompletionOp GRPC_FINAL : public CallOpBuffer {
|
|||
void Unref();
|
||||
|
||||
private:
|
||||
std::mutex mu_;
|
||||
grpc::mutex mu_;
|
||||
int refs_;
|
||||
bool finalized_;
|
||||
bool cancelled_;
|
||||
};
|
||||
|
||||
void ServerContext::CompletionOp::Unref() {
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
grpc::unique_lock<grpc::mutex> lock(mu_);
|
||||
if (--refs_ == 0) {
|
||||
lock.unlock();
|
||||
delete this;
|
||||
|
|
@ -73,13 +72,13 @@ void ServerContext::CompletionOp::Unref() {
|
|||
|
||||
bool ServerContext::CompletionOp::CheckCancelled(CompletionQueue* cq) {
|
||||
cq->TryPluck(this);
|
||||
std::lock_guard<std::mutex> g(mu_);
|
||||
grpc::lock_guard<grpc::mutex> g(mu_);
|
||||
return finalized_ ? cancelled_ : false;
|
||||
}
|
||||
|
||||
bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) {
|
||||
GPR_ASSERT(CallOpBuffer::FinalizeResult(tag, status));
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
grpc::unique_lock<grpc::mutex> lock(mu_);
|
||||
finalized_ = true;
|
||||
if (!*status) cancelled_ = true;
|
||||
if (--refs_ == 0) {
|
||||
|
|
|
|||
|
|
@ -31,48 +31,52 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <grpc++/impl/sync.h>
|
||||
#include <grpc++/impl/thd.h>
|
||||
|
||||
#include "src/cpp/server/thread_pool.h"
|
||||
|
||||
namespace grpc {
|
||||
|
||||
void ThreadPool::ThreadFunc() {
|
||||
for (;;) {
|
||||
// Wait until work is available or we are shutting down.
|
||||
grpc::unique_lock<grpc::mutex> lock(mu_);
|
||||
if (!shutdown_ && callbacks_.empty()) {
|
||||
cv_.wait(lock);
|
||||
}
|
||||
// Drain callbacks before considering shutdown to ensure all work
|
||||
// gets completed.
|
||||
if (!callbacks_.empty()) {
|
||||
auto cb = callbacks_.front();
|
||||
callbacks_.pop();
|
||||
lock.unlock();
|
||||
cb();
|
||||
} else if (shutdown_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::ThreadPool(int num_threads) : shutdown_(false) {
|
||||
for (int i = 0; i < num_threads; i++) {
|
||||
threads_.push_back(std::thread([this]() {
|
||||
for (;;) {
|
||||
// Wait until work is available or we are shutting down.
|
||||
auto have_work = [this]() { return shutdown_ || !callbacks_.empty(); };
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
if (!have_work()) {
|
||||
cv_.wait(lock, have_work);
|
||||
}
|
||||
// Drain callbacks before considering shutdown to ensure all work
|
||||
// gets completed.
|
||||
if (!callbacks_.empty()) {
|
||||
auto cb = callbacks_.front();
|
||||
callbacks_.pop();
|
||||
lock.unlock();
|
||||
cb();
|
||||
} else if (shutdown_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}));
|
||||
threads_.push_back(grpc::thread(&ThreadPool::ThreadFunc, this));
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::~ThreadPool() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
grpc::lock_guard<grpc::mutex> lock(mu_);
|
||||
shutdown_ = true;
|
||||
cv_.notify_all();
|
||||
}
|
||||
for (auto& t : threads_) {
|
||||
t.join();
|
||||
for (auto t = threads_.begin(); t != threads_.end(); t++) {
|
||||
t->join();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::ScheduleCallback(const std::function<void()>& callback) {
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
grpc::lock_guard<grpc::mutex> lock(mu_);
|
||||
callbacks_.push(callback);
|
||||
cv_.notify_one();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,11 +35,11 @@
|
|||
#define GRPC_INTERNAL_CPP_SERVER_THREAD_POOL_H
|
||||
|
||||
#include <grpc++/config.h>
|
||||
|
||||
#include <grpc++/impl/sync.h>
|
||||
#include <grpc++/impl/thd.h>
|
||||
#include <grpc++/thread_pool_interface.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -53,11 +53,13 @@ class ThreadPool GRPC_FINAL : public ThreadPoolInterface {
|
|||
void ScheduleCallback(const std::function<void()>& callback) GRPC_OVERRIDE;
|
||||
|
||||
private:
|
||||
std::mutex mu_;
|
||||
std::condition_variable cv_;
|
||||
grpc::mutex mu_;
|
||||
grpc::condition_variable cv_;
|
||||
bool shutdown_;
|
||||
std::queue<std::function<void()>> callbacks_;
|
||||
std::vector<std::thread> threads_;
|
||||
std::vector<grpc::thread> threads_;
|
||||
|
||||
void ThreadFunc();
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("0.1.*")]
|
||||
[assembly: AssemblyVersion("0.2.*")]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.
|
||||
This is an experimental release, not ready to use.
|
||||
</description>
|
||||
<version>0.1.0</version>
|
||||
<version>0.2.0</version>
|
||||
<authors>Google Inc.</authors>
|
||||
<owners>jtattermusch</owners>
|
||||
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("0.1.*")]
|
||||
[assembly: AssemblyVersion("0.2.*")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Grpc.Core.Tests")]
|
||||
|
|
|
|||
|
|
@ -46,11 +46,15 @@ namespace math
|
|||
MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel);
|
||||
MathExamples.DivExample(stub);
|
||||
|
||||
MathExamples.FibExample(stub);
|
||||
MathExamples.DivAsyncExample(stub).Wait();
|
||||
|
||||
MathExamples.SumExample(stub);
|
||||
MathExamples.FibExample(stub).Wait();
|
||||
|
||||
MathExamples.DivManyExample(stub);
|
||||
MathExamples.SumExample(stub).Wait();
|
||||
|
||||
MathExamples.DivManyExample(stub).Wait();
|
||||
|
||||
MathExamples.DependendRequestsExample(stub).Wait();
|
||||
}
|
||||
|
||||
GrpcEnvironment.Shutdown();
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("0.1.*")]
|
||||
[assembly: AssemblyVersion("0.2.*")]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
bin
|
||||
obj
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>10.0.0</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{BF62FE08-373A-43D6-9D73-41CAA38B7011}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Grpc.Examples.MathServer</RootNamespace>
|
||||
<AssemblyName>Grpc.Examples.MathServer</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="MathServer.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
|
||||
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
|
||||
<Name>Grpc.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Grpc.Examples\Grpc.Examples.csproj">
|
||||
<Project>{7DC1433E-3225-42C7-B7EA-546D56E27A4B}</Project>
|
||||
<Name>Grpc.Examples</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
#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 Grpc.Core;
|
||||
|
||||
namespace math
|
||||
{
|
||||
class MainClass
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
String host = "0.0.0.0";
|
||||
|
||||
GrpcEnvironment.Initialize();
|
||||
|
||||
Server server = new Server();
|
||||
server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl()));
|
||||
int port = server.AddListeningPort(host + ":0");
|
||||
server.Start();
|
||||
|
||||
Console.WriteLine("MathServer listening on port " + port);
|
||||
|
||||
Console.WriteLine("Press any key to stop the server...");
|
||||
Console.ReadKey();
|
||||
|
||||
server.ShutdownAsync().Wait();
|
||||
GrpcEnvironment.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyTitle("Grpc.Examples.MathServer")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("0.1.*")]
|
||||
|
|
@ -37,6 +37,18 @@
|
|||
<Reference Include="Google.ProtocolBuffers">
|
||||
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Interfaces">
|
||||
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Core">
|
||||
<HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Linq">
|
||||
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.PlatformServices">
|
||||
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Grpc.Core;
|
||||
|
|
@ -120,14 +121,12 @@ namespace math.Tests
|
|||
[Test]
|
||||
public void Sum()
|
||||
{
|
||||
var res = client.Sum();
|
||||
foreach (var num in new long[] { 10, 20, 30 })
|
||||
{
|
||||
res.Inputs.OnNext(Num.CreateBuilder().SetNum_(num).Build());
|
||||
}
|
||||
res.Inputs.OnCompleted();
|
||||
var clientStreamingResult = client.Sum();
|
||||
var numList = new List<long> { 10, 20, 30 }.ConvertAll(
|
||||
n => Num.CreateBuilder().SetNum_(n).Build());
|
||||
numList.Subscribe(clientStreamingResult.Inputs);
|
||||
|
||||
Assert.AreEqual(60, res.Task.Result.Num_);
|
||||
Assert.AreEqual(60, clientStreamingResult.Task.Result.Num_);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
@ -142,13 +141,7 @@ namespace math.Tests
|
|||
|
||||
var recorder = new RecordingObserver<DivReply>();
|
||||
var requestObserver = client.DivMany(recorder);
|
||||
|
||||
foreach (var arg in divArgsList)
|
||||
{
|
||||
requestObserver.OnNext(arg);
|
||||
}
|
||||
requestObserver.OnCompleted();
|
||||
|
||||
divArgsList.Subscribe(requestObserver);
|
||||
var result = recorder.ToList().Result;
|
||||
|
||||
CollectionAssert.AreEqual(new long[] { 3, 4, 3 }, result.ConvertAll((divReply) => divReply.Quotient));
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("0.1.*")]
|
||||
[assembly: AssemblyVersion("0.2.*")]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" />
|
||||
<package id="NUnit" version="2.6.4" targetFramework="net45" />
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" />
|
||||
<package id="NUnit" version="2.6.4" targetFramework="net45" />
|
||||
<package id="Rx-Core" version="2.2.5" targetFramework="net45" />
|
||||
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" />
|
||||
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" />
|
||||
<package id="Rx-Main" version="2.2.5" targetFramework="net45" />
|
||||
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" />
|
||||
</packages>
|
||||
|
|
@ -45,51 +45,45 @@ namespace math
|
|||
Console.WriteLine("Div Result: " + result);
|
||||
}
|
||||
|
||||
public static void DivAsyncExample(MathGrpc.IMathServiceClient stub)
|
||||
public static async Task DivAsyncExample(MathGrpc.IMathServiceClient stub)
|
||||
{
|
||||
Task<DivReply> call = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
|
||||
DivReply result = call.Result;
|
||||
Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
|
||||
DivReply result = await resultTask;
|
||||
Console.WriteLine("DivAsync Result: " + result);
|
||||
}
|
||||
|
||||
public static async Task DivAsyncWithCancellationExample(MathGrpc.IMathServiceClient stub)
|
||||
{
|
||||
Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
|
||||
DivReply result = await resultTask;
|
||||
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 async Task FibExample(MathGrpc.IMathServiceClient stub)
|
||||
{
|
||||
var recorder = new RecordingObserver<Num>();
|
||||
stub.Fib(new FibArgs.Builder { Limit = 5 }.Build(), recorder);
|
||||
|
||||
List<Num> numbers = recorder.ToList().Result;
|
||||
Console.WriteLine("Fib Result: " + string.Join("|", recorder.ToList().Result));
|
||||
List<Num> result = await recorder.ToList();
|
||||
Console.WriteLine("Fib Result: " + string.Join("|", result));
|
||||
}
|
||||
|
||||
public static void SumExample(MathGrpc.IMathServiceClient stub)
|
||||
public static async Task SumExample(MathGrpc.IMathServiceClient stub)
|
||||
{
|
||||
List<Num> numbers = new List<Num>
|
||||
var 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)
|
||||
{
|
||||
res.Inputs.OnNext(num);
|
||||
}
|
||||
res.Inputs.OnCompleted();
|
||||
|
||||
Console.WriteLine("Sum Result: " + res.Task.Result);
|
||||
var clientStreamingResult = stub.Sum();
|
||||
numbers.Subscribe(clientStreamingResult.Inputs);
|
||||
Console.WriteLine("Sum Result: " + await clientStreamingResult.Task);
|
||||
}
|
||||
|
||||
public static void DivManyExample(MathGrpc.IMathServiceClient stub)
|
||||
public static async Task DivManyExample(MathGrpc.IMathServiceClient stub)
|
||||
{
|
||||
List<DivArgs> divArgsList = new List<DivArgs>
|
||||
var divArgsList = new List<DivArgs>
|
||||
{
|
||||
new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(),
|
||||
new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(),
|
||||
|
|
@ -97,26 +91,27 @@ namespace math
|
|||
};
|
||||
|
||||
var recorder = new RecordingObserver<DivReply>();
|
||||
|
||||
var inputs = stub.DivMany(recorder);
|
||||
foreach (var input in divArgsList)
|
||||
{
|
||||
inputs.OnNext(input);
|
||||
}
|
||||
inputs.OnCompleted();
|
||||
|
||||
Console.WriteLine("DivMany Result: " + string.Join("|", recorder.ToList().Result));
|
||||
divArgsList.Subscribe(inputs);
|
||||
var result = await recorder.ToList();
|
||||
Console.WriteLine("DivMany Result: " + string.Join("|", result));
|
||||
}
|
||||
|
||||
public static void DependendRequestsExample(MathGrpc.IMathServiceClient stub)
|
||||
public static async Task DependendRequestsExample(MathGrpc.IMathServiceClient stub)
|
||||
{
|
||||
var numberList = new List<Num>
|
||||
var numbers = new List<Num>
|
||||
{
|
||||
new Num.Builder { Num_ = 1 }.Build(),
|
||||
new Num.Builder { Num_ = 2 }.Build(), new Num.Builder { Num_ = 3 }.Build()
|
||||
new Num.Builder { Num_ = 1 }.Build(),
|
||||
new Num.Builder { Num_ = 2 }.Build(),
|
||||
new Num.Builder { Num_ = 3 }.Build()
|
||||
};
|
||||
|
||||
numberList.ToObservable();
|
||||
var clientStreamingResult = stub.Sum();
|
||||
numbers.Subscribe(clientStreamingResult.Inputs);
|
||||
Num sum = await clientStreamingResult.Task;
|
||||
|
||||
DivReply result = await stub.DivAsync(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numbers.Count }.Build());
|
||||
Console.WriteLine("Avg Result: " + result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("0.1.*")]
|
||||
[assembly: AssemblyVersion("0.2.*")]
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("0.1.*")]
|
||||
[assembly: AssemblyVersion("0.2.*")]
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("0.1.*")]
|
||||
[assembly: AssemblyVersion("0.2.*")]
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
|
|||
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("0.1.*")]
|
||||
[assembly: AssemblyVersion("0.2.*")]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<description>C# implementation of gRPC - an RPC library and framework. See project site for more info.
|
||||
This is an experimental release, not ready to use.
|
||||
</description>
|
||||
<version>0.1.0</version>
|
||||
<version>0.2.0</version>
|
||||
<authors>Google Inc.</authors>
|
||||
<owners>jtattermusch</owners>
|
||||
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
<copyright>Copyright 2015, Google Inc.</copyright>
|
||||
<tags>gRPC RPC Protocol HTTP/2</tags>
|
||||
<dependencies>
|
||||
<dependency id="Grpc.Core" version="0.1.0" />
|
||||
<dependency id="Grpc.Core" version="0.2.0" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
</package>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.Cli
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.Server", "Grpc.IntegrationTesting.Server\Grpc.IntegrationTesting.Server.csproj", "{A654F3B8-E859-4E6A-B30D-227527DBEF0D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Examples.MathServer", "Grpc.Examples.MathServer\Grpc.Examples.MathServer.csproj", "{BF62FE08-373A-43D6-9D73-41CAA38B7011}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
|
|
@ -47,6 +49,10 @@ Global
|
|||
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|x86.Build.0 = Debug|x86
|
||||
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.ActiveCfg = Release|x86
|
||||
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.Build.0 = Release|x86
|
||||
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.Build.0 = Debug|x86
|
||||
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.ActiveCfg = Release|x86
|
||||
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.Build.0 = Release|x86
|
||||
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.Build.0 = Debug|x86
|
||||
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.ActiveCfg = Release|x86
|
||||
|
|
|
|||
|
|
@ -731,7 +731,7 @@ grpcsharp_ssl_credentials_create(const char *pem_root_certs,
|
|||
}
|
||||
}
|
||||
|
||||
GPR_EXPORT void grpcsharp_credentials_release(grpc_credentials *creds) {
|
||||
GPR_EXPORT void GPR_CALLTYPE grpcsharp_credentials_release(grpc_credentials *creds) {
|
||||
grpc_credentials_release(creds);
|
||||
}
|
||||
|
||||
|
|
@ -765,7 +765,7 @@ grpcsharp_ssl_server_credentials_create(
|
|||
return creds;
|
||||
}
|
||||
|
||||
GPR_EXPORT void grpcsharp_server_credentials_release(
|
||||
GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_credentials_release(
|
||||
grpc_server_credentials *creds) {
|
||||
grpc_server_credentials_release(creds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,12 +18,29 @@
|
|||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-lrt',
|
||||
'-lpthread',
|
||||
'-lgrpc',
|
||||
'-lgpr'
|
||||
],
|
||||
]
|
||||
},
|
||||
"conditions": [
|
||||
['OS == "mac"', {
|
||||
'xcode_settings': {
|
||||
'MACOSX_DEPLOYMENT_TARGET': '10.9',
|
||||
'OTHER_CFLAGS': [
|
||||
'-std=c++11',
|
||||
'-stdlib=libc++'
|
||||
]
|
||||
}
|
||||
}],
|
||||
['OS != "mac"', {
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-lrt'
|
||||
]
|
||||
}
|
||||
}]
|
||||
],
|
||||
"target_name": "grpc",
|
||||
"sources": [
|
||||
"ext/byte_buffer.cc",
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <node.h>
|
||||
#include <nan.h>
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <node.h>
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@
|
|||
#include <node.h>
|
||||
#include <nan.h>
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
#include <vector>
|
||||
#include "grpc/grpc.h"
|
||||
#include "grpc/grpc_security.h"
|
||||
|
|
|
|||
|
|
@ -318,8 +318,8 @@ var test_cases = {
|
|||
empty_stream: emptyStream,
|
||||
cancel_after_begin: cancelAfterBegin,
|
||||
cancel_after_first_response: cancelAfterFirstResponse,
|
||||
compute_engine_creds: _.partial(authTest, AUTH_USER),
|
||||
service_account_creds: _.partial(authTest, COMPUTE_ENGINE_USER)
|
||||
compute_engine_creds: _.partial(authTest, COMPUTE_ENGINE_USER),
|
||||
service_account_creds: _.partial(authTest, AUTH_USER)
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -241,13 +241,13 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
|
|||
callback(err);
|
||||
return;
|
||||
}
|
||||
emitter.emit('status', response.status);
|
||||
if (response.status.code !== grpc.status.OK) {
|
||||
var error = new Error(response.status.details);
|
||||
error.code = response.status.code;
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
emitter.emit('status', response.status);
|
||||
emitter.emit('metadata', response.metadata);
|
||||
callback(null, deserialize(response.read));
|
||||
});
|
||||
|
|
@ -312,13 +312,13 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
|
|||
callback(err);
|
||||
return;
|
||||
}
|
||||
stream.emit('status', response.status);
|
||||
if (response.status.code !== grpc.status.OK) {
|
||||
var error = new Error(response.status.details);
|
||||
error.code = response.status.code;
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
stream.emit('status', response.status);
|
||||
callback(null, deserialize(response.read));
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ function handleError(call, error) {
|
|||
status.details = error.details;
|
||||
}
|
||||
}
|
||||
if (error.hasOwnProperty('metadata')) {
|
||||
status.metadata = error.metadata;
|
||||
}
|
||||
var error_batch = {};
|
||||
error_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status;
|
||||
call.startBatch(error_batch, function(){});
|
||||
|
|
@ -102,15 +105,20 @@ function waitForCancel(call, emitter) {
|
|||
* @param {*} value The value to respond with
|
||||
* @param {function(*):Buffer=} serialize Serialization function for the
|
||||
* response
|
||||
* @param {Object=} metadata Optional trailing metadata to send with status
|
||||
*/
|
||||
function sendUnaryResponse(call, value, serialize) {
|
||||
function sendUnaryResponse(call, value, serialize, metadata) {
|
||||
var end_batch = {};
|
||||
end_batch[grpc.opType.SEND_MESSAGE] = serialize(value);
|
||||
end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
|
||||
var status = {
|
||||
code: grpc.status.OK,
|
||||
details: 'OK',
|
||||
metadata: {}
|
||||
};
|
||||
if (metadata) {
|
||||
status.metadata = metadata;
|
||||
}
|
||||
end_batch[grpc.opType.SEND_MESSAGE] = serialize(value);
|
||||
end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status;
|
||||
call.startBatch(end_batch, function (){});
|
||||
}
|
||||
|
||||
|
|
@ -143,6 +151,7 @@ function setUpWritable(stream, serialize) {
|
|||
function setStatus(err) {
|
||||
var code = grpc.status.INTERNAL;
|
||||
var details = 'Unknown Error';
|
||||
var metadata = {};
|
||||
if (err.hasOwnProperty('message')) {
|
||||
details = err.message;
|
||||
}
|
||||
|
|
@ -152,7 +161,10 @@ function setUpWritable(stream, serialize) {
|
|||
details = err.details;
|
||||
}
|
||||
}
|
||||
stream.status = {code: code, details: details, metadata: {}};
|
||||
if (err.hasOwnProperty('metadata')) {
|
||||
metadata = err.metadata;
|
||||
}
|
||||
stream.status = {code: code, details: details, metadata: metadata};
|
||||
}
|
||||
/**
|
||||
* Terminate the call. This includes indicating that reads are done, draining
|
||||
|
|
@ -166,6 +178,17 @@ function setUpWritable(stream, serialize) {
|
|||
stream.end();
|
||||
}
|
||||
stream.on('error', terminateCall);
|
||||
/**
|
||||
* Override of Writable#end method that allows for sending metadata with a
|
||||
* success status.
|
||||
* @param {Object=} metadata Metadata to send with the status
|
||||
*/
|
||||
stream.end = function(metadata) {
|
||||
if (metadata) {
|
||||
stream.status.metadata = metadata;
|
||||
}
|
||||
Writable.prototype.end.call(this);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -335,11 +358,13 @@ function handleUnary(call, handler, metadata) {
|
|||
if (emitter.cancelled) {
|
||||
return;
|
||||
}
|
||||
handler.func(emitter, function sendUnaryData(err, value) {
|
||||
handler.func(emitter, function sendUnaryData(err, value, trailer) {
|
||||
if (err) {
|
||||
err.metadata = trailer;
|
||||
handleError(call, err);
|
||||
} else {
|
||||
sendUnaryResponse(call, value, handler.serialize, trailer);
|
||||
}
|
||||
sendUnaryResponse(call, value, handler.serialize);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -378,12 +403,14 @@ function handleClientStreaming(call, handler, metadata) {
|
|||
var metadata_batch = {};
|
||||
metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata;
|
||||
call.startBatch(metadata_batch, function() {});
|
||||
handler.func(stream, function(err, value) {
|
||||
handler.func(stream, function(err, value, trailer) {
|
||||
stream.terminate();
|
||||
if (err) {
|
||||
err.metadata = trailer;
|
||||
handleError(call, err);
|
||||
} else {
|
||||
sendUnaryResponse(call, value, handler.serialize, trailer);
|
||||
}
|
||||
sendUnaryResponse(call, value, handler.serialize);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,167 @@ describe('Generic client and server', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
describe('Trailing metadata', function() {
|
||||
var client;
|
||||
var server;
|
||||
before(function() {
|
||||
var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
|
||||
var test_service = test_proto.lookup('TestService');
|
||||
var Server = grpc.buildServer([test_service]);
|
||||
server = new Server({
|
||||
TestService: {
|
||||
unary: function(call, cb) {
|
||||
var req = call.request;
|
||||
if (req.error) {
|
||||
cb(new Error('Requested error'), null, {metadata: ['yes']});
|
||||
} else {
|
||||
cb(null, {count: 1}, {metadata: ['yes']});
|
||||
}
|
||||
},
|
||||
clientStream: function(stream, cb){
|
||||
var count = 0;
|
||||
var errored;
|
||||
stream.on('data', function(data) {
|
||||
if (data.error) {
|
||||
errored = true;
|
||||
cb(new Error('Requested error'), null, {metadata: ['yes']});
|
||||
} else {
|
||||
count += 1;
|
||||
}
|
||||
});
|
||||
stream.on('end', function() {
|
||||
if (!errored) {
|
||||
cb(null, {count: count}, {metadata: ['yes']});
|
||||
}
|
||||
});
|
||||
},
|
||||
serverStream: function(stream) {
|
||||
var req = stream.request;
|
||||
if (req.error) {
|
||||
var err = new Error('Requested error');
|
||||
err.metadata = {metadata: ['yes']};
|
||||
stream.emit('error', err);
|
||||
} else {
|
||||
for (var i = 0; i < 5; i++) {
|
||||
stream.write({count: i});
|
||||
}
|
||||
stream.end({metadata: ['yes']});
|
||||
}
|
||||
},
|
||||
bidiStream: function(stream) {
|
||||
var count = 0;
|
||||
stream.on('data', function(data) {
|
||||
if (data.error) {
|
||||
var err = new Error('Requested error');
|
||||
err.metadata = {
|
||||
metadata: ['yes'],
|
||||
count: ['' + count]
|
||||
};
|
||||
stream.emit('error', err);
|
||||
} else {
|
||||
stream.write({count: count});
|
||||
count += 1;
|
||||
}
|
||||
});
|
||||
stream.on('end', function() {
|
||||
stream.end({metadata: ['yes']});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
var port = server.bind('localhost:0');
|
||||
var Client = surface_client.makeProtobufClientConstructor(test_service);
|
||||
client = new Client('localhost:' + port);
|
||||
server.listen();
|
||||
});
|
||||
after(function() {
|
||||
server.shutdown();
|
||||
});
|
||||
it('should be present when a unary call succeeds', function(done) {
|
||||
var call = client.unary({error: false}, function(err, data) {
|
||||
assert.ifError(err);
|
||||
});
|
||||
call.on('status', function(status) {
|
||||
assert.deepEqual(status.metadata.metadata, ['yes']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be present when a unary call fails', function(done) {
|
||||
var call = client.unary({error: true}, function(err, data) {
|
||||
assert(err);
|
||||
});
|
||||
call.on('status', function(status) {
|
||||
assert.deepEqual(status.metadata.metadata, ['yes']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be present when a client stream call succeeds', function(done) {
|
||||
var call = client.clientStream(function(err, data) {
|
||||
assert.ifError(err);
|
||||
});
|
||||
call.write({error: false});
|
||||
call.write({error: false});
|
||||
call.end();
|
||||
call.on('status', function(status) {
|
||||
assert.deepEqual(status.metadata.metadata, ['yes']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be present when a client stream call fails', function(done) {
|
||||
var call = client.clientStream(function(err, data) {
|
||||
assert(err);
|
||||
});
|
||||
call.write({error: false});
|
||||
call.write({error: true});
|
||||
call.end();
|
||||
call.on('status', function(status) {
|
||||
assert.deepEqual(status.metadata.metadata, ['yes']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be present when a server stream call succeeds', function(done) {
|
||||
var call = client.serverStream({error: false});
|
||||
call.on('data', function(){});
|
||||
call.on('status', function(status) {
|
||||
assert.strictEqual(status.code, grpc.status.OK);
|
||||
assert.deepEqual(status.metadata.metadata, ['yes']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be present when a server stream call fails', function(done) {
|
||||
var call = client.serverStream({error: true});
|
||||
call.on('data', function(){});
|
||||
call.on('status', function(status) {
|
||||
assert.notStrictEqual(status.code, grpc.status.OK);
|
||||
assert.deepEqual(status.metadata.metadata, ['yes']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be present when a bidi stream succeeds', function(done) {
|
||||
var call = client.bidiStream();
|
||||
call.write({error: false});
|
||||
call.write({error: false});
|
||||
call.end();
|
||||
call.on('data', function(){});
|
||||
call.on('status', function(status) {
|
||||
assert.strictEqual(status.code, grpc.status.OK);
|
||||
assert.deepEqual(status.metadata.metadata, ['yes']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should be present when a bidi stream fails', function(done) {
|
||||
var call = client.bidiStream();
|
||||
call.write({error: false});
|
||||
call.write({error: true});
|
||||
call.end();
|
||||
call.on('data', function(){});
|
||||
call.on('status', function(status) {
|
||||
assert.notStrictEqual(status.code, grpc.status.OK);
|
||||
assert.deepEqual(status.metadata.metadata, ['yes']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('Cancelling surface client', function() {
|
||||
var client;
|
||||
var server;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue