Merge remote-tracking branch 'upstream/master' into extend_thd_stack_size

pull/19393/head
Yunjia Wang 6 years ago
commit 266c919afc
  1. 1
      BUILD
  2. 1
      BUILD.gn
  3. 3
      CMakeLists.txt
  4. 3
      Makefile
  5. 2
      WORKSPACE
  6. 6
      bazel/generate_cc.bzl
  7. 6
      bazel/python_rules.bzl
  8. 1
      build.yaml
  9. 65
      examples/python/auth/BUILD.bazel
  10. 112
      examples/python/auth/README.md
  11. 31
      examples/python/auth/_credentials.py
  12. 19
      examples/python/auth/credentials/localhost.crt
  13. 27
      examples/python/auth/credentials/localhost.key
  14. 20
      examples/python/auth/credentials/root.crt
  15. 105
      examples/python/auth/customized_auth_client.py
  16. 110
      examples/python/auth/customized_auth_server.py
  17. 56
      examples/python/auth/test/_auth_example_test.py
  18. 1
      gRPC-C++.podspec
  19. 1
      grpc.def
  20. 25
      include/grpc/grpc_security.h
  21. 24
      include/grpcpp/completion_queue_impl.h
  22. 1
      include/grpcpp/generic/generic_stub_impl.h
  23. 4
      include/grpcpp/impl/codegen/async_generic_service.h
  24. 47
      include/grpcpp/impl/codegen/async_stream.h
  25. 19
      include/grpcpp/impl/codegen/async_unary_call.h
  26. 8
      include/grpcpp/impl/codegen/call_op_set.h
  27. 36
      include/grpcpp/impl/codegen/client_callback.h
  28. 2
      include/grpcpp/impl/codegen/intercepted_channel.h
  29. 39
      include/grpcpp/impl/codegen/method_handler_impl.h
  30. 3
      include/grpcpp/impl/codegen/server_interface.h
  31. 49
      include/grpcpp/impl/codegen/sync_stream.h
  32. 4
      include/grpcpp/impl/server_builder_plugin.h
  33. 1
      include/grpcpp/security/credentials.h
  34. 28
      include/grpcpp/security/credentials_impl.h
  35. 49
      include/grpcpp/server_impl.h
  36. 5
      src/compiler/cpp_generator.cc
  37. 25
      src/core/ext/filters/client_channel/client_channel_channelz.cc
  38. 17
      src/core/ext/filters/client_channel/client_channel_channelz.h
  39. 480
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc
  40. 27
      src/core/ext/filters/client_channel/subchannel.cc
  41. 8
      src/core/ext/filters/client_channel/subchannel.h
  42. 5
      src/core/ext/transport/chttp2/transport/hpack_encoder.cc
  43. 5
      src/core/lib/iomgr/executor.cc
  44. 8
      src/core/lib/security/credentials/jwt/json_token.cc
  45. 258
      src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
  46. 16
      src/core/lib/security/credentials/oauth2/oauth2_credentials.h
  47. 24
      src/core/lib/security/util/json_util.cc
  48. 4
      src/core/lib/security/util/json_util.h
  49. 3
      src/core/lib/transport/metadata.h
  50. 1
      src/cpp/client/create_channel_internal.h
  51. 10
      src/cpp/client/insecure_credentials.cc
  52. 10
      src/cpp/client/secure_credentials.cc
  53. 8
      src/cpp/client/secure_credentials.h
  54. 10
      src/csharp/Grpc.Core/Common.csproj.include
  55. 9
      src/csharp/Grpc.Tools.Tests/Grpc.Tools.Tests.csproj
  56. 9
      src/csharp/Grpc.Tools/Grpc.Tools.csproj
  57. 3
      src/csharp/Grpc/Grpc.csproj
  58. 44
      src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd.pxi
  59. 42
      src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi
  60. 2
      src/ruby/ext/grpc/rb_grpc_imports.generated.c
  61. 3
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  62. 305
      test/core/security/credentials_test.cc
  63. 82
      test/core/security/fetch_oauth2.cc
  64. 15
      test/core/security/oauth2_utils.cc
  65. 1
      test/core/surface/public_headers_must_be_c89.c
  66. 2
      test/cpp/codegen/compiler_test_golden
  67. 1
      test/cpp/qps/server.h
  68. 14
      test/cpp/util/create_test_channel.h
  69. 46
      tools/distrib/check_protobuf_pod_version.sh
  70. 1
      tools/doxygen/Doxyfile.c++
  71. 1
      tools/doxygen/Doxyfile.c++.internal
  72. 4
      tools/interop_matrix/client_matrix.py
  73. 2
      tools/run_tests/generated/sources_and_headers.json
  74. 3
      tools/run_tests/sanity/sanity_tests.yaml

@ -222,6 +222,7 @@ GRPCXX_PUBLIC_HDRS = [
"include/grpcpp/channel_impl.h",
"include/grpcpp/client_context.h",
"include/grpcpp/completion_queue.h",
"include/grpcpp/completion_queue_impl.h",
"include/grpcpp/create_channel.h",
"include/grpcpp/create_channel_impl.h",
"include/grpcpp/create_channel_posix.h",

@ -1028,6 +1028,7 @@ config("grpc_config") {
"include/grpcpp/channel_impl.h",
"include/grpcpp/client_context.h",
"include/grpcpp/completion_queue.h",
"include/grpcpp/completion_queue_impl.h",
"include/grpcpp/create_channel.h",
"include/grpcpp/create_channel_impl.h",
"include/grpcpp/create_channel_posix.h",

@ -3160,6 +3160,7 @@ foreach(_hdr
include/grpcpp/channel_impl.h
include/grpcpp/client_context.h
include/grpcpp/completion_queue.h
include/grpcpp/completion_queue_impl.h
include/grpcpp/create_channel.h
include/grpcpp/create_channel_impl.h
include/grpcpp/create_channel_posix.h
@ -3781,6 +3782,7 @@ foreach(_hdr
include/grpcpp/channel_impl.h
include/grpcpp/client_context.h
include/grpcpp/completion_queue.h
include/grpcpp/completion_queue_impl.h
include/grpcpp/create_channel.h
include/grpcpp/create_channel_impl.h
include/grpcpp/create_channel_posix.h
@ -4780,6 +4782,7 @@ foreach(_hdr
include/grpcpp/channel_impl.h
include/grpcpp/client_context.h
include/grpcpp/completion_queue.h
include/grpcpp/completion_queue_impl.h
include/grpcpp/create_channel.h
include/grpcpp/create_channel_impl.h
include/grpcpp/create_channel_posix.h

@ -5534,6 +5534,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \
@ -6163,6 +6164,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \
@ -7111,6 +7113,7 @@ PUBLIC_HEADERS_CXX += \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \

@ -20,7 +20,7 @@ register_toolchains(
git_repository(
name = "io_bazel_rules_python",
commit = "8b5d0683a7d878b28fffe464779c8a53659fc645",
commit = "fdbb17a4118a1728d19e638a5291b4c4266ea5b8",
remote = "https://github.com/bazelbuild/rules_python.git",
)

@ -41,11 +41,11 @@ def _join_directories(directories):
def generate_cc_impl(ctx):
"""Implementation of the generate_cc rule."""
protos = [f for src in ctx.attr.srcs for f in src.proto.check_deps_sources.to_list()]
protos = [f for src in ctx.attr.srcs for f in src[ProtoInfo].check_deps_sources.to_list()]
includes = [
f
for src in ctx.attr.srcs
for f in src.proto.transitive_imports.to_list()
for f in src[ProtoInfo].transitive_imports.to_list()
]
outs = []
proto_root = get_proto_root(
@ -146,7 +146,7 @@ _generate_cc = rule(
"srcs": attr.label_list(
mandatory = True,
allow_empty = False,
providers = ["proto"],
providers = [ProtoInfo],
),
"plugin": attr.label(
executable = True,

@ -28,12 +28,12 @@ def _get_staged_proto_file(context, source_file):
def _generate_py_impl(context):
protos = []
for src in context.attr.deps:
for file in src.proto.direct_sources:
for file in src[ProtoInfo].direct_sources:
protos.append(_get_staged_proto_file(context, file))
includes = [
file
for src in context.attr.deps
for file in src.proto.transitive_imports.to_list()
for file in src[ProtoInfo].transitive_imports.to_list()
]
proto_root = get_proto_root(context.label.workspace_root)
format_str = (_GENERATED_GRPC_PROTO_FORMAT if context.executable.plugin else _GENERATED_PROTO_FORMAT)
@ -99,7 +99,7 @@ __generate_py = rule(
"deps": attr.label_list(
mandatory = True,
allow_empty = False,
providers = ["proto"],
providers = [ProtoInfo],
),
"plugin": attr.label(
executable = True,

@ -1366,6 +1366,7 @@ filegroups:
- include/grpcpp/channel_impl.h
- include/grpcpp/client_context.h
- include/grpcpp/completion_queue.h
- include/grpcpp/completion_queue_impl.h
- include/grpcpp/create_channel.h
- include/grpcpp/create_channel_impl.h
- include/grpcpp/create_channel_posix.h

@ -0,0 +1,65 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
filegroup(
name = "_credentials_files",
testonly = 1,
srcs = [
"credentials/localhost.key",
"credentials/localhost.crt",
"credentials/root.crt",
],
)
py_library(
name = "_credentials",
testonly = 1,
srcs = ["_credentials.py"],
data = [":_credentials_files"],
)
py_binary(
name = "customized_auth_client",
testonly = 1,
srcs = ["customized_auth_client.py"],
deps = [
":_credentials",
"//src/python/grpcio/grpc:grpcio",
"//examples:py_helloworld",
],
)
py_binary(
name = "customized_auth_server",
testonly = 1,
srcs = ["customized_auth_server.py"],
deps = [
":_credentials",
"//src/python/grpcio/grpc:grpcio",
"//examples:py_helloworld",
],
)
py_test(
name = "_auth_example_test",
srcs = ["test/_auth_example_test.py"],
deps = [
"//src/python/grpcio/grpc:grpcio",
"//examples:py_helloworld",
":customized_auth_client",
":customized_auth_server",
":_credentials",
],
)

@ -0,0 +1,112 @@
# Authentication Extension Example in gRPC Python
## Check Our Guide First
For most common usage of authentication in gRPC Python, please see our
[Authentication](https://grpc.io/docs/guides/auth/) guide's Python section. The
Guide includes following scenarios:
1. Server SSL credential setup
2. Client SSL credential setup
3. Authenticate with Google using a JWT
4. Authenticate with Google using an Oauth2 token
Also, the guide talks about gRPC specific credential types.
### Channel credentials
Channel credentials are attached to a `Channel` object, the most common use case
are SSL credentials.
### Call credentials
Call credentials are attached to a `Call` object (corresponding to an RPC).
Under the hood, the call credentials is a function that takes in information of
the RPC and modify metadata through callback.
## About This Example
This example focuses on extending gRPC authentication mechanism:
1) Customize authentication plugin;
2) Composite client side credentials;
3) Validation through interceptor on server side.
## AuthMetadataPlugin: Manipulate metadata for each call
Unlike TLS/SSL based authentication, the authentication extension in gRPC Python
lives at a much higher level of networking. It relies on the transmission of
metadata (HTTP Header) between client and server, instead of alternating the
transport protocol.
gRPC Python provides a way to intercept an RPC and append authentication related
metadata through
[`AuthMetadataPlugin`](https://grpc.github.io/grpc/python/grpc.html#grpc.AuthMetadataPlugin).
Those in need of a custom authentication method may simply provide a concrete
implementation of the following interface:
```Python
class AuthMetadataPlugin:
"""A specification for custom authentication."""
def __call__(self, context, callback):
"""Implements authentication by passing metadata to a callback.
Implementations of this method must not block.
Args:
context: An AuthMetadataContext providing information on the RPC that
the plugin is being called to authenticate.
callback: An AuthMetadataPluginCallback to be invoked either
synchronously or asynchronously.
"""
```
Then pass the instance of the concrete implementation to
`grpc.metadata_call_credentials` function to be converted into a
`CallCredentials` object. Please NOTE that it is possible to pass a Python
function object directly, but we recommend to inherit from the base class to
ensure implementation correctness.
```Python
def metadata_call_credentials(metadata_plugin, name=None):
"""Construct CallCredentials from an AuthMetadataPlugin.
Args:
metadata_plugin: An AuthMetadataPlugin to use for authentication.
name: An optional name for the plugin.
Returns:
A CallCredentials.
"""
```
The `CallCredentials` object can be passed directly into an RPC like:
```Python
call_credentials = grpc.metadata_call_credentials(my_foo_plugin)
stub.FooRpc(request, credentials=call_credentials)
```
Or you can use `ChannelCredentials` and `CallCredentials` at the same time by
combining them:
```Python
channel_credentials = ...
call_credentials = ...
composite_credentials = grpc.composite_channel_credentials(
channel_credential,
call_credentials)
channel = grpc.secure_channel(server_address, composite_credentials)
```
It is also possible to apply multiple `CallCredentials` to a single RPC:
```Python
call_credentials_foo = ...
call_credentials_bar = ...
call_credentials = grpc.composite_call_credentials(
call_credentials_foo,
call_credentials_bar)
stub.FooRpc(request, credentials=call_credentials)
```

@ -0,0 +1,31 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Loading SSL credentials for gRPC Python authentication example."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
def _load_credential_from_file(filepath):
real_path = os.path.join(os.path.dirname(__file__), filepath)
with open(real_path, 'rb') as f:
return f.read()
SERVER_CERTIFICATE = _load_credential_from_file('credentials/localhost.crt')
SERVER_CERTIFICATE_KEY = _load_credential_from_file('credentials/localhost.key')
ROOT_CERTIFICATE = _load_credential_from_file('credentials/root.crt')

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDFjCCAf4CCQCzrLIhrWa55zANBgkqhkiG9w0BAQsFADBCMQswCQYDVQQGEwJV
UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGR29vZ2xlMQ0wCwYDVQQL
DARnUlBDMCAXDTE5MDYyNDIyMjIzM1oYDzIxMTkwNTMxMjIyMjMzWjBWMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEPMA0GA1UECgwGR29vZ2xlMQ0w
CwYDVQQLDARnUlBDMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCtCW0TjugnIUu8BEVIYvdMP+/2GENQDjZhZ8eKR5C6
toDGbgjsDtt/GxISAg4cg70fIvy0XolnGPZodvfHDM4lJ7yHBOdZD8TXQoE6okR7
HZuLUJ20M0pXgWqtRewKRUjuYsSDXBnzLiZw1dcv9nGpo+Bqa8NonpiGRRpEkshF
D6T9KU9Ts/x+wMQBIra2Gj0UMh79jPhUuxcYAQA0JQGivnOtdwuPiumpnUT8j8h6
tWg5l01EsCZWJecCF85KnGpJEVYPyPqBqGsy0nGS9plGotOWF87+jyUQt+KD63xA
aBmTro86mKDDKEK4JvzjVeMGz2UbVcLPiiZnErTFaiXJAgMBAAEwDQYJKoZIhvcN
AQELBQADggEBAKsDgOPCWp5WCy17vJbRlgfgk05sVNIHZtzrmdswjBmvSg8MUpep
XqcPNUpsljAXsf9UM5IFEMRdilUsFGWvHjBEtNAW8WUK9UV18WRuU//0w1Mp5HAN
xUEKb4BoyZr65vlCnTR+AR5c9FfPvLibhr5qHs2RA8Y3GyLOcGqBWed87jhdQLCc
P1bxB+96le5JeXq0tw215lxonI2/3ZYVK4/ok9gwXrQoWm8YieJqitk/ZQ4S17/4
pynHtDfdxLn23EXeGx+UTxJGfpRmhEZdJ+MN7QGYoomzx5qS5XoYKxRNrDlirJpr
OqXIn8E1it+6d5gOZfuHawcNGhRLplE/pfA=
-----END CERTIFICATE-----

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEArQltE47oJyFLvARFSGL3TD/v9hhDUA42YWfHikeQuraAxm4I
7A7bfxsSEgIOHIO9HyL8tF6JZxj2aHb3xwzOJSe8hwTnWQ/E10KBOqJEex2bi1Cd
tDNKV4FqrUXsCkVI7mLEg1wZ8y4mcNXXL/ZxqaPgamvDaJ6YhkUaRJLIRQ+k/SlP
U7P8fsDEASK2tho9FDIe/Yz4VLsXGAEANCUBor5zrXcLj4rpqZ1E/I/IerVoOZdN
RLAmViXnAhfOSpxqSRFWD8j6gahrMtJxkvaZRqLTlhfO/o8lELfig+t8QGgZk66P
OpigwyhCuCb841XjBs9lG1XCz4omZxK0xWolyQIDAQABAoIBADeq/Kh6JT3RfGf0
h8WN8TlaqHxnueAbcmtL0+oss+cdp7gu1jf7X6o4r0uT1a5ew40s2Fe+wj2kzkE1
ZOlouTlC22gkr7j7Vbxa7PBMG/Pvxoa/XL0IczZLsGImSJXVTG1E4SvRiZeulTdf
1GbdxhtpWV1jZe5Wd4Na3+SHxF5S7m3PrHiZlYdz1ND+8XZs1NlL9+ej72qSFul9
t/QjMWJ9pky/Wad5abnRLRyOsg+BsgnXbkUy2rD89ZxFMLda9pzXo3TPyAlBHonr
mkEsE4eRMWMpjBM79JbeyDdHn/cs/LjAZrzeDf7ugXr2CHQpKaM5O0PsNHezJII9
L5kCfzECgYEA4M/rz1UP1/BJoSqigUlSs0tPAg8a5UlkVsh6Osuq72IPNo8qg/Fw
oV/IiIS+q+obRcFj1Od3PGdTpCJwW5dzd2fXBQGmGdj0HucnCrs13RtBh91JiF5i
y/YYI9KfgOG2ZT9gG68T0gTs6jRrS3Qd83npqjrkJqMOd7s00MK9tUcCgYEAxQq7
T541oCYHSBRIIb0IrR25krZy9caxzCqPDwOcuuhaCqCiaq+ATvOWlSfgecm4eH0K
PCH0xlWxG0auPEwm4pA8+/WR/XJwscPZMuoht1EoKy1his4eKx/s7hHNeO6KOF0V
Y/zqIiuZnEwUoKbn7EqqNFSTT65PJKyGsICJFG8CgYAfaw9yl1myfQNdQb8aQGwN
YJ33FLNWje427qeeZe5KrDKiFloDvI9YDjHRWnPnRL1w/zj7fSm9yFb5HlMDieP6
MQnsyjEzdY2QcA+VwVoiv3dmDHgFVeOKy6bOAtaFxYWfGr9MvygO9t9BT/gawGyb
JVORlc9i0vDnrMMR1dV7awKBgBpTWLtGc/u1mPt0Wj7HtsUKV6TWY32a0l5owTxM
S0BdksogtBJ06DukJ9Y9wawD23WdnyRxlPZ6tHLkeprrwbY7dypioOKvy4a0l+xJ
g7+uRCOgqIuXBkjUtx8HmeAyXp0xMo5tWArAsIFFWOwt4IadYygitJvMuh44PraO
NcJZAoGADEiV0dheXUCVr8DrtSom8DQMj92/G/FIYjXL8OUhh0+F+YlYP0+F8PEU
yYIWEqL/S5tVKYshimUXQa537JcRKsTVJBG/ZKD2kuqgOc72zQy3oplimXeJDCXY
h2eAQ0u8GN6tN9C4t8Kp4a3y6FGsxgu+UTxdnL3YQ+yHAVhtCzo=
-----END RSA PRIVATE KEY-----

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDWTCCAkGgAwIBAgIJAPOConZMwykwMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMQ8wDQYDVQQKDAZHb29nbGUxDTAL
BgNVBAsMBGdSUEMwIBcNMTkwNjI0MjIyMDA3WhgPMjExOTA1MzEyMjIwMDdaMEIx
CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMQ8wDQYDVQQKDAZHb29n
bGUxDTALBgNVBAsMBGdSUEMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCwqei3TfyLidnQNDJ2lierMYo229K92DuORni7nSjJQ59Jc3dNMsmqGQJjCD8o
6mTlKM/oCbs27Wpx+OxcOLvT95j2kiDGca1fCvaMdguIod09SWiyMpv/hp0trLv7
NJIKHznath6rHYX2Ii3fZ1yCPzyQbEPSAA+GNpoNm1v1ZWmWKke9v7vLlS3inNlW
Mt9jepK7DrtbNZnVDjeItnppBSbVYRMxIyNHkepFbqXx5TpkCvl4M4XQZw9bfSxQ
i3WZ3q+T1Tw//OUdPNc+OfMhu0MA0QoMwikskP0NaIC3dbJZ5Ogx0RcnaB4E+9C6
O/znUEh3WuKVl5HXBF+UwWoFAgMBAAGjUDBOMB0GA1UdDgQWBBRm3JIgzgK4G97J
fbMGatWMZc7V3jAfBgNVHSMEGDAWgBRm3JIgzgK4G97JfbMGatWMZc7V3jAMBgNV
HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCNiV8x41if094ry2srS0YucpiN
3rTPk08FOLsENTMYai524TGXJti1P6ofGr5KXCL0uxTByHE3fEiMMud2TIY5iHQo
Y4mzDTTcb+Q7yKHwYZMlcp6nO8W+NeY5t+S0JPHhb8deKWepcN2UpXBUYQLw7AiE
l96T9Gi+vC9h/XE5IVwHFQXTxf5UYzXtW1nfapvrOONg/ms41dgmrRKIi+knWfiJ
FdHpHX2sfDAoJtnpEISX+nxRGNVTLY64utXWm4yxaZJshvy2s8zWJgRg7rtwAhTT
Np9E9MnihXLEmDI4Co9XlLPJyZFmqImsbmVuKFeQOCiLAoPJaMI2lbi7fiTo
-----END CERTIFICATE-----

@ -0,0 +1,105 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Client of the Python example of customizing authentication mechanism."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import contextlib
import logging
import grpc
from examples import helloworld_pb2
from examples import helloworld_pb2_grpc
from examples.python.auth import _credentials
_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.INFO)
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
_SERVER_ADDR_TEMPLATE = 'localhost:%d'
_SIGNATURE_HEADER_KEY = 'x-signature'
class AuthGateway(grpc.AuthMetadataPlugin):
def __call__(self, context, callback):
"""Implements authentication by passing metadata to a callback.
Implementations of this method must not block.
Args:
context: An AuthMetadataContext providing information on the RPC that
the plugin is being called to authenticate.
callback: An AuthMetadataPluginCallback to be invoked either
synchronously or asynchronously.
"""
# Example AuthMetadataContext object:
# AuthMetadataContext(
# service_url=u'https://localhost:50051/helloworld.Greeter',
# method_name=u'SayHello')
signature = context.method_name[::-1]
callback(((_SIGNATURE_HEADER_KEY, signature),), None)
@contextlib.contextmanager
def create_client_channel(addr):
# Call credential object will be invoked for every single RPC
call_credentials = grpc.metadata_call_credentials(
AuthGateway(), name='auth gateway')
# Channel credential will be valid for the entire channel
channel_credential = grpc.ssl_channel_credentials(
_credentials.ROOT_CERTIFICATE)
# Combining channel credentials and call credentials together
composite_credentials = grpc.composite_channel_credentials(
channel_credential,
call_credentials,
)
channel = grpc.secure_channel(addr, composite_credentials)
yield channel
def send_rpc(channel):
stub = helloworld_pb2_grpc.GreeterStub(channel)
request = helloworld_pb2.HelloRequest(name='you')
try:
response = stub.SayHello(request)
except grpc.RpcError as rpc_error:
_LOGGER.error('Received error: %s', rpc_error)
return rpc_error
else:
_LOGGER.info('Received message: %s', response)
return response
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--port',
nargs='?',
type=int,
default=50051,
help='the address of server')
args = parser.parse_args()
with create_client_channel(_SERVER_ADDR_TEMPLATE % args.port) as channel:
send_rpc(channel)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
main()

@ -0,0 +1,110 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Server of the Python example of customizing authentication mechanism."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import contextlib
import logging
import time
from concurrent import futures
import grpc
from examples import helloworld_pb2
from examples import helloworld_pb2_grpc
from examples.python.auth import _credentials
_LOGGER = logging.getLogger(__name__)
_LOGGER.setLevel(logging.INFO)
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
_LISTEN_ADDRESS_TEMPLATE = 'localhost:%d'
_SIGNATURE_HEADER_KEY = 'x-signature'
class SignatureValidationInterceptor(grpc.ServerInterceptor):
def __init__(self):
def abort(ignored_request, context):
context.abort(grpc.StatusCode.UNAUTHENTICATED, 'Invalid signature')
self._abortion = grpc.unary_unary_rpc_method_handler(abort)
def intercept_service(self, continuation, handler_call_details):
# Example HandlerCallDetails object:
# _HandlerCallDetails(
# method=u'/helloworld.Greeter/SayHello',
# invocation_metadata=...)
method_name = handler_call_details.method.split('/')[-1]
expected_metadata = (_SIGNATURE_HEADER_KEY, method_name[::-1])
if expected_metadata in handler_call_details.invocation_metadata:
return continuation(handler_call_details)
else:
return self._abortion
class SimpleGreeter(helloworld_pb2_grpc.GreeterServicer):
def SayHello(self, request, unused_context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
@contextlib.contextmanager
def run_server(port):
# Bind interceptor to server
server = grpc.server(
futures.ThreadPoolExecutor(),
interceptors=(SignatureValidationInterceptor(),))
helloworld_pb2_grpc.add_GreeterServicer_to_server(SimpleGreeter(), server)
# Loading credentials
server_credentials = grpc.ssl_server_credentials(((
_credentials.SERVER_CERTIFICATE_KEY,
_credentials.SERVER_CERTIFICATE,
),))
# Pass down credentials
port = server.add_secure_port(_LISTEN_ADDRESS_TEMPLATE % port,
server_credentials)
server.start()
try:
yield port
finally:
server.stop(0)
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'--port', nargs='?', type=int, default=50051, help='the listening port')
args = parser.parse_args()
with run_server(args.port) as port:
logging.info('Server is listening at port :%d', port)
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
pass
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
main()

@ -0,0 +1,56 @@
# Copyright 2019 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test for gRPC Python authentication example."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import unittest
import grpc
from examples.python.auth import _credentials
from examples.python.auth import customized_auth_client
from examples.python.auth import customized_auth_server
_SERVER_ADDR_TEMPLATE = 'localhost:%d'
class AuthExampleTest(unittest.TestCase):
def test_successful_call(self):
with customized_auth_server.run_server(0) as port:
with customized_auth_client.create_client_channel(
_SERVER_ADDR_TEMPLATE % port) as channel:
customized_auth_client.send_rpc(channel)
# No unhandled exception raised, test passed!
def test_no_channel_credential(self):
with customized_auth_server.run_server(0) as port:
with grpc.insecure_channel(_SERVER_ADDR_TEMPLATE % port) as channel:
resp = customized_auth_client.send_rpc(channel)
self.assertEqual(resp.code(), grpc.StatusCode.UNAVAILABLE)
def test_no_call_credential(self):
with customized_auth_server.run_server(0) as port:
channel_credential = grpc.ssl_channel_credentials(
_credentials.ROOT_CERTIFICATE)
with grpc.secure_channel(_SERVER_ADDR_TEMPLATE % port,
channel_credential) as channel:
resp = customized_auth_client.send_rpc(channel)
self.assertEqual(resp.code(), grpc.StatusCode.UNAUTHENTICATED)
if __name__ == '__main__':
unittest.main(verbosity=2)

@ -85,6 +85,7 @@ Pod::Spec.new do |s|
'include/grpcpp/channel_impl.h',
'include/grpcpp/client_context.h',
'include/grpcpp/completion_queue.h',
'include/grpcpp/completion_queue_impl.h',
'include/grpcpp/create_channel.h',
'include/grpcpp/create_channel_impl.h',
'include/grpcpp/create_channel_posix.h',

@ -111,6 +111,7 @@ EXPORTS
grpc_google_refresh_token_credentials_create
grpc_access_token_credentials_create
grpc_google_iam_credentials_create
grpc_sts_credentials_create
grpc_metadata_credentials_create_from_plugin
grpc_secure_channel_create
grpc_server_credentials_release

@ -328,6 +328,31 @@ GRPCAPI grpc_call_credentials* grpc_google_iam_credentials_create(
const char* authorization_token, const char* authority_selector,
void* reserved);
/** Options for creating STS Oauth Token Exchange credentials following the IETF
draft https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16.
Optional fields may be set to NULL. It is the responsibility of the caller to
ensure that the subject and actor tokens are refreshed on disk at the
specified paths. This API is used for experimental purposes for now and may
change in the future. */
typedef struct {
const char* sts_endpoint_url; /* Required. */
const char* resource; /* Optional. */
const char* audience; /* Optional. */
const char* scope; /* Optional. */
const char* requested_token_type; /* Optional. */
const char* subject_token_path; /* Required. */
const char* subject_token_type; /* Required. */
const char* actor_token_path; /* Optional. */
const char* actor_token_type; /* Optional. */
} grpc_sts_credentials_options;
/** Creates an STS credentials following the STS Token Exchanged specifed in the
IETF draft https://tools.ietf.org/html/draft-ietf-oauth-token-exchange-16.
This API is used for experimental purposes for now and may change in the
future. */
GRPCAPI grpc_call_credentials* grpc_sts_credentials_create(
const grpc_sts_credentials_options* options, void* reserved);
/** Callback function to be called by the metadata credentials plugin
implementation when the metadata is ready.
- user_data is the opaque pointer that was passed in the get_metadata method

@ -0,0 +1,24 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPCPP_COMPLETION_QUEUE_IMPL_H
#define GRPCPP_COMPLETION_QUEUE_IMPL_H
#include <grpcpp/impl/codegen/completion_queue_impl.h>
#endif // GRPCPP_COMPLETION_QUEUE_IMPL_H

@ -21,6 +21,7 @@
#include <functional>
#include <grpcpp/client_context.h>
#include <grpcpp/support/async_stream.h>
#include <grpcpp/support/async_unary_call.h>
#include <grpcpp/support/byte_buffer.h>

@ -33,7 +33,7 @@ typedef ServerAsyncResponseWriter<ByteBuffer> GenericServerAsyncResponseWriter;
typedef ServerAsyncReader<ByteBuffer, ByteBuffer> GenericServerAsyncReader;
typedef ServerAsyncWriter<ByteBuffer> GenericServerAsyncWriter;
class GenericServerContext final : public ServerContext {
class GenericServerContext final : public ::grpc_impl::ServerContext {
public:
const grpc::string& method() const { return method_; }
const grpc::string& host() const { return host_; }
@ -99,7 +99,7 @@ class ServerGenericBidiReactor
virtual void OnStarted(GenericServerContext* context) {}
private:
void OnStarted(ServerContext* ctx) final {
void OnStarted(::grpc_impl::ServerContext* ctx) final {
OnStarted(static_cast<GenericServerContext*>(ctx));
}
};

@ -22,7 +22,7 @@
#include <grpcpp/impl/codegen/call.h>
#include <grpcpp/impl/codegen/channel_interface.h>
#include <grpcpp/impl/codegen/core_codegen_interface.h>
#include <grpcpp/impl/codegen/server_context.h>
#include <grpcpp/impl/codegen/server_context_impl.h>
#include <grpcpp/impl/codegen/service_type.h>
#include <grpcpp/impl/codegen/status.h>
@ -181,8 +181,8 @@ class ClientAsyncReaderFactory {
static ClientAsyncReader<R>* Create(ChannelInterface* channel,
CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, const W& request,
bool start, void* tag) {
::grpc_impl::ClientContext* context,
const W& request, bool start, void* tag) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncReader<R>)))
@ -260,8 +260,9 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
private:
friend class internal::ClientAsyncReaderFactory<R>;
template <class W>
ClientAsyncReader(::grpc::internal::Call call, ClientContext* context,
const W& request, bool start, void* tag)
ClientAsyncReader(::grpc::internal::Call call,
::grpc_impl::ClientContext* context, const W& request,
bool start, void* tag)
: context_(context), call_(call), started_(start) {
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
@ -280,7 +281,7 @@ class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
call_.PerformOps(&init_ops_);
}
ClientContext* context_;
::grpc_impl::ClientContext* context_;
::grpc::internal::Call call_;
bool started_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
@ -329,8 +330,8 @@ class ClientAsyncWriterFactory {
static ClientAsyncWriter<W>* Create(ChannelInterface* channel,
CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, R* response,
bool start, void* tag) {
::grpc_impl::ClientContext* context,
R* response, bool start, void* tag) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncWriter<W>)))
@ -426,8 +427,9 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
private:
friend class internal::ClientAsyncWriterFactory<W>;
template <class R>
ClientAsyncWriter(::grpc::internal::Call call, ClientContext* context,
R* response, bool start, void* tag)
ClientAsyncWriter(::grpc::internal::Call call,
::grpc_impl::ClientContext* context, R* response,
bool start, void* tag)
: context_(context), call_(call), started_(start) {
finish_ops_.RecvMessage(response);
finish_ops_.AllowNoMessage();
@ -449,7 +451,7 @@ class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
}
}
ClientContext* context_;
::grpc_impl::ClientContext* context_;
::grpc::internal::Call call_;
bool started_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
@ -493,8 +495,8 @@ class ClientAsyncReaderWriterFactory {
/// used to send to the server when starting the call.
static ClientAsyncReaderWriter<W, R>* Create(
ChannelInterface* channel, CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method, ClientContext* context,
bool start, void* tag) {
const ::grpc::internal::RpcMethod& method,
::grpc_impl::ClientContext* context, bool start, void* tag) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
@ -599,8 +601,9 @@ class ClientAsyncReaderWriter final
private:
friend class internal::ClientAsyncReaderWriterFactory<W, R>;
ClientAsyncReaderWriter(::grpc::internal::Call call, ClientContext* context,
bool start, void* tag)
ClientAsyncReaderWriter(::grpc::internal::Call call,
::grpc_impl::ClientContext* context, bool start,
void* tag)
: context_(context), call_(call), started_(start) {
if (start) {
StartCallInternal(tag);
@ -620,7 +623,7 @@ class ClientAsyncReaderWriter final
}
}
ClientContext* context_;
::grpc_impl::ClientContext* context_;
::grpc::internal::Call call_;
bool started_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
@ -696,7 +699,7 @@ class ServerAsyncReaderInterface
template <class W, class R>
class ServerAsyncReader final : public ServerAsyncReaderInterface<W, R> {
public:
explicit ServerAsyncReader(ServerContext* ctx)
explicit ServerAsyncReader(::grpc_impl::ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
/// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
@ -782,7 +785,7 @@ class ServerAsyncReader final : public ServerAsyncReaderInterface<W, R> {
void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
::grpc::internal::Call call_;
ServerContext* ctx_;
::grpc_impl::ServerContext* ctx_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
meta_ops_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_;
@ -843,7 +846,7 @@ class ServerAsyncWriterInterface
template <class W>
class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
public:
explicit ServerAsyncWriter(ServerContext* ctx)
explicit ServerAsyncWriter(::grpc_impl::ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
/// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
@ -940,7 +943,7 @@ class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
}
::grpc::internal::Call call_;
ServerContext* ctx_;
::grpc_impl::ServerContext* ctx_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
meta_ops_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
@ -1009,7 +1012,7 @@ template <class W, class R>
class ServerAsyncReaderWriter final
: public ServerAsyncReaderWriterInterface<W, R> {
public:
explicit ServerAsyncReaderWriter(ServerContext* ctx)
explicit ServerAsyncReaderWriter(::grpc_impl::ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
/// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
@ -1114,7 +1117,7 @@ class ServerAsyncReaderWriter final
}
::grpc::internal::Call call_;
ServerContext* ctx_;
::grpc_impl::ServerContext* ctx_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
meta_ops_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_;

@ -22,8 +22,8 @@
#include <assert.h>
#include <grpcpp/impl/codegen/call.h>
#include <grpcpp/impl/codegen/channel_interface.h>
#include <grpcpp/impl/codegen/client_context.h>
#include <grpcpp/impl/codegen/server_context.h>
#include <grpcpp/impl/codegen/client_context_impl.h>
#include <grpcpp/impl/codegen/server_context_impl.h>
#include <grpcpp/impl/codegen/service_type.h>
#include <grpcpp/impl/codegen/status.h>
@ -80,9 +80,9 @@ class ClientAsyncResponseReaderFactory {
/// used to send to the server when starting the call.
template <class W>
static ClientAsyncResponseReader<R>* Create(
ChannelInterface* channel, CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method, ClientContext* context,
const W& request, bool start) {
ChannelInterface* channel, ::grpc_impl::CompletionQueue* cq,
const ::grpc::internal::RpcMethod& method,
::grpc_impl::ClientContext* context, const W& request, bool start) {
::grpc::internal::Call call = channel->CreateCall(method, context, cq);
return new (g_core_codegen_interface->grpc_call_arena_alloc(
call.call(), sizeof(ClientAsyncResponseReader<R>)))
@ -156,13 +156,14 @@ class ClientAsyncResponseReader final
private:
friend class internal::ClientAsyncResponseReaderFactory<R>;
ClientContext* const context_;
::grpc_impl::ClientContext* const context_;
::grpc::internal::Call call_;
bool started_;
bool initial_metadata_read_ = false;
template <class W>
ClientAsyncResponseReader(::grpc::internal::Call call, ClientContext* context,
ClientAsyncResponseReader(::grpc::internal::Call call,
::grpc_impl::ClientContext* context,
const W& request, bool start)
: context_(context), call_(call), started_(start) {
// Bind the metadata at time of StartCallInternal but set up the rest here
@ -199,7 +200,7 @@ template <class W>
class ServerAsyncResponseWriter final
: public internal::ServerAsyncStreamingInterface {
public:
explicit ServerAsyncResponseWriter(ServerContext* ctx)
explicit ServerAsyncResponseWriter(::grpc_impl::ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
/// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
@ -289,7 +290,7 @@ class ServerAsyncResponseWriter final
void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
::grpc::internal::Call call_;
ServerContext* ctx_;
::grpc_impl::ServerContext* ctx_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
meta_buf_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,

@ -31,7 +31,7 @@
#include <grpcpp/impl/codegen/call.h>
#include <grpcpp/impl/codegen/call_hook.h>
#include <grpcpp/impl/codegen/call_op_set_interface.h>
#include <grpcpp/impl/codegen/client_context.h>
#include <grpcpp/impl/codegen/client_context_impl.h>
#include <grpcpp/impl/codegen/completion_queue.h>
#include <grpcpp/impl/codegen/completion_queue_tag.h>
#include <grpcpp/impl/codegen/config.h>
@ -697,7 +697,7 @@ class CallOpRecvInitialMetadata {
public:
CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
void RecvInitialMetadata(ClientContext* context) {
void RecvInitialMetadata(::grpc_impl::ClientContext* context) {
context->initial_metadata_received_ = true;
metadata_map_ = &context->recv_initial_metadata_;
}
@ -746,7 +746,7 @@ class CallOpClientRecvStatus {
CallOpClientRecvStatus()
: recv_status_(nullptr), debug_error_string_(nullptr) {}
void ClientRecvStatus(ClientContext* context, Status* status) {
void ClientRecvStatus(::grpc_impl::ClientContext* context, Status* status) {
client_context_ = context;
metadata_map_ = &client_context_->trailing_metadata_;
recv_status_ = status;
@ -807,7 +807,7 @@ class CallOpClientRecvStatus {
private:
bool hijacked_ = false;
ClientContext* client_context_;
::grpc_impl::ClientContext* client_context_;
MetadataMap* metadata_map_;
Status* recv_status_;
const char* debug_error_string_;

@ -44,8 +44,8 @@ class RpcMethod;
/// TODO(vjpai): Combine as much as possible with the blocking unary call code
template <class InputMessage, class OutputMessage>
void CallbackUnaryCall(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, const InputMessage* request,
OutputMessage* result,
::grpc_impl::ClientContext* context,
const InputMessage* request, OutputMessage* result,
std::function<void(Status)> on_completion) {
CallbackUnaryCallImpl<InputMessage, OutputMessage> x(
channel, method, context, request, result, on_completion);
@ -55,8 +55,8 @@ template <class InputMessage, class OutputMessage>
class CallbackUnaryCallImpl {
public:
CallbackUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, const InputMessage* request,
OutputMessage* result,
::grpc_impl::ClientContext* context,
const InputMessage* request, OutputMessage* result,
std::function<void(Status)> on_completion) {
CompletionQueue* cq = channel->CallbackCQ();
GPR_CODEGEN_ASSERT(cq != nullptr);
@ -550,7 +550,7 @@ class ClientCallbackReaderWriterImpl
friend class ClientCallbackReaderWriterFactory<Request, Response>;
ClientCallbackReaderWriterImpl(
Call call, ClientContext* context,
Call call, ::grpc_impl::ClientContext* context,
::grpc::experimental::ClientBidiReactor<Request, Response>* reactor)
: context_(context),
call_(call),
@ -559,7 +559,7 @@ class ClientCallbackReaderWriterImpl
this->BindReactor(reactor);
}
ClientContext* const context_;
::grpc_impl::ClientContext* const context_;
Call call_;
::grpc::experimental::ClientBidiReactor<Request, Response>* const reactor_;
@ -594,7 +594,7 @@ class ClientCallbackReaderWriterFactory {
public:
static void Create(
ChannelInterface* channel, const ::grpc::internal::RpcMethod& method,
ClientContext* context,
::grpc_impl::ClientContext* context,
::grpc::experimental::ClientBidiReactor<Request, Response>* reactor) {
Call call = channel->CreateCall(method, context, channel->CallbackCQ());
@ -692,7 +692,7 @@ class ClientCallbackReaderImpl
template <class Request>
ClientCallbackReaderImpl(
Call call, ClientContext* context, Request* request,
Call call, ::grpc_impl::ClientContext* context, Request* request,
::grpc::experimental::ClientReadReactor<Response>* reactor)
: context_(context), call_(call), reactor_(reactor) {
this->BindReactor(reactor);
@ -701,7 +701,7 @@ class ClientCallbackReaderImpl
start_ops_.ClientSendClose();
}
ClientContext* const context_;
::grpc_impl::ClientContext* const context_;
Call call_;
::grpc::experimental::ClientReadReactor<Response>* const reactor_;
@ -729,7 +729,7 @@ class ClientCallbackReaderFactory {
template <class Request>
static void Create(
ChannelInterface* channel, const ::grpc::internal::RpcMethod& method,
ClientContext* context, const Request* request,
::grpc_impl::ClientContext* context, const Request* request,
::grpc::experimental::ClientReadReactor<Response>* reactor) {
Call call = channel->CreateCall(method, context, channel->CallbackCQ());
@ -866,7 +866,7 @@ class ClientCallbackWriterImpl
template <class Response>
ClientCallbackWriterImpl(
Call call, ClientContext* context, Response* response,
Call call, ::grpc_impl::ClientContext* context, Response* response,
::grpc::experimental::ClientWriteReactor<Request>* reactor)
: context_(context),
call_(call),
@ -877,7 +877,7 @@ class ClientCallbackWriterImpl
finish_ops_.AllowNoMessage();
}
ClientContext* const context_;
::grpc_impl::ClientContext* const context_;
Call call_;
::grpc::experimental::ClientWriteReactor<Request>* const reactor_;
@ -909,7 +909,7 @@ class ClientCallbackWriterFactory {
template <class Response>
static void Create(
ChannelInterface* channel, const ::grpc::internal::RpcMethod& method,
ClientContext* context, Response* response,
::grpc_impl::ClientContext* context, Response* response,
::grpc::experimental::ClientWriteReactor<Request>* reactor) {
Call call = channel->CreateCall(method, context, channel->CallbackCQ());
@ -976,8 +976,8 @@ class ClientCallbackUnaryImpl final
friend class ClientCallbackUnaryFactory;
template <class Request, class Response>
ClientCallbackUnaryImpl(Call call, ClientContext* context, Request* request,
Response* response,
ClientCallbackUnaryImpl(Call call, ::grpc_impl::ClientContext* context,
Request* request, Response* response,
::grpc::experimental::ClientUnaryReactor* reactor)
: context_(context), call_(call), reactor_(reactor) {
this->BindReactor(reactor);
@ -988,7 +988,7 @@ class ClientCallbackUnaryImpl final
finish_ops_.AllowNoMessage();
}
ClientContext* const context_;
::grpc_impl::ClientContext* const context_;
Call call_;
::grpc::experimental::ClientUnaryReactor* const reactor_;
@ -1011,8 +1011,8 @@ class ClientCallbackUnaryFactory {
template <class Request, class Response>
static void Create(ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, const Request* request,
Response* response,
::grpc_impl::ClientContext* context,
const Request* request, Response* response,
::grpc::experimental::ClientUnaryReactor* reactor) {
Call call = channel->CreateCall(method, context, channel->CallbackCQ());

@ -49,7 +49,7 @@ class InterceptedChannel : public ChannelInterface {
InterceptedChannel(ChannelInterface* channel, size_t pos)
: channel_(channel), interceptor_pos_(pos) {}
Call CreateCall(const RpcMethod& method, ClientContext* context,
Call CreateCall(const RpcMethod& method, ::grpc_impl::ClientContext* context,
::grpc_impl::CompletionQueue* cq) override {
return channel_->CreateCallInternal(method, context, cq, interceptor_pos_);
}

@ -52,10 +52,11 @@ Status CatchingFunctionHandler(Callable&& handler) {
template <class ServiceType, class RequestType, class ResponseType>
class RpcMethodHandler : public MethodHandler {
public:
RpcMethodHandler(std::function<Status(ServiceType*, ServerContext*,
const RequestType*, ResponseType*)>
func,
ServiceType* service)
RpcMethodHandler(
std::function<Status(ServiceType*, ::grpc_impl::ServerContext*,
const RequestType*, ResponseType*)>
func,
ServiceType* service)
: func_(func), service_(service) {}
void RunHandler(const HandlerParameter& param) final {
@ -103,8 +104,8 @@ class RpcMethodHandler : public MethodHandler {
private:
/// Application provided rpc handler function.
std::function<Status(ServiceType*, ServerContext*, const RequestType*,
ResponseType*)>
std::function<Status(ServiceType*, ::grpc_impl::ServerContext*,
const RequestType*, ResponseType*)>
func_;
// The class the above handler function lives in.
ServiceType* service_;
@ -115,7 +116,7 @@ template <class ServiceType, class RequestType, class ResponseType>
class ClientStreamingHandler : public MethodHandler {
public:
ClientStreamingHandler(
std::function<Status(ServiceType*, ServerContext*,
std::function<Status(ServiceType*, ::grpc_impl::ServerContext*,
ServerReader<RequestType>*, ResponseType*)>
func,
ServiceType* service)
@ -147,8 +148,8 @@ class ClientStreamingHandler : public MethodHandler {
}
private:
std::function<Status(ServiceType*, ServerContext*, ServerReader<RequestType>*,
ResponseType*)>
std::function<Status(ServiceType*, ::grpc_impl::ServerContext*,
ServerReader<RequestType>*, ResponseType*)>
func_;
ServiceType* service_;
};
@ -158,8 +159,8 @@ template <class ServiceType, class RequestType, class ResponseType>
class ServerStreamingHandler : public MethodHandler {
public:
ServerStreamingHandler(
std::function<Status(ServiceType*, ServerContext*, const RequestType*,
ServerWriter<ResponseType>*)>
std::function<Status(ServiceType*, ::grpc_impl::ServerContext*,
const RequestType*, ServerWriter<ResponseType>*)>
func,
ServiceType* service)
: func_(func), service_(service) {}
@ -207,8 +208,8 @@ class ServerStreamingHandler : public MethodHandler {
}
private:
std::function<Status(ServiceType*, ServerContext*, const RequestType*,
ServerWriter<ResponseType>*)>
std::function<Status(ServiceType*, ::grpc_impl::ServerContext*,
const RequestType*, ServerWriter<ResponseType>*)>
func_;
ServiceType* service_;
};
@ -224,7 +225,7 @@ template <class Streamer, bool WriteNeeded>
class TemplatedBidiStreamingHandler : public MethodHandler {
public:
TemplatedBidiStreamingHandler(
std::function<Status(ServerContext*, Streamer*)> func)
std::function<Status(::grpc_impl::ServerContext*, Streamer*)> func)
: func_(func), write_needed_(WriteNeeded) {}
void RunHandler(const HandlerParameter& param) final {
@ -256,7 +257,7 @@ class TemplatedBidiStreamingHandler : public MethodHandler {
}
private:
std::function<Status(ServerContext*, Streamer*)> func_;
std::function<Status(::grpc_impl::ServerContext*, Streamer*)> func_;
const bool write_needed_;
};
@ -266,7 +267,7 @@ class BidiStreamingHandler
ServerReaderWriter<ResponseType, RequestType>, false> {
public:
BidiStreamingHandler(
std::function<Status(ServiceType*, ServerContext*,
std::function<Status(ServiceType*, ::grpc_impl::ServerContext*,
ServerReaderWriter<ResponseType, RequestType>*)>
func,
ServiceType* service)
@ -281,7 +282,7 @@ class StreamedUnaryHandler
ServerUnaryStreamer<RequestType, ResponseType>, true> {
public:
explicit StreamedUnaryHandler(
std::function<Status(ServerContext*,
std::function<Status(::grpc_impl::ServerContext*,
ServerUnaryStreamer<RequestType, ResponseType>*)>
func)
: TemplatedBidiStreamingHandler<
@ -294,7 +295,7 @@ class SplitServerStreamingHandler
ServerSplitStreamer<RequestType, ResponseType>, false> {
public:
explicit SplitServerStreamingHandler(
std::function<Status(ServerContext*,
std::function<Status(::grpc_impl::ServerContext*,
ServerSplitStreamer<RequestType, ResponseType>*)>
func)
: TemplatedBidiStreamingHandler<
@ -307,7 +308,7 @@ template <StatusCode code>
class ErrorMethodHandler : public MethodHandler {
public:
template <class T>
static void FillOps(ServerContext* context, T* ops) {
static void FillOps(::grpc_impl::ServerContext* context, T* ops) {
Status status(code, "");
if (!context->sent_initial_metadata_) {
ops->SendInitialMetadata(&context->initial_metadata_,

@ -26,7 +26,7 @@
#include <grpcpp/impl/codegen/completion_queue_tag.h>
#include <grpcpp/impl/codegen/core_codegen_interface.h>
#include <grpcpp/impl/codegen/rpc_service_method.h>
#include <grpcpp/impl/codegen/server_context.h>
#include <grpcpp/impl/codegen/server_context_impl.h>
namespace grpc_impl {
@ -34,7 +34,6 @@ class Channel;
class CompletionQueue;
class ServerCompletionQueue;
class ServerCredentials;
class ServerContext;
} // namespace grpc_impl
namespace grpc {

@ -21,10 +21,10 @@
#include <grpcpp/impl/codegen/call.h>
#include <grpcpp/impl/codegen/channel_interface.h>
#include <grpcpp/impl/codegen/client_context.h>
#include <grpcpp/impl/codegen/client_context_impl.h>
#include <grpcpp/impl/codegen/completion_queue.h>
#include <grpcpp/impl/codegen/core_codegen_interface.h>
#include <grpcpp/impl/codegen/server_context.h>
#include <grpcpp/impl/codegen/server_context_impl.h>
#include <grpcpp/impl/codegen/service_type.h>
#include <grpcpp/impl/codegen/status.h>
@ -163,7 +163,8 @@ class ClientReaderFactory {
template <class W>
static ClientReader<R>* Create(ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, const W& request) {
::grpc_impl::ClientContext* context,
const W& request) {
return new ClientReader<R>(channel, method, context, request);
}
};
@ -230,8 +231,8 @@ class ClientReader final : public ClientReaderInterface<R> {
private:
friend class internal::ClientReaderFactory<R>;
ClientContext* context_;
CompletionQueue cq_;
::grpc_impl::ClientContext* context_;
::grpc_impl::CompletionQueue cq_;
::grpc::internal::Call call_;
/// Block to create a stream and write the initial metadata and \a request
@ -240,7 +241,7 @@ class ClientReader final : public ClientReaderInterface<R> {
template <class W>
ClientReader(::grpc::ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, const W& request)
::grpc_impl::ClientContext* context, const W& request)
: context_(context),
cq_(grpc_completion_queue_attributes{
GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
@ -281,7 +282,8 @@ class ClientWriterFactory {
template <class R>
static ClientWriter<W>* Create(::grpc::ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, R* response) {
::grpc_impl::ClientContext* context,
R* response) {
return new ClientWriter<W>(channel, method, context, response);
}
};
@ -374,7 +376,7 @@ class ClientWriter : public ClientWriterInterface<W> {
template <class R>
ClientWriter(ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context, R* response)
::grpc_impl::ClientContext* context, R* response)
: context_(context),
cq_(grpc_completion_queue_attributes{
GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
@ -393,12 +395,12 @@ class ClientWriter : public ClientWriterInterface<W> {
}
}
ClientContext* context_;
::grpc_impl::ClientContext* context_;
::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
::grpc::internal::CallOpGenericRecvMessage,
::grpc::internal::CallOpClientRecvStatus>
finish_ops_;
CompletionQueue cq_;
::grpc_impl::CompletionQueue cq_;
::grpc::internal::Call call_;
};
@ -431,7 +433,8 @@ class ClientReaderWriterFactory {
public:
static ClientReaderWriter<W, R>* Create(
::grpc::ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method, ClientContext* context) {
const ::grpc::internal::RpcMethod& method,
::grpc_impl::ClientContext* context) {
return new ClientReaderWriter<W, R>(channel, method, context);
}
};
@ -539,8 +542,8 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
private:
friend class internal::ClientReaderWriterFactory<W, R>;
ClientContext* context_;
CompletionQueue cq_;
::grpc_impl::ClientContext* context_;
::grpc_impl::CompletionQueue cq_;
::grpc::internal::Call call_;
/// Block to create a stream and write the initial metadata and \a request
@ -548,7 +551,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
/// used to send to the server when starting the call.
ClientReaderWriter(::grpc::ChannelInterface* channel,
const ::grpc::internal::RpcMethod& method,
ClientContext* context)
::grpc_impl::ClientContext* context)
: context_(context),
cq_(grpc_completion_queue_attributes{
GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
@ -607,12 +610,12 @@ class ServerReader final : public ServerReaderInterface<R> {
private:
internal::Call* const call_;
ServerContext* const ctx_;
::grpc_impl::ServerContext* const ctx_;
template <class ServiceType, class RequestType, class ResponseType>
friend class internal::ClientStreamingHandler;
ServerReader(internal::Call* call, ServerContext* ctx)
ServerReader(internal::Call* call, ::grpc_impl::ServerContext* ctx)
: call_(call), ctx_(ctx) {}
};
@ -681,12 +684,12 @@ class ServerWriter final : public ServerWriterInterface<W> {
private:
internal::Call* const call_;
ServerContext* const ctx_;
::grpc_impl::ServerContext* const ctx_;
template <class ServiceType, class RequestType, class ResponseType>
friend class internal::ServerStreamingHandler;
ServerWriter(internal::Call* call, ServerContext* ctx)
ServerWriter(internal::Call* call, ::grpc_impl::ServerContext* ctx)
: call_(call), ctx_(ctx) {}
};
@ -701,7 +704,7 @@ namespace internal {
template <class W, class R>
class ServerReaderWriterBody final {
public:
ServerReaderWriterBody(Call* call, ServerContext* ctx)
ServerReaderWriterBody(Call* call, ::grpc_impl::ServerContext* ctx)
: call_(call), ctx_(ctx) {}
void SendInitialMetadata() {
@ -759,7 +762,7 @@ class ServerReaderWriterBody final {
private:
Call* const call_;
ServerContext* const ctx_;
::grpc_impl::ServerContext* const ctx_;
};
} // namespace internal
@ -797,7 +800,7 @@ class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
friend class internal::TemplatedBidiStreamingHandler<ServerReaderWriter<W, R>,
false>;
ServerReaderWriter(internal::Call* call, ServerContext* ctx)
ServerReaderWriter(internal::Call* call, ::grpc_impl::ServerContext* ctx)
: body_(call, ctx) {}
};
@ -865,7 +868,7 @@ class ServerUnaryStreamer final
friend class internal::TemplatedBidiStreamingHandler<
ServerUnaryStreamer<RequestType, ResponseType>, true>;
ServerUnaryStreamer(internal::Call* call, ServerContext* ctx)
ServerUnaryStreamer(internal::Call* call, ::grpc_impl::ServerContext* ctx)
: body_(call, ctx), read_done_(false), write_done_(false) {}
};
@ -925,7 +928,7 @@ class ServerSplitStreamer final
friend class internal::TemplatedBidiStreamingHandler<
ServerSplitStreamer<RequestType, ResponseType>, false>;
ServerSplitStreamer(internal::Call* call, ServerContext* ctx)
ServerSplitStreamer(internal::Call* call, ::grpc_impl::ServerContext* ctx)
: body_(call, ctx), read_done_(false) {}
};

@ -21,11 +21,11 @@
#include <memory>
#include <grpcpp/support/channel_arguments.h>
#include <grpcpp/support/config.h>
namespace grpc_impl {
class ChannelArguments;
class ServerBuilder;
class ServerInitializer;
} // namespace grpc_impl
@ -57,7 +57,7 @@ class ServerBuilderPlugin {
/// UpdateChannelArguments will be called in ServerBuilder::BuildAndStart(),
/// before the Server instance is created.
virtual void UpdateChannelArguments(grpc_impl::ChannelArguments* args) {}
virtual void UpdateChannelArguments(ChannelArguments* args) {}
virtual bool has_sync_methods() const { return false; }
virtual bool has_async_methods() const { return false; }

@ -28,6 +28,7 @@ typedef ::grpc_impl::CallCredentials CallCredentials;
typedef ::grpc_impl::SslCredentialsOptions SslCredentialsOptions;
typedef ::grpc_impl::SecureCallCredentials SecureCallCredentials;
typedef ::grpc_impl::SecureChannelCredentials SecureChannelCredentials;
typedef ::grpc_impl::MetadataCredentialsPlugin MetadataCredentialsPlugin;
static inline std::shared_ptr<grpc_impl::ChannelCredentials>
GoogleDefaultCredentials() {

@ -24,11 +24,11 @@
#include <vector>
#include <grpc/grpc_security_constants.h>
#include <grpcpp/channel.h>
#include <grpcpp/channel_impl.h>
#include <grpcpp/impl/codegen/client_interceptor.h>
#include <grpcpp/impl/codegen/grpc_library.h>
#include <grpcpp/security/auth_context.h>
#include <grpcpp/support/channel_arguments.h>
#include <grpcpp/support/channel_arguments_impl.h>
#include <grpcpp/support/status.h>
#include <grpcpp/support/string_ref.h>
@ -41,16 +41,16 @@ class CallCredentials;
class SecureCallCredentials;
class SecureChannelCredentials;
std::shared_ptr<::grpc::Channel> CreateCustomChannelImpl(
std::shared_ptr<Channel> CreateCustomChannelImpl(
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds,
const grpc::ChannelArguments& args);
const ChannelArguments& args);
namespace experimental {
std::shared_ptr<::grpc::Channel> CreateCustomChannelWithInterceptors(
std::shared_ptr<Channel> CreateCustomChannelWithInterceptors(
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds,
const grpc::ChannelArguments& args,
const ChannelArguments& args,
std::vector<
std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>>
interceptor_creators);
@ -75,27 +75,27 @@ class ChannelCredentials : private grpc::GrpcLibraryCodegen {
virtual SecureChannelCredentials* AsSecureCredentials() = 0;
private:
friend std::shared_ptr<::grpc::Channel> CreateCustomChannelImpl(
friend std::shared_ptr<Channel> CreateCustomChannelImpl(
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds,
const grpc::ChannelArguments& args);
const ChannelArguments& args);
friend std::shared_ptr<::grpc::Channel>
friend std::shared_ptr<Channel>
grpc_impl::experimental::CreateCustomChannelWithInterceptors(
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds,
const grpc::ChannelArguments& args,
const ChannelArguments& args,
std::vector<std::unique_ptr<
grpc::experimental::ClientInterceptorFactoryInterface>>
interceptor_creators);
virtual std::shared_ptr<::grpc::Channel> CreateChannelImpl(
const grpc::string& target, const grpc::ChannelArguments& args) = 0;
virtual std::shared_ptr<Channel> CreateChannelImpl(
const grpc::string& target, const ChannelArguments& args) = 0;
// This function should have been a pure virtual function, but it is
// implemented as a virtual function so that it does not break API.
virtual std::shared_ptr<::grpc::Channel> CreateChannelWithInterceptors(
const grpc::string& target, const grpc::ChannelArguments& args,
virtual std::shared_ptr<Channel> CreateChannelWithInterceptors(
const grpc::string& target, const ChannelArguments& args,
std::vector<std::unique_ptr<
grpc::experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) {

@ -27,16 +27,17 @@
#include <grpc/compression.h>
#include <grpc/support/atm.h>
#include <grpcpp/channel.h>
#include <grpcpp/completion_queue.h>
#include <grpcpp/channel_impl.h>
#include <grpcpp/completion_queue_impl.h>
#include <grpcpp/health_check_service_interface.h>
#include <grpcpp/impl/call.h>
#include <grpcpp/impl/codegen/client_interceptor.h>
#include <grpcpp/impl/codegen/completion_queue_impl.h>
#include <grpcpp/impl/codegen/grpc_library.h>
#include <grpcpp/impl/codegen/server_interface.h>
#include <grpcpp/impl/rpc_service_method.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/support/channel_arguments.h>
#include <grpcpp/support/channel_arguments_impl.h>
#include <grpcpp/support/config.h>
#include <grpcpp/support/status.h>
@ -80,7 +81,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
public:
virtual ~GlobalCallbacks() {}
/// Called before server is created.
virtual void UpdateArguments(grpc::ChannelArguments* args) {}
virtual void UpdateArguments(ChannelArguments* args) {}
/// Called before application callback for each synchronous server request
virtual void PreSynchronousRequest(grpc_impl::ServerContext* context) = 0;
/// Called after application callback for each synchronous server request
@ -108,8 +109,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
}
/// Establish a channel for in-process communication
std::shared_ptr<::grpc::Channel> InProcessChannel(
const grpc::ChannelArguments& args);
std::shared_ptr<Channel> InProcessChannel(const ChannelArguments& args);
/// NOTE: class experimental_type is not part of the public API of this class.
/// TODO(yashykt): Integrate into public API when this is no longer
@ -120,8 +120,8 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
/// Establish a channel for in-process communication with client
/// interceptors
std::shared_ptr<::grpc::Channel> InProcessChannelWithInterceptors(
const grpc::ChannelArguments& args,
std::shared_ptr<Channel> InProcessChannelWithInterceptors(
const ChannelArguments& args,
std::vector<std::unique_ptr<
grpc::experimental::ClientInterceptorFactoryInterface>>
interceptor_creators);
@ -182,19 +182,18 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
///
/// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on
/// server completion queues passed via sync_server_cqs param.
Server(
int max_message_size, grpc::ChannelArguments* args,
std::shared_ptr<std::vector<std::unique_ptr<grpc::ServerCompletionQueue>>>
sync_server_cqs,
int min_pollers, int max_pollers, int sync_cq_timeout_msec,
std::vector<
std::shared_ptr<grpc::internal::ExternalConnectionAcceptorImpl>>
acceptors,
grpc_resource_quota* server_rq = nullptr,
std::vector<std::unique_ptr<
grpc::experimental::ServerInterceptorFactoryInterface>>
interceptor_creators = std::vector<std::unique_ptr<
grpc::experimental::ServerInterceptorFactoryInterface>>());
Server(int max_message_size, ChannelArguments* args,
std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
sync_server_cqs,
int min_pollers, int max_pollers, int sync_cq_timeout_msec,
std::vector<
std::shared_ptr<grpc::internal::ExternalConnectionAcceptorImpl>>
acceptors,
grpc_resource_quota* server_rq = nullptr,
std::vector<std::unique_ptr<
grpc::experimental::ServerInterceptorFactoryInterface>>
interceptor_creators = std::vector<std::unique_ptr<
grpc::experimental::ServerInterceptorFactoryInterface>>());
/// Start the server.
///
@ -202,7 +201,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
/// caller is required to keep all completion queues live until the server is
/// destroyed.
/// \param num_cqs How many completion queues does \a cqs hold.
void Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) override;
void Start(ServerCompletionQueue** cqs, size_t num_cqs) override;
grpc_server* server() override { return server_; }
@ -283,7 +282,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
return max_receive_message_size_;
}
grpc::CompletionQueue* CallbackCQ() override;
CompletionQueue* CallbackCQ() override;
grpc_impl::ServerInitializer* initializer();
@ -304,7 +303,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
/// The following completion queues are ONLY used in case of Sync API
/// i.e. if the server has any services with sync methods. The server uses
/// these completion queues to poll for new RPCs
std::shared_ptr<std::vector<std::unique_ptr<grpc::ServerCompletionQueue>>>
std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
sync_server_cqs_;
/// List of \a ThreadManager instances (one for each cq in
@ -374,7 +373,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen {
// It is _not owned_ by the server; ownership belongs with its internal
// shutdown callback tag (invoked when the CQ is fully shutdown).
// It is protected by mu_
grpc::CompletionQueue* callback_cq_ = nullptr;
CompletionQueue* callback_cq_ = nullptr;
};
} // namespace grpc_impl

@ -142,14 +142,17 @@ grpc::string GetHeaderIncludes(grpc_generator::File* file,
"grpcpp/impl/codegen/async_stream.h",
"grpcpp/impl/codegen/async_unary_call.h",
"grpcpp/impl/codegen/client_callback.h",
"grpcpp/impl/codegen/client_context.h",
"grpcpp/impl/codegen/method_handler_impl.h",
"grpcpp/impl/codegen/proto_utils.h",
"grpcpp/impl/codegen/rpc_method.h",
"grpcpp/impl/codegen/server_callback.h",
"grpcpp/impl/codegen/server_context.h",
"grpcpp/impl/codegen/service_type.h",
"grpcpp/impl/codegen/status.h",
"grpcpp/impl/codegen/stub_options.h",
"grpcpp/impl/codegen/sync_stream.h"};
"grpcpp/impl/codegen/sync_stream.h",
};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
PrintIncludes(printer.get(), headers, params.use_system_headers,
params.grpc_search_path);

@ -30,24 +30,25 @@
namespace grpc_core {
namespace channelz {
SubchannelNode::SubchannelNode(Subchannel* subchannel,
SubchannelNode::SubchannelNode(const char* target_address,
size_t channel_tracer_max_nodes)
: BaseNode(EntityType::kSubchannel),
subchannel_(subchannel),
target_(UniquePtr<char>(gpr_strdup(subchannel_->GetTargetAddress()))),
target_(UniquePtr<char>(gpr_strdup(target_address))),
trace_(channel_tracer_max_nodes) {}
SubchannelNode::~SubchannelNode() {}
void SubchannelNode::UpdateConnectivityState(grpc_connectivity_state state) {
connectivity_state_.Store(state, MemoryOrder::RELAXED);
}
void SubchannelNode::SetChildSocketUuid(intptr_t uuid) {
child_socket_uuid_.Store(uuid, MemoryOrder::RELAXED);
}
void SubchannelNode::PopulateConnectivityState(grpc_json* json) {
grpc_connectivity_state state;
if (subchannel_ == nullptr) {
state = GRPC_CHANNEL_SHUTDOWN;
} else {
state = subchannel_->CheckConnectivityState(
nullptr /* health_check_service_name */,
nullptr /* connected_subchannel */);
}
grpc_connectivity_state state =
connectivity_state_.Load(MemoryOrder::RELAXED);
json = grpc_json_create_child(nullptr, json, "state", nullptr,
GRPC_JSON_OBJECT, false);
grpc_json_create_child(nullptr, json, "state",
@ -87,7 +88,7 @@ grpc_json* SubchannelNode::RenderJson() {
call_counter_.PopulateCallCounts(json);
json = top_level_json;
// populate the child socket.
intptr_t socket_uuid = subchannel_->GetChildSocketUuid();
intptr_t socket_uuid = child_socket_uuid_.Load(MemoryOrder::RELAXED);
if (socket_uuid != 0) {
grpc_json* array_parent = grpc_json_create_child(
nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false);

@ -34,13 +34,17 @@ namespace channelz {
class SubchannelNode : public BaseNode {
public:
SubchannelNode(Subchannel* subchannel, size_t channel_tracer_max_nodes);
SubchannelNode(const char* target_address, size_t channel_tracer_max_nodes);
~SubchannelNode() override;
void MarkSubchannelDestroyed() {
GPR_ASSERT(subchannel_ != nullptr);
subchannel_ = nullptr;
}
// Sets the subchannel's connectivity state without health checking.
void UpdateConnectivityState(grpc_connectivity_state state);
// Used when the subchannel's child socket uuid changes. This should be set
// when the subchannel's transport is created and set to 0 when the subchannel
// unrefs the transport. A uuid of 0 indicates that the child socket is no
// longer associated with this subchannel.
void SetChildSocketUuid(intptr_t uuid);
grpc_json* RenderJson() override;
@ -61,7 +65,8 @@ class SubchannelNode : public BaseNode {
private:
void PopulateConnectivityState(grpc_json* json);
Subchannel* subchannel_;
Atomic<grpc_connectivity_state> connectivity_state_{GRPC_CHANNEL_IDLE};
Atomic<intptr_t> child_socket_uuid_{0};
UniquePtr<char> target_;
CallCountingHelper call_counter_;
ChannelTrace trace_;

@ -31,6 +31,9 @@
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/iocp_windows.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/sockaddr_windows.h"
#include "src/core/lib/iomgr/socket_windows.h"
#include "src/core/lib/iomgr/tcp_windows.h"
#include "src/core/lib/slice/slice_internal.h"
@ -50,6 +53,32 @@ struct iovec {
namespace grpc_core {
/* c-ares reads and takes action on the error codes of the
* "virtual socket operations" in this file, via the WSAGetLastError
* APIs. If code in this file wants to set a specific WSA error that
* c-ares should read, it must do so by calling SetWSAError() on the
* WSAErrorContext instance passed to it. A WSAErrorContext must only be
* instantiated at the top of the virtual socket function callstack. */
class WSAErrorContext {
public:
explicit WSAErrorContext(){};
~WSAErrorContext() {
if (error_ != 0) {
WSASetLastError(error_);
}
}
/* Disallow copy and assignment operators */
WSAErrorContext(const WSAErrorContext&) = delete;
WSAErrorContext& operator=(const WSAErrorContext&) = delete;
void SetWSAError(int error) { error_ = error; }
private:
int error_ = 0;
};
/* c-ares creates its own sockets and is meant to read them when readable and
* write them when writeable. To fit this socket usage model into the grpc
* windows poller (which gives notifications when attempted reads and writes are
@ -68,11 +97,14 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY,
};
GrpcPolledFdWindows(ares_socket_t as, grpc_combiner* combiner)
GrpcPolledFdWindows(ares_socket_t as, grpc_combiner* combiner,
int address_family, int socket_type)
: read_buf_(grpc_empty_slice()),
write_buf_(grpc_empty_slice()),
write_state_(WRITE_IDLE),
gotten_into_driver_list_(false) {
tcp_write_state_(WRITE_IDLE),
gotten_into_driver_list_(false),
address_family_(address_family),
socket_type_(socket_type) {
gpr_asprintf(&name_, "c-ares socket: %" PRIdPTR, as);
winsocket_ = grpc_winsocket_create(as, name_);
combiner_ = GRPC_COMBINER_REF(combiner, name_);
@ -82,6 +114,16 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
GRPC_CLOSURE_INIT(&outer_write_closure_,
&GrpcPolledFdWindows::OnIocpWriteable, this,
grpc_combiner_scheduler(combiner_));
GRPC_CLOSURE_INIT(&on_tcp_connect_locked_,
&GrpcPolledFdWindows::OnTcpConnectLocked, this,
grpc_combiner_scheduler(combiner_));
GRPC_CLOSURE_INIT(&continue_register_for_on_readable_locked_,
&GrpcPolledFdWindows::ContinueRegisterForOnReadableLocked,
this, grpc_combiner_scheduler(combiner_));
GRPC_CLOSURE_INIT(
&continue_register_for_on_writeable_locked_,
&GrpcPolledFdWindows::ContinueRegisterForOnWriteableLocked, this,
grpc_combiner_scheduler(combiner_));
}
~GrpcPolledFdWindows() {
@ -111,6 +153,33 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
grpc_slice_unref_internal(read_buf_);
GPR_ASSERT(!read_buf_has_data_);
read_buf_ = GRPC_SLICE_MALLOC(4192);
if (connect_done_) {
GRPC_CLOSURE_SCHED(&continue_register_for_on_readable_locked_,
GRPC_ERROR_NONE);
} else {
GPR_ASSERT(pending_continue_register_for_on_readable_locked_ == nullptr);
pending_continue_register_for_on_readable_locked_ =
&continue_register_for_on_readable_locked_;
}
}
static void ContinueRegisterForOnReadableLocked(void* arg,
grpc_error* unused_error) {
GrpcPolledFdWindows* grpc_polled_fd =
static_cast<GrpcPolledFdWindows*>(arg);
grpc_polled_fd->InnerContinueRegisterForOnReadableLocked(GRPC_ERROR_NONE);
}
void InnerContinueRegisterForOnReadableLocked(grpc_error* unused_error) {
GRPC_CARES_TRACE_LOG(
"fd:|%s| InnerContinueRegisterForOnReadableLocked "
"wsa_connect_error_:%d",
GetName(), wsa_connect_error_);
GPR_ASSERT(connect_done_);
if (wsa_connect_error_ != 0) {
ScheduleAndNullReadClosure(GRPC_WSA_ERROR(wsa_connect_error_, "connect"));
return;
}
WSABUF buffer;
buffer.buf = (char*)GRPC_SLICE_START_PTR(read_buf_);
buffer.len = GRPC_SLICE_LENGTH(read_buf_);
@ -123,13 +192,14 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
&winsocket_->read_info.overlapped, nullptr)) {
int wsa_last_error = WSAGetLastError();
char* msg = gpr_format_message(wsa_last_error);
grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
GRPC_CARES_TRACE_LOG(
"RegisterForOnReadableLocked: WSARecvFrom error:|%s|. fd:|%s|", msg,
GetName());
"fd:|%s| RegisterForOnReadableLocked WSARecvFrom error code:|%d| "
"msg:|%s|",
GetName(), wsa_last_error, msg);
gpr_free(msg);
if (wsa_last_error != WSA_IO_PENDING) {
ScheduleAndNullReadClosure(error);
ScheduleAndNullReadClosure(
GRPC_WSA_ERROR(wsa_last_error, "WSARecvFrom"));
return;
}
}
@ -137,23 +207,68 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
}
void RegisterForOnWriteableLocked(grpc_closure* write_closure) override {
GRPC_CARES_TRACE_LOG(
"RegisterForOnWriteableLocked. fd:|%s|. Current write state: %d",
GetName(), write_state_);
if (socket_type_ == SOCK_DGRAM) {
GRPC_CARES_TRACE_LOG("fd:|%s| RegisterForOnWriteableLocked called",
GetName());
} else {
GPR_ASSERT(socket_type_ == SOCK_STREAM);
GRPC_CARES_TRACE_LOG(
"fd:|%s| RegisterForOnWriteableLocked called tcp_write_state_: %d",
GetName(), tcp_write_state_);
}
GPR_ASSERT(write_closure_ == nullptr);
write_closure_ = write_closure;
switch (write_state_) {
case WRITE_IDLE:
ScheduleAndNullWriteClosure(GRPC_ERROR_NONE);
break;
case WRITE_REQUESTED:
write_state_ = WRITE_PENDING;
SendWriteBuf(nullptr, &winsocket_->write_info.overlapped);
grpc_socket_notify_on_write(winsocket_, &outer_write_closure_);
break;
case WRITE_PENDING:
case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY:
abort();
if (connect_done_) {
GRPC_CLOSURE_SCHED(&continue_register_for_on_writeable_locked_,
GRPC_ERROR_NONE);
} else {
GPR_ASSERT(pending_continue_register_for_on_writeable_locked_ == nullptr);
pending_continue_register_for_on_writeable_locked_ =
&continue_register_for_on_writeable_locked_;
}
}
static void ContinueRegisterForOnWriteableLocked(void* arg,
grpc_error* unused_error) {
GrpcPolledFdWindows* grpc_polled_fd =
static_cast<GrpcPolledFdWindows*>(arg);
grpc_polled_fd->InnerContinueRegisterForOnWriteableLocked(GRPC_ERROR_NONE);
}
void InnerContinueRegisterForOnWriteableLocked(grpc_error* unused_error) {
GRPC_CARES_TRACE_LOG(
"fd:|%s| InnerContinueRegisterForOnWriteableLocked "
"wsa_connect_error_:%d",
GetName(), wsa_connect_error_);
GPR_ASSERT(connect_done_);
if (wsa_connect_error_ != 0) {
ScheduleAndNullWriteClosure(
GRPC_WSA_ERROR(wsa_connect_error_, "connect"));
return;
}
if (socket_type_ == SOCK_DGRAM) {
ScheduleAndNullWriteClosure(GRPC_ERROR_NONE);
} else {
GPR_ASSERT(socket_type_ == SOCK_STREAM);
int wsa_error_code = 0;
switch (tcp_write_state_) {
case WRITE_IDLE:
ScheduleAndNullWriteClosure(GRPC_ERROR_NONE);
break;
case WRITE_REQUESTED:
tcp_write_state_ = WRITE_PENDING;
if (SendWriteBuf(nullptr, &winsocket_->write_info.overlapped,
&wsa_error_code) != 0) {
ScheduleAndNullWriteClosure(
GRPC_WSA_ERROR(wsa_error_code, "WSASend (overlapped)"));
} else {
grpc_socket_notify_on_write(winsocket_, &outer_write_closure_);
}
break;
case WRITE_PENDING:
case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY:
abort();
}
}
}
@ -171,13 +286,15 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
const char* GetName() override { return name_; }
ares_ssize_t RecvFrom(void* data, ares_socket_t data_len, int flags,
ares_ssize_t RecvFrom(WSAErrorContext* wsa_error_ctx, void* data,
ares_socket_t data_len, int flags,
struct sockaddr* from, ares_socklen_t* from_len) {
GRPC_CARES_TRACE_LOG(
"RecvFrom called on fd:|%s|. Current read buf length:|%d|", GetName(),
GRPC_SLICE_LENGTH(read_buf_));
"fd:|%s| RecvFrom called read_buf_has_data:%d Current read buf "
"length:|%d|",
GetName(), read_buf_has_data_, GRPC_SLICE_LENGTH(read_buf_));
if (!read_buf_has_data_) {
WSASetLastError(WSAEWOULDBLOCK);
wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
return -1;
}
ares_ssize_t bytes_read = 0;
@ -215,54 +332,99 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
return out;
}
int SendWriteBuf(LPDWORD bytes_sent_ptr, LPWSAOVERLAPPED overlapped) {
int SendWriteBuf(LPDWORD bytes_sent_ptr, LPWSAOVERLAPPED overlapped,
int* wsa_error_code) {
WSABUF buf;
buf.len = GRPC_SLICE_LENGTH(write_buf_);
buf.buf = (char*)GRPC_SLICE_START_PTR(write_buf_);
DWORD flags = 0;
int out = WSASend(grpc_winsocket_wrapped_socket(winsocket_), &buf, 1,
bytes_sent_ptr, flags, overlapped, nullptr);
*wsa_error_code = WSAGetLastError();
GRPC_CARES_TRACE_LOG(
"WSASend: name:%s. buf len:%d. bytes sent: %d. overlapped %p. return "
"val: %d",
GetName(), buf.len, *bytes_sent_ptr, overlapped, out);
"fd:|%s| SendWriteBuf WSASend buf.len:%d *bytes_sent_ptr:%d "
"overlapped:%p "
"return:%d *wsa_error_code:%d",
GetName(), buf.len, bytes_sent_ptr != nullptr ? *bytes_sent_ptr : 0,
overlapped, out, *wsa_error_code);
return out;
}
ares_ssize_t TrySendWriteBufSyncNonBlocking() {
GPR_ASSERT(write_state_ == WRITE_IDLE);
ares_ssize_t SendV(WSAErrorContext* wsa_error_ctx, const struct iovec* iov,
int iov_count) {
GRPC_CARES_TRACE_LOG(
"fd:|%s| SendV called connect_done_:%d wsa_connect_error_:%d",
GetName(), connect_done_, wsa_connect_error_);
if (!connect_done_) {
wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
return -1;
}
if (wsa_connect_error_ != 0) {
wsa_error_ctx->SetWSAError(wsa_connect_error_);
return -1;
}
switch (socket_type_) {
case SOCK_DGRAM:
return SendVUDP(wsa_error_ctx, iov, iov_count);
case SOCK_STREAM:
return SendVTCP(wsa_error_ctx, iov, iov_count);
default:
abort();
}
}
ares_ssize_t SendVUDP(WSAErrorContext* wsa_error_ctx, const struct iovec* iov,
int iov_count) {
// c-ares doesn't handle retryable errors on writes of UDP sockets.
// Therefore, the sendv handler for UDP sockets must only attempt
// to write everything inline.
GRPC_CARES_TRACE_LOG("fd:|%s| SendVUDP called", GetName());
GPR_ASSERT(GRPC_SLICE_LENGTH(write_buf_) == 0);
grpc_slice_unref_internal(write_buf_);
write_buf_ = FlattenIovec(iov, iov_count);
DWORD bytes_sent = 0;
if (SendWriteBuf(&bytes_sent, nullptr) != 0) {
int wsa_last_error = WSAGetLastError();
char* msg = gpr_format_message(wsa_last_error);
int wsa_error_code = 0;
if (SendWriteBuf(&bytes_sent, nullptr, &wsa_error_code) != 0) {
wsa_error_ctx->SetWSAError(wsa_error_code);
char* msg = gpr_format_message(wsa_error_code);
GRPC_CARES_TRACE_LOG(
"TrySendWriteBufSyncNonBlocking: SendWriteBuf error:|%s|. fd:|%s|",
msg, GetName());
"fd:|%s| SendVUDP SendWriteBuf error code:%d msg:|%s|", GetName(),
wsa_error_code, msg);
gpr_free(msg);
if (wsa_last_error == WSA_IO_PENDING) {
WSASetLastError(WSAEWOULDBLOCK);
write_state_ = WRITE_REQUESTED;
}
return -1;
}
write_buf_ = grpc_slice_sub_no_ref(write_buf_, bytes_sent,
GRPC_SLICE_LENGTH(write_buf_));
return bytes_sent;
}
ares_ssize_t SendV(const struct iovec* iov, int iov_count) {
GRPC_CARES_TRACE_LOG("SendV called on fd:|%s|. Current write state: %d",
GetName(), write_state_);
switch (write_state_) {
ares_ssize_t SendVTCP(WSAErrorContext* wsa_error_ctx, const struct iovec* iov,
int iov_count) {
// The "sendv" handler on TCP sockets buffers up write
// requests and returns an artifical WSAEWOULDBLOCK. Writing that buffer out
// in the background, and making further send progress in general, will
// happen as long as c-ares continues to show interest in writeability on
// this fd.
GRPC_CARES_TRACE_LOG("fd:|%s| SendVTCP called tcp_write_state_:%d",
GetName(), tcp_write_state_);
switch (tcp_write_state_) {
case WRITE_IDLE:
tcp_write_state_ = WRITE_REQUESTED;
GPR_ASSERT(GRPC_SLICE_LENGTH(write_buf_) == 0);
grpc_slice_unref_internal(write_buf_);
write_buf_ = FlattenIovec(iov, iov_count);
return TrySendWriteBufSyncNonBlocking();
wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
return -1;
case WRITE_REQUESTED:
case WRITE_PENDING:
WSASetLastError(WSAEWOULDBLOCK);
wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
return -1;
case WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY:
// c-ares is retrying a send on data that we previously returned
// WSAEWOULDBLOCK for, but then subsequently wrote out in the
// background. Right now, we assume that c-ares is retrying the same
// send again. If c-ares still needs to send even more data, we'll get
// to it eventually.
grpc_slice currently_attempted = FlattenIovec(iov, iov_count);
GPR_ASSERT(GRPC_SLICE_LENGTH(currently_attempted) >=
GRPC_SLICE_LENGTH(write_buf_));
@ -272,31 +434,159 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
GRPC_SLICE_START_PTR(write_buf_)[i]);
total_sent++;
}
grpc_slice_unref_internal(write_buf_);
write_buf_ =
grpc_slice_sub_no_ref(currently_attempted, total_sent,
GRPC_SLICE_LENGTH(currently_attempted));
write_state_ = WRITE_IDLE;
total_sent += TrySendWriteBufSyncNonBlocking();
grpc_slice_unref_internal(currently_attempted);
tcp_write_state_ = WRITE_IDLE;
return total_sent;
}
abort();
}
int Connect(const struct sockaddr* target, ares_socklen_t target_len) {
static void OnTcpConnectLocked(void* arg, grpc_error* error) {
GrpcPolledFdWindows* grpc_polled_fd =
static_cast<GrpcPolledFdWindows*>(arg);
grpc_polled_fd->InnerOnTcpConnectLocked(error);
}
void InnerOnTcpConnectLocked(grpc_error* error) {
GRPC_CARES_TRACE_LOG(
"fd:%s InnerOnTcpConnectLocked error:|%s| "
"pending_register_for_readable:%" PRIdPTR
" pending_register_for_writeable:%" PRIdPTR,
GetName(), grpc_error_string(error),
pending_continue_register_for_on_readable_locked_,
pending_continue_register_for_on_writeable_locked_);
GPR_ASSERT(!connect_done_);
connect_done_ = true;
GPR_ASSERT(wsa_connect_error_ == 0);
if (error == GRPC_ERROR_NONE) {
DWORD transfered_bytes = 0;
DWORD flags;
BOOL wsa_success = WSAGetOverlappedResult(
grpc_winsocket_wrapped_socket(winsocket_),
&winsocket_->write_info.overlapped, &transfered_bytes, FALSE, &flags);
GPR_ASSERT(transfered_bytes == 0);
if (!wsa_success) {
wsa_connect_error_ = WSAGetLastError();
char* msg = gpr_format_message(wsa_connect_error_);
GRPC_CARES_TRACE_LOG(
"fd:%s InnerOnTcpConnectLocked WSA overlapped result code:%d "
"msg:|%s|",
GetName(), wsa_connect_error_, msg);
gpr_free(msg);
}
} else {
// Spoof up an error code that will cause any future c-ares operations on
// this fd to abort.
wsa_connect_error_ = WSA_OPERATION_ABORTED;
}
if (pending_continue_register_for_on_readable_locked_ != nullptr) {
GRPC_CLOSURE_SCHED(pending_continue_register_for_on_readable_locked_,
GRPC_ERROR_NONE);
}
if (pending_continue_register_for_on_writeable_locked_ != nullptr) {
GRPC_CLOSURE_SCHED(pending_continue_register_for_on_writeable_locked_,
GRPC_ERROR_NONE);
}
}
int Connect(WSAErrorContext* wsa_error_ctx, const struct sockaddr* target,
ares_socklen_t target_len) {
switch (socket_type_) {
case SOCK_DGRAM:
return ConnectUDP(wsa_error_ctx, target, target_len);
case SOCK_STREAM:
return ConnectTCP(wsa_error_ctx, target, target_len);
default:
abort();
}
}
int ConnectUDP(WSAErrorContext* wsa_error_ctx, const struct sockaddr* target,
ares_socklen_t target_len) {
GRPC_CARES_TRACE_LOG("fd:%s ConnectUDP", GetName());
GPR_ASSERT(!connect_done_);
GPR_ASSERT(wsa_connect_error_ == 0);
SOCKET s = grpc_winsocket_wrapped_socket(winsocket_);
GRPC_CARES_TRACE_LOG("Connect: fd:|%s|", GetName());
int out =
WSAConnect(s, target, target_len, nullptr, nullptr, nullptr, nullptr);
if (out != 0) {
wsa_connect_error_ = WSAGetLastError();
wsa_error_ctx->SetWSAError(wsa_connect_error_);
connect_done_ = true;
char* msg = gpr_format_message(wsa_connect_error_);
GRPC_CARES_TRACE_LOG("fd:%s WSAConnect error code:|%d| msg:|%s|", GetName(),
wsa_connect_error_, msg);
gpr_free(msg);
// c-ares expects a posix-style connect API
return out == 0 ? 0 : -1;
}
int ConnectTCP(WSAErrorContext* wsa_error_ctx, const struct sockaddr* target,
ares_socklen_t target_len) {
GRPC_CARES_TRACE_LOG("fd:%s ConnectTCP", GetName());
LPFN_CONNECTEX ConnectEx;
GUID guid = WSAID_CONNECTEX;
DWORD ioctl_num_bytes;
SOCKET s = grpc_winsocket_wrapped_socket(winsocket_);
if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
&ConnectEx, sizeof(ConnectEx), &ioctl_num_bytes, nullptr,
nullptr) != 0) {
int wsa_last_error = WSAGetLastError();
wsa_error_ctx->SetWSAError(wsa_last_error);
char* msg = gpr_format_message(wsa_last_error);
GRPC_CARES_TRACE_LOG(
"fd:%s WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER) error code:%d "
"msg:|%s|",
GetName(), wsa_last_error, msg);
gpr_free(msg);
connect_done_ = true;
wsa_connect_error_ = wsa_last_error;
return -1;
}
grpc_resolved_address wildcard4_addr;
grpc_resolved_address wildcard6_addr;
grpc_sockaddr_make_wildcards(0, &wildcard4_addr, &wildcard6_addr);
grpc_resolved_address* local_address = nullptr;
if (address_family_ == AF_INET) {
local_address = &wildcard4_addr;
} else {
local_address = &wildcard6_addr;
}
if (bind(s, (struct sockaddr*)local_address->addr,
(int)local_address->len) != 0) {
int wsa_last_error = WSAGetLastError();
wsa_error_ctx->SetWSAError(wsa_last_error);
char* msg = gpr_format_message(wsa_last_error);
GRPC_CARES_TRACE_LOG("Connect error code:|%d|, msg:|%s|. fd:|%s|",
wsa_last_error, msg, GetName());
GRPC_CARES_TRACE_LOG("fd:%s bind error code:%d msg:|%s|", GetName(),
wsa_last_error, msg);
gpr_free(msg);
// c-ares expects a posix-style connect API
connect_done_ = true;
wsa_connect_error_ = wsa_last_error;
return -1;
}
int out = 0;
if (ConnectEx(s, target, target_len, nullptr, 0, nullptr,
&winsocket_->write_info.overlapped) == 0) {
out = -1;
int wsa_last_error = WSAGetLastError();
wsa_error_ctx->SetWSAError(wsa_last_error);
char* msg = gpr_format_message(wsa_last_error);
GRPC_CARES_TRACE_LOG("fd:%s ConnectEx error code:%d msg:|%s|", GetName(),
wsa_last_error, msg);
gpr_free(msg);
if (wsa_last_error == WSA_IO_PENDING) {
// c-ares only understands WSAEINPROGRESS and EWOULDBLOCK error codes on
// connect, but an async connect on IOCP socket will give
// WSA_IO_PENDING, so we need to convert.
wsa_error_ctx->SetWSAError(WSAEWOULDBLOCK);
} else {
// By returning a non-retryable error to c-ares at this point,
// we're aborting the possibility of any future operations on this fd.
connect_done_ = true;
wsa_connect_error_ = wsa_last_error;
return -1;
}
}
grpc_socket_notify_on_write(winsocket_, &on_tcp_connect_locked_);
return out;
}
@ -319,12 +609,13 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
* in subsequent c-ares reads. */
if (winsocket_->read_info.wsa_error != WSAEMSGSIZE) {
GRPC_ERROR_UNREF(error);
char* msg = gpr_format_message(winsocket_->read_info.wsa_error);
error = GRPC_WSA_ERROR(winsocket_->read_info.wsa_error,
"OnIocpReadableInner");
GRPC_CARES_TRACE_LOG(
"OnIocpReadableInner. winsocket error:|%s|. fd:|%s|", msg,
GetName());
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(msg);
"fd:|%s| OnIocpReadableInner winsocket_->read_info.wsa_error "
"code:|%d| msg:|%s|",
GetName(), winsocket_->read_info.wsa_error,
grpc_error_string(error));
}
}
}
@ -337,8 +628,8 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
read_buf_ = grpc_empty_slice();
}
GRPC_CARES_TRACE_LOG(
"OnIocpReadable finishing. read buf length now:|%d|. :fd:|%s|",
GRPC_SLICE_LENGTH(read_buf_), GetName());
"fd:|%s| OnIocpReadable finishing. read buf length now:|%d|", GetName(),
GRPC_SLICE_LENGTH(read_buf_));
ScheduleAndNullReadClosure(error);
}
@ -349,22 +640,26 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
void OnIocpWriteableInner(grpc_error* error) {
GRPC_CARES_TRACE_LOG("OnIocpWriteableInner. fd:|%s|", GetName());
GPR_ASSERT(socket_type_ == SOCK_STREAM);
if (error == GRPC_ERROR_NONE) {
if (winsocket_->write_info.wsa_error != 0) {
char* msg = gpr_format_message(winsocket_->write_info.wsa_error);
GRPC_CARES_TRACE_LOG(
"OnIocpWriteableInner. winsocket error:|%s|. fd:|%s|", msg,
GetName());
GRPC_ERROR_UNREF(error);
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
gpr_free(msg);
error = GRPC_WSA_ERROR(winsocket_->write_info.wsa_error,
"OnIocpWriteableInner");
GRPC_CARES_TRACE_LOG(
"fd:|%s| OnIocpWriteableInner. winsocket_->write_info.wsa_error "
"code:|%d| msg:|%s|",
GetName(), winsocket_->write_info.wsa_error,
grpc_error_string(error));
}
}
GPR_ASSERT(write_state_ == WRITE_PENDING);
GPR_ASSERT(tcp_write_state_ == WRITE_PENDING);
if (error == GRPC_ERROR_NONE) {
write_state_ = WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY;
tcp_write_state_ = WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY;
write_buf_ = grpc_slice_sub_no_ref(
write_buf_, 0, winsocket_->write_info.bytes_transfered);
GRPC_CARES_TRACE_LOG("fd:|%s| OnIocpWriteableInner. bytes transferred:%d",
GetName(), winsocket_->write_info.bytes_transfered);
} else {
grpc_slice_unref_internal(write_buf_);
write_buf_ = grpc_empty_slice();
@ -386,9 +681,22 @@ class GrpcPolledFdWindows : public GrpcPolledFd {
grpc_closure outer_read_closure_;
grpc_closure outer_write_closure_;
grpc_winsocket* winsocket_;
WriteState write_state_;
// tcp_write_state_ is only used on TCP GrpcPolledFds
WriteState tcp_write_state_;
char* name_ = nullptr;
bool gotten_into_driver_list_;
int address_family_;
int socket_type_;
grpc_closure on_tcp_connect_locked_;
bool connect_done_ = false;
int wsa_connect_error_ = 0;
// We don't run register_for_{readable,writeable} logic until
// a socket is connected. In the interim, we queue readable/writeable
// registrations with the following state.
grpc_closure continue_register_for_on_readable_locked_;
grpc_closure continue_register_for_on_writeable_locked_;
grpc_closure* pending_continue_register_for_on_readable_locked_ = nullptr;
grpc_closure* pending_continue_register_for_on_writeable_locked_ = nullptr;
};
struct SockToPolledFdEntry {
@ -454,39 +762,53 @@ class SockToPolledFdMap {
* objects.
*/
static ares_socket_t Socket(int af, int type, int protocol, void* user_data) {
if (type != SOCK_DGRAM && type != SOCK_STREAM) {
GRPC_CARES_TRACE_LOG("Socket called with invalid socket type:%d", type);
return INVALID_SOCKET;
}
SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
SOCKET s = WSASocket(af, type, protocol, nullptr, 0,
grpc_get_default_wsa_socket_flags());
if (s == INVALID_SOCKET) {
GRPC_CARES_TRACE_LOG(
"WSASocket failed with params af:%d type:%d protocol:%d", af, type,
protocol);
return s;
}
grpc_tcp_set_non_block(s);
GrpcPolledFdWindows* polled_fd =
New<GrpcPolledFdWindows>(s, map->combiner_);
New<GrpcPolledFdWindows>(s, map->combiner_, af, type);
GRPC_CARES_TRACE_LOG(
"fd:|%s| created with params af:%d type:%d protocol:%d",
polled_fd->GetName(), af, type, protocol);
map->AddNewSocket(s, polled_fd);
return s;
}
static int Connect(ares_socket_t as, const struct sockaddr* target,
ares_socklen_t target_len, void* user_data) {
WSAErrorContext wsa_error_ctx;
SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as);
return polled_fd->Connect(target, target_len);
return polled_fd->Connect(&wsa_error_ctx, target, target_len);
}
static ares_ssize_t SendV(ares_socket_t as, const struct iovec* iov,
int iovec_count, void* user_data) {
WSAErrorContext wsa_error_ctx;
SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as);
return polled_fd->SendV(iov, iovec_count);
return polled_fd->SendV(&wsa_error_ctx, iov, iovec_count);
}
static ares_ssize_t RecvFrom(ares_socket_t as, void* data, size_t data_len,
int flags, struct sockaddr* from,
ares_socklen_t* from_len, void* user_data) {
WSAErrorContext wsa_error_ctx;
SockToPolledFdMap* map = static_cast<SockToPolledFdMap*>(user_data);
GrpcPolledFdWindows* polled_fd = map->LookupPolledFd(as);
return polled_fd->RecvFrom(data, data_len, flags, from, from_len);
return polled_fd->RecvFrom(&wsa_error_ctx, data, data_len, flags, from,
from_len);
}
static int CloseSocket(SOCKET s, void* user_data) {

@ -84,13 +84,11 @@ DebugOnlyTraceFlag grpc_trace_subchannel_refcount(false, "subchannel_refcount");
ConnectedSubchannel::ConnectedSubchannel(
grpc_channel_stack* channel_stack, const grpc_channel_args* args,
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel,
intptr_t socket_uuid)
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel)
: ConnectedSubchannelInterface(&grpc_trace_subchannel_refcount),
channel_stack_(channel_stack),
args_(grpc_channel_args_copy(args)),
channelz_subchannel_(std::move(channelz_subchannel)),
socket_uuid_(socket_uuid) {}
channelz_subchannel_(std::move(channelz_subchannel)) {}
ConnectedSubchannel::~ConnectedSubchannel() {
grpc_channel_args_destroy(args_);
@ -344,6 +342,9 @@ class Subchannel::ConnectedSubchannelStateWatcher {
self->pending_connectivity_state_));
}
c->connected_subchannel_.reset();
if (c->channelz_node() != nullptr) {
c->channelz_node()->SetChildSocketUuid(0);
}
c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE);
c->backoff_begun_ = false;
c->backoff_.Reset();
@ -676,7 +677,7 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector,
(size_t)grpc_channel_arg_get_integer(arg, options);
if (channelz_enabled) {
channelz_node_ = MakeRefCounted<channelz::SubchannelNode>(
this, channel_tracer_max_memory);
GetTargetAddress(), channel_tracer_max_memory);
channelz_node_->AddTraceEvent(
channelz::ChannelTrace::Severity::Info,
grpc_slice_from_static_string("subchannel created"));
@ -688,7 +689,7 @@ Subchannel::~Subchannel() {
channelz_node_->AddTraceEvent(
channelz::ChannelTrace::Severity::Info,
grpc_slice_from_static_string("Subchannel destroyed"));
channelz_node_->MarkSubchannelDestroyed();
channelz_node_->UpdateConnectivityState(GRPC_CHANNEL_SHUTDOWN);
}
grpc_channel_args_destroy(args_);
grpc_connector_unref(connector_);
@ -778,14 +779,6 @@ Subchannel* Subchannel::RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
}
}
intptr_t Subchannel::GetChildSocketUuid() {
if (connected_subchannel_ != nullptr) {
return connected_subchannel_->socket_uuid();
} else {
return 0;
}
}
const char* Subchannel::GetTargetAddress() {
const grpc_arg* addr_arg =
grpc_channel_args_find(args_, GRPC_ARG_SUBCHANNEL_ADDRESS);
@ -930,6 +923,7 @@ const char* SubchannelConnectivityStateChangeString(
void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state) {
state_ = state;
if (channelz_node_ != nullptr) {
channelz_node_->UpdateConnectivityState(state);
channelz_node_->AddTraceEvent(
channelz::ChannelTrace::Severity::Info,
grpc_slice_from_static_string(
@ -1078,9 +1072,12 @@ bool Subchannel::PublishTransportLocked() {
}
// Publish.
connected_subchannel_.reset(
New<ConnectedSubchannel>(stk, args_, channelz_node_, socket_uuid));
New<ConnectedSubchannel>(stk, args_, channelz_node_));
gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
connected_subchannel_.get(), this);
if (channelz_node_ != nullptr) {
channelz_node_->SetChildSocketUuid(socket_uuid);
}
// Instantiate state watcher. Will clean itself up.
New<ConnectedSubchannelStateWatcher>(this);
// Report initial state.

@ -85,8 +85,7 @@ class ConnectedSubchannel : public ConnectedSubchannelInterface {
ConnectedSubchannel(
grpc_channel_stack* channel_stack, const grpc_channel_args* args,
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel,
intptr_t socket_uuid);
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel);
~ConnectedSubchannel();
void NotifyOnStateChange(grpc_pollset_set* interested_parties,
@ -101,7 +100,6 @@ class ConnectedSubchannel : public ConnectedSubchannelInterface {
channelz::SubchannelNode* channelz_subchannel() const {
return channelz_subchannel_.get();
}
intptr_t socket_uuid() const { return socket_uuid_; }
size_t GetInitialCallSizeEstimate(size_t parent_data_size) const;
@ -111,8 +109,6 @@ class ConnectedSubchannel : public ConnectedSubchannelInterface {
// ref counted pointer to the channelz node in this connected subchannel's
// owning subchannel.
RefCountedPtr<channelz::SubchannelNode> channelz_subchannel_;
// uuid of this subchannel's socket. 0 if this subchannel is not connected.
const intptr_t socket_uuid_;
};
// Implements the interface of RefCounted<>.
@ -200,8 +196,6 @@ class Subchannel {
// returns null.
Subchannel* RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
intptr_t GetChildSocketUuid();
// Gets the string representing the subchannel address.
// Caller doesn't take ownership.
const char* GetTargetAddress();

@ -130,8 +130,9 @@ static void begin_frame(framer_state* st) {
space to add at least about_to_add bytes -- finishes the current frame if
needed */
static void ensure_space(framer_state* st, size_t need_bytes) {
if (st->output->length - st->output_length_at_start_of_frame + need_bytes <=
st->max_frame_size) {
if (GPR_LIKELY(st->output->length - st->output_length_at_start_of_frame +
need_bytes <=
st->max_frame_size)) {
return;
}
finish_frame(st, 0, 0);

@ -120,7 +120,10 @@ size_t Executor::RunClosures(const char* executor_name,
// thread itself, but this is the point where we could start seeing
// application-level callbacks. No need to create a new ExecCtx, though,
// since there already is one and it is flushed (but not destructed) in this
// function itself.
// function itself. The ApplicationCallbackExecCtx will have its callbacks
// invoked on its destruction, which will be after completing any closures in
// the executor's closure list (which were explicitly scheduled onto the
// executor).
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx(
GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);

@ -18,6 +18,7 @@
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/security/credentials/jwt/json_token.h"
#include <string.h>
@ -69,6 +70,7 @@ grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json* json) {
BIO* bio = nullptr;
const char* prop_value;
int success = 0;
grpc_error* error = GRPC_ERROR_NONE;
memset(&result, 0, sizeof(grpc_auth_json_key));
result.type = GRPC_AUTH_JSON_TYPE_INVALID;
@ -77,7 +79,8 @@ grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json* json) {
goto end;
}
prop_value = grpc_json_get_string_property(json, "type");
prop_value = grpc_json_get_string_property(json, "type", &error);
GRPC_LOG_IF_ERROR("JSON key parsing", error);
if (prop_value == nullptr ||
strcmp(prop_value, GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT)) {
goto end;
@ -92,7 +95,8 @@ grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json* json) {
goto end;
}
prop_value = grpc_json_get_string_property(json, "private_key");
prop_value = grpc_json_get_string_property(json, "private_key", &error);
GRPC_LOG_IF_ERROR("JSON key parsing", error);
if (prop_value == nullptr) {
goto end;
}

@ -22,14 +22,23 @@
#include <string.h>
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/security/util/json_util.h"
#include "src/core/lib/surface/api_trace.h"
#include <grpc/grpc_security.h>
#include <grpc/impl/codegen/slice.h>
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/inlined_vector.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/util/json_util.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/uri/uri_parser.h"
//
// Auth Refresh Token.
//
@ -45,6 +54,7 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
grpc_auth_refresh_token result;
const char* prop_value;
int success = 0;
grpc_error* error = GRPC_ERROR_NONE;
memset(&result, 0, sizeof(grpc_auth_refresh_token));
result.type = GRPC_AUTH_JSON_TYPE_INVALID;
@ -53,7 +63,8 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
goto end;
}
prop_value = grpc_json_get_string_property(json, "type");
prop_value = grpc_json_get_string_property(json, "type", &error);
GRPC_LOG_IF_ERROR("Parsing refresh token", error);
if (prop_value == nullptr ||
strcmp(prop_value, GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER)) {
goto end;
@ -218,8 +229,10 @@ void grpc_oauth2_token_fetcher_credentials::on_http_response(
grpc_mdelem access_token_md = GRPC_MDNULL;
grpc_millis token_lifetime;
grpc_credentials_status status =
grpc_oauth2_token_fetcher_credentials_parse_server_response(
&r->response, &access_token_md, &token_lifetime);
error == GRPC_ERROR_NONE
? grpc_oauth2_token_fetcher_credentials_parse_server_response(
&r->response, &access_token_md, &token_lifetime)
: GRPC_CREDENTIALS_ERROR;
// Update cache and grab list of pending requests.
gpr_mu_lock(&mu_);
token_fetch_pending_ = false;
@ -234,14 +247,15 @@ void grpc_oauth2_token_fetcher_credentials::on_http_response(
gpr_mu_unlock(&mu_);
// Invoke callbacks for all pending requests.
while (pending_request != nullptr) {
grpc_error* new_error = GRPC_ERROR_NONE;
if (status == GRPC_CREDENTIALS_OK) {
grpc_credentials_mdelem_array_add(pending_request->md_array,
access_token_md);
} else {
error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
new_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Error occurred when fetching oauth2 token.", &error, 1);
}
GRPC_CLOSURE_SCHED(pending_request->on_request_metadata, error);
GRPC_CLOSURE_SCHED(pending_request->on_request_metadata, new_error);
grpc_polling_entity_del_from_pollset_set(
pending_request->pollent, grpc_polling_entity_pollset_set(&pollent_));
grpc_oauth2_pending_get_request_metadata* prev = pending_request;
@ -356,7 +370,8 @@ class grpc_compute_engine_token_fetcher_credentials
grpc_polling_entity* pollent,
grpc_iomgr_cb_func response_cb,
grpc_millis deadline) override {
grpc_http_header header = {(char*)"Metadata-Flavor", (char*)"Google"};
grpc_http_header header = {const_cast<char*>("Metadata-Flavor"),
const_cast<char*>("Google")};
grpc_httpcli_request request;
memset(&request, 0, sizeof(grpc_httpcli_request));
request.host = (char*)GRPC_COMPUTE_ENGINE_METADATA_HOST;
@ -369,11 +384,14 @@ class grpc_compute_engine_token_fetcher_credentials
grpc_resource_quota* resource_quota =
grpc_resource_quota_create("oauth2_credentials");
grpc_httpcli_get(http_context, pollent, resource_quota, &request, deadline,
GRPC_CLOSURE_CREATE(response_cb, metadata_req,
grpc_schedule_on_exec_ctx),
GRPC_CLOSURE_INIT(&http_get_cb_closure_, response_cb,
metadata_req, grpc_schedule_on_exec_ctx),
&metadata_req->response);
grpc_resource_quota_unref_internal(resource_quota);
}
private:
grpc_closure http_get_cb_closure_;
};
} // namespace
@ -401,8 +419,9 @@ void grpc_google_refresh_token_credentials::fetch_oauth2(
grpc_credentials_metadata_request* metadata_req,
grpc_httpcli_context* httpcli_context, grpc_polling_entity* pollent,
grpc_iomgr_cb_func response_cb, grpc_millis deadline) {
grpc_http_header header = {(char*)"Content-Type",
(char*)"application/x-www-form-urlencoded"};
grpc_http_header header = {
const_cast<char*>("Content-Type"),
const_cast<char*>("application/x-www-form-urlencoded")};
grpc_httpcli_request request;
char* body = nullptr;
gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
@ -419,11 +438,11 @@ void grpc_google_refresh_token_credentials::fetch_oauth2(
extreme memory pressure. */
grpc_resource_quota* resource_quota =
grpc_resource_quota_create("oauth2_credentials_refresh");
grpc_httpcli_post(
httpcli_context, pollent, resource_quota, &request, body, strlen(body),
deadline,
GRPC_CLOSURE_CREATE(response_cb, metadata_req, grpc_schedule_on_exec_ctx),
&metadata_req->response);
grpc_httpcli_post(httpcli_context, pollent, resource_quota, &request, body,
strlen(body), deadline,
GRPC_CLOSURE_INIT(&http_post_cb_closure_, response_cb,
metadata_req, grpc_schedule_on_exec_ctx),
&metadata_req->response);
grpc_resource_quota_unref_internal(resource_quota);
gpr_free(body);
}
@ -472,6 +491,207 @@ grpc_call_credentials* grpc_google_refresh_token_credentials_create(
.release();
}
//
// STS credentials.
//
namespace grpc_core {
namespace {
void MaybeAddToBody(gpr_strvec* body_strvec, const char* field_name,
const char* field) {
if (field == nullptr || strlen(field) == 0) return;
char* new_query;
gpr_asprintf(&new_query, "&%s=%s", field_name, field);
gpr_strvec_add(body_strvec, new_query);
}
grpc_error* LoadTokenFile(const char* path, gpr_slice* token) {
grpc_error* err = grpc_load_file(path, 1, token);
if (err != GRPC_ERROR_NONE) return err;
if (GRPC_SLICE_LENGTH(*token) == 0) {
gpr_log(GPR_ERROR, "Token file %s is empty", path);
err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Token file is empty.");
}
return err;
}
class StsTokenFetcherCredentials
: public grpc_oauth2_token_fetcher_credentials {
public:
StsTokenFetcherCredentials(grpc_uri* sts_url, // Ownership transfered.
const grpc_sts_credentials_options* options)
: sts_url_(sts_url),
resource_(gpr_strdup(options->resource)),
audience_(gpr_strdup(options->audience)),
scope_(gpr_strdup(options->scope)),
requested_token_type_(gpr_strdup(options->requested_token_type)),
subject_token_path_(gpr_strdup(options->subject_token_path)),
subject_token_type_(gpr_strdup(options->subject_token_type)),
actor_token_path_(gpr_strdup(options->actor_token_path)),
actor_token_type_(gpr_strdup(options->actor_token_type)) {}
~StsTokenFetcherCredentials() override { grpc_uri_destroy(sts_url_); }
private:
void fetch_oauth2(grpc_credentials_metadata_request* metadata_req,
grpc_httpcli_context* http_context,
grpc_polling_entity* pollent,
grpc_iomgr_cb_func response_cb,
grpc_millis deadline) override {
char* body = nullptr;
size_t body_length = 0;
grpc_error* err = FillBody(&body, &body_length);
if (err != GRPC_ERROR_NONE) {
response_cb(metadata_req, err);
GRPC_ERROR_UNREF(err);
return;
}
grpc_http_header header = {
const_cast<char*>("Content-Type"),
const_cast<char*>("application/x-www-form-urlencoded")};
grpc_httpcli_request request;
memset(&request, 0, sizeof(grpc_httpcli_request));
request.host = (char*)sts_url_->authority;
request.http.path = (char*)sts_url_->path;
request.http.hdr_count = 1;
request.http.hdrs = &header;
request.handshaker = (strcmp(sts_url_->scheme, "https") == 0)
? &grpc_httpcli_ssl
: &grpc_httpcli_plaintext;
/* TODO(ctiller): Carry the resource_quota in ctx and share it with the host
channel. This would allow us to cancel an authentication query when under
extreme memory pressure. */
grpc_resource_quota* resource_quota =
grpc_resource_quota_create("oauth2_credentials_refresh");
grpc_httpcli_post(
http_context, pollent, resource_quota, &request, body, body_length,
deadline,
GRPC_CLOSURE_INIT(&http_post_cb_closure_, response_cb, metadata_req,
grpc_schedule_on_exec_ctx),
&metadata_req->response);
grpc_resource_quota_unref_internal(resource_quota);
gpr_free(body);
}
grpc_error* FillBody(char** body, size_t* body_length) {
*body = nullptr;
gpr_strvec body_strvec;
gpr_strvec_init(&body_strvec);
grpc_slice subject_token = grpc_empty_slice();
grpc_slice actor_token = grpc_empty_slice();
grpc_error* err = GRPC_ERROR_NONE;
auto cleanup = [&body, &body_length, &body_strvec, &subject_token,
&actor_token, &err]() {
if (err == GRPC_ERROR_NONE) {
*body = gpr_strvec_flatten(&body_strvec, body_length);
} else {
gpr_free(*body);
}
gpr_strvec_destroy(&body_strvec);
grpc_slice_unref_internal(subject_token);
grpc_slice_unref_internal(actor_token);
return err;
};
err = LoadTokenFile(subject_token_path_.get(), &subject_token);
if (err != GRPC_ERROR_NONE) return cleanup();
gpr_asprintf(
body, GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING,
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(subject_token)),
subject_token_type_.get());
gpr_strvec_add(&body_strvec, *body);
MaybeAddToBody(&body_strvec, "resource", resource_.get());
MaybeAddToBody(&body_strvec, "audience", audience_.get());
MaybeAddToBody(&body_strvec, "scope", scope_.get());
MaybeAddToBody(&body_strvec, "requested_token_type",
requested_token_type_.get());
if (actor_token_path_ != nullptr) {
err = LoadTokenFile(actor_token_path_.get(), &actor_token);
if (err != GRPC_ERROR_NONE) return cleanup();
MaybeAddToBody(
&body_strvec, "actor_token",
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(subject_token)));
MaybeAddToBody(&body_strvec, "actor_token_type", actor_token_type_.get());
}
return cleanup();
}
grpc_uri* sts_url_;
grpc_closure http_post_cb_closure_;
grpc_core::UniquePtr<char> resource_;
grpc_core::UniquePtr<char> audience_;
grpc_core::UniquePtr<char> scope_;
grpc_core::UniquePtr<char> requested_token_type_;
grpc_core::UniquePtr<char> subject_token_path_;
grpc_core::UniquePtr<char> subject_token_type_;
grpc_core::UniquePtr<char> actor_token_path_;
grpc_core::UniquePtr<char> actor_token_type_;
};
} // namespace
grpc_error* ValidateStsCredentialsOptions(
const grpc_sts_credentials_options* options, grpc_uri** sts_url_out) {
struct GrpcUriDeleter {
void operator()(grpc_uri* uri) { grpc_uri_destroy(uri); }
};
*sts_url_out = nullptr;
InlinedVector<grpc_error*, 3> error_list;
UniquePtr<grpc_uri, GrpcUriDeleter> sts_url(
options->sts_endpoint_url != nullptr
? grpc_uri_parse(options->sts_endpoint_url, false)
: nullptr);
if (sts_url == nullptr) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Invalid or missing STS endpoint URL"));
} else {
if (strcmp(sts_url->scheme, "https") != 0 &&
strcmp(sts_url->scheme, "http") != 0) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Invalid URI scheme, must be https to http."));
}
}
if (options->subject_token_path == nullptr ||
strlen(options->subject_token_path) == 0) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"subject_token needs to be specified"));
}
if (options->subject_token_type == nullptr ||
strlen(options->subject_token_type) == 0) {
error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"subject_token_type needs to be specified"));
}
if (error_list.empty()) {
*sts_url_out = sts_url.release();
return GRPC_ERROR_NONE;
} else {
return GRPC_ERROR_CREATE_FROM_VECTOR("Invalid STS Credentials Options",
&error_list);
}
}
} // namespace grpc_core
grpc_call_credentials* grpc_sts_credentials_create(
const grpc_sts_credentials_options* options, void* reserved) {
GPR_ASSERT(reserved == nullptr);
grpc_uri* sts_url;
grpc_error* error =
grpc_core::ValidateStsCredentialsOptions(options, &sts_url);
if (error != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR, "STS Credentials creation failed. Error: %s.",
grpc_error_string(error));
GRPC_ERROR_UNREF(error);
return nullptr;
}
return grpc_core::MakeRefCounted<grpc_core::StsTokenFetcherCredentials>(
sts_url, options)
.release();
}
//
// Oauth2 Access Token credentials.
//

@ -21,8 +21,15 @@
#include <grpc/support/port_platform.h>
#include <grpc/grpc_security.h>
#include "src/core/lib/json/json.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/uri/uri_parser.h"
// Constants.
#define GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING \
"grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=%" \
"s&subject_token_type=%s"
// auth_refresh_token parsing.
typedef struct {
@ -115,6 +122,7 @@ class grpc_google_refresh_token_credentials final
private:
grpc_auth_refresh_token refresh_token_;
grpc_closure http_post_cb_closure_;
};
// Access token credentials.
@ -148,4 +156,12 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
const struct grpc_http_response* response, grpc_mdelem* token_md,
grpc_millis* token_lifetime);
namespace grpc_core {
// Exposed for testing only. This function validates the options, ensuring that
// the required fields are set, and outputs the parsed URL of the STS token
// exchanged service.
grpc_error* ValidateStsCredentialsOptions(
const grpc_sts_credentials_options* options, grpc_uri** sts_url);
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_OAUTH2_OAUTH2_CREDENTIALS_H */

@ -18,6 +18,7 @@
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/security/util/json_util.h"
#include <string.h>
@ -26,17 +27,27 @@
#include <grpc/support/string_util.h>
const char* grpc_json_get_string_property(const grpc_json* json,
const char* prop_name) {
grpc_json* child;
const char* prop_name,
grpc_error** error) {
grpc_json* child = nullptr;
if (error != nullptr) *error = GRPC_ERROR_NONE;
for (child = json->child; child != nullptr; child = child->next) {
if (child->key == nullptr) {
gpr_log(GPR_ERROR, "Invalid (null) JSON key encountered");
if (error != nullptr) {
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Invalid (null) JSON key encountered");
}
return nullptr;
}
if (strcmp(child->key, prop_name) == 0) break;
}
if (child == nullptr || child->type != GRPC_JSON_STRING) {
gpr_log(GPR_ERROR, "Invalid or missing %s property.", prop_name);
if (error != nullptr) {
char* error_msg;
gpr_asprintf(&error_msg, "Invalid or missing %s property.", prop_name);
*error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
gpr_free(error_msg);
}
return nullptr;
}
return child->value;
@ -45,7 +56,10 @@ const char* grpc_json_get_string_property(const grpc_json* json,
bool grpc_copy_json_string_property(const grpc_json* json,
const char* prop_name,
char** copied_value) {
const char* prop_value = grpc_json_get_string_property(json, prop_name);
grpc_error* error = GRPC_ERROR_NONE;
const char* prop_value =
grpc_json_get_string_property(json, prop_name, &error);
GRPC_LOG_IF_ERROR("Could not copy JSON property", error);
if (prop_value == nullptr) return false;
*copied_value = gpr_strdup(prop_value);
return true;

@ -23,6 +23,7 @@
#include <stdbool.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json.h"
// Constants.
@ -32,7 +33,8 @@
// Gets a child property from a json node.
const char* grpc_json_get_string_property(const grpc_json* json,
const char* prop_name);
const char* prop_name,
grpc_error** error);
// Copies the value of the json child property specified by prop_name.
// Returns false if the property was not found.

@ -348,10 +348,11 @@ inline void grpc_mdelem_unref(grpc_mdelem gmd) {
free an interned md at any time: it's unsafe from this point on to
access it so we read the hash now. */
uint32_t hash = md->hash();
if (GPR_UNLIKELY(md->Unref())) {
#ifndef NDEBUG
if (GPR_UNLIKELY(md->Unref(file, line))) {
grpc_mdelem_on_final_unref(storage, md, hash, file, line);
#else
if (GPR_UNLIKELY(md->Unref())) {
grpc_mdelem_on_final_unref(storage, md, hash);
#endif
}

@ -21,6 +21,7 @@
#include <memory>
#include <grpcpp/channel.h>
#include <grpcpp/impl/codegen/client_interceptor.h>
#include <grpcpp/support/config.h>

@ -15,13 +15,11 @@
* limitations under the License.
*
*/
#include <grpcpp/security/credentials.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpcpp/channel.h>
#include <grpcpp/security/credentials.h>
#include <grpcpp/support/channel_arguments.h>
#include <grpcpp/support/config.h>
#include "src/cpp/client/create_channel_internal.h"
@ -31,16 +29,16 @@ namespace grpc_impl {
namespace {
class InsecureChannelCredentialsImpl final : public ChannelCredentials {
public:
std::shared_ptr<::grpc::Channel> CreateChannelImpl(
const grpc::string& target, const grpc::ChannelArguments& args) override {
std::shared_ptr<Channel> CreateChannelImpl(
const grpc::string& target, const ChannelArguments& args) override {
return CreateChannelWithInterceptors(
target, args,
std::vector<std::unique_ptr<
grpc::experimental::ClientInterceptorFactoryInterface>>());
}
std::shared_ptr<::grpc::Channel> CreateChannelWithInterceptors(
const grpc::string& target, const grpc::ChannelArguments& args,
std::shared_ptr<Channel> CreateChannelWithInterceptors(
const grpc::string& target, const ChannelArguments& args,
std::vector<std::unique_ptr<
grpc::experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) override {

@ -36,17 +36,17 @@ SecureChannelCredentials::SecureChannelCredentials(
g_gli_initializer.summon();
}
std::shared_ptr<grpc::Channel> SecureChannelCredentials::CreateChannelImpl(
const grpc::string& target, const grpc::ChannelArguments& args) {
std::shared_ptr<Channel> SecureChannelCredentials::CreateChannelImpl(
const grpc::string& target, const ChannelArguments& args) {
return CreateChannelWithInterceptors(
target, args,
std::vector<std::unique_ptr<
grpc::experimental::ClientInterceptorFactoryInterface>>());
}
std::shared_ptr<grpc::Channel>
std::shared_ptr<Channel>
SecureChannelCredentials::CreateChannelWithInterceptors(
const grpc::string& target, const grpc::ChannelArguments& args,
const grpc::string& target, const ChannelArguments& args,
std::vector<
std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) {
@ -209,7 +209,7 @@ std::shared_ptr<CallCredentials> CompositeCallCredentials(
return nullptr;
}
std::shared_ptr<grpc_impl::CallCredentials> MetadataCredentialsFromPlugin(
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin> plugin) {
grpc::GrpcLibraryCodegen init; // To call grpc_init().
const char* type = plugin->GetType();

@ -39,14 +39,14 @@ class SecureChannelCredentials final : public ChannelCredentials {
}
grpc_channel_credentials* GetRawCreds() { return c_creds_; }
std::shared_ptr<::grpc::Channel> CreateChannelImpl(
const grpc::string& target, const grpc::ChannelArguments& args) override;
std::shared_ptr<Channel> CreateChannelImpl(
const grpc::string& target, const ChannelArguments& args) override;
SecureChannelCredentials* AsSecureCredentials() override { return this; }
private:
std::shared_ptr<::grpc::Channel> CreateChannelWithInterceptors(
const grpc::string& target, const grpc::ChannelArguments& args,
std::shared_ptr<Channel> CreateChannelWithInterceptors(
const grpc::string& target, const ChannelArguments& args,
std::vector<std::unique_ptr<
::grpc::experimental::ClientInterceptorFactoryInterface>>
interceptor_creators) override;

@ -19,10 +19,8 @@
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<PropertyGroup Condition="'$(OS)' != 'Windows_NT'">
<!-- Workaround for https://github.com/dotnet/sdk/issues/335 -->
<FrameworkPathOverride Condition="Exists('/usr/lib/mono/4.5-api')">/usr/lib/mono/4.5-api</FrameworkPathOverride>
<FrameworkPathOverride Condition="Exists('/usr/local/lib/mono/4.5-api')">/usr/local/lib/mono/4.5-api</FrameworkPathOverride>
<FrameworkPathOverride Condition="Exists('/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api')">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api</FrameworkPathOverride>
</PropertyGroup>
<!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
<ItemGroup>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0-preview.2" PrivateAssets="All" />
</ItemGroup>
</Project>

@ -7,13 +7,10 @@
<Import Project="..\Grpc.Core\SourceLink.csproj.include" />
<!-- This is copied verbatim from Grpc.Core/Common.csproj.include. Other settings
in that file conflict with the intent of this build, as it cannot be signed,
and may not compile Grpc.Core/Version.cs, as that file references constants
in Grpc.Core.dll.
TODO(kkm): Refactor imports. -->
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT' and '$(MSBuildRuntimeType)' == 'Core' ">
<!-- Use Mono reference assemblies in SDK build: https://github.com/dotnet/sdk/issues/335 -->
<!-- Use Mono reference assemblies in SDK build: https://github.com/dotnet/sdk/issues/335.
This is a different approach than used in Grpc.Core/Common.csproj.include because
the workaround used there doesn't seem to be working for Microsoft.Build.* assemblies -->
<FrameworkPathOverride Condition="Exists('/usr/lib/mono/4.5-api')">/usr/lib/mono/4.5-api</FrameworkPathOverride>
<FrameworkPathOverride Condition="Exists('/usr/local/lib/mono/4.5-api')">/usr/local/lib/mono/4.5-api</FrameworkPathOverride>
<FrameworkPathOverride Condition="Exists('/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api')">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api</FrameworkPathOverride>

@ -7,13 +7,10 @@
<TargetFrameworks>net45;netstandard1.3</TargetFrameworks>
</PropertyGroup>
<!-- This is copied verbatim from Grpc.Core/Common.csproj.include. Other settings
in that file conflict with the intent of this build, as it cannot be signed,
and may not compile Grpc.Core/Version.cs, as that file references constants
in Grpc.Core.dll.
TODO(kkm): Refactor imports. -->
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT' and '$(MSBuildRuntimeType)' == 'Core' ">
<!-- Use Mono reference assemblies in SDK build: https://github.com/dotnet/sdk/issues/335 -->
<!-- Use Mono reference assemblies in SDK build: https://github.com/dotnet/sdk/issues/335.
This is a different approach than used in Grpc.Core/Common.csproj.include because
the workaround used there doesn't seem to be working for Microsoft.Build.* assemblies -->
<FrameworkPathOverride Condition="Exists('/usr/lib/mono/4.5-api')">/usr/lib/mono/4.5-api</FrameworkPathOverride>
<FrameworkPathOverride Condition="Exists('/usr/local/lib/mono/4.5-api')">/usr/local/lib/mono/4.5-api</FrameworkPathOverride>
<FrameworkPathOverride Condition="Exists('/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api')">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api</FrameworkPathOverride>

@ -21,6 +21,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj" />
<!-- PrivateAssets set to None to ensure the build targets/props are propagated to parent project -->
<ProjectReference Include="../Grpc.Core/Grpc.Core.csproj" PrivateAssets="None" />
</ItemGroup>
</Project>

@ -44,12 +44,12 @@ cdef extern from "src/core/lib/iomgr/resolve_address_custom.h":
pass
struct grpc_custom_resolver_vtable:
grpc_error* (*resolve)(char* host, char* port, grpc_resolved_addresses** res) except *
void (*resolve_async)(grpc_custom_resolver* resolver, char* host, char* port) except *
grpc_error* (*resolve)(char* host, char* port, grpc_resolved_addresses** res);
void (*resolve_async)(grpc_custom_resolver* resolver, char* host, char* port);
void grpc_custom_resolve_callback(grpc_custom_resolver* resolver,
grpc_resolved_addresses* result,
grpc_error* error)
grpc_error* error);
cdef extern from "src/core/lib/iomgr/tcp_custom.h":
struct grpc_custom_socket:
@ -67,25 +67,25 @@ cdef extern from "src/core/lib/iomgr/tcp_custom.h":
ctypedef void (*grpc_custom_close_callback)(grpc_custom_socket* socket)
struct grpc_socket_vtable:
grpc_error* (*init)(grpc_custom_socket* socket, int domain) except *
grpc_error* (*init)(grpc_custom_socket* socket, int domain);
void (*connect)(grpc_custom_socket* socket, const grpc_sockaddr* addr,
size_t len, grpc_custom_connect_callback cb) except *
void (*destroy)(grpc_custom_socket* socket) except *
void (*shutdown)(grpc_custom_socket* socket) except *
void (*close)(grpc_custom_socket* socket, grpc_custom_close_callback cb) except *
size_t len, grpc_custom_connect_callback cb);
void (*destroy)(grpc_custom_socket* socket);
void (*shutdown)(grpc_custom_socket* socket);
void (*close)(grpc_custom_socket* socket, grpc_custom_close_callback cb);
void (*write)(grpc_custom_socket* socket, grpc_slice_buffer* slices,
grpc_custom_write_callback cb) except *
grpc_custom_write_callback cb);
void (*read)(grpc_custom_socket* socket, char* buffer, size_t length,
grpc_custom_read_callback cb) except *
grpc_custom_read_callback cb);
grpc_error* (*getpeername)(grpc_custom_socket* socket,
const grpc_sockaddr* addr, int* len) except *
const grpc_sockaddr* addr, int* len);
grpc_error* (*getsockname)(grpc_custom_socket* socket,
const grpc_sockaddr* addr, int* len) except *
const grpc_sockaddr* addr, int* len);
grpc_error* (*bind)(grpc_custom_socket* socket, const grpc_sockaddr* addr,
size_t len, int flags) except *
grpc_error* (*listen)(grpc_custom_socket* socket) except *
size_t len, int flags);
grpc_error* (*listen)(grpc_custom_socket* socket);
void (*accept)(grpc_custom_socket* socket, grpc_custom_socket* client,
grpc_custom_accept_callback cb) except *
grpc_custom_accept_callback cb);
cdef extern from "src/core/lib/iomgr/timer_custom.h":
struct grpc_custom_timer:
@ -94,17 +94,17 @@ cdef extern from "src/core/lib/iomgr/timer_custom.h":
# We don't care about the rest of the fields
struct grpc_custom_timer_vtable:
void (*start)(grpc_custom_timer* t) except *
void (*stop)(grpc_custom_timer* t) except *
void (*start)(grpc_custom_timer* t);
void (*stop)(grpc_custom_timer* t);
void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* error)
void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* error);
cdef extern from "src/core/lib/iomgr/pollset_custom.h":
struct grpc_custom_poller_vtable:
void (*init)() except *
void (*poll)(size_t timeout_ms) except *
void (*kick)() except *
void (*shutdown)() except *
void (*init)()
void (*poll)(size_t timeout_ms)
void (*kick)()
void (*shutdown)()
cdef extern from "src/core/lib/iomgr/iomgr_custom.h":
void grpc_custom_iomgr_init(grpc_socket_vtable* socket,

@ -56,7 +56,7 @@ cdef sockaddr_is_ipv4(const grpc_sockaddr* address, size_t length):
c_addr.len = length
return grpc_sockaddr_get_uri_scheme(&c_addr) == b'ipv4'
cdef grpc_resolved_addresses* tuples_to_resolvaddr(tups) except *:
cdef grpc_resolved_addresses* tuples_to_resolvaddr(tups):
cdef grpc_resolved_addresses* addresses
tups_set = set((tup[4][0], tup[4][1]) for tup in tups)
addresses = <grpc_resolved_addresses*> malloc(sizeof(grpc_resolved_addresses))
@ -84,7 +84,7 @@ cdef class SocketWrapper:
self.c_buffer = NULL
self.len = 0
cdef grpc_error* socket_init(grpc_custom_socket* socket, int domain) except * with gil:
cdef grpc_error* socket_init(grpc_custom_socket* socket, int domain) with gil:
sw = SocketWrapper()
sw.c_socket = socket
sw.sockopts = []
@ -112,7 +112,7 @@ def socket_connect_async(socket_wrapper, addr_tuple):
cdef void socket_connect(grpc_custom_socket* socket, const grpc_sockaddr* addr,
size_t addr_len,
grpc_custom_connect_callback cb) except * with gil:
grpc_custom_connect_callback cb) with gil:
py_socket = None
socket_wrapper = <SocketWrapper>socket.impl
socket_wrapper.connect_cb = cb
@ -125,10 +125,10 @@ cdef void socket_connect(grpc_custom_socket* socket, const grpc_sockaddr* addr,
socket_wrapper.socket = py_socket
_spawn_greenlet(socket_connect_async, socket_wrapper, addr_tuple)
cdef void socket_destroy(grpc_custom_socket* socket) except * with gil:
cdef void socket_destroy(grpc_custom_socket* socket) with gil:
cpython.Py_DECREF(<SocketWrapper>socket.impl)
cdef void socket_shutdown(grpc_custom_socket* socket) except * with gil:
cdef void socket_shutdown(grpc_custom_socket* socket) with gil:
try:
(<SocketWrapper>socket.impl).socket.shutdown(gevent_socket.SHUT_RDWR)
except IOError as io_error:
@ -136,7 +136,7 @@ cdef void socket_shutdown(grpc_custom_socket* socket) except * with gil:
raise io_error
cdef void socket_close(grpc_custom_socket* socket,
grpc_custom_close_callback cb) except * with gil:
grpc_custom_close_callback cb) with gil:
socket_wrapper = (<SocketWrapper>socket.impl)
if socket_wrapper.socket is not None:
socket_wrapper.socket.close()
@ -176,7 +176,7 @@ def socket_write_async(socket_wrapper, write_bytes):
socket_write_async_cython(socket_wrapper, write_bytes)
cdef void socket_write(grpc_custom_socket* socket, grpc_slice_buffer* buffer,
grpc_custom_write_callback cb) except * with gil:
grpc_custom_write_callback cb) with gil:
cdef char* start
sw = <SocketWrapper>socket.impl
sw.write_cb = cb
@ -204,7 +204,7 @@ def socket_read_async(socket_wrapper):
socket_read_async_cython(socket_wrapper)
cdef void socket_read(grpc_custom_socket* socket, char* buffer,
size_t length, grpc_custom_read_callback cb) except * with gil:
size_t length, grpc_custom_read_callback cb) with gil:
sw = <SocketWrapper>socket.impl
sw.read_cb = cb
sw.c_buffer = buffer
@ -213,7 +213,7 @@ cdef void socket_read(grpc_custom_socket* socket, char* buffer,
cdef grpc_error* socket_getpeername(grpc_custom_socket* socket,
const grpc_sockaddr* addr,
int* length) except * with gil:
int* length) with gil:
cdef char* src_buf
peer = (<SocketWrapper>socket.impl).socket.getpeername()
@ -226,7 +226,7 @@ cdef grpc_error* socket_getpeername(grpc_custom_socket* socket,
cdef grpc_error* socket_getsockname(grpc_custom_socket* socket,
const grpc_sockaddr* addr,
int* length) except * with gil:
int* length) with gil:
cdef char* src_buf
cdef grpc_resolved_address c_addr
if (<SocketWrapper>socket.impl).socket is None:
@ -245,7 +245,7 @@ def applysockopts(s):
cdef grpc_error* socket_bind(grpc_custom_socket* socket,
const grpc_sockaddr* addr,
size_t len, int flags) except * with gil:
size_t len, int flags) with gil:
addr_tuple = sockaddr_to_tuple(addr, len)
try:
try:
@ -262,7 +262,7 @@ cdef grpc_error* socket_bind(grpc_custom_socket* socket,
else:
return grpc_error_none()
cdef grpc_error* socket_listen(grpc_custom_socket* socket) except * with gil:
cdef grpc_error* socket_listen(grpc_custom_socket* socket) with gil:
(<SocketWrapper>socket.impl).socket.listen(50)
return grpc_error_none()
@ -292,7 +292,7 @@ def socket_accept_async(s):
accept_callback_cython(s)
cdef void socket_accept(grpc_custom_socket* socket, grpc_custom_socket* client,
grpc_custom_accept_callback cb) except * with gil:
grpc_custom_accept_callback cb) with gil:
sw = <SocketWrapper>socket.impl
sw.accepting_socket = client
sw.accept_cb = cb
@ -322,7 +322,7 @@ cdef socket_resolve_async_cython(ResolveWrapper resolve_wrapper):
def socket_resolve_async_python(resolve_wrapper):
socket_resolve_async_cython(resolve_wrapper)
cdef void socket_resolve_async(grpc_custom_resolver* r, char* host, char* port) except * with gil:
cdef void socket_resolve_async(grpc_custom_resolver* r, char* host, char* port) with gil:
rw = ResolveWrapper()
rw.c_resolver = r
rw.c_host = host
@ -330,7 +330,7 @@ cdef void socket_resolve_async(grpc_custom_resolver* r, char* host, char* port)
_spawn_greenlet(socket_resolve_async_python, rw)
cdef grpc_error* socket_resolve(char* host, char* port,
grpc_resolved_addresses** res) except * with gil:
grpc_resolved_addresses** res) with gil:
try:
result = gevent_socket.getaddrinfo(host, port)
res[0] = tuples_to_resolvaddr(result)
@ -360,13 +360,13 @@ cdef class TimerWrapper:
self.event.set()
self.timer.stop()
cdef void timer_start(grpc_custom_timer* t) except * with gil:
cdef void timer_start(grpc_custom_timer* t) with gil:
timer = TimerWrapper(t.timeout_ms / 1000.0)
timer.c_timer = t
t.timer = <void*>timer
timer.start()
cdef void timer_stop(grpc_custom_timer* t) except * with gil:
cdef void timer_stop(grpc_custom_timer* t) with gil:
time_wrapper = <object>t.timer
time_wrapper.stop()
@ -374,16 +374,16 @@ cdef void timer_stop(grpc_custom_timer* t) except * with gil:
### pollset implementation ###
###############################
cdef void init_loop() except * with gil:
cdef void init_loop() with gil:
pass
cdef void destroy_loop() except * with gil:
cdef void destroy_loop() with gil:
g_pool.join()
cdef void kick_loop() except * with gil:
cdef void kick_loop() with gil:
g_event.set()
cdef void run_loop(size_t timeout_ms) except * with gil:
cdef void run_loop(size_t timeout_ms) with gil:
timeout = timeout_ms / 1000.0
if timeout_ms > 0:
g_event.wait(timeout)

@ -134,6 +134,7 @@ grpc_service_account_jwt_access_credentials_create_type grpc_service_account_jwt
grpc_google_refresh_token_credentials_create_type grpc_google_refresh_token_credentials_create_import;
grpc_access_token_credentials_create_type grpc_access_token_credentials_create_import;
grpc_google_iam_credentials_create_type grpc_google_iam_credentials_create_import;
grpc_sts_credentials_create_type grpc_sts_credentials_create_import;
grpc_metadata_credentials_create_from_plugin_type grpc_metadata_credentials_create_from_plugin_import;
grpc_secure_channel_create_type grpc_secure_channel_create_import;
grpc_server_credentials_release_type grpc_server_credentials_release_import;
@ -404,6 +405,7 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_google_refresh_token_credentials_create_import = (grpc_google_refresh_token_credentials_create_type) GetProcAddress(library, "grpc_google_refresh_token_credentials_create");
grpc_access_token_credentials_create_import = (grpc_access_token_credentials_create_type) GetProcAddress(library, "grpc_access_token_credentials_create");
grpc_google_iam_credentials_create_import = (grpc_google_iam_credentials_create_type) GetProcAddress(library, "grpc_google_iam_credentials_create");
grpc_sts_credentials_create_import = (grpc_sts_credentials_create_type) GetProcAddress(library, "grpc_sts_credentials_create");
grpc_metadata_credentials_create_from_plugin_import = (grpc_metadata_credentials_create_from_plugin_type) GetProcAddress(library, "grpc_metadata_credentials_create_from_plugin");
grpc_secure_channel_create_import = (grpc_secure_channel_create_type) GetProcAddress(library, "grpc_secure_channel_create");
grpc_server_credentials_release_import = (grpc_server_credentials_release_type) GetProcAddress(library, "grpc_server_credentials_release");

@ -377,6 +377,9 @@ extern grpc_access_token_credentials_create_type grpc_access_token_credentials_c
typedef grpc_call_credentials*(*grpc_google_iam_credentials_create_type)(const char* authorization_token, const char* authority_selector, void* reserved);
extern grpc_google_iam_credentials_create_type grpc_google_iam_credentials_create_import;
#define grpc_google_iam_credentials_create grpc_google_iam_credentials_create_import
typedef grpc_call_credentials*(*grpc_sts_credentials_create_type)(const grpc_sts_credentials_options* options, void* reserved);
extern grpc_sts_credentials_create_type grpc_sts_credentials_create_import;
#define grpc_sts_credentials_create grpc_sts_credentials_create_import
typedef grpc_call_credentials*(*grpc_metadata_credentials_create_from_plugin_type)(grpc_metadata_credentials_plugin plugin, void* reserved);
extern grpc_metadata_credentials_create_from_plugin_type grpc_metadata_credentials_create_from_plugin_import;
#define grpc_metadata_credentials_create_from_plugin grpc_metadata_credentials_create_from_plugin_import

@ -24,8 +24,8 @@
#include <stdlib.h>
#include <string.h>
#include <grpc/grpc_security.h>
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@ -34,13 +34,16 @@
#include "src/core/lib/gpr/env.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/tmpfile.h"
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/security/credentials/composite/composite_credentials.h"
#include "src/core/lib/security/credentials/fake/fake_credentials.h"
#include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
#include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
#include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
#include "src/core/lib/security/transport/auth_filters.h"
#include "src/core/lib/uri/uri_parser.h"
#include "test/core/util/test_config.h"
using grpc_core::internal::grpc_flush_cached_google_default_credentials;
@ -99,15 +102,27 @@ static const char valid_oauth2_json_response[] =
" \"expires_in\":3599, "
" \"token_type\":\"Bearer\"}";
static const char valid_sts_json_response[] =
"{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
" \"expires_in\":3599, "
" \"issued_token_type\":\"urn:ietf:params:oauth:token-type:access_token\", "
" \"token_type\":\"Bearer\"}";
static const char test_scope[] = "perm1 perm2";
static const char test_signed_jwt[] =
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW"
"U0MDcyZTViYTdmZDkwODg2YzcifQ";
static const char test_signed_jwt_token_type[] =
"urn:ietf:params:oauth:token-type:id_token";
static const char test_signed_jwt_path_prefix[] = "test_sign_jwt";
static const char test_service_url[] = "https://foo.com/foo.v1";
static const char other_test_service_url[] = "https://bar.com/bar.v1";
static const char test_sts_endpoint_url[] =
"https://foo.com:5555/v1/token-exchange";
static const char test_method[] = "ThisIsNotAMethod";
/* -- Global state flags. -- */
@ -657,11 +672,11 @@ static int refresh_token_httpcli_post_success(
return 1;
}
static int refresh_token_httpcli_post_failure(
const grpc_httpcli_request* request, const char* body, size_t body_size,
grpc_millis deadline, grpc_closure* on_done,
grpc_httpcli_response* response) {
validate_refresh_token_http_request(request, body, body_size);
static int token_httpcli_post_failure(const grpc_httpcli_request* request,
const char* body, size_t body_size,
grpc_millis deadline,
grpc_closure* on_done,
grpc_httpcli_response* response) {
*response = http_response(403, "Not Authorized.");
GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
return 1;
@ -676,7 +691,7 @@ static void test_refresh_token_creds_success(void) {
grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
test_refresh_token_str, nullptr);
/* First request: http get should be called. */
/* First request: http put should be called. */
request_metadata_state* state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
@ -707,10 +722,279 @@ static void test_refresh_token_creds_failure(void) {
grpc_call_credentials* creds = grpc_google_refresh_token_credentials_create(
test_refresh_token_str, nullptr);
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
refresh_token_httpcli_post_failure);
token_httpcli_post_failure);
run_request_metadata_test(creds, auth_md_ctx, state);
creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
}
static void test_valid_sts_creds_options(void) {
grpc_sts_credentials_options valid_options = {
test_sts_endpoint_url, // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_uri* sts_url;
grpc_error* error =
grpc_core::ValidateStsCredentialsOptions(&valid_options, &sts_url);
GPR_ASSERT(error == GRPC_ERROR_NONE);
GPR_ASSERT(sts_url != nullptr);
grpc_core::StringView host;
grpc_core::StringView port;
GPR_ASSERT(grpc_core::SplitHostPort(sts_url->authority, &host, &port));
GPR_ASSERT(host.cmp("foo.com") == 0);
GPR_ASSERT(port.cmp("5555") == 0);
grpc_uri_destroy(sts_url);
}
static void test_invalid_sts_creds_options(void) {
grpc_sts_credentials_options invalid_options = {
test_sts_endpoint_url, // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
nullptr, // subject_token_path (Required)
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_uri* url_should_be_null;
grpc_error* error = grpc_core::ValidateStsCredentialsOptions(
&invalid_options, &url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
invalid_options = {
test_sts_endpoint_url, // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
nullptr, // subject_token_type (Required)
nullptr, // actor_token_path
nullptr // actor_token_type
};
error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
&url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
invalid_options = {
nullptr, // sts_endpoint_url (Required)
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
test_signed_jwt_token_type, // subject_token_type (Required)
nullptr, // actor_token_path
nullptr // actor_token_type
};
error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
&url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
invalid_options = {
"not_a_valid_uri", // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
test_signed_jwt_token_type, // subject_token_type (Required)
nullptr, // actor_token_path
nullptr // actor_token_type
};
error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
&url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
invalid_options = {
"ftp://ftp.is.not.a.valid.scheme/bar", // sts_endpoint_url
nullptr, // resource
nullptr, // audience
nullptr, // scope
nullptr, // requested_token_type
test_signed_jwt_path_prefix, // subject_token_path
test_signed_jwt_token_type, // subject_token_type (Required)
nullptr, // actor_token_path
nullptr // actor_token_type
};
error = grpc_core::ValidateStsCredentialsOptions(&invalid_options,
&url_should_be_null);
GPR_ASSERT(error != GRPC_ERROR_NONE);
GRPC_ERROR_UNREF(error);
GPR_ASSERT(url_should_be_null == nullptr);
}
static void validate_sts_token_http_request(const grpc_httpcli_request* request,
const char* body,
size_t body_size) {
// Check that the body is constructed properly.
GPR_ASSERT(body != nullptr);
GPR_ASSERT(body_size != 0);
GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
char* get_url_equivalent;
gpr_asprintf(&get_url_equivalent, "%s?%s", test_sts_endpoint_url, body);
grpc_uri* url = grpc_uri_parse(get_url_equivalent, false);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "resource"), "resource") == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "audience"), "audience") == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "scope"), "scope") == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "requested_token_type"),
"requested_token_type") == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "subject_token"),
test_signed_jwt) == 0);
GPR_ASSERT(strcmp(grpc_uri_get_query_arg(url, "subject_token_type"),
test_signed_jwt_token_type) == 0);
GPR_ASSERT(grpc_uri_get_query_arg(url, "actor_token") == nullptr);
GPR_ASSERT(grpc_uri_get_query_arg(url, "actor_token_type") == nullptr);
grpc_uri_destroy(url);
gpr_free(get_url_equivalent);
// Check the rest of the request.
GPR_ASSERT(strcmp(request->host, "foo.com:5555") == 0);
GPR_ASSERT(strcmp(request->http.path, "/v1/token-exchange") == 0);
GPR_ASSERT(request->http.hdr_count == 1);
GPR_ASSERT(strcmp(request->http.hdrs[0].key, "Content-Type") == 0);
GPR_ASSERT(strcmp(request->http.hdrs[0].value,
"application/x-www-form-urlencoded") == 0);
}
static int sts_token_httpcli_post_success(const grpc_httpcli_request* request,
const char* body, size_t body_size,
grpc_millis deadline,
grpc_closure* on_done,
grpc_httpcli_response* response) {
validate_sts_token_http_request(request, body, body_size);
*response = http_response(200, valid_sts_json_response);
GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
return 1;
}
static char* write_tmp_jwt_file(void) {
char* path;
FILE* tmp = gpr_tmpfile(test_signed_jwt_path_prefix, &path);
GPR_ASSERT(path != nullptr);
GPR_ASSERT(tmp != nullptr);
size_t jwt_length = strlen(test_signed_jwt);
GPR_ASSERT(fwrite(test_signed_jwt, 1, jwt_length, tmp) == jwt_length);
fclose(tmp);
return path;
}
static void test_sts_creds_success(void) {
grpc_core::ExecCtx exec_ctx;
expected_md emd[] = {
{"authorization", "Bearer ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_"}};
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
nullptr, nullptr};
char* test_signed_jwt_path = write_tmp_jwt_file();
grpc_sts_credentials_options valid_options = {
test_sts_endpoint_url, // sts_endpoint_url
"resource", // resource
"audience", // audience
"scope", // scope
"requested_token_type", // requested_token_type
test_signed_jwt_path, // subject_token_path
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_call_credentials* creds =
grpc_sts_credentials_create(&valid_options, nullptr);
/* First request: http put should be called. */
request_metadata_state* state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
sts_token_httpcli_post_success);
run_request_metadata_test(creds, auth_md_ctx, state);
grpc_core::ExecCtx::Get()->Flush();
/* Second request: the cached token should be served directly. */
state =
make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd));
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
run_request_metadata_test(creds, auth_md_ctx, state);
grpc_core::ExecCtx::Get()->Flush();
creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
gpr_free(test_signed_jwt_path);
}
static void test_sts_creds_load_token_failure(void) {
grpc_core::ExecCtx exec_ctx;
request_metadata_state* state = make_request_metadata_state(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Error occurred when fetching oauth2 token."),
nullptr, 0);
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
nullptr, nullptr};
char* test_signed_jwt_path = write_tmp_jwt_file();
grpc_sts_credentials_options options = {
test_sts_endpoint_url, // sts_endpoint_url
"resource", // resource
"audience", // audience
"scope", // scope
"requested_token_type", // requested_token_type
"invalid_path", // subject_token_path
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_call_credentials* creds = grpc_sts_credentials_create(&options, nullptr);
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
httpcli_post_should_not_be_called);
run_request_metadata_test(creds, auth_md_ctx, state);
creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
gpr_free(test_signed_jwt_path);
}
static void test_sts_creds_http_failure(void) {
grpc_core::ExecCtx exec_ctx;
request_metadata_state* state = make_request_metadata_state(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Error occurred when fetching oauth2 token."),
nullptr, 0);
grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method,
nullptr, nullptr};
char* test_signed_jwt_path = write_tmp_jwt_file();
grpc_sts_credentials_options valid_options = {
test_sts_endpoint_url, // sts_endpoint_url
"resource", // resource
"audience", // audience
"scope", // scope
"requested_token_type", // requested_token_type
test_signed_jwt_path, // subject_token_path
test_signed_jwt_token_type, // subject_token_type
nullptr, // actor_token_path
nullptr // actor_token_type
};
grpc_call_credentials* creds =
grpc_sts_credentials_create(&valid_options, nullptr);
grpc_httpcli_set_override(httpcli_get_should_not_be_called,
token_httpcli_post_failure);
run_request_metadata_test(creds, auth_md_ctx, state);
creds->Unref();
grpc_httpcli_set_override(nullptr, nullptr);
gpr_free(test_signed_jwt_path);
}
static void validate_jwt_encode_and_sign_params(
@ -1288,6 +1572,11 @@ int main(int argc, char** argv) {
test_compute_engine_creds_failure();
test_refresh_token_creds_success();
test_refresh_token_creds_failure();
test_valid_sts_creds_options();
test_invalid_sts_creds_options();
test_sts_creds_success();
test_sts_creds_load_token_failure();
test_sts_creds_http_failure();
test_jwt_creds_lifetime();
test_jwt_creds_success();
test_jwt_creds_signing_failure();

@ -26,33 +26,82 @@
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/util/json_util.h"
#include "test/core/security/oauth2_utils.h"
#include "test/core/util/cmdline.h"
static grpc_sts_credentials_options sts_options_from_json(grpc_json* json) {
grpc_sts_credentials_options options;
memset(&options, 0, sizeof(options));
grpc_error* error = GRPC_ERROR_NONE;
options.sts_endpoint_url =
grpc_json_get_string_property(json, "sts_endpoint_url", &error);
GRPC_LOG_IF_ERROR("STS credentials parsing", error);
options.resource = grpc_json_get_string_property(json, "resource", nullptr);
options.audience = grpc_json_get_string_property(json, "audience", nullptr);
options.scope = grpc_json_get_string_property(json, "scope", nullptr);
options.requested_token_type =
grpc_json_get_string_property(json, "requested_token_type", nullptr);
options.subject_token_path =
grpc_json_get_string_property(json, "subject_token_path", &error);
GRPC_LOG_IF_ERROR("STS credentials parsing", error);
options.subject_token_type =
grpc_json_get_string_property(json, "subject_token_type", &error);
GRPC_LOG_IF_ERROR("STS credentials parsing", error);
options.actor_token_path =
grpc_json_get_string_property(json, "actor_token_path", nullptr);
options.actor_token_type =
grpc_json_get_string_property(json, "actor_token_type", nullptr);
return options;
}
static grpc_call_credentials* create_sts_creds(const char* json_file_path) {
grpc_slice sts_options_slice;
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"load_file", grpc_load_file(json_file_path, 1, &sts_options_slice)));
grpc_json* json = grpc_json_parse_string(
reinterpret_cast<char*>(GRPC_SLICE_START_PTR(sts_options_slice)));
if (json == nullptr) {
gpr_log(GPR_ERROR, "Invalid json");
return nullptr;
}
grpc_sts_credentials_options options = sts_options_from_json(json);
grpc_call_credentials* result =
grpc_sts_credentials_create(&options, nullptr);
grpc_json_destroy(json);
gpr_slice_unref(sts_options_slice);
return result;
}
static grpc_call_credentials* create_refresh_token_creds(
const char* json_refresh_token_file_path) {
grpc_slice refresh_token;
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"load_file",
grpc_load_file(json_refresh_token_file_path, 1, &refresh_token)));
return grpc_google_refresh_token_credentials_create(
grpc_call_credentials* result = grpc_google_refresh_token_credentials_create(
reinterpret_cast<const char*> GRPC_SLICE_START_PTR(refresh_token),
nullptr);
gpr_slice_unref(refresh_token);
return result;
}
int main(int argc, char** argv) {
grpc_call_credentials* creds = nullptr;
char* json_key_file_path = nullptr;
const char* json_sts_options_file_path = nullptr;
const char* json_refresh_token_file_path = nullptr;
char* token = nullptr;
int use_gce = 0;
char* scope = nullptr;
gpr_cmdline* cl = gpr_cmdline_create("fetch_oauth2");
gpr_cmdline_add_string(cl, "json_refresh_token",
"File path of the json refresh token.",
&json_refresh_token_file_path);
gpr_cmdline_add_string(cl, "json_sts_options",
"File path of the json sts options.",
&json_sts_options_file_path);
gpr_cmdline_add_flag(
cl, "gce",
"Get a token from the GCE metadata server (only works in GCE).",
@ -61,18 +110,20 @@ int main(int argc, char** argv) {
grpc_init();
if (json_key_file_path != nullptr &&
if (json_sts_options_file_path != nullptr &&
json_refresh_token_file_path != nullptr) {
gpr_log(GPR_ERROR,
"--json_key and --json_refresh_token are mutually exclusive.");
gpr_log(
GPR_ERROR,
"--json_sts_options and --json_refresh_token are mutually exclusive.");
exit(1);
}
if (use_gce) {
if (json_key_file_path != nullptr || scope != nullptr) {
if (json_sts_options_file_path != nullptr ||
json_refresh_token_file_path != nullptr) {
gpr_log(GPR_INFO,
"Ignoring json key and scope to get a token from the GCE "
"metadata server.");
"Ignoring json refresh token or sts options to get a token from "
"the GCE metadata server.");
}
creds = grpc_google_compute_engine_credentials_create(nullptr);
if (creds == nullptr) {
@ -88,8 +139,19 @@ int main(int argc, char** argv) {
json_refresh_token_file_path);
exit(1);
}
} else if (json_sts_options_file_path != nullptr) {
creds = create_sts_creds(json_sts_options_file_path);
if (creds == nullptr) {
gpr_log(GPR_ERROR,
"Could not create sts creds. %s does probably not contain a "
"valid json for sts options.",
json_sts_options_file_path);
exit(1);
}
} else {
gpr_log(GPR_ERROR, "Missing --gce or --json_refresh_token option.");
gpr_log(
GPR_ERROR,
"Missing --gce, --json_sts_options, or --json_refresh_token option.");
exit(1);
}
GPR_ASSERT(creds != nullptr);

@ -63,14 +63,17 @@ static void on_oauth2_response(void* arg, grpc_error* error) {
gpr_mu_unlock(request->mu);
}
static void do_nothing(void* unused, grpc_error* error) {}
static void destroy_after_shutdown(void* pollset, grpc_error* error) {
grpc_pollset_destroy(reinterpret_cast<grpc_pollset*>(pollset));
gpr_free(pollset);
}
char* grpc_test_fetch_oauth2_token_with_credentials(
grpc_call_credentials* creds) {
oauth2_request request;
memset(&request, 0, sizeof(request));
grpc_core::ExecCtx exec_ctx;
grpc_closure do_nothing_closure;
grpc_closure destroy_after_shutdown_closure;
grpc_auth_metadata_context null_ctx = {"", "", nullptr, nullptr};
grpc_pollset* pollset =
@ -79,8 +82,8 @@ char* grpc_test_fetch_oauth2_token_with_credentials(
request.pops = grpc_polling_entity_create_from_pollset(pollset);
request.is_done = false;
GRPC_CLOSURE_INIT(&do_nothing_closure, do_nothing, nullptr,
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&destroy_after_shutdown_closure, destroy_after_shutdown,
pollset, grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&request.closure, on_oauth2_response, &request,
grpc_schedule_on_exec_ctx);
@ -107,8 +110,6 @@ char* grpc_test_fetch_oauth2_token_with_credentials(
gpr_mu_unlock(request.mu);
grpc_pollset_shutdown(grpc_polling_entity_pollset(&request.pops),
&do_nothing_closure);
gpr_free(grpc_polling_entity_pollset(&request.pops));
&destroy_after_shutdown_closure);
return request.token;
}

@ -171,6 +171,7 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_google_refresh_token_credentials_create);
printf("%lx", (unsigned long) grpc_access_token_credentials_create);
printf("%lx", (unsigned long) grpc_google_iam_credentials_create);
printf("%lx", (unsigned long) grpc_sts_credentials_create);
printf("%lx", (unsigned long) grpc_metadata_credentials_create_from_plugin);
printf("%lx", (unsigned long) grpc_secure_channel_create);
printf("%lx", (unsigned long) grpc_server_credentials_release);

@ -31,10 +31,12 @@
#include <grpcpp/impl/codegen/async_stream.h>
#include <grpcpp/impl/codegen/async_unary_call.h>
#include <grpcpp/impl/codegen/client_callback.h>
#include <grpcpp/impl/codegen/client_context.h>
#include <grpcpp/impl/codegen/method_handler_impl.h>
#include <grpcpp/impl/codegen/proto_utils.h>
#include <grpcpp/impl/codegen/rpc_method.h>
#include <grpcpp/impl/codegen/server_callback.h>
#include <grpcpp/impl/codegen/server_context.h>
#include <grpcpp/impl/codegen/service_type.h>
#include <grpcpp/impl/codegen/status.h>
#include <grpcpp/impl/codegen/stub_options.h>

@ -21,6 +21,7 @@
#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpcpp/channel.h>
#include <grpcpp/resource_quota.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/server_builder.h>

@ -21,8 +21,10 @@
#include <memory>
#include <grpcpp/channel.h>
#include <grpcpp/impl/codegen/client_interceptor.h>
#include <grpcpp/security/credentials.h>
#include <grpcpp/support/channel_arguments.h>
namespace grpc_impl {
@ -37,31 +39,31 @@ typedef enum { INSECURE = 0, TLS, ALTS } transport_security;
} // namespace testing
std::shared_ptr<::grpc_impl::Channel> CreateTestChannel(
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, testing::transport_security security_type);
std::shared_ptr<::grpc_impl::Channel> CreateTestChannel(
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots);
std::shared_ptr<::grpc_impl::Channel> CreateTestChannel(
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds);
std::shared_ptr<::grpc_impl::Channel> CreateTestChannel(
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
testing::transport_security security_type, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds,
const ChannelArguments& args);
std::shared_ptr<::grpc_impl::Channel> CreateTestChannel(
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& cred_type,
const grpc::string& override_hostname, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds,
const ChannelArguments& args);
std::shared_ptr<::grpc_impl::Channel> CreateTestChannel(
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& credential_type,
const std::shared_ptr<CallCredentials>& creds);

@ -0,0 +1,46 @@
#!/bin/bash
# Copyright 2019 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -ex
cd `dirname $0`/../..
# get the version of protobuf in /third_party/protobuf
pushd third_party/protobuf
version1=$(git describe --tags | cut -f 1 -d'-')
v1=${version1:1}
popd
# get the version of protobuf in /src/objective-c/!ProtoCompiler.podspec
v2=$(cat src/objective-c/\!ProtoCompiler.podspec | egrep "v = " | cut -f 2 -d"'")
# get the version of protobuf in /src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
v3=$(cat src/objective-c/\!ProtoCompiler-gRPCPlugin.podspec | egrep 'dependency.*!ProtoCompiler' | cut -f 4 -d"'")
# compare and emit error
ret=0
if [ $v1 != $v2 ]; then
echo 'Protobuf version in src/objective-c/!ProtoCompiler.podspec does not match protobuf version in third_party/protobuf.'
ret=1
fi
if [ $v1 != $v3 ]; then
echo 'Protobuf version in src/objective-c/!ProtoCompiler-gRPCPlugin.podspec does not match protobuf version in third_party/protobuf.'
ret=1
fi
exit $ret

@ -930,6 +930,7 @@ include/grpcpp/channel.h \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \

@ -931,6 +931,7 @@ include/grpcpp/channel.h \
include/grpcpp/channel_impl.h \
include/grpcpp/client_context.h \
include/grpcpp/completion_queue.h \
include/grpcpp/completion_queue_impl.h \
include/grpcpp/create_channel.h \
include/grpcpp/create_channel_impl.h \
include/grpcpp/create_channel_posix.h \

@ -284,9 +284,9 @@ LANG_RELEASE_MATRIX = {
('v1.16.0', ReleaseInfo(testcases_file='php__v1.0.1')),
('v1.17.1', ReleaseInfo(testcases_file='php__v1.0.1')),
('v1.18.0', ReleaseInfo()),
# v1.19 and v1.20 were deliberately ommitted here because of an issue.
# See https://github.com/grpc/grpc/issues/18264
('v1.21.4', ReleaseInfo()),
# TODO:https://github.com/grpc/grpc/issues/18264
# Error in above issues needs to be resolved.
]),
'csharp':
OrderedDict([

@ -10381,6 +10381,7 @@
"include/grpcpp/channel_impl.h",
"include/grpcpp/client_context.h",
"include/grpcpp/completion_queue.h",
"include/grpcpp/completion_queue_impl.h",
"include/grpcpp/create_channel.h",
"include/grpcpp/create_channel_impl.h",
"include/grpcpp/create_channel_posix.h",
@ -10508,6 +10509,7 @@
"include/grpcpp/channel_impl.h",
"include/grpcpp/client_context.h",
"include/grpcpp/completion_queue.h",
"include/grpcpp/completion_queue_impl.h",
"include/grpcpp/create_channel.h",
"include/grpcpp/create_channel_impl.h",
"include/grpcpp/create_channel_posix.h",

@ -23,5 +23,6 @@
- script: tools/distrib/pylint_code.sh
- script: tools/distrib/yapf_code.sh
- script: tools/distrib/python/check_grpcio_tools.py
- script: tools/distrib/check_shadow_boringssl_symbol_list.sh
cpu_cost: 1000
- script: tools/distrib/check_shadow_boringssl_symbol_list.sh
- script: tools/distrib/check_protobuf_pod_version.sh

Loading…
Cancel
Save