Merge branch 'master' of github.com:grpc/grpc into sanity

Conflicts:
	tools/run_tests/run_tests.py
This commit is contained in:
Nicolas "Pixel" Noble 2015-04-10 04:46:03 +02:00
commit a9ef765bfc
274 changed files with 10304 additions and 4246 deletions

2
.gitmodules vendored
View File

@ -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

View File

@ -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

566
BUILD Normal file
View File

@ -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",
],
)

338
Makefile

File diff suppressed because one or more lines are too long

View File

@ -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.

View File

@ -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"
},
{

View File

@ -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.

View File

@ -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();

View File

@ -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;

View File

@ -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 {

View File

@ -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_));
}

View File

@ -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) {

View File

@ -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 {

View File

@ -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());
}

View File

@ -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;

View File

@ -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_;

View File

@ -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_;

24
src/php/ext/grpc/event.h → include/grpc++/impl/sync.h Executable file → Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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_;

View File

@ -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;

View File

@ -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

View File

@ -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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &params) {
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 &param) {
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 &params) {
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 &params) {
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

View File

@ -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 &params);
// 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 &params);
// Return the includes needed for generated source file.
grpc::string GetSourceIncludes();
grpc::string GetSourceIncludes(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
// Return the epilogue of the generated header file.
grpc::string GetHeaderEpilogue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
// Return the prologue of the generated source file.
grpc::string GetSourcePrologue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
// 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 &params);
// 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 &params);
// Return the epilogue of the generated source file.
grpc::string GetSourceEpilogue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
} // namespace grpc_cpp_generator

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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 &parameter,
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);
}

View File

@ -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;

View File

@ -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 */

View File

@ -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) {

View File

@ -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) {

View File

@ -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);

View File

@ -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",

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

66
src/core/support/thd.c Normal file
View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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));
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);

View File

@ -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.");

View File

@ -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

View File

@ -31,8 +31,6 @@
*
*/
#include <string>
#include <grpc/grpc.h>
#include <grpc/support/log.h>

View File

@ -31,8 +31,6 @@
*
*/
#include <string>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>

View File

@ -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_) {

View File

@ -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(),

View File

@ -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();

View File

@ -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()) {

View File

@ -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) {

View File

@ -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();
}

View File

@ -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

View File

@ -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.*")]

View File

@ -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>

View File

@ -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")]

View File

@ -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();

View File

@ -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.*")]

View File

@ -0,0 +1,2 @@
bin
obj

View File

@ -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>

View File

@ -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();
}
}
}

View File

@ -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.*")]

View File

@ -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" />

View File

@ -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));

View File

@ -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.*")]

View File

@ -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>

View File

@ -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);
}
}
}

View File

@ -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.*")]

View File

@ -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.*")]

View File

@ -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.*")]

View File

@ -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.*")]

View File

@ -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>

View File

@ -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

View File

@ -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);
}

View File

@ -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",

View File

@ -32,7 +32,6 @@
*/
#include <string.h>
#include <malloc.h>
#include <node.h>
#include <nan.h>

View File

@ -31,8 +31,6 @@
*
*/
#include <malloc.h>
#include <vector>
#include <node.h>

View File

@ -38,8 +38,6 @@
#include <node.h>
#include <nan.h>
#include <malloc.h>
#include <vector>
#include "grpc/grpc.h"
#include "grpc/grpc_security.h"

View File

@ -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)
};
/**

View File

@ -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));
});
});

View File

@ -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);
});
}

View File

@ -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