Merge branch 'master' into unary_promotion_with_concurrent_poll

pull/602/head
David Klempner 10 years ago
commit 9869cd3c7a
  1. 53
      CONTRIBUTING.md
  2. 5
      INSTALL
  3. 601
      Makefile
  4. 35
      README.md
  5. 157
      build.json
  6. 5114
      etc/roots.pem
  7. 11
      examples/pubsub/main.cc
  8. 2
      examples/pubsub/publisher_test.cc
  9. 9
      examples/pubsub/pubsub.proto
  10. 15
      include/grpc/grpc_security.h
  11. 5
      include/grpc/support/host_port.h
  12. 330
      src/compiler/python_generator.cc
  13. 51
      src/compiler/python_generator.h
  14. 87
      src/compiler/python_plugin.cc
  15. 5
      src/compiler/ruby_generator_map-inl.h
  16. 9
      src/core/README.md
  17. 14
      src/core/channel/channel_stack.h
  18. 29
      src/core/channel/client_setup.c
  19. 6
      src/core/channel/client_setup.h
  20. 110
      src/core/debug/trace.c
  21. 60
      src/core/debug/trace.h
  22. 12
      src/core/httpcli/httpcli.c
  23. 87
      src/core/iomgr/fd_posix.c
  24. 14
      src/core/iomgr/fd_posix.h
  25. 4
      src/core/iomgr/pollset_multipoller_with_poll_posix.c
  26. 8
      src/core/iomgr/pollset_posix.c
  27. 69
      src/core/iomgr/resolve_address_posix.c
  28. 166
      src/core/iomgr/resolve_address_windows.c
  29. 7
      src/core/iomgr/tcp_client_posix.c
  30. 5
      src/core/iomgr/tcp_client_windows.c
  31. 54
      src/core/iomgr/tcp_posix.c
  32. 7
      src/core/iomgr/tcp_server_posix.c
  33. 5
      src/core/iomgr/tcp_server_windows.c
  34. 32
      src/core/security/auth.c
  35. 164
      src/core/security/credentials.c
  36. 3
      src/core/security/credentials.h
  37. 11277
      src/core/security/google_root_certs.c
  38. 43
      src/core/security/json_token.c
  39. 13
      src/core/security/json_token.h
  40. 2183
      src/core/security/roots.pem
  41. 35
      src/core/security/secure_endpoint.c
  42. 20
      src/core/security/security_context.c
  43. 8
      src/core/security/security_context.h
  44. 2
      src/core/support/cpu_posix.c
  45. 2
      src/core/support/cpu_windows.c
  46. 58
      src/core/support/host_port.c
  47. 9
      src/core/surface/call.c
  48. 5
      src/core/surface/channel_create.c
  49. 6
      src/core/surface/init.c
  50. 5
      src/core/surface/secure_channel_create.c
  51. 2
      src/core/surface/server.c
  52. 13
      src/core/surface/surface_trace.h
  53. 2
      src/core/transport/chttp2/frame_data.c
  54. 6
      src/core/transport/chttp2_transport.c
  55. 2
      src/core/tsi/ssl_transport_security.c
  56. 9
      src/cpp/README.md
  57. 156
      src/cpp/server/server.cc
  58. 1
      src/csharp/EXPERIMENTAL-ONLY
  59. 0
      src/csharp/Grpc.Core.Tests/.gitignore
  60. 14
      src/csharp/Grpc.Core.Tests/ClientServerTest.cs
  61. 8
      src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
  62. 6
      src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
  63. 6
      src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
  64. 10
      src/csharp/Grpc.Core.Tests/ServerTest.cs
  65. 6
      src/csharp/Grpc.Core.Tests/TestResult.xml
  66. 6
      src/csharp/Grpc.Core.Tests/TimespecTest.cs
  67. 0
      src/csharp/Grpc.Core.Tests/packages.config
  68. 0
      src/csharp/Grpc.Core/.gitignore
  69. 4
      src/csharp/Grpc.Core/Call.cs
  70. 4
      src/csharp/Grpc.Core/Calls.cs
  71. 4
      src/csharp/Grpc.Core/Channel.cs
  72. 2
      src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs
  73. 4
      src/csharp/Grpc.Core/Grpc.Core.csproj
  74. 23
      src/csharp/Grpc.Core/Grpc.Core.nuspec
  75. 4
      src/csharp/Grpc.Core/GrpcEnvironment.cs
  76. 14
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  77. 4
      src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs
  78. 6
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  79. 2
      src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
  80. 4
      src/csharp/Grpc.Core/Internal/ClientStreamingInputObserver.cs
  81. 2
      src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
  82. 2
      src/csharp/Grpc.Core/Internal/Enums.cs
  83. 6
      src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
  84. 2
      src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs
  85. 6
      src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
  86. 6
      src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs
  87. 2
      src/csharp/Grpc.Core/Internal/Timespec.cs
  88. 2
      src/csharp/Grpc.Core/Marshaller.cs
  89. 2
      src/csharp/Grpc.Core/Method.cs
  90. 8
      src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
  91. 2
      src/csharp/Grpc.Core/RpcException.cs
  92. 10
      src/csharp/Grpc.Core/Server.cs
  93. 6
      src/csharp/Grpc.Core/ServerCallHandler.cs
  94. 2
      src/csharp/Grpc.Core/ServerCalls.cs
  95. 2
      src/csharp/Grpc.Core/ServerServiceDefinition.cs
  96. 2
      src/csharp/Grpc.Core/Status.cs
  97. 40
      src/csharp/Grpc.Core/StatusCode.cs
  98. 4
      src/csharp/Grpc.Core/Utils/RecordingObserver.cs
  99. 2
      src/csharp/Grpc.Core/Utils/RecordingQueue.cs
  100. 0
      src/csharp/Grpc.Examples.MathClient/.gitignore
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,53 @@
# How to contribute
We definitely welcome patches and contribution to grpc! Here is some guideline
and information about how to do so.
## Getting started
### Legal requirements
In order to protect both you and ourselves, you will need to sign the
[Contributor License Agreement](https://cla.developers.google.com/clas).
### Technical requirements
You will need several tools to work with this repository. In addition to all of
the packages described in the [INSTALL](INSTALL) file, you will also need
python, and the mako template renderer. To install the latter, using pip, one
should simply be able to do `pip install mako`.
In order to run all of the tests we provide, you will need valgrind and clang.
More specifically, under debian, you will need the package libc++-dev to
properly run all the tests.
If you are planning to work on any of the languages other than C and C++, you
will also need their appropriate development environments.
If you want to work under Windows, we recommend you to use Visual Studio 2013.
The [Community or Express editions](http://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx)
are free and suitable for developing with grpc. Note however that our test
environment and tools are available for Unix environments only at the moment.
## Testing your changes
We provide a tool to help you run our suite of tests in various environments.
In order to run most of the available tests, one would need to run:
`./tools/run_tests/run_tests.py`
If you want to run all the possible tests for all possible languages, do this:
`./tools/run_tests/run_tests.py -lall -call`
## Adding or removing source code
Each language uses its own build system to work. Currently, the root's Makefile
and the Visual Studio project files are building the C and C++ source code only
at the moment. In order to ease the maintenance of these files, we have a
template system. Please do not contribute manual changes to any of the generated
files. Instead, modify the template files, or the build.json file, and
re-generate the project files using the following command:
`./tools/buildgen/generate_projects.sh`

@ -23,6 +23,11 @@ Building the python wrapper requires the following:
# apt-get install python-all-dev python-virtualenv # apt-get install python-all-dev python-virtualenv
If you want to install in a different directory than the default /usr/lib, you can
override it on the command line:
# make install prefix=/opt
******************************* *******************************
* More detailled instructions * * More detailled instructions *

File diff suppressed because one or more lines are too long

@ -7,6 +7,39 @@ Copyright 2015 Google Inc.
See grpc/INSTALL for installation instructions for various platforms. See grpc/INSTALL for installation instructions for various platforms.
#Repository Structure
This repository contains source code for gRPC libraries for multiple lanugages written on top
of shared C core library [src/core] (src/core).
* C++ source code: [src/cpp] (src/cpp)
* Python source code: [src/python] (src/python)
* Ruby source code: [src/ruby] (src/ruby)
* NodeJS source code: [src/node] (src/node)
* PHP source code: [src/php] (src/php)
* C# source code: [src/csharp] (src/csharp)
* Objective-C source code: [src/objective-c] (src/objective-c)
Java source code is in [grpc-java] (http://github.com/grpc/grpc-java) repository.
Go source code is in [grpc-go] (http://github.com/grpc/grpc-go) repository.
#Documentation
You can find more detailed documentation and examples in the [grpc-common repository](http://github.com/grpc/grpc-common).
#Current Status of libraries
Libraries in different languages are in different state of development. We are seeking contributions for all of these libraries.
* shared C core library [src/core] (src/core) : Early adopter ready - Alpha.
* C++ Library: [src/cpp] (src/cpp) : Early adopter ready - Alpha.
* Python Library: [src/python] (src/python) : Early adopter ready - Alpha.
* Ruby Library: [src/ruby] (src/ruby) : Early adopter ready - Alpha.
* NodeJS Library: [src/node] (src/node) : Early adopter ready - Alpha.
* PHP Library: [src/php] (src/php) : Pre-Alpha.
* C# Library: [src/csharp] (src/csharp) : Pre-Alpha.
* Objective-C Library: [src/objective-c] (src/objective-c): Pre-Alpha.
#Overview #Overview
@ -59,7 +92,7 @@ messages are delivered in the order they were sent.
#Protocol #Protocol
The gRPC protocol specifies the abstract requirements for communication between The [gRPC protocol](https://github.com/grpc/grpc-common/blob/master/PROTOCOL-HTTP2.md) specifies the abstract requirements for communication between
clients and servers. A concrete embedding over HTTP/2 completes the picture by clients and servers. A concrete embedding over HTTP/2 completes the picture by
fleshing out the details of each of the required operations. fleshing out the details of each of the required operations.

@ -32,10 +32,7 @@
"src/core/channel/noop_filter.h", "src/core/channel/noop_filter.h",
"src/core/compression/algorithm.h", "src/core/compression/algorithm.h",
"src/core/compression/message_compress.h", "src/core/compression/message_compress.h",
"src/core/httpcli/format_request.h", "src/core/debug/trace.h",
"src/core/httpcli/httpcli.h",
"src/core/httpcli/httpcli_security_context.h",
"src/core/httpcli/parser.h",
"src/core/iomgr/alarm.h", "src/core/iomgr/alarm.h",
"src/core/iomgr/alarm_heap.h", "src/core/iomgr/alarm_heap.h",
"src/core/iomgr/alarm_internal.h", "src/core/iomgr/alarm_internal.h",
@ -124,10 +121,7 @@
"src/core/channel/noop_filter.c", "src/core/channel/noop_filter.c",
"src/core/compression/algorithm.c", "src/core/compression/algorithm.c",
"src/core/compression/message_compress.c", "src/core/compression/message_compress.c",
"src/core/httpcli/format_request.c", "src/core/debug/trace.c",
"src/core/httpcli/httpcli.c",
"src/core/httpcli/httpcli_security_context.c",
"src/core/httpcli/parser.c",
"src/core/iomgr/alarm.c", "src/core/iomgr/alarm.c",
"src/core/iomgr/alarm_heap.c", "src/core/iomgr/alarm_heap.c",
"src/core/iomgr/endpoint.c", "src/core/iomgr/endpoint.c",
@ -142,7 +136,8 @@
"src/core/iomgr/pollset_multipoller_with_poll_posix.c", "src/core/iomgr/pollset_multipoller_with_poll_posix.c",
"src/core/iomgr/pollset_posix.c", "src/core/iomgr/pollset_posix.c",
"src/core/iomgr/pollset_windows.c", "src/core/iomgr/pollset_windows.c",
"src/core/iomgr/resolve_address.c", "src/core/iomgr/resolve_address_posix.c",
"src/core/iomgr/resolve_address_windows.c",
"src/core/iomgr/sockaddr_utils.c", "src/core/iomgr/sockaddr_utils.c",
"src/core/iomgr/socket_utils_common_posix.c", "src/core/iomgr/socket_utils_common_posix.c",
"src/core/iomgr/socket_utils_linux.c", "src/core/iomgr/socket_utils_linux.c",
@ -182,8 +177,6 @@
"src/core/surface/init.c", "src/core/surface/init.c",
"src/core/surface/lame_client.c", "src/core/surface/lame_client.c",
"src/core/surface/metadata_array.c", "src/core/surface/metadata_array.c",
"src/core/surface/secure_channel_create.c",
"src/core/surface/secure_server_create.c",
"src/core/surface/server.c", "src/core/surface/server.c",
"src/core/surface/server_chttp2.c", "src/core/surface/server_chttp2.c",
"src/core/surface/server_create.c", "src/core/surface/server_create.c",
@ -239,7 +232,6 @@
"include/grpc/support/useful.h" "include/grpc/support/useful.h"
], ],
"headers": [ "headers": [
"src/core/support/cpu.h",
"src/core/support/env.h", "src/core/support/env.h",
"src/core/support/file.h", "src/core/support/file.h",
"src/core/support/murmur_hash.h", "src/core/support/murmur_hash.h",
@ -305,10 +297,13 @@
"include/grpc/grpc_security.h" "include/grpc/grpc_security.h"
], ],
"headers": [ "headers": [
"src/core/httpcli/format_request.h",
"src/core/httpcli/httpcli.h",
"src/core/httpcli/httpcli_security_context.h",
"src/core/httpcli/parser.h",
"src/core/security/auth.h", "src/core/security/auth.h",
"src/core/security/base64.h", "src/core/security/base64.h",
"src/core/security/credentials.h", "src/core/security/credentials.h",
"src/core/security/google_root_certs.h",
"src/core/security/json_token.h", "src/core/security/json_token.h",
"src/core/security/secure_transport_setup.h", "src/core/security/secure_transport_setup.h",
"src/core/security/security_context.h", "src/core/security/security_context.h",
@ -318,16 +313,21 @@
"src/core/tsi/transport_security_interface.h" "src/core/tsi/transport_security_interface.h"
], ],
"src": [ "src": [
"src/core/httpcli/format_request.c",
"src/core/httpcli/httpcli.c",
"src/core/httpcli/httpcli_security_context.c",
"src/core/httpcli/parser.c",
"src/core/security/auth.c", "src/core/security/auth.c",
"src/core/security/base64.c", "src/core/security/base64.c",
"src/core/security/credentials.c", "src/core/security/credentials.c",
"src/core/security/factories.c", "src/core/security/factories.c",
"src/core/security/google_root_certs.c",
"src/core/security/json_token.c", "src/core/security/json_token.c",
"src/core/security/secure_endpoint.c", "src/core/security/secure_endpoint.c",
"src/core/security/secure_transport_setup.c", "src/core/security/secure_transport_setup.c",
"src/core/security/security_context.c", "src/core/security/security_context.c",
"src/core/security/server_secure_chttp2.c", "src/core/security/server_secure_chttp2.c",
"src/core/surface/secure_channel_create.c",
"src/core/surface/secure_server_create.c",
"src/core/tsi/fake_transport_security.c", "src/core/tsi/fake_transport_security.c",
"src/core/tsi/ssl_transport_security.c", "src/core/tsi/ssl_transport_security.c",
"src/core/tsi/transport_security.c" "src/core/tsi/transport_security.c"
@ -342,26 +342,12 @@
"secure": true, "secure": true,
"vs_project_guid": "{29D16885-7228-4C31-81ED-5F9187C7F2A9}" "vs_project_guid": "{29D16885-7228-4C31-81ED-5F9187C7F2A9}"
}, },
{
"name": "grpc_csharp_ext",
"build": "all",
"language": "csharp",
"src": [
"src/csharp/ext/grpc_csharp_ext.c"
],
"deps": [
"gpr",
"grpc"
],
"vs_project_guid": "{D64C6D63-4458-4A88-AB38-35678384A7E4}"
},
{ {
"name": "grpc_test_util", "name": "grpc_test_util",
"build": "private", "build": "private",
"language": "c", "language": "c",
"src": [ "src": [
"test/core/end2end/cq_verifier.c", "test/core/end2end/cq_verifier.c",
"test/core/end2end/data/prod_roots_certs.c",
"test/core/end2end/data/server1_cert.c", "test/core/end2end/data/server1_cert.c",
"test/core/end2end/data/server1_key.c", "test/core/end2end/data/server1_key.c",
"test/core/end2end/data/test_root_cert.c", "test/core/end2end/data/test_root_cert.c",
@ -411,12 +397,15 @@
"include/grpc++/impl/internal_stub.h", "include/grpc++/impl/internal_stub.h",
"include/grpc++/impl/rpc_method.h", "include/grpc++/impl/rpc_method.h",
"include/grpc++/impl/rpc_service_method.h", "include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/server.h", "include/grpc++/server.h",
"include/grpc++/server_builder.h", "include/grpc++/server_builder.h",
"include/grpc++/server_context.h", "include/grpc++/server_context.h",
"include/grpc++/server_credentials.h", "include/grpc++/server_credentials.h",
"include/grpc++/status.h", "include/grpc++/status.h",
"include/grpc++/stream.h" "include/grpc++/status_code_enum.h",
"include/grpc++/stream.h",
"include/grpc++/thread_pool_interface.h"
], ],
"headers": [ "headers": [
"src/cpp/client/channel.h", "src/cpp/client/channel.h",
@ -445,6 +434,7 @@
"src/cpp/util/time.cc" "src/cpp/util/time.cc"
], ],
"deps": [ "deps": [
"gpr",
"grpc" "grpc"
], ],
"secure": true, "secure": true,
@ -477,6 +467,19 @@
"grpc", "grpc",
"gpr" "gpr"
] ]
},
{
"name": "grpc_csharp_ext",
"build": "all",
"language": "csharp",
"src": [
"src/csharp/ext/grpc_csharp_ext.c"
],
"deps": [
"gpr",
"grpc"
],
"vs_project_guid": "{D64C6D63-4458-4A88-AB38-35678384A7E4}"
} }
], ],
"targets": [ "targets": [
@ -1127,6 +1130,20 @@
"gpr" "gpr"
] ]
}, },
{
"name": "grpc_create_jwt",
"build": "tool",
"language": "c",
"src": [
"test/core/security/create_jwt.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{ {
"name": "grpc_credentials_test", "name": "grpc_credentials_test",
"build": "test", "build": "test",
@ -1242,6 +1259,7 @@
{ {
"name": "httpcli_test", "name": "httpcli_test",
"build": "test", "build": "test",
"run": false,
"language": "c", "language": "c",
"src": [ "src": [
"test/core/httpcli/httpcli_test.c" "test/core/httpcli/httpcli_test.c"
@ -1269,7 +1287,6 @@
{ {
"name": "json_rewrite_test", "name": "json_rewrite_test",
"build": "test", "build": "test",
"run": false,
"language": "c", "language": "c",
"src": [ "src": [
"test/core/json/json_rewrite_test.c" "test/core/json/json_rewrite_test.c"
@ -1574,21 +1591,6 @@
"gpr" "gpr"
] ]
}, },
{
"name": "cpp_plugin",
"build": "protoc",
"language": "c++",
"headers": [
"src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers.h"
],
"src": [
"src/compiler/cpp_generator.cc",
"src/compiler/cpp_plugin.cc"
],
"deps": [],
"secure": false
},
{ {
"name": "credentials_test", "name": "credentials_test",
"build": "test", "build": "test",
@ -1618,6 +1620,46 @@
"gpr" "gpr"
] ]
}, },
{
"name": "grpc_cpp_plugin",
"build": "protoc",
"language": "c++",
"headers": [
"src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers.h"
],
"src": [
"src/compiler/cpp_generator.cc",
"src/compiler/cpp_plugin.cc"
],
"deps": [],
"secure": false
},
{
"name": "grpc_python_plugin",
"build": "protoc",
"language": "c++",
"headers": [
"src/compiler/python_generator.h"
],
"src": [
"src/compiler/python_generator.cc",
"src/compiler/python_plugin.cc"
],
"deps": [],
"secure": false
},
{
"name": "grpc_ruby_plugin",
"build": "protoc",
"language": "c++",
"src": [
"src/compiler/ruby_generator.cc",
"src/compiler/ruby_plugin.cc"
],
"deps": [],
"secure": false
},
{ {
"name": "interop_client", "name": "interop_client",
"build": "test", "build": "test",
@ -1658,6 +1700,20 @@
"gpr" "gpr"
] ]
}, },
{
"name": "interop_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/interop/interop_test.cc"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{ {
"name": "pubsub_client", "name": "pubsub_client",
"build": "test", "build": "test",
@ -1746,17 +1802,6 @@
"gpr" "gpr"
] ]
}, },
{
"name": "ruby_plugin",
"build": "protoc",
"language": "c++",
"src": [
"src/compiler/ruby_generator.cc",
"src/compiler/ruby_plugin.cc"
],
"deps": [],
"secure": false
},
{ {
"name": "status_test", "name": "status_test",
"build": "test", "build": "test",

File diff suppressed because it is too large Load Diff

@ -40,7 +40,7 @@
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <google/gflags.h> #include <gflags/gflags.h>
#include <grpc++/channel_interface.h> #include <grpc++/channel_interface.h>
#include <grpc++/create_channel.h> #include <grpc++/create_channel.h>
#include <grpc++/credentials.h> #include <grpc++/credentials.h>
@ -60,6 +60,13 @@ DEFINE_string(oauth_scope,
"https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/cloud-platform",
"Scope for OAuth tokens."); "Scope for OAuth tokens.");
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google { }
namespace gflags { }
using namespace google;
using namespace gflags;
namespace { namespace {
const char kTopic[] = "testtopics"; const char kTopic[] = "testtopics";
@ -81,7 +88,7 @@ grpc::string GetServiceAccountJsonKey() {
int main(int argc, char** argv) { int main(int argc, char** argv) {
grpc_init(); grpc_init();
google::ParseCommandLineFlags(&argc, &argv, true); ParseCommandLineFlags(&argc, &argv, true);
gpr_log(GPR_INFO, "Start PUBSUB client"); gpr_log(GPR_INFO, "Start PUBSUB client");
std::ostringstream ss; std::ostringstream ss;

@ -138,7 +138,7 @@ TEST_F(PublisherTest, TestPublisher) {
std::vector<grpc::string> topics; std::vector<grpc::string> topics;
EXPECT_TRUE(publisher_->ListTopics(kProjectId, &topics).IsOk()); EXPECT_TRUE(publisher_->ListTopics(kProjectId, &topics).IsOk());
EXPECT_EQ(topics.size(), 1); EXPECT_EQ(topics.size(), static_cast<size_t>(1));
EXPECT_EQ(topics[0], kTopic); EXPECT_EQ(topics[0], kTopic);
} }

@ -157,9 +157,7 @@ package tech.pubsub;
// //
// Consuming messages via push: // Consuming messages via push:
// //
// TODO(eschapira): Add HTTP push example. // The port 'machinename:8888' must be bound to a server that implements
//
// The port 'machinename:8888' must be bound to a stubby server that implements
// the PushEndpointService with the following method: // the PushEndpointService with the following method:
// //
// int HandlePubsubEvent(PubsubEvent event) { // int HandlePubsubEvent(PubsubEvent event) {
@ -252,8 +250,6 @@ service PublisherService {
// Adds a message to the topic. Returns NOT_FOUND if the topic does not // Adds a message to the topic. Returns NOT_FOUND if the topic does not
// exist. // exist.
// (-- For different error code values returned via Stubby, see
// util/task/codes.proto. --)
rpc Publish(PublishRequest) returns (proto2.Empty) { rpc Publish(PublishRequest) returns (proto2.Empty) {
} }
@ -292,7 +288,6 @@ message PubsubMessage {
// Optional list of labels for this message. Keys in this collection must // Optional list of labels for this message. Keys in this collection must
// be unique. // be unique.
//(-- TODO(eschapira): Define how key namespace may be scoped to the topic.--)
repeated tech.label.Label label = 2; repeated tech.label.Label label = 2;
// ID of this message assigned by the server at publication time. Guaranteed // ID of this message assigned by the server at publication time. Guaranteed
@ -467,7 +462,7 @@ message Subscription {
// If <code>query</code> is non-empty, only messages on the subscriber's // If <code>query</code> is non-empty, only messages on the subscriber's
// topic whose labels match the query will be returned. Otherwise all // topic whose labels match the query will be returned. Otherwise all
// messages on the topic will be returned. // messages on the topic will be returned.
// (-- The query syntax is described in tech/label/proto/label_query.proto --) // (-- The query syntax is described in label_query.proto --)
optional string query = 3; optional string query = 3;
// The subscriber may specify requirements for truncating unacknowledged // The subscriber may specify requirements for truncating unacknowledged

@ -73,8 +73,11 @@ typedef struct {
/* Creates an SSL credentials object. /* Creates an SSL credentials object.
- pem_roots_cert is the NULL-terminated string containing the PEM encoding - pem_roots_cert is the NULL-terminated string containing the PEM encoding
of the server root certificates. If this parameter is NULL, the default of the server root certificates. If this parameter is NULL, the
roots will be used. implementation will first try to dereference the file pointed by the
GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment variable, and if that fails,
get the roots from a well-known place on disk (in the grpc install
directory).
- pem_key_cert_pair is a pointer on the object containing client's private - pem_key_cert_pair is a pointer on the object containing client's private
key and certificate chain. This parameter can be NULL if the client does key and certificate chain. This parameter can be NULL if the client does
not have such a key/cert pair. */ not have such a key/cert pair. */
@ -100,6 +103,14 @@ extern const gpr_timespec grpc_max_auth_token_lifetime;
grpc_credentials *grpc_service_account_credentials_create( grpc_credentials *grpc_service_account_credentials_create(
const char *json_key, const char *scope, gpr_timespec token_lifetime); const char *json_key, const char *scope, gpr_timespec token_lifetime);
/* Creates a JWT credentials object. May return NULL if the input is invalid.
- json_key is the JSON key string containing the client's private key.
- token_lifetime is the lifetime of each Json Web Token (JWT) created with
this credentials. It should not exceed grpc_max_auth_token_lifetime or
will be cropped to this value. */
grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
gpr_timespec token_lifetime);
/* Creates a fake transport security credentials object for testing. */ /* Creates a fake transport security credentials object for testing. */
grpc_credentials *grpc_fake_transport_security_credentials_create(void); grpc_credentials *grpc_fake_transport_security_credentials_create(void);

@ -50,6 +50,11 @@ extern "C" {
In the unlikely event of an error, returns -1 and sets *out to NULL. */ In the unlikely event of an error, returns -1 and sets *out to NULL. */
int gpr_join_host_port(char **out, const char *host, int port); int gpr_join_host_port(char **out, const char *host, int port);
/* Given a name in the form "host:port" or "[ho:st]:port", split into hostname
and port number, into newly allocated strings, which must later be
destroyed using gpr_free(). */
void gpr_split_host_port(const char *name, char **host, char **port);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -0,0 +1,330 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <cassert>
#include <cctype>
#include <map>
#include <ostream>
#include <sstream>
#include "src/compiler/python_generator.h"
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
using google::protobuf::FileDescriptor;
using google::protobuf::ServiceDescriptor;
using google::protobuf::MethodDescriptor;
using google::protobuf::io::Printer;
using google::protobuf::io::StringOutputStream;
using std::initializer_list;
using std::map;
using std::string;
namespace grpc_python_generator {
namespace {
//////////////////////////////////
// BEGIN FORMATTING BOILERPLATE //
//////////////////////////////////
// Converts an initializer list of the form { key0, value0, key1, value1, ... }
// into a map of key* to value*. Is merely a readability helper for later code.
map<string, string> ListToDict(const initializer_list<string>& values) {
assert(values.size() % 2 == 0);
map<string, string> value_map;
auto value_iter = values.begin();
for (unsigned i = 0; i < values.size()/2; ++i) {
string key = *value_iter;
++value_iter;
string value = *value_iter;
value_map[key] = value;
++value_iter;
}
return value_map;
}
// Provides RAII indentation handling. Use as:
// {
// IndentScope raii_my_indent_var_name_here(my_py_printer);
// // constructor indented my_py_printer
// ...
// // destructor called at end of scope, un-indenting my_py_printer
// }
class IndentScope {
public:
explicit IndentScope(Printer* printer) : printer_(printer) {
printer_->Indent();
}
~IndentScope() {
printer_->Outdent();
}
private:
Printer* printer_;
};
////////////////////////////////
// END FORMATTING BOILERPLATE //
////////////////////////////////
void PrintService(const ServiceDescriptor* service,
Printer* out) {
string doc = "<fill me in later!>";
map<string, string> dict = ListToDict({
"Service", service->name(),
"Documentation", doc,
});
out->Print(dict, "class $Service$Service(object):\n");
{
IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
out->Print("def __init__(self):\n");
{
IndentScope raii_method_indent(out);
out->Print("pass\n");
}
}
}
void PrintServicer(const ServiceDescriptor* service,
Printer* out) {
string doc = "<fill me in later!>";
map<string, string> dict = ListToDict({
"Service", service->name(),
"Documentation", doc,
});
out->Print(dict, "class $Service$Servicer(object):\n");
{
IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
for (int i = 0; i < service->method_count(); ++i) {
auto meth = service->method(i);
out->Print("def $Method$(self, arg):\n", "Method", meth->name());
{
IndentScope raii_method_indent(out);
out->Print("raise NotImplementedError()\n");
}
}
}
}
void PrintStub(const ServiceDescriptor* service,
Printer* out) {
string doc = "<fill me in later!>";
map<string, string> dict = ListToDict({
"Service", service->name(),
"Documentation", doc,
});
out->Print(dict, "class $Service$Stub(object):\n");
{
IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i);
auto methdict = ListToDict({"Method", meth->name()});
out->Print(methdict, "def $Method$(self, arg):\n");
{
IndentScope raii_method_indent(out);
out->Print("raise NotImplementedError()\n");
}
out->Print(methdict, "$Method$.async = None\n");
}
}
}
void PrintStubImpl(const ServiceDescriptor* service,
Printer* out) {
map<string, string> dict = ListToDict({
"Service", service->name(),
});
out->Print(dict, "class _$Service$Stub($Service$Stub):\n");
{
IndentScope raii_class_indent(out);
out->Print("def __init__(self, face_stub, default_timeout):\n");
{
IndentScope raii_method_indent(out);
out->Print("self._face_stub = face_stub\n"
"self._default_timeout = default_timeout\n"
"stub_self = self\n");
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i);
bool server_streaming = meth->server_streaming();
bool client_streaming = meth->client_streaming();
std::string blocking_call, future_call;
if (server_streaming) {
if (client_streaming) {
blocking_call = "stub_self._face_stub.inline_stream_in_stream_out";
future_call = blocking_call;
} else {
blocking_call = "stub_self._face_stub.inline_value_in_stream_out";
future_call = blocking_call;
}
} else {
if (client_streaming) {
blocking_call = "stub_self._face_stub.blocking_stream_in_value_out";
future_call = "stub_self._face_stub.future_stream_in_value_out";
} else {
blocking_call = "stub_self._face_stub.blocking_value_in_value_out";
future_call = "stub_self._face_stub.future_value_in_value_out";
}
}
// TODO(atash): use the solution described at
// http://stackoverflow.com/a/2982 to bind 'async' attribute
// functions to def'd functions instead of using callable attributes.
auto methdict = ListToDict({
"Method", meth->name(),
"BlockingCall", blocking_call,
"FutureCall", future_call
});
out->Print(methdict, "class $Method$(object):\n");
{
IndentScope raii_callable_indent(out);
out->Print("def __call__(self, arg):\n");
{
IndentScope raii_callable_call_indent(out);
out->Print(methdict,
"return $BlockingCall$(\"$Method$\", arg, "
"stub_self._default_timeout)\n");
}
out->Print("def async(self, arg):\n");
{
IndentScope raii_callable_async_indent(out);
out->Print(methdict,
"return $FutureCall$(\"$Method$\", arg, "
"stub_self._default_timeout)\n");
}
}
out->Print(methdict, "self.$Method$ = $Method$()\n");
}
}
}
}
void PrintStubGenerators(const ServiceDescriptor* service, Printer* out) {
map<string, string> dict = ListToDict({
"Service", service->name(),
});
// Write out a generator of linked pairs of Server/Stub
out->Print(dict, "def mock_$Service$(servicer, default_timeout):\n");
{
IndentScope raii_mock_indent(out);
out->Print("value_in_value_out = {}\n"
"value_in_stream_out = {}\n"
"stream_in_value_out = {}\n"
"stream_in_stream_out = {}\n");
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i);
std::string super_interface, meth_dict;
bool server_streaming = meth->server_streaming();
bool client_streaming = meth->client_streaming();
if (server_streaming) {
if (client_streaming) {
super_interface = "InlineStreamInStreamOutMethod";
meth_dict = "stream_in_stream_out";
} else {
super_interface = "InlineValueInStreamOutMethod";
meth_dict = "value_in_stream_out";
}
} else {
if (client_streaming) {
super_interface = "InlineStreamInValueOutMethod";
meth_dict = "stream_in_value_out";
} else {
super_interface = "InlineValueInValueOutMethod";
meth_dict = "value_in_value_out";
}
}
map<string, string> methdict = ListToDict({
"Method", meth->name(),
"SuperInterface", super_interface,
"MethodDict", meth_dict
});
out->Print(
methdict, "class $Method$(_face_interfaces.$SuperInterface$):\n");
{
IndentScope raii_inline_class_indent(out);
out->Print("def service(self, request, context):\n");
{
IndentScope raii_inline_class_fn_indent(out);
out->Print(methdict, "return servicer.$Method$(request)\n");
}
}
out->Print(methdict, "$MethodDict$['$Method$'] = $Method$()\n");
}
out->Print(
"face_linked_pair = _face_testing.server_and_stub(default_timeout,"
"inline_value_in_value_out_methods=value_in_value_out,"
"inline_value_in_stream_out_methods=value_in_stream_out,"
"inline_stream_in_value_out_methods=stream_in_value_out,"
"inline_stream_in_stream_out_methods=stream_in_stream_out)\n");
out->Print("class LinkedPair(object):\n");
{
IndentScope raii_linked_pair(out);
out->Print("def __init__(self, server, stub):\n");
{
IndentScope raii_linked_pair_init(out);
out->Print("self.server = server\n"
"self.stub = stub\n");
}
}
out->Print(
dict,
"stub = _$Service$Stub(face_linked_pair.stub, default_timeout)\n");
out->Print("return LinkedPair(None, stub)\n");
}
}
} // namespace
string GetServices(const FileDescriptor* file) {
string output;
StringOutputStream output_stream(&output);
Printer out(&output_stream, '$');
out.Print("from grpc.framework.face import demonstration as _face_testing\n");
out.Print("from grpc.framework.face import interfaces as _face_interfaces\n");
for (int i = 0; i < file->service_count(); ++i) {
auto service = file->service(i);
PrintService(service, &out);
PrintServicer(service, &out);
PrintStub(service, &out);
PrintStubImpl(service, &out);
PrintStubGenerators(service, &out);
}
return output;
}
} // namespace grpc_python_generator

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

@ -0,0 +1,87 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// Generates a Python gRPC service interface out of Protobuf IDL.
#include <memory>
#include <string>
#include "src/compiler/python_generator.h"
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.h>
using google::protobuf::FileDescriptor;
using google::protobuf::compiler::CodeGenerator;
using google::protobuf::compiler::GeneratorContext;
using google::protobuf::compiler::PluginMain;
using google::protobuf::io::CodedOutputStream;
using google::protobuf::io::ZeroCopyOutputStream;
using std::string;
class PythonGrpcGenerator : public CodeGenerator {
public:
PythonGrpcGenerator() {}
~PythonGrpcGenerator() override {}
bool Generate(const FileDescriptor* file,
const string& parameter,
GeneratorContext* context,
string* error) const override {
// Get output file name.
string file_name;
static const int proto_suffix_length = 6; // length of ".proto"
if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
file->name().find_last_of(".proto") == file->name().size() - 1) {
file_name = file->name().substr(
0, file->name().size() - proto_suffix_length) + "_pb2.py";
} else {
*error = "Invalid proto file name. Proto file must end with .proto";
return false;
}
std::unique_ptr<ZeroCopyOutputStream> output(
context->OpenForInsert(file_name, "module_scope"));
CodedOutputStream coded_out(output.get());
string code = grpc_python_generator::GetServices(file);
coded_out.WriteRaw(code.data(), code.size());
return true;
}
};
int main(int argc, char* argv[]) {
PythonGrpcGenerator generator;
return PluginMain(argc, argv, &generator);
}

@ -34,6 +34,7 @@
#ifndef NET_GRPC_COMPILER_RUBY_GENERATOR_MAP_INL_H_ #ifndef NET_GRPC_COMPILER_RUBY_GENERATOR_MAP_INL_H_
#define NET_GRPC_COMPILER_RUBY_GENERATOR_MAP_INL_H_ #define NET_GRPC_COMPILER_RUBY_GENERATOR_MAP_INL_H_
#include <iostream>
#include <initializer_list> #include <initializer_list>
#include <map> #include <map>
#include <ostream> // NOLINT #include <ostream> // NOLINT
@ -51,8 +52,8 @@ namespace grpc_ruby_generator {
inline std::map<std::string, std::string> ListToDict( inline std::map<std::string, std::string> ListToDict(
const initializer_list<std::string> &values) { const initializer_list<std::string> &values) {
if (values.size() % 2 != 0) { if (values.size() % 2 != 0) {
// MOE: insert std::cerr << "Not every 'key' has a value in `values`." std::cerr << "Not every 'key' has a value in `values`."
// << std::endl; << std::endl;
} }
std::map<std::string, std::string> value_map; std::map<std::string, std::string> value_map;
auto value_iter = values.begin(); auto value_iter = values.begin();

@ -0,0 +1,9 @@
#Overview
This directory contains source code for shared C library. Libraries in other languages in this repository (C++, Ruby,
Python, PHP, NodeJS, Objective-C) are layered on top of this library.
#Status
Alpha : Ready for early adopters

@ -45,10 +45,9 @@
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/debug/trace.h"
#include "src/core/transport/transport.h" #include "src/core/transport/transport.h"
/* #define GRPC_CHANNEL_STACK_TRACE 1 */
typedef struct grpc_channel_element grpc_channel_element; typedef struct grpc_channel_element grpc_channel_element;
typedef struct grpc_call_element grpc_call_element; typedef struct grpc_call_element grpc_call_element;
@ -246,9 +245,7 @@ typedef struct {
/* A call stack tracks a set of related filters for one call, and guarantees /* A call stack tracks a set of related filters for one call, and guarantees
they live within a single malloc() allocation */ they live within a single malloc() allocation */
typedef struct { typedef struct { size_t count; } grpc_call_stack;
size_t count;
} grpc_call_stack;
/* Get a channel element given a channel stack and its index */ /* Get a channel element given a channel stack and its index */
grpc_channel_element *grpc_channel_stack_element(grpc_channel_stack *stack, grpc_channel_element *grpc_channel_stack_element(grpc_channel_stack *stack,
@ -301,12 +298,7 @@ void grpc_call_element_recv_metadata(grpc_call_element *cur_elem,
void grpc_call_element_send_cancel(grpc_call_element *cur_elem); void grpc_call_element_send_cancel(grpc_call_element *cur_elem);
void grpc_call_element_send_finish(grpc_call_element *cur_elem); void grpc_call_element_send_finish(grpc_call_element *cur_elem);
#ifdef GRPC_CHANNEL_STACK_TRACE
#define GRPC_CALL_LOG_OP(sev, elem, op) grpc_call_log_op(sev, elem, op)
#else
#define GRPC_CALL_LOG_OP(sev, elem, op) \ #define GRPC_CALL_LOG_OP(sev, elem, op) \
do { \ if (grpc_trace_bits & GRPC_TRACE_CHANNEL) grpc_call_log_op(sev, elem, op)
} while (0)
#endif
#endif /* __GRPC_INTERNAL_CHANNEL_CHANNEL_STACK_H__ */ #endif /* __GRPC_INTERNAL_CHANNEL_CHANNEL_STACK_H__ */

@ -49,8 +49,11 @@ struct grpc_client_setup {
grpc_alarm backoff_alarm; grpc_alarm backoff_alarm;
gpr_timespec current_backoff_interval; gpr_timespec current_backoff_interval;
int in_alarm; int in_alarm;
int in_cb;
int cancelled;
gpr_mu mu; gpr_mu mu;
gpr_cv cv;
grpc_client_setup_request *active_request; grpc_client_setup_request *active_request;
int refs; int refs;
}; };
@ -67,6 +70,7 @@ gpr_timespec grpc_client_setup_request_deadline(grpc_client_setup_request *r) {
static void destroy_setup(grpc_client_setup *s) { static void destroy_setup(grpc_client_setup *s) {
gpr_mu_destroy(&s->mu); gpr_mu_destroy(&s->mu);
gpr_cv_destroy(&s->cv);
s->done(s->user_data); s->done(s->user_data);
grpc_channel_args_destroy(s->args); grpc_channel_args_destroy(s->args);
gpr_free(s); gpr_free(s);
@ -111,6 +115,10 @@ static void setup_cancel(grpc_transport_setup *sp) {
int cancel_alarm = 0; int cancel_alarm = 0;
gpr_mu_lock(&s->mu); gpr_mu_lock(&s->mu);
s->cancelled = 1;
while (s->in_cb) {
gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
}
GPR_ASSERT(s->refs > 0); GPR_ASSERT(s->refs > 0);
/* effectively cancels the current request (if any) */ /* effectively cancels the current request (if any) */
@ -129,6 +137,24 @@ static void setup_cancel(grpc_transport_setup *sp) {
} }
} }
int grpc_client_setup_cb_begin(grpc_client_setup_request *r) {
gpr_mu_lock(&r->setup->mu);
if (r->setup->cancelled) {
gpr_mu_unlock(&r->setup->mu);
return 0;
}
r->setup->in_cb++;
gpr_mu_unlock(&r->setup->mu);
return 1;
}
void grpc_client_setup_cb_end(grpc_client_setup_request *r) {
gpr_mu_lock(&r->setup->mu);
r->setup->in_cb--;
if (r->setup->cancelled) gpr_cv_signal(&r->setup->cv);
gpr_mu_unlock(&r->setup->mu);
}
/* vtable for transport setup */ /* vtable for transport setup */
static const grpc_transport_setup_vtable setup_vtable = {setup_initiate, static const grpc_transport_setup_vtable setup_vtable = {setup_initiate,
setup_cancel}; setup_cancel};
@ -142,6 +168,7 @@ void grpc_client_setup_create_and_attach(
s->base.vtable = &setup_vtable; s->base.vtable = &setup_vtable;
gpr_mu_init(&s->mu); gpr_mu_init(&s->mu);
gpr_cv_init(&s->cv);
s->refs = 1; s->refs = 1;
s->mdctx = mdctx; s->mdctx = mdctx;
s->initiate = initiate; s->initiate = initiate;
@ -151,6 +178,8 @@ void grpc_client_setup_create_and_attach(
s->args = grpc_channel_args_copy(args); s->args = grpc_channel_args_copy(args);
s->current_backoff_interval = gpr_time_from_micros(1000000); s->current_backoff_interval = gpr_time_from_micros(1000000);
s->in_alarm = 0; s->in_alarm = 0;
s->in_cb = 0;
s->cancelled = 0;
grpc_client_channel_set_transport_setup(newly_minted_channel, &s->base); grpc_client_channel_set_transport_setup(newly_minted_channel, &s->base);
} }

@ -58,6 +58,12 @@ void grpc_client_setup_request_finish(grpc_client_setup_request *r,
const grpc_channel_args *grpc_client_setup_get_channel_args( const grpc_channel_args *grpc_client_setup_get_channel_args(
grpc_client_setup_request *r); grpc_client_setup_request *r);
/* Call before calling back into the setup listener, and call only if
this function returns 1. If it returns 1, also promise to call
grpc_client_setup_cb_end */
int grpc_client_setup_cb_begin(grpc_client_setup_request *r);
void grpc_client_setup_cb_end(grpc_client_setup_request *r);
/* Get the deadline for a request passed in to initiate. Implementations should /* Get the deadline for a request passed in to initiate. Implementations should
make a best effort to honor this deadline. */ make a best effort to honor this deadline. */
gpr_timespec grpc_client_setup_request_deadline(grpc_client_setup_request *r); gpr_timespec grpc_client_setup_request_deadline(grpc_client_setup_request *r);

@ -0,0 +1,110 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/debug/trace.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/support/env.h"
#if GRPC_ENABLE_TRACING
gpr_uint32 grpc_trace_bits = 0;
static void add(const char *beg, const char *end, char ***ss, size_t *ns) {
size_t n = *ns;
size_t np = n + 1;
char *s = gpr_malloc(end - beg + 1);
memcpy(s, beg, end - beg);
s[end-beg] = 0;
*ss = gpr_realloc(*ss, sizeof(char**) * np);
(*ss)[n] = s;
*ns = np;
}
static void split(const char *s, char ***ss, size_t *ns) {
const char *c = strchr(s, ',');
if (c == NULL) {
add(s, s + strlen(s), ss, ns);
} else {
add(s, c, ss, ns);
split(c+1, ss, ns);
}
}
static void parse(const char *s) {
char **strings = NULL;
size_t nstrings = 0;
size_t i;
split(s, &strings, &nstrings);
grpc_trace_bits = 0;
for (i = 0; i < nstrings; i++) {
const char *s = strings[i];
if (0 == strcmp(s, "surface")) {
grpc_trace_bits |= GRPC_TRACE_SURFACE;
} else if (0 == strcmp(s, "channel")) {
grpc_trace_bits |= GRPC_TRACE_CHANNEL;
} else if (0 == strcmp(s, "tcp")) {
grpc_trace_bits |= GRPC_TRACE_TCP;
} else if (0 == strcmp(s, "secure_endpoint")) {
grpc_trace_bits |= GRPC_TRACE_SECURE_ENDPOINT;
} else if (0 == strcmp(s, "all")) {
grpc_trace_bits = -1;
} else {
gpr_log(GPR_ERROR, "Unknown trace var: '%s'", s);
}
}
for (i = 0; i < nstrings; i++) {
gpr_free(strings[i]);
}
gpr_free(strings);
}
void grpc_init_trace_bits() {
char *e = gpr_getenv("GRPC_TRACE");
if (e == NULL) {
grpc_trace_bits = 0;
} else {
parse(e);
gpr_free(e);
}
}
#else
void grpc_init_trace_bits() {
}
#endif

@ -0,0 +1,60 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_CORE_DEBUG_TRACE_H
#define GRPC_CORE_DEBUG_TRACE_H
#include <grpc/support/port_platform.h>
/* set to zero to remove all debug trace code */
#ifndef GRPC_ENABLE_TRACING
# define GRPC_ENABLE_TRACING 1
#endif
typedef enum {
GRPC_TRACE_SURFACE = 1 << 0,
GRPC_TRACE_CHANNEL = 1 << 1,
GRPC_TRACE_TCP = 1 << 2,
GRPC_TRACE_SECURE_ENDPOINT = 1 << 3
} grpc_trace_bit_value;
#if GRPC_ENABLE_TRACING
extern gpr_uint32 grpc_trace_bits;
#else
# define grpc_trace_bits 0
#endif
void grpc_init_trace_bits();
#endif

@ -43,7 +43,6 @@
#include "src/core/httpcli/httpcli_security_context.h" #include "src/core/httpcli/httpcli_security_context.h"
#include "src/core/httpcli/parser.h" #include "src/core/httpcli/parser.h"
#include "src/core/security/security_context.h" #include "src/core/security/security_context.h"
#include "src/core/security/google_root_certs.h"
#include "src/core/security/secure_transport_setup.h" #include "src/core/security/secure_transport_setup.h"
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
@ -182,9 +181,16 @@ static void on_connected(void *arg, grpc_endpoint *tcp) {
req->ep = tcp; req->ep = tcp;
if (req->use_ssl) { if (req->use_ssl) {
grpc_channel_security_context *ctx = NULL; grpc_channel_security_context *ctx = NULL;
const unsigned char *pem_root_certs = NULL;
size_t pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
if (pem_root_certs == NULL || pem_root_certs_size == 0) {
gpr_log(GPR_ERROR, "Could not get default pem root certs.");
finish(req, 0);
return;
}
GPR_ASSERT(grpc_httpcli_ssl_channel_security_context_create( GPR_ASSERT(grpc_httpcli_ssl_channel_security_context_create(
grpc_google_root_certs, grpc_google_root_certs_size, pem_root_certs, pem_root_certs_size, req->host, &ctx) ==
req->host, &ctx) == GRPC_SECURITY_OK); GRPC_SECURITY_OK);
grpc_setup_secure_transport(&ctx->base, tcp, on_secure_transport_setup_done, grpc_setup_secure_transport(&ctx->base, tcp, on_secure_transport_setup_done,
req); req);
grpc_security_context_unref(&ctx->base); grpc_security_context_unref(&ctx->base);

@ -45,7 +45,10 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
enum descriptor_state { NOT_READY, READY, WAITING }; enum descriptor_state {
NOT_READY = 0,
READY = 1
}; /* or a pointer to a closure to call */
/* We need to keep a freelist not because of any concerns of malloc performance /* We need to keep a freelist not because of any concerns of malloc performance
* but instead so that implementations with multiple threads in (for example) * but instead so that implementations with multiple threads in (for example)
@ -88,8 +91,8 @@ static grpc_fd *alloc_fd(int fd) {
gpr_mu_init(&r->watcher_mu); gpr_mu_init(&r->watcher_mu);
} }
gpr_atm_rel_store(&r->refst, 1); gpr_atm_rel_store(&r->refst, 1);
gpr_atm_rel_store(&r->readst.state, NOT_READY); gpr_atm_rel_store(&r->readst, NOT_READY);
gpr_atm_rel_store(&r->writest.state, NOT_READY); gpr_atm_rel_store(&r->writest, NOT_READY);
gpr_atm_rel_store(&r->shutdown, 0); gpr_atm_rel_store(&r->shutdown, 0);
r->fd = fd; r->fd = fd;
r->watcher_root.next = r->watcher_root.prev = &r->watcher_root; r->watcher_root.next = r->watcher_root.prev = &r->watcher_root;
@ -166,11 +169,6 @@ void grpc_fd_ref(grpc_fd *fd) { ref_by(fd, 2); }
void grpc_fd_unref(grpc_fd *fd) { unref_by(fd, 2); } void grpc_fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
typedef struct {
grpc_iomgr_cb_func cb;
void *arg;
} callback;
static void make_callback(grpc_iomgr_cb_func cb, void *arg, int success, static void make_callback(grpc_iomgr_cb_func cb, void *arg, int success,
int allow_synchronous_callback) { int allow_synchronous_callback) {
if (allow_synchronous_callback) { if (allow_synchronous_callback) {
@ -180,18 +178,18 @@ static void make_callback(grpc_iomgr_cb_func cb, void *arg, int success,
} }
} }
static void make_callbacks(callback *callbacks, size_t n, int success, static void make_callbacks(grpc_iomgr_closure *callbacks, size_t n, int success,
int allow_synchronous_callback) { int allow_synchronous_callback) {
size_t i; size_t i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
make_callback(callbacks[i].cb, callbacks[i].arg, success, make_callback(callbacks[i].cb, callbacks[i].cb_arg, success,
allow_synchronous_callback); allow_synchronous_callback);
} }
} }
static void notify_on(grpc_fd *fd, grpc_fd_state *st, grpc_iomgr_cb_func cb, static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure,
void *arg, int allow_synchronous_callback) { int allow_synchronous_callback) {
switch ((enum descriptor_state)gpr_atm_acq_load(&st->state)) { switch (gpr_atm_acq_load(st)) {
case NOT_READY: case NOT_READY:
/* There is no race if the descriptor is already ready, so we skip /* There is no race if the descriptor is already ready, so we skip
the interlocked op in that case. As long as the app doesn't the interlocked op in that case. As long as the app doesn't
@ -199,9 +197,7 @@ static void notify_on(grpc_fd *fd, grpc_fd_state *st, grpc_iomgr_cb_func cb,
oldval should never be anything other than READY or NOT_READY. We oldval should never be anything other than READY or NOT_READY. We
don't don't
check for user error on the fast path. */ check for user error on the fast path. */
st->cb = cb; if (gpr_atm_rel_cas(st, NOT_READY, (gpr_intptr)closure)) {
st->cb_arg = arg;
if (gpr_atm_rel_cas(&st->state, NOT_READY, WAITING)) {
/* swap was successful -- the closure will run after the next /* swap was successful -- the closure will run after the next
set_ready call. NOTE: we don't have an ABA problem here, set_ready call. NOTE: we don't have an ABA problem here,
since we should never have concurrent calls to the same since we should never have concurrent calls to the same
@ -212,12 +208,13 @@ static void notify_on(grpc_fd *fd, grpc_fd_state *st, grpc_iomgr_cb_func cb,
/* swap was unsuccessful due to an intervening set_ready call. /* swap was unsuccessful due to an intervening set_ready call.
Fall through to the READY code below */ Fall through to the READY code below */
case READY: case READY:
assert(gpr_atm_acq_load(&st->state) == READY); assert(gpr_atm_acq_load(st) == READY);
gpr_atm_rel_store(&st->state, NOT_READY); gpr_atm_rel_store(st, NOT_READY);
make_callback(cb, arg, !gpr_atm_acq_load(&fd->shutdown), make_callback(closure->cb, closure->cb_arg,
!gpr_atm_acq_load(&fd->shutdown),
allow_synchronous_callback); allow_synchronous_callback);
return; return;
case WAITING: default: /* WAITING */
/* upcallptr was set to a different closure. This is an error! */ /* upcallptr was set to a different closure. This is an error! */
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
"User called a notify_on function with a previous callback still " "User called a notify_on function with a previous callback still "
@ -228,38 +225,38 @@ static void notify_on(grpc_fd *fd, grpc_fd_state *st, grpc_iomgr_cb_func cb,
abort(); abort();
} }
static void set_ready_locked(grpc_fd_state *st, callback *callbacks, static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure *callbacks,
size_t *ncallbacks) { size_t *ncallbacks) {
callback *c; gpr_intptr state = gpr_atm_acq_load(st);
switch ((enum descriptor_state)gpr_atm_acq_load(&st->state)) { switch (state) {
case READY:
/* duplicate ready, ignore */
return;
case NOT_READY: case NOT_READY:
if (gpr_atm_rel_cas(&st->state, NOT_READY, READY)) { if (gpr_atm_rel_cas(st, NOT_READY, READY)) {
/* swap was successful -- the closure will run after the next /* swap was successful -- the closure will run after the next
notify_on call. */ notify_on call. */
return; return;
} }
/* swap was unsuccessful due to an intervening set_ready call. /* swap was unsuccessful due to an intervening set_ready call.
Fall through to the WAITING code below */ Fall through to the WAITING code below */
case WAITING: state = gpr_atm_acq_load(st);
assert(gpr_atm_acq_load(&st->state) == WAITING); default: /* waiting */
c = &callbacks[(*ncallbacks)++]; assert(gpr_atm_acq_load(st) != READY &&
c->cb = st->cb; gpr_atm_acq_load(st) != NOT_READY);
c->arg = st->cb_arg; callbacks[(*ncallbacks)++] = *(grpc_iomgr_closure *)state;
gpr_atm_rel_store(&st->state, NOT_READY); gpr_atm_rel_store(st, NOT_READY);
return;
case READY:
/* duplicate ready, ignore */
return; return;
} }
} }
static void set_ready(grpc_fd *fd, grpc_fd_state *st, static void set_ready(grpc_fd *fd, gpr_atm *st,
int allow_synchronous_callback) { int allow_synchronous_callback) {
/* only one set_ready can be active at once (but there may be a racing /* only one set_ready can be active at once (but there may be a racing
notify_on) */ notify_on) */
int success; int success;
callback cb; grpc_iomgr_closure cb;
size_t ncb = 0; size_t ncb = 0;
gpr_mu_lock(&fd->set_state_mu); gpr_mu_lock(&fd->set_state_mu);
set_ready_locked(st, &cb, &ncb); set_ready_locked(st, &cb, &ncb);
@ -269,7 +266,7 @@ static void set_ready(grpc_fd *fd, grpc_fd_state *st,
} }
void grpc_fd_shutdown(grpc_fd *fd) { void grpc_fd_shutdown(grpc_fd *fd) {
callback cb[2]; grpc_iomgr_closure cb[2];
size_t ncb = 0; size_t ncb = 0;
gpr_mu_lock(&fd->set_state_mu); gpr_mu_lock(&fd->set_state_mu);
GPR_ASSERT(!gpr_atm_acq_load(&fd->shutdown)); GPR_ASSERT(!gpr_atm_acq_load(&fd->shutdown));
@ -280,14 +277,12 @@ void grpc_fd_shutdown(grpc_fd *fd) {
make_callbacks(cb, ncb, 0, 0); make_callbacks(cb, ncb, 0, 0);
} }
void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_cb_func read_cb, void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure) {
void *read_cb_arg) { notify_on(fd, &fd->readst, closure, 0);
notify_on(fd, &fd->readst, read_cb, read_cb_arg, 0);
} }
void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_cb_func write_cb, void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_closure *closure) {
void *write_cb_arg) { notify_on(fd, &fd->writest, closure, 0);
notify_on(fd, &fd->writest, write_cb, write_cb_arg, 0);
} }
gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset, gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset,
@ -305,8 +300,8 @@ gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset,
watcher->fd = fd; watcher->fd = fd;
gpr_mu_unlock(&fd->watcher_mu); gpr_mu_unlock(&fd->watcher_mu);
return (gpr_atm_acq_load(&fd->readst.state) != READY ? read_mask : 0) | return (gpr_atm_acq_load(&fd->readst) != READY ? read_mask : 0) |
(gpr_atm_acq_load(&fd->writest.state) != READY ? write_mask : 0); (gpr_atm_acq_load(&fd->writest) != READY ? write_mask : 0);
} }
void grpc_fd_end_poll(grpc_fd_watcher *watcher) { void grpc_fd_end_poll(grpc_fd_watcher *watcher) {

@ -43,9 +43,7 @@
typedef struct { typedef struct {
grpc_iomgr_cb_func cb; grpc_iomgr_cb_func cb;
void *cb_arg; void *cb_arg;
int success; } grpc_iomgr_closure;
gpr_atm state;
} grpc_fd_state;
typedef struct grpc_fd grpc_fd; typedef struct grpc_fd grpc_fd;
@ -71,8 +69,8 @@ struct grpc_fd {
gpr_mu watcher_mu; gpr_mu watcher_mu;
grpc_fd_watcher watcher_root; grpc_fd_watcher watcher_root;
grpc_fd_state readst; gpr_atm readst;
grpc_fd_state writest; gpr_atm writest;
grpc_iomgr_cb_func on_done; grpc_iomgr_cb_func on_done;
void *on_done_user_data; void *on_done_user_data;
@ -126,12 +124,10 @@ void grpc_fd_shutdown(grpc_fd *fd);
underlying platform. This means that users must drain fd in read_cb before underlying platform. This means that users must drain fd in read_cb before
calling notify_on_read again. Users are also expected to handle spurious calling notify_on_read again. Users are also expected to handle spurious
events, i.e read_cb is called while nothing can be readable from fd */ events, i.e read_cb is called while nothing can be readable from fd */
void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_cb_func read_cb, void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure);
void *read_cb_arg);
/* Exactly the same semantics as above, except based on writable events. */ /* Exactly the same semantics as above, except based on writable events. */
void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_cb_func write_cb, void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_closure *closure);
void *write_cb_arg);
/* Notification from the poller to an fd that it has become readable or /* Notification from the poller to an fd that it has become readable or
writable. writable.

@ -183,10 +183,10 @@ static int multipoll_with_poll_pollset_maybe_work(
grpc_pollset_kick_consume(&pollset->kick_state); grpc_pollset_kick_consume(&pollset->kick_state);
} }
for (i = 1; i < np; i++) { for (i = 1; i < np; i++) {
if (h->pfds[i].revents & POLLIN) { if (h->pfds[i].revents & (POLLIN | POLLHUP | POLLERR)) {
grpc_fd_become_readable(h->watchers[i].fd, allow_synchronous_callback); grpc_fd_become_readable(h->watchers[i].fd, allow_synchronous_callback);
} }
if (h->pfds[i].revents & POLLOUT) { if (h->pfds[i].revents & (POLLOUT | POLLHUP | POLLERR)) {
grpc_fd_become_writable(h->watchers[i].fd, allow_synchronous_callback); grpc_fd_become_writable(h->watchers[i].fd, allow_synchronous_callback);
} }
} }

@ -63,9 +63,9 @@ static void backup_poller(void *p) {
gpr_mu_lock(&g_backup_pollset.mu); gpr_mu_lock(&g_backup_pollset.mu);
while (g_shutdown_backup_poller == 0) { while (g_shutdown_backup_poller == 0) {
gpr_timespec next_poll = gpr_time_add(last_poll, delta); gpr_timespec next_poll = gpr_time_add(last_poll, delta);
grpc_pollset_work(&g_backup_pollset, next_poll); grpc_pollset_work(&g_backup_pollset, gpr_time_add(gpr_now(), gpr_time_from_seconds(1)));
gpr_mu_unlock(&g_backup_pollset.mu); gpr_mu_unlock(&g_backup_pollset.mu);
gpr_sleep_until(next_poll); /*gpr_sleep_until(next_poll);*/
gpr_mu_lock(&g_backup_pollset.mu); gpr_mu_lock(&g_backup_pollset.mu);
last_poll = next_poll; last_poll = next_poll;
} }
@ -340,10 +340,10 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset,
if (pfd[0].revents & POLLIN) { if (pfd[0].revents & POLLIN) {
grpc_pollset_kick_consume(&pollset->kick_state); grpc_pollset_kick_consume(&pollset->kick_state);
} }
if (pfd[1].revents & POLLIN) { if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
grpc_fd_become_readable(fd, allow_synchronous_callback); grpc_fd_become_readable(fd, allow_synchronous_callback);
} }
if (pfd[1].revents & POLLOUT) { if (pfd[1].revents & (POLLOUT | POLLHUP | POLLERR)) {
grpc_fd_become_writable(fd, allow_synchronous_callback); grpc_fd_become_writable(fd, allow_synchronous_callback);
} }
} }

@ -31,9 +31,8 @@
* *
*/ */
#ifndef _POSIX_SOURCE #include <grpc/support/port_platform.h>
#define _POSIX_SOURCE #ifdef GPR_POSIX_SOCKET
#endif
#include "src/core/iomgr/sockaddr.h" #include "src/core/iomgr/sockaddr.h"
#include "src/core/iomgr/resolve_address.h" #include "src/core/iomgr/resolve_address.h"
@ -46,6 +45,7 @@
#include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/thd.h> #include <grpc/support/thd.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
@ -57,63 +57,6 @@ typedef struct {
void *arg; void *arg;
} request; } request;
static void split_host_port(const char *name, char **host, char **port) {
const char *host_start;
size_t host_len;
const char *port_start;
*host = NULL;
*port = NULL;
if (name[0] == '[') {
/* Parse a bracketed host, typically an IPv6 literal. */
const char *rbracket = strchr(name, ']');
if (rbracket == NULL) {
/* Unmatched [ */
return;
}
if (rbracket[1] == '\0') {
/* ]<end> */
port_start = NULL;
} else if (rbracket[1] == ':') {
/* ]:<port?> */
port_start = rbracket + 2;
} else {
/* ]<invalid> */
return;
}
host_start = name + 1;
host_len = rbracket - host_start;
if (memchr(host_start, ':', host_len) == NULL) {
/* Require all bracketed hosts to contain a colon, because a hostname or
IPv4 address should never use brackets. */
return;
}
} else {
const char *colon = strchr(name, ':');
if (colon != NULL && strchr(colon + 1, ':') == NULL) {
/* Exactly 1 colon. Split into host:port. */
host_start = name;
host_len = colon - name;
port_start = colon + 1;
} else {
/* 0 or 2+ colons. Bare hostname or IPv6 litearal. */
host_start = name;
host_len = strlen(name);
port_start = NULL;
}
}
/* Allocate return values. */
*host = gpr_malloc(host_len + 1);
memcpy(*host, host_start, host_len);
(*host)[host_len] = '\0';
if (port_start != NULL) {
*port = gpr_strdup(port_start);
}
}
grpc_resolved_addresses *grpc_blocking_resolve_address( grpc_resolved_addresses *grpc_blocking_resolve_address(
const char *name, const char *default_port) { const char *name, const char *default_port) {
struct addrinfo hints; struct addrinfo hints;
@ -134,12 +77,12 @@ grpc_resolved_addresses *grpc_blocking_resolve_address(
un = (struct sockaddr_un *)addrs->addrs->addr; un = (struct sockaddr_un *)addrs->addrs->addr;
un->sun_family = AF_UNIX; un->sun_family = AF_UNIX;
strcpy(un->sun_path, name + 5); strcpy(un->sun_path, name + 5);
addrs->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family); addrs->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
return addrs; return addrs;
} }
/* parse name, splitting it into host and port parts */ /* parse name, splitting it into host and port parts */
split_host_port(name, &host, &port); gpr_split_host_port(name, &host, &port);
if (host == NULL) { if (host == NULL) {
gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name); gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
goto done; goto done;
@ -233,3 +176,5 @@ void grpc_resolve_address(const char *name, const char *default_port,
r->arg = arg; r->arg = arg;
gpr_thd_new(&id, do_request, r, NULL); gpr_thd_new(&id, do_request, r, NULL);
} }
#endif

@ -0,0 +1,166 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/port_platform.h>
#ifdef GPR_WINSOCK_SOCKET
#include "src/core/iomgr/sockaddr.h"
#include "src/core/iomgr/resolve_address.h"
#include <sys/types.h>
#include <string.h>
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
typedef struct {
char *name;
char *default_port;
grpc_resolve_cb cb;
void *arg;
} request;
grpc_resolved_addresses *grpc_blocking_resolve_address(
const char *name, const char *default_port) {
struct addrinfo hints;
struct addrinfo *result = NULL, *resp;
char *host;
char *port;
int s;
size_t i;
grpc_resolved_addresses *addrs = NULL;
const gpr_timespec start_time = gpr_now();
/* parse name, splitting it into host and port parts */
gpr_split_host_port(name, &host, &port);
if (host == NULL) {
gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
goto done;
}
if (port == NULL) {
if (default_port == NULL) {
gpr_log(GPR_ERROR, "no port in name '%s'", name);
goto done;
}
port = gpr_strdup(default_port);
}
/* Call getaddrinfo */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */
hints.ai_socktype = SOCK_STREAM; /* stream socket */
hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */
s = getaddrinfo(host, port, &hints, &result);
if (s != 0) {
gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
goto done;
}
/* Success path: set addrs non-NULL, fill it in */
addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
addrs->naddrs = 0;
for (resp = result; resp != NULL; resp = resp->ai_next) {
addrs->naddrs++;
}
addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
i = 0;
for (resp = result; resp != NULL; resp = resp->ai_next) {
memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
addrs->addrs[i].len = resp->ai_addrlen;
i++;
}
/* Temporary logging, to help identify flakiness in dualstack_socket_test. */
{
const gpr_timespec delay = gpr_time_sub(gpr_now(), start_time);
const int delay_ms =
delay.tv_sec * GPR_MS_PER_SEC + delay.tv_nsec / GPR_NS_PER_MS;
gpr_log(GPR_INFO, "logspam: getaddrinfo(%s, %s) resolved %d addrs in %dms:",
host, port, addrs->naddrs, delay_ms);
for (i = 0; i < addrs->naddrs; i++) {
char *buf;
grpc_sockaddr_to_string(&buf, (struct sockaddr *)&addrs->addrs[i].addr,
0);
gpr_log(GPR_INFO, "logspam: [%d] %s", i, buf);
gpr_free(buf);
}
}
done:
gpr_free(host);
gpr_free(port);
if (result) {
freeaddrinfo(result);
}
return addrs;
}
/* Thread function to asynch-ify grpc_blocking_resolve_address */
static void do_request(void *rp) {
request *r = rp;
grpc_resolved_addresses *resolved =
grpc_blocking_resolve_address(r->name, r->default_port);
void *arg = r->arg;
grpc_resolve_cb cb = r->cb;
gpr_free(r->name);
gpr_free(r->default_port);
gpr_free(r);
cb(arg, resolved);
grpc_iomgr_unref();
}
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
gpr_free(addrs->addrs);
gpr_free(addrs);
}
void grpc_resolve_address(const char *name, const char *default_port,
grpc_resolve_cb cb, void *arg) {
request *r = gpr_malloc(sizeof(request));
gpr_thd_id id;
grpc_iomgr_ref();
r->name = gpr_strdup(name);
r->default_port = gpr_strdup(default_port);
r->cb = cb;
r->arg = arg;
gpr_thd_new(&id, do_request, r, NULL);
}
#endif

@ -60,6 +60,7 @@ typedef struct {
gpr_timespec deadline; gpr_timespec deadline;
grpc_alarm alarm; grpc_alarm alarm;
int refs; int refs;
grpc_iomgr_closure write_closure;
} async_connect; } async_connect;
static int prepare_socket(const struct sockaddr *addr, int fd) { static int prepare_socket(const struct sockaddr *addr, int fd) {
@ -136,7 +137,7 @@ static void on_writable(void *acp, int success) {
opened too many network connections. The "easy" fix: opened too many network connections. The "easy" fix:
don't do that! */ don't do that! */
gpr_log(GPR_ERROR, "kernel out of buffers"); gpr_log(GPR_ERROR, "kernel out of buffers");
grpc_fd_notify_on_write(ac->fd, on_writable, ac); grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
return; return;
} else { } else {
switch (so_error) { switch (so_error) {
@ -229,9 +230,11 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
ac->fd = grpc_fd_create(fd); ac->fd = grpc_fd_create(fd);
gpr_mu_init(&ac->mu); gpr_mu_init(&ac->mu);
ac->refs = 2; ac->refs = 2;
ac->write_closure.cb = on_writable;
ac->write_closure.cb_arg = ac;
grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now()); grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now());
grpc_fd_notify_on_write(ac->fd, on_writable, ac); grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
} }
#endif #endif

@ -43,12 +43,13 @@
#include <grpc/support/slice_buffer.h> #include <grpc/support/slice_buffer.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/iomgr/alarm.h"
#include "src/core/iomgr/iocp_windows.h"
#include "src/core/iomgr/tcp_client.h" #include "src/core/iomgr/tcp_client.h"
#include "src/core/iomgr/tcp_windows.h" #include "src/core/iomgr/tcp_windows.h"
#include "src/core/iomgr/socket_windows.h"
#include "src/core/iomgr/alarm.h"
#include "src/core/iomgr/sockaddr.h" #include "src/core/iomgr/sockaddr.h"
#include "src/core/iomgr/sockaddr_utils.h" #include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/iomgr/socket_windows.h"
typedef struct { typedef struct {
void(*cb)(void *arg, grpc_endpoint *tcp); void(*cb)(void *arg, grpc_endpoint *tcp);

@ -45,6 +45,7 @@
#include <unistd.h> #include <unistd.h>
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include "src/core/debug/trace.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
@ -263,6 +264,9 @@ typedef struct {
void *write_user_data; void *write_user_data;
grpc_tcp_slice_state write_state; grpc_tcp_slice_state write_state;
grpc_iomgr_closure read_closure;
grpc_iomgr_closure write_closure;
} grpc_tcp; } grpc_tcp;
static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success); static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success);
@ -290,17 +294,17 @@ static void call_read_cb(grpc_tcp *tcp, gpr_slice *slices, size_t nslices,
grpc_endpoint_cb_status status) { grpc_endpoint_cb_status status) {
grpc_endpoint_read_cb cb = tcp->read_cb; grpc_endpoint_read_cb cb = tcp->read_cb;
#ifdef GRPC_TRACE_TCP if (grpc_trace_bits & GRPC_TRACE_TCP) {
size_t i; size_t i;
gpr_log(GPR_DEBUG, "read: status=%d", status); gpr_log(GPR_DEBUG, "read: status=%d", status);
for (i = 0; i < nslices; i++) { for (i = 0; i < nslices; i++) {
char *dump = char *dump =
gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]), gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]),
GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT); GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT);
gpr_log(GPR_DEBUG, "READ: %s", dump); gpr_log(GPR_DEBUG, "READ: %s", dump);
gpr_free(dump); gpr_free(dump);
}
} }
#endif
tcp->read_cb = NULL; tcp->read_cb = NULL;
cb(tcp->read_user_data, slices, nslices, status); cb(tcp->read_user_data, slices, nslices, status);
@ -370,7 +374,7 @@ static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) {
} else { } else {
/* Spurious read event, consume it here */ /* Spurious read event, consume it here */
slice_state_destroy(&read_state); slice_state_destroy(&read_state);
grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp); grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure);
} }
} else { } else {
/* TODO(klempner): Log interesting errors */ /* TODO(klempner): Log interesting errors */
@ -405,7 +409,7 @@ static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb,
tcp->read_cb = cb; tcp->read_cb = cb;
tcp->read_user_data = user_data; tcp->read_user_data = user_data;
gpr_ref(&tcp->refcount); gpr_ref(&tcp->refcount);
grpc_fd_notify_on_read(tcp->em_fd, grpc_tcp_handle_read, tcp); grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure);
} }
#define MAX_WRITE_IOVEC 16 #define MAX_WRITE_IOVEC 16
@ -468,7 +472,7 @@ static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success) {
write_status = grpc_tcp_flush(tcp); write_status = grpc_tcp_flush(tcp);
if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { if (write_status == GRPC_ENDPOINT_WRITE_PENDING) {
grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp); grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure);
} else { } else {
slice_state_destroy(&tcp->write_state); slice_state_destroy(&tcp->write_state);
if (write_status == GRPC_ENDPOINT_WRITE_DONE) { if (write_status == GRPC_ENDPOINT_WRITE_DONE) {
@ -491,17 +495,17 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep,
grpc_tcp *tcp = (grpc_tcp *)ep; grpc_tcp *tcp = (grpc_tcp *)ep;
grpc_endpoint_write_status status; grpc_endpoint_write_status status;
#ifdef GRPC_TRACE_TCP if (grpc_trace_bits & GRPC_TRACE_TCP) {
size_t i; size_t i;
for (i = 0; i < nslices; i++) { for (i = 0; i < nslices; i++) {
char *data = char *data =
gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]), gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]),
GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT); GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT);
gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data); gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data);
gpr_free(data); gpr_free(data);
}
} }
#endif
GPR_ASSERT(tcp->write_cb == NULL); GPR_ASSERT(tcp->write_cb == NULL);
slice_state_init(&tcp->write_state, slices, nslices, nslices); slice_state_init(&tcp->write_state, slices, nslices, nslices);
@ -513,7 +517,7 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep,
gpr_ref(&tcp->refcount); gpr_ref(&tcp->refcount);
tcp->write_cb = cb; tcp->write_cb = cb;
tcp->write_user_data = user_data; tcp->write_user_data = user_data;
grpc_fd_notify_on_write(tcp->em_fd, grpc_tcp_handle_write, tcp); grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure);
} }
return status; return status;
@ -541,6 +545,10 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size) {
/* paired with unref in grpc_tcp_destroy */ /* paired with unref in grpc_tcp_destroy */
gpr_ref_init(&tcp->refcount, 1); gpr_ref_init(&tcp->refcount, 1);
tcp->em_fd = em_fd; tcp->em_fd = em_fd;
tcp->read_closure.cb = grpc_tcp_handle_read;
tcp->read_closure.cb_arg = tcp;
tcp->write_closure.cb = grpc_tcp_handle_write;
tcp->write_closure.cb_arg = tcp;
return &tcp->base; return &tcp->base;
} }

@ -82,6 +82,7 @@ typedef struct {
struct sockaddr_un un; struct sockaddr_un un;
} addr; } addr;
int addr_len; int addr_len;
grpc_iomgr_closure read_closure;
} server_port; } server_port;
static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) { static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) {
@ -244,7 +245,7 @@ static void on_read(void *arg, int success) {
case EINTR: case EINTR:
continue; continue;
case EAGAIN: case EAGAIN:
grpc_fd_notify_on_read(sp->emfd, on_read, sp); grpc_fd_notify_on_read(sp->emfd, &sp->read_closure);
return; return;
default: default:
gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno)); gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
@ -393,7 +394,9 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollsets,
for (j = 0; j < pollset_count; j++) { for (j = 0; j < pollset_count; j++) {
grpc_pollset_add_fd(pollsets[j], s->ports[i].emfd); grpc_pollset_add_fd(pollsets[j], s->ports[i].emfd);
} }
grpc_fd_notify_on_read(s->ports[i].emfd, on_read, &s->ports[i]); s->ports[i].read_closure.cb = on_read;
s->ports[i].read_closure.cb_arg = &s->ports[i];
grpc_fd_notify_on_read(s->ports[i].emfd, &s->ports[i].read_closure);
s->active_ports++; s->active_ports++;
} }
gpr_mu_unlock(&s->mu); gpr_mu_unlock(&s->mu);

@ -355,8 +355,9 @@ SOCKET grpc_tcp_server_get_socket(grpc_tcp_server *s, unsigned index) {
return (index < s->nports) ? s->ports[index].socket->socket : INVALID_SOCKET; return (index < s->nports) ? s->ports[index].socket->socket : INVALID_SOCKET;
} }
void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset *pollset, void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollset,
grpc_tcp_server_cb cb, void *cb_arg) { size_t pollset_count, grpc_tcp_server_cb cb,
void *cb_arg) {
size_t i; size_t i;
GPR_ASSERT(cb); GPR_ASSERT(cb);
gpr_mu_lock(&s->mu); gpr_mu_lock(&s->mu);

@ -48,6 +48,7 @@
typedef struct { typedef struct {
grpc_credentials *creds; grpc_credentials *creds;
grpc_mdstr *host; grpc_mdstr *host;
grpc_mdstr *method;
grpc_call_op op; grpc_call_op op;
} call_data; } call_data;
@ -56,6 +57,7 @@ typedef struct {
grpc_channel_security_context *security_context; grpc_channel_security_context *security_context;
grpc_mdctx *md_ctx; grpc_mdctx *md_ctx;
grpc_mdstr *authority_string; grpc_mdstr *authority_string;
grpc_mdstr *path_string;
grpc_mdstr *error_msg_key; grpc_mdstr *error_msg_key;
} channel_data; } channel_data;
@ -89,6 +91,26 @@ static void on_credentials_metadata(void *user_data, grpc_mdelem **md_elems,
grpc_call_next_op(elem, &((call_data *)elem->call_data)->op); grpc_call_next_op(elem, &((call_data *)elem->call_data)->op);
} }
static char *build_service_url(const char *url_scheme, call_data *calld) {
char *service_url;
char *service = gpr_strdup(grpc_mdstr_as_c_string(calld->method));
char *last_slash = strrchr(service, '/');
if (last_slash == NULL) {
gpr_log(GPR_ERROR, "No '/' found in fully qualified method name");
service[0] = '\0';
} else if (last_slash == service) {
/* No service part in fully qualified method name: will just be "/". */
service[1] = '\0';
} else {
*last_slash = '\0';
}
if (url_scheme == NULL) url_scheme = "";
gpr_asprintf(&service_url, "%s://%s%s", url_scheme,
grpc_mdstr_as_c_string(calld->host), service);
gpr_free(service);
return service_url;
}
static void send_security_metadata(grpc_call_element *elem, grpc_call_op *op) { static void send_security_metadata(grpc_call_element *elem, grpc_call_op *op) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
@ -106,9 +128,12 @@ static void send_security_metadata(grpc_call_element *elem, grpc_call_op *op) {
} }
if (channel_creds != NULL && if (channel_creds != NULL &&
grpc_credentials_has_request_metadata(channel_creds)) { grpc_credentials_has_request_metadata(channel_creds)) {
char *service_url =
build_service_url(channeld->security_context->base.url_scheme, calld);
calld->op = *op; /* Copy op (originates from the caller's stack). */ calld->op = *op; /* Copy op (originates from the caller's stack). */
grpc_credentials_get_request_metadata(channel_creds, grpc_credentials_get_request_metadata(channel_creds, service_url,
on_credentials_metadata, elem); on_credentials_metadata, elem);
gpr_free(service_url);
} else { } else {
grpc_call_next_op(elem, op); grpc_call_next_op(elem, op);
} }
@ -146,6 +171,9 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
if (op->data.metadata->key == channeld->authority_string) { if (op->data.metadata->key == channeld->authority_string) {
if (calld->host != NULL) grpc_mdstr_unref(calld->host); if (calld->host != NULL) grpc_mdstr_unref(calld->host);
calld->host = grpc_mdstr_ref(op->data.metadata->value); calld->host = grpc_mdstr_ref(op->data.metadata->value);
} else if (op->data.metadata->key == channeld->path_string) {
if (calld->method != NULL) grpc_mdstr_unref(calld->method);
calld->method = grpc_mdstr_ref(op->data.metadata->value);
} }
grpc_call_next_op(elem, op); grpc_call_next_op(elem, op);
break; break;
@ -194,6 +222,7 @@ static void init_call_elem(grpc_call_element *elem,
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
calld->creds = NULL; calld->creds = NULL;
calld->host = NULL; calld->host = NULL;
calld->method = NULL;
} }
/* Destructor for call_data */ /* Destructor for call_data */
@ -230,6 +259,7 @@ static void init_channel_elem(grpc_channel_element *elem,
channeld->md_ctx = metadata_context; channeld->md_ctx = metadata_context;
channeld->authority_string = channeld->authority_string =
grpc_mdstr_from_string(channeld->md_ctx, ":authority"); grpc_mdstr_from_string(channeld->md_ctx, ":authority");
channeld->path_string = grpc_mdstr_from_string(channeld->md_ctx, ":path");
channeld->error_msg_key = channeld->error_msg_key =
grpc_mdstr_from_string(channeld->md_ctx, "grpc-message"); grpc_mdstr_from_string(channeld->md_ctx, "grpc-message");
} }

@ -33,6 +33,10 @@
#include "src/core/security/credentials.h" #include "src/core/security/credentials.h"
#include <string.h>
#include <stdio.h>
#include "src/core/json/json.h"
#include "src/core/httpcli/httpcli.h" #include "src/core/httpcli/httpcli.h"
#include "src/core/iomgr/iomgr.h" #include "src/core/iomgr/iomgr.h"
#include "src/core/security/json_token.h" #include "src/core/security/json_token.h"
@ -42,14 +46,9 @@
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include "src/core/json/json.h"
#include <string.h>
#include <stdio.h>
/* -- Constants. -- */ /* -- Constants. -- */
#define GRPC_OAUTH2_TOKEN_REFRESH_THRESHOLD_SECS 60 #define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60
#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata" #define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata"
#define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \ #define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \
@ -113,6 +112,7 @@ int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) {
} }
void grpc_credentials_get_request_metadata(grpc_credentials *creds, void grpc_credentials_get_request_metadata(grpc_credentials *creds,
const char *service_url,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
void *user_data) { void *user_data) {
if (creds == NULL || !grpc_credentials_has_request_metadata(creds) || if (creds == NULL || !grpc_credentials_has_request_metadata(creds) ||
@ -122,7 +122,7 @@ void grpc_credentials_get_request_metadata(grpc_credentials *creds,
} }
return; return;
} }
creds->vtable->get_request_metadata(creds, cb, user_data); creds->vtable->get_request_metadata(creds, service_url, cb, user_data);
} }
void grpc_server_credentials_release(grpc_server_credentials *creds) { void grpc_server_credentials_release(grpc_server_credentials *creds) {
@ -288,6 +288,128 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
return &c->base; return &c->base;
} }
/* -- Jwt credentials -- */
typedef struct {
grpc_credentials base;
grpc_mdctx *md_ctx;
/* Have a simple cache for now with just 1 entry. We could have a map based on
the service_url for a more sophisticated one. */
gpr_mu cache_mu;
struct {
grpc_mdelem *jwt_md;
char *service_url;
gpr_timespec jwt_expiration;
} cached;
grpc_auth_json_key key;
gpr_timespec jwt_lifetime;
} grpc_jwt_credentials;
static void jwt_reset_cache(grpc_jwt_credentials *c) {
if (c->cached.jwt_md != NULL) {
grpc_mdelem_unref(c->cached.jwt_md);
c->cached.jwt_md = NULL;
}
if (c->cached.service_url != NULL) {
gpr_free(c->cached.service_url);
c->cached.service_url = NULL;
}
c->cached.jwt_expiration = gpr_inf_past;
}
static void jwt_destroy(grpc_credentials *creds) {
grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds;
grpc_auth_json_key_destruct(&c->key);
jwt_reset_cache(c);
gpr_mu_destroy(&c->cache_mu);
grpc_mdctx_unref(c->md_ctx);
gpr_free(c);
}
static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
static int jwt_has_request_metadata_only(const grpc_credentials *creds) {
return 1;
}
static void jwt_get_request_metadata(grpc_credentials *creds,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds;
gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
0};
/* See if we can return a cached jwt. */
grpc_mdelem *jwt_md = NULL;
{
gpr_mu_lock(&c->cache_mu);
if (c->cached.service_url != NULL &&
!strcmp(c->cached.service_url, service_url) &&
c->cached.jwt_md != NULL &&
(gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()),
refresh_threshold) > 0)) {
jwt_md = grpc_mdelem_ref(c->cached.jwt_md);
}
gpr_mu_unlock(&c->cache_mu);
}
if (jwt_md == NULL) {
char *jwt = NULL;
/* Generate a new jwt. */
gpr_mu_lock(&c->cache_mu);
jwt_reset_cache(c);
jwt = grpc_jwt_encode_and_sign(&c->key, service_url, c->jwt_lifetime, NULL);
if (jwt != NULL) {
char *md_value;
gpr_asprintf(&md_value, "Bearer %s", jwt);
gpr_free(jwt);
c->cached.jwt_expiration = gpr_time_add(gpr_now(), c->jwt_lifetime);
c->cached.service_url = gpr_strdup(service_url);
c->cached.jwt_md = grpc_mdelem_from_strings(
c->md_ctx, GRPC_AUTHORIZATION_METADATA_KEY, md_value);
gpr_free(md_value);
jwt_md = grpc_mdelem_ref(c->cached.jwt_md);
}
gpr_mu_unlock(&c->cache_mu);
}
if (jwt_md != NULL) {
cb(user_data, &jwt_md, 1, GRPC_CREDENTIALS_OK);
grpc_mdelem_unref(jwt_md);
} else {
cb(user_data, NULL, 0, GRPC_CREDENTIALS_ERROR);
}
}
static grpc_credentials_vtable jwt_vtable = {
jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
jwt_get_request_metadata};
grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
gpr_timespec token_lifetime) {
grpc_jwt_credentials *c;
grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key);
if (!grpc_auth_json_key_is_valid(&key)) {
gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
return NULL;
}
c = gpr_malloc(sizeof(grpc_jwt_credentials));
memset(c, 0, sizeof(grpc_jwt_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_JWT;
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &jwt_vtable;
c->md_ctx = grpc_mdctx_create();
c->key = key;
c->jwt_lifetime = token_lifetime;
gpr_mu_init(&c->cache_mu);
jwt_reset_cache(c);
return &c->base;
}
/* -- Oauth2TokenFetcher credentials -- */ /* -- Oauth2TokenFetcher credentials -- */
/* This object is a base for credentials that need to acquire an oauth2 token /* This object is a base for credentials that need to acquire an oauth2 token
@ -336,6 +458,12 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response(
grpc_credentials_status status = GRPC_CREDENTIALS_OK; grpc_credentials_status status = GRPC_CREDENTIALS_OK;
grpc_json *json = NULL; grpc_json *json = NULL;
if (response == NULL) {
gpr_log(GPR_ERROR, "Received NULL response.");
status = GRPC_CREDENTIALS_ERROR;
goto end;
}
if (response->body_length > 0) { if (response->body_length > 0) {
null_terminated_body = gpr_malloc(response->body_length + 1); null_terminated_body = gpr_malloc(response->body_length + 1);
null_terminated_body[response->body_length] = '\0'; null_terminated_body[response->body_length] = '\0';
@ -433,10 +561,11 @@ static void on_oauth2_token_fetcher_http_response(
} }
static void oauth2_token_fetcher_get_request_metadata( static void oauth2_token_fetcher_get_request_metadata(
grpc_credentials *creds, grpc_credentials_metadata_cb cb, void *user_data) { grpc_credentials *creds, const char *service_url,
grpc_credentials_metadata_cb cb, void *user_data) {
grpc_oauth2_token_fetcher_credentials *c = grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds; (grpc_oauth2_token_fetcher_credentials *)creds;
gpr_timespec refresh_threshold = {GRPC_OAUTH2_TOKEN_REFRESH_THRESHOLD_SECS, gpr_timespec refresh_threshold = {GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS,
0}; 0};
grpc_mdelem *cached_access_token_md = NULL; grpc_mdelem *cached_access_token_md = NULL;
{ {
@ -529,7 +658,8 @@ static void service_account_fetch_oauth2(
"application/x-www-form-urlencoded"}; "application/x-www-form-urlencoded"};
grpc_httpcli_request request; grpc_httpcli_request request;
char *body = NULL; char *body = NULL;
char *jwt = grpc_jwt_encode_and_sign(&c->key, c->scope, c->token_lifetime); char *jwt = grpc_jwt_encode_and_sign(&c->key, GRPC_JWT_OAUTH2_AUDIENCE,
c->token_lifetime, c->scope);
if (jwt == NULL) { if (jwt == NULL) {
grpc_httpcli_response response; grpc_httpcli_response response;
memset(&response, 0, sizeof(grpc_httpcli_response)); memset(&response, 0, sizeof(grpc_httpcli_response));
@ -610,6 +740,7 @@ void on_simulated_token_fetch_done(void *user_data, int success) {
} }
static void fake_oauth2_get_request_metadata(grpc_credentials *creds, static void fake_oauth2_get_request_metadata(grpc_credentials *creds,
const char *service_url,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
void *user_data) { void *user_data) {
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
@ -703,6 +834,7 @@ typedef struct {
size_t creds_index; size_t creds_index;
grpc_mdelem **md_elems; grpc_mdelem **md_elems;
size_t num_md; size_t num_md;
char *service_url;
void *user_data; void *user_data;
grpc_credentials_metadata_cb cb; grpc_credentials_metadata_cb cb;
} grpc_composite_credentials_metadata_context; } grpc_composite_credentials_metadata_context;
@ -748,6 +880,7 @@ static void composite_md_context_destroy(
grpc_mdelem_unref(ctx->md_elems[i]); grpc_mdelem_unref(ctx->md_elems[i]);
} }
gpr_free(ctx->md_elems); gpr_free(ctx->md_elems);
if (ctx->service_url != NULL) gpr_free(ctx->service_url);
gpr_free(ctx); gpr_free(ctx);
} }
@ -777,8 +910,8 @@ static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems,
grpc_credentials *inner_creds = grpc_credentials *inner_creds =
ctx->composite_creds->inner.creds_array[ctx->creds_index++]; ctx->composite_creds->inner.creds_array[ctx->creds_index++];
if (grpc_credentials_has_request_metadata(inner_creds)) { if (grpc_credentials_has_request_metadata(inner_creds)) {
grpc_credentials_get_request_metadata(inner_creds, composite_metadata_cb, grpc_credentials_get_request_metadata(inner_creds, ctx->service_url,
ctx); composite_metadata_cb, ctx);
return; return;
} }
} }
@ -789,6 +922,7 @@ static void composite_metadata_cb(void *user_data, grpc_mdelem **md_elems,
} }
static void composite_get_request_metadata(grpc_credentials *creds, static void composite_get_request_metadata(grpc_credentials *creds,
const char *service_url,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
void *user_data) { void *user_data) {
grpc_composite_credentials *c = (grpc_composite_credentials *)creds; grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
@ -799,14 +933,15 @@ static void composite_get_request_metadata(grpc_credentials *creds,
} }
ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context)); ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context));
memset(ctx, 0, sizeof(grpc_composite_credentials_metadata_context)); memset(ctx, 0, sizeof(grpc_composite_credentials_metadata_context));
ctx->service_url = gpr_strdup(service_url);
ctx->user_data = user_data; ctx->user_data = user_data;
ctx->cb = cb; ctx->cb = cb;
ctx->composite_creds = c; ctx->composite_creds = c;
while (ctx->creds_index < c->inner.num_creds) { while (ctx->creds_index < c->inner.num_creds) {
grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++]; grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++];
if (grpc_credentials_has_request_metadata(inner_creds)) { if (grpc_credentials_has_request_metadata(inner_creds)) {
grpc_credentials_get_request_metadata(inner_creds, composite_metadata_cb, grpc_credentials_get_request_metadata(inner_creds, service_url,
ctx); composite_metadata_cb, ctx);
return; return;
} }
} }
@ -910,6 +1045,7 @@ static int iam_has_request_metadata_only(const grpc_credentials *creds) {
} }
static void iam_get_request_metadata(grpc_credentials *creds, static void iam_get_request_metadata(grpc_credentials *creds,
const char *service_url,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
void *user_data) { void *user_data) {
grpc_iam_credentials *c = (grpc_iam_credentials *)creds; grpc_iam_credentials *c = (grpc_iam_credentials *)creds;

@ -50,6 +50,7 @@ typedef enum {
#define GRPC_CREDENTIALS_TYPE_SSL "Ssl" #define GRPC_CREDENTIALS_TYPE_SSL "Ssl"
#define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2" #define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
#define GRPC_CREDENTIALS_TYPE_JWT "Jwt"
#define GRPC_CREDENTIALS_TYPE_IAM "Iam" #define GRPC_CREDENTIALS_TYPE_IAM "Iam"
#define GRPC_CREDENTIALS_TYPE_COMPOSITE "Composite" #define GRPC_CREDENTIALS_TYPE_COMPOSITE "Composite"
#define GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY "FakeTransportSecurity" #define GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY "FakeTransportSecurity"
@ -71,6 +72,7 @@ typedef struct {
int (*has_request_metadata)(const grpc_credentials *c); int (*has_request_metadata)(const grpc_credentials *c);
int (*has_request_metadata_only)(const grpc_credentials *c); int (*has_request_metadata_only)(const grpc_credentials *c);
void (*get_request_metadata)(grpc_credentials *c, void (*get_request_metadata)(grpc_credentials *c,
const char *service_url,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
void *user_data); void *user_data);
} grpc_credentials_vtable; } grpc_credentials_vtable;
@ -86,6 +88,7 @@ void grpc_credentials_unref(grpc_credentials *creds);
int grpc_credentials_has_request_metadata(grpc_credentials *creds); int grpc_credentials_has_request_metadata(grpc_credentials *creds);
int grpc_credentials_has_request_metadata_only(grpc_credentials *creds); int grpc_credentials_has_request_metadata_only(grpc_credentials *creds);
void grpc_credentials_get_request_metadata(grpc_credentials *creds, void grpc_credentials_get_request_metadata(grpc_credentials *creds,
const char *service_url,
grpc_credentials_metadata_cb cb, grpc_credentials_metadata_cb cb,
void *user_data); void *user_data);
typedef struct { typedef struct {

File diff suppressed because it is too large Load Diff

@ -55,7 +55,6 @@ const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0};
#define GRPC_AUTH_JSON_KEY_TYPE_INVALID "invalid" #define GRPC_AUTH_JSON_KEY_TYPE_INVALID "invalid"
#define GRPC_AUTH_JSON_KEY_TYPE_SERVICE_ACCOUNT "service_account" #define GRPC_AUTH_JSON_KEY_TYPE_SERVICE_ACCOUNT "service_account"
#define GRPC_JWT_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
#define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256" #define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256"
#define GRPC_JWT_TYPE "JWT" #define GRPC_JWT_TYPE "JWT"
@ -171,8 +170,8 @@ void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key) {
/* --- jwt encoding and signature. --- */ /* --- jwt encoding and signature. --- */
static grpc_json *create_child(grpc_json *brother, grpc_json *parent, static grpc_json *create_child(grpc_json *brother, grpc_json *parent,
const char *key, const char *value, const char *key, const char *value,
grpc_json_type type) { grpc_json_type type) {
grpc_json *child = grpc_json_create(type); grpc_json *child = grpc_json_create(type);
if (brother) brother->next = child; if (brother) brother->next = child;
if (!parent->child) parent->child = child; if (!parent->child) parent->child = child;
@ -182,14 +181,15 @@ static grpc_json *create_child(grpc_json *brother, grpc_json *parent,
return child; return child;
} }
static char *encoded_jwt_header(const char *algorithm) { static char *encoded_jwt_header(const char *key_id, const char *algorithm) {
grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json *child = NULL; grpc_json *child = NULL;
char *json_str = NULL; char *json_str = NULL;
char *result = NULL; char *result = NULL;
child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING); child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING);
create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING); child = create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING);
create_child(child, json, "kid", key_id, GRPC_JSON_STRING);
json_str = grpc_json_dump_to_string(json, 0); json_str = grpc_json_dump_to_string(json, 0);
result = grpc_base64_encode(json_str, strlen(json_str), 1, 0); result = grpc_base64_encode(json_str, strlen(json_str), 1, 0);
@ -199,27 +199,34 @@ static char *encoded_jwt_header(const char *algorithm) {
} }
static char *encoded_jwt_claim(const grpc_auth_json_key *json_key, static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
const char *scope, gpr_timespec token_lifetime) { const char *audience,
gpr_timespec token_lifetime, const char *scope) {
grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json *json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json *child = NULL; grpc_json *child = NULL;
char *json_str = NULL; char *json_str = NULL;
char *result = NULL; char *result = NULL;
gpr_timespec now = gpr_now(); gpr_timespec now = gpr_now();
gpr_timespec expiration = gpr_time_add(now, token_lifetime); gpr_timespec expiration = gpr_time_add(now, token_lifetime);
/* log10(2^64) ~= 20 */ char now_str[GPR_LTOA_MIN_BUFSIZE];
char now_str[24]; char expiration_str[GPR_LTOA_MIN_BUFSIZE];
char expiration_str[24];
if (gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime) > 0) { if (gpr_time_cmp(token_lifetime, grpc_max_auth_token_lifetime) > 0) {
gpr_log(GPR_INFO, "Cropping token lifetime to maximum allowed value."); gpr_log(GPR_INFO, "Cropping token lifetime to maximum allowed value.");
expiration = gpr_time_add(now, grpc_max_auth_token_lifetime); expiration = gpr_time_add(now, grpc_max_auth_token_lifetime);
} }
sprintf(now_str, "%ld", now.tv_sec); gpr_ltoa(now.tv_sec, now_str);
sprintf(expiration_str, "%ld", expiration.tv_sec); gpr_ltoa(expiration.tv_sec, expiration_str);
child = create_child(NULL, json, "iss", json_key->client_email, child = create_child(NULL, json, "iss", json_key->client_email,
GRPC_JSON_STRING); GRPC_JSON_STRING);
child = create_child(child, json, "scope", scope, GRPC_JSON_STRING); if (scope != NULL) {
child = create_child(child, json, "aud", GRPC_JWT_AUDIENCE, GRPC_JSON_STRING); child = create_child(child, json, "scope", scope, GRPC_JSON_STRING);
} else {
/* Unscoped JWTs need a sub field. */
child = create_child(child, json, "sub", json_key->client_email,
GRPC_JSON_STRING);
}
child = create_child(child, json, "aud", audience, GRPC_JSON_STRING);
child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER); child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER);
create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER); create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER);
@ -301,14 +308,16 @@ end:
} }
char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key, char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key,
const char *scope, gpr_timespec token_lifetime) { const char *audience,
gpr_timespec token_lifetime, const char *scope) {
if (g_jwt_encode_and_sign_override != NULL) { if (g_jwt_encode_and_sign_override != NULL) {
return g_jwt_encode_and_sign_override(json_key, scope, token_lifetime); return g_jwt_encode_and_sign_override(json_key, audience, token_lifetime,
scope);
} else { } else {
const char *sig_algo = GRPC_JWT_RSA_SHA256_ALGORITHM; const char *sig_algo = GRPC_JWT_RSA_SHA256_ALGORITHM;
char *to_sign = dot_concat_and_free_strings( char *to_sign = dot_concat_and_free_strings(
encoded_jwt_header(sig_algo), encoded_jwt_header(json_key->private_key_id, sig_algo),
encoded_jwt_claim(json_key, scope, token_lifetime)); encoded_jwt_claim(json_key, audience, token_lifetime, scope));
char *sig = compute_and_encode_signature(json_key, sig_algo, to_sign); char *sig = compute_and_encode_signature(json_key, sig_algo, to_sign);
if (sig == NULL) { if (sig == NULL) {
gpr_free(to_sign); gpr_free(to_sign);

@ -37,6 +37,10 @@
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
/* --- Constants. --- */
#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
/* --- auth_json_key parsing. --- */ /* --- auth_json_key parsing. --- */
typedef struct { typedef struct {
@ -61,14 +65,15 @@ void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key);
/* --- json token encoding and signing. --- */ /* --- json token encoding and signing. --- */
/* Caller is responsible for calling gpr_free on the returned value. May return /* Caller is responsible for calling gpr_free on the returned value. May return
NULL on invalid input. */ NULL on invalid input. The scope parameter may be NULL. */
char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key, char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key,
const char *scope, gpr_timespec token_lifetime); const char *audience,
gpr_timespec token_lifetime, const char *scope);
/* Override encode_and_sign function for testing. */ /* Override encode_and_sign function for testing. */
typedef char *(*grpc_jwt_encode_and_sign_override)( typedef char *(*grpc_jwt_encode_and_sign_override)(
const grpc_auth_json_key *json_key, const char *scope, const grpc_auth_json_key *json_key, const char *audience,
gpr_timespec token_lifetime); gpr_timespec token_lifetime, const char *scope);
/* Set a custom encode_and_sign override for testing. */ /* Set a custom encode_and_sign override for testing. */
void grpc_jwt_encode_and_sign_set_override( void grpc_jwt_encode_and_sign_set_override(

File diff suppressed because it is too large Load Diff

@ -39,6 +39,7 @@
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include "src/core/tsi/transport_security_interface.h" #include "src/core/tsi/transport_security_interface.h"
#include "src/core/debug/trace.h"
#define STAGING_BUFFER_SIZE 8192 #define STAGING_BUFFER_SIZE 8192
@ -95,16 +96,16 @@ static void flush_read_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur,
static void call_read_cb(secure_endpoint *ep, gpr_slice *slices, size_t nslices, static void call_read_cb(secure_endpoint *ep, gpr_slice *slices, size_t nslices,
grpc_endpoint_cb_status error) { grpc_endpoint_cb_status error) {
#ifdef GRPC_TRACE_SECURE_TRANSPORT if (grpc_trace_bits & GRPC_TRACE_SECURE_ENDPOINT) {
size_t i; size_t i;
for (i = 0; i < nslices; i++) { for (i = 0; i < nslices; i++) {
char *data = char *data =
gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]), gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]),
GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT); GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT);
gpr_log(GPR_DEBUG, "READ %p: %s", ep, data); gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
gpr_free(data); gpr_free(data);
}
} }
#endif
ep->read_cb(ep->read_user_data, slices, nslices, error); ep->read_cb(ep->read_user_data, slices, nslices, error);
secure_endpoint_unref(ep); secure_endpoint_unref(ep);
} }
@ -230,15 +231,15 @@ static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep,
grpc_endpoint_write_status status; grpc_endpoint_write_status status;
GPR_ASSERT(ep->output_buffer.count == 0); GPR_ASSERT(ep->output_buffer.count == 0);
#ifdef GRPC_TRACE_SECURE_TRANSPORT if (grpc_trace_bits & GRPC_TRACE_SECURE_ENDPOINT) {
for (i = 0; i < nslices; i++) { for (i = 0; i < nslices; i++) {
char *data = char *data =
gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]), gpr_hexdump((char *)GPR_SLICE_START_PTR(slices[i]),
GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT); GPR_SLICE_LENGTH(slices[i]), GPR_HEXDUMP_PLAINTEXT);
gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data); gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data);
gpr_free(data); gpr_free(data);
}
} }
#endif
for (i = 0; i < nslices; i++) { for (i = 0; i < nslices; i++) {
gpr_slice plain = slices[i]; gpr_slice plain = slices[i];

@ -60,6 +60,12 @@
"AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-" \ "AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-" \
"SHA256:AES256-SHA256" "SHA256:AES256-SHA256"
#ifndef INSTALL_PREFIX
static const char *installed_roots_path = "/usr/share/grpc/roots.pem";
#else
static const char *installed_roots_path = INSTALL_PREFIX "/share/grpc/roots.pem";
#endif
/* -- Common methods. -- */ /* -- Common methods. -- */
grpc_security_status grpc_security_context_create_handshaker( grpc_security_status grpc_security_context_create_handshaker(
@ -232,6 +238,7 @@ grpc_channel_security_context *grpc_fake_channel_security_context_create(
gpr_malloc(sizeof(grpc_fake_channel_security_context)); gpr_malloc(sizeof(grpc_fake_channel_security_context));
gpr_ref_init(&c->base.base.refcount, 1); gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.is_client_side = 1; c->base.base.is_client_side = 1;
c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
c->base.base.vtable = &fake_channel_vtable; c->base.base.vtable = &fake_channel_vtable;
GPR_ASSERT(check_request_metadata_creds(request_metadata_creds)); GPR_ASSERT(check_request_metadata_creds(request_metadata_creds));
c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds); c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
@ -244,6 +251,7 @@ grpc_security_context *grpc_fake_server_security_context_create(void) {
grpc_security_context *c = gpr_malloc(sizeof(grpc_security_context)); grpc_security_context *c = gpr_malloc(sizeof(grpc_security_context));
gpr_ref_init(&c->refcount, 1); gpr_ref_init(&c->refcount, 1);
c->vtable = &fake_server_vtable; c->vtable = &fake_server_vtable;
c->url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
return c; return c;
} }
@ -396,6 +404,7 @@ static grpc_security_context_vtable ssl_server_vtable = {
static gpr_slice default_pem_root_certs; static gpr_slice default_pem_root_certs;
static void init_default_pem_root_certs(void) { static void init_default_pem_root_certs(void) {
/* First try to load the roots from the environment. */
char *default_root_certs_path = char *default_root_certs_path =
gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
if (default_root_certs_path == NULL) { if (default_root_certs_path == NULL) {
@ -404,9 +413,14 @@ static void init_default_pem_root_certs(void) {
default_pem_root_certs = gpr_load_file(default_root_certs_path, NULL); default_pem_root_certs = gpr_load_file(default_root_certs_path, NULL);
gpr_free(default_root_certs_path); gpr_free(default_root_certs_path);
} }
/* Fall back to installed certs if needed. */
if (GPR_SLICE_IS_EMPTY(default_pem_root_certs)) {
default_pem_root_certs = gpr_load_file(installed_roots_path, NULL);
}
} }
static size_t get_default_pem_roots(const unsigned char **pem_root_certs) { size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) {
/* TODO(jboeuf@google.com): Maybe revisit the approach which consists in /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in
loading all the roots once for the lifetime of the process. */ loading all the roots once for the lifetime of the process. */
static gpr_once once = GPR_ONCE_INIT; static gpr_once once = GPR_ONCE_INIT;
@ -451,6 +465,7 @@ grpc_security_status grpc_ssl_channel_security_context_create(
gpr_ref_init(&c->base.base.refcount, 1); gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.vtable = &ssl_channel_vtable; c->base.base.vtable = &ssl_channel_vtable;
c->base.base.is_client_side = 1; c->base.base.is_client_side = 1;
c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds); c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
c->base.check_call_host = ssl_channel_check_call_host; c->base.check_call_host = ssl_channel_check_call_host;
if (target_name != NULL) { if (target_name != NULL) {
@ -460,7 +475,7 @@ grpc_security_status grpc_ssl_channel_security_context_create(
c->overridden_target_name = gpr_strdup(overridden_target_name); c->overridden_target_name = gpr_strdup(overridden_target_name);
} }
if (config->pem_root_certs == NULL) { if (config->pem_root_certs == NULL) {
pem_root_certs_size = get_default_pem_roots(&pem_root_certs); pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
if (pem_root_certs == NULL || pem_root_certs_size == 0) { if (pem_root_certs == NULL || pem_root_certs_size == 0) {
gpr_log(GPR_ERROR, "Could not get default pem root certs."); gpr_log(GPR_ERROR, "Could not get default pem root certs.");
goto error; goto error;
@ -518,6 +533,7 @@ grpc_security_status grpc_ssl_server_security_context_create(
memset(c, 0, sizeof(grpc_ssl_server_security_context)); memset(c, 0, sizeof(grpc_ssl_server_security_context));
gpr_ref_init(&c->base.refcount, 1); gpr_ref_init(&c->base.refcount, 1);
c->base.url_scheme = GRPC_SSL_URL_SCHEME;
c->base.vtable = &ssl_server_vtable; c->base.vtable = &ssl_server_vtable;
result = tsi_create_ssl_server_handshaker_factory( result = tsi_create_ssl_server_handshaker_factory(
(const unsigned char **)config->pem_private_keys, (const unsigned char **)config->pem_private_keys,

@ -47,6 +47,11 @@ typedef enum {
GRPC_SECURITY_ERROR GRPC_SECURITY_ERROR
} grpc_security_status; } grpc_security_status;
/* --- URL schemes. --- */
#define GRPC_SSL_URL_SCHEME "https"
#define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security"
/* --- security_context object. --- /* --- security_context object. ---
A security context object represents away to configure the underlying A security context object represents away to configure the underlying
@ -72,6 +77,7 @@ struct grpc_security_context {
const grpc_security_context_vtable *vtable; const grpc_security_context_vtable *vtable;
gpr_refcount refcount; gpr_refcount refcount;
int is_client_side; int is_client_side;
const char *url_scheme;
}; };
/* Increments the refcount. */ /* Increments the refcount. */
@ -171,6 +177,8 @@ grpc_security_status grpc_ssl_server_security_context_create(
/* Secure client channel creation. */ /* Secure client channel creation. */
size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs);
grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds, grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds,
grpc_credentials *request_metadata_creds, grpc_credentials *request_metadata_creds,
const char *target, const char *target,

@ -35,8 +35,6 @@
#ifdef GPR_CPU_POSIX #ifdef GPR_CPU_POSIX
#include "src/core/support/cpu.h"
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>

@ -35,8 +35,6 @@
#ifdef GPR_WIN32 #ifdef GPR_WIN32
#include "src/core/support/cpu.h"
#include <grpc/support/log.h> #include <grpc/support/log.h>
unsigned gpr_cpu_num_cores(void) { unsigned gpr_cpu_num_cores(void) {

@ -36,6 +36,7 @@
#include <string.h> #include <string.h>
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
int gpr_join_host_port(char **out, const char *host, int port) { int gpr_join_host_port(char **out, const char *host, int port) {
@ -47,3 +48,60 @@ int gpr_join_host_port(char **out, const char *host, int port) {
return gpr_asprintf(out, "%s:%d", host, port); return gpr_asprintf(out, "%s:%d", host, port);
} }
} }
void gpr_split_host_port(const char *name, char **host, char **port) {
const char *host_start;
size_t host_len;
const char *port_start;
*host = NULL;
*port = NULL;
if (name[0] == '[') {
/* Parse a bracketed host, typically an IPv6 literal. */
const char *rbracket = strchr(name, ']');
if (rbracket == NULL) {
/* Unmatched [ */
return;
}
if (rbracket[1] == '\0') {
/* ]<end> */
port_start = NULL;
} else if (rbracket[1] == ':') {
/* ]:<port?> */
port_start = rbracket + 2;
} else {
/* ]<invalid> */
return;
}
host_start = name + 1;
host_len = rbracket - host_start;
if (memchr(host_start, ':', host_len) == NULL) {
/* Require all bracketed hosts to contain a colon, because a hostname or
IPv4 address should never use brackets. */
return;
}
} else {
const char *colon = strchr(name, ':');
if (colon != NULL && strchr(colon + 1, ':') == NULL) {
/* Exactly 1 colon. Split into host:port. */
host_start = name;
host_len = colon - name;
port_start = colon + 1;
} else {
/* 0 or 2+ colons. Bare hostname or IPv6 litearal. */
host_start = name;
host_len = strlen(name);
port_start = NULL;
}
}
/* Allocate return values. */
*host = gpr_malloc(host_len + 1);
memcpy(*host, host_start, host_len);
(*host)[host_len] = '\0';
if (port_start != NULL) {
*port = gpr_strdup(port_start);
}
}

@ -360,8 +360,7 @@ static void unlock(grpc_call *call) {
int num_completed_requests = call->num_completed_requests; int num_completed_requests = call->num_completed_requests;
int need_more_data = int need_more_data =
call->need_more_data && call->need_more_data &&
!call->sending && (call->write_state >= WRITE_STATE_STARTED || !call->is_client);
call->write_state >= WRITE_STATE_STARTED;
int i; int i;
if (need_more_data) { if (need_more_data) {
@ -536,14 +535,16 @@ static void finish_finish_step(void *pc, grpc_op_error error) {
} }
static void finish_start_step(void *pc, grpc_op_error error) { static void finish_start_step(void *pc, grpc_op_error error) {
finish_send_op(pc, GRPC_IOREQ_SEND_INITIAL_METADATA, WRITE_STATE_STARTED, error); finish_send_op(pc, GRPC_IOREQ_SEND_INITIAL_METADATA, WRITE_STATE_STARTED,
error);
} }
static send_action choose_send_action(grpc_call *call) { static send_action choose_send_action(grpc_call *call) {
switch (call->write_state) { switch (call->write_state) {
case WRITE_STATE_INITIAL: case WRITE_STATE_INITIAL:
if (is_op_live(call, GRPC_IOREQ_SEND_INITIAL_METADATA)) { if (is_op_live(call, GRPC_IOREQ_SEND_INITIAL_METADATA)) {
if (is_op_live(call, GRPC_IOREQ_SEND_MESSAGE) || is_op_live(call, GRPC_IOREQ_SEND_CLOSE)) { if (is_op_live(call, GRPC_IOREQ_SEND_MESSAGE) ||
is_op_live(call, GRPC_IOREQ_SEND_CLOSE)) {
return SEND_BUFFERED_INITIAL_METADATA; return SEND_BUFFERED_INITIAL_METADATA;
} else { } else {
return SEND_INITIAL_METADATA; return SEND_INITIAL_METADATA;

@ -107,13 +107,16 @@ static void on_connect(void *rp, grpc_endpoint *tcp) {
} else { } else {
return; return;
} }
} else { } else if (grpc_client_setup_cb_begin(r->cs_request)) {
grpc_create_chttp2_transport( grpc_create_chttp2_transport(
r->setup->setup_callback, r->setup->setup_user_data, r->setup->setup_callback, r->setup->setup_user_data,
grpc_client_setup_get_channel_args(r->cs_request), tcp, NULL, 0, grpc_client_setup_get_channel_args(r->cs_request), tcp, NULL, 0,
grpc_client_setup_get_mdctx(r->cs_request), 1); grpc_client_setup_get_mdctx(r->cs_request), 1);
grpc_client_setup_cb_end(r->cs_request);
done(r, 1); done(r, 1);
return; return;
} else {
done(r, 0);
} }
} }

@ -32,14 +32,15 @@
*/ */
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include "src/core/statistics/census_interface.h"
#include "src/core/iomgr/iomgr.h" #include "src/core/iomgr/iomgr.h"
#include "src/core/debug/trace.h"
#include "src/core/statistics/census_interface.h"
static gpr_once g_init = GPR_ONCE_INIT; static gpr_once g_init = GPR_ONCE_INIT;
static gpr_mu g_init_mu; static gpr_mu g_init_mu;
static int g_initializations; static int g_initializations;
static void do_init() { static void do_init(void) {
gpr_mu_init(&g_init_mu); gpr_mu_init(&g_init_mu);
g_initializations = 0; g_initializations = 0;
} }
@ -49,6 +50,7 @@ void grpc_init(void) {
gpr_mu_lock(&g_init_mu); gpr_mu_lock(&g_init_mu);
if (++g_initializations == 1) { if (++g_initializations == 1) {
grpc_init_trace_bits();
grpc_iomgr_init(); grpc_iomgr_init();
census_init(); census_init();
} }

@ -97,12 +97,15 @@ static void on_secure_transport_setup_done(void *rp,
if (status != GRPC_SECURITY_OK) { if (status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status); gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status);
done(r, 0); done(r, 0);
} else { } else if (grpc_client_setup_cb_begin(r->cs_request)) {
grpc_create_chttp2_transport( grpc_create_chttp2_transport(
r->setup->setup_callback, r->setup->setup_user_data, r->setup->setup_callback, r->setup->setup_user_data,
grpc_client_setup_get_channel_args(r->cs_request), secure_endpoint, grpc_client_setup_get_channel_args(r->cs_request), secure_endpoint,
NULL, 0, grpc_client_setup_get_mdctx(r->cs_request), 1); NULL, 0, grpc_client_setup_get_mdctx(r->cs_request), 1);
grpc_client_setup_cb_end(r->cs_request);
done(r, 1); done(r, 1);
} else {
done(r, 0);
} }
} }

@ -291,7 +291,7 @@ static void orphan_channel(channel_data *chand) {
static void finish_destroy_channel(void *cd, int success) { static void finish_destroy_channel(void *cd, int success) {
channel_data *chand = cd; channel_data *chand = cd;
grpc_server *server = chand->server; grpc_server *server = chand->server;
grpc_channel_destroy(chand->channel); grpc_channel_internal_unref(chand->channel);
server_unref(server); server_unref(server);
} }

@ -34,21 +34,14 @@
#ifndef __GRPC_INTERNAL_SURFACE_SURFACE_TRACE_H__ #ifndef __GRPC_INTERNAL_SURFACE_SURFACE_TRACE_H__
#define __GRPC_INTERNAL_SURFACE_SURFACE_TRACE_H__ #define __GRPC_INTERNAL_SURFACE_SURFACE_TRACE_H__
#include "src/core/debug/trace.h"
#include <grpc/support/log.h> #include <grpc/support/log.h>
/* #define GRPC_ENABLE_SURFACE_TRACE 1 */
#ifdef GRPC_ENABLE_SURFACE_TRACE
#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \ #define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \
do { \ if (grpc_trace_bits & GRPC_TRACE_SURFACE) { \
char *_ev = grpc_event_string(event); \ char *_ev = grpc_event_string(event); \
gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \ gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \
gpr_free(_ev); \ gpr_free(_ev); \
} while (0) }
#else
#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \
do { \
} while (0)
#endif
#endif /* __GRPC_INTERNAL_SURFACE_SURFACE_TRACE_H__ */ #endif /* __GRPC_INTERNAL_SURFACE_SURFACE_TRACE_H__ */

@ -135,7 +135,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
case GRPC_CHTTP2_DATA_FRAME: case GRPC_CHTTP2_DATA_FRAME:
if (cur == end) { if (cur == end) {
return GRPC_CHTTP2_PARSE_OK; return GRPC_CHTTP2_PARSE_OK;
} else if (end - cur == p->frame_size) { } else if ((gpr_uint32)(end - cur) == p->frame_size) {
state->need_flush_reads = 1; state->need_flush_reads = 1;
grpc_sopb_add_slice(&p->incoming_sopb, grpc_sopb_add_slice(&p->incoming_sopb,
gpr_slice_sub(slice, cur - beg, end - beg)); gpr_slice_sub(slice, cur - beg, end - beg));

@ -191,6 +191,7 @@ struct transport {
gpr_uint8 writing; gpr_uint8 writing;
gpr_uint8 calling_back; gpr_uint8 calling_back;
gpr_uint8 destroying; gpr_uint8 destroying;
gpr_uint8 closed;
error_state error_state; error_state error_state;
/* stream indexing */ /* stream indexing */
@ -416,6 +417,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup,
t->next_stream_id = is_client ? 1 : 2; t->next_stream_id = is_client ? 1 : 2;
t->last_incoming_stream_id = 0; t->last_incoming_stream_id = 0;
t->destroying = 0; t->destroying = 0;
t->closed = 0;
t->is_client = is_client; t->is_client = is_client;
t->outgoing_window = DEFAULT_WINDOW; t->outgoing_window = DEFAULT_WINDOW;
t->incoming_window = DEFAULT_WINDOW; t->incoming_window = DEFAULT_WINDOW;
@ -521,6 +523,8 @@ static void destroy_transport(grpc_transport *gt) {
static void close_transport(grpc_transport *gt) { static void close_transport(grpc_transport *gt) {
transport *t = (transport *)gt; transport *t = (transport *)gt;
gpr_mu_lock(&t->mu); gpr_mu_lock(&t->mu);
GPR_ASSERT(!t->closed);
t->closed = 1;
if (t->ep) { if (t->ep) {
grpc_endpoint_shutdown(t->ep); grpc_endpoint_shutdown(t->ep);
} }
@ -1631,7 +1635,7 @@ static int process_read(transport *t, gpr_slice slice) {
/* fallthrough */ /* fallthrough */
case DTS_FRAME: case DTS_FRAME:
GPR_ASSERT(cur < end); GPR_ASSERT(cur < end);
if (end - cur == t->incoming_frame_size) { if ((gpr_uint32)(end - cur) == t->incoming_frame_size) {
if (!parse_frame_slice( if (!parse_frame_slice(
t, gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 1)) { t, gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 1)) {
return 0; return 0;

@ -1084,7 +1084,7 @@ static int server_handshaker_factory_alpn_callback(
tsi_ssl_server_handshaker_factory* factory = tsi_ssl_server_handshaker_factory* factory =
(tsi_ssl_server_handshaker_factory*)arg; (tsi_ssl_server_handshaker_factory*)arg;
const unsigned char* client_current = in; const unsigned char* client_current = in;
while ((client_current - in) < inlen) { while ((unsigned int)(client_current - in) < inlen) {
unsigned char client_current_len = *(client_current++); unsigned char client_current_len = *(client_current++);
const unsigned char* server_current = factory->alpn_protocol_list; const unsigned char* server_current = factory->alpn_protocol_list;
while ((server_current >= factory->alpn_protocol_list) && while ((server_current >= factory->alpn_protocol_list) &&

@ -0,0 +1,9 @@
#Overview
This directory contains source code for C++ implementation of gRPC.
#Status
Alpha : Ready for early adopters

@ -49,84 +49,6 @@
namespace grpc { namespace grpc {
Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
ServerCredentials* creds)
: started_(false),
shutdown_(false),
num_running_cb_(0),
thread_pool_(thread_pool),
thread_pool_owned_(thread_pool_owned),
secure_(creds != nullptr) {
if (creds) {
server_ =
grpc_secure_server_create(creds->GetRawCreds(), cq_.cq(), nullptr);
} else {
server_ = grpc_server_create(cq_.cq(), nullptr);
}
}
Server::Server() {
// Should not be called.
GPR_ASSERT(false);
}
Server::~Server() {
std::unique_lock<std::mutex> lock(mu_);
if (started_ && !shutdown_) {
lock.unlock();
Shutdown();
} else {
lock.unlock();
}
grpc_server_destroy(server_);
if (thread_pool_owned_) {
delete thread_pool_;
}
}
bool Server::RegisterService(RpcService* service) {
for (int i = 0; i < service->GetMethodCount(); ++i) {
RpcServiceMethod* method = service->GetMethod(i);
void* tag =
grpc_server_register_method(server_, method->name(), nullptr, cq_.cq());
if (!tag) {
gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
method->name());
return false;
}
sync_methods_.emplace_back(method, tag);
}
return true;
}
bool Server::RegisterAsyncService(AsynchronousService* service) {
GPR_ASSERT(service->dispatch_impl_ == nullptr &&
"Can only register an asynchronous service against one server.");
service->dispatch_impl_ = this;
service->request_args_ = new void* [service->method_count_];
for (size_t i = 0; i < service->method_count_; ++i) {
void* tag =
grpc_server_register_method(server_, service->method_names_[i], nullptr,
service->completion_queue()->cq());
if (!tag) {
gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
service->method_names_[i]);
return false;
}
service->request_args_[i] = tag;
}
return true;
}
int Server::AddPort(const grpc::string& addr) {
GPR_ASSERT(!started_);
if (secure_) {
return grpc_server_add_secure_http2_port(server_, addr.c_str());
} else {
return grpc_server_add_http2_port(server_, addr.c_str());
}
}
class Server::SyncRequest final : public CompletionQueueTag { class Server::SyncRequest final : public CompletionQueueTag {
public: public:
SyncRequest(RpcServiceMethod* method, void* tag) SyncRequest(RpcServiceMethod* method, void* tag)
@ -247,6 +169,84 @@ class Server::SyncRequest final : public CompletionQueueTag {
grpc_completion_queue* cq_; grpc_completion_queue* cq_;
}; };
Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
ServerCredentials* creds)
: started_(false),
shutdown_(false),
num_running_cb_(0),
thread_pool_(thread_pool),
thread_pool_owned_(thread_pool_owned),
secure_(creds != nullptr) {
if (creds) {
server_ =
grpc_secure_server_create(creds->GetRawCreds(), cq_.cq(), nullptr);
} else {
server_ = grpc_server_create(cq_.cq(), nullptr);
}
}
Server::Server() {
// Should not be called.
GPR_ASSERT(false);
}
Server::~Server() {
std::unique_lock<std::mutex> lock(mu_);
if (started_ && !shutdown_) {
lock.unlock();
Shutdown();
} else {
lock.unlock();
}
grpc_server_destroy(server_);
if (thread_pool_owned_) {
delete thread_pool_;
}
}
bool Server::RegisterService(RpcService* service) {
for (int i = 0; i < service->GetMethodCount(); ++i) {
RpcServiceMethod* method = service->GetMethod(i);
void* tag =
grpc_server_register_method(server_, method->name(), nullptr, cq_.cq());
if (!tag) {
gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
method->name());
return false;
}
sync_methods_.emplace_back(method, tag);
}
return true;
}
bool Server::RegisterAsyncService(AsynchronousService* service) {
GPR_ASSERT(service->dispatch_impl_ == nullptr &&
"Can only register an asynchronous service against one server.");
service->dispatch_impl_ = this;
service->request_args_ = new void* [service->method_count_];
for (size_t i = 0; i < service->method_count_; ++i) {
void* tag =
grpc_server_register_method(server_, service->method_names_[i], nullptr,
service->completion_queue()->cq());
if (!tag) {
gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
service->method_names_[i]);
return false;
}
service->request_args_[i] = tag;
}
return true;
}
int Server::AddPort(const grpc::string& addr) {
GPR_ASSERT(!started_);
if (secure_) {
return grpc_server_add_secure_http2_port(server_, addr.c_str());
} else {
return grpc_server_add_http2_port(server_, addr.c_str());
}
}
bool Server::Start() { bool Server::Start() {
GPR_ASSERT(!started_); GPR_ASSERT(!started_);
started_ = true; started_ = true;

@ -0,0 +1 @@
gRPC C# is work-in-progress and is not intended to be used. See README.

@ -32,15 +32,15 @@
#endregion #endregion
using System; using System;
using NUnit.Framework;
using Google.GRPC.Core;
using Google.GRPC.Core.Internal;
using System.Threading;
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Google.GRPC.Core.Utils; using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
using NUnit.Framework;
namespace Google.GRPC.Core.Tests namespace Grpc.Core.Tests
{ {
public class ClientServerTest public class ClientServerTest
{ {
@ -133,7 +133,7 @@ namespace Google.GRPC.Core.Tests
Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)); Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken));
Assert.Fail(); Assert.Fail();
} catch(RpcException e) { } catch(RpcException e) {
Assert.AreEqual(StatusCode.GRPC_STATUS_UNIMPLEMENTED, e.Status.StatusCode); Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
} }
} }

@ -7,8 +7,8 @@
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{86EC5CB4-4EA2-40A2-8057-86542A0353BB}</ProjectGuid> <ProjectGuid>{86EC5CB4-4EA2-40A2-8057-86542A0353BB}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>GrpcCoreTests</RootNamespace> <RootNamespace>Grpc.Core.Tests</RootNamespace>
<AssemblyName>GrpcCoreTests</AssemblyName> <AssemblyName>Grpc.Core.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@ -44,9 +44,9 @@
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\GrpcCore\GrpcCore.csproj"> <ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project> <Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
<Name>GrpcCore</Name> <Name>Grpc.Core</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -32,11 +32,11 @@
#endregion #endregion
using System; using System;
using NUnit.Framework;
using Google.GRPC.Core;
using System.Threading; using System.Threading;
using Grpc.Core;
using NUnit.Framework;
namespace Google.GRPC.Core.Tests namespace Grpc.Core.Tests
{ {
public class GrpcEnvironmentTest public class GrpcEnvironmentTest
{ {

@ -3,18 +3,18 @@ using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes. // Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project. // Change them to the values specific to your project.
[assembly: AssemblyTitle("GrpcApiTests")] [assembly: AssemblyTitle("Grpc.Core.Tests")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")] [assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("jtattermusch")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision, // The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision. // and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.1.*")]
// The following attributes are used to specify the signing key for the assembly, // The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing. // if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyDelaySign(false)]

@ -32,12 +32,12 @@
#endregion #endregion
using System; using System;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
using NUnit.Framework; using NUnit.Framework;
using Google.GRPC.Core.Internal;
using Google.GRPC.Core;
using Google.GRPC.Core.Utils;
namespace Google.GRPC.Core.Tests namespace Grpc.Core.Tests
{ {
public class ServerTest public class ServerTest
{ {
@ -47,7 +47,7 @@ namespace Google.GRPC.Core.Tests
GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize();
Server server = new Server(); Server server = new Server();
int port = server.AddPort("localhost:0"); server.AddPort("localhost:0");
server.Start(); server.Start();
server.ShutdownAsync().Wait(); server.ShutdownAsync().Wait();

@ -15,17 +15,17 @@
<results> <results>
<test-suite type="TestFixture" name="CallsTest" executed="True" result="Success" success="True" time="0.009" asserts="0"> <test-suite type="TestFixture" name="CallsTest" executed="True" result="Success" success="True" time="0.009" asserts="0">
<results> <results>
<test-case name="Google.GRPC.Core.Tests.CallsTest.Test1" executed="True" result="Success" success="True" time="0.004" asserts="0" /> <test-case name="Grpc.Core.Tests.CallsTest.Test1" executed="True" result="Success" success="True" time="0.004" asserts="0" />
</results> </results>
</test-suite> </test-suite>
<test-suite type="TestFixture" name="ClientServerTest" executed="True" result="Success" success="True" time="0.149" asserts="0"> <test-suite type="TestFixture" name="ClientServerTest" executed="True" result="Success" success="True" time="0.149" asserts="0">
<results> <results>
<test-case name="Google.GRPC.Core.Tests.ClientServerTest.EmptyCall" executed="True" result="Success" success="True" time="0.111" asserts="0" /> <test-case name="Grpc.Core.Tests.ClientServerTest.EmptyCall" executed="True" result="Success" success="True" time="0.111" asserts="0" />
</results> </results>
</test-suite> </test-suite>
<test-suite type="TestFixture" name="ServerTest" executed="True" result="Success" success="True" time="0.001" asserts="0"> <test-suite type="TestFixture" name="ServerTest" executed="True" result="Success" success="True" time="0.001" asserts="0">
<results> <results>
<test-case name="Google.GRPC.Core.Tests.ServerTest.StartAndShutdownServer" executed="True" result="Success" success="True" time="0.001" asserts="0" /> <test-case name="Grpc.Core.Tests.ServerTest.StartAndShutdownServer" executed="True" result="Success" success="True" time="0.001" asserts="0" />
</results> </results>
</test-suite> </test-suite>
</results> </results>

@ -32,11 +32,11 @@
#endregion #endregion
using System; using System;
using NUnit.Framework;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Google.GRPC.Core.Internal; using Grpc.Core.Internal;
using NUnit.Framework;
namespace Google.GRPC.Core.Internal.Tests namespace Grpc.Core.Internal.Tests
{ {
public class TimespecTest public class TimespecTest
{ {

@ -32,9 +32,9 @@
#endregion #endregion
using System; using System;
using Google.GRPC.Core.Internal; using Grpc.Core.Internal;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
public class Call<TRequest, TResponse> public class Call<TRequest, TResponse>
{ {

@ -34,9 +34,9 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Google.GRPC.Core.Internal; using Grpc.Core.Internal;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
// NOTE: this class is work-in-progress // NOTE: this class is work-in-progress

@ -35,9 +35,9 @@ using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Google.GRPC.Core.Internal; using Grpc.Core.Internal;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
public class Channel : IDisposable public class Channel : IDisposable
{ {

@ -34,7 +34,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
/// <summary> /// <summary>
/// Return type for client streaming async method. /// Return type for client streaming async method.

@ -7,8 +7,8 @@
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</ProjectGuid> <ProjectGuid>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>GrpcCore</RootNamespace> <RootNamespace>Grpc.Core</RootNamespace>
<AssemblyName>GrpcCore</AssemblyName> <AssemblyName>Grpc.Core</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>Grpc.Core</id>
<title>gRPC Core</title>
<summary>Core C# implementation of gRPC - an RPC library and framework</summary>
<description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.
This is an experimental release, not ready to use.
</description>
<version>0.1.0</version>
<authors>Google Inc.</authors>
<owners>jtattermusch</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>The first experimental release. Not ready to use.</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags>
</metadata>
<files>
<file src="bin/Release/Grpc.Core.dll" target="lib/net45" />
</files>
</package>

@ -32,10 +32,10 @@
#endregion #endregion
using System; using System;
using Google.GRPC.Core.Internal;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Grpc.Core.Internal;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
/// <summary> /// <summary>
/// Encapsulates initialization and shutdown of gRPC library. /// Encapsulates initialization and shutdown of gRPC library.

@ -32,14 +32,14 @@
#endregion #endregion
using System; using System;
using System.Runtime.InteropServices;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Runtime.CompilerServices; using Grpc.Core.Internal;
using Google.GRPC.Core.Internal;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
/// <summary> /// <summary>
/// Handles native call lifecycle and provides convenience methods. /// Handles native call lifecycle and provides convenience methods.
@ -381,7 +381,7 @@ namespace Google.GRPC.Core.Internal
private void CompleteStreamObserver(Status status) private void CompleteStreamObserver(Status status)
{ {
if (status.StatusCode != StatusCode.GRPC_STATUS_OK) if (status.StatusCode != StatusCode.OK)
{ {
// TODO: wrap to handle exceptions; // TODO: wrap to handle exceptions;
readObserver.OnError(new RpcException(status)); readObserver.OnError(new RpcException(status));
@ -413,13 +413,13 @@ namespace Google.GRPC.Core.Internal
if (error != GRPCOpError.GRPC_OP_OK) if (error != GRPCOpError.GRPC_OP_OK)
{ {
tcs.SetException(new RpcException( tcs.SetException(new RpcException(
new Status(StatusCode.GRPC_STATUS_INTERNAL, "Internal error occured.") new Status(StatusCode.Internal, "Internal error occured.")
)); ));
return; return;
} }
var status = ctx.GetReceivedStatus(); var status = ctx.GetReceivedStatus();
if (status.StatusCode != StatusCode.GRPC_STATUS_OK) if (status.StatusCode != StatusCode.OK)
{ {
tcs.SetException(new RpcException(status)); tcs.SetException(new RpcException(status));
return; return;

@ -33,9 +33,9 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Google.GRPC.Core; using Grpc.Core;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
/// <summary> /// <summary>
/// Not owned version of /// Not owned version of

@ -32,11 +32,11 @@
#endregion #endregion
using System; using System;
using System.Runtime.InteropServices;
using System.Diagnostics; using System.Diagnostics;
using Google.GRPC.Core; using System.Runtime.InteropServices;
using Grpc.Core;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
//TODO: rename the delegate //TODO: rename the delegate
internal delegate void CompletionCallbackDelegate(GRPCOpError error, IntPtr batchContextPtr); internal delegate void CompletionCallbackDelegate(GRPCOpError error, IntPtr batchContextPtr);

@ -36,7 +36,7 @@ using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
/// <summary> /// <summary>
/// grpc_channel from <grpc/grpc.h> /// grpc_channel from <grpc/grpc.h>

@ -32,9 +32,9 @@
#endregion #endregion
using System; using System;
using Google.GRPC.Core.Internal; using Grpc.Core.Internal;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
internal class ClientStreamingInputObserver<TWrite, TRead> : IObserver<TWrite> internal class ClientStreamingInputObserver<TWrite, TRead> : IObserver<TWrite>
{ {

@ -35,7 +35,7 @@ using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
/// <summary> /// <summary>
/// grpc_completion_queue from <grpc/grpc.h> /// grpc_completion_queue from <grpc/grpc.h>

@ -34,7 +34,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
/// <summary> /// <summary>
/// from grpc/grpc.h /// from grpc/grpc.h

@ -32,13 +32,13 @@
#endregion #endregion
using System; using System;
using Google.GRPC.Core.Internal; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic; using Grpc.Core.Internal;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
/// <summary> /// <summary>
/// Pool of threads polling on the same completion queue. /// Pool of threads polling on the same completion queue.

@ -34,7 +34,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
/// <summary> /// <summary>
/// Safe handle to wrap native objects. /// Safe handle to wrap native objects.

@ -32,11 +32,11 @@
#endregion #endregion
using System; using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
// TODO: we need to make sure that the delegates are not collected before invoked. // TODO: we need to make sure that the delegates are not collected before invoked.
internal delegate void ServerShutdownCallbackDelegate(IntPtr eventPtr); internal delegate void ServerShutdownCallbackDelegate(IntPtr eventPtr);

@ -32,9 +32,9 @@
#endregion #endregion
using System; using System;
using Google.GRPC.Core.Internal; using Grpc.Core.Internal;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
/// <summary> /// <summary>
/// Observer that writes all arriving messages to a call abstraction (in blocking fashion) /// Observer that writes all arriving messages to a call abstraction (in blocking fashion)
@ -52,7 +52,7 @@ namespace Google.GRPC.Core.Internal
public void OnCompleted() public void OnCompleted()
{ {
// TODO: how bad is the Wait here? // TODO: how bad is the Wait here?
call.SendStatusFromServerAsync(new Status(StatusCode.GRPC_STATUS_OK, "")).Wait(); call.SendStatusFromServerAsync(new Status(StatusCode.OK, "")).Wait();
} }
public void OnError(Exception error) public void OnError(Exception error)

@ -35,7 +35,7 @@ using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
namespace Google.GRPC.Core.Internal namespace Grpc.Core.Internal
{ {
/// <summary> /// <summary>
/// gpr_timespec from grpc/support/time.h /// gpr_timespec from grpc/support/time.h

@ -33,7 +33,7 @@
using System; using System;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
/// <summary> /// <summary>
/// For serializing and deserializing messages. /// For serializing and deserializing messages.

@ -33,7 +33,7 @@
using System; using System;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
public enum MethodType public enum MethodType
{ {

@ -3,22 +3,22 @@ using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes. // Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project. // Change them to the values specific to your project.
[assembly: AssemblyTitle ("GrpcCore")] [assembly: AssemblyTitle ("Grpc.Core")]
[assembly: AssemblyDescription ("")] [assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")] [assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("")] [assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("")] [assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("jtattermusch")] [assembly: AssemblyCopyright ("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark ("")] [assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")] [assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision, // The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision. // and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")] [assembly: AssemblyVersion ("0.1.*")]
// The following attributes are used to specify the signing key for the assembly, // The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing. // if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")] //[assembly: AssemblyKeyFile("")]
[assembly: InternalsVisibleTo("GrpcCoreTests")] [assembly: InternalsVisibleTo("Grpc.Core.Tests")]

@ -33,7 +33,7 @@
using System; using System;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
public class RpcException : Exception public class RpcException : Exception
{ {

@ -32,14 +32,14 @@
#endregion #endregion
using System; using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using Google.GRPC.Core.Internal; using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Grpc.Core.Internal;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
/// <summary> /// <summary>
/// Server is implemented only to be able to do /// Server is implemented only to be able to do

@ -32,9 +32,9 @@
#endregion #endregion
using System; using System;
using Google.GRPC.Core.Internal; using Grpc.Core.Internal;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
internal interface IServerCallHandler internal interface IServerCallHandler
{ {
@ -111,7 +111,7 @@ namespace Google.GRPC.Core
var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(new NullObserver<byte[]>()); var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(new NullObserver<byte[]>());
asyncCall.SendStatusFromServerAsync(new Status(StatusCode.GRPC_STATUS_UNIMPLEMENTED, "No such method.")).Wait(); asyncCall.SendStatusFromServerAsync(new Status(StatusCode.Unimplemented, "No such method.")).Wait();
finishedTask.Wait(); finishedTask.Wait();
} }

@ -33,7 +33,7 @@
using System; using System;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
// TODO: perhaps add also serverSideStreaming and clientSideStreaming // TODO: perhaps add also serverSideStreaming and clientSideStreaming

@ -34,7 +34,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
public class ServerServiceDefinition public class ServerServiceDefinition
{ {

@ -34,7 +34,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
/// <summary> /// <summary>
/// Represents RPC result. /// Represents RPC result.

@ -33,22 +33,22 @@
using System; using System;
namespace Google.GRPC.Core namespace Grpc.Core
{ {
// TODO: element names should changed to comply with C# naming conventions. // TODO: element names should changed to comply with C# naming conventions.
/// <summary> /// <summary>
/// grpc_status_code from grpc/status.h /// based on grpc_status_code from grpc/status.h
/// </summary> /// </summary>
public enum StatusCode public enum StatusCode
{ {
/* Not an error; returned on success /* Not an error; returned on success
HTTP Mapping: 200 OK */ HTTP Mapping: 200 OK */
GRPC_STATUS_OK = 0, OK = 0,
/* The operation was cancelled (typically by the caller). /* The operation was cancelled (typically by the caller).
HTTP Mapping: 499 Client Closed Request */ HTTP Mapping: 499 Client Closed Request */
GRPC_STATUS_CANCELLED = 1, Cancelled = 1,
/* Unknown error. An example of where this error may be returned is /* Unknown error. An example of where this error may be returned is
if a Status value received from another address space belongs to if a Status value received from another address space belongs to
an error-space that is not known in this address space. Also an error-space that is not known in this address space. Also
@ -56,14 +56,14 @@ namespace Google.GRPC.Core
may be converted to this error. may be converted to this error.
HTTP Mapping: 500 Internal Server Error */ HTTP Mapping: 500 Internal Server Error */
GRPC_STATUS_UNKNOWN = 2, Unknown = 2,
/* Client specified an invalid argument. Note that this differs /* Client specified an invalid argument. Note that this differs
from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments
that are problematic regardless of the state of the system that are problematic regardless of the state of the system
(e.g., a malformed file name). (e.g., a malformed file name).
HTTP Mapping: 400 Bad Request */ HTTP Mapping: 400 Bad Request */
GRPC_STATUS_INVALID_ARGUMENT = 3, InvalidArgument = 3,
/* Deadline expired before operation could complete. For operations /* Deadline expired before operation could complete. For operations
that change the state of the system, this error may be returned that change the state of the system, this error may be returned
even if the operation has completed successfully. For example, a even if the operation has completed successfully. For example, a
@ -71,16 +71,16 @@ namespace Google.GRPC.Core
enough for the deadline to expire. enough for the deadline to expire.
HTTP Mapping: 504 Gateway Timeout */ HTTP Mapping: 504 Gateway Timeout */
GRPC_STATUS_DEADLINE_EXCEEDED = 4, DeadlineExceeded = 4,
/* Some requested entity (e.g., file or directory) was not found. /* Some requested entity (e.g., file or directory) was not found.
HTTP Mapping: 404 Not Found */ HTTP Mapping: 404 Not Found */
GRPC_STATUS_NOT_FOUND = 5, NotFound = 5,
/* Some entity that we attempted to create (e.g., file or directory) /* Some entity that we attempted to create (e.g., file or directory)
already exists. already exists.
HTTP Mapping: 409 Conflict */ HTTP Mapping: 409 Conflict */
GRPC_STATUS_ALREADY_EXISTS = 6, AlreadyExists = 6,
/* The caller does not have permission to execute the specified /* The caller does not have permission to execute the specified
operation. PERMISSION_DENIED must not be used for rejections operation. PERMISSION_DENIED must not be used for rejections
caused by exhausting some resource (use RESOURCE_EXHAUSTED caused by exhausting some resource (use RESOURCE_EXHAUSTED
@ -89,17 +89,17 @@ namespace Google.GRPC.Core
instead for those errors). instead for those errors).
HTTP Mapping: 403 Forbidden */ HTTP Mapping: 403 Forbidden */
GRPC_STATUS_PERMISSION_DENIED = 7, PermissionDenied = 7,
/* The request does not have valid authentication credentials for the /* The request does not have valid authentication credentials for the
operation. operation.
HTTP Mapping: 401 Unauthorized */ HTTP Mapping: 401 Unauthorized */
GRPC_STATUS_UNAUTHENTICATED = 16, Unauthenticated = 16,
/* Some resource has been exhausted, perhaps a per-user quota, or /* Some resource has been exhausted, perhaps a per-user quota, or
perhaps the entire file system is out of space. perhaps the entire file system is out of space.
HTTP Mapping: 429 Too Many Requests */ HTTP Mapping: 429 Too Many Requests */
GRPC_STATUS_RESOURCE_EXHAUSTED = 8, ResourceExhausted = 8,
/* Operation was rejected because the system is not in a state /* Operation was rejected because the system is not in a state
required for the operation's execution. For example, directory required for the operation's execution. For example, directory
to be deleted may be non-empty, an rmdir operation is applied to to be deleted may be non-empty, an rmdir operation is applied to
@ -126,7 +126,7 @@ namespace Google.GRPC.Core
the request contains Etag related headers. So if the server does see the request contains Etag related headers. So if the server does see
Etag related headers in the request, it may choose to return 412 Etag related headers in the request, it may choose to return 412
instead of 400 for this error code. */ instead of 400 for this error code. */
GRPC_STATUS_FAILED_PRECONDITION = 9, FailedPrecondition = 9,
/* The operation was aborted, typically due to a concurrency issue /* The operation was aborted, typically due to a concurrency issue
like sequencer check failures, transaction aborts, etc. like sequencer check failures, transaction aborts, etc.
@ -134,7 +134,7 @@ namespace Google.GRPC.Core
ABORTED, and UNAVAILABLE. ABORTED, and UNAVAILABLE.
HTTP Mapping: 409 Conflict */ HTTP Mapping: 409 Conflict */
GRPC_STATUS_ABORTED = 10, Aborted = 10,
/* Operation was attempted past the valid range. E.g., seeking or /* Operation was attempted past the valid range. E.g., seeking or
reading past end of file. reading past end of file.
@ -152,17 +152,17 @@ namespace Google.GRPC.Core
they are done. they are done.
HTTP Mapping: 400 Bad Request */ HTTP Mapping: 400 Bad Request */
GRPC_STATUS_OUT_OF_RANGE = 11, OutOfRange = 11,
/* Operation is not implemented or not supported/enabled in this service. /* Operation is not implemented or not supported/enabled in this service.
HTTP Mapping: 501 Not Implemented */ HTTP Mapping: 501 Not Implemented */
GRPC_STATUS_UNIMPLEMENTED = 12, Unimplemented = 12,
/* Internal errors. Means some invariants expected by underlying /* Internal errors. Means some invariants expected by underlying
system has been broken. If you see one of these errors, system has been broken. If you see one of these errors,
something is very broken. something is very broken.
HTTP Mapping: 500 Internal Server Error */ HTTP Mapping: 500 Internal Server Error */
GRPC_STATUS_INTERNAL = 13, Internal = 13,
/* The service is currently unavailable. This is a most likely a /* The service is currently unavailable. This is a most likely a
transient condition and may be corrected by retrying with transient condition and may be corrected by retrying with
a backoff. a backoff.
@ -171,13 +171,11 @@ namespace Google.GRPC.Core
ABORTED, and UNAVAILABLE. ABORTED, and UNAVAILABLE.
HTTP Mapping: 503 Service Unavailable */ HTTP Mapping: 503 Service Unavailable */
GRPC_STATUS_UNAVAILABLE = 14, Unavailable = 14,
/* Unrecoverable data loss or corruption. /* Unrecoverable data loss or corruption.
HTTP Mapping: 500 Internal Server Error */ HTTP Mapping: 500 Internal Server Error */
GRPC_STATUS_DATA_LOSS = 15, DataLoss = 15
/* Force users to include a default branch: */
GRPC_STATUS__DO_NOT_USE = -1
} }
} }

@ -32,10 +32,10 @@
#endregion #endregion
using System; using System;
using System.Threading.Tasks;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
namespace Google.GRPC.Core.Utils namespace Grpc.Core.Utils
{ {
public class RecordingObserver<T> : IObserver<T> public class RecordingObserver<T> : IObserver<T>
{ {

@ -36,7 +36,7 @@ using System.Threading.Tasks;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Concurrent; using System.Collections.Concurrent;
namespace Google.GRPC.Core.Utils namespace Grpc.Core.Utils
{ {
// TODO: replace this by something that implements IAsyncEnumerator. // TODO: replace this by something that implements IAsyncEnumerator.
/// <summary> /// <summary>

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

Loading…
Cancel
Save