Merge branch 'master' into node_dbg_release_split

pull/10294/head
Michael Lumish 8 years ago committed by GitHub
commit 68dff87bac
  1. 1
      .clang_complete
  2. 3
      .gitignore
  3. 4
      .gitmodules
  4. 30
      .vscode/launch.json
  5. 60
      BUILD
  6. 1696
      CMakeLists.txt
  7. 30
      INSTALL.md
  8. 1023
      Makefile
  9. 1
      PYTHON-MANIFEST.in
  10. 18
      README.md
  11. 3
      Rakefile
  12. 28
      WORKSPACE
  13. 34
      binding.gyp
  14. 78
      build.yaml
  15. 17
      config.m4
  16. 26
      doc/PROTOCOL-HTTP2.md
  17. 8
      doc/environment_variables.md
  18. 4
      doc/interop-test-descriptions.md
  19. 25
      examples/ruby/errors_and_cancellation/README.md
  20. 117
      examples/ruby/errors_and_cancellation/error_examples_client.rb
  21. 76
      examples/ruby/errors_and_cancellation/error_examples_server.rb
  22. 61
      gRPC-Core.podspec
  23. 2
      gRPC-ProtoRPC.podspec
  24. 2
      gRPC-RxLibrary.podspec
  25. 2
      gRPC.podspec
  26. 3
      grpc.def
  27. 107
      grpc.gemspec
  28. 247
      include/grpc++/impl/codegen/async_stream.h
  29. 48
      include/grpc++/impl/codegen/call.h
  30. 15
      include/grpc++/impl/codegen/client_context.h
  31. 26
      include/grpc++/impl/codegen/grpc_library.h
  32. 1
      include/grpc++/impl/codegen/server_context.h
  33. 106
      include/grpc++/impl/codegen/sync_stream.h
  34. 2
      include/grpc++/server.h
  35. 65
      include/grpc/grpc.h
  36. 5
      include/grpc/impl/codegen/atm_gcc_atomic.h
  37. 1
      include/grpc/impl/codegen/atm_gcc_sync.h
  38. 35
      include/grpc/impl/codegen/grpc_types.h
  39. 8
      include/grpc/impl/codegen/port_platform.h
  40. 7
      package.json
  41. 34
      package.xml
  42. 18
      setup.py
  43. 49
      src/c-ares/CMakeLists.txt
  44. 149
      src/c-ares/gen_build_yaml.py
  45. 2
      src/compiler/README.md
  46. 77
      src/compiler/csharp_generator.cc
  47. 2
      src/compiler/php_generator.cc
  48. 2
      src/core/README.md
  49. 2
      src/core/ext/census/gen/README.md
  50. 23
      src/core/ext/client_channel/client_channel.c
  51. 1
      src/core/ext/client_channel/resolver_registry.c
  52. 1
      src/core/ext/client_channel/subchannel.c
  53. 4
      src/core/ext/lb_policy/grpclb/grpclb.c
  54. 4
      src/core/ext/lb_policy/pick_first/pick_first.c
  55. 4
      src/core/ext/lb_policy/round_robin/round_robin.c
  56. 350
      src/core/ext/resolver/dns/c_ares/dns_resolver_ares.c
  57. 65
      src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h
  58. 319
      src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
  59. 289
      src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.c
  60. 63
      src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h
  61. 17
      src/core/ext/resolver/dns/native/dns_resolver.c
  62. 89
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  63. 20
      src/core/ext/transport/chttp2/transport/frame_ping.c
  64. 3
      src/core/ext/transport/chttp2/transport/frame_ping.h
  65. 8
      src/core/ext/transport/chttp2/transport/internal.h
  66. 8
      src/core/ext/transport/chttp2/transport/writing.c
  67. 59
      src/core/lib/channel/http_client_filter.c
  68. 60
      src/core/lib/channel/http_server_filter.c
  69. 386
      src/core/lib/channel/max_age_filter.c
  70. 39
      src/core/lib/channel/max_age_filter.h
  71. 2
      src/core/lib/http/httpcli_security_connector.c
  72. 135
      src/core/lib/iomgr/ev_epoll_linux.c
  73. 14
      src/core/lib/iomgr/resource_quota.c
  74. 110
      src/core/lib/iomgr/socket_factory_posix.c
  75. 90
      src/core/lib/iomgr/socket_factory_posix.h
  76. 18
      src/core/lib/iomgr/socket_utils_common_posix.c
  77. 7
      src/core/lib/iomgr/socket_utils_posix.h
  78. 7
      src/core/lib/iomgr/tcp_server_posix.c
  79. 4
      src/core/lib/iomgr/tcp_server_utils_posix_common.c
  80. 4
      src/core/lib/iomgr/timer_uv.c
  81. 58
      src/core/lib/iomgr/udp_server.c
  82. 2
      src/core/lib/iomgr/udp_server.h
  83. 2
      src/core/lib/security/credentials/jwt/json_token.c
  84. 4
      src/core/lib/security/credentials/jwt/jwt_verifier.c
  85. 2
      src/core/lib/security/transport/secure_endpoint.c
  86. 4
      src/core/lib/security/transport/security_connector.c
  87. 2
      src/core/lib/security/transport/security_connector.h
  88. 2
      src/core/lib/security/transport/tsi_error.h
  89. 27
      src/core/lib/slice/b64.c
  90. 20
      src/core/lib/slice/b64.h
  91. 14
      src/core/lib/support/time.c
  92. 6
      src/core/lib/surface/call.c
  93. 23
      src/core/lib/surface/channel.c
  94. 77
      src/core/lib/surface/completion_queue_factory.c
  95. 51
      src/core/lib/surface/completion_queue_factory.h
  96. 4
      src/core/lib/surface/init.c
  97. 2
      src/core/lib/surface/init_secure.c
  98. 2
      src/core/lib/transport/bdp_estimator.h
  99. 4
      src/core/plugin_registry/grpc_plugin_registry.c
  100. 4
      src/core/plugin_registry/grpc_unsecure_plugin_registry.c
  101. Some files were not shown because too many files have changed in this diff Show More

@ -4,5 +4,6 @@
-Igens
-I.
-Ithird_party/boringssl/include
-Ithird_party/benchmark/include
-Ithird_party/zlib
-Ithird_party/protobuf/src

3
.gitignore vendored

@ -115,3 +115,6 @@ bazel-testlogs
# Debug output
gdb.txt
# ctags file
tags

4
.gitmodules vendored

@ -23,3 +23,7 @@
[submodule "third_party/boringssl-with-bazel"]
path = third_party/boringssl-with-bazel
url = https://boringssl.googlesource.com/boringssl
[submodule "third_party/cares/cares"]
path = third_party/cares/cares
url = https://github.com/c-ares/c-ares.git
branch = cares-1_12_0

@ -0,0 +1,30 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Mocha Tests",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/mocha",
"windows": {
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/mocha.cmd"
},
"runtimeArgs": [
"-u",
"tdd",
"--timeout",
"999999",
"--colors",
"${workspaceRoot}/src/node/test"
],
"internalConsoleOptions": "openOnSessionStart"
},
{
"type": "node",
"request": "attach",
"name": "Attach to Process",
"port": 5858
}
]
}

60
BUILD

@ -37,11 +37,11 @@ package(default_visibility = ["//visibility:public"])
load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_proto_plugin")
g_stands_for = "good"
g_stands_for = "green"
core_version = "2.0.0-dev"
core_version = "3.0.0-dev"
version = "1.1.0-dev"
version = "1.2.0"
grpc_cc_library(
name = "gpr",
@ -67,6 +67,7 @@ grpc_cc_library(
"grpc_lb_policy_pick_first",
"grpc_lb_policy_round_robin",
"grpc_load_reporting",
"grpc_resolver_dns_ares",
"grpc_resolver_dns_native",
"grpc_resolver_sockaddr",
"grpc_secure",
@ -308,8 +309,8 @@ grpc_cc_library(
srcs = [
"src/core/lib/profiling/basic_timers.c",
"src/core/lib/profiling/stap_timers.c",
"src/core/lib/support/arena.c",
"src/core/lib/support/alloc.c",
"src/core/lib/support/arena.c",
"src/core/lib/support/atm.c",
"src/core/lib/support/avl.c",
"src/core/lib/support/backoff.c",
@ -354,8 +355,8 @@ grpc_cc_library(
"src/core/lib/support/wrap_memcpy.c",
],
hdrs = [
"src/core/lib/support/arena.h",
"src/core/lib/profiling/timers.h",
"src/core/lib/support/arena.h",
"src/core/lib/support/backoff.h",
"src/core/lib/support/block_annotate.h",
"src/core/lib/support/env.h",
@ -414,7 +415,6 @@ grpc_cc_library(
"include/grpc/impl/codegen/gpr_slice.h",
"include/grpc/impl/codegen/gpr_types.h",
"include/grpc/impl/codegen/port_platform.h",
"include/grpc/impl/codegen/slice.h",
"include/grpc/impl/codegen/sync.h",
"include/grpc/impl/codegen/sync_generic.h",
"include/grpc/impl/codegen/sync_posix.h",
@ -436,6 +436,7 @@ grpc_cc_library(
"src/core/lib/channel/handshaker_registry.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/max_age_filter.c",
"src/core/lib/channel/message_size_filter.c",
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
@ -472,6 +473,7 @@ grpc_cc_library(
"src/core/lib/iomgr/resolve_address_windows.c",
"src/core/lib/iomgr/resource_quota.c",
"src/core/lib/iomgr/sockaddr_utils.c",
"src/core/lib/iomgr/socket_factory_posix.c",
"src/core/lib/iomgr/socket_mutator.c",
"src/core/lib/iomgr/socket_utils_common_posix.c",
"src/core/lib/iomgr/socket_utils_linux.c",
@ -509,6 +511,7 @@ grpc_cc_library(
"src/core/lib/json/json_reader.c",
"src/core/lib/json/json_string.c",
"src/core/lib/json/json_writer.c",
"src/core/lib/slice/b64.c",
"src/core/lib/slice/percent_encoding.c",
"src/core/lib/slice/slice.c",
"src/core/lib/slice/slice_buffer.c",
@ -527,6 +530,7 @@ grpc_cc_library(
"src/core/lib/surface/channel_ping.c",
"src/core/lib/surface/channel_stack_type.c",
"src/core/lib/surface/completion_queue.c",
"src/core/lib/surface/completion_queue_factory.c",
"src/core/lib/surface/event_string.c",
"src/core/lib/surface/lame_client.c",
"src/core/lib/surface/metadata_array.c",
@ -560,6 +564,7 @@ grpc_cc_library(
"src/core/lib/channel/handshaker_registry.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/max_age_filter.h",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
@ -597,6 +602,7 @@ grpc_cc_library(
"src/core/lib/iomgr/sockaddr_posix.h",
"src/core/lib/iomgr/sockaddr_utils.h",
"src/core/lib/iomgr/sockaddr_windows.h",
"src/core/lib/iomgr/socket_factory_posix.h",
"src/core/lib/iomgr/socket_mutator.h",
"src/core/lib/iomgr/socket_utils.h",
"src/core/lib/iomgr/socket_utils_posix.h",
@ -625,6 +631,7 @@ grpc_cc_library(
"src/core/lib/json/json_common.h",
"src/core/lib/json/json_reader.h",
"src/core/lib/json/json_writer.h",
"src/core/lib/slice/b64.h",
"src/core/lib/slice/percent_encoding.h",
"src/core/lib/slice/slice_hash_table.h",
"src/core/lib/slice/slice_internal.h",
@ -636,6 +643,7 @@ grpc_cc_library(
"src/core/lib/surface/channel_init.h",
"src/core/lib/surface/channel_stack_type.h",
"src/core/lib/surface/completion_queue.h",
"src/core/lib/surface/completion_queue_factory.h",
"src/core/lib/surface/event_string.h",
"src/core/lib/surface/init.h",
"src/core/lib/surface/lame_client.h",
@ -739,6 +747,7 @@ grpc_cc_library(
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
"include/grpc/impl/codegen/slice.h",
],
deps = [
"gpr_codegen",
@ -846,6 +855,27 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "grpc_resolver_dns_ares",
srcs = [
"src/core/ext/resolver/dns/c_ares/dns_resolver_ares.c",
"src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c",
"src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.c",
],
hdrs = [
"src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h",
"src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h",
],
language = "c",
deps = [
"grpc_base",
"grpc_client_channel",
],
external_deps = [
"cares",
],
)
grpc_cc_library(
name = "grpc_resolver_sockaddr",
srcs = [
@ -883,7 +913,6 @@ grpc_cc_library(
"src/core/lib/security/transport/security_handshaker.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",
],
@ -906,7 +935,6 @@ grpc_cc_library(
"src/core/lib/security/transport/security_connector.h",
"src/core/lib/security/transport/security_handshaker.h",
"src/core/lib/security/transport/tsi_error.h",
"src/core/lib/security/util/b64.h",
"src/core/lib/security/util/json_util.h",
],
language = "c",
@ -1100,16 +1128,16 @@ grpc_cc_library(
grpc_cc_library(
name = "tsi",
srcs = [
"src/core/lib/tsi/fake_transport_security.c",
"src/core/lib/tsi/ssl_transport_security.c",
"src/core/lib/tsi/transport_security.c",
"src/core/tsi/fake_transport_security.c",
"src/core/tsi/ssl_transport_security.c",
"src/core/tsi/transport_security.c",
],
hdrs = [
"src/core/lib/tsi/fake_transport_security.h",
"src/core/lib/tsi/ssl_transport_security.h",
"src/core/lib/tsi/ssl_types.h",
"src/core/lib/tsi/transport_security.h",
"src/core/lib/tsi/transport_security_interface.h",
"src/core/tsi/fake_transport_security.h",
"src/core/tsi/ssl_transport_security.h",
"src/core/tsi/ssl_types.h",
"src/core/tsi/transport_security.h",
"src/core/tsi/transport_security_interface.h",
],
external_deps = [
"libssl",

File diff suppressed because it is too large Load Diff

@ -1,4 +1,4 @@
#If you are in a hurry
# If you are in a hurry
For language-specific installation instructions for gRPC runtime, please
refer to these documents
@ -14,15 +14,21 @@ refer to these documents
* [Ruby](src/ruby): `gem install grpc`
#Pre-requisites
# Pre-requisites
##Linux
## Linux
```sh
$ [sudo] apt-get install build-essential autoconf libtool
```
##Mac OSX
If you plan to build from source and run tests, install the following as well:
```sh
$ [sudo] apt-get install libgflags-dev libgtest-dev
$ [sudo] apt-get install clang libc++-dev
```
## Mac OSX
For a Mac system, git is not available by default. You will first need to
install Xcode from the Mac AppStore and then run the following command from a
@ -32,7 +38,7 @@ terminal:
$ [sudo] xcode-select --install
```
##Protoc
## Protoc
By default gRPC uses [protocol buffers](https://github.com/google/protobuf),
you will need the `protoc` compiler to generate stub server and client code.
@ -43,7 +49,7 @@ repository recursively and it detects that you don't already have it
installed.
#Build from Source
# Build from Source
For developers who are interested to contribute, here is how to compile the
gRPC C Core library.
@ -56,16 +62,16 @@ gRPC C Core library.
$ [sudo] make install
```
##Windows
## Windows
There are several ways to build under Windows, of varying complexity depending
on experience with the tools involved.
###Pre-generated Visual Studio solution
### Pre-generated Visual Studio solution
The pre-generated VS projects & solution are checked into the repository under the [vsprojects](/vsprojects) directory.
###Building using CMake (with BoringSSL)
### Building using CMake (with BoringSSL)
- Install [CMake](https://cmake.org/download/).
- Install [Active State Perl](http://www.activestate.com/activeperl/) (`choco install activeperl`)
- Install [Ninja](https://ninja-build.org/) (`choco install ninja`)
@ -81,14 +87,14 @@ The pre-generated VS projects & solution are checked into the repository under t
```
NOTE: Currently you can only use Ninja to build using cmake on Windows (because of the boringssl dependency).
###msys2 (with mingw)
### msys2 (with mingw)
The Makefile (and source code) should support msys2's mingw32 and mingw64
compilers. Building with msys2's native compiler is also possible, but
difficult.
This approach requires having [msys2](https://msys2.github.io/) installed.
```
# Install prerequisites
MSYS2$ pacman -S autoconf automake gcc libtool mingw-w64-x86_64-toolchain perl pkg-config zlib

1023
Makefile

File diff suppressed because it is too large Load Diff

@ -7,6 +7,7 @@ graft include/grpc
graft third_party/boringssl
graft third_party/nanopb
graft third_party/zlib
graft third_party/c-ares
include src/python/grpcio/_spawn_patch.py
include src/python/grpcio/commands.py
include src/python/grpcio/grpc_version.py

@ -7,11 +7,11 @@
Copyright 2015 Google Inc.
#Documentation
# Documentation
You can find more detailed documentation and examples in the [doc](doc) and [examples](examples) directories respectively.
#Installation & Testing
# Installation & Testing
See [INSTALL](INSTALL.md) for installation instructions for various platforms.
@ -19,7 +19,7 @@ See [tools/run_tests](tools/run_tests) for more guidance on how to run various t
See [Performance dashboard](http://performance-dot-grpc-testing.appspot.com/explore?dashboard=5712453606309888) for the performance numbers for v1.0.x.
#Repository Structure & Status
# 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).
@ -37,14 +37,14 @@ Libraries in different languages may be in different states of development. We a
| Objective-C | [src/objective-c] (src/objective-c) | 1.0 |
<small>
Java source code is in the [grpc-java] (http://github.com/grpc/grpc-java) repository.
Go source code is in the [grpc-go] (http://github.com/grpc/grpc-go) repository.
Java source code is in the [grpc-java](http://github.com/grpc/grpc-java) repository.
Go source code is in the [grpc-go](http://github.com/grpc/grpc-go) repository.
</small>
See [MANIFEST.md](MANIFEST.md) for a listing of top-level items in the
repository.
#Overview
# Overview
Remote Procedure Calls (RPCs) provide a useful abstraction for building
@ -54,7 +54,7 @@ These libraries enable communication between clients and servers using any
combination of the supported languages.
##Interface
## Interface
Developers using gRPC typically start with the description of an RPC service
@ -66,7 +66,7 @@ Interface Definition Language (IDL) for describing both the service interface
and the structure of the payload messages. It is possible to use other
alternatives if desired.
###Surface API
### Surface API
Starting from an interface definition in a .proto file, gRPC provides
Protocol Compiler plugins that generate Client- and Server-side APIs.
gRPC users typically call into these APIs on the Client side and implement
@ -94,7 +94,7 @@ the client and the server can send a stream of messages to each other. The strea
messages are delivered in the order they were sent.
#Protocol
# Protocol
The [gRPC protocol](doc/PROTOCOL-HTTP2.md) specifies the abstract requirements for communication between
clients and servers. A concrete embedding over HTTP/2 completes the picture by

@ -12,7 +12,8 @@ load 'tools/distrib/docker_for_windows.rb'
# Add rubocop style checking tasks
RuboCop::RakeTask.new(:rubocop) do |task|
task.options = ['-c', 'src/ruby/.rubocop.yml']
task.patterns = ['src/ruby/{lib,spec}/**/*.rb']
# add end2end tests to formatter but don't add generated proto _pb.rb's
task.patterns = ['src/ruby/{lib,spec}/**/*.rb', 'src/ruby/end2end/*.rb']
end
spec = Gem::Specification.load('grpc.gemspec')

@ -28,11 +28,21 @@ bind(
actual = "@submodule_protobuf//:protoc",
)
bind(
name = "cares",
actual = "@submodule_cares//:ares",
)
bind(
name = "gtest",
actual = "@submodule_gtest//:gtest",
)
bind(
name = "benchmark",
actual = "@submodule_benchmark//:benchmark",
)
bind(
name = "gflags",
actual = "@com_github_gflags_gflags//:gflags",
@ -66,3 +76,21 @@ local_repository(
name = "com_github_gflags_gflags",
path = "third_party/gflags",
)
git_repository(
name = "mongoose_repo",
commit = "4120a97945b41195a6223a600dae8e3b19bed19e",
remote = "https://github.com/makdharma/mongoose.git"
)
new_local_repository(
name = "submodule_benchmark",
path = "third_party/benchmark",
build_file = "third_party/benchmark.BUILD",
)
new_local_repository(
name = "submodule_cares",
path = "third_party/cares",
build_file = "third_party/cares/cares.BUILD",
)

@ -39,11 +39,9 @@
{
'variables': {
'runtime%': 'node',
# UV integration in C core is disabled by default while bugs are ironed
# out. It can be re-enabled for one build by setting the npm config
# variable grpc_uv to true, and it can be re-enabled permanently by
# setting it to true here.
'grpc_uv%': 'false',
# UV integration in C core is enabled by default. It can be disabled
# by setting this argument to anything else.
'grpc_uv%': 'true',
# Some Node installations use the system installation of OpenSSL, and on
# some systems, the system OpenSSL still does not have ALPN support. This
# will let users recompile gRPC to work without ALPN.
@ -93,6 +91,9 @@
'conditions': [
['grpc_uv=="true"', {
'defines': [
'GRPC_ARES=0',
# Disabling this while bugs are ironed out. Uncomment this to
# re-enable libuv integration in C core.
'GRPC_UV'
]
}],
@ -156,7 +157,8 @@
}],
['OS == "win"', {
"include_dirs": [
"third_party/zlib"
"third_party/zlib",
"third_party/cares/cares"
],
"defines": [
'_WIN32_WINNT=0x0600',
@ -176,7 +178,8 @@
]
}, { # OS != "win"
'include_dirs': [
'<(node_root_dir)/deps/zlib'
'<(node_root_dir)/deps/zlib',
'<(node_root_dir)/deps/cares/include'
]
}]
]
@ -563,6 +566,7 @@
}]
],
'targets': [
{
'cflags': [
'-std=c99',
@ -641,6 +645,7 @@
'type': 'static_library',
'dependencies': [
'gpr',
'node_modules/cares/deps/cares/cares.gyp:cares',
],
'sources': [
'src/core/lib/surface/init.c',
@ -655,6 +660,7 @@
'src/core/lib/channel/handshaker_registry.c',
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/channel/max_age_filter.c',
'src/core/lib/channel/message_size_filter.c',
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
@ -691,6 +697,7 @@
'src/core/lib/iomgr/resolve_address_windows.c',
'src/core/lib/iomgr/resource_quota.c',
'src/core/lib/iomgr/sockaddr_utils.c',
'src/core/lib/iomgr/socket_factory_posix.c',
'src/core/lib/iomgr/socket_mutator.c',
'src/core/lib/iomgr/socket_utils_common_posix.c',
'src/core/lib/iomgr/socket_utils_linux.c',
@ -728,6 +735,7 @@
'src/core/lib/json/json_reader.c',
'src/core/lib/json/json_string.c',
'src/core/lib/json/json_writer.c',
'src/core/lib/slice/b64.c',
'src/core/lib/slice/percent_encoding.c',
'src/core/lib/slice/slice.c',
'src/core/lib/slice/slice_buffer.c',
@ -746,6 +754,7 @@
'src/core/lib/surface/channel_ping.c',
'src/core/lib/surface/channel_stack_type.c',
'src/core/lib/surface/completion_queue.c',
'src/core/lib/surface/completion_queue_factory.c',
'src/core/lib/surface/event_string.c',
'src/core/lib/surface/lame_client.c',
'src/core/lib/surface/metadata_array.c',
@ -809,12 +818,11 @@
'src/core/lib/security/transport/security_handshaker.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',
'src/core/lib/tsi/transport_security.c',
'src/core/tsi/fake_transport_security.c',
'src/core/tsi/ssl_transport_security.c',
'src/core/tsi/transport_security.c',
'src/core/ext/transport/chttp2/server/chttp2_server.c',
'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c',
'src/core/ext/client_channel/channel_connectivity.c',
@ -851,6 +859,9 @@
'third_party/nanopb/pb_encode.c',
'src/core/ext/lb_policy/pick_first/pick_first.c',
'src/core/ext/lb_policy/round_robin/round_robin.c',
'src/core/ext/resolver/dns/c_ares/dns_resolver_ares.c',
'src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c',
'src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.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',
@ -935,6 +946,7 @@
"dependencies": [
"grpc",
"gpr",
"node_modules/cares/deps/cares/cares.gyp:cares",
]
},
{

@ -156,7 +156,6 @@ filegroups:
- include/grpc/impl/codegen/gpr_slice.h
- include/grpc/impl/codegen/gpr_types.h
- include/grpc/impl/codegen/port_platform.h
- include/grpc/impl/codegen/slice.h
- include/grpc/impl/codegen/sync.h
- include/grpc/impl/codegen/sync_generic.h
- include/grpc/impl/codegen/sync_posix.h
@ -186,6 +185,7 @@ filegroups:
- src/core/lib/channel/handshaker_registry.h
- src/core/lib/channel/http_client_filter.h
- src/core/lib/channel/http_server_filter.h
- src/core/lib/channel/max_age_filter.h
- src/core/lib/channel/message_size_filter.h
- src/core/lib/compression/algorithm_metadata.h
- src/core/lib/compression/message_compress.h
@ -223,6 +223,7 @@ filegroups:
- src/core/lib/iomgr/sockaddr_posix.h
- src/core/lib/iomgr/sockaddr_utils.h
- src/core/lib/iomgr/sockaddr_windows.h
- src/core/lib/iomgr/socket_factory_posix.h
- src/core/lib/iomgr/socket_mutator.h
- src/core/lib/iomgr/socket_utils.h
- src/core/lib/iomgr/socket_utils_posix.h
@ -251,6 +252,7 @@ filegroups:
- src/core/lib/json/json_common.h
- src/core/lib/json/json_reader.h
- src/core/lib/json/json_writer.h
- src/core/lib/slice/b64.h
- src/core/lib/slice/percent_encoding.h
- src/core/lib/slice/slice_hash_table.h
- src/core/lib/slice/slice_internal.h
@ -262,6 +264,7 @@ filegroups:
- src/core/lib/surface/channel_init.h
- src/core/lib/surface/channel_stack_type.h
- src/core/lib/surface/completion_queue.h
- src/core/lib/surface/completion_queue_factory.h
- src/core/lib/surface/event_string.h
- src/core/lib/surface/init.h
- src/core/lib/surface/lame_client.h
@ -293,6 +296,7 @@ filegroups:
- src/core/lib/channel/handshaker_registry.c
- src/core/lib/channel/http_client_filter.c
- src/core/lib/channel/http_server_filter.c
- src/core/lib/channel/max_age_filter.c
- src/core/lib/channel/message_size_filter.c
- src/core/lib/compression/compression.c
- src/core/lib/compression/message_compress.c
@ -329,6 +333,7 @@ filegroups:
- src/core/lib/iomgr/resolve_address_windows.c
- src/core/lib/iomgr/resource_quota.c
- src/core/lib/iomgr/sockaddr_utils.c
- src/core/lib/iomgr/socket_factory_posix.c
- src/core/lib/iomgr/socket_mutator.c
- src/core/lib/iomgr/socket_utils_common_posix.c
- src/core/lib/iomgr/socket_utils_linux.c
@ -366,6 +371,7 @@ filegroups:
- src/core/lib/json/json_reader.c
- src/core/lib/json/json_string.c
- src/core/lib/json/json_writer.c
- src/core/lib/slice/b64.c
- src/core/lib/slice/percent_encoding.c
- src/core/lib/slice/slice.c
- src/core/lib/slice/slice_buffer.c
@ -384,6 +390,7 @@ filegroups:
- src/core/lib/surface/channel_ping.c
- src/core/lib/surface/channel_stack_type.c
- src/core/lib/surface/completion_queue.c
- src/core/lib/surface/completion_queue_factory.c
- src/core/lib/surface/event_string.c
- src/core/lib/surface/lame_client.c
- src/core/lib/surface/metadata_array.c
@ -459,6 +466,7 @@ filegroups:
- include/grpc/impl/codegen/exec_ctx_fwd.h
- include/grpc/impl/codegen/grpc_types.h
- include/grpc/impl/codegen/propagation_bits.h
- include/grpc/impl/codegen/slice.h
- include/grpc/impl/codegen/status.h
uses:
- gpr_codegen
@ -492,6 +500,7 @@ filegroups:
plugin: grpc_lb_policy_grpclb
uses:
- grpc_base
- grpc_secure
- grpc_client_channel
- nanopb
- name: grpc_lb_policy_pick_first
@ -518,6 +527,18 @@ filegroups:
plugin: grpc_load_reporting_plugin
uses:
- grpc_base
- name: grpc_resolver_dns_ares
headers:
- src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h
- src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h
src:
- src/core/ext/resolver/dns/c_ares/dns_resolver_ares.c
- src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
- src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.c
plugin: grpc_resolver_dns_ares
uses:
- grpc_base
- grpc_client_channel
- name: grpc_resolver_dns_native
src:
- src/core/ext/resolver/dns/native/dns_resolver.c
@ -554,7 +575,6 @@ filegroups:
- src/core/lib/security/transport/security_connector.h
- src/core/lib/security/transport/security_handshaker.h
- src/core/lib/security/transport/tsi_error.h
- src/core/lib/security/util/b64.h
- src/core/lib/security/util/json_util.h
src:
- src/core/lib/http/httpcli_security_connector.c
@ -579,7 +599,6 @@ filegroups:
- src/core/lib/security/transport/security_handshaker.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
secure: true
@ -684,6 +703,7 @@ filegroups:
uses:
- grpc_transport_chttp2
- grpc_base
- grpc_client_channel
- name: grpc_transport_chttp2_client_insecure
src:
- src/core/ext/transport/chttp2/client/insecure/channel_create.c
@ -753,15 +773,15 @@ filegroups:
- third_party/nanopb/pb_encode.c
- name: tsi
headers:
- src/core/lib/tsi/fake_transport_security.h
- src/core/lib/tsi/ssl_transport_security.h
- src/core/lib/tsi/ssl_types.h
- src/core/lib/tsi/transport_security.h
- src/core/lib/tsi/transport_security_interface.h
- src/core/tsi/fake_transport_security.h
- src/core/tsi/ssl_transport_security.h
- src/core/tsi/ssl_types.h
- src/core/tsi/transport_security.h
- src/core/tsi/transport_security_interface.h
src:
- src/core/lib/tsi/fake_transport_security.c
- src/core/lib/tsi/ssl_transport_security.c
- src/core/lib/tsi/transport_security.c
- src/core/tsi/fake_transport_security.c
- src/core/tsi/ssl_transport_security.c
- src/core/tsi/transport_security.c
deps:
- gpr
secure: true
@ -857,6 +877,8 @@ filegroups:
- src/cpp/util/time_cc.cc
uses:
- grpc++_codegen_base
- grpc_base
- nanopb
- name: grpc++_codegen_base
language: c++
public_headers:
@ -962,6 +984,7 @@ libs:
- grpc_lb_policy_grpclb_secure
- grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin
- grpc_resolver_dns_ares
- grpc_resolver_dns_native
- grpc_resolver_sockaddr
- grpc_load_reporting
@ -1055,6 +1078,7 @@ libs:
- grpc_base
- grpc_transport_chttp2_server_insecure
- grpc_transport_chttp2_client_insecure
- grpc_resolver_dns_ares
- grpc_resolver_dns_native
- grpc_resolver_sockaddr
- grpc_load_reporting
@ -1236,6 +1260,7 @@ libs:
- grpc++
- grpc_test_util
- grpc
defaults: benchmark
- name: grpc_cli_libs
build: private
language: c++
@ -1384,6 +1409,7 @@ libs:
build: private
language: c++
headers:
- test/cpp/qps/benchmark_config.h
- test/cpp/qps/client.h
- test/cpp/qps/driver.h
- test/cpp/qps/histogram.h
@ -1394,13 +1420,13 @@ libs:
- test/cpp/qps/server.h
- test/cpp/qps/stats.h
- test/cpp/qps/usage_timer.h
- test/cpp/util/benchmark_config.h
src:
- src/proto/grpc/testing/messages.proto
- src/proto/grpc/testing/payloads.proto
- src/proto/grpc/testing/stats.proto
- src/proto/grpc/testing/control.proto
- src/proto/grpc/testing/services.proto
- test/cpp/qps/benchmark_config.cc
- test/cpp/qps/client_async.cc
- test/cpp/qps/client_sync.cc
- test/cpp/qps/driver.cc
@ -1410,7 +1436,6 @@ libs:
- test/cpp/qps/server_async.cc
- test/cpp/qps/server_sync.cc
- test/cpp/qps/usage_timer.cc
- test/cpp/util/benchmark_config.cc
deps:
- grpc_test_util
- grpc++_test_util
@ -2017,7 +2042,7 @@ targets:
build: test
language: c
src:
- test/core/security/b64_test.c
- test/core/slice/b64_test.c
deps:
- grpc_test_util
- grpc
@ -3070,6 +3095,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
platforms:
- mac
- linux
@ -3090,6 +3116,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
platforms:
- mac
- linux
@ -3110,6 +3137,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
platforms:
- mac
- linux
@ -3130,6 +3158,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
platforms:
- mac
- linux
@ -3150,6 +3179,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
platforms:
- mac
- linux
@ -3170,6 +3200,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
platforms:
- mac
- linux
@ -3190,6 +3221,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
platforms:
- mac
- linux
@ -3210,6 +3242,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
excluded_poll_engines:
- poll
- poll-cv
@ -3234,6 +3267,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
excluded_poll_engines:
- poll
- poll-cv
@ -3258,6 +3292,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
excluded_poll_engines:
- poll
- poll-cv
@ -3282,6 +3317,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
excluded_poll_engines:
- poll
- poll-cv
@ -3306,6 +3342,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
platforms:
- mac
- linux
@ -3326,6 +3363,7 @@ targets:
- gpr
args:
- --benchmark_min_time=0
defaults: benchmark
platforms:
- mac
- linux
@ -3809,6 +3847,7 @@ targets:
- test/cpp/microbenchmarks/noop-benchmark.cc
deps:
- benchmark
defaults: benchmark
- name: proto_server_reflection_test
gtest: true
build: test
@ -4117,7 +4156,6 @@ targets:
- test/cpp/interop/interop_client.cc
- test/cpp/interop/stress_interop_client.cc
- test/cpp/interop/stress_test.cc
- test/cpp/util/create_test_channel.cc
- test/cpp/util/metrics_server.cc
deps:
- grpc++_test_util
@ -4254,6 +4292,9 @@ configs:
DEFINES: _DEBUG DEBUG
LDFLAGS: -rdynamic
valgrind: --tool=helgrind
lto:
CPPFLAGS: -O2
DEFINES: NDEBUG
memcheck:
CPPFLAGS: -O0
DEFINES: _DEBUG DEBUG
@ -4306,6 +4347,11 @@ configs:
test_environ:
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1:suppressions=tools/ubsan_suppressions.txt
defaults:
ares:
CFLAGS: -Wno-sign-conversion -Wno-invalid-source-encoding
CPPFLAGS: -Ithird_party/cares -Ithird_party/cares/cares $(if $(subst Linux,,$(SYSTEM)),,-Ithird_party/cares/config_linux)
$(if $(subst Darwin,,$(SYSTEM)),,-Ithird_party/cares/config_darwin) -fvisibility=hidden
-D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DHAVE_CONFIG_H
benchmark:
CPPFLAGS: -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
boringssl:
@ -4396,11 +4442,13 @@ python_dependencies:
deps:
- grpc
- gpr
- ares
- boringssl
- z
ruby_gem:
deps:
- grpc
- gpr
- ares
- boringssl
- z

@ -94,6 +94,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/channel/handshaker_registry.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/max_age_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
@ -130,6 +131,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/iomgr/resolve_address_windows.c \
src/core/lib/iomgr/resource_quota.c \
src/core/lib/iomgr/sockaddr_utils.c \
src/core/lib/iomgr/socket_factory_posix.c \
src/core/lib/iomgr/socket_mutator.c \
src/core/lib/iomgr/socket_utils_common_posix.c \
src/core/lib/iomgr/socket_utils_linux.c \
@ -167,6 +169,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/json/json_reader.c \
src/core/lib/json/json_string.c \
src/core/lib/json/json_writer.c \
src/core/lib/slice/b64.c \
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
@ -185,6 +188,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/surface/channel_ping.c \
src/core/lib/surface/channel_stack_type.c \
src/core/lib/surface/completion_queue.c \
src/core/lib/surface/completion_queue_factory.c \
src/core/lib/surface/event_string.c \
src/core/lib/surface/lame_client.c \
src/core/lib/surface/metadata_array.c \
@ -248,12 +252,11 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/security/transport/security_handshaker.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 \
src/core/lib/tsi/transport_security.c \
src/core/tsi/fake_transport_security.c \
src/core/tsi/ssl_transport_security.c \
src/core/tsi/transport_security.c \
src/core/ext/transport/chttp2/server/chttp2_server.c \
src/core/ext/transport/chttp2/client/secure/secure_channel_create.c \
src/core/ext/client_channel/channel_connectivity.c \
@ -290,6 +293,9 @@ if test "$PHP_GRPC" != "no"; then
third_party/nanopb/pb_encode.c \
src/core/ext/lb_policy/pick_first/pick_first.c \
src/core/ext/lb_policy/round_robin/round_robin.c \
src/core/ext/resolver/dns/c_ares/dns_resolver_ares.c \
src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c \
src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.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 \
@ -629,6 +635,7 @@ if test "$PHP_GRPC" != "no"; then
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/c_ares)
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)
@ -662,8 +669,8 @@ if test "$PHP_GRPC" != "no"; then
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)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/tsi)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/plugin_registry)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/aes)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/asn1)

@ -91,7 +91,7 @@ A **Compressed-Flag** value of 1 indicates that the binary octet sequence of **M
For requests, **EOS** (end-of-stream) is indicated by the presence of the END_STREAM flag on the last received DATA frame. In scenarios where the **Request** stream needs to be closed but no data remains to be sent implementations MUST send an empty DATA frame with this flag set.
###Responses
### Responses
* **Response** → (Response-Headers \*Length-Prefixed-Message Trailers) / Trailers-Only
* **Response-Headers** → HTTP-Status [Message-Encoding] [Message-Accept-Encoding] Content-Type \*Custom-Metadata
@ -128,7 +128,7 @@ implementation can decode valid portions while leaving broken %-encodings as-is
or replacing them with a replacement character (e.g., '?' or the Unicode
replacement character).
####Example
#### Example
Sample unary-call showing HTTP2 framing sequence
@ -162,7 +162,7 @@ HEADERS (flags = END_STREAM, END_HEADERS)
grpc-status = 0 # OK
trace-proto-bin = jher831yy13JHy3hc
```
####User Agents
#### User Agents
While the protocol does not require a user-agent to function it is recommended that clients provide a structured user-agent string that provides a basic description of the calling library, version & platform to facilitate issue diagnosis in heterogeneous environments. The following structure is recommended to library developers
```
@ -177,7 +177,7 @@ grpc-ruby-jruby/1.3.4
grpc-java-android/0.9.1 (gingerbread/1.2.4; nexus5; tmobile)
```
####Idempotency and Retries
#### Idempotency and Retries
Unless explicitly defined to be, gRPC Calls are not assumed to be idempotent. Specifically:
@ -186,15 +186,15 @@ Unless explicitly defined to be, gRPC Calls are not assumed to be idempotent. S
* Calls that are marked as idempotent may be sent multiple times.
####HTTP2 Transport Mapping
#### HTTP2 Transport Mapping
#####Stream Identification
##### Stream Identification
All GRPC calls need to specify an internal ID. We will use HTTP2 stream-ids as call identifiers in this scheme. NOTE: These id’s are contextual to an open HTTP2 session and will not be unique within a given process that is handling more than one HTTP2 session nor can they be used as GUIDs.
#####Data Frames
##### Data Frames
DATA frame boundaries have no relation to **Length-Prefixed-Message** boundaries and implementations should make no assumptions about their alignment.
#####Errors
##### Errors
When an application or runtime error occurs during an RPC a **Status** and **Status-Message** are delivered in **Trailers**.
@ -219,20 +219,20 @@ ENHANCE_YOUR_CALM|RESOURCE_EXHAUSTED ...with additional error detail provided by
INADEQUATE_SECURITY| PERMISSION_DENIED … with additional detail indicating that permission was denied as protocol is not secure enough for call.
#####Security
##### Security
The HTTP2 specification mandates the use of TLS 1.2 or higher when TLS is used with HTTP2. It also places some additional constraints on the allowed ciphers in deployments to avoid known-problems as well as requiring SNI support. It is also expected that HTTP2 will be used in conjunction with proprietary transport security mechanisms about which the specification can make no meaningful recommendations.
#####Connection Management
######GOAWAY Frame
##### Connection Management
###### GOAWAY Frame
Sent by servers to clients to indicate that they will no longer accept any new streams on the associated connections. This frame includes the id of the last successfully accepted stream by the server. Clients should consider any stream initiated after the last successfully accepted stream as UNAVAILABLE and retry the call elsewhere. Clients are free to continue working with the already accepted streams until they complete or the connection is terminated.
Servers should send GOAWAY before terminating a connection to reliably inform clients which work has been accepted by the server and is being executed.
######PING Frame
###### PING Frame
Both clients and servers can send a PING frame that the peer must respond to by precisely echoing what they received. This is used to assert that the connection is still live as well as providing a means to estimate end-to-end latency. If a server initiated PING does not receive a response within the deadline expected by the runtime all outstanding calls on the server will be closed with a CANCELLED status. An expired client initiated PING will cause all calls to be closed with an UNAVAILABLE status. Note that the frequency of PINGs is highly dependent on the network environment, implementations are free to adjust PING frequency based on network and application requirements.
######Connection failure
###### Connection failure
If a detectable connection failure occurs on the client all calls will be closed with an UNAVAILABLE status. For servers open calls will be closed with a CANCELLED status.

@ -69,3 +69,11 @@ some configuration as environment variables that can be set.
- DEBUG - log all gRPC messages
- INFO - log INFO and ERROR message
- ERROR - log only errors
* GRPC_DNS_RESOLVER
Declares which DNS resolver to use. The default is ares if gRPC is built with
c-ares support. Otherwise, the value of this environment variable is ignored.
Available DNS resolver include:
- native (default)- a DNS resolver based around getaddrinfo(), creates a new thread to
perform name resolution
- ares - a DNS resolver based around the c-ares library

@ -27,7 +27,7 @@ Clients should accept these arguments:
* Whether to use a plaintext or encrypted connection
* --use_test_ca=BOOLEAN
* Whether to replace platform root CAs with
[ca.pem](https://github.com/grpc/grpc/blob/master/src/core/lib/tsi/test_creds/ca.pem)
[ca.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/ca.pem)
as the CA root
* --default_service_account=ACCOUNT_EMAIL
* Email of the GCE default service account.
@ -969,7 +969,7 @@ Servers should accept these arguments:
* Whether to use a plaintext or encrypted connection
Servers must support TLS with ALPN. They should use
[server1.pem](https://github.com/grpc/grpc/blob/master/src/core/lib/tsi/test_creds/server1.pem)
[server1.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/server1.pem)
for their certificate.
### EmptyCall

@ -0,0 +1,25 @@
#Errors and Cancelletion code samples for grpc-ruby
The examples in this directory show use of grpc errors.
On the server side, errors are returned from service
implementations by raising a certain `GRPC::BadStatus` exception.
On the client side, GRPC errors get raised when either:
* the call completes (unary and client-streaming call types)
* the response `Enumerable` is iterated through (server-streaming and
bidi call types).
## To run the examples here:
Start the server:
```
> ruby error_examples_server.rb
```
Then run the client:
```
> ruby error_examples_client.rb
```

@ -0,0 +1,117 @@
#!/usr/bin/env ruby
# 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.
# Sample app that connects to an error-throwing implementation of
# Route Guide service.
#
# Usage: $ path/to/route_guide_client.rb
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(File.dirname(this_dir), 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'route_guide_services_pb'
include Routeguide
def run_get_feature_expect_error(stub)
resp = stub.get_feature(Point.new)
end
def run_list_features_expect_error(stub)
resps = stub.list_features(Rectangle.new)
# NOOP iteration to pick up error
resps.each { }
end
def run_record_route_expect_error(stub)
stub.record_route([])
end
def run_route_chat_expect_error(stub)
resps = stub.route_chat([])
# NOOP iteration to pick up error
resps.each { }
end
def main
stub = RouteGuide::Stub.new('localhost:50051', :this_channel_is_insecure)
begin
run_get_feature_expect_error(stub)
rescue GRPC::BadStatus => e
puts "===== GetFeature exception: ====="
puts e.inspect
puts "e.code: #{e.code}"
puts "e.details: #{e.details}"
puts "e.metadata: #{e.metadata}"
puts "================================="
end
begin
run_list_features_expect_error(stub)
rescue GRPC::BadStatus => e
error = true
puts "===== ListFeatures exception: ====="
puts e.inspect
puts "e.code: #{e.code}"
puts "e.details: #{e.details}"
puts "e.metadata: #{e.metadata}"
puts "================================="
end
begin
run_route_chat_expect_error(stub)
rescue GRPC::BadStatus => e
puts "==== RouteChat exception: ===="
puts e.inspect
puts "e.code: #{e.code}"
puts "e.details: #{e.details}"
puts "e.metadata: #{e.metadata}"
puts "================================="
end
begin
run_record_route_expect_error(stub)
rescue GRPC::BadStatus => e
puts "==== RecordRoute exception: ===="
puts e.inspect
puts "e.code: #{e.code}"
puts "e.details: #{e.details}"
puts "e.metadata: #{e.metadata}"
puts "================================="
end
end
main

@ -0,0 +1,76 @@
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# 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.
# Error-throwing implementation of Route Guide service.
#
# Usage: $ path/to/route_guide_server.rb
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(File.dirname(this_dir), 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'route_guide_services_pb'
include Routeguide
include GRPC::Core::StatusCodes
# CanellingandErrorReturningServiceImpl provides an implementation of the RouteGuide service.
class CancellingAndErrorReturningServerImpl < RouteGuide::Service
# def get_feature
# Note get_feature isn't implemented in this subclass, so the server
# will get a gRPC UNIMPLEMENTED error when it's called.
def list_features(rectangle, _call)
raise "string appears on the client in the 'details' field of a 'GRPC::Unknown' exception"
end
def record_route(call)
raise GRPC::BadStatus.new_status_exception(CANCELLED)
end
def route_chat(notes)
raise GRPC::BadStatus.new_status_exception(ABORTED, details = 'arbitrary', metadata = {somekey: 'val'})
end
end
def main
port = '0.0.0.0:50051'
s = GRPC::RpcServer.new
s.add_http2_port(port, :this_port_is_insecure)
GRPC.logger.info("... running insecurely on #{port}")
s.handle(CancellingAndErrorReturningServerImpl.new)
s.run_till_terminated
end
main

@ -51,7 +51,7 @@ Pod::Spec.new do |s|
:submodules => true,
}
s.ios.deployment_target = '7.1'
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'
s.requires_arc = false
@ -104,6 +104,7 @@ Pod::Spec.new do |s|
}
s.default_subspecs = 'Interface', 'Implementation'
s.compiler_flags = '-DGRPC_ARES=0'
# Like many other C libraries, gRPC-Core has its public headers under `include/<libname>/` and its
# sources and private headers in other directories outside `include/`. Cocoapods' linter doesn't
@ -151,7 +152,6 @@ Pod::Spec.new do |s|
'include/grpc/impl/codegen/gpr_slice.h',
'include/grpc/impl/codegen/gpr_types.h',
'include/grpc/impl/codegen/port_platform.h',
'include/grpc/impl/codegen/slice.h',
'include/grpc/impl/codegen/sync.h',
'include/grpc/impl/codegen/sync_generic.h',
'include/grpc/impl/codegen/sync_posix.h',
@ -172,6 +172,7 @@ Pod::Spec.new do |s|
'include/grpc/impl/codegen/exec_ctx_fwd.h',
'include/grpc/impl/codegen/grpc_types.h',
'include/grpc/impl/codegen/propagation_bits.h',
'include/grpc/impl/codegen/slice.h',
'include/grpc/impl/codegen/status.h',
'include/grpc/impl/codegen/atm.h',
'include/grpc/impl/codegen/atm_gcc_atomic.h',
@ -180,7 +181,6 @@ Pod::Spec.new do |s|
'include/grpc/impl/codegen/gpr_slice.h',
'include/grpc/impl/codegen/gpr_types.h',
'include/grpc/impl/codegen/port_platform.h',
'include/grpc/impl/codegen/slice.h',
'include/grpc/impl/codegen/sync.h',
'include/grpc/impl/codegen/sync_generic.h',
'include/grpc/impl/codegen/sync_posix.h',
@ -267,6 +267,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/handshaker_registry.h',
'src/core/lib/channel/http_client_filter.h',
'src/core/lib/channel/http_server_filter.h',
'src/core/lib/channel/max_age_filter.h',
'src/core/lib/channel/message_size_filter.h',
'src/core/lib/compression/algorithm_metadata.h',
'src/core/lib/compression/message_compress.h',
@ -304,6 +305,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/sockaddr_posix.h',
'src/core/lib/iomgr/sockaddr_utils.h',
'src/core/lib/iomgr/sockaddr_windows.h',
'src/core/lib/iomgr/socket_factory_posix.h',
'src/core/lib/iomgr/socket_mutator.h',
'src/core/lib/iomgr/socket_utils.h',
'src/core/lib/iomgr/socket_utils_posix.h',
@ -332,6 +334,7 @@ Pod::Spec.new do |s|
'src/core/lib/json/json_common.h',
'src/core/lib/json/json_reader.h',
'src/core/lib/json/json_writer.h',
'src/core/lib/slice/b64.h',
'src/core/lib/slice/percent_encoding.h',
'src/core/lib/slice/slice_hash_table.h',
'src/core/lib/slice/slice_internal.h',
@ -343,6 +346,7 @@ Pod::Spec.new do |s|
'src/core/lib/surface/channel_init.h',
'src/core/lib/surface/channel_stack_type.h',
'src/core/lib/surface/completion_queue.h',
'src/core/lib/surface/completion_queue_factory.h',
'src/core/lib/surface/event_string.h',
'src/core/lib/surface/init.h',
'src/core/lib/surface/lame_client.h',
@ -399,13 +403,12 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/security_connector.h',
'src/core/lib/security/transport/security_handshaker.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/b64.h',
'src/core/lib/security/util/json_util.h',
'src/core/lib/tsi/fake_transport_security.h',
'src/core/lib/tsi/ssl_transport_security.h',
'src/core/lib/tsi/ssl_types.h',
'src/core/lib/tsi/transport_security.h',
'src/core/lib/tsi/transport_security_interface.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security.h',
'src/core/tsi/transport_security_interface.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/client_channel/client_channel.h',
'src/core/ext/client_channel/client_channel_factory.h',
@ -434,6 +437,8 @@ Pod::Spec.new do |s|
'third_party/nanopb/pb_common.h',
'third_party/nanopb/pb_decode.h',
'third_party/nanopb/pb_encode.h',
'src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h',
'src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h',
'src/core/ext/load_reporting/load_reporting.h',
'src/core/ext/load_reporting/load_reporting_filter.h',
'src/core/ext/census/aggregation.h',
@ -464,6 +469,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/handshaker_registry.c',
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/channel/max_age_filter.c',
'src/core/lib/channel/message_size_filter.c',
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
@ -500,6 +506,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/resolve_address_windows.c',
'src/core/lib/iomgr/resource_quota.c',
'src/core/lib/iomgr/sockaddr_utils.c',
'src/core/lib/iomgr/socket_factory_posix.c',
'src/core/lib/iomgr/socket_mutator.c',
'src/core/lib/iomgr/socket_utils_common_posix.c',
'src/core/lib/iomgr/socket_utils_linux.c',
@ -537,6 +544,7 @@ Pod::Spec.new do |s|
'src/core/lib/json/json_reader.c',
'src/core/lib/json/json_string.c',
'src/core/lib/json/json_writer.c',
'src/core/lib/slice/b64.c',
'src/core/lib/slice/percent_encoding.c',
'src/core/lib/slice/slice.c',
'src/core/lib/slice/slice_buffer.c',
@ -555,6 +563,7 @@ Pod::Spec.new do |s|
'src/core/lib/surface/channel_ping.c',
'src/core/lib/surface/channel_stack_type.c',
'src/core/lib/surface/completion_queue.c',
'src/core/lib/surface/completion_queue_factory.c',
'src/core/lib/surface/event_string.c',
'src/core/lib/surface/lame_client.c',
'src/core/lib/surface/metadata_array.c',
@ -618,12 +627,11 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/security_handshaker.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',
'src/core/lib/tsi/transport_security.c',
'src/core/tsi/fake_transport_security.c',
'src/core/tsi/ssl_transport_security.c',
'src/core/tsi/transport_security.c',
'src/core/ext/transport/chttp2/server/chttp2_server.c',
'src/core/ext/transport/chttp2/client/secure/secure_channel_create.c',
'src/core/ext/client_channel/channel_connectivity.c',
@ -660,6 +668,9 @@ Pod::Spec.new do |s|
'third_party/nanopb/pb_encode.c',
'src/core/ext/lb_policy/pick_first/pick_first.c',
'src/core/ext/lb_policy/round_robin/round_robin.c',
'src/core/ext/resolver/dns/c_ares/dns_resolver_ares.c',
'src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c',
'src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.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',
@ -706,6 +717,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/handshaker_registry.h',
'src/core/lib/channel/http_client_filter.h',
'src/core/lib/channel/http_server_filter.h',
'src/core/lib/channel/max_age_filter.h',
'src/core/lib/channel/message_size_filter.h',
'src/core/lib/compression/algorithm_metadata.h',
'src/core/lib/compression/message_compress.h',
@ -743,6 +755,7 @@ Pod::Spec.new do |s|
'src/core/lib/iomgr/sockaddr_posix.h',
'src/core/lib/iomgr/sockaddr_utils.h',
'src/core/lib/iomgr/sockaddr_windows.h',
'src/core/lib/iomgr/socket_factory_posix.h',
'src/core/lib/iomgr/socket_mutator.h',
'src/core/lib/iomgr/socket_utils.h',
'src/core/lib/iomgr/socket_utils_posix.h',
@ -771,6 +784,7 @@ Pod::Spec.new do |s|
'src/core/lib/json/json_common.h',
'src/core/lib/json/json_reader.h',
'src/core/lib/json/json_writer.h',
'src/core/lib/slice/b64.h',
'src/core/lib/slice/percent_encoding.h',
'src/core/lib/slice/slice_hash_table.h',
'src/core/lib/slice/slice_internal.h',
@ -782,6 +796,7 @@ Pod::Spec.new do |s|
'src/core/lib/surface/channel_init.h',
'src/core/lib/surface/channel_stack_type.h',
'src/core/lib/surface/completion_queue.h',
'src/core/lib/surface/completion_queue_factory.h',
'src/core/lib/surface/event_string.h',
'src/core/lib/surface/init.h',
'src/core/lib/surface/lame_client.h',
@ -838,13 +853,12 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/security_connector.h',
'src/core/lib/security/transport/security_handshaker.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/b64.h',
'src/core/lib/security/util/json_util.h',
'src/core/lib/tsi/fake_transport_security.h',
'src/core/lib/tsi/ssl_transport_security.h',
'src/core/lib/tsi/ssl_types.h',
'src/core/lib/tsi/transport_security.h',
'src/core/lib/tsi/transport_security_interface.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security.h',
'src/core/tsi/transport_security_interface.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/client_channel/client_channel.h',
'src/core/ext/client_channel/client_channel_factory.h',
@ -873,6 +887,8 @@ Pod::Spec.new do |s|
'third_party/nanopb/pb_common.h',
'third_party/nanopb/pb_decode.h',
'third_party/nanopb/pb_encode.h',
'src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h',
'src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h',
'src/core/ext/load_reporting/load_reporting.h',
'src/core/ext/load_reporting/load_reporting_filter.h',
'src/core/ext/census/aggregation.h',
@ -895,8 +911,7 @@ Pod::Spec.new do |s|
s.subspec 'Cronet-Interface' do |ss|
ss.header_mappings_dir = 'include/grpc'
ss.source_files = 'include/grpc/grpc_cronet.h',
'src/core/ext/transport/cronet/transport/cronet_transport.h'
ss.source_files = 'include/grpc/grpc_cronet.h'
end
s.subspec 'Cronet-Implementation' do |ss|
@ -907,7 +922,7 @@ Pod::Spec.new do |s|
ss.dependency "#{s.name}/Cronet-Interface", version
ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.c',
'src/core/ext/transport/cronet/transport/cronet_transport.c',
'src/core/ext/transport/cronet/transport/cronet_transport.{c,h}',
'third_party/objective_c/Cronet/bidirectional_stream_c.h'
end
@ -922,7 +937,7 @@ Pod::Spec.new do |s|
'test/core/end2end/end2end_test_utils.c',
'test/core/end2end/tests/*.{c,h}',
'test/core/end2end/data/*.{c,h}',
'test/core/util/debugger_macros.c',
'test/core/util/debugger_macros.{c,h}',
'test/core/util/test_config.{c,h}',
'test/core/util/port.h',
'test/core/util/port.c',

@ -48,7 +48,7 @@ Pod::Spec.new do |s|
:tag => "v#{version}",
}
s.ios.deployment_target = '7.1'
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'
name = 'ProtoRPC'

@ -48,7 +48,7 @@ Pod::Spec.new do |s|
:tag => "v#{version}",
}
s.ios.deployment_target = '7.1'
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'
name = 'RxLibrary'

@ -47,7 +47,7 @@ Pod::Spec.new do |s|
:tag => "v#{version}",
}
s.ios.deployment_target = '7.1'
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'
name = 'GRPCClient'

@ -53,6 +53,9 @@ EXPORTS
grpc_shutdown
grpc_version_string
grpc_g_stands_for
grpc_completion_queue_factory_lookup
grpc_completion_queue_create_for_next
grpc_completion_queue_create_for_pluck
grpc_completion_queue_create
grpc_completion_queue_next
grpc_completion_queue_pluck

@ -76,7 +76,6 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/gpr_slice.h )
s.files += %w( include/grpc/impl/codegen/gpr_types.h )
s.files += %w( include/grpc/impl/codegen/port_platform.h )
s.files += %w( include/grpc/impl/codegen/slice.h )
s.files += %w( include/grpc/impl/codegen/sync.h )
s.files += %w( include/grpc/impl/codegen/sync_generic.h )
s.files += %w( include/grpc/impl/codegen/sync_posix.h )
@ -157,6 +156,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/exec_ctx_fwd.h )
s.files += %w( include/grpc/impl/codegen/grpc_types.h )
s.files += %w( include/grpc/impl/codegen/propagation_bits.h )
s.files += %w( include/grpc/impl/codegen/slice.h )
s.files += %w( include/grpc/impl/codegen/status.h )
s.files += %w( include/grpc/impl/codegen/atm.h )
s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h )
@ -165,7 +165,6 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/gpr_slice.h )
s.files += %w( include/grpc/impl/codegen/gpr_types.h )
s.files += %w( include/grpc/impl/codegen/port_platform.h )
s.files += %w( include/grpc/impl/codegen/slice.h )
s.files += %w( include/grpc/impl/codegen/sync.h )
s.files += %w( include/grpc/impl/codegen/sync_generic.h )
s.files += %w( include/grpc/impl/codegen/sync_posix.h )
@ -184,6 +183,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/handshaker_registry.h )
s.files += %w( src/core/lib/channel/http_client_filter.h )
s.files += %w( src/core/lib/channel/http_server_filter.h )
s.files += %w( src/core/lib/channel/max_age_filter.h )
s.files += %w( src/core/lib/channel/message_size_filter.h )
s.files += %w( src/core/lib/compression/algorithm_metadata.h )
s.files += %w( src/core/lib/compression/message_compress.h )
@ -221,6 +221,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/sockaddr_posix.h )
s.files += %w( src/core/lib/iomgr/sockaddr_utils.h )
s.files += %w( src/core/lib/iomgr/sockaddr_windows.h )
s.files += %w( src/core/lib/iomgr/socket_factory_posix.h )
s.files += %w( src/core/lib/iomgr/socket_mutator.h )
s.files += %w( src/core/lib/iomgr/socket_utils.h )
s.files += %w( src/core/lib/iomgr/socket_utils_posix.h )
@ -249,6 +250,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/json/json_common.h )
s.files += %w( src/core/lib/json/json_reader.h )
s.files += %w( src/core/lib/json/json_writer.h )
s.files += %w( src/core/lib/slice/b64.h )
s.files += %w( src/core/lib/slice/percent_encoding.h )
s.files += %w( src/core/lib/slice/slice_hash_table.h )
s.files += %w( src/core/lib/slice/slice_internal.h )
@ -260,6 +262,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/surface/channel_init.h )
s.files += %w( src/core/lib/surface/channel_stack_type.h )
s.files += %w( src/core/lib/surface/completion_queue.h )
s.files += %w( src/core/lib/surface/completion_queue_factory.h )
s.files += %w( src/core/lib/surface/event_string.h )
s.files += %w( src/core/lib/surface/init.h )
s.files += %w( src/core/lib/surface/lame_client.h )
@ -316,13 +319,12 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/transport/security_connector.h )
s.files += %w( src/core/lib/security/transport/security_handshaker.h )
s.files += %w( src/core/lib/security/transport/tsi_error.h )
s.files += %w( src/core/lib/security/util/b64.h )
s.files += %w( src/core/lib/security/util/json_util.h )
s.files += %w( src/core/lib/tsi/fake_transport_security.h )
s.files += %w( src/core/lib/tsi/ssl_transport_security.h )
s.files += %w( src/core/lib/tsi/ssl_types.h )
s.files += %w( src/core/lib/tsi/transport_security.h )
s.files += %w( src/core/lib/tsi/transport_security_interface.h )
s.files += %w( src/core/tsi/fake_transport_security.h )
s.files += %w( src/core/tsi/ssl_transport_security.h )
s.files += %w( src/core/tsi/ssl_types.h )
s.files += %w( src/core/tsi/transport_security.h )
s.files += %w( src/core/tsi/transport_security_interface.h )
s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.h )
s.files += %w( src/core/ext/client_channel/client_channel.h )
s.files += %w( src/core/ext/client_channel/client_channel_factory.h )
@ -351,6 +353,8 @@ Gem::Specification.new do |s|
s.files += %w( third_party/nanopb/pb_common.h )
s.files += %w( third_party/nanopb/pb_decode.h )
s.files += %w( third_party/nanopb/pb_encode.h )
s.files += %w( src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h )
s.files += %w( src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h )
s.files += %w( src/core/ext/load_reporting/load_reporting.h )
s.files += %w( src/core/ext/load_reporting/load_reporting_filter.h )
s.files += %w( src/core/ext/census/aggregation.h )
@ -381,6 +385,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/handshaker_registry.c )
s.files += %w( src/core/lib/channel/http_client_filter.c )
s.files += %w( src/core/lib/channel/http_server_filter.c )
s.files += %w( src/core/lib/channel/max_age_filter.c )
s.files += %w( src/core/lib/channel/message_size_filter.c )
s.files += %w( src/core/lib/compression/compression.c )
s.files += %w( src/core/lib/compression/message_compress.c )
@ -417,6 +422,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/iomgr/resolve_address_windows.c )
s.files += %w( src/core/lib/iomgr/resource_quota.c )
s.files += %w( src/core/lib/iomgr/sockaddr_utils.c )
s.files += %w( src/core/lib/iomgr/socket_factory_posix.c )
s.files += %w( src/core/lib/iomgr/socket_mutator.c )
s.files += %w( src/core/lib/iomgr/socket_utils_common_posix.c )
s.files += %w( src/core/lib/iomgr/socket_utils_linux.c )
@ -454,6 +460,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/json/json_reader.c )
s.files += %w( src/core/lib/json/json_string.c )
s.files += %w( src/core/lib/json/json_writer.c )
s.files += %w( src/core/lib/slice/b64.c )
s.files += %w( src/core/lib/slice/percent_encoding.c )
s.files += %w( src/core/lib/slice/slice.c )
s.files += %w( src/core/lib/slice/slice_buffer.c )
@ -472,6 +479,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/surface/channel_ping.c )
s.files += %w( src/core/lib/surface/channel_stack_type.c )
s.files += %w( src/core/lib/surface/completion_queue.c )
s.files += %w( src/core/lib/surface/completion_queue_factory.c )
s.files += %w( src/core/lib/surface/event_string.c )
s.files += %w( src/core/lib/surface/lame_client.c )
s.files += %w( src/core/lib/surface/metadata_array.c )
@ -535,12 +543,11 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/transport/security_handshaker.c )
s.files += %w( src/core/lib/security/transport/server_auth_filter.c )
s.files += %w( src/core/lib/security/transport/tsi_error.c )
s.files += %w( src/core/lib/security/util/b64.c )
s.files += %w( src/core/lib/security/util/json_util.c )
s.files += %w( src/core/lib/surface/init_secure.c )
s.files += %w( src/core/lib/tsi/fake_transport_security.c )
s.files += %w( src/core/lib/tsi/ssl_transport_security.c )
s.files += %w( src/core/lib/tsi/transport_security.c )
s.files += %w( src/core/tsi/fake_transport_security.c )
s.files += %w( src/core/tsi/ssl_transport_security.c )
s.files += %w( src/core/tsi/transport_security.c )
s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.c )
s.files += %w( src/core/ext/transport/chttp2/client/secure/secure_channel_create.c )
s.files += %w( src/core/ext/client_channel/channel_connectivity.c )
@ -577,6 +584,9 @@ Gem::Specification.new do |s|
s.files += %w( third_party/nanopb/pb_encode.c )
s.files += %w( src/core/ext/lb_policy/pick_first/pick_first.c )
s.files += %w( src/core/ext/lb_policy/round_robin/round_robin.c )
s.files += %w( src/core/ext/resolver/dns/c_ares/dns_resolver_ares.c )
s.files += %w( src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c )
s.files += %w( src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.c )
s.files += %w( src/core/ext/resolver/dns/native/dns_resolver.c )
s.files += %w( src/core/ext/resolver/sockaddr/sockaddr_resolver.c )
s.files += %w( src/core/ext/load_reporting/load_reporting.c )
@ -1030,4 +1040,77 @@ Gem::Specification.new do |s|
s.files += %w( third_party/zlib/trees.c )
s.files += %w( third_party/zlib/uncompr.c )
s.files += %w( third_party/zlib/zutil.c )
s.files += %w( third_party/cares/cares/ares.h )
s.files += %w( third_party/cares/cares/ares_data.h )
s.files += %w( third_party/cares/cares/ares_dns.h )
s.files += %w( third_party/cares/cares/ares_getenv.h )
s.files += %w( third_party/cares/cares/ares_getopt.h )
s.files += %w( third_party/cares/cares/ares_inet_net_pton.h )
s.files += %w( third_party/cares/cares/ares_iphlpapi.h )
s.files += %w( third_party/cares/cares/ares_ipv6.h )
s.files += %w( third_party/cares/cares/ares_library_init.h )
s.files += %w( third_party/cares/cares/ares_llist.h )
s.files += %w( third_party/cares/cares/ares_nowarn.h )
s.files += %w( third_party/cares/cares/ares_platform.h )
s.files += %w( third_party/cares/cares/ares_private.h )
s.files += %w( third_party/cares/cares/ares_rules.h )
s.files += %w( third_party/cares/cares/ares_setup.h )
s.files += %w( third_party/cares/cares/ares_strcasecmp.h )
s.files += %w( third_party/cares/cares/ares_strdup.h )
s.files += %w( third_party/cares/cares/ares_version.h )
s.files += %w( third_party/cares/cares/bitncmp.h )
s.files += %w( third_party/cares/cares/config-win32.h )
s.files += %w( third_party/cares/cares/setup_once.h )
s.files += %w( third_party/cares/ares_build.h )
s.files += %w( third_party/cares/config_linux/ares_config.h )
s.files += %w( third_party/cares/config_darwin/ares_config.h )
s.files += %w( third_party/cares/cares/ares__close_sockets.c )
s.files += %w( third_party/cares/cares/ares__get_hostent.c )
s.files += %w( third_party/cares/cares/ares__read_line.c )
s.files += %w( third_party/cares/cares/ares__timeval.c )
s.files += %w( third_party/cares/cares/ares_cancel.c )
s.files += %w( third_party/cares/cares/ares_create_query.c )
s.files += %w( third_party/cares/cares/ares_data.c )
s.files += %w( third_party/cares/cares/ares_destroy.c )
s.files += %w( third_party/cares/cares/ares_expand_name.c )
s.files += %w( third_party/cares/cares/ares_expand_string.c )
s.files += %w( third_party/cares/cares/ares_fds.c )
s.files += %w( third_party/cares/cares/ares_free_hostent.c )
s.files += %w( third_party/cares/cares/ares_free_string.c )
s.files += %w( third_party/cares/cares/ares_getenv.c )
s.files += %w( third_party/cares/cares/ares_gethostbyaddr.c )
s.files += %w( third_party/cares/cares/ares_gethostbyname.c )
s.files += %w( third_party/cares/cares/ares_getnameinfo.c )
s.files += %w( third_party/cares/cares/ares_getopt.c )
s.files += %w( third_party/cares/cares/ares_getsock.c )
s.files += %w( third_party/cares/cares/ares_init.c )
s.files += %w( third_party/cares/cares/ares_library_init.c )
s.files += %w( third_party/cares/cares/ares_llist.c )
s.files += %w( third_party/cares/cares/ares_mkquery.c )
s.files += %w( third_party/cares/cares/ares_nowarn.c )
s.files += %w( third_party/cares/cares/ares_options.c )
s.files += %w( third_party/cares/cares/ares_parse_a_reply.c )
s.files += %w( third_party/cares/cares/ares_parse_aaaa_reply.c )
s.files += %w( third_party/cares/cares/ares_parse_mx_reply.c )
s.files += %w( third_party/cares/cares/ares_parse_naptr_reply.c )
s.files += %w( third_party/cares/cares/ares_parse_ns_reply.c )
s.files += %w( third_party/cares/cares/ares_parse_ptr_reply.c )
s.files += %w( third_party/cares/cares/ares_parse_soa_reply.c )
s.files += %w( third_party/cares/cares/ares_parse_srv_reply.c )
s.files += %w( third_party/cares/cares/ares_parse_txt_reply.c )
s.files += %w( third_party/cares/cares/ares_platform.c )
s.files += %w( third_party/cares/cares/ares_process.c )
s.files += %w( third_party/cares/cares/ares_query.c )
s.files += %w( third_party/cares/cares/ares_search.c )
s.files += %w( third_party/cares/cares/ares_send.c )
s.files += %w( third_party/cares/cares/ares_strcasecmp.c )
s.files += %w( third_party/cares/cares/ares_strdup.c )
s.files += %w( third_party/cares/cares/ares_strerror.c )
s.files += %w( third_party/cares/cares/ares_timeout.c )
s.files += %w( third_party/cares/cares/ares_version.c )
s.files += %w( third_party/cares/cares/ares_writev.c )
s.files += %w( third_party/cares/cares/bitncmp.c )
s.files += %w( third_party/cares/cares/inet_net_pton.c )
s.files += %w( third_party/cares/cares/inet_ntop.c )
s.files += %w( third_party/cares/cares/windows_port.c )
end

@ -101,6 +101,39 @@ class AsyncWriterInterface {
/// \param[in] msg The message to be written.
/// \param[in] tag The tag identifying the operation.
virtual void Write(const W& msg, void* tag) = 0;
/// Request the writing of \a msg using WriteOptions \a options with
/// identifying tag \a tag.
///
/// Only one write may be outstanding at any given time. This means that
/// after calling Write, one must wait to receive \a tag from the completion
/// queue BEFORE calling Write again.
/// WriteOptions \a options is used to set the write options of this message.
/// This is thread-safe with respect to \a Read
///
/// \param[in] msg The message to be written.
/// \param[in] options The WriteOptions to be used to write this message.
/// \param[in] tag The tag identifying the operation.
virtual void Write(const W& msg, WriteOptions options, void* tag) = 0;
/// Request the writing of \a msg and coalesce it with the writing
/// of trailing metadata, using WriteOptions \a options with identifying tag
/// \a tag.
///
/// For client, WriteLast is equivalent of performing Write and WritesDone in
/// a single step.
/// For server, WriteLast buffers the \a msg. The writing of \a msg is held
/// until Finish is called, where \a msg and trailing metadata are coalesced
/// and write is initiated. Note that WriteLast can only buffer \a msg up to
/// the flow control window size. If \a msg size is larger than the window
/// size, it will be sent on wire without buffering.
///
/// \param[in] msg The message to be written.
/// \param[in] options The WriteOptions to be used to write this message.
/// \param[in] tag The tag identifying the operation.
void WriteLast(const W& msg, WriteOptions options, void* tag) {
Write(msg, options.set_last_message(), tag);
}
};
template <class R>
@ -183,11 +216,17 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
: context_(context), call_(channel->CreateCall(method, context, cq)) {
finish_ops_.RecvMessage(response);
finish_ops_.AllowNoMessage();
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&init_ops_);
// if corked bit is set in context, we buffer up the initial metadata to
// coalesce with later message to be sent. No op is performed.
if (context_->initial_metadata_corked_) {
write_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
} else {
write_ops_.set_output_tag(tag);
write_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&write_ops_);
}
}
void ReadInitialMetadata(void* tag) override {
@ -205,10 +244,21 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
call_.PerformOps(&write_ops_);
}
void Write(const W& msg, WriteOptions options, void* tag) override {
write_ops_.set_output_tag(tag);
if (options.is_last_message()) {
options.set_buffer_hint();
write_ops_.ClientSendClose();
}
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
call_.PerformOps(&write_ops_);
}
void WritesDone(void* tag) override {
writes_done_ops_.set_output_tag(tag);
writes_done_ops_.ClientSendClose();
call_.PerformOps(&writes_done_ops_);
write_ops_.set_output_tag(tag);
write_ops_.ClientSendClose();
call_.PerformOps(&write_ops_);
}
void Finish(Status* status, void* tag) override {
@ -223,10 +273,9 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata> init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpSendMessage> write_ops_;
CallOpSet<CallOpClientSendClose> writes_done_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
write_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
CallOpClientRecvStatus>
finish_ops_;
@ -253,10 +302,17 @@ class ClientAsyncReaderWriter final
const RpcMethod& method, ClientContext* context,
void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&init_ops_);
if (context_->initial_metadata_corked_) {
// if corked bit is set in context, we buffer up the initial metadata to
// coalesce with later message to be sent. No op is performed.
write_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
} else {
write_ops_.set_output_tag(tag);
write_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&write_ops_);
}
}
void ReadInitialMetadata(void* tag) override {
@ -283,10 +339,21 @@ class ClientAsyncReaderWriter final
call_.PerformOps(&write_ops_);
}
void Write(const W& msg, WriteOptions options, void* tag) override {
write_ops_.set_output_tag(tag);
if (options.is_last_message()) {
options.set_buffer_hint();
write_ops_.ClientSendClose();
}
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
call_.PerformOps(&write_ops_);
}
void WritesDone(void* tag) override {
writes_done_ops_.set_output_tag(tag);
writes_done_ops_.ClientSendClose();
call_.PerformOps(&writes_done_ops_);
write_ops_.set_output_tag(tag);
write_ops_.ClientSendClose();
call_.PerformOps(&write_ops_);
}
void Finish(Status* status, void* tag) override {
@ -301,11 +368,10 @@ class ClientAsyncReaderWriter final
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata> init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendMessage> write_ops_;
CallOpSet<CallOpClientSendClose> writes_done_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
write_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
};
@ -395,6 +461,20 @@ class ServerAsyncWriterInterface : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
virtual void Finish(const Status& status, void* tag) = 0;
/// Request the writing of \a msg and coalesce it with trailing metadata which
/// contains \a status, using WriteOptions options with identifying tag \a
/// tag.
///
/// WriteAndFinish is equivalent of performing WriteLast and Finish in a
/// single step.
///
/// \param[in] msg The message to be written.
/// \param[in] options The WriteOptions to be used to write this message.
/// \param[in] status The Status that server returns to client.
/// \param[in] tag The tag identifying the operation.
virtual void WriteAndFinish(const W& msg, WriteOptions options,
const Status& status, void* tag) = 0;
};
template <class W>
@ -418,29 +498,37 @@ class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
void Write(const W& msg, void* tag) override {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
write_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
EnsureInitialMetadataSent(&write_ops_);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void Write(const W& msg, WriteOptions options, void* tag) override {
write_ops_.set_output_tag(tag);
if (options.is_last_message()) {
options.set_buffer_hint();
}
EnsureInitialMetadataSent(&write_ops_);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
call_.PerformOps(&write_ops_);
}
void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
void* tag) override {
write_ops_.set_output_tag(tag);
EnsureInitialMetadataSent(&write_ops_);
options.set_buffer_hint();
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
write_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&write_ops_);
}
void Finish(const Status& status, void* tag) override {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
finish_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
EnsureInitialMetadataSent(&finish_ops_);
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
@ -448,10 +536,24 @@ class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
private:
void BindCall(Call* call) override { call_ = *call; }
template <class T>
void EnsureInitialMetadataSent(T* ops) {
if (!ctx_->sent_initial_metadata_) {
ops->SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
ops->set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
}
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus>
write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
};
@ -462,6 +564,20 @@ class ServerAsyncReaderWriterInterface : public ServerAsyncStreamingInterface,
public AsyncReaderInterface<R> {
public:
virtual void Finish(const Status& status, void* tag) = 0;
/// Request the writing of \a msg and coalesce it with trailing metadata which
/// contains \a status, using WriteOptions options with identifying tag \a
/// tag.
///
/// WriteAndFinish is equivalent of performing WriteLast and Finish in a
/// single step.
///
/// \param[in] msg The message to be written.
/// \param[in] options The WriteOptions to be used to write this message.
/// \param[in] status The Status that server returns to client.
/// \param[in] tag The tag identifying the operation.
virtual void WriteAndFinish(const W& msg, WriteOptions options,
const Status& status, void* tag) = 0;
};
template <class W, class R>
@ -492,29 +608,36 @@ class ServerAsyncReaderWriter final
void Write(const W& msg, void* tag) override {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
write_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
EnsureInitialMetadataSent(&write_ops_);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void Write(const W& msg, WriteOptions options, void* tag) override {
write_ops_.set_output_tag(tag);
if (options.is_last_message()) {
options.set_buffer_hint();
}
EnsureInitialMetadataSent(&write_ops_);
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
call_.PerformOps(&write_ops_);
}
void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
void* tag) override {
write_ops_.set_output_tag(tag);
EnsureInitialMetadataSent(&write_ops_);
options.set_buffer_hint();
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
write_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&write_ops_);
}
void Finish(const Status& status, void* tag) override {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
finish_ops_.set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
EnsureInitialMetadataSent(&finish_ops_);
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
@ -524,11 +647,25 @@ class ServerAsyncReaderWriter final
void BindCall(Call* call) override { call_ = *call; }
template <class T>
void EnsureInitialMetadataSent(T* ops) {
if (!ctx_->sent_initial_metadata_) {
ops->SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
if (ctx_->compression_level_set()) {
ops->set_compression_level(ctx_->compression_level());
}
ctx_->sent_initial_metadata_ = true;
}
}
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus>
write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
};

@ -84,8 +84,9 @@ inline grpc_metadata* FillMetadataArray(
/// Per-message write options.
class WriteOptions {
public:
WriteOptions() : flags_(0) {}
WriteOptions(const WriteOptions& other) : flags_(other.flags_) {}
WriteOptions() : flags_(0), last_message_(false) {}
WriteOptions(const WriteOptions& other)
: flags_(other.flags_), last_message_(other.last_message_) {}
/// Clear all flags.
inline void Clear() { flags_ = 0; }
@ -141,6 +142,43 @@ class WriteOptions {
/// \sa GRPC_WRITE_BUFFER_HINT
inline bool get_buffer_hint() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
/// corked bit: aliases set_buffer_hint currently, with the intent that
/// set_buffer_hint will be removed in the future
inline WriteOptions& set_corked() {
SetBit(GRPC_WRITE_BUFFER_HINT);
return *this;
}
inline WriteOptions& clear_corked() {
ClearBit(GRPC_WRITE_BUFFER_HINT);
return *this;
}
inline bool is_corked() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
/// last-message bit: indicates this is the last message in a stream
/// client-side: makes Write the equivalent of performing Write, WritesDone
/// in a single step
/// server-side: hold the Write until the service handler returns (sync api)
/// or until Finish is called (async api)
inline WriteOptions& set_last_message() {
last_message_ = true;
return *this;
}
/// Clears flag indicating that this is the last message in a stream,
/// disabling coalescing.
inline WriteOptions& clear_last_messsage() {
last_message_ = false;
return *this;
}
/// Get value for the flag indicating that this is the last message, and
/// should be coalesced with trailing metadata.
///
/// \sa GRPC_WRITE_LAST_MESSAGE
bool is_last_message() const { return last_message_; }
WriteOptions& operator=(const WriteOptions& rhs) {
flags_ = rhs.flags_;
return *this;
@ -154,6 +192,7 @@ class WriteOptions {
bool GetBit(const uint32_t mask) const { return (flags_ & mask) != 0; }
uint32_t flags_;
bool last_message_;
};
/// Default argument for CallOpSet. I is unused by the class, but can be
@ -224,7 +263,7 @@ class CallOpSendMessage {
/// after use.
template <class M>
Status SendMessage(const M& message,
const WriteOptions& options) GRPC_MUST_USE_RESULT;
WriteOptions options) GRPC_MUST_USE_RESULT;
template <class M>
Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
@ -252,8 +291,7 @@ class CallOpSendMessage {
};
template <class M>
Status CallOpSendMessage::SendMessage(const M& message,
const WriteOptions& options) {
Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) {
write_options_ = options;
return SerializationTraits<M>::Serialize(message, &send_buf_, &own_buf_);
}

@ -281,6 +281,17 @@ class ClientContext {
/// \param algorithm The compression algorithm used for the client call.
void set_compression_algorithm(grpc_compression_algorithm algorithm);
/// Flag whether the initial metadata should be \a corked
///
/// If \a corked is true, then the initial metadata will be colasced with the
/// write of first message in the stream.
///
/// \param corked The flag indicating whether the initial metadata is to be
/// corked or not.
void set_initial_metadata_corked(bool corked) {
initial_metadata_corked_ = corked;
}
/// Return the peer uri in a string.
///
/// \warning This value is never authenticated or subject to any security
@ -357,7 +368,8 @@ class ClientContext {
(cacheable_ ? GRPC_INITIAL_METADATA_CACHEABLE_REQUEST : 0) |
(wait_for_ready_explicitly_set_
? GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET
: 0);
: 0) |
(initial_metadata_corked_ ? GRPC_INITIAL_METADATA_CORKED : 0);
}
grpc::string authority() { return authority_; }
@ -384,6 +396,7 @@ class ClientContext {
PropagationOptions propagation_options_;
grpc_compression_algorithm compression_algorithm_;
bool initial_metadata_corked_;
};
} // namespace grpc

@ -51,18 +51,26 @@ extern GrpcLibraryInterface* g_glip;
/// Classes that require gRPC to be initialized should inherit from this class.
class GrpcLibraryCodegen {
public:
GrpcLibraryCodegen() {
GPR_CODEGEN_ASSERT(g_glip &&
"gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer.");
g_glip->init();
GrpcLibraryCodegen(bool call_grpc_init = true) : grpc_init_called_(false) {
if (call_grpc_init) {
GPR_CODEGEN_ASSERT(g_glip &&
"gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer.");
g_glip->init();
grpc_init_called_ = true;
}
}
virtual ~GrpcLibraryCodegen() {
GPR_CODEGEN_ASSERT(g_glip &&
"gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer.");
g_glip->shutdown();
if (grpc_init_called_) {
GPR_CODEGEN_ASSERT(g_glip &&
"gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer.");
g_glip->shutdown();
}
}
private:
bool grpc_init_called_;
};
} // namespace grpc

@ -39,7 +39,6 @@
#include <vector>
#include <grpc/impl/codegen/compression_types.h>
#include <grpc/load_reporting.h>
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/create_auth_context.h>

@ -100,22 +100,40 @@ class WriterInterface {
public:
virtual ~WriterInterface() {}
/// Blocking write \a msg to the stream with options.
/// Blocking write \a msg to the stream with WriteOptions \a options.
/// This is thread-safe with respect to \a Read
///
/// \param msg The message to be written to the stream.
/// \param options Options affecting the write operation.
/// \param options The WriteOptions affecting the write operation.
///
/// \return \a true on success, \a false when the stream has been closed.
virtual bool Write(const W& msg, const WriteOptions& options) = 0;
virtual bool Write(const W& msg, WriteOptions options) = 0;
/// Blocking write \a msg to the stream with default options.
/// Blocking write \a msg to the stream with default write options.
/// This is thread-safe with respect to \a Read
///
/// \param msg The message to be written to the stream.
///
/// \return \a true on success, \a false when the stream has been closed.
inline bool Write(const W& msg) { return Write(msg, WriteOptions()); }
/// Write \a msg and coalesce it with the writing of trailing metadata, using
/// WriteOptions \a options.
///
/// For client, WriteLast is equivalent of performing Write and WritesDone in
/// a single step. \a msg and trailing metadata are coalesced and sent on wire
/// by calling this function.
/// For server, WriteLast buffers the \a msg. The writing of \a msg is held
/// until the service handler returns, where \a msg and trailing metadata are
/// coalesced and sent on wire. Note that WriteLast can only buffer \a msg up
/// to the flow control window size. If \a msg size is larger than the window
/// size, it will be sent on wire without buffering.
///
/// \param[in] msg The message to be written to the stream.
/// \param[in] options The WriteOptions to be used to write this message.
void WriteLast(const W& msg, WriteOptions options) {
Write(msg, options.set_last_message());
}
};
/// Client-side interface for streaming reads of message of type \a R.
@ -213,11 +231,13 @@ class ClientWriter : public ClientWriterInterface<W> {
finish_ops_.RecvMessage(response);
finish_ops_.AllowNoMessage();
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&ops);
cq_.Pluck(&ops);
if (!context_->initial_metadata_corked_) {
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&ops);
cq_.Pluck(&ops);
}
}
void WaitForInitialMetadata() {
@ -230,11 +250,24 @@ class ClientWriter : public ClientWriterInterface<W> {
}
using WriterInterface<W>::Write;
bool Write(const W& msg, const WriteOptions& options) override {
CallOpSet<CallOpSendMessage> ops;
bool Write(const W& msg, WriteOptions options) override {
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpClientSendClose>
ops;
if (options.is_last_message()) {
options.set_buffer_hint();
ops.ClientSendClose();
}
if (context_->initial_metadata_corked_) {
ops.SendInitialMetadata(context_->send_initial_metadata_,
context_->initial_metadata_flags());
context_->set_initial_metadata_corked(false);
}
if (!ops.SendMessage(msg, options).ok()) {
return false;
}
call_.PerformOps(&ops);
return cq_.Pluck(&ops);
}
@ -293,11 +326,13 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context)
: context_(context), call_(channel->CreateCall(method, context, &cq_)) {
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&ops);
cq_.Pluck(&ops);
if (!context_->initial_metadata_corked_) {
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&ops);
cq_.Pluck(&ops);
}
}
void WaitForInitialMetadata() override {
@ -325,9 +360,24 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
}
using WriterInterface<W>::Write;
bool Write(const W& msg, const WriteOptions& options) override {
CallOpSet<CallOpSendMessage> ops;
if (!ops.SendMessage(msg, options).ok()) return false;
bool Write(const W& msg, WriteOptions options) override {
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpClientSendClose>
ops;
if (options.is_last_message()) {
options.set_buffer_hint();
ops.ClientSendClose();
}
if (context_->initial_metadata_corked_) {
ops.SendInitialMetadata(context_->send_initial_metadata_,
context_->initial_metadata_flags());
context_->set_initial_metadata_corked(false);
}
if (!ops.SendMessage(msg, options).ok()) {
return false;
}
call_.PerformOps(&ops);
return cq_.Pluck(&ops);
}
@ -423,7 +473,10 @@ class ServerWriter final : public ServerWriterInterface<W> {
}
using WriterInterface<W>::Write;
bool Write(const W& msg, const WriteOptions& options) override {
bool Write(const W& msg, WriteOptions options) override {
if (options.is_last_message()) {
options.set_buffer_hint();
}
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> ops;
if (!ops.SendMessage(msg, options).ok()) {
return false;
@ -485,7 +538,10 @@ class ServerReaderWriterBody final {
return call_->cq()->Pluck(&ops) && ops.got_message;
}
bool Write(const W& msg, const WriteOptions& options) {
bool Write(const W& msg, WriteOptions options) {
if (options.is_last_message()) {
options.set_buffer_hint();
}
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> ops;
if (!ops.SendMessage(msg, options).ok()) {
return false;
@ -523,7 +579,7 @@ class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
bool Read(R* msg) override { return body_.Read(msg); }
using WriterInterface<W>::Write;
bool Write(const W& msg, const WriteOptions& options) override {
bool Write(const W& msg, WriteOptions options) override {
return body_.Write(msg, options);
}
@ -562,8 +618,7 @@ class ServerUnaryStreamer final
}
using WriterInterface<ResponseType>::Write;
bool Write(const ResponseType& response,
const WriteOptions& options) override {
bool Write(const ResponseType& response, WriteOptions options) override {
if (write_done_ || !read_done_) {
return false;
}
@ -604,8 +659,7 @@ class ServerSplitStreamer final
}
using WriterInterface<ResponseType>::Write;
bool Write(const ResponseType& response,
const WriteOptions& options) override {
bool Write(const ResponseType& response, WriteOptions options) override {
return read_done_ && body_.Write(response, options);
}

@ -88,6 +88,8 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen {
virtual void PostSynchronousRequest(ServerContext* context) = 0;
/// Called before server is started.
virtual void PreServerStart(Server* server) {}
/// Called after a server port is added.
virtual void AddPort(Server* server, int port) {}
};
/// Set the global callback object. Can only be called once. Does not take
/// ownership of callbacks, and expects the pointed to object to be alive

@ -93,6 +93,71 @@ GRPCAPI const char *grpc_version_string(void);
/** Return a string specifying what the 'g' in gRPC stands for */
GRPCAPI const char *grpc_g_stands_for(void);
/** Specifies the type of APIs to use to pop events from the completion queue */
typedef enum {
/* Events are popped out by calling grpc_completion_queue_next() API ONLY */
GRPC_CQ_NEXT = 1,
/* Events are popped out by calling grpc_completion_queue_pluck() API ONLY */
GRPC_CQ_PLUCK
} grpc_cq_completion_type;
/** Completion queues internally MAY maintain a set of file descriptors in a
structure called 'pollset'. This enum specifies if a completion queue has an
associated pollset and any restrictions on the type of file descriptors that
can be present in the pollset.
I/O progress can only be made when grpc_completion_queue_next() or
grpc_completion_queue_pluck() are called on the completion queue (unless the
grpc_cq_polling_type is GRPC_CQ_NON_POLLING) and hence it is very important
to actively call these APIs */
typedef enum {
/** The completion queue will have an associated pollset and there is no
restriction on the type of file descriptors the pollset may contain */
GRPC_CQ_DEFAULT_POLLING,
/* Similar to GRPC_CQ_DEFAULT_POLLING except that the completion queues will
not contain any 'listening file descriptors' (i.e file descriptors used to
listen to incoming channels) */
GRPC_CQ_NON_LISTENING,
/* The completion queue will not have an associated pollset. Note that
grpc_completion_queue_next() or grpc_completion_queue_pluck() MUST still be
called to pop events from the completion queue; it is not required to call
them actively to make I/O progress */
GRPC_CQ_NON_POLLING
} grpc_cq_polling_type;
#define GRPC_CQ_CURRENT_VERSION 1
typedef struct grpc_completion_queue_attributes {
/* The version number of this structure. More fields might be added to this
structure in future. */
int version; /* Set to GRPC_CQ_CURRENT_VERSION */
grpc_cq_completion_type cq_completion_type;
grpc_cq_polling_type cq_polling_type;
} grpc_completion_queue_attributes;
/** The completion queue factory structure is opaque to the callers of grpc */
typedef struct grpc_completion_queue_factory grpc_completion_queue_factory;
/** Returns the completion queue factory based on the attributes. MAY return a
NULL if no factory can be found */
GRPCAPI const grpc_completion_queue_factory *
grpc_completion_queue_factory_lookup(
const grpc_completion_queue_attributes *attributes);
/** Helper function to create a completion queue with grpc_cq_completion_type
of GRPC_CQ_NEXT and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING */
GRPCAPI grpc_completion_queue *grpc_completion_queue_create_for_next(
void *reserved);
/** Helper function to create a completion queue with grpc_cq_completion_type
of GRPC_CQ_PLUCK and grpc_cq_polling_type of GRPC_CQ_DEFAULT_POLLING */
GRPCAPI grpc_completion_queue *grpc_completion_queue_create_for_pluck(
void *reserved);
/** Create a completion queue */
GRPCAPI grpc_completion_queue *grpc_completion_queue_create(void *reserved);

@ -85,6 +85,11 @@ static __inline int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
p, &o, n, 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED));
}
static __inline int gpr_atm_full_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
return GPR_ATM_INC_CAS_THEN(__atomic_compare_exchange_n(
p, &o, n, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED));
}
#define gpr_atm_full_xchg(p, n) \
GPR_ATM_INC_CAS_THEN(__atomic_exchange_n((p), (n), __ATOMIC_ACQ_REL))

@ -83,6 +83,7 @@ static __inline void gpr_atm_no_barrier_store(gpr_atm *p, gpr_atm value) {
#define gpr_atm_no_barrier_cas(p, o, n) gpr_atm_acq_cas((p), (o), (n))
#define gpr_atm_acq_cas(p, o, n) (__sync_bool_compare_and_swap((p), (o), (n)))
#define gpr_atm_rel_cas(p, o, n) gpr_atm_acq_cas((p), (o), (n))
#define gpr_atm_full_cas(p, o, n) gpr_atm_acq_cas((p), (o), (n))
static __inline gpr_atm gpr_atm_full_xchg(gpr_atm *p, gpr_atm n) {
gpr_atm cur;

@ -87,6 +87,9 @@ typedef struct grpc_call grpc_call;
/** The Socket Mutator interface allows changes on socket options */
typedef struct grpc_socket_mutator grpc_socket_mutator;
/** The Socket Factory interface creates and binds sockets */
typedef struct grpc_socket_factory grpc_socket_factory;
/** Type specifier for grpc_arg */
typedef enum {
GRPC_ARG_STRING,
@ -160,6 +163,15 @@ typedef struct {
/** Maximum message length that the channel can send. Int valued, bytes.
-1 means unlimited. */
#define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length"
/** Maximum time that a channel may have no outstanding rpcs. Int valued,
milliseconds. INT_MAX means unlimited. */
#define GRPC_ARG_MAX_CONNECTION_IDLE_MS "grpc.max_connection_idle_ms"
/** Maximum time that a channel may exist. Int valued, milliseconds. INT_MAX
means unlimited. */
#define GRPC_ARG_MAX_CONNECTION_AGE_MS "grpc.max_connection_age_ms"
/** Grace period after the chennel reaches its max age. Int valued,
milliseconds. INT_MAX means unlimited. */
#define GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS "grpc.max_connection_age_grace_ms"
/** Initial sequence number for http2 transports. Int valued. */
#define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \
"grpc.http2.initial_sequence_number"
@ -195,14 +207,14 @@ typedef struct {
#define GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE "grpc.http2.write_buffer_size"
/** After a duration of this time the client pings the server to see if the
transport is still alive. Int valued, seconds. */
#define GRPC_ARG_HTTP2_KEEPALIVE_TIME "grpc.http2.keepalive_time"
#define GRPC_ARG_CLIENT_KEEPALIVE_TIME_S "grpc.client_keepalive_time"
/** After waiting for a duration of this time, if the client does not receive
the ping ack, it will close the transport. Int valued, seconds. */
#define GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT "grpc.http2.keepalive_timeout"
#define GRPC_ARG_CLIENT_KEEPALIVE_TIMEOUT_S "grpc.client_keepalive_timeout"
/** Is it permissible to send keepalive pings without any outstanding streams.
Int valued, 0(false)/1(true). */
#define GRPC_ARG_HTTP2_KEEPALIVE_PERMIT_WITHOUT_CALLS \
"grpc.http2.keepalive_permit_without_calls"
#define GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS \
"grpc.keepalive_permit_without_calls"
/** Default authority to pass if none specified on call construction. A string.
* */
#define GRPC_ARG_DEFAULT_AUTHORITY "grpc.default_authority"
@ -240,6 +252,8 @@ typedef struct {
#define GRPC_ARG_LB_POLICY_NAME "grpc.lb_policy_name"
/** The grpc_socket_mutator instance that set the socket options. A pointer. */
#define GRPC_ARG_SOCKET_MUTATOR "grpc.socket_mutator"
/** The grpc_socket_factory instance to create and bind sockets. A pointer. */
#define GRPC_ARG_SOCKET_FACTORY "grpc.socket_factory"
/** If non-zero, Cronet transport will coalesce packets to fewer frames when
* possible. */
#define GRPC_ARG_USE_CRONET_PACKET_COALESCING \
@ -311,13 +325,16 @@ typedef enum grpc_call_error {
/** Signal that GRPC_INITIAL_METADATA_WAIT_FOR_READY was explicitly set
by the calling application. */
#define GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET (0x00000080u)
/** Signal that the initial metadata should be corked */
#define GRPC_INITIAL_METADATA_CORKED (0x00000100u)
/** Mask of all valid flags */
#define GRPC_INITIAL_METADATA_USED_MASK \
(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST | \
GRPC_INITIAL_METADATA_WAIT_FOR_READY | \
GRPC_INITIAL_METADATA_CACHEABLE_REQUEST | \
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET)
#define GRPC_INITIAL_METADATA_USED_MASK \
(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST | \
GRPC_INITIAL_METADATA_WAIT_FOR_READY | \
GRPC_INITIAL_METADATA_CACHEABLE_REQUEST | \
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET | \
GRPC_INITIAL_METADATA_CORKED)
/** A single metadata element */
typedef struct grpc_metadata {

@ -364,6 +364,14 @@ typedef unsigned __int64 uint64_t;
power of two */
#define GPR_MAX_ALIGNMENT 16
#ifndef GRPC_ARES
#ifdef GPR_WINDOWS
#define GRPC_ARES 0
#else
#define GRPC_ARES 1
#endif
#endif
#ifndef GRPC_MUST_USE_RESULT
#if defined(__GNUC__) && !defined(__MINGW32__)
#define GRPC_MUST_USE_RESULT __attribute__((warn_unused_result))

@ -24,7 +24,7 @@
"electron-build": "./node_modules/.bin/node-pre-gyp configure build --runtime=electron --disturl=https://atom.io/download/atom-shell",
"gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json",
"coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test",
"install": "./node_modules/.bin/node-pre-gyp install --fallback-to-build"
"install": "./node_modules/.bin/node-pre-gyp install --fallback-to-build --library=static_library"
},
"bundledDependencies": [
"node-pre-gyp"
@ -34,7 +34,8 @@
"lodash": "^4.15.0",
"nan": "^2.0.0",
"node-pre-gyp": "^0.6.0",
"protobufjs": "^5.0.0"
"protobufjs": "^5.0.0",
"cares": "^1.1.5"
},
"devDependencies": {
"async": "^2.0.1",
@ -52,7 +53,7 @@
"poisson-process": "^0.2.1"
},
"engines": {
"node": ">=1.1.0"
"node": ">=4"
},
"binary": {
"module_name": "grpc_node",

@ -85,7 +85,6 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_slice.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/port_platform.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/slice.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_generic.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
@ -166,6 +165,7 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/exec_ctx_fwd.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/grpc_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/propagation_bits.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/slice.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/status.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/atm.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/atm_gcc_atomic.h" role="src" />
@ -174,7 +174,6 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_slice.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/gpr_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/port_platform.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/slice.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_generic.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_posix.h" role="src" />
@ -193,6 +192,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/handshaker_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/max_age_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/message_size_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/algorithm_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/message_compress.h" role="src" />
@ -230,6 +230,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/sockaddr_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/sockaddr_utils.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/sockaddr_windows.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/socket_factory_posix.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/socket_mutator.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils_posix.h" role="src" />
@ -258,6 +259,7 @@
<file baseinstalldir="/" name="src/core/lib/json/json_common.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/json/json_reader.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/json/json_writer.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/b64.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_hash_table.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_internal.h" role="src" />
@ -269,6 +271,7 @@
<file baseinstalldir="/" name="src/core/lib/surface/channel_init.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/channel_stack_type.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/completion_queue.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/completion_queue_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/event_string.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/init.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/lame_client.h" role="src" />
@ -325,13 +328,12 @@
<file baseinstalldir="/" name="src/core/lib/security/transport/security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/b64.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/json_util.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/tsi/fake_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/tsi/ssl_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/tsi/ssl_types.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/tsi/transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/tsi/transport_security_interface.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_types.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security_interface.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/client_channel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/client_channel_factory.h" role="src" />
@ -360,6 +362,8 @@
<file baseinstalldir="/" name="third_party/nanopb/pb_common.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_decode.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_encode.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/load_reporting/load_reporting.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/load_reporting/load_reporting_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/aggregation.h" role="src" />
@ -390,6 +394,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/handshaker_registry.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/max_age_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/message_size_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/compression.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/message_compress.c" role="src" />
@ -426,6 +431,7 @@
<file baseinstalldir="/" name="src/core/lib/iomgr/resolve_address_windows.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/resource_quota.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/sockaddr_utils.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/socket_factory_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/socket_mutator.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils_common_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils_linux.c" role="src" />
@ -463,6 +469,7 @@
<file baseinstalldir="/" name="src/core/lib/json/json_reader.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/json/json_string.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/json/json_writer.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/b64.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice_buffer.c" role="src" />
@ -481,6 +488,7 @@
<file baseinstalldir="/" name="src/core/lib/surface/channel_ping.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/channel_stack_type.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/completion_queue.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/completion_queue_factory.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/event_string.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/lame_client.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/metadata_array.c" role="src" />
@ -544,12 +552,11 @@
<file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/server_auth_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/b64.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/json_util.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/init_secure.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/tsi/fake_transport_security.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/tsi/ssl_transport_security.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/tsi/transport_security.c" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.c" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.c" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/secure/secure_channel_create.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/channel_connectivity.c" role="src" />
@ -586,6 +593,9 @@
<file baseinstalldir="/" name="third_party/nanopb/pb_encode.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/pick_first/pick_first.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/lb_policy/round_robin/round_robin.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/resolver/dns/c_ares/dns_resolver_ares.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/resolver/dns/native/dns_resolver.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/resolver/sockaddr/sockaddr_resolver.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/load_reporting/load_reporting.c" role="src" />

@ -52,6 +52,13 @@ PYTHON_STEM = os.path.join('src', 'python', 'grpcio')
CORE_INCLUDE = ('include', '.',)
BORINGSSL_INCLUDE = (os.path.join('third_party', 'boringssl', 'include'),)
ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),)
CARES_INCLUDE = (
os.path.join('third_party', 'cares'),
os.path.join('third_party', 'cares', 'cares'),)
if 'linux' in sys.platform:
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_linux'),)
if 'darwin' in sys.platform:
CARES_INCLUDE += (os.path.join('third_party', 'cares', 'config_darwin'),)
README = os.path.join(PYTHON_STEM, 'README.rst')
# Ensure we're in the proper directory whether or not we're being used by pip.
@ -136,7 +143,8 @@ CYTHON_HELPER_C_FILES = ()
CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES)
EXTENSION_INCLUDE_DIRECTORIES = (
(PYTHON_STEM,) + CORE_INCLUDE + BORINGSSL_INCLUDE + ZLIB_INCLUDE)
(PYTHON_STEM,) + CORE_INCLUDE + BORINGSSL_INCLUDE + ZLIB_INCLUDE +
CARES_INCLUDE)
EXTENSION_LIBRARIES = ()
if "linux" in sys.platform:
@ -150,13 +158,15 @@ DEFINE_MACROS = (
('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600),
('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
if "win32" in sys.platform:
DEFINE_MACROS += (('WIN32_LEAN_AND_MEAN', 1),)
DEFINE_MACROS += (('WIN32_LEAN_AND_MEAN', 1), ('CARES_STATICLIB', 1),)
if '64bit' in platform.architecture()[0]:
DEFINE_MACROS += (('MS_WIN64', 1),)
elif sys.version_info >= (3, 5):
# For some reason, this is needed to get access to inet_pton/inet_ntop
# on msvc, but only for 32 bits
DEFINE_MACROS += (('NTDDI_VERSION', 0x06000000),)
else:
DEFINE_MACROS += (('HAVE_CONFIG_H', 1),)
LDFLAGS = tuple(EXTRA_LINK_ARGS)
CFLAGS = tuple(EXTRA_COMPILE_ARGS)
@ -264,6 +274,10 @@ PACKAGES = setuptools.find_packages(PYTHON_STEM)
setuptools.setup(
name='grpcio',
version=grpc_version.VERSION,
description='HTTP/2-based RPC framework',
author='The gRPC Authors',
author_email='grpc-io@googlegroups.com',
url='http://www.grpc.io',
license=LICENSE,
long_description=open(README).read(),
ext_modules=CYTHON_EXTENSION_MODULES,

@ -0,0 +1,49 @@
# c-ares cmake file for gRPC
#
# This is currently very experimental, and unsupported.
#
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
string(TOLOWER ${CMAKE_SYSTEM_NAME} cares_system_name)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/cares)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/cares/cares)
if(${cares_system_name} MATCHES windows)
add_definitions(-DCARES_STATICLIB=1)
add_definitions(-DWIN32_LEAN_AND_MEAN=1)
else()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/cares/config_${cares_system_name})
add_definitions(-DHAVE_CONFIG_H=1)
add_definitions(-D_GNU_SOURCE=1)
endif()
file(GLOB lib_sources ../../third_party/cares/cares/*.c)
add_library(cares ${lib_sources})

@ -0,0 +1,149 @@
#!/usr/bin/env python2.7
# 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.
import re
import os
import sys
import yaml
os.chdir(os.path.dirname(sys.argv[0])+'/../..')
out = {}
try:
def gen_ares_build(x):
subprocess.call("third_party/cares/cares/buildconf", shell=True)
subprocess.call("third_party/cares/cares/configure", shell=True)
def config_platform(x):
if 'linux' in sys.platform:
return 'src/cares/cares/config_linux/ares_config.h'
if 'darwin' in sys.platform:
return 'src/cares/cares/config_darwin/ares_config.h'
if not os.path.isfile('third_party/cares/cares/ares_config.h'):
gen_ares_build(x)
return 'third_party/cares/cares/ares_config.h'
def ares_build(x):
if os.path.isfile('src/cares/cares/ares_build.h'):
return 'src/cares/cares/ares_build.h'
if not os.path.isfile('third_party/cares/cares/ares_build.h'):
gen_ares_build(x)
return 'third_party/cares/cares/ares_build.h'
out['libs'] = [{
'name': 'ares',
'defaults': 'ares',
'build': 'private',
'language': 'c',
'secure': 'no',
'src': [
"third_party/cares/cares/ares__close_sockets.c",
"third_party/cares/cares/ares__get_hostent.c",
"third_party/cares/cares/ares__read_line.c",
"third_party/cares/cares/ares__timeval.c",
"third_party/cares/cares/ares_cancel.c",
"third_party/cares/cares/ares_create_query.c",
"third_party/cares/cares/ares_data.c",
"third_party/cares/cares/ares_destroy.c",
"third_party/cares/cares/ares_expand_name.c",
"third_party/cares/cares/ares_expand_string.c",
"third_party/cares/cares/ares_fds.c",
"third_party/cares/cares/ares_free_hostent.c",
"third_party/cares/cares/ares_free_string.c",
"third_party/cares/cares/ares_getenv.c",
"third_party/cares/cares/ares_gethostbyaddr.c",
"third_party/cares/cares/ares_gethostbyname.c",
"third_party/cares/cares/ares_getnameinfo.c",
"third_party/cares/cares/ares_getopt.c",
"third_party/cares/cares/ares_getsock.c",
"third_party/cares/cares/ares_init.c",
"third_party/cares/cares/ares_library_init.c",
"third_party/cares/cares/ares_llist.c",
"third_party/cares/cares/ares_mkquery.c",
"third_party/cares/cares/ares_nowarn.c",
"third_party/cares/cares/ares_options.c",
"third_party/cares/cares/ares_parse_a_reply.c",
"third_party/cares/cares/ares_parse_aaaa_reply.c",
"third_party/cares/cares/ares_parse_mx_reply.c",
"third_party/cares/cares/ares_parse_naptr_reply.c",
"third_party/cares/cares/ares_parse_ns_reply.c",
"third_party/cares/cares/ares_parse_ptr_reply.c",
"third_party/cares/cares/ares_parse_soa_reply.c",
"third_party/cares/cares/ares_parse_srv_reply.c",
"third_party/cares/cares/ares_parse_txt_reply.c",
"third_party/cares/cares/ares_platform.c",
"third_party/cares/cares/ares_process.c",
"third_party/cares/cares/ares_query.c",
"third_party/cares/cares/ares_search.c",
"third_party/cares/cares/ares_send.c",
"third_party/cares/cares/ares_strcasecmp.c",
"third_party/cares/cares/ares_strdup.c",
"third_party/cares/cares/ares_strerror.c",
"third_party/cares/cares/ares_timeout.c",
"third_party/cares/cares/ares_version.c",
"third_party/cares/cares/ares_writev.c",
"third_party/cares/cares/bitncmp.c",
"third_party/cares/cares/inet_net_pton.c",
"third_party/cares/cares/inet_ntop.c",
"third_party/cares/cares/windows_port.c",
],
'headers': [
"third_party/cares/cares/ares.h",
"third_party/cares/cares/ares_data.h",
"third_party/cares/cares/ares_dns.h",
"third_party/cares/cares/ares_getenv.h",
"third_party/cares/cares/ares_getopt.h",
"third_party/cares/cares/ares_inet_net_pton.h",
"third_party/cares/cares/ares_iphlpapi.h",
"third_party/cares/cares/ares_ipv6.h",
"third_party/cares/cares/ares_library_init.h",
"third_party/cares/cares/ares_llist.h",
"third_party/cares/cares/ares_nowarn.h",
"third_party/cares/cares/ares_platform.h",
"third_party/cares/cares/ares_private.h",
"third_party/cares/cares/ares_rules.h",
"third_party/cares/cares/ares_setup.h",
"third_party/cares/cares/ares_strcasecmp.h",
"third_party/cares/cares/ares_strdup.h",
"third_party/cares/cares/ares_version.h",
"third_party/cares/cares/bitncmp.h",
"third_party/cares/cares/config-win32.h",
"third_party/cares/cares/setup_once.h",
"third_party/cares/ares_build.h",
"third_party/cares/config_linux/ares_config.h",
"third_party/cares/config_darwin/ares_config.h"
],
}]
except:
pass
print yaml.dump(out)

@ -1,4 +1,4 @@
#Overview
# Overview
This directory contains source code for gRPC protocol buffer compiler (*protoc*) plugins. Along with `protoc`,
these plugins are used to generate gRPC client and server stubs from `.proto` files.

@ -203,13 +203,13 @@ std::string GetServerClassName(const ServiceDescriptor *service) {
std::string GetCSharpMethodType(MethodType method_type) {
switch (method_type) {
case METHODTYPE_NO_STREAMING:
return "MethodType.Unary";
return "grpc::MethodType.Unary";
case METHODTYPE_CLIENT_STREAMING:
return "MethodType.ClientStreaming";
return "grpc::MethodType.ClientStreaming";
case METHODTYPE_SERVER_STREAMING:
return "MethodType.ServerStreaming";
return "grpc::MethodType.ServerStreaming";
case METHODTYPE_BIDI_STREAMING:
return "MethodType.DuplexStreaming";
return "grpc::MethodType.DuplexStreaming";
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
@ -243,16 +243,19 @@ std::string GetAccessLevel(bool internal_access) {
std::string GetMethodReturnTypeClient(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
return "AsyncUnaryCall<" + GetClassName(method->output_type()) + ">";
return "grpc::AsyncUnaryCall<" + GetClassName(method->output_type()) +
">";
case METHODTYPE_CLIENT_STREAMING:
return "AsyncClientStreamingCall<" + GetClassName(method->input_type()) +
", " + GetClassName(method->output_type()) + ">";
return "grpc::AsyncClientStreamingCall<" +
GetClassName(method->input_type()) + ", " +
GetClassName(method->output_type()) + ">";
case METHODTYPE_SERVER_STREAMING:
return "AsyncServerStreamingCall<" + GetClassName(method->output_type()) +
">";
return "grpc::AsyncServerStreamingCall<" +
GetClassName(method->output_type()) + ">";
case METHODTYPE_BIDI_STREAMING:
return "AsyncDuplexStreamingCall<" + GetClassName(method->input_type()) +
", " + GetClassName(method->output_type()) + ">";
return "grpc::AsyncDuplexStreamingCall<" +
GetClassName(method->input_type()) + ", " +
GetClassName(method->output_type()) + ">";
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
@ -265,7 +268,7 @@ std::string GetMethodRequestParamServer(const MethodDescriptor *method) {
return GetClassName(method->input_type()) + " request";
case METHODTYPE_CLIENT_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return "IAsyncStreamReader<" + GetClassName(method->input_type()) +
return "grpc::IAsyncStreamReader<" + GetClassName(method->input_type()) +
"> requestStream";
}
GOOGLE_LOG(FATAL) << "Can't get here.";
@ -293,8 +296,8 @@ std::string GetMethodResponseStreamMaybe(const MethodDescriptor *method) {
return "";
case METHODTYPE_SERVER_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return ", IServerStreamWriter<" + GetClassName(method->output_type()) +
"> responseStream";
return ", grpc::IServerStreamWriter<" +
GetClassName(method->output_type()) + "> responseStream";
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return "";
@ -325,8 +328,8 @@ void GenerateMarshallerFields(Printer *out, const ServiceDescriptor *service) {
for (size_t i = 0; i < used_messages.size(); i++) {
const Descriptor *message = used_messages[i];
out->Print(
"static readonly Marshaller<$type$> $fieldname$ = "
"Marshallers.Create((arg) => "
"static readonly grpc::Marshaller<$type$> $fieldname$ = "
"grpc::Marshallers.Create((arg) => "
"global::Google.Protobuf.MessageExtensions.ToByteArray(arg), "
"$type$.Parser.ParseFrom);\n",
"fieldname", GetMarshallerFieldName(message), "type",
@ -337,8 +340,8 @@ void GenerateMarshallerFields(Printer *out, const ServiceDescriptor *service) {
void GenerateStaticMethodField(Printer *out, const MethodDescriptor *method) {
out->Print(
"static readonly Method<$request$, $response$> $fieldname$ = new "
"Method<$request$, $response$>(\n",
"static readonly grpc::Method<$request$, $response$> $fieldname$ = new "
"grpc::Method<$request$, $response$>(\n",
"fieldname", GetMethodFieldName(method), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
@ -389,7 +392,7 @@ void GenerateServerClass(Printer *out, const ServiceDescriptor *service) {
out->Print(
"public virtual $returntype$ "
"$methodname$($request$$response_stream_maybe$, "
"ServerCallContext context)\n",
"grpc::ServerCallContext context)\n",
"methodname", method->name(), "returntype",
GetMethodReturnTypeServer(method), "request",
GetMethodRequestParamServer(method), "response_stream_maybe",
@ -397,8 +400,8 @@ void GenerateServerClass(Printer *out, const ServiceDescriptor *service) {
out->Print("{\n");
out->Indent();
out->Print(
"throw new RpcException("
"new Status(StatusCode.Unimplemented, \"\"));\n");
"throw new grpc::RpcException("
"new grpc::Status(grpc::StatusCode.Unimplemented, \"\"));\n");
out->Outdent();
out->Print("}\n\n");
}
@ -410,7 +413,7 @@ void GenerateServerClass(Printer *out, const ServiceDescriptor *service) {
void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
out->Print("/// <summary>Client for $servicename$</summary>\n", "servicename",
GetServiceClassName(service));
out->Print("public partial class $name$ : ClientBase<$name$>\n", "name",
out->Print("public partial class $name$ : grpc::ClientBase<$name$>\n", "name",
GetClientClassName(service));
out->Print("{\n");
out->Indent();
@ -421,7 +424,7 @@ void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
"/// <param name=\"channel\">The channel to use to make remote "
"calls.</param>\n",
"servicename", GetServiceClassName(service));
out->Print("public $name$(Channel channel) : base(channel)\n", "name",
out->Print("public $name$(grpc::Channel channel) : base(channel)\n", "name",
GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
@ -431,8 +434,9 @@ void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
"/// <param name=\"callInvoker\">The callInvoker to use to make remote "
"calls.</param>\n",
"servicename", GetServiceClassName(service));
out->Print("public $name$(CallInvoker callInvoker) : base(callInvoker)\n",
"name", GetClientClassName(service));
out->Print(
"public $name$(grpc::CallInvoker callInvoker) : base(callInvoker)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print(
@ -461,7 +465,8 @@ void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
// unary calls have an extra synchronous stub method
GenerateDocCommentClientMethod(out, method, true, false);
out->Print(
"public virtual $response$ $methodname$($request$ request, Metadata "
"public virtual $response$ $methodname$($request$ request, "
"grpc::Metadata "
"headers = null, DateTime? deadline = null, CancellationToken "
"cancellationToken = default(CancellationToken))\n",
"methodname", method->name(), "request",
@ -470,7 +475,8 @@ void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
out->Print("{\n");
out->Indent();
out->Print(
"return $methodname$(request, new CallOptions(headers, deadline, "
"return $methodname$(request, new grpc::CallOptions(headers, "
"deadline, "
"cancellationToken));\n",
"methodname", method->name());
out->Outdent();
@ -480,7 +486,7 @@ void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
GenerateDocCommentClientMethod(out, method, true, true);
out->Print(
"public virtual $response$ $methodname$($request$ request, "
"CallOptions options)\n",
"grpc::CallOptions options)\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
@ -500,7 +506,8 @@ void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
}
GenerateDocCommentClientMethod(out, method, false, false);
out->Print(
"public virtual $returntype$ $methodname$($request_maybe$Metadata "
"public virtual $returntype$ "
"$methodname$($request_maybe$grpc::Metadata "
"headers = null, DateTime? deadline = null, CancellationToken "
"cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
@ -510,7 +517,8 @@ void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
out->Indent();
out->Print(
"return $methodname$($request_maybe$new CallOptions(headers, deadline, "
"return $methodname$($request_maybe$new grpc::CallOptions(headers, "
"deadline, "
"cancellationToken));\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method, true));
@ -520,7 +528,8 @@ void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
// overload taking CallOptions as a param
GenerateDocCommentClientMethod(out, method, false, true);
out->Print(
"public virtual $returntype$ $methodname$($request_maybe$CallOptions "
"public virtual $returntype$ "
"$methodname$($request_maybe$grpc::CallOptions "
"options)\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
@ -587,13 +596,13 @@ void GenerateBindServiceMethod(Printer *out, const ServiceDescriptor *service) {
"/// <param name=\"serviceImpl\">An object implementing the server-side"
" handling logic.</param>\n");
out->Print(
"public static ServerServiceDefinition BindService($implclass$ "
"public static grpc::ServerServiceDefinition BindService($implclass$ "
"serviceImpl)\n",
"implclass", GetServerClassName(service));
out->Print("{\n");
out->Indent();
out->Print("return ServerServiceDefinition.CreateBuilder()\n");
out->Print("return grpc::ServerServiceDefinition.CreateBuilder()\n");
out->Indent();
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
@ -681,7 +690,7 @@ grpc::string GetServices(const FileDescriptor *file, bool generate_client,
out.Print("using System;\n");
out.Print("using System.Threading;\n");
out.Print("using System.Threading.Tasks;\n");
out.Print("using Grpc.Core;\n");
out.Print("using grpc = global::Grpc.Core;\n");
out.Print("\n");
out.Print("namespace $namespace$ {\n", "namespace", GetFileNamespace(file));

@ -118,7 +118,7 @@ void PrintService(const ServiceDescriptor *service, Printer *out) {
out->Print(
"/**\n * @param string $$hostname hostname\n"
" * @param array $$opts channel options\n"
" * @param Grpc\\Channel $$channel (optional) re-use channel "
" * @param \\Grpc\\Channel $$channel (optional) re-use channel "
"object\n */\n"
"public function __construct($$hostname, $$opts, "
"$$channel = null) {\n");

@ -1,4 +1,4 @@
#Overview
# Overview
This directory contains source code for C library (a.k.a the *gRPC C core*) that provides all gRPC's core functionality through a low level API. Libraries in other languages in this repository (C++, Ruby,
Python, PHP, NodeJS, Objective-C) are layered on top of this library.

@ -1,6 +1,6 @@
Files generated for use by Census stats and trace recording subsystem.
#Files
# Files
* census.pb.{h,c} - Generated from src/core/ext/census/census.proto, using the
script `tools/codegen/core/gen_nano_proto.sh src/proto/census/census.proto
$PWD/src/core/ext/census/gen src/core/ext/census/gen`

@ -374,8 +374,7 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
// resolver actually specified.
channel_arg =
grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
if (channel_arg != NULL && channel_arg->type == GRPC_ARG_POINTER) {
grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
bool found_backend_address = false;
for (size_t i = 0; i < addresses->num_addresses; ++i) {
@ -643,14 +642,26 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
// Record client channel factory.
const grpc_arg *arg = grpc_channel_args_find(args->channel_args,
GRPC_ARG_CLIENT_CHANNEL_FACTORY);
GPR_ASSERT(arg != NULL);
GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
if (arg == NULL) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Missing client channel factory in args for client channel filter");
}
if (arg->type != GRPC_ARG_POINTER) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"client channel factory arg must be a pointer");
}
grpc_client_channel_factory_ref(arg->value.pointer.p);
chand->client_channel_factory = arg->value.pointer.p;
// Get server name to resolve, using proxy mapper if needed.
arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
GPR_ASSERT(arg != NULL);
GPR_ASSERT(arg->type == GRPC_ARG_STRING);
if (arg == NULL) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Missing server uri in args for client channel filter");
}
if (arg->type != GRPC_ARG_STRING) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"server uri arg must be a string");
}
char *proxy_name = NULL;
grpc_channel_args *new_args = NULL;
grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,

@ -93,7 +93,6 @@ static grpc_resolver_factory *lookup_factory(const char *name) {
return g_all_of_the_resolvers[i];
}
}
return NULL;
}

@ -360,7 +360,6 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
for (size_t i = 0; i < c->args->num_args; i++) {
if (0 == strcmp(c->args->args[i].key,
"grpc.testing.fixed_reconnect_backoff_ms")) {
GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
fixed_reconnect_backoff = true;
initial_backoff_ms = min_backoff_ms = max_backoff_ms =
grpc_channel_arg_get_integer(

@ -847,7 +847,9 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
* this is the right LB policy to use. */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
if (arg == NULL || arg->type != GRPC_ARG_POINTER) {
return NULL;
}
grpc_lb_addresses *addresses = arg->value.pointer.p;
size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < addresses->num_addresses; ++i) {

@ -402,7 +402,9 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
* addresses, since we don't know how to handle them. */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
if (arg == NULL || arg->type != GRPC_ARG_POINTER) {
return NULL;
}
grpc_lb_addresses *addresses = arg->value.pointer.p;
size_t num_addrs = 0;
for (size_t i = 0; i < addresses->num_addresses; i++) {

@ -691,7 +691,9 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
* addresses, since we don't know how to handle them. */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
if (arg == NULL || arg->type != GRPC_ARG_POINTER) {
return NULL;
}
grpc_lb_addresses *addresses = arg->value.pointer.p;
size_t num_addrs = 0;
for (size_t i = 0; i < addresses->num_addresses; i++) {

@ -0,0 +1,350 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/port_platform.h>
#if GRPC_ARES == 1 && !defined(GRPC_UV)
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/http_connect_handshaker.h"
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/support/backoff.h"
#include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h"
#define GRPC_DNS_MIN_CONNECT_TIMEOUT_SECONDS 1
#define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1
#define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6
#define GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS 120
#define GRPC_DNS_RECONNECT_JITTER 0.2
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** name to resolve (usually the same as target_name) */
char *name_to_resolve;
/** default port to use */
char *default_port;
/** channel args. */
grpc_channel_args *channel_args;
/** pollset_set to drive the name resolution process */
grpc_pollset_set *interested_parties;
/** Closures used by the combiner */
grpc_closure dns_ares_on_retry_timer_locked;
grpc_closure dns_ares_on_resolved_locked;
/** Combiner guarding the rest of the state */
grpc_combiner *combiner;
/** are we currently resolving? */
bool resolving;
/** which version of the result have we published? */
int published_version;
/** which version of the result is current? */
int resolved_version;
/** pending next completion, or NULL */
grpc_closure *next_completion;
/** target result address for next completion */
grpc_channel_args **target_result;
/** current (fully resolved) result */
grpc_channel_args *resolved_result;
/** retry timer */
bool have_retry_timer;
grpc_timer retry_timer;
/** retry backoff state */
gpr_backoff backoff_state;
/** currently resolving addresses */
grpc_resolved_addresses *addresses;
} ares_dns_resolver;
static void dns_ares_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_ares_start_resolving_locked(grpc_exec_ctx *exec_ctx,
ares_dns_resolver *r);
static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
ares_dns_resolver *r);
static void dns_ares_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_ares_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *r);
static void dns_ares_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_channel_args **target_result,
grpc_closure *on_complete);
static const grpc_resolver_vtable dns_ares_resolver_vtable = {
dns_ares_destroy, dns_ares_shutdown_locked,
dns_ares_channel_saw_error_locked, dns_ares_next_locked};
static void dns_ares_shutdown_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) {
ares_dns_resolver *r = (ares_dns_resolver *)resolver;
if (r->have_retry_timer) {
grpc_timer_cancel(exec_ctx, &r->retry_timer);
}
if (r->next_completion != NULL) {
*r->target_result = NULL;
grpc_closure_sched(
exec_ctx, r->next_completion,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown"));
r->next_completion = NULL;
}
}
static void dns_ares_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) {
ares_dns_resolver *r = (ares_dns_resolver *)resolver;
if (!r->resolving) {
gpr_backoff_reset(&r->backoff_state);
dns_ares_start_resolving_locked(exec_ctx, r);
}
}
static void dns_ares_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
ares_dns_resolver *r = arg;
r->have_retry_timer = false;
if (error == GRPC_ERROR_NONE) {
if (!r->resolving) {
dns_ares_start_resolving_locked(exec_ctx, r);
}
}
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
}
static void dns_ares_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
ares_dns_resolver *r = arg;
grpc_channel_args *result = NULL;
GPR_ASSERT(r->resolving);
r->resolving = false;
if (r->addresses != NULL) {
grpc_lb_addresses *addresses = grpc_lb_addresses_create(
r->addresses->naddrs, NULL /* user_data_vtable */);
for (size_t i = 0; i < r->addresses->naddrs; ++i) {
grpc_lb_addresses_set_address(
addresses, i, &r->addresses->addrs[i].addr,
r->addresses->addrs[i].len, false /* is_balancer */,
NULL /* balancer_name */, NULL /* user_data */);
}
grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses);
result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1);
grpc_resolved_addresses_destroy(r->addresses);
grpc_lb_addresses_destroy(exec_ctx, addresses);
} else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
gpr_timespec timeout = gpr_time_sub(next_try, now);
gpr_log(GPR_INFO, "dns resolution failed (will retry): %s",
grpc_error_string(error));
GPR_ASSERT(!r->have_retry_timer);
r->have_retry_timer = true;
GRPC_RESOLVER_REF(&r->base, "retry-timer");
if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) > 0) {
gpr_log(GPR_DEBUG, "retrying in %" PRId64 ".%09d seconds", timeout.tv_sec,
timeout.tv_nsec);
} else {
gpr_log(GPR_DEBUG, "retrying immediately");
}
grpc_timer_init(exec_ctx, &r->retry_timer, next_try,
&r->dns_ares_on_retry_timer_locked, now);
}
if (r->resolved_result != NULL) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result);
}
r->resolved_result = result;
r->resolved_version++;
dns_ares_maybe_finish_next_locked(exec_ctx, r);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
}
static void dns_ares_next_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver,
grpc_channel_args **target_result,
grpc_closure *on_complete) {
gpr_log(GPR_DEBUG, "dns_ares_next is called.");
ares_dns_resolver *r = (ares_dns_resolver *)resolver;
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_result = target_result;
if (r->resolved_version == 0 && !r->resolving) {
gpr_backoff_reset(&r->backoff_state);
dns_ares_start_resolving_locked(exec_ctx, r);
} else {
dns_ares_maybe_finish_next_locked(exec_ctx, r);
}
}
static void dns_ares_start_resolving_locked(grpc_exec_ctx *exec_ctx,
ares_dns_resolver *r) {
GRPC_RESOLVER_REF(&r->base, "dns-resolving");
GPR_ASSERT(!r->resolving);
r->resolving = true;
r->addresses = NULL;
grpc_resolve_address(exec_ctx, r->name_to_resolve, r->default_port,
r->interested_parties, &r->dns_ares_on_resolved_locked,
&r->addresses);
}
static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
ares_dns_resolver *r) {
if (r->next_completion != NULL &&
r->resolved_version != r->published_version) {
*r->target_result = r->resolved_result == NULL
? NULL
: grpc_channel_args_copy(r->resolved_result);
grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
r->next_completion = NULL;
r->published_version = r->resolved_version;
}
}
static void dns_ares_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
gpr_log(GPR_DEBUG, "dns_ares_destroy");
ares_dns_resolver *r = (ares_dns_resolver *)gr;
if (r->resolved_result != NULL) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result);
}
grpc_pollset_set_destroy(exec_ctx, r->interested_parties);
gpr_free(r->name_to_resolve);
gpr_free(r->default_port);
grpc_channel_args_destroy(exec_ctx, r->channel_args);
gpr_free(r);
}
static grpc_resolver *dns_ares_create(grpc_exec_ctx *exec_ctx,
grpc_resolver_args *args,
const char *default_port) {
// Get name from args.
const char *path = args->uri->path;
if (0 != strcmp(args->uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based dns uri's not supported");
return NULL;
}
if (path[0] == '/') ++path;
// Create resolver.
ares_dns_resolver *r = gpr_zalloc(sizeof(ares_dns_resolver));
grpc_resolver_init(&r->base, &dns_ares_resolver_vtable, args->combiner);
r->name_to_resolve = gpr_strdup(path);
r->default_port = gpr_strdup(default_port);
r->channel_args = grpc_channel_args_copy(args->args);
r->interested_parties = grpc_pollset_set_create();
if (args->pollset_set != NULL) {
grpc_pollset_set_add_pollset_set(exec_ctx, r->interested_parties,
args->pollset_set);
}
gpr_backoff_init(&r->backoff_state, GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS,
GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER,
GRPC_DNS_RECONNECT_JITTER,
GRPC_DNS_MIN_CONNECT_TIMEOUT_SECONDS * 1000,
GRPC_DNS_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
grpc_closure_init(&r->dns_ares_on_retry_timer_locked,
dns_ares_on_retry_timer_locked, r,
grpc_combiner_scheduler(r->base.combiner, false));
grpc_closure_init(&r->dns_ares_on_resolved_locked,
dns_ares_on_resolved_locked, r,
grpc_combiner_scheduler(r->base.combiner, false));
return &r->base;
}
/*
* FACTORY
*/
static void dns_ares_factory_ref(grpc_resolver_factory *factory) {}
static void dns_ares_factory_unref(grpc_resolver_factory *factory) {}
static grpc_resolver *dns_factory_create_resolver(
grpc_exec_ctx *exec_ctx, grpc_resolver_factory *factory,
grpc_resolver_args *args) {
return dns_ares_create(exec_ctx, args, "https");
}
static char *dns_ares_factory_get_default_host_name(
grpc_resolver_factory *factory, grpc_uri *uri) {
const char *path = uri->path;
if (path[0] == '/') ++path;
return gpr_strdup(path);
}
static const grpc_resolver_factory_vtable dns_ares_factory_vtable = {
dns_ares_factory_ref, dns_ares_factory_unref, dns_factory_create_resolver,
dns_ares_factory_get_default_host_name, "dns"};
static grpc_resolver_factory dns_resolver_factory = {&dns_ares_factory_vtable};
static grpc_resolver_factory *dns_ares_resolver_factory_create() {
return &dns_resolver_factory;
}
void grpc_resolver_dns_ares_init(void) {
char *resolver = gpr_getenv("GRPC_DNS_RESOLVER");
/* TODO(zyc): Turn on c-ares based resolver by default after the address
sorter and the CNAME support are added. */
if (resolver != NULL && gpr_stricmp(resolver, "ares") == 0) {
grpc_error *error = grpc_ares_init();
if (error != GRPC_ERROR_NONE) {
GRPC_LOG_IF_ERROR("ares_library_init() failed", error);
return;
}
grpc_resolve_address = grpc_resolve_address_ares;
grpc_register_resolver_type(dns_ares_resolver_factory_create());
}
gpr_free(resolver);
}
void grpc_resolver_dns_ares_shutdown(void) {
char *resolver = gpr_getenv("GRPC_DNS_RESOLVER");
if (resolver != NULL && gpr_stricmp(resolver, "ares") == 0) {
grpc_ares_cleanup();
}
gpr_free(resolver);
}
#else /* GRPC_ARES == 1 && !defined(GRPC_UV) */
void grpc_resolver_dns_ares_init(void) {}
void grpc_resolver_dns_ares_shutdown(void) {}
#endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */

@ -0,0 +1,65 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_EXT_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H
#define GRPC_CORE_EXT_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H
#include <ares.h>
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/pollset_set.h"
typedef struct grpc_ares_ev_driver grpc_ares_ev_driver;
/* Start \a ev_driver. It will keep working until all IO on its ares_channel is
done, or grpc_ares_ev_driver_destroy() is called. It may notify the callbacks
bound to its ares_channel when necessary. */
void grpc_ares_ev_driver_start(grpc_exec_ctx *exec_ctx,
grpc_ares_ev_driver *ev_driver);
/* Returns the ares_channel owned by \a ev_driver. To bind a c-ares query to
\a ev_driver, use the ares_channel owned by \a ev_driver as the arg of the
query. */
ares_channel *grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver *ev_driver);
/* Creates a new grpc_ares_ev_driver. Returns GRPC_ERROR_NONE if \a ev_driver is
created successfully. */
grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver,
grpc_pollset_set *pollset_set);
/* Destroys \a ev_driver asynchronously. Pending lookups made on \a ev_driver
will be cancelled and their on_done callbacks will be invoked with a status
of ARES_ECANCELLED. */
void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver *ev_driver);
#endif /* GRPC_CORE_EXT_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H */

@ -0,0 +1,319 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET)
#include "src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/support/string.h"
typedef struct fd_node {
/** the owner of this fd node */
grpc_ares_ev_driver *ev_driver;
/** the grpc_fd owned by this fd node */
grpc_fd *grpc_fd;
/** a closure wrapping on_readable_cb, which should be invoked when the
grpc_fd in this node becomes readable. */
grpc_closure read_closure;
/** a closure wrapping on_writable_cb, which should be invoked when the
grpc_fd in this node becomes writable. */
grpc_closure write_closure;
/** next fd node in the list */
struct fd_node *next;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** if the readable closure has been registered */
bool readable_registered;
/** if the writable closure has been registered */
bool writable_registered;
} fd_node;
struct grpc_ares_ev_driver {
/** the ares_channel owned by this event driver */
ares_channel channel;
/** pollset set for driving the IO events of the channel */
grpc_pollset_set *pollset_set;
/** refcount of the event driver */
gpr_refcount refs;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** a list of grpc_fd that this event driver is currently using. */
fd_node *fds;
/** is this event driver currently working? */
bool working;
/** is this event driver being shut down */
bool shutting_down;
};
static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx,
grpc_ares_ev_driver *ev_driver);
static grpc_ares_ev_driver *grpc_ares_ev_driver_ref(
grpc_ares_ev_driver *ev_driver) {
gpr_log(GPR_DEBUG, "Ref ev_driver %" PRIuPTR, (uintptr_t)ev_driver);
gpr_ref(&ev_driver->refs);
return ev_driver;
}
static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver *ev_driver) {
gpr_log(GPR_DEBUG, "Unref ev_driver %" PRIuPTR, (uintptr_t)ev_driver);
if (gpr_unref(&ev_driver->refs)) {
gpr_log(GPR_DEBUG, "destroy ev_driver %" PRIuPTR, (uintptr_t)ev_driver);
GPR_ASSERT(ev_driver->fds == NULL);
gpr_mu_destroy(&ev_driver->mu);
ares_destroy(ev_driver->channel);
gpr_free(ev_driver);
}
}
static void fd_node_destroy(grpc_exec_ctx *exec_ctx, fd_node *fdn) {
gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->grpc_fd));
GPR_ASSERT(!fdn->readable_registered);
GPR_ASSERT(!fdn->writable_registered);
gpr_mu_destroy(&fdn->mu);
grpc_pollset_set_del_fd(exec_ctx, fdn->ev_driver->pollset_set, fdn->grpc_fd);
grpc_fd_shutdown(exec_ctx, fdn->grpc_fd,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("fd node destroyed"));
grpc_fd_orphan(exec_ctx, fdn->grpc_fd, NULL, NULL, "c-ares query finished");
gpr_free(fdn);
}
grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver,
grpc_pollset_set *pollset_set) {
*ev_driver = gpr_malloc(sizeof(grpc_ares_ev_driver));
int status = ares_init(&(*ev_driver)->channel);
gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create");
if (status != ARES_SUCCESS) {
char *err_msg;
gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s",
ares_strerror(status));
grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_msg);
gpr_free(err_msg);
gpr_free(*ev_driver);
return err;
}
gpr_mu_init(&(*ev_driver)->mu);
gpr_ref_init(&(*ev_driver)->refs, 1);
(*ev_driver)->pollset_set = pollset_set;
(*ev_driver)->fds = NULL;
(*ev_driver)->working = false;
(*ev_driver)->shutting_down = false;
return GRPC_ERROR_NONE;
}
void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver *ev_driver) {
// It's not safe to shut down remaining fds here directly, becauses
// ares_host_callback does not provide an exec_ctx. We mark the event driver
// as being shut down. If the event driver is working,
// grpc_ares_notify_on_event_locked will shut down the fds; if it's not
// working, there are no fds to shut down.
gpr_mu_lock(&ev_driver->mu);
ev_driver->shutting_down = true;
gpr_mu_unlock(&ev_driver->mu);
grpc_ares_ev_driver_unref(ev_driver);
}
// Search fd in the fd_node list head. This is an O(n) search, the max possible
// value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests.
static fd_node *pop_fd_node(fd_node **head, int fd) {
fd_node dummy_head;
dummy_head.next = *head;
fd_node *node = &dummy_head;
while (node->next != NULL) {
if (grpc_fd_wrapped_fd(node->next->grpc_fd) == fd) {
fd_node *ret = node->next;
node->next = node->next->next;
*head = dummy_head.next;
return ret;
}
node = node->next;
}
return NULL;
}
static void on_readable_cb(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
fd_node *fdn = arg;
grpc_ares_ev_driver *ev_driver = fdn->ev_driver;
gpr_mu_lock(&fdn->mu);
fdn->readable_registered = false;
gpr_mu_unlock(&fdn->mu);
gpr_log(GPR_DEBUG, "readable on %d", grpc_fd_wrapped_fd(fdn->grpc_fd));
if (error == GRPC_ERROR_NONE) {
ares_process_fd(ev_driver->channel, grpc_fd_wrapped_fd(fdn->grpc_fd),
ARES_SOCKET_BAD);
} else {
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
// timed out. The pending lookups made on this ev_driver will be cancelled
// by the following ares_cancel() and the on_done callbacks will be invoked
// with a status of ARES_ECANCELLED. The remaining file descriptors in this
// ev_driver will be cleaned up in the follwing
// grpc_ares_notify_on_event_locked().
ares_cancel(ev_driver->channel);
}
gpr_mu_lock(&ev_driver->mu);
grpc_ares_notify_on_event_locked(exec_ctx, ev_driver);
gpr_mu_unlock(&ev_driver->mu);
grpc_ares_ev_driver_unref(ev_driver);
}
static void on_writable_cb(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
fd_node *fdn = arg;
grpc_ares_ev_driver *ev_driver = fdn->ev_driver;
gpr_mu_lock(&fdn->mu);
fdn->writable_registered = false;
gpr_mu_unlock(&fdn->mu);
gpr_log(GPR_DEBUG, "writable on %d", grpc_fd_wrapped_fd(fdn->grpc_fd));
if (error == GRPC_ERROR_NONE) {
ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD,
grpc_fd_wrapped_fd(fdn->grpc_fd));
} else {
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
// timed out. The pending lookups made on this ev_driver will be cancelled
// by the following ares_cancel() and the on_done callbacks will be invoked
// with a status of ARES_ECANCELLED. The remaining file descriptors in this
// ev_driver will be cleaned up in the follwing
// grpc_ares_notify_on_event_locked().
ares_cancel(ev_driver->channel);
}
gpr_mu_lock(&ev_driver->mu);
grpc_ares_notify_on_event_locked(exec_ctx, ev_driver);
gpr_mu_unlock(&ev_driver->mu);
grpc_ares_ev_driver_unref(ev_driver);
}
ares_channel *grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver *ev_driver) {
return &ev_driver->channel;
}
// Get the file descriptors used by the ev_driver's ares channel, register
// driver_closure with these filedescriptors.
static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx,
grpc_ares_ev_driver *ev_driver) {
fd_node *new_list = NULL;
if (!ev_driver->shutting_down) {
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
int socks_bitmask =
ares_getsock(ev_driver->channel, socks, ARES_GETSOCK_MAXNUM);
for (size_t i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
if (ARES_GETSOCK_READABLE(socks_bitmask, i) ||
ARES_GETSOCK_WRITABLE(socks_bitmask, i)) {
fd_node *fdn = pop_fd_node(&ev_driver->fds, socks[i]);
// Create a new fd_node if sock[i] is not in the fd_node list.
if (fdn == NULL) {
char *fd_name;
gpr_asprintf(&fd_name, "ares_ev_driver-%" PRIuPTR, i);
fdn = gpr_malloc(sizeof(fd_node));
gpr_log(GPR_DEBUG, "new fd: %d", socks[i]);
fdn->grpc_fd = grpc_fd_create(socks[i], fd_name);
fdn->ev_driver = ev_driver;
fdn->readable_registered = false;
fdn->writable_registered = false;
gpr_mu_init(&fdn->mu);
grpc_closure_init(&fdn->read_closure, on_readable_cb, fdn,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&fdn->write_closure, on_writable_cb, fdn,
grpc_schedule_on_exec_ctx);
grpc_pollset_set_add_fd(exec_ctx, ev_driver->pollset_set,
fdn->grpc_fd);
gpr_free(fd_name);
}
fdn->next = new_list;
new_list = fdn;
gpr_mu_lock(&fdn->mu);
// Register read_closure if the socket is readable and read_closure has
// not been registered with this socket.
if (ARES_GETSOCK_READABLE(socks_bitmask, i) &&
!fdn->readable_registered) {
grpc_ares_ev_driver_ref(ev_driver);
gpr_log(GPR_DEBUG, "notify read on: %d",
grpc_fd_wrapped_fd(fdn->grpc_fd));
grpc_fd_notify_on_read(exec_ctx, fdn->grpc_fd, &fdn->read_closure);
fdn->readable_registered = true;
}
// Register write_closure if the socket is writable and write_closure
// has not been registered with this socket.
if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) &&
!fdn->writable_registered) {
gpr_log(GPR_DEBUG, "notify write on: %d",
grpc_fd_wrapped_fd(fdn->grpc_fd));
grpc_ares_ev_driver_ref(ev_driver);
grpc_fd_notify_on_write(exec_ctx, fdn->grpc_fd, &fdn->write_closure);
fdn->writable_registered = true;
}
gpr_mu_unlock(&fdn->mu);
}
}
}
// Any remaining fds in ev_driver->fds were not returned by ares_getsock() and
// are therefore no longer in use, so they can be shut down and removed from
// the list.
while (ev_driver->fds != NULL) {
fd_node *cur = ev_driver->fds;
ev_driver->fds = ev_driver->fds->next;
fd_node_destroy(exec_ctx, cur);
}
ev_driver->fds = new_list;
// If the ev driver has no working fd, all the tasks are done.
if (new_list == NULL) {
ev_driver->working = false;
gpr_log(GPR_DEBUG, "ev driver stop working");
}
}
void grpc_ares_ev_driver_start(grpc_exec_ctx *exec_ctx,
grpc_ares_ev_driver *ev_driver) {
gpr_mu_lock(&ev_driver->mu);
if (!ev_driver->working) {
ev_driver->working = true;
grpc_ares_notify_on_event_locked(exec_ctx, ev_driver);
}
gpr_mu_unlock(&ev_driver->mu);
}
#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) */

@ -0,0 +1,289 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/port_platform.h>
#if GRPC_ARES == 1 && !defined(GRPC_UV)
#include "src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/socket_utils_posix.h"
#include <string.h>
#include <sys/types.h>
#include <ares.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h"
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/support/string.h"
static gpr_once g_basic_init = GPR_ONCE_INIT;
static gpr_mu g_init_mu;
typedef struct grpc_ares_request {
/** following members are set in grpc_resolve_address_ares_impl */
/** host to resolve, parsed from the name to resolve */
char *host;
/** port to fill in sockaddr_in, parsed from the name to resolve */
char *port;
/** default port to use */
char *default_port;
/** closure to call when the request completes */
grpc_closure *on_done;
/** the pointer to receive the resolved addresses */
grpc_resolved_addresses **addrs_out;
/** the evernt driver used by this request */
grpc_ares_ev_driver *ev_driver;
/** number of ongoing queries */
gpr_refcount pending_queries;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** is there at least one successful query, set in on_done_cb */
bool success;
/** the errors explaining the request failure, set in on_done_cb */
grpc_error *error;
} grpc_ares_request;
static void do_basic_init(void) { gpr_mu_init(&g_init_mu); }
static uint16_t strhtons(const char *port) {
if (strcmp(port, "http") == 0) {
return htons(80);
} else if (strcmp(port, "https") == 0) {
return htons(443);
}
return htons((unsigned short)atoi(port));
}
static void grpc_ares_request_unref(grpc_exec_ctx *exec_ctx,
grpc_ares_request *r) {
/* If there are no pending queries, invoke on_done callback and destroy the
request */
if (gpr_unref(&r->pending_queries)) {
/* TODO(zyc): Sort results with RFC6724 before invoking on_done. */
if (exec_ctx == NULL) {
/* A new exec_ctx is created here, as the c-ares interface does not
provide one in ares_host_callback. It's safe to schedule on_done with
the newly created exec_ctx, since the caller has been warned not to
acquire locks in on_done. ares_dns_resolver is using combiner to
protect resources needed by on_done. */
grpc_exec_ctx new_exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_closure_sched(&new_exec_ctx, r->on_done, r->error);
grpc_exec_ctx_finish(&new_exec_ctx);
} else {
grpc_closure_sched(exec_ctx, r->on_done, r->error);
}
gpr_mu_destroy(&r->mu);
grpc_ares_ev_driver_destroy(r->ev_driver);
gpr_free(r->host);
gpr_free(r->port);
gpr_free(r->default_port);
gpr_free(r);
}
}
static void on_done_cb(void *arg, int status, int timeouts,
struct hostent *hostent) {
grpc_ares_request *r = (grpc_ares_request *)arg;
gpr_mu_lock(&r->mu);
if (status == ARES_SUCCESS) {
GRPC_ERROR_UNREF(r->error);
r->error = GRPC_ERROR_NONE;
r->success = true;
grpc_resolved_addresses **addresses = r->addrs_out;
if (*addresses == NULL) {
*addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
(*addresses)->naddrs = 0;
(*addresses)->addrs = NULL;
}
size_t prev_naddr = (*addresses)->naddrs;
size_t i;
for (i = 0; hostent->h_addr_list[i] != NULL; i++) {
}
(*addresses)->naddrs += i;
(*addresses)->addrs =
gpr_realloc((*addresses)->addrs,
sizeof(grpc_resolved_address) * (*addresses)->naddrs);
for (i = prev_naddr; i < (*addresses)->naddrs; i++) {
memset(&(*addresses)->addrs[i], 0, sizeof(grpc_resolved_address));
if (hostent->h_addrtype == AF_INET6) {
(*addresses)->addrs[i].len = sizeof(struct sockaddr_in6);
struct sockaddr_in6 *addr =
(struct sockaddr_in6 *)&(*addresses)->addrs[i].addr;
addr->sin6_family = (sa_family_t)hostent->h_addrtype;
addr->sin6_port = strhtons(r->port);
char output[INET6_ADDRSTRLEN];
memcpy(&addr->sin6_addr, hostent->h_addr_list[i - prev_naddr],
sizeof(struct in6_addr));
ares_inet_ntop(AF_INET6, &addr->sin6_addr, output, INET6_ADDRSTRLEN);
gpr_log(GPR_DEBUG,
"c-ares resolver gets a AF_INET6 result: \n"
" addr: %s\n port: %s\n sin6_scope_id: %d\n",
output, r->port, addr->sin6_scope_id);
} else {
(*addresses)->addrs[i].len = sizeof(struct sockaddr_in);
struct sockaddr_in *addr =
(struct sockaddr_in *)&(*addresses)->addrs[i].addr;
memcpy(&addr->sin_addr, hostent->h_addr_list[i - prev_naddr],
sizeof(struct in_addr));
addr->sin_family = (sa_family_t)hostent->h_addrtype;
addr->sin_port = strhtons(r->port);
char output[INET_ADDRSTRLEN];
ares_inet_ntop(AF_INET, &addr->sin_addr, output, INET_ADDRSTRLEN);
gpr_log(GPR_DEBUG,
"c-ares resolver gets a AF_INET result: \n"
" addr: %s\n port: %s\n",
output, r->port);
}
}
} else if (!r->success) {
char *error_msg;
gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
ares_strerror(status));
grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
gpr_free(error_msg);
if (r->error == GRPC_ERROR_NONE) {
r->error = error;
} else {
r->error = grpc_error_add_child(error, r->error);
}
}
gpr_mu_unlock(&r->mu);
grpc_ares_request_unref(NULL, r);
}
void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port,
grpc_pollset_set *interested_parties,
grpc_closure *on_done,
grpc_resolved_addresses **addrs) {
/* TODO(zyc): Enable tracing after #9603 is checked in */
/* if (grpc_dns_trace) {
gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s",
name, default_port);
} */
/* parse name, splitting it into host and port parts */
char *host;
char *port;
gpr_split_host_port(name, &host, &port);
if (host == NULL) {
grpc_error *err = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
grpc_closure_sched(exec_ctx, on_done, err);
goto error_cleanup;
} else if (port == NULL) {
if (default_port == NULL) {
grpc_error *err = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
grpc_closure_sched(exec_ctx, on_done, err);
goto error_cleanup;
}
port = gpr_strdup(default_port);
}
grpc_ares_ev_driver *ev_driver;
grpc_error *err = grpc_ares_ev_driver_create(&ev_driver, interested_parties);
if (err != GRPC_ERROR_NONE) {
GRPC_LOG_IF_ERROR("grpc_ares_ev_driver_create() failed", err);
goto error_cleanup;
}
grpc_ares_request *r = gpr_malloc(sizeof(grpc_ares_request));
gpr_mu_init(&r->mu);
r->ev_driver = ev_driver;
r->on_done = on_done;
r->addrs_out = addrs;
r->default_port = gpr_strdup(default_port);
r->port = port;
r->host = host;
r->success = false;
r->error = GRPC_ERROR_NONE;
ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver);
gpr_ref_init(&r->pending_queries, 2);
if (grpc_ipv6_loopback_available()) {
gpr_ref(&r->pending_queries);
ares_gethostbyname(*channel, r->host, AF_INET6, on_done_cb, r);
}
ares_gethostbyname(*channel, r->host, AF_INET, on_done_cb, r);
/* TODO(zyc): Handle CNAME records here. */
grpc_ares_ev_driver_start(exec_ctx, r->ev_driver);
grpc_ares_request_unref(exec_ctx, r);
return;
error_cleanup:
gpr_free(host);
gpr_free(port);
}
void (*grpc_resolve_address_ares)(
grpc_exec_ctx *exec_ctx, const char *name, const char *default_port,
grpc_pollset_set *interested_parties, grpc_closure *on_done,
grpc_resolved_addresses **addrs) = grpc_resolve_address_ares_impl;
grpc_error *grpc_ares_init(void) {
gpr_once_init(&g_basic_init, do_basic_init);
gpr_mu_lock(&g_init_mu);
int status = ares_library_init(ARES_LIB_INIT_ALL);
gpr_mu_unlock(&g_init_mu);
if (status != ARES_SUCCESS) {
char *error_msg;
gpr_asprintf(&error_msg, "ares_library_init failed: %s",
ares_strerror(status));
grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
gpr_free(error_msg);
return error;
}
return GRPC_ERROR_NONE;
}
void grpc_ares_cleanup(void) {
gpr_mu_lock(&g_init_mu);
ares_library_cleanup();
gpr_mu_unlock(&g_init_mu);
}
#endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */

@ -0,0 +1,63 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_EXT_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H
#define GRPC_CORE_EXT_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/iomgr/resolve_address.h"
/* Asynchronously resolve addr. Use \a default_port if a port isn't designated
in addr, otherwise use the port in addr. grpc_ares_init() must be called at
least once before this function. \a on_done may be called directly in this
function without being scheduled with \a exec_ctx, it must not try to acquire
locks that are being held by the caller. */
extern void (*grpc_resolve_address_ares)(grpc_exec_ctx *exec_ctx,
const char *addr,
const char *default_port,
grpc_pollset_set *interested_parties,
grpc_closure *on_done,
grpc_resolved_addresses **addresses);
/* Initialize gRPC ares wrapper. Must be called at least once before
grpc_resolve_address_ares(). */
grpc_error *grpc_ares_init(void);
/* Uninitialized gRPC ares wrapper. If there was more than one previous call to
grpc_ares_init(), this function uninitializes the gRPC ares wrapper only if
it has been called the same number of times as grpc_ares_init(). */
void grpc_ares_cleanup(void);
#endif /* GRPC_CORE_EXT_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H */

@ -44,6 +44,7 @@
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/support/backoff.h"
#include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h"
#define GRPC_DNS_MIN_CONNECT_TIMEOUT_SECONDS 1
@ -304,7 +305,21 @@ static grpc_resolver_factory *dns_resolver_factory_create() {
}
void grpc_resolver_dns_native_init(void) {
grpc_register_resolver_type(dns_resolver_factory_create());
char *resolver = gpr_getenv("GRPC_DNS_RESOLVER");
if (resolver != NULL && gpr_stricmp(resolver, "native") == 0) {
gpr_log(GPR_DEBUG, "Using native dns resolver");
grpc_register_resolver_type(dns_resolver_factory_create());
} else {
grpc_resolver_factory *existing_factory =
grpc_resolver_factory_lookup("dns");
if (existing_factory == NULL) {
gpr_log(GPR_DEBUG, "Using native dns resolver");
grpc_register_resolver_type(dns_resolver_factory_create());
} else {
grpc_resolver_factory_unref(existing_factory);
}
}
gpr_free(resolver);
}
void grpc_resolver_dns_native_shutdown(void) {}

@ -69,10 +69,16 @@
#define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
#define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024)
#define DEFAULT_KEEPALIVE_TIME_SECOND INT_MAX
#define DEFAULT_KEEPALIVE_TIMEOUT_SECOND 20
#define DEFAULT_CLIENT_KEEPALIVE_TIME_S INT_MAX
#define DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_S 20
#define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false
static int g_default_client_keepalive_time_s = DEFAULT_CLIENT_KEEPALIVE_TIME_S;
static int g_default_client_keepalive_timeout_s =
DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_S;
static bool g_default_keepalive_permit_without_calls =
DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS;
#define MAX_CLIENT_STREAM_ID 0x7fffffffu
int grpc_http_trace = 0;
int grpc_flowctl_trace = 0;
@ -142,6 +148,8 @@ static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_chttp2_ping_type ping_type,
grpc_closure *on_initiate,
grpc_closure *on_complete);
static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *error);
#define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0
#define DEFAULT_MAX_PINGS_BETWEEN_DATA 3
@ -267,6 +275,8 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_closure_init(&t->destructive_reclaimer_locked,
destructive_reclaimer_locked, t,
grpc_combiner_scheduler(t->combiner, false));
grpc_closure_init(&t->retry_initiate_ping_locked, retry_initiate_ping_locked,
t, grpc_combiner_scheduler(t->combiner, false));
grpc_closure_init(&t->start_bdp_ping_locked, start_bdp_ping_locked, t,
grpc_combiner_scheduler(t->combiner, false));
grpc_closure_init(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t,
@ -345,15 +355,16 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
/* client-side keepalive setting */
t->keepalive_time =
DEFAULT_KEEPALIVE_TIME_SECOND == INT_MAX
g_default_client_keepalive_time_s == INT_MAX
? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIME_SECOND, GPR_TIMESPAN);
: gpr_time_from_seconds(g_default_client_keepalive_time_s,
GPR_TIMESPAN);
t->keepalive_timeout =
DEFAULT_KEEPALIVE_TIMEOUT_SECOND == INT_MAX
g_default_client_keepalive_timeout_s == INT_MAX
? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIMEOUT_SECOND,
: gpr_time_from_seconds(g_default_client_keepalive_timeout_s,
GPR_TIMESPAN);
t->keepalive_permit_without_calls = DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS;
t->keepalive_permit_without_calls = g_default_keepalive_permit_without_calls;
if (channel_args) {
for (i = 0; i < channel_args->num_args; i++) {
@ -403,24 +414,25 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->enable_bdp_probe = grpc_channel_arg_get_integer(
&channel_args->args[i], (grpc_integer_options){1, 0, 1});
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_KEEPALIVE_TIME)) {
GRPC_ARG_CLIENT_KEEPALIVE_TIME_S)) {
const int value = grpc_channel_arg_get_integer(
&channel_args->args[i],
(grpc_integer_options){DEFAULT_KEEPALIVE_TIME_SECOND, 1, INT_MAX});
(grpc_integer_options){g_default_client_keepalive_time_s, 1,
INT_MAX});
t->keepalive_time = value == INT_MAX
? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_seconds(value, GPR_TIMESPAN);
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT)) {
GRPC_ARG_CLIENT_KEEPALIVE_TIMEOUT_S)) {
const int value = grpc_channel_arg_get_integer(
&channel_args->args[i],
(grpc_integer_options){DEFAULT_KEEPALIVE_TIMEOUT_SECOND, 0,
(grpc_integer_options){g_default_client_keepalive_timeout_s, 0,
INT_MAX});
t->keepalive_timeout = value == INT_MAX
? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_seconds(value, GPR_TIMESPAN);
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_KEEPALIVE_PERMIT_WITHOUT_CALLS)) {
GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) {
t->keepalive_permit_without_calls =
(uint32_t)grpc_channel_arg_get_integer(
&channel_args->args[i], (grpc_integer_options){0, 0, 1});
@ -474,6 +486,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
t->ping_state.is_delayed_ping_timer_set = false;
/** Start client-side keepalive pings */
if (t->is_client) {
@ -1089,7 +1102,7 @@ static void continue_fetching_send_locked(grpc_exec_ctx *exec_ctx,
return; /* early out */
} else if (grpc_byte_stream_next(exec_ctx, s->fetching_send_message,
&s->fetching_slice, UINT32_MAX,
&s->complete_fetch)) {
&s->complete_fetch_locked)) {
add_fetched_slice_locked(exec_ctx, t, s);
}
}
@ -1210,8 +1223,13 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
}
} else {
GPR_ASSERT(s->id != 0);
grpc_chttp2_become_writable(exec_ctx, t, s,
GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
grpc_chttp2_stream_write_type write_type =
GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED;
if (op->send_message != NULL &&
(op->send_message->flags & GRPC_WRITE_BUFFER_HINT)) {
write_type = GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK;
}
grpc_chttp2_become_writable(exec_ctx, t, s, write_type,
"op.send_initial_metadata");
}
} else {
@ -1394,6 +1412,13 @@ static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
}
}
static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
grpc_error *error) {
grpc_chttp2_transport *t = tp;
t->ping_state.is_delayed_ping_timer_set = false;
grpc_chttp2_initiate_write(exec_ctx, t, false, "retry_send_ping");
}
void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
uint64_t id) {
grpc_chttp2_ping_queue *pq =
@ -1835,7 +1860,7 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
size_t msg_len = GRPC_SLICE_LENGTH(slice);
GPR_ASSERT(msg_len <= UINT32_MAX);
uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0);
uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 1);
message_pfx = grpc_slice_malloc(14 + msg_len_len);
p = GRPC_SLICE_START_PTR(message_pfx);
*p++ = 0x00; /* literal header, not indexed */
@ -1852,7 +1877,7 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
*p++ = 'a';
*p++ = 'g';
*p++ = 'e';
GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p, (uint32_t)msg_len_len);
GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 1, 0, p, (uint32_t)msg_len_len);
p += msg_len_len;
GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx);
@ -2103,6 +2128,32 @@ static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping");
}
void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args) {
size_t i;
if (args) {
for (i = 0; i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_CLIENT_KEEPALIVE_TIME_S)) {
g_default_client_keepalive_time_s = grpc_channel_arg_get_integer(
&args->args[i], (grpc_integer_options){
g_default_client_keepalive_time_s, 1, INT_MAX});
} else if (0 == strcmp(args->args[i].key,
GRPC_ARG_CLIENT_KEEPALIVE_TIMEOUT_S)) {
g_default_client_keepalive_timeout_s = grpc_channel_arg_get_integer(
&args->args[i],
(grpc_integer_options){g_default_client_keepalive_timeout_s, 0,
INT_MAX});
} else if (0 == strcmp(args->args[i].key,
GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) {
g_default_keepalive_permit_without_calls =
(uint32_t)grpc_channel_arg_get_integer(
&args->args[i],
(grpc_integer_options){g_default_keepalive_permit_without_calls,
0, 1});
}
}
}
}
static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_chttp2_transport *t = arg;
@ -2146,9 +2197,7 @@ static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_timer_init(
exec_ctx, &t->keepalive_ping_timer,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
grpc_closure_create(init_keepalive_ping_locked, t,
grpc_combiner_scheduler(t->combiner, false)),
gpr_now(GPR_CLOCK_MONOTONIC));
&t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
}
}
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping end");

@ -40,6 +40,8 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
static bool g_disable_ping_ack = false;
grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes) {
grpc_slice slice = grpc_slice_malloc(9 + 8);
uint8_t *p = GRPC_SLICE_START_PTR(slice);
@ -101,15 +103,21 @@ grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser,
if (p->is_ack) {
grpc_chttp2_ack_ping(exec_ctx, t, p->opaque_8bytes);
} else {
if (t->ping_ack_count == t->ping_ack_capacity) {
t->ping_ack_capacity = GPR_MAX(t->ping_ack_capacity * 3 / 2, 3);
t->ping_acks = gpr_realloc(
t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks));
if (!g_disable_ping_ack) {
if (t->ping_ack_count == t->ping_ack_capacity) {
t->ping_ack_capacity = GPR_MAX(t->ping_ack_capacity * 3 / 2, 3);
t->ping_acks = gpr_realloc(
t->ping_acks, t->ping_ack_capacity * sizeof(*t->ping_acks));
}
t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes;
grpc_chttp2_initiate_write(exec_ctx, t, false, "ping response");
}
t->ping_acks[t->ping_ack_count++] = p->opaque_8bytes;
grpc_chttp2_initiate_write(exec_ctx, t, false, "ping response");
}
}
return GRPC_ERROR_NONE;
}
void grpc_set_disable_ping_ack(bool disable_ping_ack) {
g_disable_ping_ack = disable_ping_ack;
}

@ -53,4 +53,7 @@ grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_stream *s,
grpc_slice slice, int is_last);
/* Test-only function for disabling ping ack */
void grpc_set_disable_ping_ack(bool disable_ping_ack);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H */

@ -102,6 +102,8 @@ typedef struct {
typedef struct {
gpr_timespec last_ping_sent_time;
int pings_before_data_required;
grpc_timer delayed_ping_timer;
bool is_delayed_ping_timer_set;
} grpc_chttp2_repeated_ping_state;
/* deframer state for the overall http2 stream of bytes */
@ -308,6 +310,7 @@ struct grpc_chttp2_transport {
grpc_chttp2_repeated_ping_policy ping_policy;
grpc_chttp2_repeated_ping_state ping_state;
uint64_t ping_ctr; /* unique id for pings */
grpc_closure retry_initiate_ping_locked;
/** ping acks */
size_t ping_ack_count;
@ -449,7 +452,6 @@ struct grpc_chttp2_stream {
int64_t next_message_end_offset;
int64_t flow_controlled_bytes_written;
bool complete_fetch_covered_by_poller;
grpc_closure complete_fetch;
grpc_closure complete_fetch_locked;
grpc_closure *fetching_send_message_finished;
@ -827,4 +829,8 @@ void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx,
uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t);
/** Set the default keepalive configurations, must only be called at
initialization */
void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args);
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */

@ -101,6 +101,14 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
"Ping delayed [%p]: not enough time elapsed since last ping",
t->peer_string);
}
if (!t->ping_state.is_delayed_ping_timer_set) {
t->ping_state.is_delayed_ping_timer_set = true;
grpc_timer_init(exec_ctx, &t->ping_state.delayed_ping_timer,
gpr_time_add(t->ping_state.last_ping_sent_time,
t->ping_policy.min_time_between_pings),
&t->retry_initiate_ping_locked,
gpr_now(GPR_CLOCK_MONOTONIC));
}
return;
}
/* coalesce equivalent pings into this one */

@ -36,6 +36,7 @@
#include <grpc/support/string_util.h>
#include <string.h>
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/b64.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
@ -56,7 +57,6 @@ typedef struct call_data {
grpc_linked_mdelem te_trailers;
grpc_linked_mdelem content_type;
grpc_linked_mdelem user_agent;
grpc_linked_mdelem payload_bin;
grpc_metadata_batch *recv_initial_metadata;
grpc_metadata_batch *recv_trailing_metadata;
@ -292,19 +292,58 @@ static grpc_error *hc_mutate_op(grpc_exec_ctx *exec_ctx,
continue_send_message(exec_ctx, elem);
if (calld->send_message_blocked == false) {
/* when all the send_message data is available, then create a MDELEM and
append to headers */
grpc_mdelem payload_bin = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_GRPC_PAYLOAD_BIN,
grpc_slice_from_copied_buffer((const char *)calld->payload_bytes,
op->send_message->length));
error =
grpc_metadata_batch_add_tail(exec_ctx, op->send_initial_metadata,
&calld->payload_bin, payload_bin);
/* when all the send_message data is available, then modify the path
* MDELEM by appending base64 encoded query to the path */
const int k_url_safe = 1;
const int k_multi_line = 0;
const unsigned char k_query_separator = '?';
grpc_slice path_slice =
GRPC_MDVALUE(op->send_initial_metadata->idx.named.path->md);
/* sum up individual component's lengths and allocate enough memory to
* hold combined path+query */
size_t estimated_len = GRPC_SLICE_LENGTH(path_slice);
estimated_len++; /* for the '?' */
estimated_len += grpc_base64_estimate_encoded_size(
op->send_message->length, k_url_safe, k_multi_line);
estimated_len += 1; /* for the trailing 0 */
grpc_slice path_with_query_slice = grpc_slice_malloc(estimated_len);
/* memcopy individual pieces into this slice */
uint8_t *write_ptr =
(uint8_t *)GRPC_SLICE_START_PTR(path_with_query_slice);
uint8_t *original_path = (uint8_t *)GRPC_SLICE_START_PTR(path_slice);
memcpy(write_ptr, original_path, GRPC_SLICE_LENGTH(path_slice));
write_ptr += GRPC_SLICE_LENGTH(path_slice);
*write_ptr = k_query_separator;
write_ptr++; /* for the '?' */
grpc_base64_encode_core((char *)write_ptr, calld->payload_bytes,
op->send_message->length, k_url_safe,
k_multi_line);
/* remove trailing unused memory and add trailing 0 to terminate string
*/
char *t = (char *)GRPC_SLICE_START_PTR(path_with_query_slice);
/* safe to use strlen since base64_encode will always add '\0' */
size_t path_length = strlen(t) + 1;
*(t + path_length) = '\0';
path_with_query_slice =
grpc_slice_sub(path_with_query_slice, 0, path_length);
/* substitute previous path with the new path+query */
grpc_mdelem mdelem_path_and_query = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_PATH, path_with_query_slice);
grpc_metadata_batch *b = op->send_initial_metadata;
error = grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path,
mdelem_path_and_query);
if (error != GRPC_ERROR_NONE) return error;
calld->on_complete = op->on_complete;
op->on_complete = &calld->hc_on_complete;
op->send_message = NULL;
grpc_slice_unref_internal(exec_ctx, path_with_query_slice);
} else {
/* Not all data is available. Fall back to POST. */
gpr_log(GPR_DEBUG,

@ -37,6 +37,7 @@
#include <grpc/support/log.h>
#include <string.h>
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/b64.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
@ -51,8 +52,8 @@ typedef struct call_data {
grpc_linked_mdelem status;
grpc_linked_mdelem content_type;
/* did this request come with payload-bin */
bool seen_payload_bin;
/* did this request come with path query containing request payload */
bool seen_path_with_query;
/* flag to ensure payload_bin is delivered only once */
bool payload_bin_delivered;
@ -61,7 +62,7 @@ typedef struct call_data {
bool *recv_cacheable_request;
/** Closure to call when finished with the hs_on_recv hook */
grpc_closure *on_done_recv;
/** Closure to call when we retrieve read message from the payload-bin header
/** Closure to call when we retrieve read message from the path URI
*/
grpc_closure *recv_message_ready;
grpc_closure *on_complete;
@ -205,6 +206,43 @@ static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"),
GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":path")));
} else if (*calld->recv_cacheable_request == true) {
/* We have a cacheable request made with GET verb. The path contains the
* query parameter which is base64 encoded request payload. */
const char k_query_separator = '?';
grpc_slice path_slice = GRPC_MDVALUE(b->idx.named.path->md);
uint8_t *path_ptr = (uint8_t *)GRPC_SLICE_START_PTR(path_slice);
size_t path_length = GRPC_SLICE_LENGTH(path_slice);
/* offset of the character '?' */
size_t offset = 0;
for (offset = 0; offset < path_length && *path_ptr != k_query_separator;
path_ptr++, offset++)
;
if (offset < path_length) {
grpc_slice query_slice =
grpc_slice_sub(path_slice, offset + 1, path_length);
/* substitute path metadata with just the path (not query) */
grpc_mdelem mdelem_path_without_query = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_PATH, grpc_slice_sub(path_slice, 0, offset));
grpc_metadata_batch_substitute(exec_ctx, b, b->idx.named.path,
mdelem_path_without_query);
/* decode payload from query and add to the slice buffer to be returned */
const int k_url_safe = 1;
grpc_slice_buffer_add(
&calld->read_slice_buffer,
grpc_base64_decode(exec_ctx,
(const char *)GRPC_SLICE_START_PTR(query_slice),
k_url_safe));
grpc_slice_buffer_stream_init(&calld->read_stream,
&calld->read_slice_buffer, 0);
calld->seen_path_with_query = true;
grpc_slice_unref_internal(exec_ctx, query_slice);
} else {
gpr_log(GPR_ERROR, "GET request without QUERY");
}
}
if (b->idx.named.host != NULL && b->idx.named.authority == NULL) {
@ -228,16 +266,6 @@ static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_STR_KEY, grpc_slice_from_static_string(":authority")));
}
if (b->idx.named.grpc_payload_bin != NULL) {
calld->seen_payload_bin = true;
grpc_slice_buffer_add(&calld->read_slice_buffer,
grpc_slice_ref_internal(
GRPC_MDVALUE(b->idx.named.grpc_payload_bin->md)));
grpc_slice_buffer_stream_init(&calld->read_stream,
&calld->read_slice_buffer, 0);
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_payload_bin);
}
return error;
}
@ -258,8 +286,8 @@ static void hs_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_error *err) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
/* Call recv_message_ready if we got the payload via the header field */
if (calld->seen_payload_bin && calld->recv_message_ready != NULL) {
/* Call recv_message_ready if we got the payload via the path field */
if (calld->seen_path_with_query && calld->recv_message_ready != NULL) {
*calld->pp_recv_message = calld->payload_bin_delivered
? NULL
: (grpc_byte_stream *)&calld->read_stream;
@ -274,7 +302,7 @@ static void hs_recv_message_ready(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_error *err) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
if (calld->seen_payload_bin) {
if (calld->seen_path_with_query) {
/* do nothing. This is probably a GET request, and payload will be returned
in hs_on_complete callback. */
} else {

@ -0,0 +1,386 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/lib/channel/message_size_filter.h"
#include <limits.h>
#include <string.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/transport/http2_errors.h"
#include "src/core/lib/transport/service_config.h"
#define DEFAULT_MAX_CONNECTION_AGE_MS INT_MAX
#define DEFAULT_MAX_CONNECTION_AGE_GRACE_MS INT_MAX
#define DEFAULT_MAX_CONNECTION_IDLE_MS INT_MAX
typedef struct channel_data {
/* We take a reference to the channel stack for the timer callback */
grpc_channel_stack* channel_stack;
/* Guards access to max_age_timer, max_age_timer_pending, max_age_grace_timer
and max_age_grace_timer_pending */
gpr_mu max_age_timer_mu;
/* True if the max_age timer callback is currently pending */
bool max_age_timer_pending;
/* True if the max_age_grace timer callback is currently pending */
bool max_age_grace_timer_pending;
/* The timer for checking if the channel has reached its max age */
grpc_timer max_age_timer;
/* The timer for checking if the max-aged channel has uesed up the grace
period */
grpc_timer max_age_grace_timer;
/* The timer for checking if the channel's idle duration reaches
max_connection_idle */
grpc_timer max_idle_timer;
/* Allowed max time a channel may have no outstanding rpcs */
gpr_timespec max_connection_idle;
/* Allowed max time a channel may exist */
gpr_timespec max_connection_age;
/* Allowed grace period after the channel reaches its max age */
gpr_timespec max_connection_age_grace;
/* Closure to run when the channel's idle duration reaches max_connection_idle
and should be closed gracefully */
grpc_closure close_max_idle_channel;
/* Closure to run when the channel reaches its max age and should be closed
gracefully */
grpc_closure close_max_age_channel;
/* Closure to run the channel uses up its max age grace time and should be
closed forcibly */
grpc_closure force_close_max_age_channel;
/* Closure to run when the init fo channel stack is done and the max_idle
timer should be started */
grpc_closure start_max_idle_timer_after_init;
/* Closure to run when the init fo channel stack is done and the max_age timer
should be started */
grpc_closure start_max_age_timer_after_init;
/* Closure to run when the goaway op is finished and the max_age_timer */
grpc_closure start_max_age_grace_timer_after_goaway_op;
/* Closure to run when the channel connectivity state changes */
grpc_closure channel_connectivity_changed;
/* Records the current connectivity state */
grpc_connectivity_state connectivity_state;
/* Number of active calls */
gpr_atm call_count;
} channel_data;
/* Increase the nubmer of active calls. Before the increasement, if there are no
calls, the max_idle_timer should be cancelled. */
static void increase_call_count(grpc_exec_ctx* exec_ctx, channel_data* chand) {
if (gpr_atm_full_fetch_add(&chand->call_count, 1) == 0) {
grpc_timer_cancel(exec_ctx, &chand->max_idle_timer);
}
}
/* Decrease the nubmer of active calls. After the decrement, if there are no
calls, the max_idle_timer should be started. */
static void decrease_call_count(grpc_exec_ctx* exec_ctx, channel_data* chand) {
if (gpr_atm_full_fetch_add(&chand->call_count, -1) == 1) {
GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_idle_timer");
grpc_timer_init(
exec_ctx, &chand->max_idle_timer,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), chand->max_connection_idle),
&chand->close_max_idle_channel, gpr_now(GPR_CLOCK_MONOTONIC));
}
}
static void start_max_idle_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
channel_data* chand = arg;
/* Decrease call_count. If there are no active calls at this time,
max_idle_timer will start here. If the number of active calls is not 0,
max_idle_timer will start after all the active calls end. */
decrease_call_count(exec_ctx, chand);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
"max_age start_max_idle_timer_after_init");
}
static void start_max_age_timer_after_init(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
channel_data* chand = arg;
gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_timer_pending = true;
GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_timer");
grpc_timer_init(
exec_ctx, &chand->max_age_timer,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), chand->max_connection_age),
&chand->close_max_age_channel, gpr_now(GPR_CLOCK_MONOTONIC));
gpr_mu_unlock(&chand->max_age_timer_mu);
grpc_transport_op* op = grpc_make_transport_op(NULL);
op->on_connectivity_state_change = &chand->channel_connectivity_changed,
op->connectivity_state = &chand->connectivity_state;
grpc_channel_next_op(exec_ctx,
grpc_channel_stack_element(chand->channel_stack, 0), op);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
"max_age start_max_age_timer_after_init");
}
static void start_max_age_grace_timer_after_goaway_op(grpc_exec_ctx* exec_ctx,
void* arg,
grpc_error* error) {
channel_data* chand = arg;
gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_grace_timer_pending = true;
GRPC_CHANNEL_STACK_REF(chand->channel_stack, "max_age max_age_grace_timer");
grpc_timer_init(exec_ctx, &chand->max_age_grace_timer,
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
chand->max_connection_age_grace),
&chand->force_close_max_age_channel,
gpr_now(GPR_CLOCK_MONOTONIC));
gpr_mu_unlock(&chand->max_age_timer_mu);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
"max_age start_max_age_grace_timer_after_goaway_op");
}
static void close_max_idle_channel(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
channel_data* chand = arg;
gpr_atm_no_barrier_fetch_add(&chand->call_count, 1);
if (error == GRPC_ERROR_NONE) {
grpc_transport_op* op = grpc_make_transport_op(NULL);
op->goaway_error =
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("max_idle"),
GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR);
grpc_channel_element* elem =
grpc_channel_stack_element(chand->channel_stack, 0);
elem->filter->start_transport_op(exec_ctx, elem, op);
} else if (error != GRPC_ERROR_CANCELLED) {
GRPC_LOG_IF_ERROR("close_max_idle_channel", error);
}
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
"max_age max_idle_timer");
}
static void close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
channel_data* chand = arg;
gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_timer_pending = false;
gpr_mu_unlock(&chand->max_age_timer_mu);
if (error == GRPC_ERROR_NONE) {
GRPC_CHANNEL_STACK_REF(chand->channel_stack,
"max_age start_max_age_grace_timer_after_goaway_op");
grpc_transport_op* op = grpc_make_transport_op(
&chand->start_max_age_grace_timer_after_goaway_op);
op->goaway_error =
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("max_age"),
GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_NO_ERROR);
grpc_channel_element* elem =
grpc_channel_stack_element(chand->channel_stack, 0);
elem->filter->start_transport_op(exec_ctx, elem, op);
} else if (error != GRPC_ERROR_CANCELLED) {
GRPC_LOG_IF_ERROR("close_max_age_channel", error);
}
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
"max_age max_age_timer");
}
static void force_close_max_age_channel(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
channel_data* chand = arg;
gpr_mu_lock(&chand->max_age_timer_mu);
chand->max_age_grace_timer_pending = false;
gpr_mu_unlock(&chand->max_age_timer_mu);
if (error == GRPC_ERROR_NONE) {
grpc_transport_op* op = grpc_make_transport_op(NULL);
op->disconnect_with_error =
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel reaches max age");
grpc_channel_element* elem =
grpc_channel_stack_element(chand->channel_stack, 0);
elem->filter->start_transport_op(exec_ctx, elem, op);
} else if (error != GRPC_ERROR_CANCELLED) {
GRPC_LOG_IF_ERROR("force_close_max_age_channel", error);
}
GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->channel_stack,
"max_age max_age_grace_timer");
}
static void channel_connectivity_changed(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
channel_data* chand = arg;
if (chand->connectivity_state != GRPC_CHANNEL_SHUTDOWN) {
grpc_transport_op* op = grpc_make_transport_op(NULL);
op->on_connectivity_state_change = &chand->channel_connectivity_changed,
op->connectivity_state = &chand->connectivity_state;
grpc_channel_next_op(
exec_ctx, grpc_channel_stack_element(chand->channel_stack, 0), op);
} else {
gpr_mu_lock(&chand->max_age_timer_mu);
if (chand->max_age_timer_pending) {
grpc_timer_cancel(exec_ctx, &chand->max_age_timer);
chand->max_age_timer_pending = false;
}
if (chand->max_age_grace_timer_pending) {
grpc_timer_cancel(exec_ctx, &chand->max_age_grace_timer);
chand->max_age_grace_timer_pending = false;
}
gpr_mu_unlock(&chand->max_age_timer_mu);
/* If there are no active calls, this increasement will cancel
max_idle_timer, and prevent max_idle_timer from being started in the
future. */
increase_call_count(exec_ctx, chand);
}
}
/* Constructor for call_data. */
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem,
const grpc_call_element_args* args) {
channel_data* chand = elem->channel_data;
increase_call_count(exec_ctx, chand);
return GRPC_ERROR_NONE;
}
/* Destructor for call_data. */
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
const grpc_call_final_info* final_info,
grpc_closure* ignored) {
channel_data* chand = elem->channel_data;
decrease_call_count(exec_ctx, chand);
}
/* Constructor for channel_data. */
static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
grpc_channel_element* elem,
grpc_channel_element_args* args) {
channel_data* chand = elem->channel_data;
gpr_mu_init(&chand->max_age_timer_mu);
chand->max_age_timer_pending = false;
chand->max_age_grace_timer_pending = false;
chand->channel_stack = args->channel_stack;
chand->max_connection_age =
DEFAULT_MAX_CONNECTION_AGE_MS == INT_MAX
? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_millis(DEFAULT_MAX_CONNECTION_AGE_MS, GPR_TIMESPAN);
chand->max_connection_age_grace =
DEFAULT_MAX_CONNECTION_AGE_GRACE_MS == INT_MAX
? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_millis(DEFAULT_MAX_CONNECTION_AGE_GRACE_MS,
GPR_TIMESPAN);
chand->max_connection_idle =
DEFAULT_MAX_CONNECTION_IDLE_MS == INT_MAX
? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_millis(DEFAULT_MAX_CONNECTION_IDLE_MS, GPR_TIMESPAN);
for (size_t i = 0; i < args->channel_args->num_args; ++i) {
if (0 == strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_CONNECTION_AGE_MS)) {
const int value = grpc_channel_arg_get_integer(
&args->channel_args->args[i],
(grpc_integer_options){DEFAULT_MAX_CONNECTION_AGE_MS, 1, INT_MAX});
chand->max_connection_age =
value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_millis(value, GPR_TIMESPAN);
} else if (0 == strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS)) {
const int value = grpc_channel_arg_get_integer(
&args->channel_args->args[i],
(grpc_integer_options){DEFAULT_MAX_CONNECTION_AGE_GRACE_MS, 0,
INT_MAX});
chand->max_connection_age_grace =
value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_millis(value, GPR_TIMESPAN);
} else if (0 == strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_CONNECTION_IDLE_MS)) {
const int value = grpc_channel_arg_get_integer(
&args->channel_args->args[i],
(grpc_integer_options){DEFAULT_MAX_CONNECTION_IDLE_MS, 1, INT_MAX});
chand->max_connection_idle =
value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN)
: gpr_time_from_millis(value, GPR_TIMESPAN);
}
}
grpc_closure_init(&chand->close_max_idle_channel, close_max_idle_channel,
chand, grpc_schedule_on_exec_ctx);
grpc_closure_init(&chand->close_max_age_channel, close_max_age_channel, chand,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&chand->force_close_max_age_channel,
force_close_max_age_channel, chand,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&chand->start_max_idle_timer_after_init,
start_max_idle_timer_after_init, chand,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&chand->start_max_age_timer_after_init,
start_max_age_timer_after_init, chand,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&chand->start_max_age_grace_timer_after_goaway_op,
start_max_age_grace_timer_after_goaway_op, chand,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&chand->channel_connectivity_changed,
channel_connectivity_changed, chand,
grpc_schedule_on_exec_ctx);
if (gpr_time_cmp(chand->max_connection_age, gpr_inf_future(GPR_TIMESPAN)) !=
0) {
/* When the channel reaches its max age, we send down an op with
goaway_error set. However, we can't send down any ops until after the
channel stack is fully initialized. If we start the timer here, we have
no guarantee that the timer won't pop before channel stack initialization
is finished. To avoid that problem, we create a closure to start the
timer, and we schedule that closure to be run after call stack
initialization is done. */
GRPC_CHANNEL_STACK_REF(chand->channel_stack,
"max_age start_max_age_timer_after_init");
grpc_closure_sched(exec_ctx, &chand->start_max_age_timer_after_init,
GRPC_ERROR_NONE);
}
/* Initialize the number of calls as 1, so that the max_idle_timer will not
start until start_max_idle_timer_after_init is invoked. */
gpr_atm_rel_store(&chand->call_count, 1);
if (gpr_time_cmp(chand->max_connection_idle, gpr_inf_future(GPR_TIMESPAN)) !=
0) {
GRPC_CHANNEL_STACK_REF(chand->channel_stack,
"max_age start_max_idle_timer_after_init");
grpc_closure_sched(exec_ctx, &chand->start_max_idle_timer_after_init,
GRPC_ERROR_NONE);
}
return GRPC_ERROR_NONE;
}
/* Destructor for channel_data. */
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
grpc_channel_element* elem) {}
const grpc_channel_filter grpc_max_age_filter = {
grpc_call_next_op,
grpc_channel_next_op,
0, /* sizeof_call_data */
init_call_elem,
grpc_call_stack_ignore_set_pollset_or_pollset_set,
destroy_call_elem,
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
grpc_call_next_get_peer,
grpc_channel_next_get_info,
"max_age"};

@ -0,0 +1,39 @@
//
// Copyright 2017, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GRPC_CORE_LIB_CHANNEL_MAX_AGE_FILTER_H
#define GRPC_CORE_LIB_CHANNEL_MAX_AGE_FILTER_H
#include "src/core/lib/channel/channel_stack.h"
extern const grpc_channel_filter grpc_max_age_filter;
#endif /* GRPC_CORE_LIB_CHANNEL_MAX_AGE_FILTER_H */

@ -43,7 +43,7 @@
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/tsi/ssl_transport_security.h"
#include "src/core/tsi/ssl_transport_security.h"
typedef struct {
grpc_channel_security_connector base;

@ -1107,19 +1107,20 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
static void notify_on(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
grpc_closure *closure) {
while (true) {
/* Fast-path: CLOSURE_NOT_READY -> <closure>.
The 'release' cas here matches the 'acquire' load in set_ready and
set_shutdown ensuring that the closure (scheduled by set_ready or
set_shutdown) happens-after the I/O event on the fd */
if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, (gpr_atm)closure)) {
return; /* Fast-path successful. Return */
}
/* Slowpath. The 'acquire' load matches the 'release' cas in set_ready and
set_shutdown */
gpr_atm curr = gpr_atm_acq_load(state);
gpr_atm curr = gpr_atm_no_barrier_load(state);
switch (curr) {
case CLOSURE_NOT_READY: {
/* CLOSURE_NOT_READY -> <closure>.
We're guaranteed by API that there's an acquire barrier before here,
so there's no need to double-dip and this can be a release-only.
The release itself pairs with the acquire half of a set_ready full
barrier. */
if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, (gpr_atm)closure)) {
return; /* Successful. Return */
}
break; /* retry */
}
@ -1134,7 +1135,7 @@ static void notify_on(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
is no other code that needs to 'happen-after' this) */
if (gpr_atm_no_barrier_cas(state, CLOSURE_READY, CLOSURE_NOT_READY)) {
grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE);
return; /* Slow-path successful. Return */
return; /* Successful. Return */
}
break; /* retry */
@ -1165,30 +1166,19 @@ static void notify_on(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
static void set_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
grpc_error *shutdown_err) {
/* Try the fast-path first (i.e expect the current value to be
CLOSURE_NOT_READY */
gpr_atm curr = CLOSURE_NOT_READY;
gpr_atm new_state = (gpr_atm)shutdown_err | FD_SHUTDOWN_BIT;
while (true) {
/* The 'release' cas here matches the 'acquire' load in notify_on to ensure
that the closure it schedules 'happens-after' the set_shutdown is called
on the fd */
if (gpr_atm_rel_cas(state, curr, new_state)) {
return; /* Fast-path successful. Return */
}
/* Fallback to slowpath. This 'acquire' load matches the 'release' cas in
notify_on and set_ready */
curr = gpr_atm_acq_load(state);
gpr_atm curr = gpr_atm_no_barrier_load(state);
switch (curr) {
case CLOSURE_READY: {
case CLOSURE_READY:
case CLOSURE_NOT_READY:
/* Need a full barrier here so that the initial load in notify_on
doesn't need a barrier */
if (gpr_atm_full_cas(state, curr, new_state)) {
return; /* early out */
}
break; /* retry */
}
case CLOSURE_NOT_READY: {
break; /* retry */
}
default: {
/* 'curr' is either a closure or the fd is already shutdown */
@ -1199,10 +1189,11 @@ static void set_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
}
/* Fd is not shutdown. Schedule the closure and move the state to
shutdown state. The 'release' cas here matches the 'acquire' load in
notify_on to ensure that the closure it schedules 'happens-after'
the set_shutdown is called on the fd */
if (gpr_atm_rel_cas(state, curr, new_state)) {
shutdown state.
Needs an acquire to pair with setting the closure (and get a
happens-after on that edge), and a release to pair with anything
loading the shutdown state. */
if (gpr_atm_full_cas(state, curr, new_state)) {
grpc_closure_sched(exec_ctx, (grpc_closure *)curr,
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"FD Shutdown", &shutdown_err, 1));
@ -1220,52 +1211,42 @@ static void set_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
}
static void set_ready(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state) {
/* Try an optimistic case first (i.e assume current state is
CLOSURE_NOT_READY).
This 'release' cas matches the 'acquire' load in notify_on ensuring that
any closure (scheduled by notify_on) 'happens-after' the return from
epoll_pwait */
if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, CLOSURE_READY)) {
return; /* early out */
}
/* The 'acquire' load here matches the 'release' cas in notify_on and
set_shutdown */
gpr_atm curr = gpr_atm_acq_load(state);
switch (curr) {
case CLOSURE_READY: {
/* Already ready. We are done here */
break;
}
while (true) {
gpr_atm curr = gpr_atm_no_barrier_load(state);
case CLOSURE_NOT_READY: {
/* The state was not CLOSURE_NOT_READY when we checked initially at the
beginning of this function but now it is CLOSURE_NOT_READY again.
This is only possible if the state transitioned out of
CLOSURE_NOT_READY to either CLOSURE_READY or <some closure> and then
back to CLOSURE_NOT_READY again (i.e after we entered this function,
the fd became "ready" and the necessary actions were already done).
So there is no need to make the state CLOSURE_READY now */
break;
}
switch (curr) {
case CLOSURE_READY: {
/* Already ready. We are done here */
return;
}
default: {
/* 'curr' is either a closure or the fd is shutdown */
if ((curr & FD_SHUTDOWN_BIT) > 0) {
/* The fd is shutdown. Do nothing */
} else if (gpr_atm_no_barrier_cas(state, curr, CLOSURE_NOT_READY)) {
/* The cas above was no-barrier since the state is being transitioned to
CLOSURE_NOT_READY; notify_on and set_shutdown do not schedule any
closures when transitioning out of CLOSURE_NO_READY state (i.e there
is no other code that needs to 'happen-after' this) */
case CLOSURE_NOT_READY: {
/* No barrier required as we're transitioning to a state that does not
involve a closure */
if (gpr_atm_no_barrier_cas(state, CLOSURE_NOT_READY, CLOSURE_READY)) {
return; /* early out */
}
break; /* retry */
}
grpc_closure_sched(exec_ctx, (grpc_closure *)curr, GRPC_ERROR_NONE);
default: {
/* 'curr' is either a closure or the fd is shutdown */
if ((curr & FD_SHUTDOWN_BIT) > 0) {
/* The fd is shutdown. Do nothing */
return;
}
/* Full cas: acquire pairs with this cas' release in the event of a
spurious set_ready; release pairs with this or the acquire in
notify_on (or set_shutdown) */
else if (gpr_atm_full_cas(state, curr, CLOSURE_NOT_READY)) {
grpc_closure_sched(exec_ctx, (grpc_closure *)curr, GRPC_ERROR_NONE);
return;
}
/* else the state changed again (only possible by either a racing
set_ready or set_shutdown functions. In both these cases, the closure
would have been scheduled for execution. So we are done here */
return;
}
/* else the state changed again (only possible by either a racing
set_ready or set_shutdown functions. In both these cases, the closure
would have been scheduled for execution. So we are done here */
break;
}
}
}

@ -279,11 +279,17 @@ static void rq_step_sched(grpc_exec_ctx *exec_ctx,
/* update the atomically available resource estimate - use no barriers since
timeliness of delivery really doesn't matter much */
static void rq_update_estimate(grpc_resource_quota *resource_quota) {
gpr_atm memory_usage_estimation = MEMORY_USAGE_ESTIMATION_MAX;
if (resource_quota->size != 0) {
memory_usage_estimation =
GPR_CLAMP((gpr_atm)((1.0 -
((double)resource_quota->free_pool) /
((double)resource_quota->size)) *
MEMORY_USAGE_ESTIMATION_MAX),
0, MEMORY_USAGE_ESTIMATION_MAX);
}
gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation,
(gpr_atm)((1.0 -
((double)resource_quota->free_pool) /
((double)resource_quota->size)) *
MEMORY_USAGE_ESTIMATION_MAX));
memory_usage_estimation);
}
/* returns true if all allocations are completed */

@ -0,0 +1,110 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_POSIX_SOCKET
#include "src/core/lib/iomgr/socket_factory_posix.h"
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/sync.h>
#include <grpc/support/useful.h>
void grpc_socket_factory_init(grpc_socket_factory *factory,
const grpc_socket_factory_vtable *vtable) {
factory->vtable = vtable;
gpr_ref_init(&factory->refcount, 1);
}
int grpc_socket_factory_socket(grpc_socket_factory *factory, int domain,
int type, int protocol) {
return factory->vtable->socket(factory, domain, type, protocol);
}
int grpc_socket_factory_bind(grpc_socket_factory *factory, int sockfd,
const grpc_resolved_address *addr) {
return factory->vtable->bind(factory, sockfd, addr);
}
int grpc_socket_factory_compare(grpc_socket_factory *a,
grpc_socket_factory *b) {
int c = GPR_ICMP(a, b);
if (c != 0) {
grpc_socket_factory *sma = a;
grpc_socket_factory *smb = b;
c = GPR_ICMP(sma->vtable, smb->vtable);
if (c == 0) {
c = sma->vtable->compare(sma, smb);
}
}
return c;
}
grpc_socket_factory *grpc_socket_factory_ref(grpc_socket_factory *factory) {
gpr_ref(&factory->refcount);
return factory;
}
void grpc_socket_factory_unref(grpc_socket_factory *factory) {
if (gpr_unref(&factory->refcount)) {
factory->vtable->destroy(factory);
}
}
static void *socket_factory_arg_copy(void *p) {
return grpc_socket_factory_ref(p);
}
static void socket_factory_arg_destroy(grpc_exec_ctx *exec_ctx, void *p) {
grpc_socket_factory_unref(p);
}
static int socket_factory_cmp(void *a, void *b) {
return grpc_socket_factory_compare((grpc_socket_factory *)a,
(grpc_socket_factory *)b);
}
static const grpc_arg_pointer_vtable socket_factory_arg_vtable = {
socket_factory_arg_copy, socket_factory_arg_destroy, socket_factory_cmp};
grpc_arg grpc_socket_factory_to_arg(grpc_socket_factory *factory) {
grpc_arg arg;
arg.type = GRPC_ARG_POINTER;
arg.key = GRPC_ARG_SOCKET_FACTORY;
arg.value.pointer.vtable = &socket_factory_arg_vtable;
arg.value.pointer.p = factory;
return arg;
}
#endif

@ -0,0 +1,90 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_LIB_IOMGR_SOCKET_FACTORY_POSIX_H
#define GRPC_CORE_LIB_IOMGR_SOCKET_FACTORY_POSIX_H
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/sync.h>
#include "src/core/lib/iomgr/resolve_address.h"
#ifdef __cplusplus
extern "C" {
#endif
/** The virtual table of grpc_socket_factory */
typedef struct {
/** Replacement for socket(2) */
int (*socket)(grpc_socket_factory *factory, int domain, int type,
int protocol);
/** Replacement for bind(2) */
int (*bind)(grpc_socket_factory *factory, int sockfd,
const grpc_resolved_address *addr);
/** Compare socket factory \a a and \a b */
int (*compare)(grpc_socket_factory *a, grpc_socket_factory *b);
/** Destroys the socket factory instance */
void (*destroy)(grpc_socket_factory *factory);
} grpc_socket_factory_vtable;
/** The Socket Factory interface allows changes on socket options */
struct grpc_socket_factory {
const grpc_socket_factory_vtable *vtable;
gpr_refcount refcount;
};
/** called by concrete implementations to initialize the base struct */
void grpc_socket_factory_init(grpc_socket_factory *factory,
const grpc_socket_factory_vtable *vtable);
/** Wrap \a factory as a grpc_arg */
grpc_arg grpc_socket_factory_to_arg(grpc_socket_factory *factory);
/** Perform the equivalent of a socket(2) operation using \a factory */
int grpc_socket_factory_socket(grpc_socket_factory *factory, int domain,
int type, int protocol);
/** Perform the equivalent of a bind(2) operation using \a factory */
int grpc_socket_factory_bind(grpc_socket_factory *factory, int sockfd,
const grpc_resolved_address *addr);
/** Compare if \a a and \a b are the same factory or have same settings */
int grpc_socket_factory_compare(grpc_socket_factory *a, grpc_socket_factory *b);
grpc_socket_factory *grpc_socket_factory_ref(grpc_socket_factory *factory);
void grpc_socket_factory_unref(grpc_socket_factory *factory);
#ifdef __cplusplus
}
#endif
#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_FACTORY_POSIX_H */

@ -278,11 +278,25 @@ static grpc_error *error_for_fd(int fd, const grpc_resolved_address *addr) {
grpc_error *grpc_create_dualstack_socket(
const grpc_resolved_address *resolved_addr, int type, int protocol,
grpc_dualstack_mode *dsmode, int *newfd) {
return grpc_create_dualstack_socket_using_factory(NULL, resolved_addr, type,
protocol, dsmode, newfd);
}
static int create_socket(grpc_socket_factory *factory, int domain, int type,
int protocol) {
return (factory != NULL)
? grpc_socket_factory_socket(factory, domain, type, protocol)
: socket(domain, type, protocol);
}
grpc_error *grpc_create_dualstack_socket_using_factory(
grpc_socket_factory *factory, const grpc_resolved_address *resolved_addr,
int type, int protocol, grpc_dualstack_mode *dsmode, int *newfd) {
const struct sockaddr *addr = (const struct sockaddr *)resolved_addr->addr;
int family = addr->sa_family;
if (family == AF_INET6) {
if (grpc_ipv6_loopback_available()) {
*newfd = socket(family, type, protocol);
*newfd = create_socket(factory, family, type, protocol);
} else {
*newfd = -1;
errno = EAFNOSUPPORT;
@ -304,7 +318,7 @@ grpc_error *grpc_create_dualstack_socket(
family = AF_INET;
}
*dsmode = family == AF_INET ? GRPC_DSMODE_IPV4 : GRPC_DSMODE_NONE;
*newfd = socket(family, type, protocol);
*newfd = create_socket(factory, family, type, protocol);
return error_for_fd(*newfd, resolved_addr);
}

@ -41,6 +41,7 @@
#include <grpc/impl/codegen/grpc_types.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/socket_factory_posix.h"
#include "src/core/lib/iomgr/socket_mutator.h"
/* a wrapper for accept or accept4 */
@ -137,4 +138,10 @@ grpc_error *grpc_create_dualstack_socket(const grpc_resolved_address *addr,
grpc_dualstack_mode *dsmode,
int *newfd);
/* Same as grpc_create_dualstack_socket(), but use the given socket factory (if
non-null) to create the socket, rather than calling socket() directly. */
grpc_error *grpc_create_dualstack_socket_using_factory(
grpc_socket_factory *factory, const grpc_resolved_address *addr, int type,
int protocol, grpc_dualstack_mode *dsmode, int *newfd);
#endif /* GRPC_CORE_LIB_IOMGR_SOCKET_UTILS_POSIX_H */

@ -185,10 +185,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
/* delete ALL the things */
gpr_mu_lock(&s->mu);
if (!s->shutdown) {
gpr_mu_unlock(&s->mu);
return;
}
GPR_ASSERT(s->shutdown);
if (s->head) {
grpc_tcp_listener *sp;
@ -301,7 +298,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
error:
gpr_mu_lock(&sp->server->mu);
if (0 == --sp->server->active_ports) {
if (0 == --sp->server->active_ports && sp->server->shutdown) {
gpr_mu_unlock(&sp->server->mu);
deactivated_all_ports(exec_ctx, sp->server);
} else {

@ -33,7 +33,7 @@
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_HAVE_IFADDRS
#ifdef GRPC_POSIX_SOCKET
#include "src/core/lib/iomgr/tcp_server_utils_posix.h"
@ -218,4 +218,4 @@ error:
return ret;
}
#endif /* GRPC_HAVE_IFADDRS */
#endif /* GRPC_POSIX_SOCKET */

@ -78,6 +78,10 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
uv_timer->data = timer;
timer->uv_timer = uv_timer;
uv_timer_start(uv_timer, run_expired_timer, timeout, 0);
/* We assume that gRPC timers are only used alongside other active gRPC
objects, and that there will therefore always be something else keeping
the uv loop alive whenever there is a timer */
uv_unref((uv_handle_t *)uv_timer);
}
void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {

@ -59,11 +59,13 @@
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/socket_factory_posix.h"
#include "src/core/lib/iomgr/socket_utils_posix.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/support/string.h"
@ -89,6 +91,9 @@ struct grpc_udp_listener {
struct grpc_udp_server {
gpr_mu mu;
/* factory to use for creating and binding sockets, or NULL */
grpc_socket_factory *socket_factory;
/* active port count: how many ports are actually still listening */
size_t active_ports;
/* destroyed port count: how many ports are completely destroyed */
@ -113,9 +118,24 @@ struct grpc_udp_server {
void *user_data;
};
grpc_udp_server *grpc_udp_server_create(void) {
static grpc_socket_factory *get_socket_factory(const grpc_channel_args *args) {
if (args) {
const grpc_arg *arg = grpc_channel_args_find(args, GRPC_ARG_SOCKET_FACTORY);
if (arg) {
GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
return arg->value.pointer.p;
}
}
return NULL;
}
grpc_udp_server *grpc_udp_server_create(const grpc_channel_args *args) {
grpc_udp_server *s = gpr_malloc(sizeof(grpc_udp_server));
gpr_mu_init(&s->mu);
s->socket_factory = get_socket_factory(args);
if (s->socket_factory) {
grpc_socket_factory_ref(s->socket_factory);
}
s->active_ports = 0;
s->destroyed_ports = 0;
s->shutdown = 0;
@ -139,6 +159,10 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
gpr_free(sp);
}
if (s->socket_factory) {
grpc_socket_factory_unref(s->socket_factory);
}
gpr_free(s);
}
@ -162,10 +186,7 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
/* delete ALL the things */
gpr_mu_lock(&s->mu);
if (!s->shutdown) {
gpr_mu_unlock(&s->mu);
return;
}
GPR_ASSERT(s->shutdown);
if (s->head) {
grpc_udp_listener *sp;
@ -215,8 +236,17 @@ void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
}
}
static int bind_socket(grpc_socket_factory *socket_factory, int sockfd,
const grpc_resolved_address *addr) {
return (socket_factory != NULL)
? grpc_socket_factory_bind(socket_factory, sockfd, addr)
: bind(sockfd, (struct sockaddr *)addr->addr,
(socklen_t)addr->len);
}
/* Prepare a recently-created socket for listening. */
static int prepare_socket(int fd, const grpc_resolved_address *addr) {
static int prepare_socket(grpc_socket_factory *socket_factory, int fd,
const grpc_resolved_address *addr) {
grpc_resolved_address sockname_temp;
struct sockaddr *addr_ptr = (struct sockaddr *)addr->addr;
/* Set send/receive socket buffers to 1 MB */
@ -246,7 +276,7 @@ static int prepare_socket(int fd, const grpc_resolved_address *addr) {
}
GPR_ASSERT(addr->len < ~(socklen_t)0);
if (bind(fd, (struct sockaddr *)addr, (socklen_t)addr->len) < 0) {
if (bind_socket(socket_factory, fd, addr) < 0) {
char *addr_str;
grpc_sockaddr_to_string(&addr_str, addr, 0);
gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
@ -288,7 +318,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
gpr_mu_lock(&sp->server->mu);
if (error != GRPC_ERROR_NONE) {
if (0 == --sp->server->active_ports) {
if (0 == --sp->server->active_ports && sp->server->shutdown) {
gpr_mu_unlock(&sp->server->mu);
deactivated_all_ports(exec_ctx, sp->server);
} else {
@ -311,7 +341,7 @@ static void on_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
gpr_mu_lock(&(sp->server->mu));
if (error != GRPC_ERROR_NONE) {
if (0 == --sp->server->active_ports) {
if (0 == --sp->server->active_ports && sp->server->shutdown) {
gpr_mu_unlock(&sp->server->mu);
deactivated_all_ports(exec_ctx, sp->server);
} else {
@ -339,7 +369,7 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
char *addr_str;
char *name;
port = prepare_socket(fd, addr);
port = prepare_socket(s->socket_factory, fd, addr);
if (port >= 0) {
grpc_sockaddr_to_string(&addr_str, addr, 1);
gpr_asprintf(&name, "udp-server-listener:%s", addr_str);
@ -417,8 +447,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s,
/* Try listening on IPv6 first. */
addr = &wild6;
// TODO(rjshade): Test and propagate the returned grpc_error*:
GRPC_ERROR_UNREF(grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP,
&dsmode, &fd));
GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
allocated_port1 =
add_socket_to_server(s, fd, addr, read_cb, write_cb, orphan_cb);
if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
@ -433,8 +463,8 @@ int grpc_udp_server_add_port(grpc_udp_server *s,
}
// TODO(rjshade): Test and propagate the returned grpc_error*:
GRPC_ERROR_UNREF(grpc_create_dualstack_socket(addr, SOCK_DGRAM, IPPROTO_UDP,
&dsmode, &fd));
GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
if (fd < 0) {
gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
}

@ -58,7 +58,7 @@ typedef void (*grpc_udp_server_orphan_cb)(grpc_exec_ctx *exec_ctx,
grpc_fd *emfd, void *user_data);
/* Create a server, initially not bound to any ports */
grpc_udp_server *grpc_udp_server_create(void);
grpc_udp_server *grpc_udp_server_create(const grpc_channel_args *args);
/* Start listening to bound ports. user_data is passed to callbacks. */
void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *udp_server,

@ -40,8 +40,8 @@
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/lib/security/util/b64.h"
#include "src/core/lib/security/util/json_util.h"
#include "src/core/lib/slice/b64.h"
#include "src/core/lib/support/string.h"
#include <openssl/bio.h>

@ -45,10 +45,10 @@
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/security/util/b64.h"
#include "src/core/lib/slice/b64.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/tsi/ssl_types.h"
#include "src/core/tsi/ssl_types.h"
/* --- Utils. --- */

@ -49,7 +49,7 @@
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/tsi/transport_security_interface.h"
#include "src/core/tsi/transport_security_interface.h"
#define STAGING_BUFFER_SIZE 8192

@ -54,8 +54,8 @@
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/tsi/fake_transport_security.h"
#include "src/core/lib/tsi/ssl_transport_security.h"
#include "src/core/tsi/fake_transport_security.h"
#include "src/core/tsi/ssl_transport_security.h"
/* -- Constants. -- */

@ -39,7 +39,7 @@
#include "src/core/lib/channel/handshaker.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/tcp_server.h"
#include "src/core/lib/tsi/transport_security_interface.h"
#include "src/core/tsi/transport_security_interface.h"
/* --- status enum. --- */

@ -35,7 +35,7 @@
#define GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/tsi/transport_security_interface.h"
#include "src/core/tsi/transport_security_interface.h"
grpc_error *grpc_set_tsi_error_result(grpc_error *error, tsi_result result);

@ -31,7 +31,7 @@
*
*/
#include "src/core/lib/security/util/b64.h"
#include "src/core/lib/slice/b64.h"
#include <stdint.h>
#include <string.h>
@ -71,15 +71,31 @@ static const char base64_url_safe_chars[] =
char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe,
int multiline) {
const unsigned char *data = vdata;
const char *base64_chars =
url_safe ? base64_url_safe_chars : base64_url_unsafe_chars;
size_t result_projected_size =
grpc_base64_estimate_encoded_size(data_size, url_safe, multiline);
char *result = gpr_malloc(result_projected_size);
grpc_base64_encode_core(result, vdata, data_size, url_safe, multiline);
return result;
}
size_t grpc_base64_estimate_encoded_size(size_t data_size, int url_safe,
int multiline) {
size_t result_projected_size =
4 * ((data_size + 3) / 3) +
2 * (multiline ? (data_size / (3 * GRPC_BASE64_MULTILINE_NUM_BLOCKS))
: 0) +
1;
char *result = gpr_malloc(result_projected_size);
return result_projected_size;
}
void grpc_base64_encode_core(char *result, const void *vdata, size_t data_size,
int url_safe, int multiline) {
const unsigned char *data = vdata;
const char *base64_chars =
url_safe ? base64_url_safe_chars : base64_url_unsafe_chars;
const size_t result_projected_size =
grpc_base64_estimate_encoded_size(data_size, url_safe, multiline);
char *current = result;
size_t num_blocks = 0;
size_t i = 0;
@ -119,7 +135,6 @@ char *grpc_base64_encode(const void *vdata, size_t data_size, int url_safe,
GPR_ASSERT(current >= result);
GPR_ASSERT((uintptr_t)(current - result) < result_projected_size);
result[current - result] = '\0';
return result;
}
grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64,

@ -31,16 +31,28 @@
*
*/
#ifndef GRPC_CORE_LIB_SECURITY_UTIL_B64_H
#define GRPC_CORE_LIB_SECURITY_UTIL_B64_H
#ifndef GRPC_CORE_LIB_SLICE_B64_H
#define GRPC_CORE_LIB_SLICE_B64_H
#include <grpc/slice.h>
/* Encodes data using base64. It is the caller's responsability to free
the returned char * using gpr_free. Returns NULL on NULL input. */
the returned char * using gpr_free. Returns NULL on NULL input.
TODO(makdharma) : change the flags to bool from int */
char *grpc_base64_encode(const void *data, size_t data_size, int url_safe,
int multiline);
/* estimate the upper bound on size of base64 encoded data. The actual size
* is guaranteed to be less than or equal to the size returned here. */
size_t grpc_base64_estimate_encoded_size(size_t data_size, int url_safe,
int multiline);
/* Encodes data using base64 and write it to memory pointed to by result. It is
* the caller's responsiblity to allocate enough memory in |result| to fit the
* encoded data. */
void grpc_base64_encode_core(char *result, const void *vdata, size_t data_size,
int url_safe, int multiline);
/* Decodes data according to the base64 specification. Returns an empty
slice in case of failure. */
grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64,
@ -50,4 +62,4 @@ grpc_slice grpc_base64_decode(grpc_exec_ctx *exec_ctx, const char *b64,
grpc_slice grpc_base64_decode_with_len(grpc_exec_ctx *exec_ctx, const char *b64,
size_t b64_len, int url_safe);
#endif /* GRPC_CORE_LIB_SECURITY_UTIL_B64_H */
#endif /* GRPC_CORE_LIB_SLICE_B64_H */

@ -42,7 +42,7 @@
int gpr_time_cmp(gpr_timespec a, gpr_timespec b) {
int cmp = (a.tv_sec > b.tv_sec) - (a.tv_sec < b.tv_sec);
GPR_ASSERT(a.clock_type == b.clock_type);
if (cmp == 0) {
if (cmp == 0 && a.tv_sec != INT64_MAX && a.tv_sec != INT64_MIN) {
cmp = (a.tv_nsec > b.tv_nsec) - (a.tv_nsec < b.tv_nsec);
}
return cmp;
@ -244,15 +244,9 @@ gpr_timespec gpr_convert_clock_type(gpr_timespec t, gpr_clock_type clock_type) {
return t;
}
if (t.tv_nsec == 0) {
if (t.tv_sec == INT64_MAX) {
t.clock_type = clock_type;
return t;
}
if (t.tv_sec == INT64_MIN) {
t.clock_type = clock_type;
return t;
}
if (t.tv_sec == INT64_MAX || t.tv_sec == INT64_MIN) {
t.clock_type = clock_type;
return t;
}
if (clock_type == GPR_TIMESPAN) {

@ -504,9 +504,9 @@ void grpc_call_destroy(grpc_call *c) {
if (c == parent->first_child) {
parent->first_child = NULL;
}
c->sibling_prev->sibling_next = c->sibling_next;
c->sibling_next->sibling_prev = c->sibling_prev;
}
c->sibling_prev->sibling_next = c->sibling_next;
c->sibling_next->sibling_prev = c->sibling_prev;
gpr_mu_unlock(&parent->child_list_mu);
GRPC_CALL_INTERNAL_UNREF(&exec_ctx, parent, "child");
}
@ -625,7 +625,7 @@ static bool get_final_status_from(
void (*set_value)(grpc_status_code code, void *user_data),
void *set_value_user_data, grpc_slice *details) {
grpc_status_code code;
grpc_slice slice;
grpc_slice slice = grpc_empty_slice();
grpc_error_get_status(error, call->send_deadline, &code, &slice, NULL);
if (code == GRPC_STATUS_OK && !allow_ok_status) {
return false;

@ -150,17 +150,20 @@ grpc_channel *grpc_channel_create_with_builder(
} else if (0 == strcmp(args->args[i].key,
GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL)) {
channel->compression_options.default_level.is_set = true;
GPR_ASSERT(args->args[i].value.integer >= 0 &&
args->args[i].value.integer < GRPC_COMPRESS_LEVEL_COUNT);
channel->compression_options.default_level.level =
(grpc_compression_level)args->args[i].value.integer;
(grpc_compression_level)grpc_channel_arg_get_integer(
&args->args[i],
(grpc_integer_options){GRPC_COMPRESS_LEVEL_NONE,
GRPC_COMPRESS_LEVEL_NONE,
GRPC_COMPRESS_LEVEL_COUNT - 1});
} else if (0 == strcmp(args->args[i].key,
GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM)) {
channel->compression_options.default_algorithm.is_set = true;
GPR_ASSERT(args->args[i].value.integer >= 0 &&
args->args[i].value.integer < GRPC_COMPRESS_ALGORITHMS_COUNT);
channel->compression_options.default_algorithm.algorithm =
(grpc_compression_algorithm)args->args[i].value.integer;
(grpc_compression_algorithm)grpc_channel_arg_get_integer(
&args->args[i],
(grpc_integer_options){GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE,
GRPC_COMPRESS_ALGORITHMS_COUNT - 1});
} else if (0 ==
strcmp(args->args[i].key,
GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET)) {
@ -194,8 +197,14 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
size_t grpc_channel_get_call_size_estimate(grpc_channel *channel) {
#define ROUND_UP_SIZE 256
/* We round up our current estimate to the NEXT value of ROUND_UP_SIZE.
This ensures:
1. a consistent size allocation when our estimate is drifting slowly
(which is common) - which tends to help most allocators reuse memory
2. a small amount of allowed growth over the estimate without hitting
the arena size doubling case, reducing overall memory usage */
return ((size_t)gpr_atm_no_barrier_load(&channel->call_size_estimate) +
ROUND_UP_SIZE) &
2 * ROUND_UP_SIZE) &
~(size_t)(ROUND_UP_SIZE - 1);
}

@ -0,0 +1,77 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/lib/surface/completion_queue_factory.h"
#include "src/core/lib/surface/completion_queue.h"
#include <grpc/support/log.h>
/* TODO (sreek) - Currently this does not use the attributes arg. This will be
added in a future PR */
static grpc_completion_queue* default_create(
const grpc_completion_queue_factory* factory,
const grpc_completion_queue_attributes* attributes) {
return grpc_completion_queue_create(NULL);
}
static grpc_completion_queue_factory_vtable default_vtable = {default_create};
static const grpc_completion_queue_factory g_default_cq_factory = {
"Default Factory", NULL, &default_vtable};
const grpc_completion_queue_factory* grpc_completion_queue_factory_lookup(
const grpc_completion_queue_attributes* attributes) {
/* As we add more fields to grpc_completion_queue_attributes, we may have to
change this assert to:
GPR_ASSERT (attributes->version >= 1 &&
attributes->version <= GRPC_CQ_CURRENT_VERSION) */
GPR_ASSERT(attributes->version == 1);
/* The default factory can handle version 1 of the attributes structure. We
may have to change this as more fields are added to the structure */
return &g_default_cq_factory;
}
grpc_completion_queue* grpc_completion_queue_create_for_next(void* reserved) {
GPR_ASSERT(!reserved);
grpc_completion_queue_attributes attr = {1, GRPC_CQ_NEXT,
GRPC_CQ_DEFAULT_POLLING};
return g_default_cq_factory.vtable->create(&g_default_cq_factory, &attr);
}
grpc_completion_queue* grpc_completion_queue_create_for_pluck(void* reserved) {
GPR_ASSERT(!reserved);
grpc_completion_queue_attributes attr = {1, GRPC_CQ_PLUCK,
GRPC_CQ_DEFAULT_POLLING};
return g_default_cq_factory.vtable->create(&g_default_cq_factory, &attr);
}

@ -0,0 +1,51 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H
#define GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H
#include <grpc/grpc.h>
#include "src/core/lib/surface/completion_queue.h"
typedef struct grpc_completion_queue_factory_vtable {
grpc_completion_queue* (*create)(const grpc_completion_queue_factory*,
const grpc_completion_queue_attributes*);
} grpc_completion_queue_factory_vtable;
struct grpc_completion_queue_factory {
const char* name;
void* data; /* Factory specific data */
grpc_completion_queue_factory_vtable* vtable;
};
#endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_FACTORY_H */

@ -47,6 +47,7 @@
#include "src/core/lib/channel/handshaker_registry.h"
#include "src/core/lib/channel/http_client_filter.h"
#include "src/core/lib/channel/http_server_filter.h"
#include "src/core/lib/channel/max_age_filter.h"
#include "src/core/lib/channel/message_size_filter.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/http/parser.h"
@ -113,6 +114,9 @@ static void register_builtin_channel_init() {
grpc_channel_init_register_stage(
GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter,
(void *)&grpc_server_deadline_filter);
grpc_channel_init_register_stage(
GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter,
(void *)&grpc_max_age_filter);
grpc_channel_init_register_stage(
GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
prepend_filter, (void *)&grpc_message_size_filter);

@ -43,7 +43,7 @@
#include "src/core/lib/security/transport/security_connector.h"
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/tsi/transport_security_interface.h"
#include "src/core/tsi/transport_security_interface.h"
void grpc_security_pre_init(void) {
grpc_register_tracer("secure_endpoint", &grpc_trace_secure_endpoint);

@ -73,4 +73,4 @@ void grpc_bdp_estimator_start_ping(grpc_bdp_estimator *estimator);
// Completes a previously started ping
void grpc_bdp_estimator_complete_ping(grpc_bdp_estimator *estimator);
#endif
#endif /* GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H */

@ -43,6 +43,8 @@ extern void grpc_lb_policy_pick_first_init(void);
extern void grpc_lb_policy_pick_first_shutdown(void);
extern void grpc_lb_policy_round_robin_init(void);
extern void grpc_lb_policy_round_robin_shutdown(void);
extern void grpc_resolver_dns_ares_init(void);
extern void grpc_resolver_dns_ares_shutdown(void);
extern void grpc_resolver_dns_native_init(void);
extern void grpc_resolver_dns_native_shutdown(void);
extern void grpc_resolver_sockaddr_init(void);
@ -63,6 +65,8 @@ void grpc_register_built_in_plugins(void) {
grpc_lb_policy_pick_first_shutdown);
grpc_register_plugin(grpc_lb_policy_round_robin_init,
grpc_lb_policy_round_robin_shutdown);
grpc_register_plugin(grpc_resolver_dns_ares_init,
grpc_resolver_dns_ares_shutdown);
grpc_register_plugin(grpc_resolver_dns_native_init,
grpc_resolver_dns_native_shutdown);
grpc_register_plugin(grpc_resolver_sockaddr_init,

@ -37,6 +37,8 @@ extern void grpc_chttp2_plugin_init(void);
extern void grpc_chttp2_plugin_shutdown(void);
extern void grpc_client_channel_init(void);
extern void grpc_client_channel_shutdown(void);
extern void grpc_resolver_dns_ares_init(void);
extern void grpc_resolver_dns_ares_shutdown(void);
extern void grpc_resolver_dns_native_init(void);
extern void grpc_resolver_dns_native_shutdown(void);
extern void grpc_resolver_sockaddr_init(void);
@ -57,6 +59,8 @@ void grpc_register_built_in_plugins(void) {
grpc_chttp2_plugin_shutdown);
grpc_register_plugin(grpc_client_channel_init,
grpc_client_channel_shutdown);
grpc_register_plugin(grpc_resolver_dns_ares_init,
grpc_resolver_dns_ares_shutdown);
grpc_register_plugin(grpc_resolver_dns_native_init,
grpc_resolver_dns_native_shutdown);
grpc_register_plugin(grpc_resolver_sockaddr_init,

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

Loading…
Cancel
Save