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

pull/7391/head
David Garcia Quintas 8 years ago
commit 62105352be
  1. 3
      .gitignore
  2. 60
      .travis.yml
  3. 8
      BUILD
  4. 785
      CMakeLists.txt
  5. 363
      Makefile
  6. 2
      PYTHON-MANIFEST.in
  7. 2
      Rakefile
  8. 1
      binding.gyp
  9. 44
      build.yaml
  10. 8
      composer.json
  11. 1
      config.m4
  12. 2
      doc/.gitignore
  13. 53
      doc/c-style-guide.md
  14. 29
      doc/command_line_tool.md
  15. BIN
      doc/images/load_balancing_design.png
  16. 75
      doc/load-balancing.md
  17. 1
      doc/statuscodes.md
  18. 1293
      etc/roots.pem
  19. 49
      examples/cpp/helloworld/CMakeLists.txt
  20. 12
      examples/cpp/helloworld/Makefile
  21. 12
      examples/cpp/route_guide/Makefile
  22. 16
      examples/csharp/helloworld/README.md
  23. 34
      examples/objective-c/auth_sample/AuthTestService.podspec
  24. 32
      examples/objective-c/auth_sample/Misc/GoogleService-Info.plist
  25. 34
      examples/objective-c/auth_sample/Podfile
  26. 34
      examples/objective-c/helloworld/HelloWorld.podspec
  27. 34
      examples/objective-c/helloworld/Podfile
  28. 34
      examples/objective-c/route_guide/Podfile
  29. 34
      examples/objective-c/route_guide/RouteGuide.podspec
  30. 2
      examples/php/README.md
  31. 8
      examples/php/composer.json
  32. 10
      examples/python/helloworld/greeter_client.py
  33. 8
      examples/python/helloworld/greeter_server.py
  34. 63
      examples/python/helloworld/helloworld_pb2.py
  35. 12
      examples/python/helloworld/run_codegen.py
  36. 1
      examples/python/multiplex/.gitignore
  37. 1
      examples/python/multiplex/README.md
  38. 204
      examples/python/multiplex/helloworld_pb2.py
  39. 139
      examples/python/multiplex/multiplex_client.py
  40. 149
      examples/python/multiplex/multiplex_server.py
  41. 601
      examples/python/multiplex/route_guide_db.json
  42. 516
      examples/python/multiplex/route_guide_pb2.py
  43. 32
      examples/python/multiplex/route_guide_resources.py
  44. 35
      examples/python/multiplex/run_codegen.py
  45. 26
      examples/python/route_guide/route_guide_client.py
  46. 172
      examples/python/route_guide/route_guide_pb2.py
  47. 0
      examples/python/route_guide/route_guide_resources.py
  48. 7
      examples/python/route_guide/route_guide_server.py
  49. 12
      examples/python/route_guide/run_codegen.py
  50. 32
      examples/python/route_guide/run_codegen.sh
  51. 33
      gRPC-Core.podspec
  52. 4
      gRPC-ProtoRPC.podspec
  53. 4
      gRPC-RxLibrary.podspec
  54. 4
      gRPC.podspec
  55. 1
      grpc.def
  56. 2
      grpc.gemspec
  57. 27
      include/grpc++/impl/codegen/async_stream.h
  58. 11
      include/grpc++/impl/codegen/async_unary_call.h
  59. 12
      include/grpc++/impl/codegen/call.h
  60. 2
      include/grpc++/impl/codegen/client_context.h
  61. 18
      include/grpc++/impl/codegen/config_protobuf.h
  62. 486
      include/grpc++/impl/codegen/impl/async_stream.h
  63. 15
      include/grpc++/impl/codegen/method_handler_impl.h
  64. 9
      include/grpc++/impl/codegen/server_context.h
  65. 15
      include/grpc++/impl/codegen/sync_stream.h
  66. 3
      include/grpc++/server.h
  67. 3
      include/grpc++/support/slice.h
  68. 17
      include/grpc/impl/codegen/compression_types.h
  69. 38
      include/grpc/impl/codegen/grpc_types.h
  70. 2
      include/grpc/impl/codegen/port_platform.h
  71. 8
      include/grpc/impl/codegen/slice.h
  72. 10
      include/grpc/module.modulemap
  73. 2
      package.json
  74. 56
      package.xml
  75. 2
      setup.cfg
  76. 141
      setup.py
  77. 7
      src/compiler/config.h
  78. 96
      src/compiler/cpp_generator.cc
  79. 30
      src/compiler/cpp_plugin.cc
  80. 271
      src/compiler/csharp_generator.cc
  81. 6
      src/compiler/csharp_generator_helpers.h
  82. 6
      src/compiler/csharp_plugin.cc
  83. 14
      src/compiler/generator_helpers.h
  84. 62
      src/compiler/node_generator.cc
  85. 2
      src/compiler/node_generator_helpers.h
  86. 29
      src/compiler/objective_c_generator.cc
  87. 1
      src/compiler/objective_c_generator_helpers.h
  88. 48
      src/compiler/objective_c_plugin.cc
  89. 333
      src/compiler/python_generator.cc
  90. 1
      src/compiler/python_generator.h
  91. 33
      src/compiler/ruby_generator.cc
  92. 4
      src/compiler/ruby_generator_helpers-inl.h
  93. 5
      src/compiler/ruby_generator_map-inl.h
  94. 2
      src/core/ext/client_config/channel_connectivity.c
  95. 36
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  96. 56
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
  97. 72
      src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
  98. 66
      src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
  99. 3
      src/core/ext/transport/chttp2/transport/chttp2_plugin.c
  100. 382
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  101. Some files were not shown because too many files have changed in this diff Show More

3
.gitignore vendored

@ -96,3 +96,6 @@ Pods/
# Artifacts directory
artifacts/
# Git generated files for conflicting
*.orig

@ -1,3 +1,5 @@
git:
depth: 1
language: objective-c
osx_image: xcode7.3
env:
@ -6,43 +8,47 @@ env:
- TEST=objc
- JOBS=1
matrix:
- SCHEME="RxLibraryUnitTests" WORKSPACE="Tests.xcworkspace"
TEST_PATH="src/objective-c/tests" BUILD_ONLY="false"
- SCHEME="RxLibraryUnitTests"
WORKSPACE="Tests.xcworkspace" TEST_PATH="src/objective-c/tests" BUILD_ONLY="false"
INTEROP_SERVER="false"
- SCHEME="InteropTestsLocalSSL" WORKSPACE="Tests.xcworkspace"
TEST_PATH="src/objective-c/tests" BUILD_ONLY="false" INTEROP_SERVER="true"
- SCHEME="InteropTestsLocalCleartext" WORKSPACE="Tests.xcworkspace"
TEST_PATH="src/objective-c/tests" BUILD_ONLY="false"
- SCHEME="InteropTestsLocalSSL"
WORKSPACE="Tests.xcworkspace" TEST_PATH="src/objective-c/tests" BUILD_ONLY="false"
INTEROP_SERVER="true"
# TODO(jcanizales): Investigate why they time out:
# - SCHEME="InteropTestsRemote" WORKSPACE="Tests.xcworkspace"
# TEST_PATH="src/objective-c/tests" BUILD_ONLY="false"
- SCHEME="InteropTestsLocalCleartext"
WORKSPACE="Tests.xcworkspace" TEST_PATH="src/objective-c/tests" BUILD_ONLY="false"
INTEROP_SERVER="true"
# TODO(jcanizales): Make tests an app project (instead of library), so the following will work.
# - SCHEME="InteropTestsRemote"
# WORKSPACE="Tests.xcworkspace" TEST_PATH="src/objective-c/tests" BUILD_ONLY="false"
# INTEROP_SERVER="true"
- SCHEME="HelloWorld" WORKSPACE="HelloWorld.xcworkspace"
TEST_PATH="examples/objective-c/helloworld" BUILD_ONLY="true"
INTEROP_SERVER="false"
- SCHEME="RouteGuideClient" WORKSPACE="RouteGuideClient.xcworkspace"
TEST_PATH="examples/objective-c/route_guide" BUILD_ONLY="true"
INTEROP_SERVER="false"
- SCHEME="AuthSample" WORKSPACE="AuthSample.xcworkspace"
TEST_PATH="examples/objective-c/auth_sample" BUILD_ONLY="true"
INTEROP_SERVER="false"
- SCHEME="Sample" WORKSPACE="Sample.xcworkspace"
TEST_PATH="src/objective-c/examples/Sample" BUILD_ONLY="true"
INTEROP_SERVER="false"
- SCHEME="SwiftSample" WORKSPACE="SwiftSample.xcworkspace"
TEST_PATH="src/objective-c/examples/SwiftSample" BUILD_ONLY="true"
- SCHEME="HelloWorld"
WORKSPACE="HelloWorld.xcworkspace" TEST_PATH="examples/objective-c/helloworld"
BUILD_ONLY="true" INTEROP_SERVER="false"
- SCHEME="RouteGuideClient"
WORKSPACE="RouteGuideClient.xcworkspace" TEST_PATH="examples/objective-c/route_guide"
BUILD_ONLY="true" INTEROP_SERVER="false"
- SCHEME="AuthSample"
WORKSPACE="AuthSample.xcworkspace" TEST_PATH="examples/objective-c/auth_sample"
BUILD_ONLY="true" INTEROP_SERVER="false"
- SCHEME="Sample"
WORKSPACE="Sample.xcworkspace" TEST_PATH="src/objective-c/examples/Sample" BUILD_ONLY="true"
INTEROP_SERVER="false"
- SCHEME="Sample"
WORKSPACE="Sample.xcworkspace" TEST_PATH="src/objective-c/examples/Sample" BUILD_ONLY="true"
INTEROP_SERVER="false" FRAMEWORKS="YES"
- SCHEME="SwiftSample"
WORKSPACE="SwiftSample.xcworkspace" TEST_PATH="src/objective-c/examples/SwiftSample"
BUILD_ONLY="true" INTEROP_SERVER="false"
before_install:
# Until Travis upgrades from Cocoapods 0.39, we need to do it here.
- pod --version
- gem uninstall cocoapods -a
- gem install cocoapods -v '1.0.0'
- gem install cocoapods -v '1.0.1'
- pod --version
# Recent pods aren't found if we don't explicitly update Cocoapods' repo.
- pod repo update
- brew install gflags
install:
- make grpc_objective_c_plugin
- install bins/opt/grpc_objective_c_plugin /usr/local/bin/protoc-gen-objcgrpc
- install bins/opt/protobuf/protoc /usr/local/bin/protoc
- pushd $TEST_PATH
- pod install
- popd

@ -165,6 +165,7 @@ cc_library(
"src/core/lib/channel/compress_filter.h",
"src/core/lib/channel/connected_channel.h",
"src/core/lib/channel/context.h",
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
@ -316,6 +317,7 @@ cc_library(
"src/core/lib/channel/channel_stack_builder.c",
"src/core/lib/channel/compress_filter.c",
"src/core/lib/channel/connected_channel.c",
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/compression/compression.c",
@ -552,6 +554,7 @@ cc_library(
"src/core/lib/channel/compress_filter.h",
"src/core/lib/channel/connected_channel.h",
"src/core/lib/channel/context.h",
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
@ -693,6 +696,7 @@ cc_library(
"src/core/lib/channel/channel_stack_builder.c",
"src/core/lib/channel/compress_filter.c",
"src/core/lib/channel/connected_channel.c",
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/compression/compression.c",
@ -904,6 +908,7 @@ cc_library(
"src/core/lib/channel/compress_filter.h",
"src/core/lib/channel/connected_channel.h",
"src/core/lib/channel/context.h",
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
@ -1032,6 +1037,7 @@ cc_library(
"src/core/lib/channel/channel_stack_builder.c",
"src/core/lib/channel/compress_filter.c",
"src/core/lib/channel/connected_channel.c",
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/compression/compression.c",
@ -1791,6 +1797,7 @@ objc_library(
"src/core/lib/channel/channel_stack_builder.c",
"src/core/lib/channel/compress_filter.c",
"src/core/lib/channel/connected_channel.c",
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/compression/compression.c",
@ -2006,6 +2013,7 @@ objc_library(
"src/core/lib/channel/compress_filter.h",
"src/core/lib/channel/connected_channel.h",
"src/core/lib/channel/context.h",
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/compression/algorithm_metadata.h",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -7,7 +7,7 @@ graft include/grpc
graft third_party/boringssl
graft third_party/nanopb
graft third_party/zlib
include src/python/grpcio/build.py
include src/python/grpcio/_unixccompiler_patch.py
include src/python/grpcio/commands.py
include src/python/grpcio/grpc_version.py
include src/python/grpcio/grpc_core_dependencies.py

@ -83,7 +83,7 @@ task 'dlls' do
env += 'EMBED_ZLIB=true '
env += 'BUILDDIR=/tmp '
env += "V=#{verbose} "
out = '/tmp/libs/opt/grpc-0.dll'
out = '/tmp/libs/opt/grpc-1.dll'
w64 = { cross: 'x86_64-w64-mingw32', out: 'grpc_c.64.ruby' }
w32 = { cross: 'i686-w64-mingw32', out: 'grpc_c.32.ruby' }

@ -568,6 +568,7 @@
'src/core/lib/channel/channel_stack_builder.c',
'src/core/lib/channel/compress_filter.c',
'src/core/lib/channel/connected_channel.c',
'src/core/lib/channel/handshaker.c',
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/compression/compression.c',

@ -7,7 +7,7 @@ settings:
'#3': Use "-preN" suffixes to identify pre-release versions
'#4': Per-language overrides are possible with (eg) ruby_version tag here
'#5': See the expand_version.py for all the quirks here
version: 0.16.0-dev
version: 1.1.0-dev
filegroups:
- name: census
public_headers:
@ -156,6 +156,7 @@ filegroups:
- src/core/lib/channel/compress_filter.h
- src/core/lib/channel/connected_channel.h
- src/core/lib/channel/context.h
- src/core/lib/channel/handshaker.h
- src/core/lib/channel/http_client_filter.h
- src/core/lib/channel/http_server_filter.h
- src/core/lib/compression/algorithm_metadata.h
@ -234,6 +235,7 @@ filegroups:
- src/core/lib/channel/channel_stack_builder.c
- src/core/lib/channel/compress_filter.c
- src/core/lib/channel/connected_channel.c
- src/core/lib/channel/handshaker.c
- src/core/lib/channel/http_client_filter.c
- src/core/lib/channel/http_server_filter.c
- src/core/lib/compression/compression.c
@ -768,6 +770,16 @@ filegroups:
language: c++
public_headers:
- include/grpc++/impl/codegen/config_protobuf.h
- name: grpc++_reflection_proto
language: c++
public_headers:
- include/grpc++/ext/reflection.grpc.pb.h
- include/grpc++/ext/reflection.pb.h
src:
- src/cpp/ext/reflection.grpc.pb.cc
- src/cpp/ext/reflection.pb.cc
uses:
- grpc++_codegen_proto
libs:
- name: gpr
build: all
@ -960,19 +972,20 @@ libs:
language: c++
public_headers:
- include/grpc++/ext/proto_server_reflection_plugin.h
- include/grpc++/ext/reflection.grpc.pb.h
- include/grpc++/ext/reflection.pb.h
headers:
- src/cpp/ext/proto_server_reflection.h
src:
- src/cpp/ext/proto_server_reflection.cc
- src/cpp/ext/proto_server_reflection_plugin.cc
- src/cpp/ext/reflection.grpc.pb.cc
- src/cpp/ext/reflection.pb.cc
deps:
- grpc++
filegroups:
- grpc++_codegen_proto
- grpc++_reflection_proto
- name: grpc++_reflection_codegen
build: private
language: c++
src:
- src/proto/grpc/reflection/v1alpha/reflection.proto
- name: grpc++_test_config
build: private
language: c++
@ -1030,10 +1043,13 @@ libs:
headers:
- test/cpp/util/cli_call.h
- test/cpp/util/proto_file_parser.h
- test/cpp/util/proto_reflection_descriptor_database.h
src:
- test/cpp/util/cli_call.cc
- test/cpp/util/proto_file_parser.cc
- test/cpp/util/proto_reflection_descriptor_database.cc
deps:
- grpc++_reflection
- grpc++
- grpc_plugin_support
- name: grpc_plugin_support
@ -2430,20 +2446,6 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: workqueue_test
build: test
language: c
src:
- test/core/iomgr/workqueue_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
platforms:
- mac
- linux
- posix
- name: alarm_cpp_test
gtest: true
build: test
@ -2671,6 +2673,7 @@ targets:
- grpc_cli_libs
- grpc++_test_util
- grpc_test_util
- grpc++_reflection
- grpc++
- grpc
- gpr_test_util
@ -3367,6 +3370,7 @@ php_config_m4:
- src/php/ext/grpc/channel.h
- src/php/ext/grpc/channel_credentials.h
- src/php/ext/grpc/completion_queue.h
- src/php/ext/grpc/php7_wrapper.h
- src/php/ext/grpc/php_grpc.h
- src/php/ext/grpc/server.h
- src/php/ext/grpc/server_credentials.h

@ -5,15 +5,9 @@
"keywords": ["rpc"],
"homepage": "http://grpc.io",
"license": "BSD-3-Clause",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/stanley-cheung/Protobuf-PHP"
}
],
"require": {
"php": ">=5.5.0",
"datto/protobuf-php": "dev-master"
"stanley-cheung/protobuf-php": "v0.6"
},
"require-dev": {
"google/auth": "v0.9"

@ -87,6 +87,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/channel/channel_stack_builder.c \
src/core/lib/channel/compress_filter.c \
src/core/lib/channel/connected_channel.c \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/compression/compression.c \

2
doc/.gitignore vendored

@ -0,0 +1,2 @@
build/
src/

@ -9,16 +9,17 @@ Here we document style rules for C usage in the gRPC Core library.
General
-------
- Layout rules are defined by clang-format, and all code should be passed through
clang-format. A (docker-based) script to do so is included in
[tools/distrib/clang\_format\_code.sh] (../tools/distrib/clang_format_code.sh).
- Layout rules are defined by clang-format, and all code should be passed
through clang-format. A (docker-based) script to do so is included in
[tools/distrib/clang\_format\_code.sh](../tools/distrib/clang_format_code.sh).
Header Files
------------
- Public header files (those in the include/grpc tree) should compile as pedantic C89
- Public header files should be includable from C++ programs. That is, they should
include the following:
- Public header files (those in the include/grpc tree) should compile as
pedantic C89.
- Public header files should be includable from C++ programs. That is, they
should include the following:
```c
#ifdef __cplusplus
extern "C" {
@ -34,24 +35,34 @@ Header Files
- All header files should have a #define guard to prevent multiple inclusion.
To guarantee uniqueness they should be based on the file's path.
For public headers: include/grpc/grpc.h --> GRPC_GRPC_H
For public headers: `include/grpc/grpc.h``GRPC_GRPC_H`
For private headers:
`src/core/channel/channel_stack.h`
`GRPC_INTERNAL_CORE_CHANNEL_CHANNEL_STACK_H`
Variable Initialization
-----------------------
When declaring a (non-static) pointer variable, always initialize it to `NULL`.
Even in the case of static pointer variables, it's recommended to explicitly
initialize them to `NULL`.
For private headers:
src/core/channel/channel_stack.h --> GRPC_INTERNAL_CORE_CHANNEL_CHANNEL_STACK_H
C99 Features
------------
- Variable sized arrays are not allowed
- Do not use the 'inline' keyword
- Flexible array members are allowed (https://en.wikipedia.org/wiki/Flexible_array_member)
- Variable sized arrays are not allowed.
- Do not use the 'inline' keyword.
- Flexible array members are allowed
(https://en.wikipedia.org/wiki/Flexible_array_member).
Comments
--------
Within public header files, only `/* */` comments are allowed.
Within implementation files and private headers, either single line `//`
Within implementation files and private headers, either single line `//`
or multi line `/* */` comments are allowed. Only one comment style per file is
allowed however (i.e. if single line comments are used anywhere within a file,
ALL comments within that file must be single line comments).
@ -59,7 +70,15 @@ ALL comments within that file must be single line comments).
Symbol Names
------------
- Non-static functions must be prefixed by grpc_
- static functions must not be prefixed by grpc_
- enumeration values and #define names are uppercased, all others are lowercased
- Multiple word identifiers use underscore as a delimiter (NEVER camel casing)
- Non-static functions must be prefixed by `grpc_`
- Static functions must *not* be prefixed by `grpc_`
- Enumeration values and `#define` names must be uppercase. All other values
must be lowercase.
- Multiple word identifiers use underscore as a delimiter, *never* camel
case. E.g. `variable_name`.
Functions
----------
- The use of [`atexit()`](http://man7.org/linux/man-pages/man3/atexit.3.html) is
in forbidden in libgrpc.

@ -15,6 +15,7 @@ The command line tool can do the following things:
- Send unary rpc.
- Attach metadata and display received metadata.
- Handle common authentication to server.
- Infer request/response types from server reflection result.
- Find the request/response types from a given proto file.
- Read proto request in text form.
- Read request in wire form (for protobuf messages, this means serialized binary form).
@ -24,7 +25,6 @@ The command line tool can do the following things:
The command line tool should support the following things:
- List server services and methods through server reflection.
- Infer request/response types from server reflection result.
- Fine-grained auth control (such as, use this oauth token to talk to the server).
- Send streaming rpc.
@ -46,24 +46,35 @@ https://github.com/grpc/grpc/blob/master/test/cpp/util/grpc_cli.cc
Send a rpc to a helloworld server at `localhost:50051`:
```
$ bins/opt/grpc_cli call localhost:50051 SayHello examples/protos/helloworld.proto \
"name: 'world'" --enable_ssl=false
$ bins/opt/grpc_cli call localhost:50051 SayHello "name: 'world'" \
--enable_ssl=false
```
On success, the tool will print out
```
Rpc succeeded with OK status
Response:
Response:
message: "Hello world"
```
The `localhost:50051` part indicates the server you are connecting to. `SayHello` is (part of) the
gRPC method string. Then there is the path to the proto file containing the service definition,
if it is not under current directory, you can use `--proto_path` to specify a new search root.
`"name: 'world'"` is the text format of the request proto message.
We are not using ssl here by `--enable_ssl=false`. For information on more
flags, look at the comments of `grpc_cli.cc`.
gRPC method string. Then `"name: 'world'"` is the text format of the request proto message. We are
not using ssl here by `--enable_ssl=false`. For information on more flags, look at the comments of `grpc_cli.cc`.
### Use local proto files
If the server does not have the server reflection service, you will need to provide local proto
files containing the service definition. The tool will try to find request/response types from
them.
```
$ bins/opt/grpc_cli call localhost:50051 SayHello "name: 'world'" \
--protofiles=examples/protos/helloworld.proto --enable_ssl=false
```
If the proto files is not under current directory, you can use `--proto_path` to specify a new
search root.
### Send non-proto rpc

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

@ -4,7 +4,7 @@ Load Balancing in gRPC
# Objective
To design a load balancing API between a gRPC client and a Load Balancer to
instruct the client how to send load to multiple backend servers.
instruct the client how to send load to multiple backend servers.
# Background
@ -19,7 +19,7 @@ have temporary copies of the RPC request and response. This model also increases
latency to the RPCs.
The proxy model was deemed inefficient when considering request heavy services
like storage.
like storage.
### Balancing-aware Client
@ -28,7 +28,7 @@ example, the client could contain many load balancing policies (Round Robin,
Random, etc) used to select servers from a list. In this model, a list of
servers would be either statically configured in the client, provided by the
name resolution system, an external load balancer, etc. In any case, the client
is responsible for choosing the preferred server from the list.
is responsible for choosing the preferred server from the list.
One of the drawbacks of this approach is writing and maintaining the load
balancing policies in multiple languages and/or versions of the clients. These
@ -53,14 +53,69 @@ unavailability or health issues. The load balancer will make any necessary
complex decisions and inform the client. The load balancer may communicate with
the backend servers to collect load and health information.
## Requirements
#### Simple API and client
The gRPC client load balancing code must be simple and portable. The client
should only contain simple algorithms (ie Round Robin) for server selection. For
complex algorithms, the client should rely on a load balancer to provide load
balancing configuration and the list of servers to which the client should send
requests. The balancer will update the server list as needed to balance the load
as well as handle server unavailability or health issues. The load balancer will
make any necessary complex decisions and inform the client. The load balancer
may communicate with the backend servers to collect load and health information.
#### Security
The load balancer may be separate from the actual server backends and a
compromise of the load balancer should only lead to a compromise of the
loadbalancing functionality. In other words, a compromised load balancer should
not be able to cause a client to trust a (potentially malicious) backend server
any more than in a comparable situation without loadbalancing.
# Proposed Architecture
The gRPC load balancing approach follows the third approach, by having an
external load balancer which provides simple clients with a list of servers.
The gRPC load balancing implements the external load balancing server approach:
an external load balancer provides simple clients with an up-to-date list of
servers.
![image](images/load_balancing_design.png)
1. On startup, the gRPC client issues a name resolution request for the service.
The name will resolve to one or more IP addresses to gRPC servers, a hint on
whether the IP address(es) point to a load balancer or not, and also return a
client config.
2. The gRPC client connects to a gRPC Server.
1. If the name resolution has hinted that the endpoint is a load balancer,
the client's gRPC LB policy will attempt to open a stream to the load
balancer service. The server may respond in only one of the following
ways.
1. `status::UNIMPLEMENTED`. There is no loadbalancing in use. The client
call will fail.
2. "I am a Load Balancer and here is the server list." (Goto Step 4.)
3. "Please contact Load Balancer X" (See Step 3.) The client will close
this connection and cancel the stream.
4. If the server fails to respond, the client will wait for some timeout
and then re-resolve the name (process to Step 1 above).
2. If the name resolution has not hinted that the endpoint is a load
balancer, the client connects directly to the service it wants to talk to.
3. The gRPC client's gRPC LB policy opens a separate connection to the Load
Balancer. If this fails, it will go back to step 1 and try another address.
1. During channel initialization to the Load Balancer, the client will
attempt to open a stream to the Load Balancer service.
2. The Load Balancer will return a server list to the gRPC client. If the
server list is empty, the call will wait until a non-empty one is
received. Optional: The Load Balancer will also open channels to the gRPC
servers if load reporting is needed.
4. The gRPC client will send RPCs to the gRPC servers contained in the server
list from the Load Balancer.
5. Optional: The gRPC servers may periodically report load to the Load Balancer.
## Client
When establishing a gRPC stream to the balancer, the client will send an initial
When establishing a gRPC _stream_ to the balancer, the client will send an initial
request to the load balancer (via a regular gRPC message). The load balancer
will respond with client config (including, for example, settings for flow
control, RPC deadlines, etc.) or a redirect to another load balancer. If the
@ -87,11 +142,3 @@ balancer in order to compute the next list of servers.
The gRPC Server is responsible for answering RPC requests and providing
responses to the client. The server will also report load to the load balancer
if a reporting stream was opened for this purpose.
### Security
The load balancer may be separate from the actual server backends and a
compromise of the load balancer should only lead to a compromise of the
loadbalancing functionality. In other words, a compromised load balancer should
not be able to cause a client to trust a (potentially malicious) backend server
any more than in a comparable situation without loadbalancing.

@ -18,6 +18,7 @@ Only a subset of the pre-defined status codes are generated by the gRPC librarie
| Could not decompress, but compression algorithm supported (Server -> Client) | INTERNAL | Client |
| Compression mechanism used by client not supported at server | UNIMPLEMENTED | Server |
| Server temporarily out of resources (e.g., Flow-control resource limits reached) | RESOURCE_EXHAUSTED | Server|
| Client does not have enough memory to hold the server response | RESOURCE_EXHAUSTED | Client |
| Flow-control protocol violation | INTERNAL | Both |
| Error parsing returned status | UNKNOWN | Client |
| Incorrect Auth metadata ( Credentials failed to get metadata, Incompatible credentials set on channel and call, Invalid host set in `:authority` metadata, etc.) | UNAUTHENTICATED | Both |

File diff suppressed because it is too large Load Diff

@ -0,0 +1,49 @@
# Minimum CMake required
cmake_minimum_required(VERSION 2.8)
# Project
project(HelloWorld CXX)
# Protobuf
set(protobuf_MODULE_COMPATIBLE TRUE)
find_package(protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${protobuf_VERSION}")
# gRPC
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
# gRPC C++ plugin
get_target_property(gRPC_CPP_PLUGIN_EXECUTABLE gRPC::grpc_cpp_plugin
IMPORTED_LOCATION_RELEASE)
# Proto file
get_filename_component(hw_proto "../../protos/helloworld.proto" ABSOLUTE)
get_filename_component(hw_proto_path "${hw_proto}" PATH)
# Generated sources
protobuf_generate_cpp(hw_proto_srcs hw_proto_hdrs "${hw_proto}")
set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc")
set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h")
add_custom_command(
OUTPUT "${hw_grpc_srcs}" "${hw_grpc_hdrs}"
COMMAND protobuf::protoc
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" -I "${hw_proto_path}"
--plugin=protoc-gen-grpc="${gRPC_CPP_PLUGIN_EXECUTABLE}"
"${hw_proto}"
DEPENDS "${hw_proto}")
# Generated include directory
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
# Targets greeter_[async_](client|server)
foreach(_target
greeter_client greeter_server
greeter_async_client greeter_async_server)
add_executable(${_target} "${_target}.cc"
${hw_proto_srcs}
${hw_grpc_srcs})
target_link_libraries(${_target}
protobuf::libprotobuf
gRPC::grpc++_unsecure)
endforeach()

@ -29,10 +29,20 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
SYSTEM ?= $(HOST_SYSTEM)
CXX = g++
CPPFLAGS += -I/usr/local/include -pthread
CXXFLAGS += -std=c++11
LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++ grpc` -lprotobuf -lpthread -ldl
ifeq ($(SYSTEM),Darwin)
LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++ grpc` \
-lgrpc++_reflection \
-lprotobuf -lpthread -ldl
else
LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++ grpc` \
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed \
-lprotobuf -lpthread -ldl
endif
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`

@ -29,10 +29,20 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
SYSTEM ?= $(HOST_SYSTEM)
CXX = g++
CPPFLAGS += -I/usr/local/include -pthread
CXXFLAGS += -std=c++11
LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` -lprotobuf -lpthread -ldl
ifeq ($(SYSTEM),Darwin)
LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` \
-lgrpc++_reflection \
-lprotobuf -lpthread -ldl
else
LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` \
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed \
-lprotobuf -lpthread -ldl
endif
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`

@ -5,23 +5,16 @@ BACKGROUND
-------------
For this sample, we've already generated the server and client stubs from [helloworld.proto][].
Example projects depend on the [Grpc](https://www.nuget.org/packages/Grpc/)
Example projects depend on the [Grpc](https://www.nuget.org/packages/Grpc/), [Grpc.Tools](https://www.nuget.org/packages/Grpc.Tools/)
and [Google.Protobuf](https://www.nuget.org/packages/Google.Protobuf/) NuGet packages
which have been already added to the project for you.
PREREQUISITES
-------------
**Windows**
- .NET 4.5+
- Visual Studio 2013 or 2015
**Linux**
- Mono 4.0+
- Monodevelop 5.9+ (with NuGet plugin installed)
**Mac OS X**
- Xamarin Studio 5.9+
- [homebrew][]
- Windows: .NET Framework 4.5+, Visual Studio 2013 or 2015
- Linux: Mono 4+, MonoDevelop 5.9+ (with NuGet add-in installed)
- Mac OS X: Xamarin Studio 5.9+
BUILD
-------
@ -56,6 +49,5 @@ Tutorial
You can find a more detailed tutorial in [gRPC Basics: C#][]
[homebrew]:http://brew.sh
[helloworld.proto]:../../protos/helloworld.proto
[gRPC Basics: C#]:http://www.grpc.io/docs/tutorials/basic/csharp.html

@ -13,27 +13,51 @@ Pod::Spec.new do |s|
# Base directory where the .proto files are.
src = "../../protos"
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0-pre1"
# Pods directory corresponding to this app's Podfile, relative to the location of this podspec.
pods_root = 'Pods'
# Path where Cocoapods downloads protoc and the gRPC plugin.
protoc_dir = "#{pods_root}/!ProtoCompiler"
protoc = "#{protoc_dir}/protoc"
plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin"
# Directory where the generated files will be placed.
dir = "Pods/" + s.name
dir = "#{pods_root}/#{s.name}"
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.prepare_command = <<-CMD
mkdir -p #{dir}
protoc -I #{src} --objc_out=#{dir} --objcgrpc_out=#{dir} #{src}/auth_sample.proto
#{protoc} \
--plugin=protoc-gen-grpc=#{plugin} \
--objc_out=#{dir} \
--grpc_out=#{dir} \
-I #{src} \
-I #{protoc_dir} \
#{src}/auth_sample.proto
CMD
# Files generated by protoc
s.subspec "Messages" do |ms|
ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}"
ms.header_mappings_dir = dir
ms.requires_arc = false
ms.dependency "Protobuf", "~> 3.0.0-alpha-4"
# The generated files depend on the protobuf runtime.
ms.dependency "Protobuf"
# This is needed by all pods that depend on Protobuf:
ms.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1',
}
end
# Files generated by the gRPC plugin
s.subspec "Services" do |ss|
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
ss.header_mappings_dir = dir
ss.requires_arc = true
ss.dependency "gRPC", "~> 0.12"
# The generated files depend on the gRPC runtime, and on the files generated by protoc.
ss.dependency "gRPC-ProtoRPC"
ss.dependency "#{s.name}/Messages"
end
end

@ -2,9 +2,39 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AD_UNIT_ID_FOR_BANNER_TEST</key>
<string>redacted</string>
<key>AD_UNIT_ID_FOR_INTERSTITIAL_TEST</key>
<string>redacted</string>
<key>CLIENT_ID</key>
<string>15087385131-lh9bpkiai9nls53uadju0if6k7un3uih.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.15087385131-lh9bpkiai9nls53uadju0if6k7un3uih</string>
<key>API_KEY</key>
<string>redacted</string>
<key>GCM_SENDER_ID</key>
<string>redacted</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>io.grpc.AuthSample</string>
<key>PROJECT_ID</key>
<string>grpc-authsample</string>
<key>STORAGE_BUCKET</key>
<string>grpc-authsample.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false/>
<key>IS_ANALYTICS_ENABLED</key>
<false/>
<key>IS_APPINVITE_ENABLED</key>
<false/>
<key>IS_GCM_ENABLED</key>
<false/>
<key>IS_SIGNIN_ENABLED</key>
<true/>
<key>GOOGLE_APP_ID</key>
<string>1:15087385131:ios:d547168abe3c362f</string>
<key>DATABASE_URL</key>
<string>https://grpc-authsample.firebaseio.com</string>
</dict>
</plist>
</plist>

@ -3,44 +3,10 @@ platform :ios, '8.0'
install! 'cocoapods', :deterministic_uuids => false
# Location of gRPC's repo root relative to this file.
GRPC_LOCAL_SRC = '../../..'
target 'AuthSample' do
# Depend on the generated AuthTestService library.
pod 'AuthTestService', :path => '.'
# Depend on Google's OAuth2 library
pod 'Google/SignIn'
# Use the local versions of Protobuf, BoringSSL, and gRPC. You don't need any of the following
# lines in your application.
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'gRPC', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC
end
# This pre_install hook is only needed to use the local version of gRPC-Core. You don't need it in
# your application.
pre_install do |installer|
# This is the gRPC-Core podspec object, as initialized by its podspec file.
grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
# Copied from gRPC-Core.podspec, except for the adjusted src_root:
src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
grpc_core_spec.pod_target_xcconfig = {
'GRPC_SRC_ROOT' => src_root,
'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
# If we don't set these two settings, `include/grpc/support/time.h` and
# `src/core/lib/support/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
# build.
'USE_HEADERMAP' => 'NO',
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
}
end

@ -13,27 +13,51 @@ Pod::Spec.new do |s|
# Base directory where the .proto files are.
src = "../../protos"
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0-pre1"
# Pods directory corresponding to this app's Podfile, relative to the location of this podspec.
pods_root = 'Pods'
# Path where Cocoapods downloads protoc and the gRPC plugin.
protoc_dir = "#{pods_root}/!ProtoCompiler"
protoc = "#{protoc_dir}/protoc"
plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin"
# Directory where the generated files will be placed.
dir = "Pods/" + s.name
dir = "#{pods_root}/#{s.name}"
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.prepare_command = <<-CMD
mkdir -p #{dir}
protoc -I #{src} --objc_out=#{dir} --objcgrpc_out=#{dir} #{src}/helloworld.proto
#{protoc} \
--plugin=protoc-gen-grpc=#{plugin} \
--objc_out=#{dir} \
--grpc_out=#{dir} \
-I #{src} \
-I #{protoc_dir} \
#{src}/helloworld.proto
CMD
# Files generated by protoc
s.subspec "Messages" do |ms|
ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}"
ms.header_mappings_dir = dir
ms.requires_arc = false
ms.dependency "Protobuf", "~> 3.0.0-alpha-4"
# The generated files depend on the protobuf runtime.
ms.dependency "Protobuf"
# This is needed by all pods that depend on Protobuf:
ms.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1',
}
end
# Files generated by the gRPC plugin
s.subspec "Services" do |ss|
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
ss.header_mappings_dir = dir
ss.requires_arc = true
ss.dependency "gRPC", "~> 0.12"
# The generated files depend on the gRPC runtime, and on the files generated by protoc.
ss.dependency "gRPC-ProtoRPC"
ss.dependency "#{s.name}/Messages"
end
end

@ -3,41 +3,7 @@ platform :ios, '8.0'
install! 'cocoapods', :deterministic_uuids => false
# Location of gRPC's repo root relative to this file.
GRPC_LOCAL_SRC = '../../..'
target 'HelloWorld' do
# Depend on the generated HelloWorld library.
pod 'HelloWorld', :path => '.'
# Use the local versions of Protobuf, BoringSSL, and gRPC. You don't need any of the following
# lines in your application.
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'gRPC', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC
end
# This pre_install hook is only needed to use the local version of gRPC-Core. You don't need it in
# your application.
pre_install do |installer|
# This is the gRPC-Core podspec object, as initialized by its podspec file.
grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
# Copied from gRPC-Core.podspec, except for the adjusted src_root:
src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
grpc_core_spec.pod_target_xcconfig = {
'GRPC_SRC_ROOT' => src_root,
'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
# If we don't set these two settings, `include/grpc/support/time.h` and
# `src/core/lib/support/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
# build.
'USE_HEADERMAP' => 'NO',
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
}
end

@ -3,41 +3,7 @@ platform :ios, '8.0'
install! 'cocoapods', :deterministic_uuids => false
# Location of gRPC's repo root relative to this file.
GRPC_LOCAL_SRC = '../../..'
target 'RouteGuideClient' do
# Depend on the generated RouteGuide library.
pod 'RouteGuide', :path => '.'
# Use the local versions of Protobuf, BoringSSL, and gRPC. You don't need any of the following
# lines in your application.
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf"
pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'gRPC', :path => GRPC_LOCAL_SRC
pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC
end
# This pre_install hook is only needed to use the local version of gRPC-Core. You don't need it in
# your application.
pre_install do |installer|
# This is the gRPC-Core podspec object, as initialized by its podspec file.
grpc_core_spec = installer.pod_targets.find{|t| t.name == 'gRPC-Core'}.root_spec
# Copied from gRPC-Core.podspec, except for the adjusted src_root:
src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}"
grpc_core_spec.pod_target_xcconfig = {
'GRPC_SRC_ROOT' => src_root,
'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"',
'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"',
# If we don't set these two settings, `include/grpc/support/time.h` and
# `src/core/lib/support/string.h` shadow the system `<time.h>` and `<string.h>`, breaking the
# build.
'USE_HEADERMAP' => 'NO',
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
}
end

@ -13,27 +13,51 @@ Pod::Spec.new do |s|
# Base directory where the .proto files are.
src = "../../protos"
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.dependency "!ProtoCompiler-gRPCPlugin", "~> 1.0.0-pre1"
# Pods directory corresponding to this app's Podfile, relative to the location of this podspec.
pods_root = 'Pods'
# Path where Cocoapods downloads protoc and the gRPC plugin.
protoc_dir = "#{pods_root}/!ProtoCompiler"
protoc = "#{protoc_dir}/protoc"
plugin = "#{pods_root}/!ProtoCompiler-gRPCPlugin/grpc_objective_c_plugin"
# Directory where the generated files will be placed.
dir = "Pods/" + s.name
dir = "#{pods_root}/#{s.name}"
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.prepare_command = <<-CMD
mkdir -p #{dir}
protoc -I #{src} --objc_out=#{dir} --objcgrpc_out=#{dir} #{src}/route_guide.proto
#{protoc} \
--plugin=protoc-gen-grpc=#{plugin} \
--objc_out=#{dir} \
--grpc_out=#{dir} \
-I #{src} \
-I #{protoc_dir} \
#{src}/route_guide.proto
CMD
# Files generated by protoc
s.subspec "Messages" do |ms|
ms.source_files = "#{dir}/*.pbobjc.{h,m}", "#{dir}/**/*.pbobjc.{h,m}"
ms.header_mappings_dir = dir
ms.requires_arc = false
ms.dependency "Protobuf", "~> 3.0.0-alpha-4"
# The generated files depend on the protobuf runtime.
ms.dependency "Protobuf"
# This is needed by all pods that depend on Protobuf:
ms.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1',
}
end
# Files generated by the gRPC plugin
s.subspec "Services" do |ss|
ss.source_files = "#{dir}/*.pbrpc.{h,m}", "#{dir}/**/*.pbrpc.{h,m}"
ss.header_mappings_dir = dir
ss.requires_arc = true
ss.dependency "gRPC", "~> 0.12"
# The generated files depend on the gRPC runtime, and on the files generated by protoc.
ss.dependency "gRPC-ProtoRPC"
ss.dependency "#{s.name}/Messages"
end
end

@ -11,7 +11,7 @@ INSTALL
- Install the gRPC PHP extension
```sh
$ [sudo] pecl install grpc-beta
$ [sudo] pecl install grpc
```
- Clone this repository

@ -2,13 +2,7 @@
"name": "grpc/grpc-demo",
"description": "gRPC example for PHP",
"minimum-stability": "dev",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/stanley-cheung/Protobuf-PHP"
}
],
"require": {
"grpc/grpc": "v0.15.0"
"grpc/grpc": "v0.15.2"
}
}

@ -31,17 +31,15 @@
from __future__ import print_function
from grpc.beta import implementations
import grpc
import helloworld_pb2
_TIMEOUT_SECONDS = 10
def run():
channel = implementations.insecure_channel('localhost', 50051)
stub = helloworld_pb2.beta_create_Greeter_stub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'), _TIMEOUT_SECONDS)
channel = grpc.insecure_channel('localhost:50051')
stub = helloworld_pb2.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + response.message)

@ -29,21 +29,25 @@
"""The Python implementation of the GRPC helloworld.Greeter server."""
from concurrent import futures
import time
import grpc
import helloworld_pb2
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class Greeter(helloworld_pb2.BetaGreeterServicer):
class Greeter(helloworld_pb2.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
def serve():
server = helloworld_pb2.beta_create_Greeter_server(Greeter())
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('[::]:50051')
server.start()
try:

@ -107,13 +107,55 @@ _sym_db.RegisterMessage(HelloReply)
DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW'))
import abc
import six
import grpc
from grpc.beta import implementations as beta_implementations
from grpc.beta import interfaces as beta_interfaces
from grpc.framework.common import cardinality
from grpc.framework.interfaces.face import utilities as face_utilities
class GreeterStub(object):
"""The greeting service definition.
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.SayHello = channel.unary_unary(
'/helloworld.Greeter/SayHello',
request_serializer=HelloRequest.SerializeToString,
response_deserializer=HelloReply.FromString,
)
class GreeterServicer(object):
"""The greeting service definition.
"""
def SayHello(self, request, context):
"""Sends a greeting
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_GreeterServicer_to_server(servicer, server):
rpc_method_handlers = {
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello,
request_deserializer=HelloRequest.FromString,
response_serializer=HelloReply.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'helloworld.Greeter', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
class BetaGreeterServicer(object):
"""The greeting service definition.
"""
@ -122,23 +164,23 @@ class BetaGreeterServicer(object):
"""
context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
class BetaGreeterStub(object):
"""The greeting service definition.
"""
def SayHello(self, request, timeout):
def SayHello(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
"""Sends a greeting
"""
raise NotImplementedError()
SayHello.future = None
def beta_create_Greeter_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None):
import helloworld_pb2
import helloworld_pb2
request_deserializers = {
('helloworld.Greeter', 'SayHello'): helloworld_pb2.HelloRequest.FromString,
('helloworld.Greeter', 'SayHello'): HelloRequest.FromString,
}
response_serializers = {
('helloworld.Greeter', 'SayHello'): helloworld_pb2.HelloReply.SerializeToString,
('helloworld.Greeter', 'SayHello'): HelloReply.SerializeToString,
}
method_implementations = {
('helloworld.Greeter', 'SayHello'): face_utilities.unary_unary_inline(servicer.SayHello),
@ -146,14 +188,13 @@ def beta_create_Greeter_server(servicer, pool=None, pool_size=None, default_time
server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout)
return beta_implementations.server(method_implementations, options=server_options)
def beta_create_Greeter_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None):
import helloworld_pb2
import helloworld_pb2
request_serializers = {
('helloworld.Greeter', 'SayHello'): helloworld_pb2.HelloRequest.SerializeToString,
('helloworld.Greeter', 'SayHello'): HelloRequest.SerializeToString,
}
response_deserializers = {
('helloworld.Greeter', 'SayHello'): helloworld_pb2.HelloReply.FromString,
('helloworld.Greeter', 'SayHello'): HelloReply.FromString,
}
cardinalities = {
'SayHello': cardinality.Cardinality.UNARY_UNARY,

@ -27,4 +27,16 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Runs protoc with the gRPC plugin to generate messages and gRPC stubs."""
from grpc.tools import protoc
protoc.main(
(
'',
'-I../../protos',
'--python_out=.',
'--grpc_python_out=.',
'../../protos/helloworld.proto',
)
)

@ -0,0 +1 @@
An example showing two stubs sharing a channel and two servicers sharing a server.

@ -0,0 +1,204 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: helloworld.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='helloworld.proto',
package='helloworld',
syntax='proto3',
serialized_pb=_b('\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3')
)
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
_HELLOREQUEST = _descriptor.Descriptor(
name='HelloRequest',
full_name='helloworld.HelloRequest',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='name', full_name='helloworld.HelloRequest.name', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=32,
serialized_end=60,
)
_HELLOREPLY = _descriptor.Descriptor(
name='HelloReply',
full_name='helloworld.HelloReply',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='message', full_name='helloworld.HelloReply.message', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=62,
serialized_end=91,
)
DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST
DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY
HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict(
DESCRIPTOR = _HELLOREQUEST,
__module__ = 'helloworld_pb2'
# @@protoc_insertion_point(class_scope:helloworld.HelloRequest)
))
_sym_db.RegisterMessage(HelloRequest)
HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), dict(
DESCRIPTOR = _HELLOREPLY,
__module__ = 'helloworld_pb2'
# @@protoc_insertion_point(class_scope:helloworld.HelloReply)
))
_sym_db.RegisterMessage(HelloReply)
DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW'))
import grpc
from grpc.beta import implementations as beta_implementations
from grpc.beta import interfaces as beta_interfaces
from grpc.framework.common import cardinality
from grpc.framework.interfaces.face import utilities as face_utilities
class GreeterStub(object):
"""The greeting service definition.
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.SayHello = channel.unary_unary(
'/helloworld.Greeter/SayHello',
request_serializer=HelloRequest.SerializeToString,
response_deserializer=HelloReply.FromString,
)
class GreeterServicer(object):
"""The greeting service definition.
"""
def SayHello(self, request, context):
"""Sends a greeting
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_GreeterServicer_to_server(servicer, server):
rpc_method_handlers = {
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello,
request_deserializer=HelloRequest.FromString,
response_serializer=HelloReply.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'helloworld.Greeter', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
class BetaGreeterServicer(object):
"""The greeting service definition.
"""
def SayHello(self, request, context):
"""Sends a greeting
"""
context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
class BetaGreeterStub(object):
"""The greeting service definition.
"""
def SayHello(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
"""Sends a greeting
"""
raise NotImplementedError()
SayHello.future = None
def beta_create_Greeter_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None):
request_deserializers = {
('helloworld.Greeter', 'SayHello'): HelloRequest.FromString,
}
response_serializers = {
('helloworld.Greeter', 'SayHello'): HelloReply.SerializeToString,
}
method_implementations = {
('helloworld.Greeter', 'SayHello'): face_utilities.unary_unary_inline(servicer.SayHello),
}
server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout)
return beta_implementations.server(method_implementations, options=server_options)
def beta_create_Greeter_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None):
request_serializers = {
('helloworld.Greeter', 'SayHello'): HelloRequest.SerializeToString,
}
response_deserializers = {
('helloworld.Greeter', 'SayHello'): HelloReply.FromString,
}
cardinalities = {
'SayHello': cardinality.Cardinality.UNARY_UNARY,
}
stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size)
return beta_implementations.dynamic_stub(channel, 'helloworld.Greeter', cardinalities, options=stub_options)
# @@protoc_insertion_point(module_scope)

@ -0,0 +1,139 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""A client that makes both Greeter and RouteGuide RPCs."""
from __future__ import print_function
import random
import time
import grpc
import helloworld_pb2
import route_guide_pb2
import route_guide_resources
def make_route_note(message, latitude, longitude):
return route_guide_pb2.RouteNote(
message=message,
location=route_guide_pb2.Point(latitude=latitude, longitude=longitude))
def guide_get_one_feature(route_guide_stub, point):
feature = route_guide_stub.GetFeature(point)
if not feature.location:
print("Server returned incomplete feature")
return
if feature.name:
print("Feature called %s at %s" % (feature.name, feature.location))
else:
print("Found no feature at %s" % feature.location)
def guide_get_feature(route_guide_stub):
guide_get_one_feature(
route_guide_stub,
route_guide_pb2.Point(latitude=409146138, longitude=-746188906))
guide_get_one_feature(
route_guide_stub, route_guide_pb2.Point(latitude=0, longitude=0))
def guide_list_features(route_guide_stub):
rectangle = route_guide_pb2.Rectangle(
lo=route_guide_pb2.Point(latitude=400000000, longitude=-750000000),
hi=route_guide_pb2.Point(latitude=420000000, longitude=-730000000))
print("Looking for features between 40, -75 and 42, -73")
features = route_guide_stub.ListFeatures(rectangle)
for feature in features:
print("Feature called %s at %s" % (feature.name, feature.location))
def generate_route(feature_list):
for _ in range(0, 10):
random_feature = feature_list[random.randint(0, len(feature_list) - 1)]
print("Visiting point %s" % random_feature.location)
yield random_feature.location
time.sleep(random.uniform(0.5, 1.5))
def guide_record_route(route_guide_stub):
feature_list = route_guide_resources.read_route_guide_database()
route_iterator = generate_route(feature_list)
route_summary = route_guide_stub.RecordRoute(route_iterator)
print("Finished trip with %s points " % route_summary.point_count)
print("Passed %s features " % route_summary.feature_count)
print("Travelled %s meters " % route_summary.distance)
print("It took %s seconds " % route_summary.elapsed_time)
def generate_messages():
messages = [
make_route_note("First message", 0, 0),
make_route_note("Second message", 0, 1),
make_route_note("Third message", 1, 0),
make_route_note("Fourth message", 0, 0),
make_route_note("Fifth message", 1, 0),
]
for msg in messages:
print("Sending %s at %s" % (msg.message, msg.location))
yield msg
time.sleep(random.uniform(0.5, 1.0))
def guide_route_chat(route_guide_stub):
responses = route_guide_stub.RouteChat(generate_messages())
for response in responses:
print("Received message %s at %s" % (response.message, response.location))
def run():
channel = grpc.insecure_channel('localhost:50051')
greeter_stub = helloworld_pb2.GreeterStub(channel)
route_guide_stub = route_guide_pb2.RouteGuideStub(channel)
greeter_response = greeter_stub.SayHello(
helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + greeter_response.message)
print("-------------- GetFeature --------------")
guide_get_feature(route_guide_stub)
print("-------------- ListFeatures --------------")
guide_list_features(route_guide_stub)
print("-------------- RecordRoute --------------")
guide_record_route(route_guide_stub)
print("-------------- RouteChat --------------")
guide_route_chat(route_guide_stub)
if __name__ == '__main__':
run()

@ -0,0 +1,149 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""A gRPC server servicing both Greeter and RouteGuide RPCs."""
from concurrent import futures
import time
import math
import grpc
import helloworld_pb2
import route_guide_pb2
import route_guide_resources
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
def _get_feature(feature_db, point):
"""Returns Feature at given location or None."""
for feature in feature_db:
if feature.location == point:
return feature
return None
def _get_distance(start, end):
"""Distance between two points."""
coord_factor = 10000000.0
lat_1 = start.latitude / coord_factor
lat_2 = end.latitude / coord_factor
lon_1 = start.longitude / coord_factor
lon_2 = end.longitude / coord_factor
lat_rad_1 = math.radians(lat_1)
lat_rad_2 = math.radians(lat_2)
delta_lat_rad = math.radians(lat_2 - lat_1)
delta_lon_rad = math.radians(lon_2 - lon_1)
a = (pow(math.sin(delta_lat_rad / 2), 2) +
(math.cos(lat_rad_1) * math.cos(lat_rad_2) *
pow(math.sin(delta_lon_rad / 2), 2)))
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
R = 6371000; # metres
return R * c;
class _GreeterServicer(helloworld_pb2.GreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, {}!'.format(request.name))
class _RouteGuideServicer(route_guide_pb2.RouteGuideServicer):
"""Provides methods that implement functionality of route guide server."""
def __init__(self):
self.db = route_guide_resources.read_route_guide_database()
def GetFeature(self, request, context):
feature = _get_feature(self.db, request)
if feature is None:
return route_guide_pb2.Feature(name="", location=request)
else:
return feature
def ListFeatures(self, request, context):
left = min(request.lo.longitude, request.hi.longitude)
right = max(request.lo.longitude, request.hi.longitude)
top = max(request.lo.latitude, request.hi.latitude)
bottom = min(request.lo.latitude, request.hi.latitude)
for feature in self.db:
if (feature.location.longitude >= left and
feature.location.longitude <= right and
feature.location.latitude >= bottom and
feature.location.latitude <= top):
yield feature
def RecordRoute(self, request_iterator, context):
point_count = 0
feature_count = 0
distance = 0.0
prev_point = None
start_time = time.time()
for point in request_iterator:
point_count += 1
if _get_feature(self.db, point):
feature_count += 1
if prev_point:
distance += _get_distance(prev_point, point)
prev_point = point
elapsed_time = time.time() - start_time
return route_guide_pb2.RouteSummary(point_count=point_count,
feature_count=feature_count,
distance=int(distance),
elapsed_time=int(elapsed_time))
def RouteChat(self, request_iterator, context):
prev_notes = []
for new_note in request_iterator:
for prev_note in prev_notes:
if prev_note.location == new_note.location:
yield prev_note
prev_notes.append(new_note)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2.add_GreeterServicer_to_server(_GreeterServicer(), server)
route_guide_pb2.add_RouteGuideServicer_to_server(
_RouteGuideServicer(), server)
server.add_insecure_port('[::]:50051')
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()

@ -0,0 +1,601 @@
[{
"location": {
"latitude": 407838351,
"longitude": -746143763
},
"name": "Patriots Path, Mendham, NJ 07945, USA"
}, {
"location": {
"latitude": 408122808,
"longitude": -743999179
},
"name": "101 New Jersey 10, Whippany, NJ 07981, USA"
}, {
"location": {
"latitude": 413628156,
"longitude": -749015468
},
"name": "U.S. 6, Shohola, PA 18458, USA"
}, {
"location": {
"latitude": 419999544,
"longitude": -740371136
},
"name": "5 Conners Road, Kingston, NY 12401, USA"
}, {
"location": {
"latitude": 414008389,
"longitude": -743951297
},
"name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA"
}, {
"location": {
"latitude": 419611318,
"longitude": -746524769
},
"name": "287 Flugertown Road, Livingston Manor, NY 12758, USA"
}, {
"location": {
"latitude": 406109563,
"longitude": -742186778
},
"name": "4001 Tremley Point Road, Linden, NJ 07036, USA"
}, {
"location": {
"latitude": 416802456,
"longitude": -742370183
},
"name": "352 South Mountain Road, Wallkill, NY 12589, USA"
}, {
"location": {
"latitude": 412950425,
"longitude": -741077389
},
"name": "Bailey Turn Road, Harriman, NY 10926, USA"
}, {
"location": {
"latitude": 412144655,
"longitude": -743949739
},
"name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA"
}, {
"location": {
"latitude": 415736605,
"longitude": -742847522
},
"name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA"
}, {
"location": {
"latitude": 413843930,
"longitude": -740501726
},
"name": "162 Merrill Road, Highland Mills, NY 10930, USA"
}, {
"location": {
"latitude": 410873075,
"longitude": -744459023
},
"name": "Clinton Road, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 412346009,
"longitude": -744026814
},
"name": "16 Old Brook Lane, Warwick, NY 10990, USA"
}, {
"location": {
"latitude": 402948455,
"longitude": -747903913
},
"name": "3 Drake Lane, Pennington, NJ 08534, USA"
}, {
"location": {
"latitude": 406337092,
"longitude": -740122226
},
"name": "6324 8th Avenue, Brooklyn, NY 11220, USA"
}, {
"location": {
"latitude": 406421967,
"longitude": -747727624
},
"name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA"
}, {
"location": {
"latitude": 416318082,
"longitude": -749677716
},
"name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA"
}, {
"location": {
"latitude": 415301720,
"longitude": -748416257
},
"name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA"
}, {
"location": {
"latitude": 402647019,
"longitude": -747071791
},
"name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA"
}, {
"location": {
"latitude": 412567807,
"longitude": -741058078
},
"name": "New York State Reference Route 987E, Southfields, NY 10975, USA"
}, {
"location": {
"latitude": 416855156,
"longitude": -744420597
},
"name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA"
}, {
"location": {
"latitude": 404663628,
"longitude": -744820157
},
"name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA"
}, {
"location": {
"latitude": 407113723,
"longitude": -749746483
},
"name": ""
}, {
"location": {
"latitude": 402133926,
"longitude": -743613249
},
"name": ""
}, {
"location": {
"latitude": 400273442,
"longitude": -741220915
},
"name": ""
}, {
"location": {
"latitude": 411236786,
"longitude": -744070769
},
"name": ""
}, {
"location": {
"latitude": 411633782,
"longitude": -746784970
},
"name": "211-225 Plains Road, Augusta, NJ 07822, USA"
}, {
"location": {
"latitude": 415830701,
"longitude": -742952812
},
"name": ""
}, {
"location": {
"latitude": 413447164,
"longitude": -748712898
},
"name": "165 Pedersen Ridge Road, Milford, PA 18337, USA"
}, {
"location": {
"latitude": 405047245,
"longitude": -749800722
},
"name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA"
}, {
"location": {
"latitude": 418858923,
"longitude": -746156790
},
"name": ""
}, {
"location": {
"latitude": 417951888,
"longitude": -748484944
},
"name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA"
}, {
"location": {
"latitude": 407033786,
"longitude": -743977337
},
"name": "26 East 3rd Street, New Providence, NJ 07974, USA"
}, {
"location": {
"latitude": 417548014,
"longitude": -740075041
},
"name": ""
}, {
"location": {
"latitude": 410395868,
"longitude": -744972325
},
"name": ""
}, {
"location": {
"latitude": 404615353,
"longitude": -745129803
},
"name": ""
}, {
"location": {
"latitude": 406589790,
"longitude": -743560121
},
"name": "611 Lawrence Avenue, Westfield, NJ 07090, USA"
}, {
"location": {
"latitude": 414653148,
"longitude": -740477477
},
"name": "18 Lannis Avenue, New Windsor, NY 12553, USA"
}, {
"location": {
"latitude": 405957808,
"longitude": -743255336
},
"name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA"
}, {
"location": {
"latitude": 411733589,
"longitude": -741648093
},
"name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA"
}, {
"location": {
"latitude": 412676291,
"longitude": -742606606
},
"name": "1270 Lakes Road, Monroe, NY 10950, USA"
}, {
"location": {
"latitude": 409224445,
"longitude": -748286738
},
"name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA"
}, {
"location": {
"latitude": 406523420,
"longitude": -742135517
},
"name": "652 Garden Street, Elizabeth, NJ 07202, USA"
}, {
"location": {
"latitude": 401827388,
"longitude": -740294537
},
"name": "349 Sea Spray Court, Neptune City, NJ 07753, USA"
}, {
"location": {
"latitude": 410564152,
"longitude": -743685054
},
"name": "13-17 Stanley Street, West Milford, NJ 07480, USA"
}, {
"location": {
"latitude": 408472324,
"longitude": -740726046
},
"name": "47 Industrial Avenue, Teterboro, NJ 07608, USA"
}, {
"location": {
"latitude": 412452168,
"longitude": -740214052
},
"name": "5 White Oak Lane, Stony Point, NY 10980, USA"
}, {
"location": {
"latitude": 409146138,
"longitude": -746188906
},
"name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA"
}, {
"location": {
"latitude": 404701380,
"longitude": -744781745
},
"name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 409642566,
"longitude": -746017679
},
"name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA"
}, {
"location": {
"latitude": 408031728,
"longitude": -748645385
},
"name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA"
}, {
"location": {
"latitude": 413700272,
"longitude": -742135189
},
"name": "367 Prospect Road, Chester, NY 10918, USA"
}, {
"location": {
"latitude": 404310607,
"longitude": -740282632
},
"name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA"
}, {
"location": {
"latitude": 409319800,
"longitude": -746201391
},
"name": "11 Ward Street, Mount Arlington, NJ 07856, USA"
}, {
"location": {
"latitude": 406685311,
"longitude": -742108603
},
"name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA"
}, {
"location": {
"latitude": 419018117,
"longitude": -749142781
},
"name": "43 Dreher Road, Roscoe, NY 12776, USA"
}, {
"location": {
"latitude": 412856162,
"longitude": -745148837
},
"name": "Swan Street, Pine Island, NY 10969, USA"
}, {
"location": {
"latitude": 416560744,
"longitude": -746721964
},
"name": "66 Pleasantview Avenue, Monticello, NY 12701, USA"
}, {
"location": {
"latitude": 405314270,
"longitude": -749836354
},
"name": ""
}, {
"location": {
"latitude": 414219548,
"longitude": -743327440
},
"name": ""
}, {
"location": {
"latitude": 415534177,
"longitude": -742900616
},
"name": "565 Winding Hills Road, Montgomery, NY 12549, USA"
}, {
"location": {
"latitude": 406898530,
"longitude": -749127080
},
"name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA"
}, {
"location": {
"latitude": 407586880,
"longitude": -741670168
},
"name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA"
}, {
"location": {
"latitude": 400106455,
"longitude": -742870190
},
"name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA"
}, {
"location": {
"latitude": 400066188,
"longitude": -746793294
},
"name": ""
}, {
"location": {
"latitude": 418803880,
"longitude": -744102673
},
"name": "40 Mountain Road, Napanoch, NY 12458, USA"
}, {
"location": {
"latitude": 414204288,
"longitude": -747895140
},
"name": ""
}, {
"location": {
"latitude": 414777405,
"longitude": -740615601
},
"name": ""
}, {
"location": {
"latitude": 415464475,
"longitude": -747175374
},
"name": "48 North Road, Forestburgh, NY 12777, USA"
}, {
"location": {
"latitude": 404062378,
"longitude": -746376177
},
"name": ""
}, {
"location": {
"latitude": 405688272,
"longitude": -749285130
},
"name": ""
}, {
"location": {
"latitude": 400342070,
"longitude": -748788996
},
"name": ""
}, {
"location": {
"latitude": 401809022,
"longitude": -744157964
},
"name": ""
}, {
"location": {
"latitude": 404226644,
"longitude": -740517141
},
"name": "9 Thompson Avenue, Leonardo, NJ 07737, USA"
}, {
"location": {
"latitude": 410322033,
"longitude": -747871659
},
"name": ""
}, {
"location": {
"latitude": 407100674,
"longitude": -747742727
},
"name": ""
}, {
"location": {
"latitude": 418811433,
"longitude": -741718005
},
"name": "213 Bush Road, Stone Ridge, NY 12484, USA"
}, {
"location": {
"latitude": 415034302,
"longitude": -743850945
},
"name": ""
}, {
"location": {
"latitude": 411349992,
"longitude": -743694161
},
"name": ""
}, {
"location": {
"latitude": 404839914,
"longitude": -744759616
},
"name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA"
}, {
"location": {
"latitude": 414638017,
"longitude": -745957854
},
"name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA"
}, {
"location": {
"latitude": 412127800,
"longitude": -740173578
},
"name": ""
}, {
"location": {
"latitude": 401263460,
"longitude": -747964303
},
"name": ""
}, {
"location": {
"latitude": 412843391,
"longitude": -749086026
},
"name": ""
}, {
"location": {
"latitude": 418512773,
"longitude": -743067823
},
"name": ""
}, {
"location": {
"latitude": 404318328,
"longitude": -740835638
},
"name": "42-102 Main Street, Belford, NJ 07718, USA"
}, {
"location": {
"latitude": 419020746,
"longitude": -741172328
},
"name": ""
}, {
"location": {
"latitude": 404080723,
"longitude": -746119569
},
"name": ""
}, {
"location": {
"latitude": 401012643,
"longitude": -744035134
},
"name": ""
}, {
"location": {
"latitude": 404306372,
"longitude": -741079661
},
"name": ""
}, {
"location": {
"latitude": 403966326,
"longitude": -748519297
},
"name": ""
}, {
"location": {
"latitude": 405002031,
"longitude": -748407866
},
"name": ""
}, {
"location": {
"latitude": 409532885,
"longitude": -742200683
},
"name": ""
}, {
"location": {
"latitude": 416851321,
"longitude": -742674555
},
"name": ""
}, {
"location": {
"latitude": 406411633,
"longitude": -741722051
},
"name": "3387 Richmond Terrace, Staten Island, NY 10303, USA"
}, {
"location": {
"latitude": 413069058,
"longitude": -744597778
},
"name": "261 Van Sickle Road, Goshen, NY 10924, USA"
}, {
"location": {
"latitude": 418465462,
"longitude": -746859398
},
"name": ""
}, {
"location": {
"latitude": 411733222,
"longitude": -744228360
},
"name": ""
}, {
"location": {
"latitude": 410248224,
"longitude": -747127767
},
"name": "3 Hasta Way, Newton, NJ 07860, USA"
}]

@ -0,0 +1,516 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: route_guide.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='route_guide.proto',
package='routeguide',
syntax='proto3',
serialized_pb=_b('\n\x11route_guide.proto\x12\nrouteguide\",\n\x05Point\x12\x10\n\x08latitude\x18\x01 \x01(\x05\x12\x11\n\tlongitude\x18\x02 \x01(\x05\"I\n\tRectangle\x12\x1d\n\x02lo\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x1d\n\x02hi\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"<\n\x07\x46\x65\x61ture\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x08location\x18\x02 \x01(\x0b\x32\x11.routeguide.Point\"A\n\tRouteNote\x12#\n\x08location\x18\x01 \x01(\x0b\x32\x11.routeguide.Point\x12\x0f\n\x07message\x18\x02 \x01(\t\"b\n\x0cRouteSummary\x12\x13\n\x0bpoint_count\x18\x01 \x01(\x05\x12\x15\n\rfeature_count\x18\x02 \x01(\x05\x12\x10\n\x08\x64istance\x18\x03 \x01(\x05\x12\x14\n\x0c\x65lapsed_time\x18\x04 \x01(\x05\x32\x85\x02\n\nRouteGuide\x12\x36\n\nGetFeature\x12\x11.routeguide.Point\x1a\x13.routeguide.Feature\"\x00\x12>\n\x0cListFeatures\x12\x15.routeguide.Rectangle\x1a\x13.routeguide.Feature\"\x00\x30\x01\x12>\n\x0bRecordRoute\x12\x11.routeguide.Point\x1a\x18.routeguide.RouteSummary\"\x00(\x01\x12?\n\tRouteChat\x12\x15.routeguide.RouteNote\x1a\x15.routeguide.RouteNote\"\x00(\x01\x30\x01\x42\x36\n\x1bio.grpc.examples.routeguideB\x0fRouteGuideProtoP\x01\xa2\x02\x03RTGb\x06proto3')
)
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
_POINT = _descriptor.Descriptor(
name='Point',
full_name='routeguide.Point',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='latitude', full_name='routeguide.Point.latitude', index=0,
number=1, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='longitude', full_name='routeguide.Point.longitude', index=1,
number=2, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=33,
serialized_end=77,
)
_RECTANGLE = _descriptor.Descriptor(
name='Rectangle',
full_name='routeguide.Rectangle',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='lo', full_name='routeguide.Rectangle.lo', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='hi', full_name='routeguide.Rectangle.hi', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=79,
serialized_end=152,
)
_FEATURE = _descriptor.Descriptor(
name='Feature',
full_name='routeguide.Feature',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='name', full_name='routeguide.Feature.name', index=0,
number=1, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='location', full_name='routeguide.Feature.location', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=154,
serialized_end=214,
)
_ROUTENOTE = _descriptor.Descriptor(
name='RouteNote',
full_name='routeguide.RouteNote',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='location', full_name='routeguide.RouteNote.location', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='message', full_name='routeguide.RouteNote.message', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=216,
serialized_end=281,
)
_ROUTESUMMARY = _descriptor.Descriptor(
name='RouteSummary',
full_name='routeguide.RouteSummary',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='point_count', full_name='routeguide.RouteSummary.point_count', index=0,
number=1, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='feature_count', full_name='routeguide.RouteSummary.feature_count', index=1,
number=2, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='distance', full_name='routeguide.RouteSummary.distance', index=2,
number=3, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
_descriptor.FieldDescriptor(
name='elapsed_time', full_name='routeguide.RouteSummary.elapsed_time', index=3,
number=4, type=5, cpp_type=1, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=283,
serialized_end=381,
)
_RECTANGLE.fields_by_name['lo'].message_type = _POINT
_RECTANGLE.fields_by_name['hi'].message_type = _POINT
_FEATURE.fields_by_name['location'].message_type = _POINT
_ROUTENOTE.fields_by_name['location'].message_type = _POINT
DESCRIPTOR.message_types_by_name['Point'] = _POINT
DESCRIPTOR.message_types_by_name['Rectangle'] = _RECTANGLE
DESCRIPTOR.message_types_by_name['Feature'] = _FEATURE
DESCRIPTOR.message_types_by_name['RouteNote'] = _ROUTENOTE
DESCRIPTOR.message_types_by_name['RouteSummary'] = _ROUTESUMMARY
Point = _reflection.GeneratedProtocolMessageType('Point', (_message.Message,), dict(
DESCRIPTOR = _POINT,
__module__ = 'route_guide_pb2'
# @@protoc_insertion_point(class_scope:routeguide.Point)
))
_sym_db.RegisterMessage(Point)
Rectangle = _reflection.GeneratedProtocolMessageType('Rectangle', (_message.Message,), dict(
DESCRIPTOR = _RECTANGLE,
__module__ = 'route_guide_pb2'
# @@protoc_insertion_point(class_scope:routeguide.Rectangle)
))
_sym_db.RegisterMessage(Rectangle)
Feature = _reflection.GeneratedProtocolMessageType('Feature', (_message.Message,), dict(
DESCRIPTOR = _FEATURE,
__module__ = 'route_guide_pb2'
# @@protoc_insertion_point(class_scope:routeguide.Feature)
))
_sym_db.RegisterMessage(Feature)
RouteNote = _reflection.GeneratedProtocolMessageType('RouteNote', (_message.Message,), dict(
DESCRIPTOR = _ROUTENOTE,
__module__ = 'route_guide_pb2'
# @@protoc_insertion_point(class_scope:routeguide.RouteNote)
))
_sym_db.RegisterMessage(RouteNote)
RouteSummary = _reflection.GeneratedProtocolMessageType('RouteSummary', (_message.Message,), dict(
DESCRIPTOR = _ROUTESUMMARY,
__module__ = 'route_guide_pb2'
# @@protoc_insertion_point(class_scope:routeguide.RouteSummary)
))
_sym_db.RegisterMessage(RouteSummary)
DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.routeguideB\017RouteGuideProtoP\001\242\002\003RTG'))
import grpc
from grpc.beta import implementations as beta_implementations
from grpc.beta import interfaces as beta_interfaces
from grpc.framework.common import cardinality
from grpc.framework.interfaces.face import utilities as face_utilities
class RouteGuideStub(object):
"""Interface exported by the server.
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.GetFeature = channel.unary_unary(
'/routeguide.RouteGuide/GetFeature',
request_serializer=Point.SerializeToString,
response_deserializer=Feature.FromString,
)
self.ListFeatures = channel.unary_stream(
'/routeguide.RouteGuide/ListFeatures',
request_serializer=Rectangle.SerializeToString,
response_deserializer=Feature.FromString,
)
self.RecordRoute = channel.stream_unary(
'/routeguide.RouteGuide/RecordRoute',
request_serializer=Point.SerializeToString,
response_deserializer=RouteSummary.FromString,
)
self.RouteChat = channel.stream_stream(
'/routeguide.RouteGuide/RouteChat',
request_serializer=RouteNote.SerializeToString,
response_deserializer=RouteNote.FromString,
)
class RouteGuideServicer(object):
"""Interface exported by the server.
"""
def GetFeature(self, request, context):
"""A simple RPC.
Obtains the feature at a given position.
A feature with an empty name is returned if there's no feature at the given
position.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def ListFeatures(self, request, context):
"""A server-to-client streaming RPC.
Obtains the Features available within the given Rectangle. Results are
streamed rather than returned at once (e.g. in a response message with a
repeated field), as the rectangle may cover a large area and contain a
huge number of features.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def RecordRoute(self, request_iterator, context):
"""A client-to-server streaming RPC.
Accepts a stream of Points on a route being traversed, returning a
RouteSummary when traversal is completed.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def RouteChat(self, request_iterator, context):
"""A Bidirectional streaming RPC.
Accepts a stream of RouteNotes sent while a route is being traversed,
while receiving other RouteNotes (e.g. from other users).
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_RouteGuideServicer_to_server(servicer, server):
rpc_method_handlers = {
'GetFeature': grpc.unary_unary_rpc_method_handler(
servicer.GetFeature,
request_deserializer=Point.FromString,
response_serializer=Feature.SerializeToString,
),
'ListFeatures': grpc.unary_stream_rpc_method_handler(
servicer.ListFeatures,
request_deserializer=Rectangle.FromString,
response_serializer=Feature.SerializeToString,
),
'RecordRoute': grpc.stream_unary_rpc_method_handler(
servicer.RecordRoute,
request_deserializer=Point.FromString,
response_serializer=RouteSummary.SerializeToString,
),
'RouteChat': grpc.stream_stream_rpc_method_handler(
servicer.RouteChat,
request_deserializer=RouteNote.FromString,
response_serializer=RouteNote.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'routeguide.RouteGuide', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
class BetaRouteGuideServicer(object):
"""Interface exported by the server.
"""
def GetFeature(self, request, context):
"""A simple RPC.
Obtains the feature at a given position.
A feature with an empty name is returned if there's no feature at the given
position.
"""
context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
def ListFeatures(self, request, context):
"""A server-to-client streaming RPC.
Obtains the Features available within the given Rectangle. Results are
streamed rather than returned at once (e.g. in a response message with a
repeated field), as the rectangle may cover a large area and contain a
huge number of features.
"""
context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
def RecordRoute(self, request_iterator, context):
"""A client-to-server streaming RPC.
Accepts a stream of Points on a route being traversed, returning a
RouteSummary when traversal is completed.
"""
context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
def RouteChat(self, request_iterator, context):
"""A Bidirectional streaming RPC.
Accepts a stream of RouteNotes sent while a route is being traversed,
while receiving other RouteNotes (e.g. from other users).
"""
context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
class BetaRouteGuideStub(object):
"""Interface exported by the server.
"""
def GetFeature(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
"""A simple RPC.
Obtains the feature at a given position.
A feature with an empty name is returned if there's no feature at the given
position.
"""
raise NotImplementedError()
GetFeature.future = None
def ListFeatures(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
"""A server-to-client streaming RPC.
Obtains the Features available within the given Rectangle. Results are
streamed rather than returned at once (e.g. in a response message with a
repeated field), as the rectangle may cover a large area and contain a
huge number of features.
"""
raise NotImplementedError()
def RecordRoute(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None):
"""A client-to-server streaming RPC.
Accepts a stream of Points on a route being traversed, returning a
RouteSummary when traversal is completed.
"""
raise NotImplementedError()
RecordRoute.future = None
def RouteChat(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None):
"""A Bidirectional streaming RPC.
Accepts a stream of RouteNotes sent while a route is being traversed,
while receiving other RouteNotes (e.g. from other users).
"""
raise NotImplementedError()
def beta_create_RouteGuide_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None):
request_deserializers = {
('routeguide.RouteGuide', 'GetFeature'): Point.FromString,
('routeguide.RouteGuide', 'ListFeatures'): Rectangle.FromString,
('routeguide.RouteGuide', 'RecordRoute'): Point.FromString,
('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString,
}
response_serializers = {
('routeguide.RouteGuide', 'GetFeature'): Feature.SerializeToString,
('routeguide.RouteGuide', 'ListFeatures'): Feature.SerializeToString,
('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.SerializeToString,
('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString,
}
method_implementations = {
('routeguide.RouteGuide', 'GetFeature'): face_utilities.unary_unary_inline(servicer.GetFeature),
('routeguide.RouteGuide', 'ListFeatures'): face_utilities.unary_stream_inline(servicer.ListFeatures),
('routeguide.RouteGuide', 'RecordRoute'): face_utilities.stream_unary_inline(servicer.RecordRoute),
('routeguide.RouteGuide', 'RouteChat'): face_utilities.stream_stream_inline(servicer.RouteChat),
}
server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout)
return beta_implementations.server(method_implementations, options=server_options)
def beta_create_RouteGuide_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None):
request_serializers = {
('routeguide.RouteGuide', 'GetFeature'): Point.SerializeToString,
('routeguide.RouteGuide', 'ListFeatures'): Rectangle.SerializeToString,
('routeguide.RouteGuide', 'RecordRoute'): Point.SerializeToString,
('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString,
}
response_deserializers = {
('routeguide.RouteGuide', 'GetFeature'): Feature.FromString,
('routeguide.RouteGuide', 'ListFeatures'): Feature.FromString,
('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.FromString,
('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString,
}
cardinalities = {
'GetFeature': cardinality.Cardinality.UNARY_UNARY,
'ListFeatures': cardinality.Cardinality.UNARY_STREAM,
'RecordRoute': cardinality.Cardinality.STREAM_UNARY,
'RouteChat': cardinality.Cardinality.STREAM_STREAM,
}
stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, request_serializers=request_serializers, response_deserializers=response_deserializers, thread_pool=pool, thread_pool_size=pool_size)
return beta_implementations.dynamic_stub(channel, 'routeguide.RouteGuide', cardinalities, options=stub_options)
# @@protoc_insertion_point(module_scope)

@ -27,25 +27,27 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Enables scheduling execution at a later time."""
"""Common resources used in the gRPC route guide example."""
import time
import json
from grpc.framework.foundation import _timer_future
import route_guide_pb2
def later(delay, computation):
"""Schedules later execution of a callable.
Args:
delay: Any numeric value. Represents the minimum length of time in seconds
to allow to pass before beginning the computation. No guarantees are made
about the maximum length of time that will pass.
computation: A callable that accepts no arguments.
def read_route_guide_database():
"""Reads the route guide database.
Returns:
A Future representing the scheduled computation.
The full contents of the route guide database as a sequence of
route_guide_pb2.Features.
"""
timer_future = _timer_future.TimerFuture(time.time() + delay, computation)
timer_future.start()
return timer_future
feature_list = []
with open("route_guide_db.json") as route_guide_db_file:
for item in json.load(route_guide_db_file):
feature = route_guide_pb2.Feature(
name=item["name"],
location=route_guide_pb2.Point(
latitude=item["location"]["latitude"],
longitude=item["location"]["longitude"]))
feature_list.append(feature)
return feature_list

@ -1,4 +1,4 @@
# Copyright 2015, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -27,18 +27,25 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Utilities provided as part of the links interface."""
"""Generates protocol messages and gRPC stubs."""
from grpc.framework.interfaces.links import links
from grpc.tools import protoc
class _NullLink(links.Link):
"""A do-nothing links.Link."""
def accept_ticket(self, ticket):
pass
def join_link(self, link):
pass
NULL_LINK = _NullLink()
protoc.main(
(
'',
'-I../../protos',
'--python_out=.',
'--grpc_python_out=.',
'../../protos/helloworld.proto',
)
)
protoc.main(
(
'',
'-I../../protos',
'--python_out=.',
'--grpc_python_out=.',
'../../protos/route_guide.proto',
)
)

@ -34,13 +34,11 @@ from __future__ import print_function
import random
import time
from grpc.beta import implementations
import grpc
import route_guide_pb2
import route_guide_resources
_TIMEOUT_SECONDS = 30
def make_route_note(message, latitude, longitude):
return route_guide_pb2.RouteNote(
@ -49,7 +47,7 @@ def make_route_note(message, latitude, longitude):
def guide_get_one_feature(stub, point):
feature = stub.GetFeature(point, _TIMEOUT_SECONDS)
feature = stub.GetFeature(point)
if not feature.location:
print("Server returned incomplete feature")
return
@ -66,14 +64,12 @@ def guide_get_feature(stub):
def guide_list_features(stub):
rect = route_guide_pb2.Rectangle(
lo=route_guide_pb2.Point(
latitude=400000000, longitude = -750000000),
hi=route_guide_pb2.Point(
latitude = 420000000, longitude = -730000000))
rectangle = route_guide_pb2.Rectangle(
lo=route_guide_pb2.Point(latitude=400000000, longitude=-750000000),
hi=route_guide_pb2.Point(latitude=420000000, longitude=-730000000))
print("Looking for features between 40, -75 and 42, -73")
features = stub.ListFeatures(rect, _TIMEOUT_SECONDS)
features = stub.ListFeatures(rectangle)
for feature in features:
print("Feature called %s at %s" % (feature.name, feature.location))
@ -90,8 +86,8 @@ def generate_route(feature_list):
def guide_record_route(stub):
feature_list = route_guide_resources.read_route_guide_database()
route_iter = generate_route(feature_list)
route_summary = stub.RecordRoute(route_iter, _TIMEOUT_SECONDS)
route_iterator = generate_route(feature_list)
route_summary = stub.RecordRoute(route_iterator)
print("Finished trip with %s points " % route_summary.point_count)
print("Passed %s features " % route_summary.feature_count)
print("Travelled %s meters " % route_summary.distance)
@ -113,14 +109,14 @@ def generate_messages():
def guide_route_chat(stub):
responses = stub.RouteChat(generate_messages(), _TIMEOUT_SECONDS)
responses = stub.RouteChat(generate_messages())
for response in responses:
print("Received message %s at %s" % (response.message, response.location))
def run():
channel = implementations.insecure_channel('localhost', 50051)
stub = route_guide_pb2.beta_create_RouteGuide_stub(channel)
channel = grpc.insecure_channel('localhost:50051')
stub = route_guide_pb2.RouteGuideStub(channel)
print("-------------- GetFeature --------------")
guide_get_feature(stub)
print("-------------- ListFeatures --------------")

@ -277,13 +277,122 @@ _sym_db.RegisterMessage(RouteSummary)
DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\033io.grpc.examples.routeguideB\017RouteGuideProtoP\001\242\002\003RTG'))
import abc
import six
import grpc
from grpc.beta import implementations as beta_implementations
from grpc.beta import interfaces as beta_interfaces
from grpc.framework.common import cardinality
from grpc.framework.interfaces.face import utilities as face_utilities
class RouteGuideStub(object):
"""Interface exported by the server.
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.GetFeature = channel.unary_unary(
'/routeguide.RouteGuide/GetFeature',
request_serializer=Point.SerializeToString,
response_deserializer=Feature.FromString,
)
self.ListFeatures = channel.unary_stream(
'/routeguide.RouteGuide/ListFeatures',
request_serializer=Rectangle.SerializeToString,
response_deserializer=Feature.FromString,
)
self.RecordRoute = channel.stream_unary(
'/routeguide.RouteGuide/RecordRoute',
request_serializer=Point.SerializeToString,
response_deserializer=RouteSummary.FromString,
)
self.RouteChat = channel.stream_stream(
'/routeguide.RouteGuide/RouteChat',
request_serializer=RouteNote.SerializeToString,
response_deserializer=RouteNote.FromString,
)
class RouteGuideServicer(object):
"""Interface exported by the server.
"""
def GetFeature(self, request, context):
"""A simple RPC.
Obtains the feature at a given position.
A feature with an empty name is returned if there's no feature at the given
position.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def ListFeatures(self, request, context):
"""A server-to-client streaming RPC.
Obtains the Features available within the given Rectangle. Results are
streamed rather than returned at once (e.g. in a response message with a
repeated field), as the rectangle may cover a large area and contain a
huge number of features.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def RecordRoute(self, request_iterator, context):
"""A client-to-server streaming RPC.
Accepts a stream of Points on a route being traversed, returning a
RouteSummary when traversal is completed.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def RouteChat(self, request_iterator, context):
"""A Bidirectional streaming RPC.
Accepts a stream of RouteNotes sent while a route is being traversed,
while receiving other RouteNotes (e.g. from other users).
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_RouteGuideServicer_to_server(servicer, server):
rpc_method_handlers = {
'GetFeature': grpc.unary_unary_rpc_method_handler(
servicer.GetFeature,
request_deserializer=Point.FromString,
response_serializer=Feature.SerializeToString,
),
'ListFeatures': grpc.unary_stream_rpc_method_handler(
servicer.ListFeatures,
request_deserializer=Rectangle.FromString,
response_serializer=Feature.SerializeToString,
),
'RecordRoute': grpc.stream_unary_rpc_method_handler(
servicer.RecordRoute,
request_deserializer=Point.FromString,
response_serializer=RouteSummary.SerializeToString,
),
'RouteChat': grpc.stream_stream_rpc_method_handler(
servicer.RouteChat,
request_deserializer=RouteNote.FromString,
response_serializer=RouteNote.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'routeguide.RouteGuide', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
class BetaRouteGuideServicer(object):
"""Interface exported by the server.
"""
@ -320,10 +429,11 @@ class BetaRouteGuideServicer(object):
"""
context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
class BetaRouteGuideStub(object):
"""Interface exported by the server.
"""
def GetFeature(self, request, timeout):
def GetFeature(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
"""A simple RPC.
Obtains the feature at a given position.
@ -333,7 +443,7 @@ class BetaRouteGuideStub(object):
"""
raise NotImplementedError()
GetFeature.future = None
def ListFeatures(self, request, timeout):
def ListFeatures(self, request, timeout, metadata=None, with_call=False, protocol_options=None):
"""A server-to-client streaming RPC.
Obtains the Features available within the given Rectangle. Results are
@ -342,7 +452,7 @@ class BetaRouteGuideStub(object):
huge number of features.
"""
raise NotImplementedError()
def RecordRoute(self, request_iterator, timeout):
def RecordRoute(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None):
"""A client-to-server streaming RPC.
Accepts a stream of Points on a route being traversed, returning a
@ -350,7 +460,7 @@ class BetaRouteGuideStub(object):
"""
raise NotImplementedError()
RecordRoute.future = None
def RouteChat(self, request_iterator, timeout):
def RouteChat(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None):
"""A Bidirectional streaming RPC.
Accepts a stream of RouteNotes sent while a route is being traversed,
@ -358,26 +468,19 @@ class BetaRouteGuideStub(object):
"""
raise NotImplementedError()
def beta_create_RouteGuide_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None):
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
request_deserializers = {
('routeguide.RouteGuide', 'GetFeature'): route_guide_pb2.Point.FromString,
('routeguide.RouteGuide', 'ListFeatures'): route_guide_pb2.Rectangle.FromString,
('routeguide.RouteGuide', 'RecordRoute'): route_guide_pb2.Point.FromString,
('routeguide.RouteGuide', 'RouteChat'): route_guide_pb2.RouteNote.FromString,
('routeguide.RouteGuide', 'GetFeature'): Point.FromString,
('routeguide.RouteGuide', 'ListFeatures'): Rectangle.FromString,
('routeguide.RouteGuide', 'RecordRoute'): Point.FromString,
('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString,
}
response_serializers = {
('routeguide.RouteGuide', 'GetFeature'): route_guide_pb2.Feature.SerializeToString,
('routeguide.RouteGuide', 'ListFeatures'): route_guide_pb2.Feature.SerializeToString,
('routeguide.RouteGuide', 'RecordRoute'): route_guide_pb2.RouteSummary.SerializeToString,
('routeguide.RouteGuide', 'RouteChat'): route_guide_pb2.RouteNote.SerializeToString,
('routeguide.RouteGuide', 'GetFeature'): Feature.SerializeToString,
('routeguide.RouteGuide', 'ListFeatures'): Feature.SerializeToString,
('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.SerializeToString,
('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString,
}
method_implementations = {
('routeguide.RouteGuide', 'GetFeature'): face_utilities.unary_unary_inline(servicer.GetFeature),
@ -388,26 +491,19 @@ def beta_create_RouteGuide_server(servicer, pool=None, pool_size=None, default_t
server_options = beta_implementations.server_options(request_deserializers=request_deserializers, response_serializers=response_serializers, thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout)
return beta_implementations.server(method_implementations, options=server_options)
def beta_create_RouteGuide_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None):
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
import route_guide_pb2
request_serializers = {
('routeguide.RouteGuide', 'GetFeature'): route_guide_pb2.Point.SerializeToString,
('routeguide.RouteGuide', 'ListFeatures'): route_guide_pb2.Rectangle.SerializeToString,
('routeguide.RouteGuide', 'RecordRoute'): route_guide_pb2.Point.SerializeToString,
('routeguide.RouteGuide', 'RouteChat'): route_guide_pb2.RouteNote.SerializeToString,
('routeguide.RouteGuide', 'GetFeature'): Point.SerializeToString,
('routeguide.RouteGuide', 'ListFeatures'): Rectangle.SerializeToString,
('routeguide.RouteGuide', 'RecordRoute'): Point.SerializeToString,
('routeguide.RouteGuide', 'RouteChat'): RouteNote.SerializeToString,
}
response_deserializers = {
('routeguide.RouteGuide', 'GetFeature'): route_guide_pb2.Feature.FromString,
('routeguide.RouteGuide', 'ListFeatures'): route_guide_pb2.Feature.FromString,
('routeguide.RouteGuide', 'RecordRoute'): route_guide_pb2.RouteSummary.FromString,
('routeguide.RouteGuide', 'RouteChat'): route_guide_pb2.RouteNote.FromString,
('routeguide.RouteGuide', 'GetFeature'): Feature.FromString,
('routeguide.RouteGuide', 'ListFeatures'): Feature.FromString,
('routeguide.RouteGuide', 'RecordRoute'): RouteSummary.FromString,
('routeguide.RouteGuide', 'RouteChat'): RouteNote.FromString,
}
cardinalities = {
'GetFeature': cardinality.Cardinality.UNARY_UNARY,

@ -29,9 +29,12 @@
"""The Python implementation of the gRPC route guide server."""
from concurrent import futures
import time
import math
import grpc
import route_guide_pb2
import route_guide_resources
@ -121,7 +124,9 @@ class RouteGuideServicer(route_guide_pb2.BetaRouteGuideServicer):
def serve():
server = route_guide_pb2.beta_create_RouteGuide_server(RouteGuideServicer())
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
route_guide_pb2.add_RouteGuideServicer_to_server(
RouteGuideServicer(), server)
server.add_insecure_port('[::]:50051')
server.start()
try:

@ -27,4 +27,16 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Runs protoc with the gRPC plugin to generate messages and gRPC stubs."""
from grpc.tools import protoc
protoc.main(
(
'',
'-I../../protos',
'--python_out=.',
'--grpc_python_out=.',
'../../protos/route_guide.proto',
)
)

@ -1,32 +0,0 @@
#!/bin/bash
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Runs the protoc with gRPC plugin to generate protocol messages and gRPC stubs.
python -m grpc.tools.protoc -I../../protos --python_out=. --grpc_python_out=. ../../protos/route_guide.proto

@ -35,7 +35,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-Core'
version = '0.14.0'
version = '1.0.0-pre1'
s.version = version
s.summary = 'Core cross-platform gRPC library, written in C'
s.homepage = 'http://www.grpc.io'
@ -44,7 +44,7 @@ Pod::Spec.new do |s|
s.source = {
:git => 'https://github.com/grpc/grpc.git',
:tag => "release-#{version.gsub(/\./, '_')}-objectivec-#{version}",
:tag => "objective-c-v#{version}",
# TODO(jcanizales): Depend explicitly on the nanopb pod, and disable submodules.
:submodules => true,
}
@ -101,6 +101,8 @@ Pod::Spec.new do |s|
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
}
s.default_subspecs = 'Interface', 'Implementation'
# Like many other C libraries, gRPC-Core has its public headers under `include/<libname>/` and its
# sources and private headers in other directories outside `include/`. Cocoapods' linter doesn't
# allow any header to be listed outside the `header_mappings_dir` (even though doing so works in
@ -191,7 +193,7 @@ Pod::Spec.new do |s|
ss.header_mappings_dir = '.'
ss.libraries = 'z'
ss.dependency "#{s.name}/Interface", version
ss.dependency 'BoringSSL', '~> 4.0'
ss.dependency 'BoringSSL', '~> 5.0'
# To save you from scrolling, this is the last part of the podspec.
ss.source_files = 'src/core/lib/profiling/timers.h',
@ -256,6 +258,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/compress_filter.h',
'src/core/lib/channel/connected_channel.h',
'src/core/lib/channel/context.h',
'src/core/lib/channel/handshaker.h',
'src/core/lib/channel/http_client_filter.h',
'src/core/lib/channel/http_server_filter.h',
'src/core/lib/compression/algorithm_metadata.h',
@ -411,6 +414,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/channel_stack_builder.c',
'src/core/lib/channel/compress_filter.c',
'src/core/lib/channel/connected_channel.c',
'src/core/lib/channel/handshaker.c',
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/compression/compression.c',
@ -609,6 +613,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/compress_filter.h',
'src/core/lib/channel/connected_channel.h',
'src/core/lib/channel/context.h',
'src/core/lib/channel/handshaker.h',
'src/core/lib/channel/http_client_filter.h',
'src/core/lib/channel/http_server_filter.h',
'src/core/lib/compression/algorithm_metadata.h',
@ -759,4 +764,26 @@ Pod::Spec.new do |s|
'src/core/ext/census/mlog.h',
'src/core/ext/census/rpc_metric_id.h'
end
s.subspec 'Cronet-Interface' do |ss|
ss.header_mappings_dir = 'include/grpc'
ss.source_files = 'include/grpc/grpc_cronet.h'
end
s.subspec 'Cronet-Tests' do |ss|
ss.header_mappings_dir = '.'
ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c',
'src/core/ext/transport/cronet/transport/cronet_transport.c',
'test/core/end2end/cq_verifier.{c,h}',
'test/core/end2end/end2end_tests.{c,h}',
'test/core/end2end/tests/*.{c,h}',
'test/core/end2end/data/*.{c,h}',
'test/core/util/test_config.{c,h}',
'test/core/util/port.h',
'test/core/util/port_posix.c',
'test/core/util/port_server_client.{c,h}'
ss.dependency 'CronetFramework'
end
end

@ -36,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-ProtoRPC'
version = '0.14.0'
version = '1.0.0-pre1'
s.version = version
s.summary = 'RPC library for Protocol Buffers, based on gRPC'
s.homepage = 'http://www.grpc.io'
@ -45,7 +45,7 @@ Pod::Spec.new do |s|
s.source = {
:git => 'https://github.com/grpc/grpc.git',
:tag => "release-#{version.gsub(/\./, '_')}-objectivec-#{version}",
:tag => "objective-c-v#{version}",
}
s.ios.deployment_target = '7.1'

@ -36,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC-RxLibrary'
version = '0.14.0'
version = '1.0.0-pre1'
s.version = version
s.summary = 'Reactive Extensions library for iOS/OSX.'
s.homepage = 'http://www.grpc.io'
@ -45,7 +45,7 @@ Pod::Spec.new do |s|
s.source = {
:git => 'https://github.com/grpc/grpc.git',
:tag => "release-#{version.gsub(/\./, '_')}-objectivec-#{version}",
:tag => "objective-c-v#{version}",
}
s.ios.deployment_target = '7.1'

@ -36,7 +36,7 @@
Pod::Spec.new do |s|
s.name = 'gRPC'
version = '0.14.0'
version = '1.0.0-pre1'
s.version = version
s.summary = 'gRPC client library for iOS/OSX'
s.homepage = 'http://www.grpc.io'
@ -45,7 +45,7 @@ Pod::Spec.new do |s|
s.source = {
:git => 'https://github.com/grpc/grpc.git',
:tag => "release-#{version.gsub(/\./, '_')}-objectivec-#{version}",
:tag => "objective-c-v#{version}",
}
s.ios.deployment_target = '7.1'

@ -148,6 +148,7 @@ EXPORTS
gpr_slice_ref
gpr_slice_unref
gpr_slice_new
gpr_slice_new_with_user_data
gpr_slice_new_with_len
gpr_slice_malloc
gpr_slice_from_copied_string

@ -177,6 +177,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/compress_filter.h )
s.files += %w( src/core/lib/channel/connected_channel.h )
s.files += %w( src/core/lib/channel/context.h )
s.files += %w( src/core/lib/channel/handshaker.h )
s.files += %w( src/core/lib/channel/http_client_filter.h )
s.files += %w( src/core/lib/channel/http_server_filter.h )
s.files += %w( src/core/lib/compression/algorithm_metadata.h )
@ -332,6 +333,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/channel_stack_builder.c )
s.files += %w( src/core/lib/channel/compress_filter.c )
s.files += %w( src/core/lib/channel/connected_channel.c )
s.files += %w( src/core/lib/channel/handshaker.c )
s.files += %w( src/core/lib/channel/http_client_filter.c )
s.files += %w( src/core/lib/channel/http_server_filter.c )
s.files += %w( src/core/lib/compression/compression.c )

@ -330,6 +330,9 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncReaderInterface<W, R> {
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
meta_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
@ -345,6 +348,9 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncReaderInterface<W, R> {
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
finish_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
@ -363,6 +369,9 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncReaderInterface<W, R> {
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
finish_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
@ -400,6 +409,9 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncWriterInterface<W> {
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
meta_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
@ -409,6 +421,9 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncWriterInterface<W> {
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
write_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
@ -421,6 +436,9 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncWriterInterface<W> {
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
finish_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
@ -459,6 +477,9 @@ class ServerAsyncReaderWriter GRPC_FINAL
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
meta_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
@ -474,6 +495,9 @@ class ServerAsyncReaderWriter GRPC_FINAL
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
write_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
@ -486,6 +510,9 @@ class ServerAsyncReaderWriter GRPC_FINAL
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
finish_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);

@ -65,7 +65,7 @@ class ClientAsyncResponseReader GRPC_FINAL
const W& request)
: context_(context),
call_(channel->CreateCall(method, context, cq)),
collection_(new CallOpSetCollection) {
collection_(std::make_shared<CallOpSetCollection>()) {
collection_->init_buf_.SetCollection(collection_);
collection_->init_buf_.SendInitialMetadata(
context->send_initial_metadata_, context->initial_metadata_flags());
@ -126,6 +126,9 @@ class ServerAsyncResponseWriter GRPC_FINAL
meta_buf_.set_output_tag(tag);
meta_buf_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
meta_buf_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_buf_);
}
@ -135,6 +138,9 @@ class ServerAsyncResponseWriter GRPC_FINAL
if (!ctx_->sent_initial_metadata_) {
finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
finish_buf_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
@ -153,6 +159,9 @@ class ServerAsyncResponseWriter GRPC_FINAL
if (!ctx_->sent_initial_metadata_) {
finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
finish_buf_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status);

@ -180,17 +180,23 @@ class CallNoOp {
class CallOpSendInitialMetadata {
public:
CallOpSendInitialMetadata() : send_(false) {}
CallOpSendInitialMetadata() : send_(false) {
maybe_compression_level_.is_set = false;
}
void SendInitialMetadata(
const std::multimap<grpc::string, grpc::string>& metadata,
uint32_t flags) {
maybe_compression_level_.is_set = false;
send_ = true;
flags_ = flags;
initial_metadata_count_ = metadata.size();
initial_metadata_ = FillMetadataArray(metadata);
// TODO(dgq): expose compression level in API so it can be properly set.
maybe_compression_level_.is_set = false;
}
void set_compression_level(grpc_compression_level level) {
maybe_compression_level_.is_set = true;
maybe_compression_level_.level = level;
}
protected:

@ -41,7 +41,7 @@
///
/// Context settings are only relevant to the call they are invoked with, that
/// is to say, they aren't sticky. Some of these settings, such as the
/// compression options, can be made persistant at channel construction time
/// compression options, can be made persistent at channel construction time
/// (see \a grpc::CreateCustomChannel).
///
/// \warning ClientContext instances should \em not be reused across rpcs.

@ -40,16 +40,21 @@
#endif
#ifndef GRPC_CUSTOM_MESSAGE
#ifdef GRPC_USE_PROTO_LITE
#include <google/protobuf/message_lite.h>
#define GRPC_CUSTOM_MESSAGE ::google::protobuf::MessageLite
#else
#include <google/protobuf/message.h>
#define GRPC_CUSTOM_MESSAGE ::google::protobuf::Message
#endif
#endif
#ifndef GRPC_CUSTOM_DESCRIPTOR
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#define GRPC_CUSTOM_DESCRIPTOR ::google::protobuf::Descriptor
#define GRPC_CUSTOM_DESCRIPTORPOOL ::google::protobuf::DescriptorPool
#define GPRC_CUSTOM_FIELDDESCRIPTOR ::google::protobuf::FieldDescriptor
#define GRPC_CUSTOM_FIELDDESCRIPTOR ::google::protobuf::FieldDescriptor
#define GRPC_CUSTOM_FILEDESCRIPTOR ::google::protobuf::FileDescriptor
#define GRPC_CUSTOM_FILEDESCRIPTORPROTO ::google::protobuf::FileDescriptorProto
#define GRPC_CUSTOM_METHODDESCRIPTOR ::google::protobuf::MethodDescriptor
@ -57,6 +62,13 @@
#define GRPC_CUSTOM_SOURCELOCATION ::google::protobuf::SourceLocation
#endif
#ifndef GRPC_CUSTOM_DESCRIPTORDATABASE
#include <google/protobuf/descriptor_database.h>
#define GRPC_CUSTOM_DESCRIPTORDATABASE ::google::protobuf::DescriptorDatabase
#define GRPC_CUSTOM_SIMPLEDESCRIPTORDATABASE \
::google::protobuf::SimpleDescriptorDatabase
#endif
#ifndef GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
@ -75,11 +87,13 @@ typedef GRPC_CUSTOM_PROTOBUF_INT64 int64;
typedef GRPC_CUSTOM_DESCRIPTOR Descriptor;
typedef GRPC_CUSTOM_DESCRIPTORPOOL DescriptorPool;
typedef GPRC_CUSTOM_FIELDDESCRIPTOR FieldDescriptor;
typedef GRPC_CUSTOM_DESCRIPTORDATABASE DescriptorDatabase;
typedef GRPC_CUSTOM_FIELDDESCRIPTOR FieldDescriptor;
typedef GRPC_CUSTOM_FILEDESCRIPTOR FileDescriptor;
typedef GRPC_CUSTOM_FILEDESCRIPTORPROTO FileDescriptorProto;
typedef GRPC_CUSTOM_METHODDESCRIPTOR MethodDescriptor;
typedef GRPC_CUSTOM_SERVICEDESCRIPTOR ServiceDescriptor;
typedef GRPC_CUSTOM_SIMPLEDESCRIPTORDATABASE SimpleDescriptorDatabase;
typedef GRPC_CUSTOM_SOURCELOCATION SourceLocation;
namespace io {

@ -1,486 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPCXX_IMPL_CODEGEN_IMPL_ASYNC_STREAM_H
#define GRPCXX_IMPL_CODEGEN_IMPL_ASYNC_STREAM_H
#include <grpc++/impl/codegen/call.h>
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/server_context.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h>
namespace grpc {
class CompletionQueue;
/// Common interface for all client side asynchronous streaming.
class ClientAsyncStreamingInterface {
public:
virtual ~ClientAsyncStreamingInterface() {}
/// Request notification of the reading of the initial metadata. Completion
/// will be notified by \a tag on the associated completion queue.
///
/// \param[in] tag Tag identifying this request.
virtual void ReadInitialMetadata(void* tag) = 0;
/// Request notification completion.
///
/// \param[out] status To be updated with the operation status.
/// \param[in] tag Tag identifying this request.
virtual void Finish(Status* status, void* tag) = 0;
};
/// An interface that yields a sequence of messages of type \a R.
template <class R>
class AsyncReaderInterface {
public:
virtual ~AsyncReaderInterface() {}
/// Read a message of type \a R into \a msg. Completion will be notified by \a
/// tag on the associated completion queue.
///
/// \param[out] msg Where to eventually store the read message.
/// \param[in] tag The tag identifying the operation.
virtual void Read(R* msg, void* tag) = 0;
};
/// An interface that can be fed a sequence of messages of type \a W.
template <class W>
class AsyncWriterInterface {
public:
virtual ~AsyncWriterInterface() {}
/// Request the writing of \a msg with identifying tag \a tag.
///
/// Only one write may be outstanding at any given time. This means that
/// after calling Write, one must wait to receive \a tag from the completion
/// queue BEFORE calling Write again.
///
/// \param[in] msg The message to be written.
/// \param[in] tag The tag identifying the operation.
virtual void Write(const W& msg, void* tag) = 0;
};
template <class R>
class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface,
public AsyncReaderInterface<R> {};
template <class R>
class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> {
public:
/// Create a stream and write the first request out.
template <class W>
ClientAsyncReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const W& request, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
init_ops_.ClientSendClose();
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_);
}
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Finish(Status* status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
}
finish_ops_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_ops_);
}
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
};
/// Common interface for client side asynchronous writing.
template <class W>
class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
/// Signal the client is done with the writes.
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0;
};
template <class W>
class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> {
public:
template <class R>
ClientAsyncWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
R* response, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
finish_ops_.RecvMessage(response);
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void WritesDone(void* tag) GRPC_OVERRIDE {
writes_done_ops_.set_output_tag(tag);
writes_done_ops_.ClientSendClose();
call_.PerformOps(&writes_done_ops_);
}
void Finish(Status* status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
}
finish_ops_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_ops_);
}
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata> init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpSendMessage> write_ops_;
CallOpSet<CallOpClientSendClose> writes_done_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
CallOpClientRecvStatus>
finish_ops_;
};
/// Client-side interface for asynchronous bi-directional streaming.
template <class W, class R>
class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
/// Signal the client is done with the writes.
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0;
};
template <class W, class R>
class ClientAsyncReaderWriter GRPC_FINAL
: public ClientAsyncReaderWriterInterface<W, R> {
public:
ClientAsyncReaderWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_);
}
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void WritesDone(void* tag) GRPC_OVERRIDE {
writes_done_ops_.set_output_tag(tag);
writes_done_ops_.ClientSendClose();
call_.PerformOps(&writes_done_ops_);
}
void Finish(Status* status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
}
finish_ops_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_ops_);
}
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata> init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendMessage> write_ops_;
CallOpSet<CallOpClientSendClose> writes_done_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
};
template <class W, class R>
class ServerAsyncReaderInterface : public ServerAsyncStreamingInterface,
public AsyncReaderInterface<R> {
public:
virtual void Finish(const W& msg, const Status& status, void* tag) = 0;
virtual void FinishWithError(const Status& status, void* tag) = 0;
};
template <class W, class R>
class ServerAsyncReader GRPC_FINAL : public ServerAsyncReaderInterface<W, R> {
public:
explicit ServerAsyncReader(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Finish(const W& msg, const Status& status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
if (status.ok()) {
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_,
finish_ops_.SendMessage(msg));
} else {
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
}
call_.PerformOps(&finish_ops_);
}
void FinishWithError(const Status& status, void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!status.ok());
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
private:
void BindCall(Call* call) GRPC_OVERRIDE { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus>
finish_ops_;
};
template <class W>
class ServerAsyncWriterInterface : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
virtual void Finish(const Status& status, void* tag) = 0;
};
template <class W>
class ServerAsyncWriter GRPC_FINAL : public ServerAsyncWriterInterface<W> {
public:
explicit ServerAsyncWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void Finish(const Status& status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
private:
void BindCall(Call* call) GRPC_OVERRIDE { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
};
/// Server-side interface for asynchronous bi-directional streaming.
template <class W, class R>
class ServerAsyncReaderWriterInterface : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
virtual void Finish(const Status& status, void* tag) = 0;
};
template <class W, class R>
class ServerAsyncReaderWriter GRPC_FINAL
: public ServerAsyncReaderWriterInterface<W, R> {
public:
explicit ServerAsyncReaderWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void Finish(const Status& status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
private:
friend class ::grpc::Server;
void BindCall(Call* call) GRPC_OVERRIDE { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
};
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_IMPL_ASYNC_STREAM_H

@ -65,6 +65,9 @@ class RpcMethodHandler : public MethodHandler {
ops;
ops.SendInitialMetadata(param.server_context->initial_metadata_,
param.server_context->initial_metadata_flags());
if (param.server_context->compression_level_set()) {
ops.set_compression_level(param.server_context->compression_level());
}
if (status.ok()) {
status = ops.SendMessage(rsp);
}
@ -104,6 +107,9 @@ class ClientStreamingHandler : public MethodHandler {
ops;
ops.SendInitialMetadata(param.server_context->initial_metadata_,
param.server_context->initial_metadata_flags());
if (param.server_context->compression_level_set()) {
ops.set_compression_level(param.server_context->compression_level());
}
if (status.ok()) {
status = ops.SendMessage(rsp);
}
@ -144,6 +150,9 @@ class ServerStreamingHandler : public MethodHandler {
if (!param.server_context->sent_initial_metadata_) {
ops.SendInitialMetadata(param.server_context->initial_metadata_,
param.server_context->initial_metadata_flags());
if (param.server_context->compression_level_set()) {
ops.set_compression_level(param.server_context->compression_level());
}
}
ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
param.call->PerformOps(&ops);
@ -177,6 +186,9 @@ class BidiStreamingHandler : public MethodHandler {
if (!param.server_context->sent_initial_metadata_) {
ops.SendInitialMetadata(param.server_context->initial_metadata_,
param.server_context->initial_metadata_flags());
if (param.server_context->compression_level_set()) {
ops.set_compression_level(param.server_context->compression_level());
}
}
ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
param.call->PerformOps(&ops);
@ -199,6 +211,9 @@ class UnknownMethodHandler : public MethodHandler {
if (!context->sent_initial_metadata_) {
ops->SendInitialMetadata(context->initial_metadata_,
context->initial_metadata_flags());
if (context->compression_level_set()) {
ops->set_compression_level(context->compression_level());
}
context->sent_initial_metadata_ = true;
}
ops->ServerSendStatus(context->trailing_metadata_, status);

@ -130,7 +130,13 @@ class ServerContext {
grpc_compression_level compression_level() const {
return compression_level_;
}
void set_compression_level(grpc_compression_level level);
void set_compression_level(grpc_compression_level level) {
compression_level_set_ = true;
compression_level_ = level;
}
bool compression_level_set() const { return compression_level_set_; }
grpc_compression_algorithm compression_algorithm() const {
return compression_algorithm_;
@ -217,6 +223,7 @@ class ServerContext {
std::multimap<grpc::string, grpc::string> initial_metadata_;
std::multimap<grpc::string, grpc::string> trailing_metadata_;
bool compression_level_set_;
grpc_compression_level compression_level_;
grpc_compression_algorithm compression_algorithm_;
};

@ -347,6 +347,9 @@ class ServerReader GRPC_FINAL : public ReaderInterface<R> {
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
ops.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
call_->PerformOps(&ops);
call_->cq()->Pluck(&ops);
@ -375,6 +378,9 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> {
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
ops.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
call_->PerformOps(&ops);
call_->cq()->Pluck(&ops);
@ -389,6 +395,9 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> {
if (!ctx_->sent_initial_metadata_) {
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
ops.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
call_->PerformOps(&ops);
@ -413,6 +422,9 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>,
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
ops.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
call_->PerformOps(&ops);
call_->cq()->Pluck(&ops);
@ -434,6 +446,9 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>,
if (!ctx_->sent_initial_metadata_) {
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
ops.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
call_->PerformOps(&ops);

@ -179,10 +179,13 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
grpc::mutex mu_;
bool started_;
bool shutdown_;
bool shutdown_notified_;
// The number of threads which are running callbacks.
int num_running_cb_;
grpc::condition_variable callback_cv_;
grpc::condition_variable shutdown_cv_;
std::shared_ptr<GlobalCallbacks> global_callbacks_;
std::list<SyncRequest>* sync_methods_;

@ -77,6 +77,9 @@ class Slice GRPC_FINAL {
/// Raw pointer to the end (one byte \em past the last element) of the slice.
const uint8_t* end() const { return GPR_SLICE_END_PTR(slice_); }
/// Raw C slice. Caller needs to call gpr_slice_unref when done.
gpr_slice c_slice() const { return gpr_slice_ref(slice_); }
private:
friend class ByteBuffer;

@ -46,12 +46,27 @@ extern "C" {
#define GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY \
"grpc-internal-encoding-request"
/** To be used in channel arguments */
/** To be used in channel arguments.
*
* \addtogroup grpc_arg_keys
* \{ */
/** Default compression algorithm for the channel.
* Its value is an int from the \a grpc_compression_algorithm enum. */
#define GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM \
"grpc.default_compression_algorithm"
/** Default compression level for the channel.
* Its value is an int from the \a grpc_compression_level enum. */
#define GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL "grpc.default_compression_level"
/** Compression algorithms supported by the channel.
* Its value is a bitset (an int). Bits correspond to algorithms in \a
* grpc_compression_algorithm. For example, its LSB corresponds to
* GRPC_COMPRESS_NONE, the next bit to GRPC_COMPRESS_DEFLATE, etc.
* Unset bits disable support for the algorithm. By default all algorithms are
* supported. It's not possible to disable GRPC_COMPRESS_NONE (the attempt will
* be ignored). */
#define GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET \
"grpc.compression_enabled_algorithms_bitset"
/** \} */
/* The various compression algorithms supported by gRPC */
typedef enum {

@ -106,58 +106,66 @@ typedef struct {
by grpc_arg; keys are strings to allow easy backwards-compatible extension
by arbitrary parties.
All evaluation is performed at channel creation time (i.e. the values in
this structure need only live through the creation invocation). */
this structure need only live through the creation invocation).
See the description of the \ref grpc_arg_keys "available args" for more
details. */
typedef struct {
size_t num_args;
grpc_arg *args;
} grpc_channel_args;
/* Channel argument keys: */
/** Enable census for tracing and stats collection */
/** \defgroup grpc_arg_keys
* Channel argument keys.
* \{
*/
/** If non-zero, enable census for tracing and stats collection. */
#define GRPC_ARG_ENABLE_CENSUS "grpc.census"
/** Enable load reporting */
/** If non-zero, enable load reporting. */
#define GRPC_ARG_ENABLE_LOAD_REPORTING "grpc.loadreporting"
/** Maximum number of concurrent incoming streams to allow on a http2
connection */
connection. Int valued. */
#define GRPC_ARG_MAX_CONCURRENT_STREAMS "grpc.max_concurrent_streams"
/** Maximum message length that the channel can receive */
/** Maximum message length that the channel can receive. Int valued, bytes. */
#define GRPC_ARG_MAX_MESSAGE_LENGTH "grpc.max_message_length"
/** Initial sequence number for http2 transports */
/** Initial sequence number for http2 transports. Int valued. */
#define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \
"grpc.http2.initial_sequence_number"
/** Amount to read ahead on individual streams. Defaults to 64kb, larger
values can help throughput on high-latency connections.
NOTE: at some point we'd like to auto-tune this, and this parameter
will become a no-op. */
will become a no-op. Int valued, bytes. */
#define GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES "grpc.http2.lookahead_bytes"
/** How much memory to use for hpack decoding */
/** How much memory to use for hpack decoding. Int valued, bytes. */
#define GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER \
"grpc.http2.hpack_table_size.decoder"
/** How much memory to use for hpack encoding */
/** How much memory to use for hpack encoding. Int valued, bytes. */
#define GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER \
"grpc.http2.hpack_table_size.encoder"
/** Default authority to pass if none specified on call construction */
/** Default authority to pass if none specified on call construction. A string.
* */
#define GRPC_ARG_DEFAULT_AUTHORITY "grpc.default_authority"
/** Primary user agent: goes at the start of the user-agent metadata
sent on each request */
sent on each request. A string. */
#define GRPC_ARG_PRIMARY_USER_AGENT_STRING "grpc.primary_user_agent"
/** Secondary user agent: goes at the end of the user-agent metadata
sent on each request */
sent on each request. A string. */
#define GRPC_ARG_SECONDARY_USER_AGENT_STRING "grpc.secondary_user_agent"
/** The maximum time between subsequent connection attempts, in ms */
#define GRPC_ARG_MAX_RECONNECT_BACKOFF_MS "grpc.max_reconnect_backoff_ms"
/* The caller of the secure_channel_create functions may override the target
name used for SSL host name checking using this channel argument which is of
type GRPC_ARG_STRING. This *should* be used for testing only.
type \a GRPC_ARG_STRING. This *should* be used for testing only.
If this argument is not specified, the name used for SSL host name checking
will be the target parameter (assuming that the secure channel is an SSL
channel). If this parameter is specified and the underlying is not an SSL
channel, it will just be ignored. */
#define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG "grpc.ssl_target_name_override"
/* Maximum metadata size */
/* Maximum metadata size, in bytes. */
#define GRPC_ARG_MAX_METADATA_SIZE "grpc.max_metadata_size"
/** If non-zero, allow the use of SO_REUSEPORT if it's available (default 1) */
#define GRPC_ARG_ALLOW_REUSEPORT "grpc.so_reuseport"
/** \} */
/** Result of a grpc call. If the caller satisfies the prerequisites of a
particular operation, the grpc_call_error returned will be GRPC_CALL_OK.

@ -119,7 +119,7 @@
// libraries; it should be integrated with the `__linux__` definitions below.
#define GPR_PLATFORM_STRING "manylinux"
#define GPR_POSIX_CRASH_HANDLER 1
#define GPR_CPU_LINUX 1
#define GPR_CPU_POSIX 1
#define GPR_GCC_ATOMIC 1
#define GPR_GCC_TLS 1
#define GPR_LINUX 1

@ -120,6 +120,14 @@ GPRAPI void gpr_slice_unref(gpr_slice s);
passed in at destruction. */
GPRAPI gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *));
/* Equivalent to gpr_slice_new, but with a separate pointer that is
passed to the destroy function. This function can be useful when
the data is part of a larger structure that must be destroyed when
the data is no longer needed. */
GPRAPI gpr_slice gpr_slice_new_with_user_data(void *p, size_t len,
void (*destroy)(void *),
void *user_data);
/* Equivalent to gpr_slice_new, but with a two argument destroy function that
also takes the slice length. */
GPRAPI gpr_slice gpr_slice_new_with_len(void *p, size_t len,

@ -1,5 +1,15 @@
framework module grpc {
umbrella header "grpc.h"
header "byte_buffer_reader.h"
header "grpc_security.h"
header "grpc_security_constants.h"
header "impl/codegen/alloc.h"
header "impl/codegen/byte_buffer_reader.h"
header "support/alloc.h"
header "support/port_platform.h"
header "support/string_util.h"
export *
module * { export * }
}

@ -1,6 +1,6 @@
{
"name": "grpc",
"version": "0.16.0-dev",
"version": "1.1.0-dev",
"author": "Google Inc.",
"description": "gRPC Library for Node",
"homepage": "http://www.grpc.io/",

@ -10,19 +10,19 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
<date>2016-06-30</date>
<date>2016-07-28</date>
<time>16:06:07</time>
<version>
<release>0.16.0</release>
<api>0.16.0</api>
<release>1.1.0</release>
<api>1.1.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
<release>stable</release>
<api>stable</api>
</stability>
<license>BSD</license>
<notes>
- Fix shutdown hang problem #4017
- PHP7 Support continued, reduce code duplication #7543
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@ -46,6 +46,7 @@
<file baseinstalldir="/" name="src/php/ext/grpc/channel.h" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/channel_credentials.h" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/completion_queue.h" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/php7_wrapper.h" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/php_grpc.h" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/server.h" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/server_credentials.h" role="src" />
@ -184,6 +185,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/compress_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/connected_channel.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/context.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/handshaker.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/algorithm_metadata.h" role="src" />
@ -339,6 +341,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack_builder.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/compress_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/connected_channel.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/handshaker.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/compression.c" role="src" />
@ -1086,18 +1089,49 @@ Update to wrap gRPC C Core version 0.10.0
</release>
<release>
<version>
<release>0.15.1</release>
<api>0.15.1</api>
<release>1.0.0RC1</release>
<api>1.0.0RC1</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
<release>stable</release>
<api>stable</api>
</stability>
<date>2016-06-30</date>
<date>2016-07-13</date>
<license>BSD</license>
<notes>
- GA release
- Fix shutdown hang problem #4017
</notes>
</release>
<release>
<version>
<release>1.0.0RC2</release>
<api>1.0.0RC2</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2016-07-21</date>
<license>BSD</license>
<notes>
- PHP7 Support #7464
</notes>
</release>
<release>
<version>
<release>1.0.0RC3</release>
<api>1.0.0RC3</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2016-07-28</date>
<license>BSD</license>
<notes>
- PHP7 Support continued, reduce code duplication #7543
</notes>
</release>
</changelog>
</package>

@ -9,5 +9,5 @@ build_base=python_build
[build_ext]
inplace=1
[build_proto_modules]
[build_package_protos]
exclude=.*protoc_plugin/protoc_plugin_test\.proto$

@ -29,17 +29,18 @@
"""A setup module for the GRPC Python package."""
from distutils import extension as _extension
from distutils import util
import os
import os.path
import pkg_resources
import platform
import re
import shlex
import shutil
import sys
import sysconfig
from distutils import core as _core
from distutils import extension as _extension
import pkg_resources
import setuptools
from setuptools.command import egg_info
@ -47,10 +48,10 @@ from setuptools.command import egg_info
egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in'
PY3 = sys.version_info.major == 3
PYTHON_STEM = './src/python/grpcio'
CORE_INCLUDE = ('./include', '.',)
BORINGSSL_INCLUDE = ('./third_party/boringssl/include',)
ZLIB_INCLUDE = ('./third_party/zlib',)
PYTHON_STEM = os.path.join('src', 'python', 'grpcio')
CORE_INCLUDE = ('include', '.',)
BORINGSSL_INCLUDE = (os.path.join('third_party', 'boringssl', 'include'),)
ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),)
# Ensure we're in the proper directory whether or not we're being used by pip.
os.chdir(os.path.dirname(os.path.abspath(__file__)))
@ -62,15 +63,17 @@ import commands
import grpc_core_dependencies
import grpc_version
# TODO(atash) make this conditional on being on a mingw32 build
_unixccompiler_patch.monkeypatch_unix_compiler()
if 'win32' in sys.platform:
_unixccompiler_patch.monkeypatch_unix_compiler()
LICENSE = '3-clause BSD'
# Environment variable to determine whether or not the Cython extension should
# *use* Cython or use the generated C files. Note that this requires the C files
# to have been generated by building first *with* Cython support.
# to have been generated by building first *with* Cython support. Even if this
# is set to false, if the script detects that the generated `.c` file isn't
# present, then it will still attempt to use Cython.
BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False)
# Environment variable to determine whether or not to enable coverage analysis
@ -82,18 +85,46 @@ ENABLE_CYTHON_TRACING = os.environ.get(
# entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support.
# We use these environment variables to thus get around that without locking
# ourselves in w.r.t. the multitude of operating systems this ought to build on.
# By default we assume a GCC-like compiler.
EXTRA_COMPILE_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_CFLAGS', ''))
EXTRA_LINK_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_LDFLAGS', ''))
# We can also use these variables as a way to inject environment-specific
# compiler/linker flags. We assume GCC-like compilers and/or MinGW as a
# reasonable default.
EXTRA_ENV_COMPILE_ARGS = os.environ.get('GRPC_PYTHON_CFLAGS', None)
EXTRA_ENV_LINK_ARGS = os.environ.get('GRPC_PYTHON_LDFLAGS', None)
if EXTRA_ENV_COMPILE_ARGS is None:
EXTRA_ENV_COMPILE_ARGS = '-fno-wrapv'
if 'win32' in sys.platform:
# We use define flags here and don't directly add to DEFINE_MACROS below to
# ensure that the expert user/builder has a way of turning it off (via the
# envvars) without adding yet more GRPC-specific envvars.
# See https://sourceforge.net/p/mingw-w64/bugs/363/
if '32' in platform.architecture()[0]:
EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s'
else:
EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
elif "linux" in sys.platform or "darwin" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden'
if EXTRA_ENV_LINK_ARGS is None:
EXTRA_ENV_LINK_ARGS = '-lpthread'
if 'win32' in sys.platform:
# TODO(atash) check if this is actually safe to just import and call on
# non-Windows (to avoid breaking import style)
from distutils.cygwinccompiler import get_msvcr
msvcr = get_msvcr()[0]
# TODO(atash) sift through the GCC specs to see if libstdc++ can have any
# influence on the linkage outcome on MinGW for non-C++ programs.
EXTRA_ENV_LINK_ARGS += (
' -static-libgcc -static-libstdc++ -mcrtdll={msvcr} '
'-static'.format(msvcr=msvcr))
elif "linux" in sys.platform:
EXTRA_ENV_LINK_ARGS += ' -Wl,-wrap,memcpy'
EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS)
EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS)
CYTHON_EXTENSION_PACKAGE_NAMES = ()
CYTHON_EXTENSION_MODULE_NAMES = ('grpc._cython.cygrpc',)
CYTHON_HELPER_C_FILES = (
os.path.join(PYTHON_STEM, 'grpc/_cython/loader.c'),
os.path.join(PYTHON_STEM, 'grpc/_cython/imports.generated.c'),
)
CYTHON_HELPER_C_FILES = ()
CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES)
@ -108,7 +139,9 @@ if not "win32" in sys.platform:
if "win32" in sys.platform:
EXTENSION_LIBRARIES += ('ws2_32',)
DEFINE_MACROS = (('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600), ('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
DEFINE_MACROS = (
('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600),
('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
if "win32" in sys.platform:
DEFINE_MACROS += (('OPENSSL_WINDOWS', 1), ('WIN32_LEAN_AND_MEAN', 1),)
if '64bit' in platform.architecture()[0]:
@ -116,13 +149,8 @@ if "win32" in sys.platform:
LDFLAGS = tuple(EXTRA_LINK_ARGS)
CFLAGS = tuple(EXTRA_COMPILE_ARGS)
if "linux" in sys.platform:
LDFLAGS += ('-Wl,-wrap,memcpy',)
if "linux" in sys.platform or "darwin" in sys.platform:
CFLAGS += ('-fvisibility=hidden',)
pymodinit_type = 'PyObject*' if PY3 else 'void'
pymodinit = '__attribute__((visibility ("default"))) {}'.format(pymodinit_type)
DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
@ -135,45 +163,32 @@ if 'darwin' in sys.platform and PY3:
if mac_target and (pkg_resources.parse_version(mac_target) <
pkg_resources.parse_version('10.7.0')):
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
def cython_extensions(module_names, extra_sources, include_dirs,
libraries, define_macros, build_with_cython=False):
# Set compiler directives linetrace argument only if we care about tracing;
# this is due to Cython having different behavior between linetrace being
# False and linetrace being unset. See issue #5689.
cython_compiler_directives = {}
if ENABLE_CYTHON_TRACING:
define_macros = define_macros + [('CYTHON_TRACE_NOGIL', 1)]
cython_compiler_directives['linetrace'] = True
file_extension = 'pyx' if build_with_cython else 'c'
module_files = [os.path.join(PYTHON_STEM,
name.replace('.', '/') + '.' + file_extension)
for name in module_names]
os.environ['_PYTHON_HOST_PLATFORM'] = re.sub(
r'macosx-[0-9]+\.[0-9]+-(.+)',
r'macosx-10.7-\1',
util.get_platform())
def cython_extensions_and_necessity():
cython_module_files = [os.path.join(PYTHON_STEM,
name.replace('.', '/') + '.pyx')
for name in CYTHON_EXTENSION_MODULE_NAMES]
extensions = [
_extension.Extension(
name=module_name,
sources=[module_file] + extra_sources,
include_dirs=include_dirs, libraries=libraries,
define_macros=define_macros,
sources=[module_file] + list(CYTHON_HELPER_C_FILES) + list(CORE_C_FILES),
include_dirs=list(EXTENSION_INCLUDE_DIRECTORIES),
libraries=list(EXTENSION_LIBRARIES),
define_macros=list(DEFINE_MACROS),
extra_compile_args=list(CFLAGS),
extra_link_args=list(LDFLAGS),
) for (module_name, module_file) in zip(module_names, module_files)
) for (module_name, module_file) in zip(list(CYTHON_EXTENSION_MODULE_NAMES), cython_module_files)
]
if build_with_cython:
import Cython.Build
return Cython.Build.cythonize(
extensions,
include_path=include_dirs,
compiler_directives=cython_compiler_directives)
else:
return extensions
CYTHON_EXTENSION_MODULES = cython_extensions(
list(CYTHON_EXTENSION_MODULE_NAMES),
list(CYTHON_HELPER_C_FILES) + list(CORE_C_FILES),
list(EXTENSION_INCLUDE_DIRECTORIES), list(EXTENSION_LIBRARIES),
list(DEFINE_MACROS), bool(BUILD_WITH_CYTHON))
need_cython = BUILD_WITH_CYTHON
if not BUILD_WITH_CYTHON:
need_cython = need_cython or not commands.check_and_update_cythonization(extensions)
return commands.try_cythonize(extensions, linetracing=ENABLE_CYTHON_TRACING, mandatory=BUILD_WITH_CYTHON), need_cython
CYTHON_EXTENSION_MODULES, need_cython = cython_extensions_and_necessity()
PACKAGE_DIRECTORIES = {
'': PYTHON_STEM,
@ -193,6 +208,15 @@ SETUP_REQUIRES = INSTALL_REQUIRES + (
'sphinx_rtd_theme>=0.1.8',
'six>=1.10',
)
if BUILD_WITH_CYTHON:
sys.stderr.write(
"You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, "
"but do not have Cython installed. We won't stop you from using "
"other commands, but the extension files will fail to build.\n")
elif need_cython:
sys.stderr.write(
'We could not find Cython. Setup may take 10-20 minutes.\n')
SETUP_REQUIRES += ('cython>=0.23',)
COMMAND_CLASS = {
'doc': commands.SphinxDocumentation,
@ -203,12 +227,13 @@ COMMAND_CLASS = {
}
# Ensure that package data is copied over before any commands have been run:
credentials_dir = os.path.join(PYTHON_STEM, 'grpc/_cython/_credentials')
credentials_dir = os.path.join(PYTHON_STEM, 'grpc', '_cython', '_credentials')
try:
os.mkdir(credentials_dir)
except OSError:
pass
shutil.copyfile('etc/roots.pem', os.path.join(credentials_dir, 'roots.pem'))
shutil.copyfile(os.path.join('etc', 'roots.pem'),
os.path.join(credentials_dir, 'roots.pem'))
PACKAGE_DATA = {
# Binaries that may or may not be present in the final installation, but are

@ -60,7 +60,8 @@
#ifndef GRPC_CUSTOM_PARSEGENERATORPARAMETER
#include <google/protobuf/compiler/code_generator.h>
#define GRPC_CUSTOM_PARSEGENERATORPARAMETER ::google::protobuf::compiler::ParseGeneratorParameter
#define GRPC_CUSTOM_PARSEGENERATORPARAMETER \
::google::protobuf::compiler::ParseGeneratorParameter
#endif
#ifndef GRPC_CUSTOM_STRING
@ -81,8 +82,8 @@ static inline int PluginMain(int argc, char* argv[],
const CodeGenerator* generator) {
return GRPC_CUSTOM_PLUGINMAIN(argc, argv, generator);
}
static inline void ParseGeneratorParameter(const string& parameter,
std::vector<std::pair<string, string> >* options) {
static inline void ParseGeneratorParameter(
const string& parameter, std::vector<std::pair<string, string> >* options) {
GRPC_CUSTOM_PARSEGENERATORPARAMETER(parameter, options);
}

@ -64,19 +64,22 @@ grpc::string FilenameIdentifier(const grpc::string &filename) {
}
} // namespace
template<class T, size_t N>
T *array_end(T (&array)[N]) { return array + N; }
template <class T, size_t N>
T *array_end(T (&array)[N]) {
return array + N;
}
void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, const Parameters &params) {
void PrintIncludes(Printer *printer, const std::vector<grpc::string> &headers,
const Parameters &params) {
std::map<grpc::string, grpc::string> vars;
vars["l"] = params.use_system_headers ? '<' : '"';
vars["r"] = params.use_system_headers ? '>' : '"';
auto& s = params.grpc_search_path;
auto &s = params.grpc_search_path;
if (!s.empty()) {
vars["l"] += s;
if (s[s.size()-1] != '/') {
if (s[s.size() - 1] != '/') {
vars["l"] += '/';
}
}
@ -101,7 +104,7 @@ grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
printer->Print(vars,
"// If you make any local change, they will be lost.\n");
"// If you make any local change, they will be lost.\n");
printer->Print(vars, "// source: $filename$\n");
grpc::string leading_comments = file->GetLeadingComments();
if (!leading_comments.empty()) {
@ -117,8 +120,7 @@ grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
return output;
}
grpc::string GetHeaderIncludes(File *file,
const Parameters &params) {
grpc::string GetHeaderIncludes(File *file, const Parameters &params) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@ -126,15 +128,14 @@ grpc::string GetHeaderIncludes(File *file,
std::map<grpc::string, grpc::string> vars;
static const char *headers_strs[] = {
"grpc++/impl/codegen/async_stream.h",
"grpc++/impl/codegen/async_unary_call.h",
"grpc++/impl/codegen/proto_utils.h",
"grpc++/impl/codegen/rpc_method.h",
"grpc++/impl/codegen/service_type.h",
"grpc++/impl/codegen/status.h",
"grpc++/impl/codegen/stub_options.h",
"grpc++/impl/codegen/sync_stream.h"
};
"grpc++/impl/codegen/async_stream.h",
"grpc++/impl/codegen/async_unary_call.h",
"grpc++/impl/codegen/proto_utils.h",
"grpc++/impl/codegen/rpc_method.h",
"grpc++/impl/codegen/service_type.h",
"grpc++/impl/codegen/status.h",
"grpc++/impl/codegen/stub_options.h",
"grpc++/impl/codegen/sync_stream.h"};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
PrintIncludes(printer.get(), headers, params);
printer->Print(vars, "\n");
@ -309,8 +310,7 @@ void PrintHeaderClientMethodInterfaces(
}
}
void PrintHeaderClientMethod(Printer *printer,
const Method *method,
void PrintHeaderClientMethod(Printer *printer, const Method *method,
std::map<grpc::string, grpc::string> *vars,
bool is_public) {
(*vars)["Method"] = method->name();
@ -490,10 +490,8 @@ void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
printer->Print(method->GetTrailingComments().c_str());
}
void PrintHeaderServerMethodAsync(
Printer *printer,
const Method *method,
std::map<grpc::string, grpc::string> *vars) {
void PrintHeaderServerMethodAsync(Printer *printer, const Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name();
@ -607,8 +605,7 @@ void PrintHeaderServerMethodAsync(
}
void PrintHeaderServerMethodGeneric(
Printer *printer,
const Method *method,
Printer *printer, const Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@ -677,8 +674,7 @@ void PrintHeaderServerMethodGeneric(
printer->Print(*vars, "};\n");
}
void PrintHeaderService(Printer *printer,
const Service *service,
void PrintHeaderService(Printer *printer, const Service *service,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name();
@ -696,14 +692,16 @@ void PrintHeaderService(Printer *printer,
printer->Print("virtual ~StubInterface() {}\n");
for (int i = 0; i < service->method_count(); ++i) {
printer->Print(service->method(i)->GetLeadingComments().c_str());
PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true);
PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
true);
printer->Print(service->method(i)->GetTrailingComments().c_str());
}
printer->Outdent();
printer->Print("private:\n");
printer->Indent();
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, false);
PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
false);
}
printer->Outdent();
printer->Print("};\n");
@ -711,7 +709,8 @@ void PrintHeaderService(Printer *printer,
"class Stub GRPC_FINAL : public StubInterface"
" {\n public:\n");
printer->Indent();
printer->Print("Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n");
printer->Print(
"Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n");
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
}
@ -776,8 +775,7 @@ void PrintHeaderService(Printer *printer,
printer->Print(service->GetTrailingComments().c_str());
}
grpc::string GetHeaderServices(File *file,
const Parameters &params) {
grpc::string GetHeaderServices(File *file, const Parameters &params) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@ -849,7 +847,7 @@ grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
printer->Print(vars,
"// If you make any local change, they will be lost.\n");
"// If you make any local change, they will be lost.\n");
printer->Print(vars, "// source: $filename$\n\n");
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
@ -860,8 +858,7 @@ grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
return output;
}
grpc::string GetSourceIncludes(File *file,
const Parameters &params) {
grpc::string GetSourceIncludes(File *file, const Parameters &params) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@ -869,15 +866,14 @@ grpc::string GetSourceIncludes(File *file,
std::map<grpc::string, grpc::string> vars;
static const char *headers_strs[] = {
"grpc++/impl/codegen/async_stream.h",
"grpc++/impl/codegen/async_unary_call.h",
"grpc++/impl/codegen/channel_interface.h",
"grpc++/impl/codegen/client_unary_call.h",
"grpc++/impl/codegen/method_handler_impl.h",
"grpc++/impl/codegen/rpc_service_method.h",
"grpc++/impl/codegen/service_type.h",
"grpc++/impl/codegen/sync_stream.h"
};
"grpc++/impl/codegen/async_stream.h",
"grpc++/impl/codegen/async_unary_call.h",
"grpc++/impl/codegen/channel_interface.h",
"grpc++/impl/codegen/client_unary_call.h",
"grpc++/impl/codegen/method_handler_impl.h",
"grpc++/impl/codegen/rpc_service_method.h",
"grpc++/impl/codegen/service_type.h",
"grpc++/impl/codegen/sync_stream.h"};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
PrintIncludes(printer.get(), headers, params);
@ -895,8 +891,7 @@ grpc::string GetSourceIncludes(File *file,
return output;
}
void PrintSourceClientMethod(Printer *printer,
const Method *method,
void PrintSourceClientMethod(Printer *printer, const Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@ -996,8 +991,7 @@ void PrintSourceClientMethod(Printer *printer,
}
}
void PrintSourceServerMethod(Printer *printer,
const Method *method,
void PrintSourceServerMethod(Printer *printer, const Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@ -1055,8 +1049,7 @@ void PrintSourceServerMethod(Printer *printer,
}
}
void PrintSourceService(Printer *printer,
const Service *service,
void PrintSourceService(Printer *printer, const Service *service,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name();
@ -1168,8 +1161,7 @@ void PrintSourceService(Printer *printer,
}
}
grpc::string GetSourceServices(File *file,
const Parameters &params) {
grpc::string GetSourceServices(File *file, const Parameters &params) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.

@ -48,7 +48,7 @@ using grpc_cpp_generator::GetCppComments;
class ProtoBufMethod : public grpc_cpp_generator::Method {
public:
ProtoBufMethod(const grpc::protobuf::MethodDescriptor *method)
: method_(method) {}
: method_(method) {}
grpc::string name() const { return method_->name(); }
@ -90,14 +90,14 @@ class ProtoBufMethod : public grpc_cpp_generator::Method {
class ProtoBufService : public grpc_cpp_generator::Service {
public:
ProtoBufService(const grpc::protobuf::ServiceDescriptor *service)
: service_(service) {}
: service_(service) {}
grpc::string name() const { return service_->name(); }
int method_count() const { return service_->method_count(); };
std::unique_ptr<const grpc_cpp_generator::Method> method(int i) const {
return std::unique_ptr<const grpc_cpp_generator::Method>(
new ProtoBufMethod(service_->method(i)));
new ProtoBufMethod(service_->method(i)));
};
grpc::string GetLeadingComments() const {
@ -115,7 +115,7 @@ class ProtoBufService : public grpc_cpp_generator::Service {
class ProtoBufPrinter : public grpc_cpp_generator::Printer {
public:
ProtoBufPrinter(grpc::string *str)
: output_stream_(str), printer_(&output_stream_, '$') {}
: output_stream_(str), printer_(&output_stream_, '$') {}
void Print(const std::map<grpc::string, grpc::string> &vars,
const char *string_template) {
@ -152,13 +152,14 @@ class ProtoBufFile : public grpc_cpp_generator::File {
int service_count() const { return file_->service_count(); };
std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const {
return std::unique_ptr<const grpc_cpp_generator::Service> (
new ProtoBufService(file_->service(i)));
return std::unique_ptr<const grpc_cpp_generator::Service>(
new ProtoBufService(file_->service(i)));
}
std::unique_ptr<grpc_cpp_generator::Printer> CreatePrinter(grpc::string *str) const {
std::unique_ptr<grpc_cpp_generator::Printer> CreatePrinter(
grpc::string *str) const {
return std::unique_ptr<grpc_cpp_generator::Printer>(
new ProtoBufPrinter(str));
new ProtoBufPrinter(str));
}
grpc::string GetLeadingComments() const {
@ -197,12 +198,11 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
if (!parameter.empty()) {
std::vector<grpc::string> parameters_list =
grpc_generator::tokenize(parameter, ",");
grpc_generator::tokenize(parameter, ",");
for (auto parameter_string = parameters_list.begin();
parameter_string != parameters_list.end();
parameter_string++) {
parameter_string != parameters_list.end(); parameter_string++) {
std::vector<grpc::string> param =
grpc_generator::tokenize(*parameter_string, "=");
grpc_generator::tokenize(*parameter_string, "=");
if (param[0] == "services_namespace") {
generator_parameters.services_namespace = param[1];
} else if (param[0] == "use_system_headers") {
@ -232,8 +232,7 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
grpc_cpp_generator::GetHeaderEpilogue(&pbfile, 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());
grpc::protobuf::io::CodedOutputStream header_coded_out(header_output.get());
header_coded_out.WriteRaw(header_code.data(), header_code.size());
grpc::string source_code =
@ -243,8 +242,7 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
grpc_cpp_generator::GetSourceEpilogue(&pbfile, 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());
grpc::protobuf::io::CodedOutputStream source_coded_out(source_output.get());
source_coded_out.WriteRaw(source_code.data(), source_code.size());
return true;

@ -36,11 +36,10 @@
#include <sstream>
#include <vector>
#include "src/compiler/csharp_generator.h"
#include "src/compiler/config.h"
#include "src/compiler/csharp_generator_helpers.h"
#include "src/compiler/csharp_generator.h"
#include "src/compiler/csharp_generator.h"
#include "src/compiler/csharp_generator_helpers.h"
using google::protobuf::compiler::csharp::GetFileNamespace;
using google::protobuf::compiler::csharp::GetClassName;
@ -61,7 +60,6 @@ using grpc_generator::StringReplace;
using std::map;
using std::vector;
namespace grpc_csharp_generator {
namespace {
@ -70,34 +68,43 @@ namespace {
// Currently, we cannot easily reuse the functionality as
// google/protobuf/compiler/csharp/csharp_doc_comment.h is not a public header.
// TODO(jtattermusch): reuse the functionality from google/protobuf.
void GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer* printer, grpc::protobuf::SourceLocation location) {
grpc::string comments = location.leading_comments.empty() ?
location.trailing_comments : location.leading_comments;
void GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer *printer,
grpc::protobuf::SourceLocation location) {
grpc::string comments = location.leading_comments.empty()
? location.trailing_comments
: location.leading_comments;
if (comments.empty()) {
return;
}
// XML escaping... no need for apostrophes etc as the whole text is going to be a child
// XML escaping... no need for apostrophes etc as the whole text is going to
// be a child
// node of a summary element, not part of an attribute.
comments = grpc_generator::StringReplace(comments, "&", "&amp;", true);
comments = grpc_generator::StringReplace(comments, "<", "&lt;", true);
std::vector<grpc::string> lines;
grpc_generator::Split(comments, '\n', &lines);
// TODO: We really should work out which part to put in the summary and which to put in the remarks...
// but that needs to be part of a bigger effort to understand the markdown better anyway.
// TODO: We really should work out which part to put in the summary and which
// to put in the remarks...
// but that needs to be part of a bigger effort to understand the markdown
// better anyway.
printer->Print("/// <summary>\n");
bool last_was_empty = false;
// We squash multiple blank lines down to one, and remove any trailing blank lines. We need
// to preserve the blank lines themselves, as this is relevant in the markdown.
// Note that we can't remove leading or trailing whitespace as *that's* relevant in markdown too.
// We squash multiple blank lines down to one, and remove any trailing blank
// lines. We need
// to preserve the blank lines themselves, as this is relevant in the
// markdown.
// Note that we can't remove leading or trailing whitespace as *that's*
// relevant in markdown too.
// (We don't skip "just whitespace" lines, either.)
for (std::vector<grpc::string>::iterator it = lines.begin(); it != lines.end(); ++it) {
for (std::vector<grpc::string>::iterator it = lines.begin();
it != lines.end(); ++it) {
grpc::string line = *it;
if (line.empty()) {
last_was_empty = true;
} else {
if (last_was_empty) {
printer->Print("///\n");
printer->Print("///\n");
}
last_was_empty = false;
printer->Print("/// $line$\n", "line", *it);
@ -107,23 +114,23 @@ void GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer* printer, grpc::prot
}
template <typename DescriptorType>
void GenerateDocCommentBody(
grpc::protobuf::io::Printer* printer, const DescriptorType* descriptor) {
void GenerateDocCommentBody(grpc::protobuf::io::Printer *printer,
const DescriptorType *descriptor) {
grpc::protobuf::SourceLocation location;
if (descriptor->GetSourceLocation(&location)) {
GenerateDocCommentBodyImpl(printer, location);
}
}
std::string GetServiceClassName(const ServiceDescriptor* service) {
std::string GetServiceClassName(const ServiceDescriptor *service) {
return service->name();
}
std::string GetClientClassName(const ServiceDescriptor* service) {
std::string GetClientClassName(const ServiceDescriptor *service) {
return service->name() + "Client";
}
std::string GetServerClassName(const ServiceDescriptor* service) {
std::string GetServerClassName(const ServiceDescriptor *service) {
return service->name() + "Base";
}
@ -138,13 +145,11 @@ std::string GetCSharpMethodType(MethodType method_type) {
case METHODTYPE_BIDI_STREAMING:
return "MethodType.DuplexStreaming";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
std::string GetServiceNameFieldName() {
return "__ServiceName";
}
std::string GetServiceNameFieldName() { return "__ServiceName"; }
std::string GetMarshallerFieldName(const Descriptor *message) {
return "__Marshaller_" + message->name();
@ -155,7 +160,7 @@ std::string GetMethodFieldName(const MethodDescriptor *method) {
}
std::string GetMethodRequestParamMaybe(const MethodDescriptor *method,
bool invocation_param=false) {
bool invocation_param = false) {
if (method->client_streaming()) {
return "";
}
@ -174,16 +179,16 @@ std::string GetMethodReturnTypeClient(const MethodDescriptor *method) {
case METHODTYPE_NO_STREAMING:
return "AsyncUnaryCall<" + GetClassName(method->output_type()) + ">";
case METHODTYPE_CLIENT_STREAMING:
return "AsyncClientStreamingCall<" + GetClassName(method->input_type())
+ ", " + GetClassName(method->output_type()) + ">";
return "AsyncClientStreamingCall<" + GetClassName(method->input_type()) +
", " + GetClassName(method->output_type()) + ">";
case METHODTYPE_SERVER_STREAMING:
return "AsyncServerStreamingCall<" + GetClassName(method->output_type())
+ ">";
return "AsyncServerStreamingCall<" + GetClassName(method->output_type()) +
">";
case METHODTYPE_BIDI_STREAMING:
return "AsyncDuplexStreamingCall<" + GetClassName(method->input_type())
+ ", " + GetClassName(method->output_type()) + ">";
return "AsyncDuplexStreamingCall<" + GetClassName(method->input_type()) +
", " + GetClassName(method->output_type()) + ">";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
@ -194,10 +199,10 @@ std::string GetMethodRequestParamServer(const MethodDescriptor *method) {
return GetClassName(method->input_type()) + " request";
case METHODTYPE_CLIENT_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return "IAsyncStreamReader<" + GetClassName(method->input_type())
+ "> requestStream";
return "IAsyncStreamReader<" + GetClassName(method->input_type()) +
"> requestStream";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
@ -205,12 +210,13 @@ std::string GetMethodReturnTypeServer(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
case METHODTYPE_CLIENT_STREAMING:
return "global::System.Threading.Tasks.Task<" + GetClassName(method->output_type()) + ">";
return "global::System.Threading.Tasks.Task<" +
GetClassName(method->output_type()) + ">";
case METHODTYPE_SERVER_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return "global::System.Threading.Tasks.Task";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
@ -221,18 +227,19 @@ std::string GetMethodResponseStreamMaybe(const MethodDescriptor *method) {
return "";
case METHODTYPE_SERVER_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return ", IServerStreamWriter<" + GetClassName(method->output_type())
+ "> responseStream";
return ", IServerStreamWriter<" + GetClassName(method->output_type()) +
"> responseStream";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
}
// Gets vector of all messages used as input or output types.
std::vector<const Descriptor*> GetUsedMessages(
std::vector<const Descriptor *> GetUsedMessages(
const ServiceDescriptor *service) {
std::set<const Descriptor*> descriptor_set;
std::vector<const Descriptor*> result; // vector is to maintain stable ordering
std::set<const Descriptor *> descriptor_set;
std::vector<const Descriptor *>
result; // vector is to maintain stable ordering
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
if (descriptor_set.find(method->input_type()) == descriptor_set.end()) {
@ -247,21 +254,25 @@ std::vector<const Descriptor*> GetUsedMessages(
return result;
}
void GenerateMarshallerFields(Printer* out, const ServiceDescriptor *service) {
std::vector<const Descriptor*> used_messages = GetUsedMessages(service);
void GenerateMarshallerFields(Printer *out, const ServiceDescriptor *service) {
std::vector<const Descriptor *> used_messages = GetUsedMessages(service);
for (size_t i = 0; i < used_messages.size(); i++) {
const Descriptor *message = used_messages[i];
out->Print(
"static readonly Marshaller<$type$> $fieldname$ = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), $type$.Parser.ParseFrom);\n",
"static readonly Marshaller<$type$> $fieldname$ = "
"Marshallers.Create((arg) => "
"global::Google.Protobuf.MessageExtensions.ToByteArray(arg), "
"$type$.Parser.ParseFrom);\n",
"fieldname", GetMarshallerFieldName(message), "type",
GetClassName(message));
}
out->Print("\n");
}
void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) {
void GenerateStaticMethodField(Printer *out, const MethodDescriptor *method) {
out->Print(
"static readonly Method<$request$, $response$> $fieldname$ = new Method<$request$, $response$>(\n",
"static readonly Method<$request$, $response$> $fieldname$ = new "
"Method<$request$, $response$>(\n",
"fieldname", GetMethodFieldName(method), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
@ -270,7 +281,7 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) {
out->Print("$methodtype$,\n", "methodtype",
GetCSharpMethodType(GetMethodType(method)));
out->Print("$servicenamefield$,\n", "servicenamefield",
GetServiceNameFieldName());
GetServiceNameFieldName());
out->Print("\"$methodname$\",\n", "methodname", method->name());
out->Print("$requestmarshaller$,\n", "requestmarshaller",
GetMarshallerFieldName(method->input_type()));
@ -281,11 +292,14 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) {
out->Outdent();
}
void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *service) {
void GenerateServiceDescriptorProperty(Printer *out,
const ServiceDescriptor *service) {
std::ostringstream index;
index << service->index();
out->Print("/// <summary>Service descriptor</summary>\n");
out->Print("public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor\n");
out->Print(
"public static global::Google.Protobuf.Reflection.ServiceDescriptor "
"Descriptor\n");
out->Print("{\n");
out->Print(" get { return $umbrella$.Descriptor.Services[$index$]; }\n",
"umbrella", GetReflectionClassName(service->file()), "index",
@ -294,9 +308,11 @@ void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *se
out->Print("\n");
}
void GenerateServerClass(Printer* out, const ServiceDescriptor *service) {
out->Print("/// <summary>Base class for server-side implementations of $servicename$</summary>\n",
"servicename", GetServiceClassName(service));
void GenerateServerClass(Printer *out, const ServiceDescriptor *service) {
out->Print(
"/// <summary>Base class for server-side implementations of "
"$servicename$</summary>\n",
"servicename", GetServiceClassName(service));
out->Print("public abstract class $name$\n", "name",
GetServerClassName(service));
out->Print("{\n");
@ -305,7 +321,8 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor *service) {
const MethodDescriptor *method = service->method(i);
GenerateDocCommentBody(out, method);
out->Print(
"public virtual $returntype$ $methodname$($request$$response_stream_maybe$, "
"public virtual $returntype$ "
"$methodname$($request$$response_stream_maybe$, "
"ServerCallContext context)\n",
"methodname", method->name(), "returntype",
GetMethodReturnTypeServer(method), "request",
@ -313,8 +330,9 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor *service) {
GetMethodResponseStreamMaybe(method));
out->Print("{\n");
out->Indent();
out->Print("throw new RpcException("
"new Status(StatusCode.Unimplemented, \"\"));\n");
out->Print(
"throw new RpcException("
"new Status(StatusCode.Unimplemented, \"\"));\n");
out->Outdent();
out->Print("}\n\n");
}
@ -323,41 +341,49 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor *service) {
out->Print("\n");
}
void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Print("/// <summary>Client for $servicename$</summary>\n",
"servicename", GetServiceClassName(service));
out->Print(
"public class $name$ : ClientBase<$name$>\n",
"name", GetClientClassName(service));
void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
out->Print("/// <summary>Client for $servicename$</summary>\n", "servicename",
GetServiceClassName(service));
out->Print("public class $name$ : ClientBase<$name$>\n", "name",
GetClientClassName(service));
out->Print("{\n");
out->Indent();
// constructors
out->Print("/// <summary>Creates a new client for $servicename$</summary>\n"
"/// <param name=\"channel\">The channel to use to make remote calls.</param>\n",
"servicename", GetServiceClassName(service));
out->Print("public $name$(Channel channel) : base(channel)\n",
"name", GetClientClassName(service));
out->Print(
"/// <summary>Creates a new client for $servicename$</summary>\n"
"/// <param name=\"channel\">The channel to use to make remote "
"calls.</param>\n",
"servicename", GetServiceClassName(service));
out->Print("public $name$(Channel channel) : base(channel)\n", "name",
GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print("/// <summary>Creates a new client for $servicename$ that uses a custom <c>CallInvoker</c>.</summary>\n"
"/// <param name=\"callInvoker\">The callInvoker to use to make remote calls.</param>\n",
"servicename", GetServiceClassName(service));
out->Print(
"/// <summary>Creates a new client for $servicename$ that uses a custom "
"<c>CallInvoker</c>.</summary>\n"
"/// <param name=\"callInvoker\">The callInvoker to use to make remote "
"calls.</param>\n",
"servicename", GetServiceClassName(service));
out->Print("public $name$(CallInvoker callInvoker) : base(callInvoker)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print("/// <summary>Protected parameterless constructor to allow creation"
" of test doubles.</summary>\n");
out->Print("protected $name$() : base()\n",
"name", GetClientClassName(service));
out->Print(
"/// <summary>Protected parameterless constructor to allow creation"
" of test doubles.</summary>\n");
out->Print("protected $name$() : base()\n", "name",
GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print("/// <summary>Protected constructor to allow creation of configured clients.</summary>\n"
"/// <param name=\"configuration\">The client configuration.</param>\n");
out->Print("protected $name$(ClientBaseConfiguration configuration)"
" : base(configuration)\n",
"name", GetClientClassName(service));
out->Print(
"/// <summary>Protected constructor to allow creation of configured "
"clients.</summary>\n"
"/// <param name=\"configuration\">The client configuration.</param>\n");
out->Print(
"protected $name$(ClientBaseConfiguration configuration)"
" : base(configuration)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n\n");
@ -368,27 +394,36 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
GenerateDocCommentBody(out, method);
out->Print("public virtual $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
out->Print(
"public virtual $response$ $methodname$($request$ request, Metadata "
"headers = null, DateTime? deadline = null, CancellationToken "
"cancellationToken = default(CancellationToken))\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("return $methodname$(request, new CallOptions(headers, deadline, cancellationToken));\n",
"methodname", method->name());
out->Print(
"return $methodname$(request, new CallOptions(headers, deadline, "
"cancellationToken));\n",
"methodname", method->name());
out->Outdent();
out->Print("}\n");
// overload taking CallOptions as a param
GenerateDocCommentBody(out, method);
out->Print("public virtual $response$ $methodname$($request$ request, CallOptions options)\n",
out->Print(
"public virtual $response$ $methodname$($request$ request, "
"CallOptions options)\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("return CallInvoker.BlockingUnaryCall($methodfield$, null, options, request);\n",
"methodfield", GetMethodFieldName(method));
out->Print(
"return CallInvoker.BlockingUnaryCall($methodfield$, null, options, "
"request);\n",
"methodfield", GetMethodFieldName(method));
out->Outdent();
out->Print("}\n");
}
@ -399,23 +434,28 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
}
GenerateDocCommentBody(out, method);
out->Print(
"public virtual $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
"public virtual $returntype$ $methodname$($request_maybe$Metadata "
"headers = null, DateTime? deadline = null, CancellationToken "
"cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("return $methodname$($request_maybe$new CallOptions(headers, deadline, cancellationToken));\n",
"methodname", method_name,
"request_maybe", GetMethodRequestParamMaybe(method, true));
out->Print(
"return $methodname$($request_maybe$new CallOptions(headers, deadline, "
"cancellationToken));\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method, true));
out->Outdent();
out->Print("}\n");
// overload taking CallOptions as a param
GenerateDocCommentBody(out, method);
out->Print(
"public virtual $returntype$ $methodname$($request_maybe$CallOptions options)\n",
"public virtual $returntype$ $methodname$($request_maybe$CallOptions "
"options)\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
@ -423,36 +463,45 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Indent();
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return CallInvoker.AsyncUnaryCall($methodfield$, null, options, request);\n",
"methodfield", GetMethodFieldName(method));
out->Print(
"return CallInvoker.AsyncUnaryCall($methodfield$, null, options, "
"request);\n",
"methodfield", GetMethodFieldName(method));
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return CallInvoker.AsyncClientStreamingCall($methodfield$, null, options);\n",
"methodfield", GetMethodFieldName(method));
out->Print(
"return CallInvoker.AsyncClientStreamingCall($methodfield$, null, "
"options);\n",
"methodfield", GetMethodFieldName(method));
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return CallInvoker.AsyncServerStreamingCall($methodfield$, null, options, request);\n",
"return CallInvoker.AsyncServerStreamingCall($methodfield$, null, "
"options, request);\n",
"methodfield", GetMethodFieldName(method));
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, options);\n",
"methodfield", GetMethodFieldName(method));
out->Print(
"return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, "
"options);\n",
"methodfield", GetMethodFieldName(method));
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
GOOGLE_LOG(FATAL) << "Can't get here.";
}
out->Outdent();
out->Print("}\n");
}
// override NewInstance method
out->Print("protected override $name$ NewInstance(ClientBaseConfiguration configuration)\n",
"name", GetClientClassName(service));
out->Print(
"protected override $name$ NewInstance(ClientBaseConfiguration "
"configuration)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Indent();
out->Print("return new $name$(configuration);\n",
"name", GetClientClassName(service));
out->Print("return new $name$(configuration);\n", "name",
GetClientClassName(service));
out->Outdent();
out->Print("}\n");
@ -461,11 +510,13 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Print("\n");
}
void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) {
void GenerateBindServiceMethod(Printer *out, const ServiceDescriptor *service) {
out->Print(
"/// <summary>Creates service definition that can be registered with a server</summary>\n");
"/// <summary>Creates service definition that can be registered with a "
"server</summary>\n");
out->Print(
"public static ServerServiceDefinition BindService($implclass$ serviceImpl)\n",
"public static ServerServiceDefinition BindService($implclass$ "
"serviceImpl)\n",
"implclass", GetServerClassName(service));
out->Print("{\n");
out->Indent();
@ -491,7 +542,7 @@ void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) {
out->Print("\n");
}
void GenerateService(Printer* out, const ServiceDescriptor *service,
void GenerateService(Printer *out, const ServiceDescriptor *service,
bool generate_client, bool generate_server,
bool internal_access) {
GenerateDocCommentBody(out, service);

@ -41,14 +41,16 @@ namespace grpc_csharp_generator {
inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file,
grpc::string *file_name_or_error) {
*file_name_or_error = grpc_generator::FileNameInUpperCamel(file, false) + "Grpc.cs";
*file_name_or_error =
grpc_generator::FileNameInUpperCamel(file, false) + "Grpc.cs";
return true;
}
// Get leading or trailing comments in a string. Comment lines start with "// ".
// Leading detached comments are put in in front of leading comments.
template <typename DescriptorType>
inline grpc::string GetCsharpComments(const DescriptorType *desc, bool leading) {
inline grpc::string GetCsharpComments(const DescriptorType *desc,
bool leading) {
return grpc_generator::GetPrefixedComments(desc, leading, "//");
}

@ -67,10 +67,8 @@ class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
}
}
grpc::string code = grpc_csharp_generator::GetServices(file,
generate_client,
generate_server,
internal_access);
grpc::string code = grpc_csharp_generator::GetServices(
file, generate_client, generate_server, internal_access);
if (code.size() == 0) {
return true; // don't generate a file if there are no services
}

@ -84,7 +84,7 @@ inline grpc::string StringReplace(grpc::string str, const grpc::string &from,
}
str.replace(pos, from.length(), to);
pos += to.length();
} while(replace_all);
} while (replace_all);
return str;
}
@ -139,8 +139,8 @@ inline grpc::string LowerUnderscoreToUpperCamel(grpc::string str) {
return result;
}
inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *file,
bool include_package_path) {
inline grpc::string FileNameInUpperCamel(
const grpc::protobuf::FileDescriptor *file, bool include_package_path) {
std::vector<grpc::string> tokens = tokenize(StripProto(file->name()), "/");
grpc::string result = "";
if (include_package_path) {
@ -152,7 +152,8 @@ inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *f
return result;
}
inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *file) {
inline grpc::string FileNameInUpperCamel(
const grpc::protobuf::FileDescriptor *file) {
return FileNameInUpperCamel(file, true);
}
@ -163,7 +164,8 @@ enum MethodType {
METHODTYPE_BIDI_STREAMING
};
inline MethodType GetMethodType(const grpc::protobuf::MethodDescriptor *method) {
inline MethodType GetMethodType(
const grpc::protobuf::MethodDescriptor *method) {
if (method->client_streaming()) {
if (method->server_streaming()) {
return METHODTYPE_BIDI_STREAMING;
@ -254,7 +256,7 @@ inline grpc::string GenerateCommentsWithPrefix(
const std::vector<grpc::string> &in, const grpc::string &prefix) {
std::ostringstream oss;
for (auto it = in.begin(); it != in.end(); it++) {
const grpc::string& elem = *it;
const grpc::string &elem = *it;
if (elem.empty()) {
oss << prefix << "\n";
} else if (elem[0] == ' ') {

@ -67,15 +67,15 @@ grpc::string ModuleAlias(const grpc::string filename) {
// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// message file foo/bar/baz.js
grpc::string GetJSMessageFilename(const grpc::string& filename) {
grpc::string GetJSMessageFilename(const grpc::string &filename) {
grpc::string name = filename;
return grpc_generator::StripProto(name) + "_pb.js";
}
// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
grpc::string GetRootPath(const grpc::string& from_filename,
const grpc::string& to_filename) {
grpc::string GetRootPath(const grpc::string &from_filename,
const grpc::string &to_filename) {
if (to_filename.find("google/protobuf") == 0) {
// Well-known types (.proto files in the google/protobuf directory) are
// assumed to come from the 'google-protobuf' npm package. We may want to
@ -96,21 +96,24 @@ grpc::string GetRootPath(const grpc::string& from_filename,
// Return the relative path to load to_file from the directory containing
// from_file, assuming that both paths are relative to the same directory
grpc::string GetRelativePath(const grpc::string& from_file,
const grpc::string& to_file) {
grpc::string GetRelativePath(const grpc::string &from_file,
const grpc::string &to_file) {
return GetRootPath(from_file, to_file) + to_file;
}
/* Finds all message types used in all services in the file, and returns them
* as a map of fully qualified message type name to message descriptor */
map<grpc::string, const Descriptor*> GetAllMessages(const FileDescriptor *file) {
map<grpc::string, const Descriptor*> message_types;
for (int service_num = 0; service_num < file->service_count(); service_num++) {
const ServiceDescriptor* service = file->service(service_num);
for (int method_num = 0; method_num < service->method_count(); method_num++) {
const MethodDescriptor* method = service->method(method_num);
const Descriptor* input_type = method->input_type();
const Descriptor* output_type = method->output_type();
map<grpc::string, const Descriptor *> GetAllMessages(
const FileDescriptor *file) {
map<grpc::string, const Descriptor *> message_types;
for (int service_num = 0; service_num < file->service_count();
service_num++) {
const ServiceDescriptor *service = file->service(service_num);
for (int method_num = 0; method_num < service->method_count();
method_num++) {
const MethodDescriptor *method = service->method(method_num);
const Descriptor *input_type = method->input_type();
const Descriptor *output_type = method->output_type();
message_types[input_type->name()] = input_type;
message_types[output_type->name()] = output_type;
}
@ -118,7 +121,7 @@ map<grpc::string, const Descriptor*> GetAllMessages(const FileDescriptor *file)
return message_types;
}
grpc::string MessageIdentifierName(const grpc::string& name) {
grpc::string MessageIdentifierName(const grpc::string &name) {
return grpc_generator::StringReplace(name, ".", "_");
}
@ -194,18 +197,18 @@ void PrintService(const ServiceDescriptor *service, Printer *out) {
out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
grpc::string method_name = grpc_generator::LowercaseFirstLetter(
service->method(i)->name());
grpc::string method_name =
grpc_generator::LowercaseFirstLetter(service->method(i)->name());
out->Print(GetNodeComments(service->method(i), true).c_str());
out->Print("$method_name$: ",
"method_name", method_name);
out->Print("$method_name$: ", "method_name", method_name);
PrintMethod(service->method(i), out);
out->Print(",\n");
out->Print(GetNodeComments(service->method(i), false).c_str());
}
out->Outdent();
out->Print("};\n\n");
out->Print(template_vars, "exports.$name$Client = "
out->Print(template_vars,
"exports.$name$Client = "
"grpc.makeGenericClientConstructor($name$Service);\n");
out->Print(GetNodeComments(service, false).c_str());
}
@ -213,27 +216,25 @@ void PrintService(const ServiceDescriptor *service, Printer *out) {
void PrintImports(const FileDescriptor *file, Printer *out) {
out->Print("var grpc = require('grpc');\n");
if (file->message_type_count() > 0) {
grpc::string file_path = GetRelativePath(file->name(),
GetJSMessageFilename(
file->name()));
out->Print("var $module_alias$ = require('$file_path$');\n",
"module_alias", ModuleAlias(file->name()),
"file_path", file_path);
grpc::string file_path =
GetRelativePath(file->name(), GetJSMessageFilename(file->name()));
out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
ModuleAlias(file->name()), "file_path", file_path);
}
for (int i = 0; i < file->dependency_count(); i++) {
grpc::string file_path = GetRelativePath(
file->name(), GetJSMessageFilename(file->dependency(i)->name()));
out->Print("var $module_alias$ = require('$file_path$');\n",
"module_alias", ModuleAlias(file->dependency(i)->name()),
"file_path", file_path);
out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
ModuleAlias(file->dependency(i)->name()), "file_path",
file_path);
}
out->Print("\n");
}
void PrintTransformers(const FileDescriptor *file, Printer *out) {
map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
for (std::map<grpc::string, const Descriptor*>::iterator it =
map<grpc::string, const Descriptor *> messages = GetAllMessages(file);
for (std::map<grpc::string, const Descriptor *>::iterator it =
messages.begin();
it != messages.end(); it++) {
PrintMessageTransformer(it->second, out);
@ -246,7 +247,6 @@ void PrintServices(const FileDescriptor *file, Printer *out) {
PrintService(file->service(i), out);
}
}
}
grpc::string GenerateFile(const FileDescriptor *file) {

@ -48,7 +48,7 @@ inline grpc::string GetJSServiceFilename(const grpc::string& filename) {
// Get leading or trailing comments in a string. Comment lines start with "// ".
// Leading detached comments are put in in front of leading comments.
template <typename DescriptorType>
inline grpc::string GetNodeComments(const DescriptorType *desc, bool leading) {
inline grpc::string GetNodeComments(const DescriptorType* desc, bool leading) {
return grpc_generator::GetPrefixedComments(desc, leading, "//");
}

@ -49,9 +49,9 @@ using ::std::map;
namespace grpc_objective_c_generator {
namespace {
void PrintProtoRpcDeclarationAsPragma(Printer *printer,
const MethodDescriptor *method,
map< ::grpc::string, ::grpc::string> vars) {
void PrintProtoRpcDeclarationAsPragma(
Printer *printer, const MethodDescriptor *method,
map< ::grpc::string, ::grpc::string> vars) {
vars["client_stream"] = method->client_streaming() ? "stream " : "";
vars["server_stream"] = method->server_streaming() ? "stream " : "";
@ -61,7 +61,7 @@ void PrintProtoRpcDeclarationAsPragma(Printer *printer,
}
template <typename DescriptorType>
static void PrintAllComments(const DescriptorType* desc, Printer* printer) {
static void PrintAllComments(const DescriptorType *desc, Printer *printer) {
std::vector<grpc::string> comments;
grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED,
&comments);
@ -100,7 +100,8 @@ void PrintMethodSignature(Printer *printer, const MethodDescriptor *method,
if (method->server_streaming()) {
printer->Print(vars,
" eventHandler:(void(^)(BOOL done, "
"$response_class$ *_Nullable response, NSError *_Nullable error))eventHandler");
"$response_class$ *_Nullable response, NSError *_Nullable "
"error))eventHandler");
} else {
printer->Print(vars,
" handler:(void(^)($response_class$ *_Nullable response, "
@ -123,7 +124,8 @@ void PrintAdvancedSignature(Printer *printer, const MethodDescriptor *method,
PrintMethodSignature(printer, method, vars);
}
inline map< ::grpc::string, ::grpc::string> GetMethodVars(const MethodDescriptor *method) {
inline map< ::grpc::string, ::grpc::string> GetMethodVars(
const MethodDescriptor *method) {
map< ::grpc::string, ::grpc::string> res;
res["method_name"] = method->name();
res["request_type"] = method->input_type()->name();
@ -210,7 +212,8 @@ void PrintMethodImplementations(Printer *printer,
grpc::protobuf::io::StringOutputStream output_stream(&output);
Printer printer(&output_stream, '$');
map< ::grpc::string, ::grpc::string> vars = {{"service_class", ServiceClassName(service)}};
map< ::grpc::string, ::grpc::string> vars = {
{"service_class", ServiceClassName(service)}};
printer.Print(vars, "@protocol $service_class$ <NSObject>\n\n");
@ -237,21 +240,23 @@ void PrintMethodImplementations(Printer *printer,
}
::grpc::string GetSource(const ServiceDescriptor *service) {
::grpc::string output;
::grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
grpc::protobuf::io::StringOutputStream output_stream(&output);
Printer printer(&output_stream, '$');
map< ::grpc::string,::grpc::string> vars = {{"service_name", service->name()},
{"service_class", ServiceClassName(service)},
{"package", service->file()->package()}};
map< ::grpc::string, ::grpc::string> vars = {
{"service_name", service->name()},
{"service_class", ServiceClassName(service)},
{"package", service->file()->package()}};
printer.Print(vars, "@implementation $service_class$\n\n");
printer.Print("// Designated initializer\n");
printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
printer.Print(vars,
printer.Print(
vars,
" return (self = [super initWithHost:host"
" packageName:@\"$package$\" serviceName:@\"$service_name$\"]);\n");
printer.Print("}\n\n");

@ -53,6 +53,5 @@ inline string ServiceClassName(const ServiceDescriptor *service) {
string prefix = file->options().objc_class_prefix();
return prefix + service->name();
}
}
#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H

@ -42,7 +42,8 @@
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
using ::google::protobuf::compiler::objectivec::ProtobufLibraryFrameworkName;
using ::google::protobuf::compiler::objectivec::IsProtobufLibraryBundledProtoFile;
using ::google::protobuf::compiler::objectivec::
IsProtobufLibraryBundledProtoFile;
class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
public:
@ -53,7 +54,6 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
const ::grpc::string &parameter,
grpc::protobuf::compiler::GeneratorContext *context,
::grpc::string *error) const {
if (file->service_count() == 0) {
// No services. Do nothing.
return true;
@ -66,29 +66,32 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
// Generate .pbrpc.h
::grpc::string imports = ::grpc::string("#import \"") + file_name +
".pbobjc.h\"\n\n"
"#import <ProtoRPC/ProtoService.h>\n"
"#import <RxLibrary/GRXWriteable.h>\n"
"#import <RxLibrary/GRXWriter.h>\n";
".pbobjc.h\"\n\n"
"#import <ProtoRPC/ProtoService.h>\n"
"#import <RxLibrary/GRXWriteable.h>\n"
"#import <RxLibrary/GRXWriter.h>\n";
// TODO(jcanizales): Instead forward-declare the input and output types
// and import the files in the .pbrpc.m
::grpc::string proto_imports;
for (int i = 0; i < file->dependency_count(); i++) {
::grpc::string header = grpc_objective_c_generator::MessageHeaderName(
file->dependency(i));
::grpc::string header =
grpc_objective_c_generator::MessageHeaderName(file->dependency(i));
const grpc::protobuf::FileDescriptor *dependency = file->dependency(i);
if (IsProtobufLibraryBundledProtoFile(dependency)) {
::grpc::string base_name = header;
grpc_generator::StripPrefix(&base_name, "google/protobuf/");
// create the import code snippet
proto_imports +=
"#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS\n"
" #import <" + ::grpc::string(ProtobufLibraryFrameworkName) +
"/" + base_name + ">\n"
"#else\n"
" #import \"" + header + "\"\n"
"#endif\n";
"#if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS\n"
" #import <" +
::grpc::string(ProtobufLibraryFrameworkName) + "/" + base_name +
">\n"
"#else\n"
" #import \"" +
header +
"\"\n"
"#endif\n";
} else {
proto_imports += ::grpc::string("#import \"") + header + "\"\n";
}
@ -100,21 +103,22 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
declarations += grpc_objective_c_generator::GetHeader(service);
}
static const ::grpc::string kNonNullBegin = "\nNS_ASSUME_NONNULL_BEGIN\n\n";
static const ::grpc::string kNonNullBegin =
"\nNS_ASSUME_NONNULL_BEGIN\n\n";
static const ::grpc::string kNonNullEnd = "\nNS_ASSUME_NONNULL_END\n";
Write(context, file_name + ".pbrpc.h",
imports + '\n' + proto_imports + '\n' + kNonNullBegin +
declarations + kNonNullEnd);
Write(context, file_name + ".pbrpc.h", imports + '\n' + proto_imports +
'\n' + kNonNullBegin +
declarations + kNonNullEnd);
}
{
// Generate .pbrpc.m
::grpc::string imports = ::grpc::string("#import \"") + file_name +
".pbrpc.h\"\n\n"
"#import <ProtoRPC/ProtoRPC.h>\n"
"#import <RxLibrary/GRXWriter+Immediate.h>\n";
".pbrpc.h\"\n\n"
"#import <ProtoRPC/ProtoRPC.h>\n"
"#import <RxLibrary/GRXWriter+Immediate.h>\n";
::grpc::string definitions;
for (int i = 0; i < file->service_count(); i++) {
@ -131,7 +135,7 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
private:
// Write the given code into the given file.
void Write(grpc::protobuf::compiler::GeneratorContext *context,
const ::grpc::string &filename, const ::grpc::string &code) const {
const ::grpc::string &filename, const ::grpc::string &code) const {
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
context->Open(filename));
grpc::protobuf::io::CodedOutputStream coded_out(output.get());

@ -74,16 +74,18 @@ PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config)
PythonGrpcGenerator::~PythonGrpcGenerator() {}
bool PythonGrpcGenerator::Generate(
const FileDescriptor* file, const grpc::string& parameter,
GeneratorContext* context, grpc::string* error) const {
bool PythonGrpcGenerator::Generate(const FileDescriptor* file,
const grpc::string& parameter,
GeneratorContext* context,
grpc::string* error) const {
// Get output file name.
grpc::string file_name;
static const int proto_suffix_length = strlen(".proto");
if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
file->name().find_last_of(".proto") == file->name().size() - 1) {
file_name = file->name().substr(
0, file->name().size() - proto_suffix_length) + "_pb2.py";
file_name =
file->name().substr(0, file->name().size() - proto_suffix_length) +
"_pb2.py";
} else {
*error = "Invalid proto file name. Proto file must end with .proto";
return false;
@ -115,7 +117,7 @@ map<grpc::string, grpc::string> ListToDict(
assert(values.size() % 2 == 0);
map<grpc::string, grpc::string> value_map;
auto value_iter = values.begin();
for (unsigned i = 0; i < values.size()/2; ++i) {
for (unsigned i = 0; i < values.size() / 2; ++i) {
grpc::string key = *value_iter;
++value_iter;
grpc::string value = *value_iter;
@ -138,9 +140,7 @@ class IndentScope {
printer_->Indent();
}
~IndentScope() {
printer_->Outdent();
}
~IndentScope() { printer_->Outdent(); }
private:
Printer* printer_;
@ -173,7 +173,6 @@ grpc::string ModuleAlias(const grpc::string& filename) {
return module_name;
}
bool GetModuleAndMessagePath(const Descriptor* type,
const ServiceDescriptor* service,
grpc::string* out) {
@ -182,7 +181,7 @@ bool GetModuleAndMessagePath(const Descriptor* type,
do {
message_path.push_back(path_elem_type);
path_elem_type = path_elem_type->containing_type();
} while (path_elem_type); // implicit nullptr comparison; don't be explicit
} while (path_elem_type); // implicit nullptr comparison; don't be explicit
grpc::string file_name = type->file()->name();
static const int proto_suffix_length = strlen(".proto");
if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&
@ -190,11 +189,11 @@ bool GetModuleAndMessagePath(const Descriptor* type,
return false;
}
grpc::string service_file_name = service->file()->name();
grpc::string module = service_file_name == file_name ?
"" : ModuleAlias(file_name) + ".";
grpc::string module =
service_file_name == file_name ? "" : ModuleAlias(file_name) + ".";
grpc::string message_type;
for (auto path_iter = message_path.rbegin();
path_iter != message_path.rend(); ++path_iter) {
for (auto path_iter = message_path.rbegin(); path_iter != message_path.rend();
++path_iter) {
message_type += (*path_iter)->name() + ".";
}
// no pop_back prior to C++11
@ -229,8 +228,7 @@ static void PrintAllComments(const DescriptorType* desc, Printer* printer) {
printer->Print("\"\"\"\n");
}
bool PrintBetaServicer(const ServiceDescriptor* service,
Printer* out) {
bool PrintBetaServicer(const ServiceDescriptor* service, Printer* out) {
out->Print("\n\n");
out->Print("class Beta$Service$Servicer(object):\n", "Service",
service->name());
@ -239,10 +237,10 @@ bool PrintBetaServicer(const ServiceDescriptor* service,
PrintAllComments(service, out);
for (int i = 0; i < service->method_count(); ++i) {
auto meth = service->method(i);
grpc::string arg_name = meth->client_streaming() ?
"request_iterator" : "request";
out->Print("def $Method$(self, $ArgName$, context):\n",
"Method", meth->name(), "ArgName", arg_name);
grpc::string arg_name =
meth->client_streaming() ? "request_iterator" : "request";
out->Print("def $Method$(self, $ArgName$, context):\n", "Method",
meth->name(), "ArgName", arg_name);
{
IndentScope raii_method_indent(out);
PrintAllComments(meth, out);
@ -253,8 +251,7 @@ bool PrintBetaServicer(const ServiceDescriptor* service,
return true;
}
bool PrintBetaStub(const ServiceDescriptor* service,
Printer* out) {
bool PrintBetaStub(const ServiceDescriptor* service, Printer* out) {
out->Print("\n\n");
out->Print("class Beta$Service$Stub(object):\n", "Service", service->name());
{
@ -262,10 +259,12 @@ bool PrintBetaStub(const ServiceDescriptor* service,
PrintAllComments(service, out);
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i);
grpc::string arg_name = meth->client_streaming() ?
"request_iterator" : "request";
grpc::string arg_name =
meth->client_streaming() ? "request_iterator" : "request";
auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
out->Print(methdict, "def $Method$(self, $ArgName$, timeout, metadata=None, with_call=False, protocol_options=None):\n");
out->Print(methdict,
"def $Method$(self, $ArgName$, timeout, metadata=None, "
"with_call=False, protocol_options=None):\n");
{
IndentScope raii_method_indent(out);
PrintAllComments(meth, out);
@ -282,9 +281,10 @@ bool PrintBetaStub(const ServiceDescriptor* service,
bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) {
out->Print("\n\n");
out->Print("def beta_create_$Service$_server(servicer, pool=None, "
"pool_size=None, default_timeout=None, maximum_timeout=None):\n",
"Service", service->name());
out->Print(
"def beta_create_$Service$_server(servicer, pool=None, "
"pool_size=None, default_timeout=None, maximum_timeout=None):\n",
"Service", service->name());
{
IndentScope raii_create_server_indent(out);
map<grpc::string, grpc::string> method_implementation_constructors;
@ -315,58 +315,62 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
}
out->Print("request_deserializers = {\n");
for (auto name_and_input_module_class_pair =
input_message_modules_and_classes.begin();
input_message_modules_and_classes.begin();
name_and_input_module_class_pair !=
input_message_modules_and_classes.end();
input_message_modules_and_classes.end();
name_and_input_module_class_pair++) {
IndentScope raii_indent(out);
out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$InputTypeModuleAndClass$.FromString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_input_module_class_pair->first,
"InputTypeModuleAndClass",
name_and_input_module_class_pair->second);
out->Print(
"(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$InputTypeModuleAndClass$.FromString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_input_module_class_pair->first,
"InputTypeModuleAndClass", name_and_input_module_class_pair->second);
}
out->Print("}\n");
out->Print("response_serializers = {\n");
for (auto name_and_output_module_class_pair =
output_message_modules_and_classes.begin();
output_message_modules_and_classes.begin();
name_and_output_module_class_pair !=
output_message_modules_and_classes.end();
output_message_modules_and_classes.end();
name_and_output_module_class_pair++) {
IndentScope raii_indent(out);
out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$OutputTypeModuleAndClass$.SerializeToString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_output_module_class_pair->first,
"OutputTypeModuleAndClass",
name_and_output_module_class_pair->second);
out->Print(
"(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$OutputTypeModuleAndClass$.SerializeToString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_output_module_class_pair->first,
"OutputTypeModuleAndClass",
name_and_output_module_class_pair->second);
}
out->Print("}\n");
out->Print("method_implementations = {\n");
for (auto name_and_implementation_constructor =
method_implementation_constructors.begin();
name_and_implementation_constructor !=
method_implementation_constructors.end();
name_and_implementation_constructor++) {
method_implementation_constructors.begin();
name_and_implementation_constructor !=
method_implementation_constructors.end();
name_and_implementation_constructor++) {
IndentScope raii_descriptions_indent(out);
const grpc::string method_name =
name_and_implementation_constructor->first;
out->Print("(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
"face_utilities.$Constructor$(servicer.$Method$),\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"Method", name_and_implementation_constructor->first,
"Constructor", name_and_implementation_constructor->second);
out->Print(
"(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
"face_utilities.$Constructor$(servicer.$Method$),\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"Method", name_and_implementation_constructor->first, "Constructor",
name_and_implementation_constructor->second);
}
out->Print("}\n");
out->Print("server_options = beta_implementations.server_options("
"request_deserializers=request_deserializers, "
"response_serializers=response_serializers, "
"thread_pool=pool, thread_pool_size=pool_size, "
"default_timeout=default_timeout, "
"maximum_timeout=maximum_timeout)\n");
out->Print("return beta_implementations.server(method_implementations, "
"options=server_options)\n");
out->Print(
"server_options = beta_implementations.server_options("
"request_deserializers=request_deserializers, "
"response_serializers=response_serializers, "
"thread_pool=pool, thread_pool_size=pool_size, "
"default_timeout=default_timeout, "
"maximum_timeout=maximum_timeout)\n");
out->Print(
"return beta_implementations.server(method_implementations, "
"options=server_options)\n");
}
return true;
}
@ -374,10 +378,11 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) {
map<grpc::string, grpc::string> dict = ListToDict({
"Service", service->name(),
});
"Service", service->name(),
});
out->Print("\n\n");
out->Print(dict, "def beta_create_$Service$_stub(channel, host=None,"
out->Print(dict,
"def beta_create_$Service$_stub(channel, host=None,"
" metadata_transformer=None, pool=None, pool_size=None):\n");
{
IndentScope raii_create_server_indent(out);
@ -387,8 +392,7 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i);
const grpc::string method_cardinality =
grpc::string(method->client_streaming() ? "STREAM" : "UNARY") +
"_" +
grpc::string(method->client_streaming() ? "STREAM" : "UNARY") + "_" +
grpc::string(method->server_streaming() ? "STREAM" : "UNARY");
grpc::string input_message_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service,
@ -409,32 +413,33 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
}
out->Print("request_serializers = {\n");
for (auto name_and_input_module_class_pair =
input_message_modules_and_classes.begin();
input_message_modules_and_classes.begin();
name_and_input_module_class_pair !=
input_message_modules_and_classes.end();
input_message_modules_and_classes.end();
name_and_input_module_class_pair++) {
IndentScope raii_indent(out);
out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$InputTypeModuleAndClass$.SerializeToString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_input_module_class_pair->first,
"InputTypeModuleAndClass",
name_and_input_module_class_pair->second);
out->Print(
"(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$InputTypeModuleAndClass$.SerializeToString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_input_module_class_pair->first,
"InputTypeModuleAndClass", name_and_input_module_class_pair->second);
}
out->Print("}\n");
out->Print("response_deserializers = {\n");
for (auto name_and_output_module_class_pair =
output_message_modules_and_classes.begin();
output_message_modules_and_classes.begin();
name_and_output_module_class_pair !=
output_message_modules_and_classes.end();
output_message_modules_and_classes.end();
name_and_output_module_class_pair++) {
IndentScope raii_indent(out);
out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$OutputTypeModuleAndClass$.FromString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_output_module_class_pair->first,
"OutputTypeModuleAndClass",
name_and_output_module_class_pair->second);
out->Print(
"(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
"$OutputTypeModuleAndClass$.FromString,\n",
"PackageQualifiedServiceName", package_qualified_service_name,
"MethodName", name_and_output_module_class_pair->first,
"OutputTypeModuleAndClass",
name_and_output_module_class_pair->second);
}
out->Print("}\n");
out->Print("cardinalities = {\n");
@ -443,17 +448,19 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
name_and_cardinality++) {
IndentScope raii_descriptions_indent(out);
out->Print("\'$Method$\': cardinality.Cardinality.$Cardinality$,\n",
"Method", name_and_cardinality->first,
"Cardinality", name_and_cardinality->second);
"Method", name_and_cardinality->first, "Cardinality",
name_and_cardinality->second);
}
out->Print("}\n");
out->Print("stub_options = beta_implementations.stub_options("
"host=host, metadata_transformer=metadata_transformer, "
"request_serializers=request_serializers, "
"response_deserializers=response_deserializers, "
"thread_pool=pool, thread_pool_size=pool_size)\n");
out->Print(
"return beta_implementations.dynamic_stub(channel, \'$PackageQualifiedServiceName$\', "
"stub_options = beta_implementations.stub_options("
"host=host, metadata_transformer=metadata_transformer, "
"request_serializers=request_serializers, "
"response_deserializers=response_deserializers, "
"thread_pool=pool, thread_pool_size=pool_size)\n");
out->Print(
"return beta_implementations.dynamic_stub(channel, "
"\'$PackageQualifiedServiceName$\', "
"cardinalities, options=stub_options)\n",
"PackageQualifiedServiceName", package_qualified_service_name);
}
@ -476,43 +483,41 @@ bool PrintStub(const grpc::string& package_qualified_service_name,
out->Print("Args:\n");
{
IndentScope raii_args_indent(out);
out->Print("channel: A grpc.Channel.\n");
out->Print("channel: A grpc.Channel.\n");
}
out->Print("\"\"\"\n");
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
auto multi_callable_constructor =
grpc::string(method->client_streaming() ? "stream" : "unary") +
"_" +
grpc::string(method->server_streaming() ? "stream" : "unary");
grpc::string request_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service,
&request_module_and_class)) {
return false;
}
grpc::string response_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service,
&response_module_and_class)) {
auto multi_callable_constructor =
grpc::string(method->client_streaming() ? "stream" : "unary") +
"_" + grpc::string(method->server_streaming() ? "stream" : "unary");
grpc::string request_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service,
&request_module_and_class)) {
return false;
}
grpc::string response_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service,
&response_module_and_class)) {
return false;
}
out->Print("self.$Method$ = channel.$MultiCallableConstructor$(\n",
"Method", method->name(),
"MultiCallableConstructor", multi_callable_constructor);
{
}
out->Print("self.$Method$ = channel.$MultiCallableConstructor$(\n",
"Method", method->name(), "MultiCallableConstructor",
multi_callable_constructor);
{
IndentScope raii_first_attribute_indent(out);
IndentScope raii_second_attribute_indent(out);
out->Print(
"'/$PackageQualifiedService$/$Method$',\n",
"PackageQualifiedService", package_qualified_service_name,
"Method", method->name());
out->Print(
"request_serializer=$RequestModuleAndClass$.SerializeToString,\n",
"RequestModuleAndClass", request_module_and_class);
out->Print(
out->Print("'/$PackageQualifiedService$/$Method$',\n",
"PackageQualifiedService", package_qualified_service_name,
"Method", method->name());
out->Print(
"request_serializer=$RequestModuleAndClass$.SerializeToString,\n",
"RequestModuleAndClass", request_module_and_class);
out->Print(
"response_deserializer=$ResponseModuleAndClass$.FromString,\n",
"ResponseModuleAndClass", response_module_and_class);
out->Print(")\n");
}
"ResponseModuleAndClass", response_module_and_class);
out->Print(")\n");
}
}
}
}
@ -527,11 +532,11 @@ bool PrintServicer(const ServiceDescriptor* service, Printer* out) {
PrintAllComments(service, out);
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
grpc::string arg_name = method->client_streaming() ?
"request_iterator" : "request";
grpc::string arg_name =
method->client_streaming() ? "request_iterator" : "request";
out->Print("\n");
out->Print("def $Method$(self, $ArgName$, context):\n",
"Method", method->name(), "ArgName", arg_name);
out->Print("def $Method$(self, $ArgName$, context):\n", "Method",
method->name(), "ArgName", arg_name);
{
IndentScope raii_method_indent(out);
PrintAllComments(method, out);
@ -544,11 +549,12 @@ bool PrintServicer(const ServiceDescriptor* service, Printer* out) {
return true;
}
bool PrintAddServicerToServer(const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) {
bool PrintAddServicerToServer(
const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) {
out->Print("\n\n");
out->Print("def add_$Service$Servicer_to_server(servicer, server):\n",
"Service", service->name());
"Service", service->name());
{
IndentScope raii_class_indent(out);
out->Print("rpc_method_handlers = {\n");
@ -557,34 +563,37 @@ bool PrintAddServicerToServer(const grpc::string& package_qualified_service_name
IndentScope raii_dict_second_indent(out);
for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i);
auto method_handler_constructor =
auto method_handler_constructor =
grpc::string(method->client_streaming() ? "stream" : "unary") +
"_" +
"_" +
grpc::string(method->server_streaming() ? "stream" : "unary") +
"_rpc_method_handler";
grpc::string request_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service,
&request_module_and_class)) {
return false;
}
grpc::string response_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service,
&response_module_and_class)) {
grpc::string request_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service,
&request_module_and_class)) {
return false;
}
out->Print("'$Method$': grpc.$MethodHandlerConstructor$(\n",
"Method", method->name(),
"MethodHandlerConstructor", method_handler_constructor);
{
}
grpc::string response_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service,
&response_module_and_class)) {
return false;
}
out->Print("'$Method$': grpc.$MethodHandlerConstructor$(\n", "Method",
method->name(), "MethodHandlerConstructor",
method_handler_constructor);
{
IndentScope raii_call_first_indent(out);
IndentScope raii_call_second_indent(out);
out->Print("servicer.$Method$,\n", "Method", method->name());
out->Print("request_deserializer=$RequestModuleAndClass$.FromString,\n",
"RequestModuleAndClass", request_module_and_class);
out->Print("response_serializer=$ResponseModuleAndClass$.SerializeToString,\n",
"ResponseModuleAndClass", response_module_and_class);
}
out->Print("),\n");
IndentScope raii_call_second_indent(out);
out->Print("servicer.$Method$,\n", "Method", method->name());
out->Print(
"request_deserializer=$RequestModuleAndClass$.FromString,\n",
"RequestModuleAndClass", request_module_and_class);
out->Print(
"response_serializer=$ResponseModuleAndClass$.SerializeToString,"
"\n",
"ResponseModuleAndClass", response_module_and_class);
}
out->Print("),\n");
}
}
out->Print("}\n");
@ -593,7 +602,7 @@ bool PrintAddServicerToServer(const grpc::string& package_qualified_service_name
IndentScope raii_call_first_indent(out);
IndentScope raii_call_second_indent(out);
out->Print("'$PackageQualifiedServiceName$', rpc_method_handlers)\n",
"PackageQualifiedServiceName", package_qualified_service_name);
"PackageQualifiedServiceName", package_qualified_service_name);
}
out->Print("server.add_generic_rpc_handlers((generic_handler,))\n");
}
@ -605,10 +614,12 @@ bool PrintPreamble(const FileDescriptor* file,
out->Print("import $Package$\n", "Package", config.grpc_package_root);
out->Print("from $Package$ import implementations as beta_implementations\n",
"Package", config.beta_package_root);
out->Print("from $Package$ import interfaces as beta_interfaces\n",
"Package", config.beta_package_root);
out->Print("from $Package$ import interfaces as beta_interfaces\n", "Package",
config.beta_package_root);
out->Print("from grpc.framework.common import cardinality\n");
out->Print("from grpc.framework.interfaces.face import utilities as face_utilities\n");
out->Print(
"from grpc.framework.interfaces.face import utilities as "
"face_utilities\n");
return true;
}
@ -632,12 +643,14 @@ pair<bool, grpc::string> GetServices(const FileDescriptor* file,
auto service = file->service(i);
auto package_qualified_service_name = package + service->name();
if (!(PrintStub(package_qualified_service_name, service, &out) &&
PrintServicer(service, &out) &&
PrintAddServicerToServer(package_qualified_service_name, service, &out) &&
PrintBetaServicer(service, &out) &&
PrintBetaStub(service, &out) &&
PrintBetaServerFactory(package_qualified_service_name, service, &out) &&
PrintBetaStubFactory(package_qualified_service_name, service, &out))) {
PrintServicer(service, &out) &&
PrintAddServicerToServer(package_qualified_service_name, service,
&out) &&
PrintBetaServicer(service, &out) && PrintBetaStub(service, &out) &&
PrintBetaServerFactory(package_qualified_service_name, service,
&out) &&
PrintBetaStubFactory(package_qualified_service_name, service,
&out))) {
return make_pair(false, "");
}
}

@ -57,6 +57,7 @@ class PythonGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
const grpc::string& parameter,
grpc::protobuf::compiler::GeneratorContext* context,
grpc::string* error) const;
private:
GeneratorConfiguration config_;
};

@ -55,17 +55,20 @@ namespace {
// Prints out the method using the ruby gRPC DSL.
void PrintMethod(const MethodDescriptor *method, const grpc::string &package,
Printer *out) {
grpc::string input_type = RubyTypeOf(method->input_type()->full_name(), package);
grpc::string input_type =
RubyTypeOf(method->input_type()->full_name(), package);
if (method->client_streaming()) {
input_type = "stream(" + input_type + ")";
}
grpc::string output_type = RubyTypeOf(method->output_type()->full_name(), package);
grpc::string output_type =
RubyTypeOf(method->output_type()->full_name(), package);
if (method->server_streaming()) {
output_type = "stream(" + output_type + ")";
}
std::map<grpc::string, grpc::string> method_vars =
ListToDict({"mth.name", method->name(), "input.type", input_type,
"output.type", output_type, });
std::map<grpc::string, grpc::string> method_vars = ListToDict({
"mth.name", method->name(), "input.type", input_type, "output.type",
output_type,
});
out->Print(GetRubyComments(method, true).c_str());
out->Print(method_vars, "rpc :$mth.name$, $input.type$, $output.type$\n");
out->Print(GetRubyComments(method, false).c_str());
@ -79,8 +82,9 @@ void PrintService(const ServiceDescriptor *service, const grpc::string &package,
}
// Begin the service module
std::map<grpc::string, grpc::string> module_vars =
ListToDict({"module.name", CapitalizeFirst(service->name()), });
std::map<grpc::string, grpc::string> module_vars = ListToDict({
"module.name", CapitalizeFirst(service->name()),
});
out->Print(module_vars, "module $module.name$\n");
out->Indent();
@ -130,8 +134,9 @@ grpc::string GetServices(const FileDescriptor *file) {
}
// Write out a file header.
std::map<grpc::string, grpc::string> header_comment_vars = ListToDict(
{"file.name", file->name(), "file.package", file->package(), });
std::map<grpc::string, grpc::string> header_comment_vars = ListToDict({
"file.name", file->name(), "file.package", file->package(),
});
out.Print("# Generated by the protocol buffer compiler. DO NOT EDIT!\n");
out.Print(header_comment_vars,
"# Source: $file.name$ for package '$file.package$'\n");
@ -147,16 +152,18 @@ grpc::string GetServices(const FileDescriptor *file) {
// Write out require statemment to import the separately generated file
// that defines the messages used by the service. This is generated by the
// main ruby plugin.
std::map<grpc::string, grpc::string> dep_vars =
ListToDict({"dep.name", MessagesRequireName(file), });
std::map<grpc::string, grpc::string> dep_vars = ListToDict({
"dep.name", MessagesRequireName(file),
});
out.Print(dep_vars, "require '$dep.name$'\n");
// Write out services within the modules
out.Print("\n");
std::vector<grpc::string> modules = Split(file->package(), '.');
for (size_t i = 0; i < modules.size(); ++i) {
std::map<grpc::string, grpc::string> module_vars =
ListToDict({"module.name", CapitalizeFirst(modules[i]), });
std::map<grpc::string, grpc::string> module_vars = ListToDict({
"module.name", CapitalizeFirst(modules[i]),
});
out.Print(module_vars, "module $module.name$\n");
out.Indent();
}

@ -48,7 +48,7 @@ inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file,
file->name().find_last_of(".proto") == file->name().size() - 1) {
*file_name_or_error =
file->name().substr(0, file->name().size() - proto_suffix_length) +
"_services.rb";
"_services_pb.rb";
return true;
} else {
*file_name_or_error = "Invalid proto file name: must end with .proto";
@ -58,7 +58,7 @@ inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file,
inline grpc::string MessagesRequireName(
const grpc::protobuf::FileDescriptor *file) {
return Replace(file->name(), ".proto", "");
return Replace(file->name(), ".proto", "_pb");
}
// Get leading or trailing comments in a string. Comment lines start with "# ".

@ -36,8 +36,8 @@
#include "src/compiler/config.h"
#include <iostream>
#include <initializer_list>
#include <iostream>
#include <map>
#include <ostream> // NOLINT
#include <vector>
@ -53,8 +53,7 @@ namespace grpc_ruby_generator {
inline std::map<grpc::string, grpc::string> ListToDict(
const initializer_list<grpc::string> &values) {
if (values.size() % 2 != 0) {
std::cerr << "Not every 'key' has a value in `values`."
<< std::endl;
std::cerr << "Not every 'key' has a value in `values`." << std::endl;
}
std::map<grpc::string, grpc::string> value_map;
auto value_iter = values.begin();

@ -59,7 +59,7 @@ grpc_connectivity_state grpc_channel_check_connectivity_state(
}
gpr_log(GPR_ERROR,
"grpc_channel_check_connectivity_state called on something that is "
"not a (u)client channel, but '%s'",
"not a client channel, but '%s'",
client_channel_elem->filter->name);
grpc_exec_ctx_finish(&exec_ctx);
return GRPC_CHANNEL_SHUTDOWN;

@ -45,6 +45,7 @@
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/compress_filter.h"
#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/channel/http_client_filter.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/surface/api_trace.h"
@ -63,6 +64,8 @@ typedef struct {
grpc_endpoint *tcp;
grpc_closure connected;
grpc_handshake_manager *handshake_mgr;
} connector;
static void connector_ref(grpc_connector *con) {
@ -74,6 +77,7 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
connector *c = (connector *)con;
if (gpr_unref(&c->refs)) {
/* c->initial_string_buffer does not need to be destroyed */
grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr);
gpr_free(c);
}
}
@ -83,9 +87,22 @@ static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
connector_unref(exec_ctx, arg);
}
static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint,
grpc_channel_args *args, void *user_data,
grpc_error *error) {
connector *c = user_data;
c->result->transport =
grpc_create_chttp2_transport(exec_ctx, args, endpoint, 1);
GPR_ASSERT(c->result->transport);
grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, 0);
c->result->channel_args = args;
grpc_closure *notify = c->notify;
c->notify = NULL;
grpc_exec_ctx_sched(exec_ctx, notify, error, NULL);
}
static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
connector *c = arg;
grpc_closure *notify;
grpc_endpoint *tcp = c->tcp;
if (tcp != NULL) {
if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
@ -97,19 +114,17 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
connector_ref(arg);
grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
&c->initial_string_sent);
} else {
grpc_handshake_manager_do_handshake(
exec_ctx, c->handshake_mgr, tcp, c->args.channel_args,
c->args.deadline, NULL /* acceptor */, on_handshake_done, c);
}
c->result->transport =
grpc_create_chttp2_transport(exec_ctx, c->args.channel_args, tcp, 1);
grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
0);
GPR_ASSERT(c->result->transport);
c->result->channel_args = grpc_channel_args_copy(c->args.channel_args);
} else {
memset(c->result, 0, sizeof(*c->result));
grpc_closure *notify = c->notify;
c->notify = NULL;
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
}
notify = c->notify;
c->notify = NULL;
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
}
static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {}
@ -171,6 +186,7 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
memset(c, 0, sizeof(*c));
c->base.vtable = &connector_vtable;
gpr_ref_init(&c->refs, 1);
c->handshake_mgr = grpc_handshake_manager_create();
args->args = final_args;
s = grpc_subchannel_create(exec_ctx, &c->base, args);
grpc_connector_unref(exec_ctx, &c->base);

@ -44,6 +44,7 @@
#include "src/core/ext/client_config/resolver_registry.h"
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"
@ -69,6 +70,11 @@ typedef struct {
grpc_endpoint *newly_connecting_endpoint;
grpc_closure connected_closure;
grpc_handshake_manager *handshake_mgr;
// TODO(roth): Remove once we eliminate on_secure_handshake_done().
grpc_channel_args *tmp_args;
} connector;
static void connector_ref(grpc_connector *con) {
@ -80,6 +86,8 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
connector *c = (connector *)con;
if (gpr_unref(&c->refs)) {
/* c->initial_string_buffer does not need to be destroyed */
grpc_channel_args_destroy(c->tmp_args);
grpc_handshake_manager_destroy(exec_ctx, c->handshake_mgr);
gpr_free(c);
}
}
@ -89,13 +97,14 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *secure_endpoint,
grpc_auth_context *auth_context) {
connector *c = arg;
grpc_closure *notify;
gpr_mu_lock(&c->mu);
grpc_error *error = GRPC_ERROR_NONE;
if (c->connecting_endpoint == NULL) {
memset(c->result, 0, sizeof(*c->result));
gpr_mu_unlock(&c->mu);
} else if (status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, "Secure handshake failed with error %d.", status);
error = grpc_error_set_int(GRPC_ERROR_CREATE("Secure handshake failed"),
GRPC_ERROR_INT_SECURITY_STATUS, status);
memset(c->result, 0, sizeof(*c->result));
c->connecting_endpoint = NULL;
gpr_mu_unlock(&c->mu);
@ -108,25 +117,43 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
0);
auth_context_arg = grpc_auth_context_to_arg(auth_context);
c->result->channel_args = grpc_channel_args_copy_and_add(
c->args.channel_args, &auth_context_arg, 1);
c->result->channel_args =
grpc_channel_args_copy_and_add(c->tmp_args, &auth_context_arg, 1);
}
notify = c->notify;
grpc_closure *notify = c->notify;
c->notify = NULL;
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_NONE, NULL);
grpc_exec_ctx_sched(exec_ctx, notify, error, NULL);
}
static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint,
grpc_channel_args *args, void *user_data,
grpc_error *error) {
connector *c = user_data;
if (error != GRPC_ERROR_NONE) {
grpc_closure *notify = c->notify;
c->notify = NULL;
grpc_exec_ctx_sched(exec_ctx, notify, error, NULL);
} else {
// TODO(roth, jboeuf): Convert security connector handshaking to use new
// handshake API, and then move the code from on_secure_handshake_done()
// into this function.
c->tmp_args = args;
grpc_channel_security_connector_do_handshake(
exec_ctx, c->security_connector, endpoint, c->args.deadline,
on_secure_handshake_done, c);
}
}
static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
connector *c = arg;
grpc_channel_security_connector_do_handshake(
exec_ctx, c->security_connector, c->connecting_endpoint, c->args.deadline,
on_secure_handshake_done, c);
grpc_handshake_manager_do_handshake(
exec_ctx, c->handshake_mgr, c->connecting_endpoint, c->args.channel_args,
c->args.deadline, NULL /* acceptor */, on_handshake_done, c);
}
static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
connector *c = arg;
grpc_closure *notify;
grpc_endpoint *tcp = c->newly_connecting_endpoint;
if (tcp != NULL) {
gpr_mu_lock(&c->mu);
@ -142,13 +169,13 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
&c->initial_string_sent);
} else {
grpc_channel_security_connector_do_handshake(
exec_ctx, c->security_connector, tcp, c->args.deadline,
on_secure_handshake_done, c);
grpc_handshake_manager_do_handshake(
exec_ctx, c->handshake_mgr, tcp, c->args.channel_args,
c->args.deadline, NULL /* acceptor */, on_handshake_done, c);
}
} else {
memset(c->result, 0, sizeof(*c->result));
notify = c->notify;
grpc_closure *notify = c->notify;
c->notify = NULL;
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL);
}
@ -227,6 +254,7 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
memset(c, 0, sizeof(*c));
c->base.vtable = &connector_vtable;
c->security_connector = f->security_connector;
c->handshake_mgr = grpc_handshake_manager_create();
gpr_mu_init(&c->mu);
gpr_ref_init(&c->refs, 1);
args->args = final_args;

@ -37,35 +37,74 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/channel/http_server_filter.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/tcp_server.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/server.h"
static void new_transport(grpc_exec_ctx *exec_ctx, void *server,
grpc_endpoint *tcp, grpc_pollset *accepting_pollset,
grpc_tcp_server_acceptor *acceptor) {
/*
* Beware that the call to grpc_create_chttp2_transport() has to happen before
* grpc_tcp_server_destroy(). This is fine here, but similar code
* asynchronously doing a handshake instead of calling grpc_tcp_server_start()
* (as in server_secure_chttp2.c) needs to add synchronization to avoid this
* case.
*/
grpc_transport *transport = grpc_create_chttp2_transport(
exec_ctx, grpc_server_get_channel_args(server), tcp, 0);
grpc_server_setup_transport(exec_ctx, server, transport, accepting_pollset,
grpc_server_get_channel_args(server));
grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
typedef struct server_connect_state {
grpc_server *server;
grpc_pollset *accepting_pollset;
grpc_tcp_server_acceptor *acceptor;
grpc_handshake_manager *handshake_mgr;
} server_connect_state;
static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint,
grpc_channel_args *args, void *user_data,
grpc_error *error) {
server_connect_state *state = user_data;
if (error != GRPC_ERROR_NONE) {
const char *error_str = grpc_error_string(error);
gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
grpc_error_free_string(error_str);
GRPC_ERROR_UNREF(error);
grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr);
} else {
// Beware that the call to grpc_create_chttp2_transport() has to happen
// before grpc_tcp_server_destroy(). This is fine here, but similar code
// asynchronously doing a handshake instead of calling
// grpc_tcp_server_start() (as in server_secure_chttp2.c) needs to add
// synchronization to avoid this case.
grpc_transport *transport =
grpc_create_chttp2_transport(exec_ctx, args, endpoint, 0);
grpc_server_setup_transport(exec_ctx, state->server, transport,
state->accepting_pollset,
grpc_server_get_channel_args(state->server));
grpc_chttp2_transport_start_reading(exec_ctx, transport, NULL, 0);
}
// Clean up.
grpc_channel_args_destroy(args);
grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr);
gpr_free(state);
}
static void on_accept(grpc_exec_ctx *exec_ctx, void *server, grpc_endpoint *tcp,
grpc_pollset *accepting_pollset,
grpc_tcp_server_acceptor *acceptor) {
server_connect_state *state = gpr_malloc(sizeof(server_connect_state));
state->server = server;
state->accepting_pollset = accepting_pollset;
state->acceptor = acceptor;
state->handshake_mgr = grpc_handshake_manager_create();
// TODO(roth): We should really get this timeout value from channel
// args instead of hard-coding it.
const gpr_timespec deadline = gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(120, GPR_TIMESPAN));
grpc_handshake_manager_do_handshake(
exec_ctx, state->handshake_mgr, tcp, grpc_server_get_channel_args(server),
deadline, acceptor, on_handshake_done, state);
}
/* Server callback: start listening on our ports */
static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
grpc_pollset **pollsets, size_t pollset_count) {
grpc_tcp_server *tcp = tcpp;
grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, new_transport,
grpc_tcp_server_start(exec_ctx, tcp, pollsets, pollset_count, on_accept,
server);
}
@ -74,6 +113,7 @@ static void start(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *tcpp,
grpc_closure *destroy_done) {
grpc_tcp_server *tcp = tcpp;
grpc_tcp_server_shutdown_listeners(exec_ctx, tcp);
grpc_tcp_server_unref(exec_ctx, tcp);
grpc_exec_ctx_sched(exec_ctx, destroy_done, GRPC_ERROR_NONE, NULL);
}

@ -42,6 +42,7 @@
#include <grpc/support/useful.h>
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/channel/http_server_filter.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/resolve_address.h"
@ -58,7 +59,7 @@ typedef struct server_secure_state {
grpc_tcp_server *tcp;
grpc_server_security_connector *sc;
grpc_server_credentials *creds;
int is_shutdown;
bool is_shutdown;
gpr_mu mu;
gpr_refcount refcount;
grpc_closure destroy_closure;
@ -68,6 +69,12 @@ typedef struct server_secure_state {
typedef struct server_secure_connect {
server_secure_state *state;
grpc_pollset *accepting_pollset;
grpc_tcp_server_acceptor *acceptor;
grpc_handshake_manager *handshake_mgr;
// TODO(roth): Remove the following two fields when we eliminate
// grpc_server_security_connector_do_handshake().
gpr_timespec deadline;
grpc_channel_args *args;
} server_secure_connect;
static void state_ref(server_secure_state *state) { gpr_ref(&state->refcount); }
@ -89,21 +96,18 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
grpc_endpoint *secure_endpoint,
grpc_auth_context *auth_context) {
server_secure_connect *state = statep;
grpc_transport *transport;
if (status == GRPC_SECURITY_OK) {
if (secure_endpoint) {
gpr_mu_lock(&state->state->mu);
if (!state->state->is_shutdown) {
transport = grpc_create_chttp2_transport(
grpc_transport *transport = grpc_create_chttp2_transport(
exec_ctx, grpc_server_get_channel_args(state->state->server),
secure_endpoint, 0);
grpc_channel_args *args_copy;
grpc_arg args_to_add[2];
args_to_add[0] = grpc_server_credentials_to_arg(state->state->creds);
args_to_add[1] = grpc_auth_context_to_arg(auth_context);
args_copy = grpc_channel_args_copy_and_add(
grpc_server_get_channel_args(state->state->server), args_to_add,
GPR_ARRAY_SIZE(args_to_add));
grpc_channel_args *args_copy = grpc_channel_args_copy_and_add(
state->args, args_to_add, GPR_ARRAY_SIZE(args_to_add));
grpc_server_setup_transport(exec_ctx, state->state->server, transport,
state->accepting_pollset, args_copy);
grpc_channel_args_destroy(args_copy);
@ -118,10 +122,38 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *statep,
} else {
gpr_log(GPR_ERROR, "Secure transport failed with error %d", status);
}
grpc_channel_args_destroy(state->args);
state_unref(state->state);
gpr_free(state);
}
static void on_handshake_done(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint,
grpc_channel_args *args, void *user_data,
grpc_error *error) {
server_secure_connect *state = user_data;
if (error != GRPC_ERROR_NONE) {
const char *error_str = grpc_error_string(error);
gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
grpc_error_free_string(error_str);
GRPC_ERROR_UNREF(error);
grpc_handshake_manager_shutdown(exec_ctx, state->handshake_mgr);
grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr);
grpc_channel_args_destroy(args);
state_unref(state->state);
gpr_free(state);
return;
}
grpc_handshake_manager_destroy(exec_ctx, state->handshake_mgr);
state->handshake_mgr = NULL;
// TODO(roth, jboeuf): Convert security connector handshaking to use new
// handshake API, and then move the code from on_secure_handshake_done()
// into this function.
state->args = args;
grpc_server_security_connector_do_handshake(
exec_ctx, state->state->sc, state->acceptor, endpoint, state->deadline,
on_secure_handshake_done, state);
}
static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
grpc_pollset *accepting_pollset,
grpc_tcp_server_acceptor *acceptor) {
@ -129,11 +161,16 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *statep, grpc_endpoint *tcp,
state->state = statep;
state_ref(state->state);
state->accepting_pollset = accepting_pollset;
grpc_server_security_connector_do_handshake(
exec_ctx, state->state->sc, acceptor, tcp,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(120, GPR_TIMESPAN)),
on_secure_handshake_done, state);
state->acceptor = acceptor;
state->handshake_mgr = grpc_handshake_manager_create();
// TODO(roth): We should really get this timeout value from channel
// args instead of hard-coding it.
state->deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(120, GPR_TIMESPAN));
grpc_handshake_manager_do_handshake(
exec_ctx, state->handshake_mgr, tcp,
grpc_server_get_channel_args(state->state->server), state->deadline,
acceptor, on_handshake_done, state);
}
/* Server callback: start listening on our ports */
@ -162,10 +199,11 @@ static void destroy(grpc_exec_ctx *exec_ctx, grpc_server *server, void *statep,
server_secure_state *state = statep;
grpc_tcp_server *tcp;
gpr_mu_lock(&state->mu);
state->is_shutdown = 1;
state->is_shutdown = true;
state->destroy_callback = callback;
tcp = state->tcp;
gpr_mu_unlock(&state->mu);
grpc_tcp_server_shutdown_listeners(exec_ctx, tcp);
grpc_tcp_server_unref(exec_ctx, tcp);
}
@ -226,7 +264,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
state->tcp = tcp;
state->sc = sc;
state->creds = grpc_server_credentials_ref(creds);
state->is_shutdown = 0;
state->is_shutdown = false;
gpr_mu_init(&state->mu);
gpr_ref_init(&state->refcount, 1);

@ -36,11 +36,14 @@
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/transport/metadata.h"
extern int grpc_http_write_state_trace;
void grpc_chttp2_plugin_init(void) {
grpc_chttp2_base64_encode_and_huffman_compress =
grpc_chttp2_base64_encode_and_huffman_compress_impl;
grpc_register_tracer("http", &grpc_http_trace);
grpc_register_tracer("flowctl", &grpc_flowctl_trace);
grpc_register_tracer("http_write_state", &grpc_http_write_state_trace);
}
void grpc_chttp2_plugin_shutdown(void) {}

@ -48,6 +48,7 @@
#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/workqueue.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h"
@ -60,9 +61,9 @@
#define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024)
#define MAX_CLIENT_STREAM_ID 0x7fffffffu
int grpc_http_trace = 0;
int grpc_flowctl_trace = 0;
int grpc_http_write_state_trace = 0;
#define TRANSPORT_FROM_WRITING(tw) \
((grpc_chttp2_transport *)((char *)(tw)-offsetof(grpc_chttp2_transport, \
@ -88,10 +89,16 @@ static const grpc_transport_vtable vtable;
static void writing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
static void reading_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
static void parsing_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
static void initiate_writing(grpc_exec_ctx *exec_ctx, void *t,
grpc_error *error);
static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
static void end_waiting_for_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, grpc_error *error);
/** Set a transport level setting, and push it to our peer */
static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
uint32_t value);
static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_setting_id id, uint32_t value);
/** Start disconnection chain */
static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@ -137,7 +144,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global);
static void incoming_byte_stream_update_flow_control(
grpc_chttp2_transport_global *transport_global,
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, size_t max_size_hint,
size_t have_already);
static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
@ -201,6 +208,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
gpr_free(t);
}
/*#define REFCOUNTING_DEBUG 1*/
#ifdef REFCOUNTING_DEBUG
#define REF_TRANSPORT(t, r) ref_transport(t, r, __FILE__, __LINE__)
#define UNREF_TRANSPORT(cl, t, r) unref_transport(cl, t, r, __FILE__, __LINE__)
@ -231,7 +239,7 @@ static void ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
const grpc_channel_args *channel_args,
grpc_endpoint *ep, uint8_t is_client) {
grpc_endpoint *ep, bool is_client) {
size_t i;
int j;
@ -273,6 +281,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_closure_init(&t->writing_action, writing_action, t);
grpc_closure_init(&t->reading_action, reading_action, t);
grpc_closure_init(&t->parsing_action, parsing_action, t);
grpc_closure_init(&t->initiate_writing, initiate_writing, t);
gpr_slice_buffer_init(&t->parsing.qbuf);
grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser);
@ -286,6 +295,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
gpr_slice_buffer_add(
&t->global.qbuf,
gpr_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING));
grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "initial_write");
}
/* 8 is a random stab in the dark as to a good initial size: it's small enough
that it shouldn't waste memory for infrequently used connections, yet
@ -311,11 +321,12 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
/* configure http2 the way we like it */
if (is_client) {
push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
}
push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW);
push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
DEFAULT_WINDOW);
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
DEFAULT_MAX_HEADER_LIST_SIZE);
if (channel_args) {
@ -329,7 +340,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_MAX_CONCURRENT_STREAMS);
} else {
push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
(uint32_t)channel_args->args[i].value.integer);
}
} else if (0 == strcmp(channel_args->args[i].key,
@ -368,7 +379,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
gpr_log(GPR_ERROR, "%s: must be non-negative",
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
} else {
push_setting(t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
(uint32_t)channel_args->args[i].value.integer);
}
} else if (0 == strcmp(channel_args->args[i].key,
@ -393,7 +404,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
gpr_log(GPR_ERROR, "%s: must be non-negative",
GRPC_ARG_MAX_METADATA_SIZE);
} else {
push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
(uint32_t)channel_args->args[i].value.integer);
}
}
@ -444,6 +455,9 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_error *error) {
if (!t->closed) {
if (grpc_http_write_state_trace) {
gpr_log(GPR_DEBUG, "W:%p close transport", t);
}
t->closed = 1;
connectivity_state_set(exec_ctx, &t->global, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(error), "close_transport");
@ -590,7 +604,8 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_incoming_metadata_buffer_destroy(
&s->global.received_trailing_metadata);
gpr_slice_buffer_destroy(&s->writing.flow_controlled_buffer);
GRPC_ERROR_UNREF(s->global.removal_error);
GRPC_ERROR_UNREF(s->global.read_closed_error);
GRPC_ERROR_UNREF(s->global.write_closed_error);
UNREF_TRANSPORT(exec_ctx, t, "stream");
@ -634,6 +649,36 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
* LOCK MANAGEMENT
*/
static const char *write_state_name(grpc_chttp2_write_state state) {
switch (state) {
case GRPC_CHTTP2_WRITING_INACTIVE:
return "INACTIVE";
case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER:
return "REQUESTED[p=0]";
case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER:
return "REQUESTED[p=1]";
case GRPC_CHTTP2_WRITE_SCHEDULED:
return "SCHEDULED";
case GRPC_CHTTP2_WRITING:
return "WRITING";
case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER:
return "WRITING[p=1]";
case GRPC_CHTTP2_WRITING_STALE_NO_POLLER:
return "WRITING[p=0]";
}
GPR_UNREACHABLE_CODE(return "UNKNOWN");
}
static void set_write_state(grpc_chttp2_transport *t,
grpc_chttp2_write_state state, const char *reason) {
if (grpc_http_write_state_trace) {
gpr_log(GPR_DEBUG, "W:%p %s -> %s because %s", t,
write_state_name(t->executor.write_state), write_state_name(state),
reason);
}
t->executor.write_state = state;
}
static void finish_global_actions(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) {
grpc_chttp2_executor_action_header *hdr;
@ -642,13 +687,6 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
GPR_TIMER_BEGIN("finish_global_actions", 0);
for (;;) {
if (!t->executor.writing_active && !t->closed &&
grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) {
t->executor.writing_active = 1;
REF_TRANSPORT(t, "writing");
prevent_endpoint_shutdown(t);
grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL);
}
check_read_ops(exec_ctx, &t->global);
gpr_mu_lock(&t->executor.mu);
@ -669,8 +707,28 @@ static void finish_global_actions(grpc_exec_ctx *exec_ctx,
continue;
} else {
t->executor.global_active = false;
switch (t->executor.write_state) {
case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER:
set_write_state(t, GRPC_CHTTP2_WRITE_SCHEDULED, "unlocking");
REF_TRANSPORT(t, "initiate_writing");
gpr_mu_unlock(&t->executor.mu);
grpc_exec_ctx_sched(
exec_ctx, &t->initiate_writing, GRPC_ERROR_NONE,
t->ep != NULL ? grpc_endpoint_get_workqueue(t->ep) : NULL);
break;
case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER:
start_writing(exec_ctx, t);
gpr_mu_unlock(&t->executor.mu);
break;
case GRPC_CHTTP2_WRITING_INACTIVE:
case GRPC_CHTTP2_WRITING:
case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER:
case GRPC_CHTTP2_WRITING_STALE_NO_POLLER:
case GRPC_CHTTP2_WRITE_SCHEDULED:
gpr_mu_unlock(&t->executor.mu);
break;
}
}
gpr_mu_unlock(&t->executor.mu);
break;
}
@ -741,16 +799,118 @@ void grpc_chttp2_run_with_global_lock(grpc_exec_ctx *exec_ctx,
* OUTPUT PROCESSING
*/
void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global,
bool covered_by_poller, const char *reason) {
/* Perform state checks, and transition to a scheduled state if appropriate.
Each time we finish the global lock execution, we check if we need to
write. If we do:
- (if there is a poller surrounding the write) schedule
initiate_writing, which locks and calls initiate_writing_locked to...
- call start_writing, which verifies (under the global lock) that there
are things that need to be written by calling
grpc_chttp2_unlocking_check_writes, and if so schedules writing_action
against the current exec_ctx, to be executed OUTSIDE of the global lock
- eventually writing_action results in grpc_chttp2_terminate_writing being
called, which re-takes the global lock, updates state, checks if we need
to do *another* write immediately, and if so loops back to
start_writing.
Current problems:
- too much lock entry/exiting
- the writing thread can become stuck indefinitely (punt through the
workqueue periodically to fix) */
grpc_chttp2_transport *t = TRANSPORT_FROM_GLOBAL(transport_global);
switch (t->executor.write_state) {
case GRPC_CHTTP2_WRITING_INACTIVE:
set_write_state(t, covered_by_poller
? GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER
: GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER,
reason);
break;
case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER:
/* nothing to do: write already requested */
break;
case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER:
if (covered_by_poller) {
/* upgrade to note poller is available to cover the write */
set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER, reason);
}
break;
case GRPC_CHTTP2_WRITE_SCHEDULED:
/* nothing to do: write already scheduled */
break;
case GRPC_CHTTP2_WRITING:
set_write_state(t,
covered_by_poller ? GRPC_CHTTP2_WRITING_STALE_WITH_POLLER
: GRPC_CHTTP2_WRITING_STALE_NO_POLLER,
reason);
break;
case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER:
/* nothing to do: write already requested */
break;
case GRPC_CHTTP2_WRITING_STALE_NO_POLLER:
if (covered_by_poller) {
/* upgrade to note poller is available to cover the write */
set_write_state(t, GRPC_CHTTP2_WRITING_STALE_WITH_POLLER, reason);
}
break;
}
}
static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
GPR_ASSERT(t->executor.write_state == GRPC_CHTTP2_WRITE_SCHEDULED ||
t->executor.write_state == GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER);
if (!t->closed &&
grpc_chttp2_unlocking_check_writes(exec_ctx, &t->global, &t->writing)) {
set_write_state(t, GRPC_CHTTP2_WRITING, "start_writing");
REF_TRANSPORT(t, "writing");
prevent_endpoint_shutdown(t);
grpc_exec_ctx_sched(exec_ctx, &t->writing_action, GRPC_ERROR_NONE, NULL);
} else {
if (t->closed) {
set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE,
"start_writing:transport_closed");
} else {
set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE,
"start_writing:nothing_to_write");
}
end_waiting_for_write(exec_ctx, t, GRPC_ERROR_CREATE("Nothing to write"));
if (t->ep && !t->endpoint_reading) {
destroy_endpoint(exec_ctx, t);
}
}
}
static void initiate_writing_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s_unused,
void *arg_ignored) {
start_writing(exec_ctx, t);
UNREF_TRANSPORT(exec_ctx, t, "initiate_writing");
}
static void initiate_writing(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_chttp2_run_with_global_lock(exec_ctx, arg, NULL, initiate_writing_locked,
NULL, 0);
}
void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global,
bool covered_by_poller, const char *reason) {
if (!TRANSPORT_FROM_GLOBAL(transport_global)->closed &&
grpc_chttp2_list_add_writable_stream(transport_global, stream_global)) {
GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
grpc_chttp2_initiate_write(exec_ctx, transport_global, covered_by_poller,
reason);
}
}
static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
uint32_t value) {
static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_setting_id id, uint32_t value) {
const grpc_chttp2_setting_parameters *sp =
&grpc_chttp2_settings_parameters[id];
uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value);
@ -761,9 +921,22 @@ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
if (use_value != t->global.settings[GRPC_LOCAL_SETTINGS][id]) {
t->global.settings[GRPC_LOCAL_SETTINGS][id] = use_value;
t->global.dirtied_local_settings = 1;
grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "push_setting");
}
}
static void end_waiting_for_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t, grpc_error *error) {
grpc_chttp2_stream_global *stream_global;
while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
&stream_global)) {
fail_pending_writes(exec_ctx, &t->global, stream_global,
GRPC_ERROR_REF(error));
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
}
GRPC_ERROR_UNREF(error);
}
static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s_ignored,
@ -778,24 +951,32 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
grpc_chttp2_stream_global *stream_global;
while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
&stream_global)) {
fail_pending_writes(exec_ctx, &t->global, stream_global,
GRPC_ERROR_REF(error));
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
end_waiting_for_write(exec_ctx, t, error);
switch (t->executor.write_state) {
case GRPC_CHTTP2_WRITING_INACTIVE:
case GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER:
case GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER:
case GRPC_CHTTP2_WRITE_SCHEDULED:
GPR_UNREACHABLE_CODE(break);
case GRPC_CHTTP2_WRITING:
set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE, "terminate_writing");
break;
case GRPC_CHTTP2_WRITING_STALE_WITH_POLLER:
set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_WITH_POLLER,
"terminate_writing");
break;
case GRPC_CHTTP2_WRITING_STALE_NO_POLLER:
set_write_state(t, GRPC_CHTTP2_WRITE_REQUESTED_NO_POLLER,
"terminate_writing");
break;
}
/* leave the writing flag up on shutdown to prevent further writes in
unlock()
from starting */
t->executor.writing_active = 0;
if (t->ep && !t->endpoint_reading) {
destroy_endpoint(exec_ctx, t);
}
UNREF_TRANSPORT(exec_ctx, t, "writing");
GRPC_ERROR_UNREF(error);
}
void grpc_chttp2_terminate_writing(grpc_exec_ctx *exec_ctx,
@ -878,7 +1059,8 @@ static void maybe_start_some_streams(
stream_global->id, STREAM_FROM_GLOBAL(stream_global));
stream_global->in_stream_map = true;
transport_global->concurrent_stream_count++;
grpc_chttp2_become_writable(transport_global, stream_global);
grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global, true,
"new_stream");
}
/* cancel out streams that will never be started */
while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@ -1018,9 +1200,11 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
maybe_start_some_streams(exec_ctx, transport_global);
} else {
GPR_ASSERT(stream_global->id != 0);
grpc_chttp2_become_writable(transport_global, stream_global);
grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
true, "op.send_initial_metadata");
}
} else {
stream_global->send_trailing_metadata = NULL;
grpc_chttp2_complete_closure_step(
exec_ctx, transport_global, stream_global,
&stream_global->send_initial_metadata_finished,
@ -1042,7 +1226,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
} else {
stream_global->send_message = op->send_message;
if (stream_global->id != 0) {
grpc_chttp2_become_writable(transport_global, stream_global);
grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
true, "op.send_message");
}
}
}
@ -1075,6 +1260,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
if (stream_global->write_closed) {
stream_global->send_trailing_metadata = NULL;
grpc_chttp2_complete_closure_step(
exec_ctx, transport_global, stream_global,
&stream_global->send_trailing_metadata_finished,
@ -1085,7 +1271,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
} else if (stream_global->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding
bytes before going writable */
grpc_chttp2_become_writable(transport_global, stream_global);
grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
true, "op.send_trailing_metadata");
}
}
}
@ -1106,8 +1293,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
(stream_global->incoming_frames.head == NULL ||
stream_global->incoming_frames.head->is_tail)) {
incoming_byte_stream_update_flow_control(
transport_global, stream_global, transport_global->stream_lookahead,
0);
exec_ctx, transport_global, stream_global,
transport_global->stream_lookahead, 0);
}
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
@ -1135,7 +1322,8 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
sizeof(*op));
}
static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) {
static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_closure *on_recv) {
grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p));
p->next = &t->global.pings;
p->prev = p->next->prev;
@ -1150,6 +1338,7 @@ static void send_ping_locked(grpc_chttp2_transport *t, grpc_closure *on_recv) {
p->id[7] = (uint8_t)(t->global.ping_counter & 0xff);
p->on_recv = on_recv;
gpr_slice_buffer_add(&t->global.qbuf, grpc_chttp2_ping_create(0, p->id));
grpc_chttp2_initiate_write(exec_ctx, &t->global, true, "send_ping");
}
static void ack_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@ -1209,6 +1398,7 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
close_transport = grpc_chttp2_has_streams(t)
? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE("GOAWAY sent");
grpc_chttp2_initiate_write(exec_ctx, &t->global, false, "goaway_sent");
}
if (op->set_accept_stream) {
@ -1226,7 +1416,7 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
}
if (op->send_ping) {
send_ping_locked(t, op->send_ping);
send_ping_locked(exec_ctx, t, op->send_ping);
}
if (close_transport != GRPC_ERROR_NONE) {
@ -1414,6 +1604,8 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx,
&transport_global->qbuf,
grpc_chttp2_rst_stream_create(stream_global->id, (uint32_t)http_error,
&stream_global->stats.outgoing));
grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
"rst_stream");
}
const char *msg =
@ -1473,10 +1665,39 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
}
}
static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) {
if (error == GRPC_ERROR_NONE) return;
for (size_t i = 0; i < *nrefs; i++) {
if (error == refs[i]) {
return;
}
}
refs[*nrefs] = error;
++*nrefs;
}
static grpc_error *removal_error(grpc_error *extra_error,
grpc_chttp2_stream_global *stream_global) {
grpc_error *refs[3];
size_t nrefs = 0;
add_error(stream_global->read_closed_error, refs, &nrefs);
add_error(stream_global->write_closed_error, refs, &nrefs);
add_error(extra_error, refs, &nrefs);
grpc_error *error = GRPC_ERROR_NONE;
if (nrefs > 0) {
error = GRPC_ERROR_CREATE_REFERENCING("Failed due to stream removal", refs,
nrefs);
}
GRPC_ERROR_UNREF(extra_error);
return error;
}
static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global,
grpc_error *error) {
error = removal_error(error, stream_global);
stream_global->send_message = NULL;
grpc_chttp2_complete_closure_step(
exec_ctx, transport_global, stream_global,
&stream_global->send_initial_metadata_finished, GRPC_ERROR_REF(error));
@ -1499,14 +1720,17 @@ void grpc_chttp2_mark_stream_closed(
}
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
if (close_reads && !stream_global->read_closed) {
stream_global->read_closed_error = GRPC_ERROR_REF(error);
stream_global->read_closed = true;
stream_global->published_initial_metadata = true;
stream_global->published_trailing_metadata = true;
decrement_active_streams_locked(exec_ctx, transport_global, stream_global);
}
if (close_writes && !stream_global->write_closed) {
stream_global->write_closed_error = GRPC_ERROR_REF(error);
stream_global->write_closed = true;
if (TRANSPORT_FROM_GLOBAL(transport_global)->executor.writing_active) {
if (TRANSPORT_FROM_GLOBAL(transport_global)->executor.write_state !=
GRPC_CHTTP2_WRITING_INACTIVE) {
GRPC_CHTTP2_STREAM_REF(stream_global, "finish_writes");
grpc_chttp2_list_add_closed_waiting_for_writing(transport_global,
stream_global);
@ -1516,7 +1740,6 @@ void grpc_chttp2_mark_stream_closed(
}
}
if (stream_global->read_closed && stream_global->write_closed) {
stream_global->removal_error = GRPC_ERROR_REF(error);
if (stream_global->id != 0 &&
TRANSPORT_FROM_GLOBAL(transport_global)->executor.parsing_active) {
grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global,
@ -1524,7 +1747,8 @@ void grpc_chttp2_mark_stream_closed(
} else {
if (stream_global->id != 0) {
remove_stream(exec_ctx, TRANSPORT_FROM_GLOBAL(transport_global),
stream_global->id, GRPC_ERROR_REF(error));
stream_global->id,
removal_error(GRPC_ERROR_REF(error), stream_global));
}
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
}
@ -1649,6 +1873,8 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, 1,
1, error);
grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
"close_from_api");
}
typedef struct {
@ -1678,8 +1904,14 @@ static void drop_connection(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
}
/** update window from a settings change */
typedef struct {
grpc_chttp2_transport *t;
grpc_exec_ctx *exec_ctx;
} update_global_window_args;
static void update_global_window(void *args, uint32_t id, void *stream) {
grpc_chttp2_transport *t = args;
update_global_window_args *a = args;
grpc_chttp2_transport *t = a->t;
grpc_chttp2_stream *s = stream;
grpc_chttp2_transport_global *transport_global = &t->global;
grpc_chttp2_stream_global *stream_global = &s->global;
@ -1693,7 +1925,8 @@ static void update_global_window(void *args, uint32_t id, void *stream) {
is_zero = stream_global->outgoing_window <= 0;
if (was_zero && !is_zero) {
grpc_chttp2_become_writable(transport_global, stream_global);
grpc_chttp2_become_writable(a->exec_ctx, transport_global, stream_global,
true, "update_global_window");
}
}
@ -1772,6 +2005,7 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_chttp2_transport *t = arg;
grpc_error *err = GRPC_ERROR_NONE;
GPR_TIMER_BEGIN("reading_action.parse", 0);
size_t i = 0;
grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
@ -1780,15 +2014,13 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg,
errors[1] = grpc_chttp2_perform_read(exec_ctx, &t->parsing,
t->read_buffer.slices[i]);
};
if (i != t->read_buffer.count) {
if (errors[1] == GRPC_ERROR_NONE) {
err = GRPC_ERROR_REF(error);
} else {
errors[2] = try_http_parsing(exec_ctx, t);
err = GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
GPR_ARRAY_SIZE(errors));
}
grpc_error *err =
errors[0] == GRPC_ERROR_NONE && errors[1] == GRPC_ERROR_NONE &&
errors[2] == GRPC_ERROR_NONE
? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE_REFERENCING("Failed parsing HTTP/2", errors,
GPR_ARRAY_SIZE(errors));
for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) {
GRPC_ERROR_UNREF(errors[i]);
}
@ -1802,14 +2034,19 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_transport_global *transport_global = &t->global;
grpc_chttp2_transport_parsing *transport_parsing = &t->parsing;
/* copy parsing qbuf to global qbuf */
gpr_slice_buffer_move_into(&t->parsing.qbuf, &t->global.qbuf);
if (t->parsing.qbuf.count > 0) {
gpr_slice_buffer_move_into(&t->parsing.qbuf, &t->global.qbuf);
grpc_chttp2_initiate_write(exec_ctx, transport_global, false,
"parsing_qbuf");
}
/* merge stream lists */
grpc_chttp2_stream_map_move_into(&t->new_stream_map, &t->parsing_stream_map);
transport_global->concurrent_stream_count =
(uint32_t)grpc_chttp2_stream_map_size(&t->parsing_stream_map);
if (transport_parsing->initial_window_update != 0) {
update_global_window_args args = {t, exec_ctx};
grpc_chttp2_stream_map_for_each(&t->parsing_stream_map,
update_global_window, t);
update_global_window, &args);
transport_parsing->initial_window_update = 0;
}
/* handle higher level things */
@ -1832,7 +2069,7 @@ static void post_parse_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
GPR_ASSERT(stream_global->write_closed);
GPR_ASSERT(stream_global->read_closed);
remove_stream(exec_ctx, t, stream_global->id,
GRPC_ERROR_REF(stream_global->removal_error));
removal_error(GRPC_ERROR_NONE, stream_global));
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2");
}
@ -1855,11 +2092,12 @@ static void post_reading_action_locked(grpc_exec_ctx *exec_ctx,
}
drop_connection(exec_ctx, t, GRPC_ERROR_REF(error));
t->endpoint_reading = 0;
if (!t->executor.writing_active && t->ep) {
grpc_endpoint_destroy(exec_ctx, t->ep);
t->ep = NULL;
/* safe as we still have a ref for read */
UNREF_TRANSPORT(exec_ctx, t, "disconnect");
if (grpc_http_write_state_trace) {
gpr_log(GPR_DEBUG, "R:%p -> 0 ws=%s", t,
write_state_name(t->executor.write_state));
}
if (t->executor.write_state == GRPC_CHTTP2_WRITING_INACTIVE && t->ep) {
destroy_endpoint(exec_ctx, t);
}
} else if (!t->closed) {
keep_reading = true;
@ -1943,7 +2181,7 @@ static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx,
}
static void incoming_byte_stream_update_flow_control(
grpc_chttp2_transport_global *transport_global,
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, size_t max_size_hint,
size_t have_already) {
uint32_t max_recv_bytes;
@ -1978,7 +2216,8 @@ static void incoming_byte_stream_update_flow_control(
add_max_recv_bytes);
grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global,
stream_global);
grpc_chttp2_become_writable(transport_global, stream_global);
grpc_chttp2_become_writable(exec_ctx, transport_global, stream_global,
false, "read_incoming_stream");
}
}
@ -2000,8 +2239,9 @@ static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global = &bs->stream->global;
if (bs->is_tail) {
incoming_byte_stream_update_flow_control(
transport_global, stream_global, arg->max_size_hint, bs->slices.length);
incoming_byte_stream_update_flow_control(exec_ctx, transport_global,
stream_global, arg->max_size_hint,
bs->slices.length);
}
if (bs->slices.count > 0) {
*arg->slice = gpr_slice_buffer_take_first(&bs->slices);
@ -2185,7 +2425,7 @@ static char *format_flowctl_context_var(const char *context, const char *var,
if (context == NULL) {
*scope = NULL;
gpr_asprintf(&buf, "%s(%" PRId64 ")", var, val);
result = gpr_leftpad(buf, ' ', 40);
result = gpr_leftpad(buf, ' ', 60);
gpr_free(buf);
return result;
}
@ -2198,7 +2438,7 @@ static char *format_flowctl_context_var(const char *context, const char *var,
gpr_free(tmp);
}
gpr_asprintf(&buf, "%s.%s(%" PRId64 ")", underscore_pos + 1, var, val);
result = gpr_leftpad(buf, ' ', 40);
result = gpr_leftpad(buf, ' ', 60);
gpr_free(buf);
return result;
}
@ -2231,7 +2471,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
tmp_phase = gpr_leftpad(phase, ' ', 8);
tmp_scope1 = gpr_leftpad(scope1, ' ', 11);
gpr_asprintf(&prefix, "FLOW %s: %s %s ", phase, clisvr, scope1);
gpr_asprintf(&prefix, "FLOW %s: %s %s ", tmp_phase, clisvr, scope1);
gpr_free(tmp_phase);
gpr_free(tmp_scope1);

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save