Merge branch 'master' of https://github.com/grpc/grpc into what-the-fuzz

pull/5803/head
Nicolas "Pixel" Noble 8 years ago
commit 18c71117b0
  1. 10
      .gitignore
  2. 2
      .gitmodules
  3. 76
      .travis.yml
  4. 823
      BUILD
  5. 1778
      CMakeLists.txt
  6. 7
      CONTRIBUTING.md
  7. 2
      INSTALL.md
  8. 1
      MANIFEST.md
  9. 2935
      Makefile
  10. 3
      PYTHON-MANIFEST.in
  11. 4
      README.md
  12. 4
      Rakefile
  13. 74
      binding.gyp
  14. 633
      build.yaml
  15. 13
      composer.json
  16. 91
      config.m4
  17. 2
      doc/.gitignore
  18. 4
      doc/PROTOCOL-HTTP2.md
  19. 49
      doc/c-style-guide.md
  20. 88
      doc/command_line_tool.md
  21. 118
      doc/compression.md
  22. 133
      doc/compression_cookbook.md
  23. 2
      doc/connectivity-semantics-and-api.md
  24. 91
      doc/cpp-style-guide.md
  25. 15
      doc/fail_fast.md
  26. BIN
      doc/images/compression_cookbook_incoming.png
  27. BIN
      doc/images/compression_cookbook_outgoing.png
  28. BIN
      doc/images/load_balancing_design.png
  29. 370
      doc/interop-test-descriptions.md
  30. 69
      doc/load-balancing.md
  31. 22
      doc/naming.md
  32. 3
      doc/statuscodes.md
  33. 1293
      etc/roots.pem
  34. 2
      examples/cpp/README.md
  35. 2
      examples/cpp/cpptutorial.md
  36. 49
      examples/cpp/helloworld/CMakeLists.txt
  37. 21
      examples/cpp/helloworld/Makefile
  38. 2
      examples/cpp/helloworld/README.md
  39. 12
      examples/cpp/helloworld/greeter_async_client.cc
  40. 153
      examples/cpp/helloworld/greeter_async_client2.cc
  41. 4
      examples/cpp/helloworld/greeter_async_server.cc
  42. 2
      examples/cpp/helloworld/greeter_client.cc
  43. 14
      examples/cpp/route_guide/Makefile
  44. 2
      examples/csharp/helloworld/.nuget/packages.config
  45. 12
      examples/csharp/helloworld/Greeter/Greeter.csproj
  46. 10
      examples/csharp/helloworld/Greeter/Helloworld.cs
  47. 120
      examples/csharp/helloworld/Greeter/HelloworldGrpc.cs
  48. 7
      examples/csharp/helloworld/Greeter/packages.config
  49. 12
      examples/csharp/helloworld/GreeterClient/GreeterClient.csproj
  50. 2
      examples/csharp/helloworld/GreeterClient/Program.cs
  51. 7
      examples/csharp/helloworld/GreeterClient/packages.config
  52. 12
      examples/csharp/helloworld/GreeterServer/GreeterServer.csproj
  53. 4
      examples/csharp/helloworld/GreeterServer/Program.cs
  54. 7
      examples/csharp/helloworld/GreeterServer/packages.config
  55. 16
      examples/csharp/helloworld/README.md
  56. 31
      examples/csharp/helloworld/generate_protos.bat
  57. 2
      examples/csharp/route_guide/.nuget/packages.config
  58. 16
      examples/csharp/route_guide/RouteGuide/RouteGuide.cs
  59. 12
      examples/csharp/route_guide/RouteGuide/RouteGuide.csproj
  60. 259
      examples/csharp/route_guide/RouteGuide/RouteGuideGrpc.cs
  61. 7
      examples/csharp/route_guide/RouteGuide/packages.config
  62. 6
      examples/csharp/route_guide/RouteGuideClient/Program.cs
  63. 12
      examples/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj
  64. 7
      examples/csharp/route_guide/RouteGuideClient/packages.config
  65. 11
      examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs
  66. 12
      examples/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj
  67. 7
      examples/csharp/route_guide/RouteGuideServer/packages.config
  68. 31
      examples/csharp/route_guide/generate_protos.bat
  69. 12
      examples/node/README.md
  70. 1
      examples/node/dynamic_codegen/README.md
  71. 53
      examples/node/dynamic_codegen/greeter_client.js
  72. 40
      examples/node/dynamic_codegen/greeter_server.js
  73. 0
      examples/node/dynamic_codegen/route_guide/README.md
  74. 2
      examples/node/dynamic_codegen/route_guide/route_guide_client.js
  75. 0
      examples/node/dynamic_codegen/route_guide/route_guide_db.json
  76. 2
      examples/node/dynamic_codegen/route_guide/route_guide_server.js
  77. 39
      examples/node/helloworld_grpc_pb.js
  78. 4
      examples/node/package.json
  79. 7
      examples/node/static_codegen/README.md
  80. 16
      examples/node/static_codegen/greeter_client.js
  81. 12
      examples/node/static_codegen/greeter_server.js
  82. 76
      examples/node/static_codegen/helloworld_grpc_pb.js
  83. 4
      examples/node/static_codegen/helloworld_pb.js
  84. 5
      examples/node/static_codegen/route_guide/README.md
  85. 247
      examples/node/static_codegen/route_guide/route_guide_client.js
  86. 601
      examples/node/static_codegen/route_guide/route_guide_db.json
  87. 161
      examples/node/static_codegen/route_guide/route_guide_grpc_pb.js
  88. 1033
      examples/node/static_codegen/route_guide/route_guide_pb.js
  89. 261
      examples/node/static_codegen/route_guide/route_guide_server.js
  90. 28
      examples/objective-c/auth_sample/AuthSample.xcodeproj/project.pbxproj
  91. 91
      examples/objective-c/auth_sample/AuthSample.xcodeproj/xcshareddata/xcschemes/AuthSample.xcscheme
  92. 38
      examples/objective-c/auth_sample/AuthTestService.podspec
  93. 30
      examples/objective-c/auth_sample/Misc/GoogleService-Info.plist
  94. 4
      examples/objective-c/auth_sample/Podfile
  95. 38
      examples/objective-c/helloworld/HelloWorld.podspec
  96. 24
      examples/objective-c/helloworld/HelloWorld.xcodeproj/project.pbxproj
  97. 91
      examples/objective-c/helloworld/HelloWorld.xcodeproj/xcshareddata/xcschemes/HelloWorld.xcscheme
  98. 4
      examples/objective-c/helloworld/Podfile
  99. 2
      examples/objective-c/helloworld/README.md
  100. 108
      examples/objective-c/route_guide/Misc/Base.lproj/Main.storyboard
  101. Some files were not shown because too many files have changed in this diff Show More

10
.gitignore vendored

@ -5,13 +5,15 @@ libs
objs
# Python items
cython_debug/
python_build/
.coverage*
.eggs
.tox
htmlcov/
dist/
*.egg
py27/
py34/
# Node installation output
^node_modules
@ -94,3 +96,9 @@ Pods/
# Artifacts directory
artifacts/
# Git generated files for conflicting
*.orig
# IDE specific folder for JetBrains IDEs
.idea/

2
.gitmodules vendored

@ -4,7 +4,7 @@
[submodule "third_party/protobuf"]
path = third_party/protobuf
url = https://github.com/google/protobuf.git
branch = v3.0.0-beta-2
branch = 3.0.0-beta-3
[submodule "third_party/gflags"]
path = third_party/gflags
url = https://github.com/gflags/gflags.git

@ -1,32 +1,70 @@
git:
depth: 1
language: objective-c
osx_image: xcode7.2
osx_image: xcode7.3
env:
global:
- CONFIG=opt
- TEST=objc
- JOBS=1
matrix:
- 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"
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="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.1'
- pod --version
# Recent pods aren't found if we don't explicitly update Cocoapods' repo.
- pod repo update
- brew install gflags
# Pod install does this too, but we don't want the output.
- pod repo update --silent
install:
- make grpc_objective_c_plugin
- pushd src/objective-c/tests
# Needs to be verbose, or otherwise OpenSSL's prepare_command makes Travis
# time out:
- pod install --verbose
- pushd $TEST_PATH
- pod install
- popd
before_script:
- make interop_server
- bins/$CONFIG/interop_server --port=5050 &
- bins/$CONFIG/interop_server --port=5051 --use_tls &
xcode_workspace: src/objective-c/tests/Tests.xcworkspace
xcode_scheme:
- RxLibraryUnitTests
- InteropTestsLocalSSL
- InteropTestsLocalCleartext
# TODO(jcanizales): Investigate why they time out:
# - InteropTestsRemote
xcode_sdk: iphonesimulator9.2
- if [ "${INTEROP_SERVER}" = "true" ]; then
make interop_server;
(bins/$CONFIG/interop_server --port=5050 &);
(bins/$CONFIG/interop_server --port=5051 --use_tls &);
fi
script:
- if [ "${BUILD_ONLY}" = "true" ]; then
xctool -workspace "$TEST_PATH/$WORKSPACE" -scheme "$SCHEME"
-sdk iphonesimulator9.3 build;
else
xctool -workspace "$TEST_PATH/$WORKSPACE" -scheme "$SCHEME"
-sdk iphonesimulator9.3 test;
fi
notifications:
email: false

823
BUILD

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -53,6 +53,13 @@ To know about the list of available commands, do this:
`./tools/run_tests/run_tests.py -h`
If you are running tests for ObjC on osx, follow these steps before running tests:
* install Xcode command-line tools by running
`sudo xcode-select --install`
* install macports from https://www.macports.org/install.php
* install autoconf, automake, libtool, gflags, cmake using macports
* restart your terminal window or run source ~/.bash_profile to pick up the new PATH changes.
## Adding or removing source code
Each language uses its own build system to work. Currently, the root's Makefile

@ -49,7 +49,7 @@ For developers who are interested to contribute, here is how to compile the
gRPC C Core library.
```sh
$ git clone https://github.com/grpc/grpc.git
$ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc
$ cd grpc
$ git submodule update --init
$ make

@ -19,7 +19,6 @@
* [requirements.txt](requirements.txt)
* [setup.cfg](setup.cfg)
* [setup.py](setup.py)
* [tox.ini](tox.ini)
* [PYTHON-MANIFEST.in](PYTHON-MANIFEST.in)
## Ruby

2935
Makefile

File diff suppressed because it is too large Load Diff

@ -1,12 +1,13 @@
recursive-include src/python/grpcio/grpc *.c *.h *.py *.pyx *.pxd *.pxi *.python *.pem
recursive-exclude src/python/grpcio/grpc/_cython *.so *.pyd
graft src/python/grpcio/tests
graft src/python/grpcio/grpcio.egg-info
graft src/core
graft src/boringssl
graft include/grpc
graft third_party/boringssl
graft third_party/nanopb
graft third_party/zlib
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

@ -11,10 +11,12 @@ Copyright 2015 Google Inc.
You can find more detailed documentation and examples in the [doc](doc) and [examples](examples) directories respectively.
#Installation
#Installation & Testing
See [INSTALL](INSTALL.md) for installation instructions for various platforms.
See [tools/run_tests](tools/run_tests) for more guidance on how to run various test suites (e.g. unit tests, interop tests, benchmarks)
#Repository Structure & Status
This repository contains source code for gRPC libraries for multiple languages written on top of shared C core library [src/core] (src/core).

@ -77,13 +77,13 @@ task 'dlls' do
grpc_config = ENV['GRPC_CONFIG'] || 'opt'
verbose = ENV['V'] || '0'
env = 'CPPFLAGS="-D_WIN32_WINNT=0x600 -DUNICODE -D_UNICODE" '
env = 'CPPFLAGS="-D_WIN32_WINNT=0x600 -DUNICODE -D_UNICODE -Wno-unused-variable -Wno-unused-result" '
env += 'LDFLAGS=-static '
env += 'SYSTEM=MINGW32 '
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' }

@ -507,37 +507,38 @@
'src/core/lib/support/cpu_windows.c',
'src/core/lib/support/env_linux.c',
'src/core/lib/support/env_posix.c',
'src/core/lib/support/env_win32.c',
'src/core/lib/support/env_windows.c',
'src/core/lib/support/histogram.c',
'src/core/lib/support/host_port.c',
'src/core/lib/support/load_file.c',
'src/core/lib/support/log.c',
'src/core/lib/support/log_android.c',
'src/core/lib/support/log_linux.c',
'src/core/lib/support/log_posix.c',
'src/core/lib/support/log_win32.c',
'src/core/lib/support/log_windows.c',
'src/core/lib/support/murmur_hash.c',
'src/core/lib/support/slice.c',
'src/core/lib/support/slice_buffer.c',
'src/core/lib/support/stack_lockfree.c',
'src/core/lib/support/string.c',
'src/core/lib/support/string_posix.c',
'src/core/lib/support/string_win32.c',
'src/core/lib/support/string_util_windows.c',
'src/core/lib/support/string_windows.c',
'src/core/lib/support/subprocess_posix.c',
'src/core/lib/support/subprocess_windows.c',
'src/core/lib/support/sync.c',
'src/core/lib/support/sync_posix.c',
'src/core/lib/support/sync_win32.c',
'src/core/lib/support/sync_windows.c',
'src/core/lib/support/thd.c',
'src/core/lib/support/thd_posix.c',
'src/core/lib/support/thd_win32.c',
'src/core/lib/support/thd_windows.c',
'src/core/lib/support/time.c',
'src/core/lib/support/time_posix.c',
'src/core/lib/support/time_precise.c',
'src/core/lib/support/time_win32.c',
'src/core/lib/support/time_windows.c',
'src/core/lib/support/tls_pthread.c',
'src/core/lib/support/tmpfile_msys.c',
'src/core/lib/support/tmpfile_posix.c',
'src/core/lib/support/tmpfile_win32.c',
'src/core/lib/support/tmpfile_windows.c',
'src/core/lib/support/wrap_memcpy.c',
],
"conditions": [
@ -567,9 +568,10 @@
'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_algorithm.c',
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/debug/trace.c',
'src/core/lib/http/format_request.c',
@ -579,7 +581,10 @@
'src/core/lib/iomgr/endpoint.c',
'src/core/lib/iomgr/endpoint_pair_posix.c',
'src/core/lib/iomgr/endpoint_pair_windows.c',
'src/core/lib/iomgr/error.c',
'src/core/lib/iomgr/ev_epoll_linux.c',
'src/core/lib/iomgr/ev_poll_and_epoll_posix.c',
'src/core/lib/iomgr/ev_poll_posix.c',
'src/core/lib/iomgr/ev_posix.c',
'src/core/lib/iomgr/exec_ctx.c',
'src/core/lib/iomgr/executor.c',
@ -587,6 +592,9 @@
'src/core/lib/iomgr/iomgr.c',
'src/core/lib/iomgr/iomgr_posix.c',
'src/core/lib/iomgr/iomgr_windows.c',
'src/core/lib/iomgr/load_file.c',
'src/core/lib/iomgr/network_status_tracker.c',
'src/core/lib/iomgr/polling_entity.c',
'src/core/lib/iomgr/pollset_set_windows.c',
'src/core/lib/iomgr/pollset_windows.c',
'src/core/lib/iomgr/resolve_address_posix.c',
@ -644,6 +652,7 @@
'src/core/lib/transport/transport.c',
'src/core/lib/transport/transport_op_string.c',
'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c',
'src/core/ext/transport/chttp2/transport/bin_decoder.c',
'src/core/ext/transport/chttp2/transport/bin_encoder.c',
'src/core/ext/transport/chttp2/transport/chttp2_plugin.c',
'src/core/ext/transport/chttp2/transport/chttp2_transport.c',
@ -667,20 +676,29 @@
'src/core/ext/transport/chttp2/transport/writing.c',
'src/core/ext/transport/chttp2/alpn/alpn.c',
'src/core/lib/http/httpcli_security_connector.c',
'src/core/lib/security/b64.c',
'src/core/lib/security/client_auth_filter.c',
'src/core/lib/security/credentials.c',
'src/core/lib/security/credentials_metadata.c',
'src/core/lib/security/credentials_posix.c',
'src/core/lib/security/credentials_win32.c',
'src/core/lib/security/google_default_credentials.c',
'src/core/lib/security/handshake.c',
'src/core/lib/security/json_token.c',
'src/core/lib/security/jwt_verifier.c',
'src/core/lib/security/secure_endpoint.c',
'src/core/lib/security/security_connector.c',
'src/core/lib/security/security_context.c',
'src/core/lib/security/server_auth_filter.c',
'src/core/lib/security/context/security_context.c',
'src/core/lib/security/credentials/composite/composite_credentials.c',
'src/core/lib/security/credentials/credentials.c',
'src/core/lib/security/credentials/credentials_metadata.c',
'src/core/lib/security/credentials/fake/fake_credentials.c',
'src/core/lib/security/credentials/google_default/credentials_posix.c',
'src/core/lib/security/credentials/google_default/credentials_windows.c',
'src/core/lib/security/credentials/google_default/google_default_credentials.c',
'src/core/lib/security/credentials/iam/iam_credentials.c',
'src/core/lib/security/credentials/jwt/json_token.c',
'src/core/lib/security/credentials/jwt/jwt_credentials.c',
'src/core/lib/security/credentials/jwt/jwt_verifier.c',
'src/core/lib/security/credentials/oauth2/oauth2_credentials.c',
'src/core/lib/security/credentials/plugin/plugin_credentials.c',
'src/core/lib/security/credentials/ssl/ssl_credentials.c',
'src/core/lib/security/transport/client_auth_filter.c',
'src/core/lib/security/transport/handshake.c',
'src/core/lib/security/transport/secure_endpoint.c',
'src/core/lib/security/transport/security_connector.c',
'src/core/lib/security/transport/server_auth_filter.c',
'src/core/lib/security/transport/tsi_error.c',
'src/core/lib/security/util/b64.c',
'src/core/lib/security/util/json_util.c',
'src/core/lib/surface/init_secure.c',
'src/core/lib/tsi/fake_transport_security.c',
'src/core/lib/tsi/ssl_transport_security.c',
@ -706,9 +724,12 @@
'src/core/ext/client_config/subchannel_index.c',
'src/core/ext/client_config/uri_parser.c',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2.c',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c',
'src/core/ext/transport/chttp2/client/insecure/channel_create.c',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c',
'src/core/ext/lb_policy/grpclb/grpclb.c',
'src/core/ext/lb_policy/grpclb/load_balancer_api.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c',
'src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',
'third_party/nanopb/pb_decode.c',
'third_party/nanopb/pb_encode.c',
@ -716,7 +737,11 @@
'src/core/ext/lb_policy/round_robin/round_robin.c',
'src/core/ext/resolver/dns/native/dns_resolver.c',
'src/core/ext/resolver/sockaddr/sockaddr_resolver.c',
'src/core/ext/load_reporting/load_reporting.c',
'src/core/ext/load_reporting/load_reporting_filter.c',
'src/core/ext/census/base_resources.c',
'src/core/ext/census/context.c',
'src/core/ext/census/gen/census.pb.c',
'src/core/ext/census/grpc_context.c',
'src/core/ext/census/grpc_filter.c',
'src/core/ext/census/grpc_plugin.c',
@ -724,6 +749,7 @@
'src/core/ext/census/mlog.c',
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',
'src/core/ext/census/resource.c',
'src/core/ext/census/tracing.c',
'src/core/plugin_registry/grpc_plugin_registry.c',
],

File diff suppressed because it is too large Load Diff

@ -2,20 +2,15 @@
"name": "grpc/grpc",
"type": "library",
"description": "gRPC library for PHP",
"version": "0.14.0",
"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",
"google/auth": "v0.7"
"stanley-cheung/protobuf-php": "v0.6"
},
"require-dev": {
"google/auth": "v0.9"
},
"autoload": {
"psr-4": {

@ -48,37 +48,38 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/support/cpu_windows.c \
src/core/lib/support/env_linux.c \
src/core/lib/support/env_posix.c \
src/core/lib/support/env_win32.c \
src/core/lib/support/env_windows.c \
src/core/lib/support/histogram.c \
src/core/lib/support/host_port.c \
src/core/lib/support/load_file.c \
src/core/lib/support/log.c \
src/core/lib/support/log_android.c \
src/core/lib/support/log_linux.c \
src/core/lib/support/log_posix.c \
src/core/lib/support/log_win32.c \
src/core/lib/support/log_windows.c \
src/core/lib/support/murmur_hash.c \
src/core/lib/support/slice.c \
src/core/lib/support/slice_buffer.c \
src/core/lib/support/stack_lockfree.c \
src/core/lib/support/string.c \
src/core/lib/support/string_posix.c \
src/core/lib/support/string_win32.c \
src/core/lib/support/string_util_windows.c \
src/core/lib/support/string_windows.c \
src/core/lib/support/subprocess_posix.c \
src/core/lib/support/subprocess_windows.c \
src/core/lib/support/sync.c \
src/core/lib/support/sync_posix.c \
src/core/lib/support/sync_win32.c \
src/core/lib/support/sync_windows.c \
src/core/lib/support/thd.c \
src/core/lib/support/thd_posix.c \
src/core/lib/support/thd_win32.c \
src/core/lib/support/thd_windows.c \
src/core/lib/support/time.c \
src/core/lib/support/time_posix.c \
src/core/lib/support/time_precise.c \
src/core/lib/support/time_win32.c \
src/core/lib/support/time_windows.c \
src/core/lib/support/tls_pthread.c \
src/core/lib/support/tmpfile_msys.c \
src/core/lib/support/tmpfile_posix.c \
src/core/lib/support/tmpfile_win32.c \
src/core/lib/support/tmpfile_windows.c \
src/core/lib/support/wrap_memcpy.c \
src/core/lib/surface/init.c \
src/core/lib/channel/channel_args.c \
@ -86,9 +87,10 @@ 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_algorithm.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
src/core/lib/http/format_request.c \
@ -98,7 +100,10 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/endpoint.c \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll_linux.c \
src/core/lib/iomgr/ev_poll_and_epoll_posix.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
@ -106,6 +111,9 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/iomgr.c \
src/core/lib/iomgr/iomgr_posix.c \
src/core/lib/iomgr/iomgr_windows.c \
src/core/lib/iomgr/load_file.c \
src/core/lib/iomgr/network_status_tracker.c \
src/core/lib/iomgr/polling_entity.c \
src/core/lib/iomgr/pollset_set_windows.c \
src/core/lib/iomgr/pollset_windows.c \
src/core/lib/iomgr/resolve_address_posix.c \
@ -163,6 +171,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \
src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c \
src/core/ext/transport/chttp2/transport/bin_decoder.c \
src/core/ext/transport/chttp2/transport/bin_encoder.c \
src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
src/core/ext/transport/chttp2/transport/chttp2_transport.c \
@ -186,20 +195,29 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/transport/chttp2/transport/writing.c \
src/core/ext/transport/chttp2/alpn/alpn.c \
src/core/lib/http/httpcli_security_connector.c \
src/core/lib/security/b64.c \
src/core/lib/security/client_auth_filter.c \
src/core/lib/security/credentials.c \
src/core/lib/security/credentials_metadata.c \
src/core/lib/security/credentials_posix.c \
src/core/lib/security/credentials_win32.c \
src/core/lib/security/google_default_credentials.c \
src/core/lib/security/handshake.c \
src/core/lib/security/json_token.c \
src/core/lib/security/jwt_verifier.c \
src/core/lib/security/secure_endpoint.c \
src/core/lib/security/security_connector.c \
src/core/lib/security/security_context.c \
src/core/lib/security/server_auth_filter.c \
src/core/lib/security/context/security_context.c \
src/core/lib/security/credentials/composite/composite_credentials.c \
src/core/lib/security/credentials/credentials.c \
src/core/lib/security/credentials/credentials_metadata.c \
src/core/lib/security/credentials/fake/fake_credentials.c \
src/core/lib/security/credentials/google_default/credentials_posix.c \
src/core/lib/security/credentials/google_default/credentials_windows.c \
src/core/lib/security/credentials/google_default/google_default_credentials.c \
src/core/lib/security/credentials/iam/iam_credentials.c \
src/core/lib/security/credentials/jwt/json_token.c \
src/core/lib/security/credentials/jwt/jwt_credentials.c \
src/core/lib/security/credentials/jwt/jwt_verifier.c \
src/core/lib/security/credentials/oauth2/oauth2_credentials.c \
src/core/lib/security/credentials/plugin/plugin_credentials.c \
src/core/lib/security/credentials/ssl/ssl_credentials.c \
src/core/lib/security/transport/client_auth_filter.c \
src/core/lib/security/transport/handshake.c \
src/core/lib/security/transport/secure_endpoint.c \
src/core/lib/security/transport/security_connector.c \
src/core/lib/security/transport/server_auth_filter.c \
src/core/lib/security/transport/tsi_error.c \
src/core/lib/security/util/b64.c \
src/core/lib/security/util/json_util.c \
src/core/lib/surface/init_secure.c \
src/core/lib/tsi/fake_transport_security.c \
src/core/lib/tsi/ssl_transport_security.c \
@ -225,9 +243,12 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/client_config/subchannel_index.c \
src/core/ext/client_config/uri_parser.c \
src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \
src/core/ext/transport/chttp2/client/insecure/channel_create.c \
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
src/core/ext/lb_policy/grpclb/grpclb.c \
src/core/ext/lb_policy/grpclb/load_balancer_api.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.c \
src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
third_party/nanopb/pb_encode.c \
@ -235,7 +256,11 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/lb_policy/round_robin/round_robin.c \
src/core/ext/resolver/dns/native/dns_resolver.c \
src/core/ext/resolver/sockaddr/sockaddr_resolver.c \
src/core/ext/load_reporting/load_reporting.c \
src/core/ext/load_reporting/load_reporting_filter.c \
src/core/ext/census/base_resources.c \
src/core/ext/census/context.c \
src/core/ext/census/gen/census.pb.c \
src/core/ext/census/grpc_context.c \
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
@ -243,6 +268,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
src/core/ext/census/resource.c \
src/core/ext/census/tracing.c \
src/core/plugin_registry/grpc_plugin_registry.c \
src/boringssl/err_data.c \
@ -551,11 +577,13 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/boringssl)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census/gen)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/client_config)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/pick_first)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/lb_policy/round_robin)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/load_reporting)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/resolver/dns/native)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/resolver/sockaddr)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/alpn)
@ -571,7 +599,18 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/iomgr)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/json)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/profiling)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/context)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/composite)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/fake)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/google_default)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/iam)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/jwt)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/oauth2)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/plugin)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/ssl)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/transport)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/util)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/support)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/surface)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/transport)

2
doc/.gitignore vendored

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

@ -38,7 +38,7 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
* **Nanosecond** → "n"
* **Content-Type** → "content-type" "application/grpc" [("+proto" / "+json" / {_custom_})]
* **Content-Coding** → "identity" / "gzip" / "deflate" / "snappy" / {_custom_}
* **Message-Encoding** → "grpc-encoding" Content-Coding
* <a name="message-encoding"></a>**Message-Encoding** → "grpc-encoding" Content-Coding
* **Message-Accept-Encoding** → "grpc-accept-encoding" Content-Coding \*("," Content-Coding)
* **User-Agent** → "user-agent" {_structured user-agent string_}
* **Message-Type** → "grpc-message-type" {_type name for message schema_}
@ -83,7 +83,7 @@ binary values' lengths being post-Base64.
The repeated sequence of **Length-Prefixed-Message** items is delivered in DATA frames
* **Length-Prefixed-Message** → Compressed-Flag Message-Length Message
* **Compressed-Flag** → 0 / 1 # encoded as 1 byte unsigned integer
* <a name="compressed-flag"></a>**Compressed-Flag** → 0 / 1 # encoded as 1 byte unsigned integer
* **Message-Length** → {_length of Message_} # encoded as 4 byte unsigned integer
* **Message** → \*{binary octet}

@ -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.
- 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,17 +35,27 @@ 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
`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`.
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
--------
@ -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.

@ -0,0 +1,88 @@
# gRPC command line tool
## Overview
This document describes the command line tool that comes with gRPC repository. It is desireable to have command line
tools written in other languages to roughly follow the same syntax and flags.
At this point, the tool needs to be built from source, and it should be moved out to grpc-tools repository as a stand
alone application once it is mature enough.
## Core functionality
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).
- Display proto response in text form.
- Write response in wire form to a file.
The command line tool should support the following things:
- List server services and methods through server reflection.
- Fine-grained auth control (such as, use this oauth token to talk to the server).
- Send streaming rpc.
## Code location
To use the tool, you need to get the grpc repository and in the grpc directory execute
```
$ make grpc_cli
```
The main file can be found at
https://github.com/grpc/grpc/blob/master/test/cpp/util/grpc_cli.cc
## Usage
### Basic usage
Send a rpc to a helloworld server at `localhost:50051`:
```
$ 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:
message: "Hello world"
```
The `localhost:50051` part indicates the server you are connecting to. `SayHello` is (part of) the
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
For using gRPC with protocols other than probobuf, you will need the exact method name string
and a file containing the raw bytes to be sent on the wire
```
$ bins/opt/grpc_cli call localhost:50051 /helloworld.Greeter/SayHello --input_binary_file=input.bin \
--output_binary_file=output.bin
```
On success, you will need to read or decode the response from the `output.bin` file.

@ -0,0 +1,118 @@
## **gRPC Compression**
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119](http://www.ietf.org/rfc/rfc2119.txt).
### Intent
Compression is used to reduce the amount of bandwidth used between peers. The
compression supported by gRPC acts _at the individual message level_, taking
_message_ [as defined in the wire format
document](PROTOCOL-HTTP2.md).
The implementation supports different compression algorithms. A _default
compression level_, to be used in the absence of message-specific settings, MAY
be specified for during channel creation.
The ability to control compression settings per call and to enable/disable
compression on a per message basis MAY be used to prevent CRIME/BEAST attacks.
It also allows for asymmetric compression communication, whereby a response MAY
be compressed differently, if at all.
### Specification
Compression MAY be configured by the Client Application by calling the
appropriate API method. There are two scenarios where compression MAY be
configured:
+ At channel creation time, which sets the channel default compression and
therefore the compression that SHALL be used in the absence of per-RPC
compression configuration.
+ At response time, via:
+ For unary RPCs, the {Client,Server}Context instance.
+ For streaming RPCs, the {Client,Server}Writer instance. In this case,
configuration is reduced to disabling compression altogether.
### Compression Method Asymmetry Between Peers
A gRPC peer MAY choose to respond using a different compression method to that
of the request, including not performing any compression, regardless of channel
and RPC settings (for example, if compression would result in small or negative
gains).
When a message from a client compressed with an unsupported algorithm is
processed by a server, it WILL result in an `UNIMPLEMENTED` error status on the
server. The server will then include in its response a `grpc-accept-encoding`
header specifying the algorithms it does accept. If an `UNIMPLEMENTED` error
status is returned from the server despite having used one of the algorithms
from the `grpc-accept-encoding` header, the cause MUST NOT be related to
compression. Data sent from a server compressed with an algorithm not supported
by the client WILL result in an `INTERNAL` error status on the client side.
Note that a peer MAY choose to not disclose all the encodings it supports.
However, if it receives a message compressed in an undisclosed but supported
encoding, it MUST include said encoding in the response's `grpc-accept-encoding
h`eader.
For every message a server is requested to compress using an algorithm it knows
the client doesn't support (as indicated by the last `grpc-accept-encoding`
header received from the client), it SHALL send the message uncompressed.
### Specific Disabling of Compression
If the user (through the previously described mechanisms) requests to disable
compression the next message MUST be sent uncompressed. This is instrumental in
preventing BEAST/CRIME attacks. This applies to both the the unary and streaming
cases.
### Compression Levels and Algorithms
The set of supported algorithm is implementation dependent. In order to simplify
the public API and to operate seamlessly across implementations (both in terms
of languages but also different version of the same one), we introduce the idea
of _compression levels_ (such as "low", "medium", "high").
Levels map to concrete algorithms and/or their settings (such as "low" mapping
to "gzip -3" and "high" mapping to "gzip -9") automatically depending on what a
peer is known to support. A server is always aware of what its clients support,
as clients disclose it in their Message-Accept-Encoding header as part of their
initial call. A client doesn't a priori (presently) know which algorithms a
server supports. This issue can be addressed with an initial negotiation of
capabilities or an automatic retry mechanism. These features will be implemented
in the future. Currently however, compression levels are only supported at the
server side, which is aware of the client's capabilities through the incoming
Message-Accept-Encoding header.
### Propagation to child RPCs
The inheritance of the compression configuration by child RPCs is left up to the
implementation. Note that in the absence of changes to the parent channel, its
configuration will be used.
### Test cases
1. When a compression level is not specified for either the channel or the
message, the default channel level _none_ is considered: data MUST NOT be
compressed.
1. When per-RPC compression configuration isn't present for a message, the
channel compression configuration MUST be used.
1. When a compression method (including no compression) is specified for an
outgoing message, the message MUST be compressed accordingly.
1. A message compressed by a client in a way not supported by its server MUST
fail with status `UNIMPLEMENTED`, its associated description indicating the
unsupported condition as well as the supported ones. The returned
`grpc-accept-encoding` header MUST NOT contain the compression method
(encoding) used.
1. A message compressed by a server in a way not supported by its client MUST
fail with status `INTERNAL`, its associated description indicating the
unsupported condition as well as the supported ones. The returned
`grpc-accept-encoding` header MUST NOT contain the compression method
(encoding) used.
1. An ill-constructed message with its [Compressed-Flag
bit](PROTOCOL-HTTP2.md#compressed-flag)
set but lacking a
"[grpc-encoding](PROTOCOL-HTTP2.md#message-encoding)"
entry different from _identity_ in its metadata MUST fail with `INTERNAL`
status, its associated description indicating the invalid Compressed-Flag
condition.

@ -0,0 +1,133 @@
# gRPC (Core) Compression Cookbook
## Introduction
This document describes compression as implemented by the gRPC C core. See [the
full compression specification](compression.md) for details.
### Intended Audience
Wrapped languages developers, for the purposes of supporting compression by
interacting with the C core.
## Criteria for GA readiness
1. Be able to set compression at [channel](#per-channel-settings),
[call](#per-call-settings) and [message](#per-message-settings) level.
In principle this API should be based on _compression levels_ as opposed to
algorithms. See the discussion [below](#level-vs-algorithms).
1. Have unit tests covering [the cases from the
spec](https://github.com/grpc/grpc/blob/master/doc/compression.md#test-cases).
1. Interop tests implemented and passing on Jenkins. The two relevant interop
test cases are
[large_compressed_unary](https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md#large_compressed_unary)
and
[server_compressed_streaming](https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md#server_compressed_streaming).
## Summary Flowcharts
The following flowcharts depict the evolution of a message, both _incoming_ and
_outgoing_, irrespective of the client/server character of the call. Aspects
still not symmetric between clients and servers (e.g. the [use of compression
levels](https://github.com/grpc/grpc/blob/master/doc/compression.md#compression-levels-and-algorithms))
are explicitly marked. The in-detail textual description for the different
scenarios is described in subsequent sections.
## Incoming Messages
![image](images/compression_cookbook_incoming.png)
## Outgoing Messages
![image](images/compression_cookbook_outgoing.png)
## Levels vs Algorithms
As mentioned in [the relevant discussion on the spec
document](https://github.com/grpc/grpc/blob/master/doc/compression.md#compression-levels-and-algorithms),
compression _levels_ are the primary mechanism for compression selection _at the
server side_. In the future, it'll also be at the client side. The use of levels
abstracts away the intricacies of selecting a concrete algorithm supported by a
peer, on top of removing the burden of choice from the developer.
As of this writing (Q2 2016), clients can only specify compression _algorithms_.
Clients will support levels as soon as an automatic retry/negotiation mechanism
is in place.
## Per Channel Settings
Compression may be configured at channel creation. This is a convenience to
avoid having to repeatedly configure compression for every call. Note that any
compression setting on individual [calls](#per-call-settings) or
[messages](#per-message-settings) overrides channel settings.
The following aspects can be configured at channel-creation time via channel arguments:
#### Disable Compression _Algorithms_
Use the channel argument key
`GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET` (from
[`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)),
takes a 32 bit bitset value. A set bit means the algorithm with that enum value
according to `grpc_compression_algorithm` is _enabled_.
For example, `GRPC_COMPRESS_GZIP` currently has a numeric value of 2. To
enable/disable GZIP for a channel, one would set/clear the 3rd LSB (eg, 0b100 =
0x4). Note that setting/clearing 0th position, that corresponding to
`GRPC_COMPRESS_NONE`, has no effect, as no-compression (a.k.a. _identity_) is
always supported.
Incoming messages compressed (ie, encoded) with a disabled algorithm will result
in the call being closed with `GRPC_STATUS_UNIMPLEMENTED`.
#### Default Compression _Level_
**(currently, Q2 2016, only applicable for server side channels. It's ignored
for clients.)**
Use the channel argument key `GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL` (from
[`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)),
valued by an integer corresponding to a value from the `grpc_compression_level`
enum.
#### Default Compression _Algorithm_
Use the channel argument key `GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM` (from
[`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)),
valued by an integer corresponding to a value from the `grpc_compression_level`
enum.
## Per Call Settings
### Compression **Level** in Call Responses
The server requests a compression level via initial metadata. The
`send_initial_metadata` `grpc_op` contains a `maybe_compression_level` field
with two fields, `is_set` and `compression_level`. The former must be set when
actively choosing a level to disambiguate the default value of zero (no
compression) from the proactive selection of no compression.
The core will receive the request for the compression level and automatically
choose a compression algorithm based on its knowledge about the peer
(communicated by the client via the `grpc-accept-encoding` header. Note that the
absence of this header means no compression is supported by the client/peer).
### Compression **Algorithm** in Call Responses
**Server should avoid setting the compression algorithm directly**. Prefer
setting compression levels unless there's a _very_ compelling reason to choose
specific algorithms (benchmarking, testing).
Selection of concrete compression algorithms is performed by adding a
`(GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, <algorithm-name>)` key-value pair to the
initial metadata, where `GRPC_COMPRESS_REQUEST_ALGORITHM_KEY` is defined in
[`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)),
and `<algorithm-name>` is the human readable name of the algorithm as given in
[the HTTP2 spec](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)
for `Message-Encoding` (e.g. gzip, identity, etc.). See
[`grpc_compression_algorithm_name`](https://github.com/grpc/grpc/blob/master/src/core/lib/compression/compression.c)
for the mapping between the `grpc_compression_algorithm` enum values and their
textual representation.
## Per Message Settings
To disable compression for a specific message, the `flags` field of `grpc_op`
instances of type `GRPC_OP_SEND_MESSAGE` must have its `GRPC_WRITE_NO_COMPRESS`
bit set. Refer to
[`grpc/impl/codegen/compression_types.h`](https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/compression_types.h)),

@ -101,7 +101,7 @@ corresponding reasons. Empty cells denote disallowed transitions.
<td>Shutdown triggered by application.</td>
</tr>
<tr>
<th>FATAL_FAILURE</th>
<th>SHUTDOWN</th>
<td></td>
<td></td>
<td></td>

@ -0,0 +1,91 @@
GRPC C++ STYLE GUIDE
=====================
Background
----------
Here we document style rules for C++ usage in the gRPC C++ bindings
and tests.
General
-------
- The majority of gRPC's C++ requirements are drawn from the [Google C++ style
guide] (https://google.github.io/styleguide/cppguide.html)
- However, gRPC has some additional requirements to maintain
[portability] (#portability)
- As in C, 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).
<a name="portability"></a>
Portability Restrictions
-------------------
gRPC supports a large number of compilers, ranging from those that are
missing many key C++11 features to those that have quite detailed
analysis. As a result, gRPC compiles with a high level of warnings and
treat all warnings as errors. gRPC also forbids the use of some common
C++11 constructs. Here are some guidelines, to be extended as needed:
- Do not use range-based for. Expressions of the form
```c
for (auto& i: vec) {
// code
}
```
are not allowed and should be replaced with code such as
```c
for (auto it = vec.begin; it != vec.end(); it++) {
auto& i = *it;
// code
}
```
- Do not use lambda of any kind (no capture, explicit capture, or
default capture). Other C++ functional features such as
`std::function` or `std::bind` are allowed
- Do not use brace-list initializers.
- Do not compare a pointer to `nullptr` . This is because gcc 4.4
does not support `nullptr` directly and gRPC implements a subset of
its features in [include/grpc++/impl/codegen/config.h]
(../include/grpc++/impl/codegen/config.h). Instead, pointers should
be checked for validity using their implicit conversion to `bool`.
In other words, use `if (p)` rather than `if (p != nullptr)`
- Do not initialize global/static pointer variables to `nullptr`. Just let
the compiler implicitly initialize them to `nullptr` (which it will
definitely do). The reason is that `nullptr` is an actual object in
our implementation rather than just a constant pointer value, so
static/global constructors will be called in a potentially
undesirable sequence.
- Do not use `final` or `override` as these are not supported by some
compilers. Instead use `GRPC_FINAL` and `GRPC_OVERRIDE` . These
compile down to the traditional C++ forms for compilers that support
them but are just elided if the compiler does not support those features.
- In the [include] (../../../tree/master/include/grpc++) and [src]
(../../../tree/master/src/cpp) directory trees, you should also not
use certain STL objects like `std::mutex`, `std::lock_guard`,
`std::unique_lock`, `std::nullptr`, `std::thread` . Instead, use
`grpc::mutex`, `grpc::lock_guard`, etc., which are gRPC
implementations of the prominent features of these objects that are
not always available. You can use the `std` versions of those in [test]
(../../../tree/master/test/cpp)
- Similarly, in the same directories, do not use `std::chrono` unless
it is guarded by `#ifndef GRPC_CXX0X_NO_CHRONO` . For platforms that
lack`std::chrono,` there is a C-language timer called gpr_timespec that can
be used instead.
- `std::unique_ptr` must be used with extreme care in any kind of
collection. For example `vector<std::unique_ptr>` does not work in
gcc 4.4 if the vector is constructed to its full size at
initialization but does work if elements are added to the vector
using functions like `push_back`. `map` and other pair-based
collections do not work with `unique_ptr` under gcc 4.4. The issue
is that many of these collection implementations assume a copy
constructor
to be available.
- Don't use `std::this_thread` . Use `gpr_sleep_until` for sleeping a thread.
- [Some adjacent character combinations cause problems]
(https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C). If declaring a
template against some class relative to the global namespace,
`<::name` will be non-portable. Separate the `<` from the `:` and use `< ::name`.

@ -0,0 +1,15 @@
gRPC Fail Fast Semantics
========================
Fail fast requests allow terminating requests (with status UNAVAILABLE) prior
to the deadline of the request being met.
gRPC implementations of fail fast can terminate requests whenever a channel is
in the TRANSIENT_FAILURE or SHUTDOWN states. If the channel is in any other
state (CONNECTING, READY, or IDLE) the request should not be terminated.
Fail fast SHOULD be the default for gRPC implementations, with an option to
switch to non fail fast.
The opposite of fail fast is 'ignore connectivity'.

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

@ -30,8 +30,7 @@ Clients should accept these arguments:
[ca.pem](https://github.com/grpc/grpc/blob/master/src/core/lib/tsi/test_creds/ca.pem)
as the CA root
* --default_service_account=ACCOUNT_EMAIL
* Email of the GCE default service account. Only applicable
for compute_engine_creds test.
* Email of the GCE default service account.
* --oauth_scope=SCOPE
* OAuth scope. For example, "https://www.googleapis.com/auth/xapi.zoo"
* --service_account_key_file=PATH
@ -68,14 +67,12 @@ control (even if compression is enabled on the channel).
Server features:
* [UnaryCall][]
* [Compressable Payload][]
Procedure:
1. Client calls UnaryCall with:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
@ -85,80 +82,106 @@ Procedure:
Client asserts:
* call was successful
* response payload type is COMPRESSABLE
* response payload body is 314159 bytes in size
* clients are free to assert that the response payload body contents are zero
and comparing the entire response message against a golden response
### large_compressed_unary
This test verifies compressed unary calls succeed in sending messages. It
sends one unary request for every combination of compression algorithm and
payload type.
In all scenarios, whether compression was actually performed is determined by
the compression bit in the response's message flags. The response's compression
value indicates which algorithm was used if said compression bit is set.
### client_compressed_unary
This test verifies the client can compress unary messages by sending two unary
calls, for compressed and uncompressed payloads. It also sends an initial
probing request to verify whether the server supports the [CompressedRequest][]
feature by checking if the probing call fails with an `INVALID_ARGUMENT` status.
Server features:
* [UnaryCall][]
* [Compressable Payload][]
* [Uncompressable Payload][]
* [Random Payload][]
* [CompressedRequest][]
Procedure:
1. Client calls UnaryCall with:
1. Client calls UnaryCall with the feature probe, an *uncompressed* message:
```
{
expect_compressed:{
value: true
}
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
}
```
1. Client calls UnaryCall with the *compressed* message:
```
{
response_compression: <one of {NONE, GZIP, DEFLATE}>
response_type: COMPRESSABLE
expect_compressed:{
value: true
}
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
}
```
Client asserts:
* call was successful
* response payload type is COMPRESSABLE
* response compression is consistent with the requested one.
* if `response_compression == NONE`, the response MUST NOT have the
compressed message flag set.
* if `response_compression != NONE`, the response MUST have the compressed
message flag set.
* response payload body is 314159 bytes in size
* clients are free to assert that the response payload body contents are
zero and comparing the entire response message against a golden response
1. Client calls UnaryCall with the *uncompressed* message:
2. Client calls UnaryCall with:
```
{
response_compression: <one of {NONE, GZIP, DEFLATE}>
response_type: UNCOMPRESSABLE
expect_compressed:{
value: false
}
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
}
```
Client asserts:
* call was successful
* response payload type is UNCOMPRESSABLE
* response compression is consistent with the requested one.
* the response MUST NOT have the compressed message flag set.
* response payload body is 314159 bytes in size
* clients are free to assert that the response payload body contents are
identical to the golden uncompressable data at `test/cpp/interop/rnd.dat`.
* First call failed with `INVALID_ARGUMENT` status.
* Subsequent calls were successful.
* Response payload body is 314159 bytes in size.
* Clients are free to assert that the response payload body contents are
zeros and comparing the entire response message against a golden response.
### server_compressed_unary
This test verifies the server can compress unary messages. It sends two unary
requests, expecting the server's response to be compressed or not according to
the `response_compressed` boolean.
Whether compression was actually performed is determined by the compression bit
in the response's message flags. *Note that some languages may not have access
to the message flags*.
Server features:
* [UnaryCall][]
* [CompressedResponse][]
Procedure:
1. Client calls UnaryCall with `SimpleRequest`:
3. Client calls UnaryCall with:
```
{
response_compression: <one of {NONE, GZIP, DEFLATE}>
response_type: RANDOM
response_compressed:{
value: true
}
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
}
```
```
{
response_compressed:{
value: false
}
response_size: 314159
payload:{
body: 271828 bytes of zeros
@ -167,9 +190,14 @@ Procedure:
```
Client asserts:
* call was successful
* response payload type is either COMPRESSABLE or UNCOMPRESSABLE
* the behavior is consistent with the randomly chosen incoming payload type,
as described in their respective sections.
* when `response_compressed` is true, the response MUST have the
compressed message flag set.
* when `response_compressed` is false, the response MUST NOT have
the compressed message flag set.
* response payload body is 314159 bytes in size in both cases.
* clients are free to assert that the response payload body contents are
zero and comparing the entire response message against a golden response
### client_streaming
@ -177,7 +205,6 @@ This test verifies that client-only streaming succeeds.
Server features:
* [StreamingInputCall][]
* [Compressable Payload][]
Procedure:
1. Client calls StreamingInputCall
@ -227,96 +254,76 @@ Client asserts:
* call was successful
* response aggregated_payload_size is 74922
### server_streaming
This test verifies that server-only streaming succeeds.
### client_compressed_streaming
Server features:
* [StreamingOutputCall][]
* [Compressable Payload][]
This test verifies the client can compress requests on per-message basis by
performing a two-request streaming call. It also sends an initial probing
request to verify whether the server supports the [CompressedRequest][] feature
by checking if the probing call fails with an `INVALID_ARGUMENT` status.
Procedure:
1. Client calls StreamingOutputCall with:
1. Client calls `StreamingInputCall` and sends the following feature-probing
*uncompressed* `StreamingInputCallRequest` message
```
{
response_type:COMPRESSABLE
response_parameters:{
size: 31415
}
response_parameters:{
size: 9
expect_compressed:{
value: true
}
response_parameters:{
size: 2653
}
response_parameters:{
size: 58979
payload:{
body: 27182 bytes of zeros
}
}
```
If the call fails with `INVALID_ARGUMENT`, the test fails. Otherwise, we
continue.
Client asserts:
* call was successful
* exactly four responses
* response payloads are COMPRESSABLE
* response payload bodies are sized (in order): 31415, 9, 2653, 58979
* clients are free to assert that the response payload body contents are zero
and comparing the entire response messages against golden responses
### server_compressed_streaming
This test verifies that server-only compressed streaming succeeds.
Server features:
* [StreamingOutputCall][]
* [Compressable Payload][]
* [Uncompressable Payload][]
* [Random Payload][]
Procedure:
1. Client calls StreamingOutputCall with:
1. Client calls `StreamingInputCall` again, sending the *compressed* message
```
{
response_compression: <one of {NONE, GZIP, DEFLATE}>
response_type:COMPRESSABLE
response_parameters:{
size: 31415
expect_compressed:{
value: true
}
response_parameters:{
size: 9
payload:{
body: 27182 bytes of zeros
}
response_parameters:{
size: 2653
}
response_parameters:{
size: 58979
```
1. And finally, the *uncompressed* message
```
{
expect_compressed:{
value: false
}
payload:{
body: 45904 bytes of zeros
}
}
```
1. Client half-closes
Client asserts:
* call was successful
* exactly four responses
* response payloads are COMPRESSABLE
* response compression is consistent with the requested one.
* if `response_compression == NONE`, the response MUST NOT have the
compressed message flag set.
* if `response_compression != NONE`, the response MUST have the compressed
message flag set.
* response payload bodies are sized (in order): 31415, 9, 2653, 58979
* clients are free to assert that the response payload body contents are
zero and comparing the entire response messages against golden responses
* First call fails with `INVALID_ARGUMENT`.
* Next calls succeeds.
* Response aggregated payload size is 73086.
2. Client calls StreamingOutputCall with:
### server_streaming
This test verifies that server-only streaming succeeds.
Server features:
* [StreamingOutputCall][]
Procedure:
1. Client calls StreamingOutputCall with `StreamingOutputCallRequest`:
```
{
response_compression: <one of {NONE, GZIP, DEFLATE}>
response_type:UNCOMPRESSABLE
response_parameters:{
size: 31415
}
@ -335,40 +342,51 @@ Procedure:
Client asserts:
* call was successful
* exactly four responses
* response payloads are UNCOMPRESSABLE
* response compressions are consistent with the requested one.
* the responses MUST NOT have the compressed message flag set.
* response payload bodies are sized (in order): 31415, 9, 2653, 58979
* clients are free to assert that the body of the responses are identical to
the golden uncompressable data at `test/cpp/interop/rnd.dat`.
* clients are free to assert that the response payload body contents are zero
and comparing the entire response messages against golden responses
### server_compressed_streaming
This test verifies that the server can compress streaming messages and disable
compression on individual messages.
3. Client calls StreamingOutputCall with:
Server features:
* [StreamingOutputCall][]
* [CompressedResponse][]
Procedure:
1. Client calls StreamingOutputCall with `StreamingOutputCallRequest`:
```
{
response_compression: <one of {NONE, GZIP, DEFLATE}>
response_type:RANDOM
response_parameters:{
size: 31415
compressed: {
value: true
}
response_parameters:{
size: 9
size: 31415
}
response_parameters:{
size: 2653
compressed: {
value: false
}
response_parameters:{
size: 58979
size: 92653
}
}
```
Client asserts:
* call was successful
* response payload type is either COMPRESSABLE or UNCOMPRESSABLE
* the behavior is consistent with the randomly chosen incoming payload type,
as described in their respective sections.
* exactly two responses
* when `response_compressed` is false, the response's messages MUST
NOT have the compressed message flag set.
* when `response_compressed` is true, the response's messages MUST
have the compressed message flag set.
* response payload bodies are sized (in order): 31415, 92653
* clients are free to assert that the response payload body contents are
zero and comparing the entire response messages against golden responses
### ping_pong
@ -376,14 +394,12 @@ This test verifies that full duplex bidi is supported.
Server features:
* [FullDuplexCall][]
* [Compressable Payload][]
Procedure:
1. Client calls FullDuplexCall with:
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 31415
}
@ -397,7 +413,6 @@ Procedure:
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 9
}
@ -411,7 +426,6 @@ Procedure:
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 2653
}
@ -425,7 +439,6 @@ Procedure:
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 58979
}
@ -440,7 +453,6 @@ Procedure:
Client asserts:
* call was successful
* exactly four responses
* response payloads are COMPRESSABLE
* response payload bodies are sized (in order): 31415, 9, 2653, 58979
* clients are free to assert that the response payload body contents are zero
and comparing the entire response messages against golden responses
@ -470,12 +482,12 @@ with desired oauth scope.
The test uses `--default_service_account` with GCE service account email and
`--oauth_scope` with the OAuth scope to use. For testing against
grpc-test.sandbox.googleapis.com, "https://www.googleapis.com/auth/xapi.zoo" should
grpc-test.sandbox.googleapis.com, "https://www.googleapis.com/auth/xapi.zoo"
should
be passed in as `--oauth_scope`.
Server features:
* [UnaryCall][]
* [Compressable Payload][]
* [Echo Authenticated Username][]
* [Echo OAuth Scope][]
@ -485,7 +497,6 @@ Procedure:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
@ -497,7 +508,8 @@ Procedure:
Client asserts:
* call was successful
* received SimpleResponse.username equals the value of `--default_service_account` flag
* received SimpleResponse.username equals the value of
`--default_service_account` flag
* received SimpleResponse.oauth_scope is in `--oauth_scope`
* response payload body is 314159 bytes in size
* clients are free to assert that the response payload body contents are zero
@ -518,7 +530,6 @@ variable GOOGLE_APPLICATION_CREDENTIALS.
Server features:
* [UnaryCall][]
* [Compressable Payload][]
* [Echo Authenticated Username][]
* [Echo OAuth Scope][]
@ -528,7 +539,6 @@ Procedure:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
@ -541,7 +551,8 @@ Client asserts:
* call was successful
* received SimpleResponse.username is not empty and is in the json key file used
by the auth library. The client can optionally check the username matches the
email address in the key file or equals the value of `--default_service_account` flag.
email address in the key file or equals the value of `--default_service_account`
flag.
* response payload body is 314159 bytes in size
* clients are free to assert that the response payload body contents are zero
and comparing the entire response message against a golden response
@ -567,18 +578,18 @@ variable GOOGLE_APPLICATION_CREDENTIALS, *OR* if GCE credentials is used to
fetch the token, `--default_service_account` can be used to pass in GCE service
account email.
- uses the flag `--oauth_scope` for the oauth scope. For testing against
grpc-test.sandbox.googleapis.com, "https://www.googleapis.com/auth/xapi.zoo" should
be passed as the `--oauth_scope`.
grpc-test.sandbox.googleapis.com, "https://www.googleapis.com/auth/xapi.zoo"
should be passed as the `--oauth_scope`.
Server features:
* [UnaryCall][]
* [Compressable Payload][]
* [Echo Authenticated Username][]
* [Echo OAuth Scope][]
Procedure:
1. Client uses the auth library to obtain an authorization token
2. Client configures the channel to use AccessTokenCredentials with the access token obtained in step 1
2. Client configures the channel to use AccessTokenCredentials with the access
token obtained in step 1
3. Client calls UnaryCall with the following message
```
@ -599,8 +610,8 @@ json key file or GCE default service account email.
Similar to the other auth tests, this test is only for cloud-to-prod path.
This test verifies unary calls succeed in sending messages using a JWT or a service account
credentials set on the RPC.
This test verifies unary calls succeed in sending messages using a JWT or a
service account credentials set on the RPC.
The test
- uses the flag `--service_account_key_file` with the path to a json key file
@ -614,7 +625,6 @@ against grpc-test.sandbox.googleapis.com, oauth scope
Server features:
* [UnaryCall][]
* [Compressable Payload][]
* [Echo Authenticated Username][]
* [Echo OAuth Scope][]
@ -645,7 +655,6 @@ by the server.
Server features:
* [UnaryCall][]
* [FullDuplexCall][]
* [Compressable Payload][]
* [Echo Metadata][]
Procedure:
@ -660,7 +669,6 @@ Procedure:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
@ -679,7 +687,6 @@ Procedure:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
@ -785,14 +792,12 @@ from the server.
Server features:
* [FullDuplexCall][]
* [Compressable Payload][]
Procedure:
1. Client starts FullDuplexCall with
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 31415
}
@ -932,9 +937,24 @@ Server implements EmptyCall which immediately returns the empty message.
[UnaryCall]: #unarycall
Server implements UnaryCall which immediately returns a SimpleResponse with a
payload body of size SimpleRequest.response_size bytes and type as appropriate
for the SimpleRequest.response_type. If the server does not support the
response_type, then it should fail the RPC with INVALID_ARGUMENT.
payload body of size `SimpleRequest.response_size` bytes and type as appropriate
for the `SimpleRequest.response_type`. If the server does not support the
`response_type`, then it should fail the RPC with `INVALID_ARGUMENT`.
### CompressedResponse
[CompressedResponse]: #compressedresponse
When the client sets `response_compressed` to true, the server's response is
sent back compressed. Note that `response_compressed` is present on both
`SimpleRequest` (unary) and `StreamingOutputCallRequest` (streaming).
### CompressedRequest
[CompressedRequest]: #compressedrequest
When the client sets `expect_compressed` to true, the server expects the client
request to be compressed. If it's not, it fails the RPC with `INVALID_ARGUMENT`.
Note that `response_compressed` is present on both `SimpleRequest` (unary) and
`StreamingOutputCallRequest` (streaming).
### StreamingInputCall
[StreamingInputCall]: #streaminginputcall
@ -947,8 +967,8 @@ request payload bodies received.
[StreamingOutputCall]: #streamingoutputcall
Server implements StreamingOutputCall by replying, in order, with one
StreamingOutputCallResponses for each ResponseParameters in
StreamingOutputCallRequest. Each StreamingOutputCallResponses should have a
StreamingOutputCallResponse for each ResponseParameters in
StreamingOutputCallRequest. Each StreamingOutputCallResponse should have a
payload body of size ResponseParameters.size bytes, as specified by its
respective ResponseParameters. After sending all responses, it closes with OK.
@ -956,34 +976,12 @@ respective ResponseParameters. After sending all responses, it closes with OK.
[FullDuplexCall]: #fullduplexcall
Server implements FullDuplexCall by replying, in order, with one
StreamingOutputCallResponses for each ResponseParameters in each
StreamingOutputCallRequest. Each StreamingOutputCallResponses should have a
StreamingOutputCallResponse for each ResponseParameters in each
StreamingOutputCallRequest. Each StreamingOutputCallResponse should have a
payload body of size ResponseParameters.size bytes, as specified by its
respective ResponseParameters. After receiving half close and sending all
responses, it closes with OK.
### Compressable Payload
[Compressable Payload]: #compressable-payload
When the client requests COMPRESSABLE payload, the response includes a payload
of the size requested containing all zeros and the payload type is
COMPRESSABLE.
### Uncompressable Payload
[Uncompressable Payload]: #uncompressable-payload
When the client requests UNCOMPRESSABLE payload, the response includes a payload
of the size requested containing uncompressable data and the payload type is
UNCOMPRESSABLE. A 512 kB dump from /dev/urandom is the current golden data,
stored at `test/cpp/interop/rnd.dat`
### Random Payload
[Random Payload]: #random-payload
When the client requests RANDOM payload, the response includes either a randomly
chosen COMPRESSABLE or UNCOMPRESSABLE payload. The data and the payload type
will be consistent with this choice.
### Echo Status
[Echo Status]: #echo-status
When the client sends a response_status in the request payload, the server closes
@ -1004,8 +1002,8 @@ key and the corresponding value back to the client as trailing metadata.
[Observe ResponseParameters.interval_us]: #observe-responseparametersinterval_us
In StreamingOutputCall and FullDuplexCall, server delays sending a
StreamingOutputCallResponse by the ResponseParameters's interval_us for that
particular response, relative to the last response sent. That is, interval_us
StreamingOutputCallResponse by the ResponseParameters's `interval_us` for that
particular response, relative to the last response sent. That is, `interval_us`
acts like a sleep *before* sending the response and accumulates from one
response to the next.
@ -1027,13 +1025,13 @@ an email address.
#### Echo OAuth scope
[Echo OAuth Scope]: #echo-oauth-scope
If a SimpleRequest has fill_oauth_scope=true and that request was successfully
If a SimpleRequest has `fill_oauth_scope=true` and that request was successfully
authenticated via OAuth, then the SimpleResponse should have oauth_scope filled
with the scope of the method being invoked.
Although a general server-side feature, most test servers won't implement this
feature. The TLS server grpc-test.sandbox.googleapis.com:443 supports this feature.
It requires at least the OAuth scope
feature. The TLS server `grpc-test.sandbox.googleapis.com:443` supports this
feature. It requires at least the OAuth scope
`https://www.googleapis.com/auth/xapi.zoo` for authentication to succeed.
Discussion:

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

@ -16,8 +16,6 @@ Here, scheme indicates the name-system to be used. Example schemes to be support
* `dns`
* `zookeeper`
* `etcd`
Authority indicates some scheme-specific bootstrap information, e.g., for DNS, the authority may include the IP[:port] of the DNS server to use. Often, a DNS name may used as the authority, since the ability to resolve DNS names is already built into all gRPC client libraries.
@ -30,23 +28,3 @@ The gRPC client library will switch on the scheme to pick the right resolver plu
Resolvers should be able to contact the authority and get a resolution that they return back to the gRPC client library. The returned contents include a list of IP:port, an optional config and optional auth config data to be used for channel authentication. The plugin API allows the resolvers to continuously watch an endpoint_name and return updated resolutions as needed.
## Zookeeper
Apache [ZooKeeper](https://zookeeper.apache.org/) is a popular solution for building name-systems. Curator is a service discovery system built on to of ZooKeeper. We propose to organize names hierarchically as `/path/service/instance` similar to Apache Curator.
A fully-qualified ZooKeeper name used to construct a gRPC channel will look as follows:
```
zookeeper://host:port/path/service/instance
```
Here `zookeeper` is the scheme identifying the name-system. `host:port` identifies an authoritative name-server for this scheme (i.e., a Zookeeper server). The host can be an IP address or a DNS name.
Finally `/path/service/instance` is the Zookeeper name to be resolved.
## Service Registration
Service providers can register their services in Zookeeper by using a Zookeeper client.
Each service is a zookeeper node, and each instance is a child node of the corresponding service. For example, a MySQL service may have multiple instances, `/mysql/1`, `/mysql/2`, `/mysql/3`. The name of the service or instance, as well as an optional path is specified by the service provider.
The data in service nodes is empty. Each instance node stores its address in the format of `host:port`, where host can be either hostname or IP address.

@ -18,9 +18,12 @@ 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 |
| Request cardinality violation (method requires exactly one request but client sent some other number of requests) | UNIMPLEMENTED | Server|
| Response cardinality violation (method requires exactly one response but server sent some other number of responses) | UNIMPLEMENTED | Client|
| Error parsing response proto | INTERNAL | Client|
| Error parsing request proto | INTERNAL | Server|

File diff suppressed because it is too large Load Diff

@ -14,7 +14,7 @@ following command:
```sh
$ git clone https://github.com/grpc/grpc.git
$ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc
```
Change your current directory to examples/cpp/helloworld

@ -20,7 +20,7 @@ With gRPC we can define our service once in a .proto file and implement clients
The example code for our tutorial is in [examples/cpp/route_guide](route_guide). To download the example, clone this repository by running the following command:
```shell
$ git clone https://github.com/grpc/grpc.git
$ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc
```
Then change your current directory to `examples/cpp/route_guide`:

@ -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 -lgrpc++_unsecure -lgrpc -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)`
@ -41,7 +51,7 @@ PROTOS_PATH = ../../protos
vpath %.proto $(PROTOS_PATH)
all: system-check greeter_client greeter_server greeter_async_client greeter_async_server
all: system-check greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server
greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o
$(CXX) $^ $(LDFLAGS) -o $@
@ -52,6 +62,9 @@ greeter_server: helloworld.pb.o helloworld.grpc.pb.o greeter_server.o
greeter_async_client: helloworld.pb.o helloworld.grpc.pb.o greeter_async_client.o
$(CXX) $^ $(LDFLAGS) -o $@
greeter_async_client2: helloworld.pb.o helloworld.grpc.pb.o greeter_async_client2.o
$(CXX) $^ $(LDFLAGS) -o $@
greeter_async_server: helloworld.pb.o helloworld.grpc.pb.o greeter_async_server.o
$(CXX) $^ $(LDFLAGS) -o $@
@ -64,7 +77,7 @@ greeter_async_server: helloworld.pb.o helloworld.grpc.pb.o greeter_async_server.
$(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $<
clean:
rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server greeter_async_client greeter_async_server
rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server
# The following is to test your system and ensure a smoother experience.
@ -94,7 +107,7 @@ ifneq ($(HAS_VALID_PROTOC),true)
@echo "Please install Google protocol buffers 3.0.0 and its compiler."
@echo "You can find it here:"
@echo
@echo " https://github.com/google/protobuf/releases/tag/v3.0.0-beta-2"
@echo " https://github.com/google/protobuf/releases/tag/v3.0.0-beta-3.3"
@echo
@echo "Here is what I get when trying to evaluate your version of protoc:"
@echo

@ -12,7 +12,7 @@ following command:
```sh
$ git clone https://github.com/grpc/grpc.git
$ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc
```
Change your current directory to examples/cpp/helloworld

@ -53,7 +53,7 @@ class GreeterClient {
explicit GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
// Assambles the client's payload, sends it and presents the response back
// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) {
// Data we are sending to the server.
@ -74,9 +74,9 @@ class GreeterClient {
// Storage for the status of the RPC upon completion.
Status status;
// stub_->AsyncSayHello() perform the RPC call, returning an instance we
// store in "rpc". Because we are using the asynchronous API, we need the
// hold on to the "rpc" instance in order to get updates on the ongoig RPC.
// stub_->AsyncSayHello() performs the RPC call, returning an instance we
// store in "rpc". Because we are using the asynchronous API, we need to
// hold on to the "rpc" instance in order to get updates on the ongoing RPC.
std::unique_ptr<ClientAsyncResponseReader<HelloReply> > rpc(
stub_->AsyncSayHello(&context, request, &cq));
@ -87,7 +87,9 @@ class GreeterClient {
void* got_tag;
bool ok = false;
// Block until the next result is available in the completion queue "cq".
cq.Next(&got_tag, &ok);
// The return value of Next should always be checked. This return value
// tells us whether there is any kind of event or the cq_ is shutting down.
GPR_ASSERT(cq.Next(&got_tag, &ok));
// Verify that the result from "cq" corresponds, by its tag, our previous
// request.

@ -0,0 +1,153 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <memory>
#include <string>
#include <grpc++/grpc++.h>
#include <thread>
#include "helloworld.grpc.pb.h"
using grpc::Channel;
using grpc::ClientAsyncResponseReader;
using grpc::ClientContext;
using grpc::CompletionQueue;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
class GreeterClient {
public:
explicit GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
// Assembles the client's payload and sends it to the server.
void SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request;
request.set_name(user);
// Call object to store rpc data
AsyncClientCall* call = new AsyncClientCall;
// stub_->AsyncSayHello() performs the RPC call, returning an instance to
// store in "call". Because we are using the asynchronous API, we need to
// hold on to the "call" instance in order to get updates on the ongoing RPC.
call->response_reader = stub_->AsyncSayHello(&call->context, request, &cq_);
// Request that, upon completion of the RPC, "reply" be updated with the
// server's response; "status" with the indication of whether the operation
// was successful. Tag the request with the memory address of the call object.
call->response_reader->Finish(&call->reply, &call->status, (void*)call);
}
// Loop while listening for completed responses.
// Prints out the response from the server.
void AsyncCompleteRpc() {
void* got_tag;
bool ok = false;
// Block until the next result is available in the completion queue "cq".
while (cq_.Next(&got_tag, &ok)) {
// The tag in this example is the memory location of the call object
AsyncClientCall* call = static_cast<AsyncClientCall*>(got_tag);
// Verify that the request was completed successfully. Note that "ok"
// corresponds solely to the request for updates introduced by Finish().
GPR_ASSERT(ok);
if (call->status.ok())
std::cout << "Greeter received: " << call->reply.message() << std::endl;
else
std::cout << "RPC failed" << std::endl;
// Once we're complete, deallocate the call object.
delete call;
}
}
private:
// struct for keeping state and data information
struct AsyncClientCall {
// Container for the data we expect from the server.
HelloReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
// Storage for the status of the RPC upon completion.
Status status;
std::unique_ptr<ClientAsyncResponseReader<HelloReply>> response_reader;
};
// Out of the passed in Channel comes the stub, stored here, our view of the
// server's exposed services.
std::unique_ptr<Greeter::Stub> stub_;
// The producer-consumer queue we use to communicate asynchronously with the
// gRPC runtime.
CompletionQueue cq_;
};
int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// are created. This channel models a connection to an endpoint (in this case,
// localhost at port 50051). We indicate that the channel isn't authenticated
// (use of InsecureChannelCredentials()).
GreeterClient greeter(grpc::CreateChannel(
"localhost:50051", grpc::InsecureChannelCredentials()));
// Spawn reader thread that loops indefinitely
std::thread thread_ = std::thread(&GreeterClient::AsyncCompleteRpc, &greeter);
for (int i = 0; i < 100; i++) {
std::string user("world " + std::to_string(i));
greeter.SayHello(user); // The actual RPC call!
}
std::cout << "Press control-c to quit" << std::endl << std::endl;
thread_.join(); //blocks forever
return 0;
}

@ -160,7 +160,9 @@ class ServerImpl final {
// Block waiting to read the next event from the completion queue. The
// event is uniquely identified by its tag, which in this case is the
// memory address of a CallData instance.
cq_->Next(&tag, &ok);
// The return value of Next should always be checked. This return value
// tells us whether there is any kind of event or cq_ is shutting down.
GPR_ASSERT(cq_->Next(&tag, &ok));
GPR_ASSERT(ok);
static_cast<CallData*>(tag)->Proceed();
}

@ -72,6 +72,8 @@ class GreeterClient {
if (status.ok()) {
return reply.message();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}

@ -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 -lgrpc++_unsecure -lgrpc -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)`
@ -86,7 +96,7 @@ ifneq ($(HAS_VALID_PROTOC),true)
@echo "Please install Google protocol buffers 3.0.0 and its compiler."
@echo "You can find it here:"
@echo
@echo " https://github.com/google/protobuf/releases/tag/v3.0.0-beta-2"
@echo " https://github.com/google/protobuf/releases/tag/v3.0.0-beta-3.3"
@echo
@echo "Here is what I get when trying to evaluate your version of protoc:"
@echo

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Grpc.Tools" version="0.13.1" />
<package id="Grpc.Tools" version="0.15.0" />
</packages>

@ -10,7 +10,7 @@
<RootNamespace>Greeter</RootNamespace>
<AssemblyName>Greeter</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<NuGetPackageImportStamp>96275748</NuGetPackageImportStamp>
<NuGetPackageImportStamp>2669b4f2</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -33,11 +33,11 @@
<ItemGroup>
<Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
<HintPath>..\packages\Grpc.Core.0.15.0\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@ -61,11 +61,11 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
<Import Project="..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
<Error Condition="!Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets'))" />
</Target>
</Project>

@ -31,9 +31,9 @@ namespace Helloworld {
"cm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
new pbr::GeneratedCodeInfo(typeof(global::Helloworld.HelloRequest), global::Helloworld.HelloRequest.Parser, new[]{ "Name" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Helloworld.HelloReply), global::Helloworld.HelloReply.Parser, new[]{ "Message" }, null, null, null)
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloRequest), global::Helloworld.HelloRequest.Parser, new[]{ "Name" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloReply), global::Helloworld.HelloReply.Parser, new[]{ "Message" }, null, null, null)
}));
}
#endregion
@ -76,7 +76,7 @@ namespace Helloworld {
public string Name {
get { return name_; }
set {
name_ = pb::Preconditions.CheckNotNull(value, "value");
name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
@ -182,7 +182,7 @@ namespace Helloworld {
public string Message {
get { return message_; }
set {
message_ = pb::Preconditions.CheckNotNull(value, "value");
message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}

@ -1,5 +1,35 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: helloworld.proto
// Original file comments:
// 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.
//
#region Designer generated code
using System;
@ -8,6 +38,9 @@ using System.Threading.Tasks;
using Grpc.Core;
namespace Helloworld {
/// <summary>
/// The greeting service definition.
/// </summary>
public static class Greeter
{
static readonly string __ServiceName = "helloworld.Greeter";
@ -22,66 +55,87 @@ namespace Helloworld {
__Marshaller_HelloRequest,
__Marshaller_HelloReply);
// service descriptor
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Helloworld.HelloworldReflection.Descriptor.Services[0]; }
}
// client interface
public interface IGreeterClient
/// <summary>Base class for server-side implementations of Greeter</summary>
public abstract class GreeterBase
{
global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options);
AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options);
/// <summary>
/// Sends a greeting
/// </summary>
public virtual global::System.Threading.Tasks.Task<global::Helloworld.HelloReply> SayHello(global::Helloworld.HelloRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
// server-side interface
public interface IGreeter
{
Task<global::Helloworld.HelloReply> SayHello(global::Helloworld.HelloRequest request, ServerCallContext context);
}
// client stub
public class GreeterClient : ClientBase, IGreeterClient
/// <summary>Client for Greeter</summary>
public class GreeterClient : ClientBase<GreeterClient>
{
/// <summary>Creates a new client for Greeter</summary>
/// <param name="channel">The channel to use to make remote calls.</param>
public GreeterClient(Channel channel) : base(channel)
{
}
public global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
/// <summary>Creates a new client for Greeter that uses a custom <c>CallInvoker</c>.</summary>
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
public GreeterClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_SayHello, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options)
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected GreeterClient() : base()
{
var call = CreateCall(__Method_SayHello, options);
return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
/// <summary>Protected constructor to allow creation of configured clients.</summary>
/// <param name="configuration">The client configuration.</param>
protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_SayHello, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options)
/// <summary>
/// Sends a greeting
/// </summary>
public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_SayHello, options);
return Calls.AsyncUnaryCall(call, request);
return SayHello(request, new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// Sends a greeting
/// </summary>
public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request);
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(IGreeter serviceImpl)
/// <summary>
/// Sends a greeting
/// </summary>
public virtual AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_SayHello, serviceImpl.SayHello).Build();
return SayHelloAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// Sends a greeting
/// </summary>
public virtual AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request);
}
protected override GreeterClient NewInstance(ClientBaseConfiguration configuration)
{
return new GreeterClient(configuration);
}
}
// creates a new client
public static GreeterClient NewClient(Channel channel)
/// <summary>Creates service definition that can be registered with a server</summary>
public static ServerServiceDefinition BindService(GreeterBase serviceImpl)
{
return new GreeterClient(channel);
return ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_SayHello, serviceImpl.SayHello).Build();
}
}

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
<package id="Grpc" version="0.13.1" targetFramework="net45" />
<package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
<package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
<package id="Grpc" version="0.15.0" targetFramework="net45" />
<package id="Grpc.Core" version="0.15.0" targetFramework="net45" />
<package id="Ix-Async" version="1.2.5" targetFramework="net45" />
</packages>

@ -10,7 +10,7 @@
<RootNamespace>GreeterClient</RootNamespace>
<AssemblyName>GreeterClient</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<NuGetPackageImportStamp>d94f6f5f</NuGetPackageImportStamp>
<NuGetPackageImportStamp>5e942a7d</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -33,11 +33,11 @@
<ItemGroup>
<Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
<HintPath>..\packages\Grpc.Core.0.15.0\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@ -59,11 +59,11 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
<Import Project="..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
<Error Condition="!Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets'))" />
</Target>
</Project>

@ -39,7 +39,7 @@ namespace GreeterClient
{
Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
var client = Greeter.NewClient(channel);
var client = new Greeter.GreeterClient(channel);
String user = "you";
var reply = client.SayHello(new HelloRequest { Name = user });

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
<package id="Grpc" version="0.13.1" targetFramework="net45" />
<package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
<package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
<package id="Grpc" version="0.15.0" targetFramework="net45" />
<package id="Grpc.Core" version="0.15.0" targetFramework="net45" />
<package id="Ix-Async" version="1.2.5" targetFramework="net45" />
</packages>

@ -10,7 +10,7 @@
<RootNamespace>GreeterServer</RootNamespace>
<AssemblyName>GreeterServer</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<NuGetPackageImportStamp>6f89e9f2</NuGetPackageImportStamp>
<NuGetPackageImportStamp>9c7b2963</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -33,11 +33,11 @@
<ItemGroup>
<Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
<HintPath>..\packages\Grpc.Core.0.15.0\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@ -59,11 +59,11 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
<Import Project="..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
<Error Condition="!Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets'))" />
</Target>
</Project>

@ -34,10 +34,10 @@ using Helloworld;
namespace GreeterServer
{
class GreeterImpl : Greeter.IGreeter
class GreeterImpl : Greeter.GreeterBase
{
// Server side handler of the SayHello RPC
public Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
}

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
<package id="Grpc" version="0.13.1" targetFramework="net45" />
<package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
<package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
<package id="Grpc" version="0.15.0" targetFramework="net45" />
<package id="Grpc.Core" version="0.15.0" targetFramework="net45" />
<package id="Ix-Async" version="1.2.5" targetFramework="net45" />
</packages>

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

@ -1,3 +1,32 @@
@rem Copyright 2016, Google Inc.
@rem All rights reserved.
@rem
@rem Redistribution and use in source and binary forms, with or without
@rem modification, are permitted provided that the following conditions are
@rem met:
@rem
@rem * Redistributions of source code must retain the above copyright
@rem notice, this list of conditions and the following disclaimer.
@rem * Redistributions in binary form must reproduce the above
@rem copyright notice, this list of conditions and the following disclaimer
@rem in the documentation and/or other materials provided with the
@rem distribution.
@rem * Neither the name of Google Inc. nor the names of its
@rem contributors may be used to endorse or promote products derived from
@rem this software without specific prior written permission.
@rem
@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@rem Generate the C# code for .proto files
setlocal
@ -5,7 +34,7 @@ setlocal
@rem enter this directory
cd /d %~dp0
set TOOLS_PATH=packages\Grpc.Tools.0.13.1\tools\windows_x86
set TOOLS_PATH=packages\Grpc.Tools.0.15.0\tools\windows_x86
%TOOLS_PATH%\protoc.exe -I../../protos --csharp_out Greeter ../../protos/helloworld.proto --grpc_out Greeter --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Grpc.Tools" version="0.13.1" />
<package id="Grpc.Tools" version="0.15.0" />
</packages>

@ -41,12 +41,12 @@ namespace Routeguide {
"ZUIPUm91dGVHdWlkZVByb3RvUAGiAgNSVEdiBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
new pbr::GeneratedCodeInfo(typeof(global::Routeguide.Point), global::Routeguide.Point.Parser, new[]{ "Latitude", "Longitude" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Routeguide.Rectangle), global::Routeguide.Rectangle.Parser, new[]{ "Lo", "Hi" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Routeguide.Feature), global::Routeguide.Feature.Parser, new[]{ "Name", "Location" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Routeguide.RouteNote), global::Routeguide.RouteNote.Parser, new[]{ "Location", "Message" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Routeguide.RouteSummary), global::Routeguide.RouteSummary.Parser, new[]{ "PointCount", "FeatureCount", "Distance", "ElapsedTime" }, null, null, null)
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.Point), global::Routeguide.Point.Parser, new[]{ "Latitude", "Longitude" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.Rectangle), global::Routeguide.Rectangle.Parser, new[]{ "Lo", "Hi" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.Feature), global::Routeguide.Feature.Parser, new[]{ "Name", "Location" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.RouteNote), global::Routeguide.RouteNote.Parser, new[]{ "Location", "Message" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Routeguide.RouteSummary), global::Routeguide.RouteSummary.Parser, new[]{ "PointCount", "FeatureCount", "Distance", "ElapsedTime" }, null, null, null)
}));
}
#endregion
@ -383,7 +383,7 @@ namespace Routeguide {
public string Name {
get { return name_; }
set {
name_ = pb::Preconditions.CheckNotNull(value, "value");
name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
@ -541,7 +541,7 @@ namespace Routeguide {
public string Message {
get { return message_; }
set {
message_ = pb::Preconditions.CheckNotNull(value, "value");
message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}

@ -11,7 +11,7 @@
<AssemblyName>RouteGuide</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>e1e648e7</NuGetPackageImportStamp>
<NuGetPackageImportStamp>de2137f9</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -33,11 +33,11 @@
<ItemGroup>
<Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
<HintPath>..\packages\Grpc.Core.0.15.0\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@ -74,12 +74,12 @@
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
<Import Project="..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
<Error Condition="!Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

@ -1,5 +1,35 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: route_guide.proto
// Original file comments:
// 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.
//
#region Designer generated code
using System;
@ -8,6 +38,9 @@ using System.Threading.Tasks;
using Grpc.Core;
namespace Routeguide {
/// <summary>
/// Interface exported by the server.
/// </summary>
public static class RouteGuide
{
static readonly string __ServiceName = "routeguide.RouteGuide";
@ -46,110 +79,216 @@ namespace Routeguide {
__Marshaller_RouteNote,
__Marshaller_RouteNote);
// service descriptor
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Routeguide.RouteGuideReflection.Descriptor.Services[0]; }
}
// client interface
public interface IRouteGuideClient
/// <summary>Base class for server-side implementations of RouteGuide</summary>
public abstract class RouteGuideBase
{
global::Routeguide.Feature GetFeature(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
global::Routeguide.Feature GetFeature(global::Routeguide.Point request, CallOptions options);
AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, CallOptions options);
AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, CallOptions options);
AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(CallOptions options);
AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(CallOptions options);
/// <summary>
/// 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.
/// </summary>
public virtual global::System.Threading.Tasks.Task<global::Routeguide.Feature> GetFeature(global::Routeguide.Point request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
/// <summary>
/// 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.
/// </summary>
public virtual global::System.Threading.Tasks.Task ListFeatures(global::Routeguide.Rectangle request, IServerStreamWriter<global::Routeguide.Feature> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
// server-side interface
public interface IRouteGuide
/// <summary>
/// A client-to-server streaming RPC.
///
/// Accepts a stream of Points on a route being traversed, returning a
/// RouteSummary when traversal is completed.
/// </summary>
public virtual global::System.Threading.Tasks.Task<global::Routeguide.RouteSummary> RecordRoute(IAsyncStreamReader<global::Routeguide.Point> requestStream, ServerCallContext context)
{
Task<global::Routeguide.Feature> GetFeature(global::Routeguide.Point request, ServerCallContext context);
Task ListFeatures(global::Routeguide.Rectangle request, IServerStreamWriter<global::Routeguide.Feature> responseStream, ServerCallContext context);
Task<global::Routeguide.RouteSummary> RecordRoute(IAsyncStreamReader<global::Routeguide.Point> requestStream, ServerCallContext context);
Task RouteChat(IAsyncStreamReader<global::Routeguide.RouteNote> requestStream, IServerStreamWriter<global::Routeguide.RouteNote> responseStream, ServerCallContext context);
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
// client stub
public class RouteGuideClient : ClientBase, IRouteGuideClient
/// <summary>
/// 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).
/// </summary>
public virtual global::System.Threading.Tasks.Task RouteChat(IAsyncStreamReader<global::Routeguide.RouteNote> requestStream, IServerStreamWriter<global::Routeguide.RouteNote> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
/// <summary>Client for RouteGuide</summary>
public class RouteGuideClient : ClientBase<RouteGuideClient>
{
/// <summary>Creates a new client for RouteGuide</summary>
/// <param name="channel">The channel to use to make remote calls.</param>
public RouteGuideClient(Channel channel) : base(channel)
{
}
public global::Routeguide.Feature GetFeature(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
/// <summary>Creates a new client for RouteGuide that uses a custom <c>CallInvoker</c>.</summary>
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
public RouteGuideClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_GetFeature, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Routeguide.Feature GetFeature(global::Routeguide.Point request, CallOptions options)
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected RouteGuideClient() : base()
{
var call = CreateCall(__Method_GetFeature, options);
return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
/// <summary>Protected constructor to allow creation of configured clients.</summary>
/// <param name="configuration">The client configuration.</param>
protected RouteGuideClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_GetFeature, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, CallOptions options)
/// <summary>
/// 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.
/// </summary>
public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_GetFeature, options);
return Calls.AsyncUnaryCall(call, request);
return GetFeature(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
/// <summary>
/// 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.
/// </summary>
public virtual global::Routeguide.Feature GetFeature(global::Routeguide.Point request, CallOptions options)
{
var call = CreateCall(__Method_ListFeatures, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncServerStreamingCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_GetFeature, null, options, request);
}
public AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, CallOptions options)
/// <summary>
/// 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.
/// </summary>
public virtual AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_ListFeatures, options);
return Calls.AsyncServerStreamingCall(call, request);
return GetFeatureAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
/// <summary>
/// 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.
/// </summary>
public virtual AsyncUnaryCall<global::Routeguide.Feature> GetFeatureAsync(global::Routeguide.Point request, CallOptions options)
{
var call = CreateCall(__Method_RecordRoute, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncClientStreamingCall(call);
return CallInvoker.AsyncUnaryCall(__Method_GetFeature, null, options, request);
}
public AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(CallOptions options)
/// <summary>
/// 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.
/// </summary>
public virtual AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_RecordRoute, options);
return Calls.AsyncClientStreamingCall(call);
return ListFeatures(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
/// <summary>
/// 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.
/// </summary>
public virtual AsyncServerStreamingCall<global::Routeguide.Feature> ListFeatures(global::Routeguide.Rectangle request, CallOptions options)
{
var call = CreateCall(__Method_RouteChat, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
return CallInvoker.AsyncServerStreamingCall(__Method_ListFeatures, null, options, request);
}
public AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(CallOptions options)
/// <summary>
/// A client-to-server streaming RPC.
///
/// Accepts a stream of Points on a route being traversed, returning a
/// RouteSummary when traversal is completed.
/// </summary>
public virtual AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_RouteChat, options);
return Calls.AsyncDuplexStreamingCall(call);
return RecordRoute(new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// A client-to-server streaming RPC.
///
/// Accepts a stream of Points on a route being traversed, returning a
/// RouteSummary when traversal is completed.
/// </summary>
public virtual AsyncClientStreamingCall<global::Routeguide.Point, global::Routeguide.RouteSummary> RecordRoute(CallOptions options)
{
return CallInvoker.AsyncClientStreamingCall(__Method_RecordRoute, null, options);
}
/// <summary>
/// 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).
/// </summary>
public virtual AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return RouteChat(new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// 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).
/// </summary>
public virtual AsyncDuplexStreamingCall<global::Routeguide.RouteNote, global::Routeguide.RouteNote> RouteChat(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_RouteChat, null, options);
}
protected override RouteGuideClient NewInstance(ClientBaseConfiguration configuration)
{
return new RouteGuideClient(configuration);
}
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(IRouteGuide serviceImpl)
/// <summary>Creates service definition that can be registered with a server</summary>
public static ServerServiceDefinition BindService(RouteGuideBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
return ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_GetFeature, serviceImpl.GetFeature)
.AddMethod(__Method_ListFeatures, serviceImpl.ListFeatures)
.AddMethod(__Method_RecordRoute, serviceImpl.RecordRoute)
.AddMethod(__Method_RouteChat, serviceImpl.RouteChat).Build();
}
// creates a new client
public static RouteGuideClient NewClient(Channel channel)
{
return new RouteGuideClient(channel);
}
}
}
#endregion

@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
<package id="Grpc" version="0.13.1" targetFramework="net45" />
<package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
<package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
<package id="Grpc" version="0.15.0" targetFramework="net45" />
<package id="Grpc.Core" version="0.15.0" targetFramework="net45" />
<package id="Ix-Async" version="1.2.5" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages>

@ -43,9 +43,9 @@ namespace Routeguide
/// </summary>
public class RouteGuideClient
{
readonly RouteGuide.IRouteGuideClient client;
readonly RouteGuide.RouteGuideClient client;
public RouteGuideClient(RouteGuide.IRouteGuideClient client)
public RouteGuideClient(RouteGuide.RouteGuideClient client)
{
this.client = client;
}
@ -231,7 +231,7 @@ namespace Routeguide
static void Main(string[] args)
{
var channel = new Channel("127.0.0.1:50052", ChannelCredentials.Insecure);
var client = new RouteGuideClient(RouteGuide.NewClient(channel));
var client = new RouteGuideClient(new RouteGuide.RouteGuideClient(channel));
// Looking for a valid feature
client.GetFeature(409146138, -746188906);

@ -11,7 +11,7 @@
<AssemblyName>RouteGuideClient</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>2a1dd0a1</NuGetPackageImportStamp>
<NuGetPackageImportStamp>b880049a</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -35,11 +35,11 @@
<ItemGroup>
<Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
<HintPath>..\packages\Grpc.Core.0.15.0\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@ -71,12 +71,12 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
<Import Project="..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
<Error Condition="!Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
<package id="Grpc" version="0.13.1" targetFramework="net45" />
<package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
<package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
<package id="Grpc" version="0.15.0" targetFramework="net45" />
<package id="Grpc.Core" version="0.15.0" targetFramework="net45" />
<package id="Ix-Async" version="1.2.5" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages>

@ -35,6 +35,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
namespace Routeguide
@ -42,7 +43,7 @@ namespace Routeguide
/// <summary>
/// Example implementation of RouteGuide server.
/// </summary>
public class RouteGuideImpl : RouteGuide.IRouteGuide
public class RouteGuideImpl : RouteGuide.RouteGuideBase
{
readonly List<Feature> features;
readonly object myLock = new object();
@ -57,7 +58,7 @@ namespace Routeguide
/// Gets the feature at the requested point. If no feature at that location
/// exists, an unnammed feature is returned at the provided location.
/// </summary>
public Task<Feature> GetFeature(Point request, Grpc.Core.ServerCallContext context)
public override Task<Feature> GetFeature(Point request, ServerCallContext context)
{
return Task.FromResult(CheckFeature(request));
}
@ -65,7 +66,7 @@ namespace Routeguide
/// <summary>
/// Gets all features contained within the given bounding rectangle.
/// </summary>
public async Task ListFeatures(Rectangle request, Grpc.Core.IServerStreamWriter<Feature> responseStream, Grpc.Core.ServerCallContext context)
public override async Task ListFeatures(Rectangle request, IServerStreamWriter<Feature> responseStream, ServerCallContext context)
{
var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) );
foreach (var response in responses)
@ -78,7 +79,7 @@ namespace Routeguide
/// Gets a stream of points, and responds with statistics about the "trip": number of points,
/// number of known features visited, total distance traveled, and total time spent.
/// </summary>
public async Task<RouteSummary> RecordRoute(Grpc.Core.IAsyncStreamReader<Point> requestStream, Grpc.Core.ServerCallContext context)
public override async Task<RouteSummary> RecordRoute(IAsyncStreamReader<Point> requestStream, ServerCallContext context)
{
int pointCount = 0;
int featureCount = 0;
@ -117,7 +118,7 @@ namespace Routeguide
/// Receives a stream of message/location pairs, and responds with a stream of all previous
/// messages at each of those locations.
/// </summary>
public async Task RouteChat(Grpc.Core.IAsyncStreamReader<RouteNote> requestStream, Grpc.Core.IServerStreamWriter<RouteNote> responseStream, Grpc.Core.ServerCallContext context)
public override async Task RouteChat(IAsyncStreamReader<RouteNote> requestStream, IServerStreamWriter<RouteNote> responseStream, ServerCallContext context)
{
while (await requestStream.MoveNext())
{

@ -11,7 +11,7 @@
<AssemblyName>RouteGuideServer</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>164e03eb</NuGetPackageImportStamp>
<NuGetPackageImportStamp>946ecc79</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -35,11 +35,11 @@
<ItemGroup>
<Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta2\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
<HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core, Version=0.13.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.0.13.1\lib\net45\Grpc.Core.dll</HintPath>
<HintPath>..\packages\Grpc.Core.0.15.0\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@ -72,12 +72,12 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets" Condition="Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" />
<Import Project="..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\grpc.native.csharp.0.13.1\build\portable-net45+netcore45+wpa81+wp8\grpc.native.csharp.targets'))" />
<Error Condition="!Exists('..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.0.15.0\build\net45\Grpc.Core.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0-beta2" targetFramework="net45" />
<package id="Grpc" version="0.13.1" targetFramework="net45" />
<package id="Grpc.Core" version="0.13.1" targetFramework="net45" />
<package id="grpc.native.csharp" version="0.13.1" targetFramework="net45" />
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
<package id="Grpc" version="0.15.0" targetFramework="net45" />
<package id="Grpc.Core" version="0.15.0" targetFramework="net45" />
<package id="Ix-Async" version="1.2.5" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages>

@ -1,3 +1,32 @@
@rem Copyright 2016, Google Inc.
@rem All rights reserved.
@rem
@rem Redistribution and use in source and binary forms, with or without
@rem modification, are permitted provided that the following conditions are
@rem met:
@rem
@rem * Redistributions of source code must retain the above copyright
@rem notice, this list of conditions and the following disclaimer.
@rem * Redistributions in binary form must reproduce the above
@rem copyright notice, this list of conditions and the following disclaimer
@rem in the documentation and/or other materials provided with the
@rem distribution.
@rem * Neither the name of Google Inc. nor the names of its
@rem contributors may be used to endorse or promote products derived from
@rem this software without specific prior written permission.
@rem
@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@rem Generate the C# code for .proto files
setlocal
@ -5,7 +34,7 @@ setlocal
@rem enter this directory
cd /d %~dp0
set TOOLS_PATH=packages\Grpc.Tools.0.13.1\tools\windows_x86
set TOOLS_PATH=packages\Grpc.Tools.0.15.0\tools\windows_x86
%TOOLS_PATH%\protoc.exe -I../../protos --csharp_out RouteGuide ../../protos/route_guide.proto --grpc_out RouteGuide --plugin=protoc-gen-grpc=%TOOLS_PATH%\grpc_csharp_plugin.exe

@ -12,7 +12,7 @@ INSTALL
```sh
$ # Get the gRPC repository
$ export REPO_ROOT=grpc # REPO root can be any directory of your choice
$ git clone https://github.com/grpc/grpc.git $REPO_ROOT
$ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc $REPO_ROOT
$ cd $REPO_ROOT
$ cd examples/node
@ -22,18 +22,24 @@ INSTALL
TRY IT!
-------
There are two ways to generate the code needed to work with protocol buffers in Node.js - one approach uses [Protobuf.js](https://github.com/dcodeIO/ProtoBuf.js/) to dynamically generate the code at runtime, the other uses code statically generated using the protocol buffer compiler `protoc`. The examples behave identically, and either server can be used with either client.
- Run the server
```sh
$ # from this directory
$ node ./greeter_server.js &
$ node ./dynamic_codegen/greeter_server.js &
$ # OR
$ node ./static_codegen/greeter_server.js &
```
- Run the client
```sh
$ # from this directory
$ node ./greeter_client.js
$ node ./dynamic_codegen/greeter_client.js
$ # OR
$ node ./dynamic_codegen/greeter_client.js
```
TUTORIAL

@ -0,0 +1 @@
This is the dynamic code generation variant of the Node examples. Code in these examples is generated at runtime using Protobuf.js.

@ -0,0 +1,53 @@
/*
*
* 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.
*
*/
var PROTO_PATH = __dirname + '/../../protos/helloworld.proto';
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;
function main() {
var client = new hello_proto.Greeter('localhost:50051',
grpc.credentials.createInsecure());
var user;
if (process.argv.length >= 3) {
user = process.argv[2];
} else {
user = 'world';
}
client.sayHello({name: user}, function(err, response) {
console.log('Greeting:', response.message);
});
}
main();

@ -31,29 +31,27 @@
*
*/
/** Support zookeeper as alternative name system in addition to DNS
* Zookeeper name in gRPC is represented as a URI:
* zookeeper://host:port/path/service/instance
*
* Where zookeeper is the name system scheme
* host:port is the address of a zookeeper server
* /path/service/instance is the zookeeper name to be resolved
*
* Refer doc/naming.md for more details
*/
#ifndef GRPC_GRPC_ZOOKEEPER_H
#define GRPC_GRPC_ZOOKEEPER_H
var PROTO_PATH = __dirname + '/../../protos/helloworld.proto';
#ifdef __cplusplus
extern "C" {
#endif
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;
/** Register zookeeper name resolver in grpc */
void grpc_zookeeper_register();
/**
* Implements the SayHello RPC method.
*/
function sayHello(call, callback) {
callback(null, {message: 'Hello ' + call.request.name});
}
#ifdef __cplusplus
/**
* Starts an RPC server that receives requests for the Greeter service at the
* sample server port
*/
function main() {
var server = new grpc.Server();
server.addProtoService(hello_proto.Greeter.service, {sayHello: sayHello});
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
server.start();
}
#endif
#endif /* GRPC_GRPC_ZOOKEEPER_H */
main();

@ -31,7 +31,7 @@
*
*/
var PROTO_PATH = __dirname + '/../../protos/route_guide.proto';
var PROTO_PATH = __dirname + '/../../../protos/route_guide.proto';
var async = require('async');
var fs = require('fs');

@ -31,7 +31,7 @@
*
*/
var PROTO_PATH = __dirname + '/../../protos/route_guide.proto';
var PROTO_PATH = __dirname + '/../../../protos/route_guide.proto';
var fs = require('fs');
var parseArgs = require('minimist');

@ -1,39 +0,0 @@
// GENERATED CODE -- DO NOT EDIT!
var grpc = require('grpc');
var helloworld_pb = require('./helloworld_pb.js');
function serialize_HelloReply(arg) {
if (!(arg instanceof helloworld_pb.HelloReply)) {
throw new Error('Expected argument of type HelloReply');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloReply(buffer_arg) {
return helloworld_pb.HelloReply.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_HelloRequest(arg) {
if (!(arg instanceof helloworld_pb.HelloRequest)) {
throw new Error('Expected argument of type HelloRequest');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloRequest(buffer_arg) {
return helloworld_pb.HelloRequest.deserializeBinary(new Uint8Array(buffer_arg));
}
var GreeterService = exports.GreeterService = {
sayHello: {
path: '/helloworld.Greeter/SayHello',
requestStream: false,
responseStream: false,
requestType: helloworld_pb.HelloRequest,
responseType: helloworld_pb.HelloReply,
requestSerialize: serialize_HelloRequest,
requestDeserialize: deserialize_HelloRequest,
responseSerialize: serialize_HelloReply,
responseDeserialize: deserialize_HelloReply,
},
};
exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService);

@ -3,8 +3,8 @@
"version": "0.1.0",
"dependencies": {
"async": "^1.5.2",
"grpc": "0.13.0",
"google-protobuf": "*",
"google-protobuf": "^3.0.0-alpha.5",
"grpc": "^0.14.0",
"lodash": "^4.6.1",
"minimist": "^1.2.0"
}

@ -0,0 +1,7 @@
This is the static code generation variant of the Node examples. Code in these examples is pre-generated using protoc and the Node gRPC protoc plugin, and the generated code can be found in various `*_pb.js` files. The command line sequence for generating those files is as follows (assuming that `protoc` and `grpc_node_plugin` are present, and starting in the base directory of this package):
```sh
cd ../protos
protoc --js_out=import_style=commonjs,binary:../node/static_codegen/ --grpc_out=../node/static_codegen --plugin=protoc-gen-grpc=grpc_node_plugin helloworld.proto
protoc --js_out=import_style=commonjs,binary:../node/static_codegen/route_guide/ --grpc_out=../node/static_codegen/route_guide/ --plugin=protoc-gen-grpc=grpc_node_plugin route_guide.proto
```

@ -31,13 +31,13 @@
*
*/
var grpc = require('grpc');
var messages = require('./helloworld_pb');
var services = require('./helloworld_grpc_pb');
var hello_messages = require('./helloworld_pb');
var hello_service = require('./helloworld_grpc_pb');
var grpc = require('grpc');
function main() {
var client = new hello_service.GreeterClient('localhost:50051',
var client = new services.GreeterClient('localhost:50051',
grpc.credentials.createInsecure());
var user;
if (process.argv.length >= 3) {
@ -45,15 +45,9 @@ function main() {
} else {
user = 'world';
}
var request = new hello_messages.HelloRequest();
var request = new messages.HelloRequest();
request.setName(user);
client.sayHello(request, function(err, response) {
if (err) {
debugger;
throw err;
}
console.log('Greeting:', response.getMessage());
});
}

@ -31,17 +31,17 @@
*
*/
var grpc = require('grpc');
var messages = require('./helloworld_pb');
var services = require('./helloworld_grpc_pb');
var hello_messages = require('./helloworld_pb');
var hello_service = require('./helloworld_grpc_pb');
var grpc = require('grpc');
/**
* Implements the SayHello RPC method.
*/
function sayHello(call, callback) {
var reply = new hello_messages.HelloReply();
reply.setMessage("Hello " + call.request.getName());
var reply = new messages.HelloReply();
reply.setMessage('Hello ' + call.request.getName());
callback(null, reply);
}
@ -51,7 +51,7 @@ function sayHello(call, callback) {
*/
function main() {
var server = new grpc.Server();
server.addService(hello_service.GreeterService, {sayHello: sayHello});
server.addService(services.GreeterService, {sayHello: sayHello});
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
server.start();
}

@ -0,0 +1,76 @@
// GENERATED CODE -- DO NOT EDIT!
// Original file comments:
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
'use strict';
var grpc = require('grpc');
var helloworld_pb = require('./helloworld_pb.js');
function serialize_HelloReply(arg) {
if (!(arg instanceof helloworld_pb.HelloReply)) {
throw new Error('Expected argument of type HelloReply');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloReply(buffer_arg) {
return helloworld_pb.HelloReply.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_HelloRequest(arg) {
if (!(arg instanceof helloworld_pb.HelloRequest)) {
throw new Error('Expected argument of type HelloRequest');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloRequest(buffer_arg) {
return helloworld_pb.HelloRequest.deserializeBinary(new Uint8Array(buffer_arg));
}
// The greeting service definition.
var GreeterService = exports.GreeterService = {
// Sends a greeting
sayHello: {
path: '/helloworld.Greeter/SayHello',
requestStream: false,
responseStream: false,
requestType: helloworld_pb.HelloRequest,
responseType: helloworld_pb.HelloReply,
requestSerialize: serialize_HelloRequest,
requestDeserialize: deserialize_HelloRequest,
responseSerialize: serialize_HelloReply,
responseDeserialize: deserialize_HelloReply,
},
};
exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService);

@ -61,7 +61,7 @@ proto.helloworld.HelloRequest.toObject = function(includeInstance, msg) {
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
obj.$jspbMessageInstance = msg;
}
return obj;
};
@ -220,7 +220,7 @@ proto.helloworld.HelloReply.toObject = function(includeInstance, msg) {
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
obj.$jspbMessageInstance = msg;
}
return obj;
};

@ -0,0 +1,5 @@
#gRPC Basics: Node.js sample code
The files in this folder are the samples used in [gRPC Basics: Node.js][], a detailed tutorial for using gRPC in Node.js.
[gRPC Basics: Node.js]:http://www.grpc.io/docs/tutorials/basic/node.html

@ -0,0 +1,247 @@
/*
*
* 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.
*
*/
var messages = require('./route_guide_pb');
var services = require('./route_guide_grpc_pb');
var async = require('async');
var fs = require('fs');
var parseArgs = require('minimist');
var path = require('path');
var _ = require('lodash');
var grpc = require('grpc');
var client = new services.RouteGuideClient('localhost:50051',
grpc.credentials.createInsecure());
var COORD_FACTOR = 1e7;
/**
* Run the getFeature demo. Calls getFeature with a point known to have a
* feature and a point known not to have a feature.
* @param {function} callback Called when this demo is complete
*/
function runGetFeature(callback) {
var next = _.after(2, callback);
function featureCallback(error, feature) {
if (error) {
callback(error);
}
var latitude = feature.getLocation().getLatitude();
var longitude = feature.getLocation().getLongitude();
if (feature.getName() === '') {
console.log('Found no feature at ' +
latitude/COORD_FACTOR + ', ' + longitude/COORD_FACTOR);
} else {
console.log('Found feature called "' + feature.getName() + '" at ' +
latitude/COORD_FACTOR + ', ' + longitude/COORD_FACTOR);
}
next();
}
var point1 = new messages.Point();
point1.setLatitude(409146138);
point1.setLongitude(-746188906);
var point2 = new messages.Point();
point2.setLatitude(0);
point2.setLongitude(0);
client.getFeature(point1, featureCallback);
client.getFeature(point2, featureCallback);
}
/**
* Run the listFeatures demo. Calls listFeatures with a rectangle containing all
* of the features in the pre-generated database. Prints each response as it
* comes in.
* @param {function} callback Called when this demo is complete
*/
function runListFeatures(callback) {
var rect = new messages.Rectangle();
var lo = new messages.Point();
lo.setLatitude(400000000);
lo.setLongitude(-750000000);
rect.setLo(lo);
var hi = new messages.Point();
hi.setLatitude(420000000);
hi.setLongitude(-730000000);
rect.setHi(hi);
console.log('Looking for features between 40, -75 and 42, -73');
var call = client.listFeatures(rect);
call.on('data', function(feature) {
console.log('Found feature called "' + feature.getName() + '" at ' +
feature.getLocation().getLatitude()/COORD_FACTOR + ', ' +
feature.getLocation().getLongitude()/COORD_FACTOR);
});
call.on('end', callback);
}
/**
* Run the recordRoute demo. Sends several randomly chosen points from the
* pre-generated feature database with a variable delay in between. Prints the
* statistics when they are sent from the server.
* @param {function} callback Called when this demo is complete
*/
function runRecordRoute(callback) {
var argv = parseArgs(process.argv, {
string: 'db_path'
});
fs.readFile(path.resolve(argv.db_path), function(err, data) {
if (err) callback(err);
// Transform the loaded features to Feature objects
var feature_list = _.map(JSON.parse(data), function(value) {
var feature = new messages.Feature();
feature.setName(value.name);
var location = new messages.Point();
location.setLatitude(value.location.latitude);
location.setLongitude(value.location.longitude);
feature.setLocation(location);
return feature;
});
var num_points = 10;
var call = client.recordRoute(function(error, stats) {
if (error) {
callback(error);
}
console.log('Finished trip with', stats.getPointCount(), 'points');
console.log('Passed', stats.getFeatureCount(), 'features');
console.log('Travelled', stats.getDistance(), 'meters');
console.log('It took', stats.getElapsedTime(), 'seconds');
callback();
});
/**
* Constructs a function that asynchronously sends the given point and then
* delays sending its callback
* @param {messages.Point} location The point to send
* @return {function(function)} The function that sends the point
*/
function pointSender(location) {
/**
* Sends the point, then calls the callback after a delay
* @param {function} callback Called when complete
*/
return function(callback) {
console.log('Visiting point ' + location.getLatitude()/COORD_FACTOR +
', ' + location.getLongitude()/COORD_FACTOR);
call.write(location);
_.delay(callback, _.random(500, 1500));
};
}
var point_senders = [];
for (var i = 0; i < num_points; i++) {
var rand_point = feature_list[_.random(0, feature_list.length - 1)];
point_senders[i] = pointSender(rand_point.getLocation());
}
async.series(point_senders, function() {
call.end();
});
});
}
/**
* Run the routeChat demo. Send some chat messages, and print any chat messages
* that are sent from the server.
* @param {function} callback Called when the demo is complete
*/
function runRouteChat(callback) {
var call = client.routeChat();
call.on('data', function(note) {
console.log('Got message "' + note.getMessage() + '" at ' +
note.getLocation().getLatitude() + ', ' +
note.getLocation().getLongitude());
});
call.on('end', callback);
var notes = [{
location: {
latitude: 0,
longitude: 0
},
message: 'First message'
}, {
location: {
latitude: 0,
longitude: 1
},
message: 'Second message'
}, {
location: {
latitude: 1,
longitude: 0
},
message: 'Third message'
}, {
location: {
latitude: 0,
longitude: 0
},
message: 'Fourth message'
}];
for (var i = 0; i < notes.length; i++) {
var note = notes[i];
console.log('Sending message "' + note.message + '" at ' +
note.location.latitude + ', ' + note.location.longitude);
var noteMsg = new messages.RouteNote();
noteMsg.setMessage(note.message);
var location = new messages.Point();
location.setLatitude(note.location.latitude);
location.setLongitude(note.location.longitude);
noteMsg.setLocation(location);
call.write(noteMsg);
}
call.end();
}
/**
* Run all of the demos in order
*/
function main() {
async.series([
runGetFeature,
runListFeatures,
runRecordRoute,
runRouteChat
]);
}
if (require.main === module) {
main();
}
exports.runGetFeature = runGetFeature;
exports.runListFeatures = runListFeatures;
exports.runRecordRoute = runRecordRoute;
exports.runRouteChat = runRouteChat;

@ -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,161 @@
// GENERATED CODE -- DO NOT EDIT!
// Original file comments:
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
'use strict';
var grpc = require('grpc');
var route_guide_pb = require('./route_guide_pb.js');
function serialize_Feature(arg) {
if (!(arg instanceof route_guide_pb.Feature)) {
throw new Error('Expected argument of type Feature');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_Feature(buffer_arg) {
return route_guide_pb.Feature.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_Point(arg) {
if (!(arg instanceof route_guide_pb.Point)) {
throw new Error('Expected argument of type Point');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_Point(buffer_arg) {
return route_guide_pb.Point.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_Rectangle(arg) {
if (!(arg instanceof route_guide_pb.Rectangle)) {
throw new Error('Expected argument of type Rectangle');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_Rectangle(buffer_arg) {
return route_guide_pb.Rectangle.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_RouteNote(arg) {
if (!(arg instanceof route_guide_pb.RouteNote)) {
throw new Error('Expected argument of type RouteNote');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_RouteNote(buffer_arg) {
return route_guide_pb.RouteNote.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_RouteSummary(arg) {
if (!(arg instanceof route_guide_pb.RouteSummary)) {
throw new Error('Expected argument of type RouteSummary');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_RouteSummary(buffer_arg) {
return route_guide_pb.RouteSummary.deserializeBinary(new Uint8Array(buffer_arg));
}
// Interface exported by the server.
var RouteGuideService = exports.RouteGuideService = {
// 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.
getFeature: {
path: '/routeguide.RouteGuide/GetFeature',
requestStream: false,
responseStream: false,
requestType: route_guide_pb.Point,
responseType: route_guide_pb.Feature,
requestSerialize: serialize_Point,
requestDeserialize: deserialize_Point,
responseSerialize: serialize_Feature,
responseDeserialize: deserialize_Feature,
},
// 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.
listFeatures: {
path: '/routeguide.RouteGuide/ListFeatures',
requestStream: false,
responseStream: true,
requestType: route_guide_pb.Rectangle,
responseType: route_guide_pb.Feature,
requestSerialize: serialize_Rectangle,
requestDeserialize: deserialize_Rectangle,
responseSerialize: serialize_Feature,
responseDeserialize: deserialize_Feature,
},
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
recordRoute: {
path: '/routeguide.RouteGuide/RecordRoute',
requestStream: true,
responseStream: false,
requestType: route_guide_pb.Point,
responseType: route_guide_pb.RouteSummary,
requestSerialize: serialize_Point,
requestDeserialize: deserialize_Point,
responseSerialize: serialize_RouteSummary,
responseDeserialize: deserialize_RouteSummary,
},
// 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).
routeChat: {
path: '/routeguide.RouteGuide/RouteChat',
requestStream: true,
responseStream: true,
requestType: route_guide_pb.RouteNote,
responseType: route_guide_pb.RouteNote,
requestSerialize: serialize_RouteNote,
requestDeserialize: deserialize_RouteNote,
responseSerialize: serialize_RouteNote,
responseDeserialize: deserialize_RouteNote,
},
};
exports.RouteGuideClient = grpc.makeGenericClientConstructor(RouteGuideService);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,261 @@
/*
*
* 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.
*
*/
var messages = require('./route_guide_pb');
var services = require('./route_guide_grpc_pb');
var fs = require('fs');
var parseArgs = require('minimist');
var path = require('path');
var _ = require('lodash');
var grpc = require('grpc');
var COORD_FACTOR = 1e7;
/**
* For simplicity, a point is a record type that looks like
* {latitude: number, longitude: number}, and a feature is a record type that
* looks like {name: string, location: point}. feature objects with name===''
* are points with no feature.
*/
/**
* List of feature objects at points that have been requested so far.
*/
var feature_list = [];
/**
* Get a feature object at the given point, or creates one if it does not exist.
* @param {point} point The point to check
* @return {feature} The feature object at the point. Note that an empty name
* indicates no feature
*/
function checkFeature(point) {
var feature;
// Check if there is already a feature object for the given point
for (var i = 0; i < feature_list.length; i++) {
feature = feature_list[i];
if (feature.getLocation().getLatitude() === point.getLatitude() &&
feature.getLocation().getLongitude() === point.getLongitude()) {
return feature;
}
}
var name = '';
feature = new messages.Feature();
feature.setName(name);
feature.setLocation(point);
return feature;
}
/**
* getFeature request handler. Gets a request with a point, and responds with a
* feature object indicating whether there is a feature at that point.
* @param {EventEmitter} call Call object for the handler to process
* @param {function(Error, feature)} callback Response callback
*/
function getFeature(call, callback) {
callback(null, checkFeature(call.request));
}
/**
* listFeatures request handler. Gets a request with two points, and responds
* with a stream of all features in the bounding box defined by those points.
* @param {Writable} call Writable stream for responses with an additional
* request property for the request value.
*/
function listFeatures(call) {
var lo = call.request.getLo();
var hi = call.request.getHi();
var left = _.min([lo.getLongitude(), hi.getLongitude()]);
var right = _.max([lo.getLongitude(), hi.getLongitude()]);
var top = _.max([lo.getLatitude(), hi.getLatitude()]);
var bottom = _.min([lo.getLatitude(), hi.getLatitude()]);
// For each feature, check if it is in the given bounding box
_.each(feature_list, function(feature) {
if (feature.getName() === '') {
return;
}
if (feature.getLocation().getLongitude() >= left &&
feature.getLocation().getLongitude() <= right &&
feature.getLocation().getLatitude() >= bottom &&
feature.getLocation().getLatitude() <= top) {
call.write(feature);
}
});
call.end();
}
/**
* Calculate the distance between two points using the "haversine" formula.
* This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
* @param start The starting point
* @param end The end point
* @return The distance between the points in meters
*/
function getDistance(start, end) {
function toRadians(num) {
return num * Math.PI / 180;
}
var lat1 = start.getLatitude() / COORD_FACTOR;
var lat2 = end.getLatitude() / COORD_FACTOR;
var lon1 = start.getLongitude() / COORD_FACTOR;
var lon2 = end.getLongitude() / COORD_FACTOR;
var R = 6371000; // metres
var φ1 = toRadians(lat1);
var φ2 = toRadians(lat2);
var Δφ = toRadians(lat2-lat1);
var Δλ = toRadians(lon2-lon1);
var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
/**
* recordRoute handler. Gets a stream of points, and responds with statistics
* about the "trip": number of points, number of known features visited, total
* distance traveled, and total time spent.
* @param {Readable} call The request point stream.
* @param {function(Error, routeSummary)} callback The callback to pass the
* response to
*/
function recordRoute(call, callback) {
var point_count = 0;
var feature_count = 0;
var distance = 0;
var previous = null;
// Start a timer
var start_time = process.hrtime();
call.on('data', function(point) {
point_count += 1;
if (checkFeature(point).name !== '') {
feature_count += 1;
}
/* For each point after the first, add the incremental distance from the
* previous point to the total distance value */
if (previous != null) {
distance += getDistance(previous, point);
}
previous = point;
});
call.on('end', function() {
var summary = new messages.RouteSummary();
summary.setPointCount(point_count);
summary.setFeatureCount(feature_count);
// Cast the distance to an integer
summary.setDistance(distance|0);
// End the timer
summary.setElapsedTime(process.hrtime(start_time)[0]);
callback(null, summary);
});
}
var route_notes = {};
/**
* Turn the point into a dictionary key.
* @param {point} point The point to use
* @return {string} The key for an object
*/
function pointKey(point) {
return point.getLatitude() + ' ' + point.getLongitude();
}
/**
* routeChat handler. Receives a stream of message/location pairs, and responds
* with a stream of all previous messages at each of those locations.
* @param {Duplex} call The stream for incoming and outgoing messages
*/
function routeChat(call) {
call.on('data', function(note) {
var key = pointKey(note.getLocation());
/* For each note sent, respond with all previous notes that correspond to
* the same point */
if (route_notes.hasOwnProperty(key)) {
_.each(route_notes[key], function(note) {
call.write(note);
});
} else {
route_notes[key] = [];
}
// Then add the new note to the list
route_notes[key].push(note);
});
call.on('end', function() {
call.end();
});
}
/**
* Get a new server with the handler functions in this file bound to the methods
* it serves.
* @return {Server} The new server object
*/
function getServer() {
var server = new grpc.Server();
server.addService(services.RouteGuideService, {
getFeature: getFeature,
listFeatures: listFeatures,
recordRoute: recordRoute,
routeChat: routeChat
});
return server;
}
if (require.main === module) {
// If this is run as a script, start a server on an unused port
var routeServer = getServer();
routeServer.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
var argv = parseArgs(process.argv, {
string: 'db_path'
});
fs.readFile(path.resolve(argv.db_path), function(err, data) {
if (err) throw err;
// Transform the loaded features to Feature objects
feature_list = _.map(JSON.parse(data), function(value) {
var feature = new messages.Feature();
feature.setName(value.name);
var location = new messages.Point();
location.setLatitude(value.location.latitude);
location.setLongitude(value.location.longitude);
feature.setLocation(location);
return feature;
});
routeServer.start();
});
}
exports.getServer = getServer;

@ -116,11 +116,12 @@
isa = PBXNativeTarget;
buildConfigurationList = 63E1E9A21B28CB2100EF0978 /* Build configuration list for PBXNativeTarget "AuthSample" */;
buildPhases = (
DAABBA7B5788A39108D7CA83 /* Check Pods Manifest.lock */,
DAABBA7B5788A39108D7CA83 /* [CP] Check Pods Manifest.lock */,
63E1E9781B28CB2000EF0978 /* Sources */,
63E1E9791B28CB2000EF0978 /* Frameworks */,
63E1E97A1B28CB2000EF0978 /* Resources */,
AEFCCC69DD59CE8F6EB769D7 /* Copy Pods Resources */,
AEFCCC69DD59CE8F6EB769D7 /* [CP] Copy Pods Resources */,
D24F6598302C412D4B863D6F /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -177,14 +178,14 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
AEFCCC69DD59CE8F6EB769D7 /* Copy Pods Resources */ = {
AEFCCC69DD59CE8F6EB769D7 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
@ -192,14 +193,29 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AuthSample/Pods-AuthSample-resources.sh\"\n";
showEnvVarsInLog = 0;
};
DAABBA7B5788A39108D7CA83 /* Check Pods Manifest.lock */ = {
D24F6598302C412D4B863D6F /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AuthSample/Pods-AuthSample-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
DAABBA7B5788A39108D7CA83 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63E1E97B1B28CB2000EF0978"
BuildableName = "AuthSample.app"
BlueprintName = "AuthSample"
ReferencedContainer = "container:AuthSample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63E1E97B1B28CB2000EF0978"
BuildableName = "AuthSample.app"
BlueprintName = "AuthSample"
ReferencedContainer = "container:AuthSample.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63E1E97B1B28CB2000EF0978"
BuildableName = "AuthSample.app"
BlueprintName = "AuthSample"
ReferencedContainer = "container:AuthSample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "63E1E97B1B28CB2000EF0978"
BuildableName = "AuthSample.app"
BlueprintName = "AuthSample"
ReferencedContainer = "container:AuthSample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -2,6 +2,10 @@ Pod::Spec.new do |s|
s.name = "AuthTestService"
s.version = "0.0.1"
s.license = "New BSD"
s.authors = { 'gRPC contributors' => 'grpc-io@googlegroups.com' }
s.homepage = "http://www.grpc.io/"
s.summary = "AuthTestService example"
s.source = { :git => 'https://github.com/grpc/grpc.git' }
s.ios.deployment_target = "7.1"
s.osx.deployment_target = "10.9"
@ -9,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>

@ -1,9 +1,7 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'Protobuf', :path => "../../../third_party/protobuf"
pod 'BoringSSL', :podspec => "../../../src/objective-c"
pod 'gRPC', :path => "../../.."
install! 'cocoapods', :deterministic_uuids => false
target 'AuthSample' do
# Depend on the generated AuthTestService library.

@ -2,6 +2,10 @@ Pod::Spec.new do |s|
s.name = "HelloWorld"
s.version = "0.0.1"
s.license = "New BSD"
s.authors = { 'gRPC contributors' => 'grpc-io@googlegroups.com' }
s.homepage = "http://www.grpc.io/"
s.summary = "HelloWorld example"
s.source = { :git => 'https://github.com/grpc/grpc.git' }
s.ios.deployment_target = "7.1"
s.osx.deployment_target = "10.9"
@ -9,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

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
3EF35C14BDC2B65E21837F02 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43AB08B32839A6700EA00DD4 /* libPods.a */; };
5E3690661B2A23800040F884 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E3690651B2A23800040F884 /* main.m */; };
5E3690691B2A23800040F884 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E3690681B2A23800040F884 /* AppDelegate.m */; };
5E36906C1B2A23800040F884 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E36906B1B2A23800040F884 /* ViewController.m */; };
@ -18,7 +17,6 @@
/* Begin PBXFileReference section */
0C432EF610DB15C0F47A66BB /* Pods-HelloWorld.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HelloWorld.release.xcconfig"; path = "Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld.release.xcconfig"; sourceTree = "<group>"; };
43AB08B32839A6700EA00DD4 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
5E3690601B2A23800040F884 /* HelloWorld.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloWorld.app; sourceTree = BUILT_PRODUCTS_DIR; };
5E3690641B2A23800040F884 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5E3690651B2A23800040F884 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@ -37,7 +35,6 @@
buildActionMask = 2147483647;
files = (
EF61CF6AE2536A31D47F0E63 /* libPods-HelloWorld.a in Frameworks */,
3EF35C14BDC2B65E21837F02 /* libPods.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -88,7 +85,6 @@
isa = PBXGroup;
children = (
6B4E1F55F8A2EC95A0E7EE88 /* libPods-HelloWorld.a */,
43AB08B32839A6700EA00DD4 /* libPods.a */,
);
name = Frameworks;
sourceTree = "<group>";
@ -109,12 +105,12 @@
isa = PBXNativeTarget;
buildConfigurationList = 5E3690831B2A23810040F884 /* Build configuration list for PBXNativeTarget "HelloWorld" */;
buildPhases = (
ACF9162361FB8F24C70657DE /* Check Pods Manifest.lock */,
ACF9162361FB8F24C70657DE /* [CP] Check Pods Manifest.lock */,
5E36905C1B2A23800040F884 /* Sources */,
5E36905D1B2A23800040F884 /* Frameworks */,
5E36905E1B2A23800040F884 /* Resources */,
4C7D815378D98AB3BFC1A7D5 /* Copy Pods Resources */,
BB76529986A8BFAF19A385B1 /* Embed Pods Frameworks */,
4C7D815378D98AB3BFC1A7D5 /* [CP] Copy Pods Resources */,
BB76529986A8BFAF19A385B1 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -170,14 +166,14 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
4C7D815378D98AB3BFC1A7D5 /* Copy Pods Resources */ = {
4C7D815378D98AB3BFC1A7D5 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
@ -185,14 +181,14 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-resources.sh\"\n";
showEnvVarsInLog = 0;
};
ACF9162361FB8F24C70657DE /* Check Pods Manifest.lock */ = {
ACF9162361FB8F24C70657DE /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
@ -200,19 +196,19 @@
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
BB76529986A8BFAF19A385B1 /* Embed Pods Frameworks */ = {
BB76529986A8BFAF19A385B1 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-HelloWorld/Pods-HelloWorld-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E36905F1B2A23800040F884"
BuildableName = "HelloWorld.app"
BlueprintName = "HelloWorld"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E36905F1B2A23800040F884"
BuildableName = "HelloWorld.app"
BlueprintName = "HelloWorld"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E36905F1B2A23800040F884"
BuildableName = "HelloWorld.app"
BlueprintName = "HelloWorld"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E36905F1B2A23800040F884"
BuildableName = "HelloWorld.app"
BlueprintName = "HelloWorld"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -1,9 +1,7 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'Protobuf', :path => "../../../third_party/protobuf"
pod 'BoringSSL', :podspec => "../../../src/objective-c"
pod 'gRPC', :path => "../../.."
install! 'cocoapods', :deterministic_uuids => false
target 'HelloWorld' do
# Depend on the generated HelloWorld library.

@ -16,7 +16,7 @@ this repository to your local machine by running the following commands:
```sh
$ git clone https://github.com/grpc/grpc.git
$ git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc
$ cd grpc
$ git submodule update --init
```

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7702" systemVersion="14D131" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="49e-Tb-3d3">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="49e-Tb-3d3">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Get Feature-->
@ -16,33 +17,35 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Get Feature Demo" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="KQZ-1w-vlD">
<rect key="frame" x="150" y="279" width="299" height="42"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" name="Helvetica" family="Helvetica" pointSize="36"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" text="Execution log:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="au7-AW-5ov">
<rect key="frame" x="16" y="0.0" width="257" height="61"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="See ViewControllers.m and this app's log in XCode" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A5M-7J-77L">
<rect key="frame" x="136" y="329" width="329" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2ga-Gd-X9q">
<rect key="frame" x="20" y="82" width="560" height="437"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" link="YES"/>
</accessibility>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="centerX" secondItem="KQZ-1w-vlD" secondAttribute="centerX" id="6BV-lF-sBN"/>
<constraint firstItem="A5M-7J-77L" firstAttribute="top" secondItem="KQZ-1w-vlD" secondAttribute="bottom" constant="8" symbolic="YES" id="cfb-er-3JN"/>
<constraint firstItem="A5M-7J-77L" firstAttribute="centerX" secondItem="KQZ-1w-vlD" secondAttribute="centerX" id="e1l-AV-tCB"/>
<constraint firstAttribute="centerY" secondItem="KQZ-1w-vlD" secondAttribute="centerY" id="exm-UA-ej4"/>
<constraint firstItem="au7-AW-5ov" firstAttribute="centerX" secondItem="tsR-hK-woN" secondAttribute="centerX" constant="20" id="JAX-zf-Z1I"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Get Feature" image="first" id="acW-dT-cKf"/>
<connections>
<outlet property="outputLabel" destination="2ga-Gd-X9q" id="yXF-xa-kbD"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="W5J-7L-Pyd" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="718" y="-660"/>
<point key="canvasLocation" x="733" y="-653"/>
</scene>
<!--List Features-->
<scene sceneID="wg7-f3-ORb">
@ -56,29 +59,35 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="List Features Demo" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="zEq-FU-wV5">
<rect key="frame" x="143" y="279" width="315" height="42"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" name="Helvetica" family="Helvetica" pointSize="36"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8mE-gq-NQc">
<rect key="frame" x="20" y="114" width="560" height="437"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" link="YES"/>
</accessibility>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="See ViewControllers.m and this app's log in XCode" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NDk-cv-Gan">
<rect key="frame" x="136" y="329" width="329" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" text="Execution log:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DbB-M0-xs2">
<rect key="frame" x="50" y="12" width="257" height="61"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" staticText="YES"/>
</accessibility>
<constraints>
<constraint firstItem="NDk-cv-Gan" firstAttribute="top" secondItem="zEq-FU-wV5" secondAttribute="bottom" constant="8" symbolic="YES" id="Day-4N-Vmt"/>
<constraint firstItem="NDk-cv-Gan" firstAttribute="centerX" secondItem="zEq-FU-wV5" secondAttribute="centerX" id="JgO-Fn-dHn"/>
<constraint firstAttribute="centerX" secondItem="zEq-FU-wV5" secondAttribute="centerX" id="qqM-NS-xev"/>
<constraint firstAttribute="centerY" secondItem="zEq-FU-wV5" secondAttribute="centerY" id="qzY-Ky-pLD"/>
<constraint firstItem="DbB-M0-xs2" firstAttribute="centerX" secondItem="QS5-Rx-YEW" secondAttribute="centerX" constant="20" id="UDo-WG-7i3"/>
<constraint firstItem="DbB-M0-xs2" firstAttribute="centerX" secondItem="QS5-Rx-YEW" secondAttribute="centerX" constant="20" id="W7v-LC-HjP"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="List Features" image="second" id="cPa-gy-q4n"/>
<connections>
<outlet property="outputLabel" destination="8mE-gq-NQc" id="6rw-Kd-21X"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="4Nw-L8-lE0" sceneMemberID="firstResponder"/>
</objects>
@ -117,29 +126,32 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Record Route Demo" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="Nqv-Vr-o8P">
<rect key="frame" x="136" y="279" width="329" height="42"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" name="Helvetica" family="Helvetica" pointSize="36"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9wL-iS-tp8">
<rect key="frame" x="20" y="114" width="560" height="437"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" link="YES"/>
</accessibility>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="See ViewControllers.m and this app's log in XCode" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xjS-0N-tLe">
<rect key="frame" x="136" y="329" width="329" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" text="Execution log:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5qv-tY-qxl">
<rect key="frame" x="30" y="10" width="257" height="61"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="centerX" secondItem="Nqv-Vr-o8P" secondAttribute="centerX" id="1wf-uc-57y"/>
<constraint firstItem="xjS-0N-tLe" firstAttribute="centerX" secondItem="Nqv-Vr-o8P" secondAttribute="centerX" id="Gnh-rN-EQ3"/>
<constraint firstItem="xjS-0N-tLe" firstAttribute="top" secondItem="Nqv-Vr-o8P" secondAttribute="bottom" constant="8" symbolic="YES" id="Xhj-u3-th9"/>
<constraint firstAttribute="centerY" secondItem="Nqv-Vr-o8P" secondAttribute="centerY" id="xqU-v8-Bb3"/>
<constraint firstItem="9wL-iS-tp8" firstAttribute="centerX" secondItem="Wvj-mg-YnO" secondAttribute="centerX" constant="20" id="7TX-Jm-662"/>
<constraint firstItem="5qv-tY-qxl" firstAttribute="centerX" secondItem="Wvj-mg-YnO" secondAttribute="centerX" id="mRS-9u-c2a"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Record Route" image="first" id="PLK-Jm-UyM"/>
<connections>
<outlet property="outputLabel" destination="9wL-iS-tp8" id="xhd-zm-66g"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="9RW-dt-a4q" sceneMemberID="firstResponder"/>
</objects>
@ -157,29 +169,31 @@
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Route Chat Demo" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="zUL-Bo-wJt">
<rect key="frame" x="156" y="279" width="289" height="42"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" name="Helvetica" family="Helvetica" pointSize="36"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" text="Execution log:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BxD-G9-xhU">
<rect key="frame" x="20" y="10" width="257" height="61"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="See ViewControllers.m and this app's log in XCode" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CgS-1q-Od9">
<rect key="frame" x="136" y="329" width="329" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="131-U2-Ogk">
<rect key="frame" x="20" y="114" width="560" height="437"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" link="YES"/>
</accessibility>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="centerY" secondItem="zUL-Bo-wJt" secondAttribute="centerY" id="5hM-q1-ZjM"/>
<constraint firstItem="CgS-1q-Od9" firstAttribute="top" secondItem="zUL-Bo-wJt" secondAttribute="bottom" constant="8" symbolic="YES" id="AqI-Ra-a5O"/>
<constraint firstItem="CgS-1q-Od9" firstAttribute="centerX" secondItem="zUL-Bo-wJt" secondAttribute="centerX" id="K8f-KI-bc6"/>
<constraint firstAttribute="centerX" secondItem="zUL-Bo-wJt" secondAttribute="centerX" id="n8b-x8-Yze"/>
<constraint firstItem="BxD-G9-xhU" firstAttribute="centerX" secondItem="c9d-af-OMP" secondAttribute="centerX" id="wSw-7t-wxX"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Route Chat" image="second" id="p2G-IC-yAR"/>
<connections>
<outlet property="outputLabel" destination="131-U2-Ogk" id="fNw-M5-x1D"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="yUz-se-Cfi" sceneMemberID="firstResponder"/>
</objects>

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

Loading…
Cancel
Save