Merge github.com:grpc/grpc into flow-like-lava-to-a-barnyard

pull/1888/head
Craig Tiller 10 years ago
commit cc44ee50e4
  1. 4
      .gitignore
  2. 3
      .travis.yml
  3. 11
      BUILD
  4. 157
      Makefile
  5. 30
      build.json
  6. 1
      gRPC.podspec
  7. 62
      include/grpc++/auth_context.h
  8. 4
      include/grpc++/client_context.h
  9. 9
      include/grpc++/server_context.h
  10. 3
      include/grpc/grpc.h
  11. 13
      include/grpc/grpc_security.h
  12. 22
      include/grpc/support/time.h
  13. 8
      src/core/channel/census_filter.c
  14. 4
      src/core/client_config/subchannel.c
  15. 1
      src/core/iomgr/iocp_windows.c
  16. 39
      src/core/iomgr/iomgr.c
  17. 3
      src/core/iomgr/pollset_multipoller_with_epoll.c
  18. 9
      src/core/iomgr/pollset_posix.c
  19. 6
      src/core/iomgr/pollset_windows.c
  20. 5
      src/core/iomgr/socket_windows.c
  21. 10
      src/core/iomgr/tcp_client_posix.c
  22. 3
      src/core/iomgr/tcp_client_windows.c
  23. 24
      src/core/iomgr/tcp_windows.c
  24. 2
      src/core/profiling/timers_preciseclock.h
  25. 18
      src/core/security/client_auth_filter.c
  26. 123
      src/core/security/credentials.c
  27. 112
      src/core/security/credentials.h
  28. 89
      src/core/security/google_default_credentials.c
  29. 54
      src/core/security/json_token.c
  30. 15
      src/core/security/json_token.h
  31. 40
      src/core/security/jwt_verifier.c
  32. 14
      src/core/security/security_context.c
  33. 8
      src/core/security/security_context.h
  34. 4
      src/core/statistics/census_rpc_stats.c
  35. 16
      src/core/statistics/census_tracing.c
  36. 6
      src/core/statistics/window_stats.h
  37. 4
      src/core/support/cancellable.c
  38. 2
      src/core/support/log_linux.c
  39. 2
      src/core/support/log_posix.c
  40. 2
      src/core/support/log_win32.c
  41. 2
      src/core/support/sync_win32.c
  42. 44
      src/core/support/time_posix.c
  43. 35
      src/core/support/time_win32.c
  44. 60
      src/core/surface/call.c
  45. 1
      src/core/surface/channel.c
  46. 232
      src/core/surface/completion_queue.c
  47. 18
      src/core/surface/completion_queue.h
  48. 2
      src/core/surface/init.c
  49. 207
      src/core/surface/server.c
  50. 41
      src/core/surface/version.c
  51. 5
      src/core/transport/chttp2/parsing.c
  52. 3
      src/core/transport/chttp2/stream_encoder.c
  53. 8
      src/core/transport/chttp2_transport.c
  54. 20
      src/core/transport/metadata.c
  55. 8
      src/cpp/client/client_context.cc
  56. 42
      src/cpp/common/create_auth_context.h
  57. 45
      src/cpp/common/insecure_create_auth_context.cc
  58. 80
      src/cpp/common/secure_auth_context.cc
  59. 62
      src/cpp/common/secure_auth_context.h
  60. 50
      src/cpp/common/secure_create_auth_context.cc
  61. 4
      src/cpp/server/server.cc
  62. 7
      src/cpp/server/server_context.cc
  63. 6
      src/csharp/Grpc.Auth/Grpc.Auth.nuspec
  64. 2
      src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs
  65. 2
      src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
  66. 7
      src/csharp/Grpc.Core/Grpc.Core.csproj
  67. 8
      src/csharp/Grpc.Core/Grpc.Core.nuspec
  68. 2
      src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
  69. 2
      src/csharp/Grpc.Core/packages.config
  70. 2
      src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
  71. 2
      src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs
  72. 2
      src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
  73. 2
      src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
  74. 2
      src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
  75. 2
      src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
  76. 7
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  77. 2
      src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
  78. 2
      src/csharp/Grpc.IntegrationTesting/packages.config
  79. 4
      src/csharp/Grpc.Tools.nuspec
  80. 6
      src/csharp/Grpc.nuspec
  81. 2
      src/csharp/ext/grpc_csharp_ext.c
  82. 70
      src/node/health_check/health.js
  83. 50
      src/node/health_check/health.proto
  84. 2
      src/node/package.json
  85. 3
      src/node/src/server.js
  86. 103
      src/node/test/health_test.js
  87. 4
      src/php/ext/grpc/README.md
  88. 31
      src/php/ext/grpc/package.xml
  89. 2
      src/php/ext/grpc/timeval.c
  90. 2
      src/python/interop/setup.py
  91. 1
      src/python/src/.gitignore
  92. 5
      src/python/src/grpc/_adapter/.gitignore
  93. 7
      src/python/src/grpc/_cython/.gitignore
  94. 52
      src/python/src/grpc/_cython/README.rst
  95. 28
      src/python/src/grpc/_cython/__init__.py
  96. 28
      src/python/src/grpc/_cython/_cygrpc/__init__.py
  97. 37
      src/python/src/grpc/_cython/_cygrpc/call.pxd
  98. 82
      src/python/src/grpc/_cython/_cygrpc/call.pyx
  99. 36
      src/python/src/grpc/_cython/_cygrpc/channel.pxd
  100. 84
      src/python/src/grpc/_cython/_cygrpc/channel.pyx
  101. Some files were not shown because too many files have changed in this diff Show More

4
.gitignore vendored

@ -4,8 +4,8 @@ gens
libs libs
objs objs
# Python virtual environment (pre-3.4 only) # Python virtual environments
python2.7_virtual_environment python*_virtual_environment
# gcov coverage data # gcov coverage data
coverage coverage

@ -6,7 +6,8 @@ before_install:
- echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list - echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
- echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | sudo tee -a /etc/apt/sources.list.d/mono-xamarin.list - echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | sudo tee -a /etc/apt/sources.list.d/mono-xamarin.list
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -qq libgtest-dev libgflags-dev python-virtualenv clang-3.5 - sudo apt-get install -qq libgtest-dev libgflags-dev python-virtualenv python-dev python3-dev clang-3.5
- sudo pip install --upgrade virtualenv
- sudo pip install cpp-coveralls mako simplejson - sudo pip install cpp-coveralls mako simplejson
- sudo apt-get install -qq mono-devel nunit - sudo apt-get install -qq mono-devel nunit
- wget www.nuget.org/NuGet.exe -O nuget.exe - wget www.nuget.org/NuGet.exe -O nuget.exe

11
BUILD

@ -348,6 +348,7 @@ cc_library(
"src/core/surface/server_chttp2.c", "src/core/surface/server_chttp2.c",
"src/core/surface/server_create.c", "src/core/surface/server_create.c",
"src/core/surface/surface_trace.c", "src/core/surface/surface_trace.c",
"src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c", "src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/bin_encoder.c", "src/core/transport/chttp2/bin_encoder.c",
"src/core/transport/chttp2/frame_data.c", "src/core/transport/chttp2/frame_data.c",
@ -578,6 +579,7 @@ cc_library(
"src/core/surface/server_chttp2.c", "src/core/surface/server_chttp2.c",
"src/core/surface/server_create.c", "src/core/surface/server_create.c",
"src/core/surface/surface_trace.c", "src/core/surface/surface_trace.c",
"src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c", "src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/bin_encoder.c", "src/core/transport/chttp2/bin_encoder.c",
"src/core/transport/chttp2/frame_data.c", "src/core/transport/chttp2/frame_data.c",
@ -629,11 +631,15 @@ cc_library(
name = "grpc++", name = "grpc++",
srcs = [ srcs = [
"src/cpp/client/secure_credentials.h", "src/cpp/client/secure_credentials.h",
"src/cpp/common/secure_auth_context.h",
"src/cpp/server/secure_server_credentials.h", "src/cpp/server/secure_server_credentials.h",
"src/cpp/client/channel.h", "src/cpp/client/channel.h",
"src/cpp/common/create_auth_context.h",
"src/cpp/server/thread_pool.h", "src/cpp/server/thread_pool.h",
"src/cpp/client/secure_channel_arguments.cc", "src/cpp/client/secure_channel_arguments.cc",
"src/cpp/client/secure_credentials.cc", "src/cpp/client/secure_credentials.cc",
"src/cpp/common/secure_auth_context.cc",
"src/cpp/common/secure_create_auth_context.cc",
"src/cpp/server/secure_server_credentials.cc", "src/cpp/server/secure_server_credentials.cc",
"src/cpp/client/channel.cc", "src/cpp/client/channel.cc",
"src/cpp/client/channel_arguments.cc", "src/cpp/client/channel_arguments.cc",
@ -663,6 +669,7 @@ cc_library(
hdrs = [ hdrs = [
"include/grpc++/async_generic_service.h", "include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h", "include/grpc++/async_unary_call.h",
"include/grpc++/auth_context.h",
"include/grpc++/byte_buffer.h", "include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h", "include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h", "include/grpc++/channel_interface.h",
@ -715,7 +722,9 @@ cc_library(
name = "grpc++_unsecure", name = "grpc++_unsecure",
srcs = [ srcs = [
"src/cpp/client/channel.h", "src/cpp/client/channel.h",
"src/cpp/common/create_auth_context.h",
"src/cpp/server/thread_pool.h", "src/cpp/server/thread_pool.h",
"src/cpp/common/insecure_create_auth_context.cc",
"src/cpp/client/channel.cc", "src/cpp/client/channel.cc",
"src/cpp/client/channel_arguments.cc", "src/cpp/client/channel_arguments.cc",
"src/cpp/client/client_context.cc", "src/cpp/client/client_context.cc",
@ -744,6 +753,7 @@ cc_library(
hdrs = [ hdrs = [
"include/grpc++/async_generic_service.h", "include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h", "include/grpc++/async_unary_call.h",
"include/grpc++/auth_context.h",
"include/grpc++/byte_buffer.h", "include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h", "include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h", "include/grpc++/channel_interface.h",
@ -1041,6 +1051,7 @@ objc_library(
"src/core/surface/server_chttp2.c", "src/core/surface/server_chttp2.c",
"src/core/surface/server_create.c", "src/core/surface/server_create.c",
"src/core/surface/surface_trace.c", "src/core/surface/surface_trace.c",
"src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c", "src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/bin_encoder.c", "src/core/transport/chttp2/bin_encoder.c",
"src/core/transport/chttp2/frame_data.c", "src/core/transport/chttp2/frame_data.c",

File diff suppressed because one or more lines are too long

@ -30,6 +30,7 @@
"public_headers": [ "public_headers": [
"include/grpc++/async_generic_service.h", "include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h", "include/grpc++/async_unary_call.h",
"include/grpc++/auth_context.h",
"include/grpc++/byte_buffer.h", "include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h", "include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h", "include/grpc++/channel_interface.h",
@ -68,6 +69,7 @@
], ],
"headers": [ "headers": [
"src/cpp/client/channel.h", "src/cpp/client/channel.h",
"src/cpp/common/create_auth_context.h",
"src/cpp/server/thread_pool.h" "src/cpp/server/thread_pool.h"
], ],
"src": [ "src": [
@ -285,6 +287,7 @@
"src/core/surface/server_chttp2.c", "src/core/surface/server_chttp2.c",
"src/core/surface/server_create.c", "src/core/surface/server_create.c",
"src/core/surface/surface_trace.c", "src/core/surface/surface_trace.c",
"src/core/surface/version.c",
"src/core/transport/chttp2/alpn.c", "src/core/transport/chttp2/alpn.c",
"src/core/transport/chttp2/bin_encoder.c", "src/core/transport/chttp2/bin_encoder.c",
"src/core/transport/chttp2/frame_data.c", "src/core/transport/chttp2/frame_data.c",
@ -559,11 +562,14 @@
"language": "c++", "language": "c++",
"headers": [ "headers": [
"src/cpp/client/secure_credentials.h", "src/cpp/client/secure_credentials.h",
"src/cpp/common/secure_auth_context.h",
"src/cpp/server/secure_server_credentials.h" "src/cpp/server/secure_server_credentials.h"
], ],
"src": [ "src": [
"src/cpp/client/secure_channel_arguments.cc", "src/cpp/client/secure_channel_arguments.cc",
"src/cpp/client/secure_credentials.cc", "src/cpp/client/secure_credentials.cc",
"src/cpp/common/secure_auth_context.cc",
"src/cpp/common/secure_create_auth_context.cc",
"src/cpp/server/secure_server_credentials.cc" "src/cpp/server/secure_server_credentials.cc"
], ],
"deps": [ "deps": [
@ -616,6 +622,9 @@
"name": "grpc++_unsecure", "name": "grpc++_unsecure",
"build": "all", "build": "all",
"language": "c++", "language": "c++",
"src": [
"src/cpp/common/insecure_create_auth_context.cc"
],
"deps": [ "deps": [
"gpr", "gpr",
"grpc_unsecure" "grpc_unsecure"
@ -2286,11 +2295,11 @@
] ]
}, },
{ {
"name": "qps_test", "name": "qps_openloop_test",
"build": "test", "build": "test",
"language": "c++", "language": "c++",
"src": [ "src": [
"test/cpp/qps/qps_test.cc" "test/cpp/qps/qps_openloop_test.cc"
], ],
"deps": [ "deps": [
"qps", "qps",
@ -2304,11 +2313,11 @@
] ]
}, },
{ {
"name": "qps_test_openloop", "name": "qps_test",
"build": "test", "build": "test",
"language": "c++", "language": "c++",
"src": [ "src": [
"test/cpp/qps/qps_test_openloop.cc" "test/cpp/qps/qps_test.cc"
], ],
"deps": [ "deps": [
"qps", "qps",
@ -2343,6 +2352,19 @@
"grpc++_test_config" "grpc++_test_config"
] ]
}, },
{
"name": "secure_auth_context_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/common/secure_auth_context_test.cc"
],
"deps": [
"grpc++",
"grpc",
"gpr"
]
},
{ {
"name": "server_crash_test", "name": "server_crash_test",
"build": "test", "build": "test",

@ -357,6 +357,7 @@ Pod::Spec.new do |s|
'src/core/surface/server_chttp2.c', 'src/core/surface/server_chttp2.c',
'src/core/surface/server_create.c', 'src/core/surface/server_create.c',
'src/core/surface/surface_trace.c', 'src/core/surface/surface_trace.c',
'src/core/surface/version.c',
'src/core/transport/chttp2/alpn.c', 'src/core/transport/chttp2/alpn.c',
'src/core/transport/chttp2/bin_encoder.c', 'src/core/transport/chttp2/bin_encoder.c',
'src/core/transport/chttp2/frame_data.c', 'src/core/transport/chttp2/frame_data.c',

@ -0,0 +1,62 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPCXX_AUTH_CONTEXT_H
#define GRPCXX_AUTH_CONTEXT_H
#include <vector>
#include <grpc++/config.h>
namespace grpc {
class AuthContext {
public:
typedef std::pair<grpc::string, grpc::string> Property;
virtual ~AuthContext() {}
// A peer identity, in general is one or more properties (in which case they
// have the same name).
virtual std::vector<grpc::string> GetPeerIdentity() const = 0;
virtual grpc::string GetPeerIdentityPropertyName() const = 0;
// Returns all the property values with the given name.
virtual std::vector<grpc::string> FindPropertyValues(
const grpc::string& name) const = 0;
};
} // namespace grpc
#endif // GRPCXX_AUTH_CONTEXT_H

@ -40,6 +40,7 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include <grpc++/auth_context.h>
#include <grpc++/config.h> #include <grpc++/config.h>
#include <grpc++/status.h> #include <grpc++/status.h>
#include <grpc++/time.h> #include <grpc++/time.h>
@ -108,6 +109,8 @@ class ClientContext {
creds_ = creds; creds_ = creds;
} }
std::shared_ptr<const AuthContext> auth_context() const;
// Get and set census context // Get and set census context
void set_census_context(census_context* ccp) { census_context_ = ccp; } void set_census_context(census_context* ccp) { census_context_ = ccp; }
census_context* get_census_context() const { return census_context_; } census_context* get_census_context() const { return census_context_; }
@ -159,6 +162,7 @@ class ClientContext {
gpr_timespec deadline_; gpr_timespec deadline_;
grpc::string authority_; grpc::string authority_;
std::shared_ptr<Credentials> creds_; std::shared_ptr<Credentials> creds_;
mutable std::shared_ptr<const AuthContext> auth_context_;
census_context* census_context_; census_context* census_context_;
std::multimap<grpc::string, grpc::string> send_initial_metadata_; std::multimap<grpc::string, grpc::string> send_initial_metadata_;
std::multimap<grpc::string, grpc::string> recv_initial_metadata_; std::multimap<grpc::string, grpc::string> recv_initial_metadata_;

@ -35,8 +35,10 @@
#define GRPCXX_SERVER_CONTEXT_H #define GRPCXX_SERVER_CONTEXT_H
#include <map> #include <map>
#include <memory>
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include <grpc++/auth_context.h>
#include <grpc++/config.h> #include <grpc++/config.h>
#include <grpc++/time.h> #include <grpc++/time.h>
@ -97,6 +99,10 @@ class ServerContext {
return client_metadata_; return client_metadata_;
} }
std::shared_ptr<const AuthContext> auth_context() const {
return auth_context_;
}
private: private:
friend class ::grpc::Server; friend class ::grpc::Server;
template <class W, class R> template <class W, class R>
@ -133,12 +139,15 @@ class ServerContext {
ServerContext(gpr_timespec deadline, grpc_metadata* metadata, ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
size_t metadata_count); size_t metadata_count);
void set_call(grpc_call* call);
CompletionOp* completion_op_; CompletionOp* completion_op_;
gpr_timespec deadline_; gpr_timespec deadline_;
grpc_call* call_; grpc_call* call_;
CompletionQueue* cq_; CompletionQueue* cq_;
bool sent_initial_metadata_; bool sent_initial_metadata_;
std::shared_ptr<const AuthContext> auth_context_;
std::multimap<grpc::string, grpc::string> client_metadata_; std::multimap<grpc::string, grpc::string> client_metadata_;
std::multimap<grpc::string, grpc::string> initial_metadata_; std::multimap<grpc::string, grpc::string> initial_metadata_;
std::multimap<grpc::string, grpc::string> trailing_metadata_; std::multimap<grpc::string, grpc::string> trailing_metadata_;

@ -351,6 +351,9 @@ void grpc_init(void);
destroyed. */ destroyed. */
void grpc_shutdown(void); void grpc_shutdown(void);
/** Return a string representing the current version of grpc */
const char *grpc_version_string(void);
/** Create a completion queue */ /** Create a completion queue */
grpc_completion_queue *grpc_completion_queue_create(void); grpc_completion_queue *grpc_completion_queue_create(void);

@ -51,6 +51,11 @@ typedef struct grpc_credentials grpc_credentials;
The creator of the credentials object is responsible for its release. */ The creator of the credentials object is responsible for its release. */
void grpc_credentials_release(grpc_credentials *creds); void grpc_credentials_release(grpc_credentials *creds);
/* Environment variable that points to the google default application
credentials json key or refresh token. Used in the
grpc_google_default_credentials_create function. */
#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"
/* Creates default credentials to connect to a google gRPC service. /* Creates default credentials to connect to a google gRPC service.
WARNING: Do NOT use this credentials to connect to a non-google service as WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak. */ this could result in an oauth2 token leak. */
@ -248,8 +253,12 @@ const char *grpc_auth_context_peer_identity_property_name(
/* Returns 1 if the peer is authenticated, 0 otherwise. */ /* Returns 1 if the peer is authenticated, 0 otherwise. */
int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx); int grpc_auth_context_peer_is_authenticated(const grpc_auth_context *ctx);
/* Gets the auth context from the call. */ /* Gets the auth context from the call. Caller needs to call
const grpc_auth_context *grpc_call_auth_context(grpc_call *call); grpc_auth_context_release on the returned context. */
grpc_auth_context *grpc_call_auth_context(grpc_call *call);
/* Releases the auth context returned from grpc_call_auth_context. */
void grpc_auth_context_release(grpc_auth_context *context);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -46,8 +46,8 @@ extern "C" {
#endif #endif
typedef struct gpr_timespec { typedef struct gpr_timespec {
time_t tv_sec; time_t tv_sec;
int tv_nsec; int tv_nsec;
} gpr_timespec; } gpr_timespec;
/* Time constants. */ /* Time constants. */
@ -62,8 +62,20 @@ extern const gpr_timespec gpr_inf_past; /* The far past. */
#define GPR_NS_PER_US 1000 #define GPR_NS_PER_US 1000
#define GPR_US_PER_MS 1000 #define GPR_US_PER_MS 1000
/* Return the current time measured from the system's default epoch. */ /* The clocks we support. */
gpr_timespec gpr_now(void); typedef enum {
/* Monotonic clock. Epoch undefined. Always moves forwards. */
GPR_CLOCK_MONOTONIC = 0,
/* Realtime clock. May jump forwards or backwards. Settable by
the system administrator. Has its epoch at 0:00:00 UTC 1 Jan 1970. */
GPR_CLOCK_REALTIME
} gpr_clock_type;
/* initialize time subsystem */
void gpr_time_init(void);
/* Return the current time measured from the given clocks epoch. */
gpr_timespec gpr_now(gpr_clock_type clock);
/* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b /* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b
respectively. */ respectively. */
@ -100,4 +112,4 @@ double gpr_timespec_to_micros(gpr_timespec t);
} }
#endif #endif
#endif /* GRPC_SUPPORT_TIME_H */ #endif /* GRPC_SUPPORT_TIME_H */

@ -151,7 +151,7 @@ static void client_init_call_elem(grpc_call_element* elem,
call_data* d = elem->call_data; call_data* d = elem->call_data;
GPR_ASSERT(d != NULL); GPR_ASSERT(d != NULL);
init_rpc_stats(&d->stats); init_rpc_stats(&d->stats);
d->start_ts = gpr_now(); d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
d->op_id = census_tracing_start_op(); d->op_id = census_tracing_start_op();
if (initial_op) client_mutate_op(elem, initial_op); if (initial_op) client_mutate_op(elem, initial_op);
} }
@ -169,7 +169,7 @@ static void server_init_call_elem(grpc_call_element* elem,
call_data* d = elem->call_data; call_data* d = elem->call_data;
GPR_ASSERT(d != NULL); GPR_ASSERT(d != NULL);
init_rpc_stats(&d->stats); init_rpc_stats(&d->stats);
d->start_ts = gpr_now(); d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
d->op_id = census_tracing_start_op(); d->op_id = census_tracing_start_op();
if (initial_op) server_mutate_op(elem, initial_op); if (initial_op) server_mutate_op(elem, initial_op);
} }
@ -177,8 +177,8 @@ static void server_init_call_elem(grpc_call_element* elem,
static void server_destroy_call_elem(grpc_call_element* elem) { static void server_destroy_call_elem(grpc_call_element* elem) {
call_data* d = elem->call_data; call_data* d = elem->call_data;
GPR_ASSERT(d != NULL); GPR_ASSERT(d != NULL);
d->stats.elapsed_time_ms = d->stats.elapsed_time_ms = gpr_timespec_to_micros(
gpr_timespec_to_micros(gpr_time_sub(gpr_now(), d->start_ts)); gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), d->start_ts));
census_record_rpc_server_stats(d->op_id, &d->stats); census_record_rpc_server_stats(d->op_id, &d->stats);
census_tracing_end_op(d->op_id); census_tracing_end_op(d->op_id);
} }

@ -300,7 +300,7 @@ static void continue_connect(grpc_subchannel *c) {
} }
static void start_connect(grpc_subchannel *c) { static void start_connect(grpc_subchannel *c) {
gpr_timespec now = gpr_now(); gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
c->next_attempt = now; c->next_attempt = now;
c->backoff_delta = gpr_time_from_seconds(1); c->backoff_delta = gpr_time_from_seconds(1);
@ -585,7 +585,7 @@ static void subchannel_connected(void *arg, int iomgr_success) {
c->have_alarm = 1; c->have_alarm = 1;
c->next_attempt = gpr_time_add(c->next_attempt, c->backoff_delta); c->next_attempt = gpr_time_add(c->next_attempt, c->backoff_delta);
c->backoff_delta = gpr_time_add(c->backoff_delta, c->backoff_delta); c->backoff_delta = gpr_time_add(c->backoff_delta, c->backoff_delta);
grpc_alarm_init(&c->alarm, c->next_attempt, on_alarm, c, gpr_now()); grpc_alarm_init(&c->alarm, c->next_attempt, on_alarm, c, gpr_now(GPR_CLOCK_REALTIME));
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
} }
} }

@ -127,7 +127,6 @@ static void iocp_loop(void *p) {
grpc_maybe_call_delayed_callbacks(NULL, 1); grpc_maybe_call_delayed_callbacks(NULL, 1);
do_iocp_work(); do_iocp_work();
} }
gpr_log(GPR_DEBUG, "iocp_loop is done");
gpr_event_set(&g_iocp_done, (void *)1); gpr_event_set(&g_iocp_done, (void *)1);
} }

@ -59,7 +59,7 @@ static void background_callback_executor(void *ignored) {
while (!g_shutdown) { while (!g_shutdown) {
gpr_timespec deadline = gpr_inf_future; gpr_timespec deadline = gpr_inf_future;
gpr_timespec short_deadline = gpr_timespec short_deadline =
gpr_time_add(gpr_now(), gpr_time_from_millis(100)); gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100));
if (g_cbs_head) { if (g_cbs_head) {
grpc_iomgr_closure *closure = g_cbs_head; grpc_iomgr_closure *closure = g_cbs_head;
g_cbs_head = closure->next; g_cbs_head = closure->next;
@ -67,7 +67,8 @@ static void background_callback_executor(void *ignored) {
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
closure->cb(closure->cb_arg, closure->success); closure->cb(closure->cb_arg, closure->success);
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
} else if (grpc_alarm_check(&g_mu, gpr_now(), &deadline)) { } else if (grpc_alarm_check(&g_mu, gpr_now(GPR_CLOCK_REALTIME),
&deadline)) {
} else { } else {
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
gpr_sleep_until(gpr_time_min(short_deadline, deadline)); gpr_sleep_until(gpr_time_min(short_deadline, deadline));
@ -89,7 +90,7 @@ void grpc_iomgr_init(void) {
gpr_thd_id id; gpr_thd_id id;
gpr_mu_init(&g_mu); gpr_mu_init(&g_mu);
gpr_cv_init(&g_rcv); gpr_cv_init(&g_rcv);
grpc_alarm_list_init(gpr_now()); grpc_alarm_list_init(gpr_now(GPR_CLOCK_REALTIME));
g_root_object.next = g_root_object.prev = &g_root_object; g_root_object.next = g_root_object.prev = &g_root_object;
g_root_object.name = "root"; g_root_object.name = "root";
grpc_iomgr_platform_init(); grpc_iomgr_platform_init();
@ -110,21 +111,27 @@ void grpc_iomgr_shutdown(void) {
grpc_iomgr_object *obj; grpc_iomgr_object *obj;
grpc_iomgr_closure *closure; grpc_iomgr_closure *closure;
gpr_timespec shutdown_deadline = gpr_timespec shutdown_deadline =
gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10));
gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
g_shutdown = 1; g_shutdown = 1;
while (g_cbs_head != NULL || g_root_object.next != &g_root_object) { while (g_cbs_head != NULL || g_root_object.next != &g_root_object) {
if (g_cbs_head != NULL && g_root_object.next != &g_root_object) { if (gpr_time_cmp(
gpr_log(GPR_DEBUG, gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time),
"Waiting for %d iomgr objects to be destroyed and executing " gpr_time_from_seconds(1)) >= 0) {
"final callbacks", if (g_cbs_head != NULL && g_root_object.next != &g_root_object) {
count_objects()); gpr_log(GPR_DEBUG,
} else if (g_cbs_head != NULL) { "Waiting for %d iomgr objects to be destroyed and executing "
gpr_log(GPR_DEBUG, "Executing final iomgr callbacks"); "final callbacks",
} else { count_objects());
gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed", } else if (g_cbs_head != NULL) {
count_objects()); gpr_log(GPR_DEBUG, "Executing final iomgr callbacks");
} else {
gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed",
count_objects());
}
last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
} }
if (g_cbs_head) { if (g_cbs_head) {
do { do {
@ -145,9 +152,9 @@ void grpc_iomgr_shutdown(void) {
if (g_root_object.next != &g_root_object) { if (g_root_object.next != &g_root_object) {
int timeout = 0; int timeout = 0;
gpr_timespec short_deadline = gpr_timespec short_deadline =
gpr_time_add(gpr_now(), gpr_time_from_millis(100)); gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100));
while (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) { while (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) {
if (gpr_time_cmp(gpr_now(), shutdown_deadline) > 0) { if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) {
timeout = 1; timeout = 1;
break; break;
} }

@ -105,10 +105,11 @@ static void multipoll_with_epoll_pollset_maybe_work(
* here. * here.
*/ */
timeout_ms = grpc_poll_deadline_to_millis_timeout(deadline, now);
pollset->counter += 1; pollset->counter += 1;
gpr_mu_unlock(&pollset->mu); gpr_mu_unlock(&pollset->mu);
timeout_ms = grpc_poll_deadline_to_millis_timeout(deadline, now);
do { do {
ep_rv = epoll_wait(h->epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms); ep_rv = epoll_wait(h->epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms);
if (ep_rv < 0) { if (ep_rv < 0) {

@ -122,7 +122,7 @@ static void finish_shutdown(grpc_pollset *pollset) {
int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) { int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
/* pollset->mu already held */ /* pollset->mu already held */
gpr_timespec now = gpr_now(); gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
if (gpr_time_cmp(now, deadline) > 0) { if (gpr_time_cmp(now, deadline) > 0) {
return 0; return 0;
} }
@ -187,15 +187,16 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->mu); gpr_mu_destroy(&pollset->mu);
} }
int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline, gpr_timespec now) { int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline,
gpr_timespec now) {
gpr_timespec timeout; gpr_timespec timeout;
static const int max_spin_polling_us = 10; static const int max_spin_polling_us = 10;
if (gpr_time_cmp(deadline, gpr_inf_future) == 0) { if (gpr_time_cmp(deadline, gpr_inf_future) == 0) {
return -1; return -1;
} }
if (gpr_time_cmp( if (gpr_time_cmp(
deadline, deadline,
gpr_time_add(now, gpr_time_from_micros(max_spin_polling_us))) <= 0) { gpr_time_add(now, gpr_time_from_micros(max_spin_polling_us))) <= 0) {
return 0; return 0;
} }
timeout = gpr_time_sub(deadline, now); timeout = gpr_time_sub(deadline, now);

@ -70,7 +70,7 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) { int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
gpr_timespec now; gpr_timespec now;
now = gpr_now(); now = gpr_now(GPR_CLOCK_REALTIME);
if (gpr_time_cmp(now, deadline) > 0) { if (gpr_time_cmp(now, deadline) > 0) {
return 0 /* GPR_FALSE */; return 0 /* GPR_FALSE */;
} }
@ -86,8 +86,6 @@ int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
return 1 /* GPR_TRUE */; return 1 /* GPR_TRUE */;
} }
void grpc_pollset_kick(grpc_pollset *p) { void grpc_pollset_kick(grpc_pollset *p) { gpr_cv_signal(&p->cv); }
gpr_cv_signal(&p->cv);
}
#endif /* GPR_WINSOCK_SOCKET */ #endif /* GPR_WINSOCK_SOCKET */

@ -45,11 +45,14 @@
#include "src/core/iomgr/socket_windows.h" #include "src/core/iomgr/socket_windows.h"
grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) { grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) {
char *final_name;
grpc_winsocket *r = gpr_malloc(sizeof(grpc_winsocket)); grpc_winsocket *r = gpr_malloc(sizeof(grpc_winsocket));
memset(r, 0, sizeof(grpc_winsocket)); memset(r, 0, sizeof(grpc_winsocket));
r->socket = socket; r->socket = socket;
gpr_mu_init(&r->state_mu); gpr_mu_init(&r->state_mu);
grpc_iomgr_register_object(&r->iomgr_object, name); gpr_asprintf(&final_name, "%s:socket=0x%p", name, r);
grpc_iomgr_register_object(&r->iomgr_object, final_name);
gpr_free(final_name);
grpc_iocp_add_socket(r); grpc_iocp_add_socket(r);
return r; return r;
} }

@ -114,6 +114,7 @@ static void on_writable(void *acp, int success) {
void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb; void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb;
void *cb_arg = ac->cb_arg; void *cb_arg = ac->cb_arg;
gpr_mu_lock(&ac->mu);
if (success) { if (success) {
do { do {
so_error_size = sizeof(so_error); so_error_size = sizeof(so_error);
@ -139,6 +140,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");
gpr_mu_unlock(&ac->mu);
grpc_fd_notify_on_write(ac->fd, &ac->write_closure); grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
return; return;
} else { } else {
@ -165,10 +167,11 @@ static void on_writable(void *acp, int success) {
abort(); abort();
finish: finish:
gpr_mu_lock(&ac->mu); if (ep == NULL) {
if (!ep) {
grpc_pollset_set_del_fd(ac->interested_parties, ac->fd); grpc_pollset_set_del_fd(ac->interested_parties, ac->fd);
grpc_fd_orphan(ac->fd, NULL, "tcp_client_orphan"); grpc_fd_orphan(ac->fd, NULL, "tcp_client_orphan");
} else {
ac->fd = NULL;
} }
done = (--ac->refs == 0); done = (--ac->refs == 0);
gpr_mu_unlock(&ac->mu); gpr_mu_unlock(&ac->mu);
@ -250,7 +253,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
ac->write_closure.cb_arg = ac; ac->write_closure.cb_arg = ac;
gpr_mu_lock(&ac->mu); gpr_mu_lock(&ac->mu);
grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now()); grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac,
gpr_now(GPR_CLOCK_REALTIME));
grpc_fd_notify_on_write(ac->fd, &ac->write_closure); grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
gpr_mu_unlock(&ac->mu); gpr_mu_unlock(&ac->mu);

@ -215,7 +215,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
ac->refs = 2; ac->refs = 2;
ac->aborted = 0; ac->aborted = 0;
grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now()); grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac,
gpr_now(GPR_CLOCK_REALTIME));
socket->write_info.outstanding = 1; socket->write_info.outstanding = 1;
grpc_socket_notify_on_write(socket, on_connect, ac); grpc_socket_notify_on_write(socket, on_connect, ac);
return; return;

@ -148,9 +148,11 @@ static void on_read(void *tcpp, int from_iocp) {
GPR_ASSERT(tcp->socket->read_info.outstanding); GPR_ASSERT(tcp->socket->read_info.outstanding);
if (socket->read_info.wsa_error != 0) { if (socket->read_info.wsa_error != 0) {
char *utf8_message = gpr_format_message(info->wsa_error); if (socket->read_info.wsa_error != WSAECONNRESET) {
gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message); char *utf8_message = gpr_format_message(info->wsa_error);
gpr_free(utf8_message); gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message);
gpr_free(utf8_message);
}
status = GRPC_ENDPOINT_CB_ERROR; status = GRPC_ENDPOINT_CB_ERROR;
} else { } else {
if (info->bytes_transfered != 0) { if (info->bytes_transfered != 0) {
@ -259,9 +261,11 @@ static void on_write(void *tcpp, int from_iocp) {
GPR_ASSERT(tcp->socket->write_info.outstanding); GPR_ASSERT(tcp->socket->write_info.outstanding);
if (info->wsa_error != 0) { if (info->wsa_error != 0) {
char *utf8_message = gpr_format_message(info->wsa_error); if (info->wsa_error != WSAECONNRESET) {
gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); char *utf8_message = gpr_format_message(info->wsa_error);
gpr_free(utf8_message); gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message);
gpr_free(utf8_message);
}
status = GRPC_ENDPOINT_CB_ERROR; status = GRPC_ENDPOINT_CB_ERROR;
} else { } else {
GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length); GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length);
@ -325,9 +329,11 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
ret = GRPC_ENDPOINT_WRITE_DONE; ret = GRPC_ENDPOINT_WRITE_DONE;
GPR_ASSERT(bytes_sent == tcp->write_slices.length); GPR_ASSERT(bytes_sent == tcp->write_slices.length);
} else { } else {
char *utf8_message = gpr_format_message(info->wsa_error); if (socket->read_info.wsa_error != WSAECONNRESET) {
gpr_log(GPR_ERROR, "WSASend error: %s", utf8_message); char *utf8_message = gpr_format_message(info->wsa_error);
gpr_free(utf8_message); gpr_log(GPR_ERROR, "WSASend error: %s", utf8_message);
gpr_free(utf8_message);
}
} }
if (allocated) gpr_free(allocated); if (allocated) gpr_free(allocated);
gpr_slice_buffer_reset_and_unref(&tcp->write_slices); gpr_slice_buffer_reset_and_unref(&tcp->write_slices);

@ -82,7 +82,7 @@ struct grpc_precise_clock {
gpr_timespec clock; gpr_timespec clock;
}; };
static void grpc_precise_clock_now(grpc_precise_clock* clk) { static void grpc_precise_clock_now(grpc_precise_clock* clk) {
clk->clock = gpr_now(); clk->clock = gpr_now(GPR_CLOCK_REALTIME);
} }
#define GRPC_PRECISE_CLOCK_FORMAT "%ld.%09d" #define GRPC_PRECISE_CLOCK_FORMAT "%ld.%09d"
#define GRPC_PRECISE_CLOCK_PRINTF_ARGS(clk) \ #define GRPC_PRECISE_CLOCK_PRINTF_ARGS(clk) \

@ -61,6 +61,7 @@ typedef struct {
grpc_transport_stream_op op; grpc_transport_stream_op op;
size_t op_md_idx; size_t op_md_idx;
int sent_initial_metadata; int sent_initial_metadata;
gpr_uint8 security_context_set;
grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT]; grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
} call_data; } call_data;
@ -199,8 +200,22 @@ static void auth_start_transport_op(grpc_call_element *elem,
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
grpc_linked_mdelem *l; grpc_linked_mdelem *l;
size_t i; size_t i;
grpc_client_security_context* sec_ctx = NULL;
/* TODO(jboeuf): write the call auth context. */ if (calld->security_context_set == 0) {
calld->security_context_set = 1;
GPR_ASSERT(op->context);
if (op->context[GRPC_CONTEXT_SECURITY].value == NULL) {
op->context[GRPC_CONTEXT_SECURITY].value =
grpc_client_security_context_create();
op->context[GRPC_CONTEXT_SECURITY].destroy =
grpc_client_security_context_destroy;
}
sec_ctx = op->context[GRPC_CONTEXT_SECURITY].value;
GRPC_AUTH_CONTEXT_UNREF(sec_ctx->auth_context, "client auth filter");
sec_ctx->auth_context = GRPC_AUTH_CONTEXT_REF(
chand->security_connector->base.auth_context, "client_auth_filter");
}
if (op->bind_pollset) { if (op->bind_pollset) {
calld->pollset = op->bind_pollset; calld->pollset = op->bind_pollset;
@ -263,6 +278,7 @@ static void init_call_elem(grpc_call_element *elem,
calld->method = NULL; calld->method = NULL;
calld->pollset = NULL; calld->pollset = NULL;
calld->sent_initial_metadata = 0; calld->sent_initial_metadata = 0;
calld->security_context_set = 0;
GPR_ASSERT(!initial_op || !initial_op->send_ops); GPR_ASSERT(!initial_op || !initial_op->send_ops);
} }

@ -41,7 +41,6 @@
#include "src/core/json/json.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/support/string.h" #include "src/core/support/string.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
@ -52,12 +51,12 @@
/* -- Common. -- */ /* -- Common. -- */
typedef struct { struct grpc_credentials_metadata_request {
grpc_credentials *creds; grpc_credentials *creds;
grpc_credentials_metadata_cb cb; grpc_credentials_metadata_cb cb;
grpc_iomgr_closure *on_simulated_token_fetch_done_closure; grpc_iomgr_closure *on_simulated_token_fetch_done_closure;
void *user_data; void *user_data;
} grpc_credentials_metadata_request; };
static grpc_credentials_metadata_request * static grpc_credentials_metadata_request *
grpc_credentials_metadata_request_create(grpc_credentials *creds, grpc_credentials_metadata_request_create(grpc_credentials *creds,
@ -152,16 +151,6 @@ grpc_security_status grpc_server_credentials_create_security_connector(
/* -- Ssl credentials. -- */ /* -- Ssl credentials. -- */
typedef struct {
grpc_credentials base;
grpc_ssl_config config;
} grpc_ssl_credentials;
typedef struct {
grpc_server_credentials base;
grpc_ssl_server_config config;
} grpc_ssl_server_credentials;
static void ssl_destroy(grpc_credentials *creds) { static void ssl_destroy(grpc_credentials *creds) {
grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
@ -326,22 +315,6 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
/* -- Jwt credentials -- */ /* -- Jwt credentials -- */
typedef struct {
grpc_credentials base;
/* 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_credentials_md_store *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) { static void jwt_reset_cache(grpc_jwt_credentials *c) {
if (c->cached.jwt_md != NULL) { if (c->cached.jwt_md != NULL) {
grpc_credentials_md_store_unref(c->cached.jwt_md); grpc_credentials_md_store_unref(c->cached.jwt_md);
@ -384,7 +357,8 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
if (c->cached.service_url != NULL && if (c->cached.service_url != NULL &&
strcmp(c->cached.service_url, service_url) == 0 && strcmp(c->cached.service_url, service_url) == 0 &&
c->cached.jwt_md != NULL && c->cached.jwt_md != NULL &&
(gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration, gpr_now()), (gpr_time_cmp(gpr_time_sub(c->cached.jwt_expiration,
gpr_now(GPR_CLOCK_REALTIME)),
refresh_threshold) > 0)) { refresh_threshold) > 0)) {
jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md); jwt_md = grpc_credentials_md_store_ref(c->cached.jwt_md);
} }
@ -401,7 +375,8 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
char *md_value; char *md_value;
gpr_asprintf(&md_value, "Bearer %s", jwt); gpr_asprintf(&md_value, "Bearer %s", jwt);
gpr_free(jwt); gpr_free(jwt);
c->cached.jwt_expiration = gpr_time_add(gpr_now(), c->jwt_lifetime); c->cached.jwt_expiration =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c->jwt_lifetime);
c->cached.service_url = gpr_strdup(service_url); c->cached.service_url = gpr_strdup(service_url);
c->cached.jwt_md = grpc_credentials_md_store_create(1); c->cached.jwt_md = grpc_credentials_md_store_create(1);
grpc_credentials_md_store_add_cstrings( grpc_credentials_md_store_add_cstrings(
@ -424,10 +399,9 @@ static grpc_credentials_vtable jwt_vtable = {
jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only, jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
jwt_get_request_metadata, NULL}; jwt_get_request_metadata, NULL};
grpc_credentials *grpc_jwt_credentials_create(const char *json_key, grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key(
gpr_timespec token_lifetime) { grpc_auth_json_key key, gpr_timespec token_lifetime) {
grpc_jwt_credentials *c; 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)) { if (!grpc_auth_json_key_is_valid(&key)) {
gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation"); gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
return NULL; return NULL;
@ -444,25 +418,13 @@ grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
return &c->base; return &c->base;
} }
/* -- Oauth2TokenFetcher credentials -- */ grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
gpr_timespec token_lifetime) {
/* This object is a base for credentials that need to acquire an oauth2 token return grpc_jwt_credentials_create_from_auth_json_key(
from an http service. */ grpc_auth_json_key_create_from_string(json_key), token_lifetime);
}
typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req,
grpc_httpcli_context *http_context,
grpc_pollset *pollset,
grpc_httpcli_response_cb response_cb,
gpr_timespec deadline);
typedef struct { /* -- Oauth2TokenFetcher credentials -- */
grpc_credentials base;
gpr_mu mu;
grpc_credentials_md_store *access_token_md;
gpr_timespec token_expiration;
grpc_httpcli_context httpcli_context;
grpc_fetch_oauth2_func fetch_func;
} grpc_oauth2_token_fetcher_credentials;
static void oauth2_token_fetcher_destroy(grpc_credentials *creds) { static void oauth2_token_fetcher_destroy(grpc_credentials *creds) {
grpc_oauth2_token_fetcher_credentials *c = grpc_oauth2_token_fetcher_credentials *c =
@ -585,7 +547,8 @@ static void on_oauth2_token_fetcher_http_response(
status = grpc_oauth2_token_fetcher_credentials_parse_server_response( status = grpc_oauth2_token_fetcher_credentials_parse_server_response(
response, &c->access_token_md, &token_lifetime); response, &c->access_token_md, &token_lifetime);
if (status == GRPC_CREDENTIALS_OK) { if (status == GRPC_CREDENTIALS_OK) {
c->token_expiration = gpr_time_add(gpr_now(), token_lifetime); c->token_expiration =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), token_lifetime);
r->cb(r->user_data, c->access_token_md->entries, r->cb(r->user_data, c->access_token_md->entries,
c->access_token_md->num_entries, status); c->access_token_md->num_entries, status);
} else { } else {
@ -607,8 +570,9 @@ static void oauth2_token_fetcher_get_request_metadata(
{ {
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
if (c->access_token_md != NULL && if (c->access_token_md != NULL &&
(gpr_time_cmp(gpr_time_sub(c->token_expiration, gpr_now()), (gpr_time_cmp(
refresh_threshold) > 0)) { gpr_time_sub(c->token_expiration, gpr_now(GPR_CLOCK_REALTIME)),
refresh_threshold) > 0)) {
cached_access_token_md = cached_access_token_md =
grpc_credentials_md_store_ref(c->access_token_md); grpc_credentials_md_store_ref(c->access_token_md);
} }
@ -622,7 +586,7 @@ static void oauth2_token_fetcher_get_request_metadata(
c->fetch_func( c->fetch_func(
grpc_credentials_metadata_request_create(creds, cb, user_data), grpc_credentials_metadata_request_create(creds, cb, user_data),
&c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response, &c->httpcli_context, pollset, on_oauth2_token_fetcher_http_response,
gpr_time_add(gpr_now(), refresh_threshold)); gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), refresh_threshold));
} }
} }
@ -669,13 +633,6 @@ grpc_credentials *grpc_compute_engine_credentials_create(void) {
/* -- ServiceAccount credentials. -- */ /* -- ServiceAccount credentials. -- */
typedef struct {
grpc_oauth2_token_fetcher_credentials base;
grpc_auth_json_key key;
char *scope;
gpr_timespec token_lifetime;
} grpc_service_account_credentials;
static void service_account_destroy(grpc_credentials *creds) { static void service_account_destroy(grpc_credentials *creds) {
grpc_service_account_credentials *c = grpc_service_account_credentials *c =
(grpc_service_account_credentials *)creds; (grpc_service_account_credentials *)creds;
@ -746,11 +703,6 @@ grpc_credentials *grpc_service_account_credentials_create(
/* -- RefreshToken credentials. -- */ /* -- RefreshToken credentials. -- */
typedef struct {
grpc_oauth2_token_fetcher_credentials base;
grpc_auth_refresh_token refresh_token;
} grpc_refresh_token_credentials;
static void refresh_token_destroy(grpc_credentials *creds) { static void refresh_token_destroy(grpc_credentials *creds) {
grpc_refresh_token_credentials *c = (grpc_refresh_token_credentials *)creds; grpc_refresh_token_credentials *c = (grpc_refresh_token_credentials *)creds;
grpc_auth_refresh_token_destruct(&c->refresh_token); grpc_auth_refresh_token_destruct(&c->refresh_token);
@ -786,12 +738,9 @@ static void refresh_token_fetch_oauth2(
gpr_free(body); gpr_free(body);
} }
grpc_credentials *grpc_refresh_token_credentials_create( grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
const char *json_refresh_token) { grpc_auth_refresh_token refresh_token) {
grpc_refresh_token_credentials *c; grpc_refresh_token_credentials *c;
grpc_auth_refresh_token refresh_token =
grpc_auth_refresh_token_create_from_string(json_refresh_token);
if (!grpc_auth_refresh_token_is_valid(&refresh_token)) { if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation"); gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
return NULL; return NULL;
@ -804,13 +753,13 @@ grpc_credentials *grpc_refresh_token_credentials_create(
return &c->base.base; return &c->base.base;
} }
/* -- Fake Oauth2 credentials. -- */ grpc_credentials *grpc_refresh_token_credentials_create(
const char *json_refresh_token) {
return grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_auth_refresh_token_create_from_string(json_refresh_token));
}
typedef struct { /* -- Fake Oauth2 credentials. -- */
grpc_credentials base;
grpc_credentials_md_store *access_token_md;
int is_async;
} grpc_fake_oauth2_credentials;
static void fake_oauth2_destroy(grpc_credentials *creds) { static void fake_oauth2_destroy(grpc_credentials *creds) {
grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds; grpc_fake_oauth2_credentials *c = (grpc_fake_oauth2_credentials *)creds;
@ -877,11 +826,6 @@ grpc_credentials *grpc_fake_oauth2_credentials_create(
/* -- Oauth2 Access Token credentials. -- */ /* -- Oauth2 Access Token credentials. -- */
typedef struct {
grpc_credentials base;
grpc_credentials_md_store *access_token_md;
} grpc_access_token_credentials;
static void access_token_destroy(grpc_credentials *creds) { static void access_token_destroy(grpc_credentials *creds) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
grpc_credentials_md_store_unref(c->access_token_md); grpc_credentials_md_store_unref(c->access_token_md);
@ -996,12 +940,6 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
/* -- Composite credentials. -- */ /* -- Composite credentials. -- */
typedef struct {
grpc_credentials base;
grpc_credentials_array inner;
grpc_credentials *connector_creds;
} grpc_composite_credentials;
typedef struct { typedef struct {
grpc_composite_credentials *composite_creds; grpc_composite_credentials *composite_creds;
size_t creds_index; size_t creds_index;
@ -1232,11 +1170,6 @@ grpc_credentials *grpc_credentials_contains_type(
/* -- IAM credentials. -- */ /* -- IAM credentials. -- */
typedef struct {
grpc_credentials base;
grpc_credentials_md_store *iam_md;
} grpc_iam_credentials;
static void iam_destroy(grpc_credentials *creds) { static void iam_destroy(grpc_credentials *creds) {
grpc_iam_credentials *c = (grpc_iam_credentials *)creds; grpc_iam_credentials *c = (grpc_iam_credentials *)creds;
grpc_credentials_md_store_unref(c->iam_md); grpc_credentials_md_store_unref(c->iam_md);

@ -39,6 +39,8 @@
#include <grpc/grpc_security.h> #include <grpc/grpc_security.h>
#include <grpc/support/sync.h> #include <grpc/support/sync.h>
#include "src/core/httpcli/httpcli.h"
#include "src/core/security/json_token.h"
#include "src/core/security/security_connector.h" #include "src/core/security/security_connector.h"
struct grpc_httpcli_response; struct grpc_httpcli_response;
@ -178,11 +180,22 @@ grpc_credentials_status
grpc_oauth2_token_fetcher_credentials_parse_server_response( grpc_oauth2_token_fetcher_credentials_parse_server_response(
const struct grpc_httpcli_response *response, const struct grpc_httpcli_response *response,
grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime); grpc_credentials_md_store **token_md, gpr_timespec *token_lifetime);
void grpc_flush_cached_google_default_credentials(void);
/* Simulates an oauth2 token fetch with the specified value for testing. */ /* Simulates an oauth2 token fetch with the specified value for testing. */
grpc_credentials *grpc_fake_oauth2_credentials_create( grpc_credentials *grpc_fake_oauth2_credentials_create(
const char *token_md_value, int is_async); const char *token_md_value, int is_async);
/* Private constructor for jwt credentials from an already parsed json key.
Takes ownership of the key. */
grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key(
grpc_auth_json_key key, gpr_timespec token_lifetime);
/* Private constructor for refresh token credentials from an already parsed
refresh token. Takes ownership of the refresh token. */
grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_auth_refresh_token token);
/* --- grpc_server_credentials. --- */ /* --- grpc_server_credentials. --- */
typedef struct { typedef struct {
@ -199,4 +212,103 @@ struct grpc_server_credentials {
grpc_security_status grpc_server_credentials_create_security_connector( grpc_security_status grpc_server_credentials_create_security_connector(
grpc_server_credentials *creds, grpc_security_connector **sc); grpc_server_credentials *creds, grpc_security_connector **sc);
/* -- Ssl credentials. -- */
typedef struct {
grpc_credentials base;
grpc_ssl_config config;
} grpc_ssl_credentials;
typedef struct {
grpc_server_credentials base;
grpc_ssl_server_config config;
} grpc_ssl_server_credentials;
/* -- Jwt credentials -- */
typedef struct {
grpc_credentials base;
/* 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_credentials_md_store *jwt_md;
char *service_url;
gpr_timespec jwt_expiration;
} cached;
grpc_auth_json_key key;
gpr_timespec jwt_lifetime;
} grpc_jwt_credentials;
/* -- Oauth2TokenFetcher credentials --
This object is a base for credentials that need to acquire an oauth2 token
from an http service. */
typedef struct grpc_credentials_metadata_request
grpc_credentials_metadata_request;
typedef void (*grpc_fetch_oauth2_func)(grpc_credentials_metadata_request *req,
grpc_httpcli_context *http_context,
grpc_pollset *pollset,
grpc_httpcli_response_cb response_cb,
gpr_timespec deadline);
typedef struct {
grpc_credentials base;
gpr_mu mu;
grpc_credentials_md_store *access_token_md;
gpr_timespec token_expiration;
grpc_httpcli_context httpcli_context;
grpc_fetch_oauth2_func fetch_func;
} grpc_oauth2_token_fetcher_credentials;
/* -- ServiceAccount credentials. -- */
typedef struct {
grpc_oauth2_token_fetcher_credentials base;
grpc_auth_json_key key;
char *scope;
gpr_timespec token_lifetime;
} grpc_service_account_credentials;
/* -- RefreshToken credentials. -- */
typedef struct {
grpc_oauth2_token_fetcher_credentials base;
grpc_auth_refresh_token refresh_token;
} grpc_refresh_token_credentials;
/* -- Oauth2 Access Token credentials. -- */
typedef struct {
grpc_credentials base;
grpc_credentials_md_store *access_token_md;
} grpc_access_token_credentials;
/* -- Fake Oauth2 credentials. -- */
typedef struct {
grpc_credentials base;
grpc_credentials_md_store *access_token_md;
int is_async;
} grpc_fake_oauth2_credentials;
/* -- IAM credentials. -- */
typedef struct {
grpc_credentials base;
grpc_credentials_md_store *iam_md;
} grpc_iam_credentials;
/* -- Composite credentials. -- */
typedef struct {
grpc_credentials base;
grpc_credentials_array inner;
grpc_credentials *connector_creds;
} grpc_composite_credentials;
#endif /* GRPC_INTERNAL_CORE_SECURITY_CREDENTIALS_H */ #endif /* GRPC_INTERNAL_CORE_SECURITY_CREDENTIALS_H */

@ -46,7 +46,6 @@
/* -- Constants. -- */ /* -- Constants. -- */
#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" #define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal"
#define GRPC_GOOGLE_CREDENTIALS_ENV_VAR "GOOGLE_APPLICATION_CREDENTIALS"
/* -- Default credentials. -- */ /* -- Default credentials. -- */
@ -104,9 +103,10 @@ static int is_stack_running_on_compute_engine(void) {
grpc_httpcli_context_init(&context); grpc_httpcli_context_init(&context);
grpc_httpcli_get(&context, &detector.pollset, &request, grpc_httpcli_get(
gpr_time_add(gpr_now(), max_detection_delay), &context, &detector.pollset, &request,
on_compute_engine_detection_http_response, &detector); gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), max_detection_delay),
on_compute_engine_detection_http_response, &detector);
/* Block until we get the response. This is not ideal but this should only be /* Block until we get the response. This is not ideal but this should only be
called once for the lifetime of the process by the default credentials. */ called once for the lifetime of the process by the default credentials. */
@ -123,36 +123,40 @@ static int is_stack_running_on_compute_engine(void) {
} }
/* Takes ownership of creds_path if not NULL. */ /* Takes ownership of creds_path if not NULL. */
static grpc_credentials *create_jwt_creds_from_path(char *creds_path) { static grpc_credentials *create_default_creds_from_path(char *creds_path) {
grpc_json *json = NULL;
grpc_auth_json_key key;
grpc_auth_refresh_token token;
grpc_credentials *result = NULL; grpc_credentials *result = NULL;
gpr_slice creds_data; gpr_slice creds_data = gpr_empty_slice();
int file_ok = 0; int file_ok = 0;
if (creds_path == NULL) return NULL; if (creds_path == NULL) goto end;
creds_data = gpr_load_file(creds_path, 1, &file_ok); creds_data = gpr_load_file(creds_path, 0, &file_ok);
gpr_free(creds_path); if (!file_ok) goto end;
if (file_ok) { json = grpc_json_parse_string_with_len(
result = grpc_jwt_credentials_create( (char *)GPR_SLICE_START_PTR(creds_data), GPR_SLICE_LENGTH(creds_data));
(const char *)GPR_SLICE_START_PTR(creds_data), if (json == NULL) goto end;
grpc_max_auth_token_lifetime);
gpr_slice_unref(creds_data); /* First, try an auth json key. */
key = grpc_auth_json_key_create_from_json(json);
if (grpc_auth_json_key_is_valid(&key)) {
result = grpc_jwt_credentials_create_from_auth_json_key(
key, grpc_max_auth_token_lifetime);
goto end;
} }
return result;
}
/* Takes ownership of creds_path if not NULL. */ /* Then try a refresh token if the auth json key was invalid. */
static grpc_credentials *create_refresh_token_creds_from_path( token = grpc_auth_refresh_token_create_from_json(json);
char *creds_path) { if (grpc_auth_refresh_token_is_valid(&token)) {
grpc_credentials *result = NULL; result =
gpr_slice creds_data; grpc_refresh_token_credentials_create_from_auth_refresh_token(token);
int file_ok = 0; goto end;
if (creds_path == NULL) return NULL;
creds_data = gpr_load_file(creds_path, 1, &file_ok);
gpr_free(creds_path);
if (file_ok) {
result = grpc_refresh_token_credentials_create(
(const char *)GPR_SLICE_START_PTR(creds_data));
gpr_slice_unref(creds_data);
} }
end:
if (creds_path != NULL) gpr_free(creds_path);
gpr_slice_unref(creds_data);
if (json != NULL) grpc_json_destroy(json);
return result; return result;
} }
@ -170,12 +174,12 @@ grpc_credentials *grpc_google_default_credentials_create(void) {
} }
/* First, try the environment variable. */ /* First, try the environment variable. */
result = result = create_default_creds_from_path(
create_jwt_creds_from_path(gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR)); gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
if (result != NULL) goto end; if (result != NULL) goto end;
/* Then the well-known file. */ /* Then the well-known file. */
result = create_refresh_token_creds_from_path( result = create_default_creds_from_path(
grpc_get_well_known_google_credentials_file_path()); grpc_get_well_known_google_credentials_file_path());
if (result != NULL) goto end; if (result != NULL) goto end;
@ -193,11 +197,24 @@ end:
if (!serving_cached_credentials && result != NULL) { if (!serving_cached_credentials && result != NULL) {
/* Blend with default ssl credentials and add a global reference so that it /* Blend with default ssl credentials and add a global reference so that it
can be cached and re-served. */ can be cached and re-served. */
result = grpc_composite_credentials_create( grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL);
grpc_ssl_credentials_create(NULL, NULL), result); default_credentials = grpc_credentials_ref(grpc_composite_credentials_create(
GPR_ASSERT(result != NULL); ssl_creds, result));
default_credentials = grpc_credentials_ref(result); GPR_ASSERT(default_credentials != NULL);
grpc_credentials_unref(ssl_creds);
grpc_credentials_unref(result);
result = default_credentials;
} }
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
return result; return result;
} }
void grpc_flush_cached_google_default_credentials(void) {
gpr_once_init(&g_once, init_default_credentials);
gpr_mu_lock(&g_mu);
if (default_credentials != NULL) {
grpc_credentials_unref(default_credentials);
default_credentials = NULL;
}
gpr_mu_unlock(&g_mu);
}

@ -46,17 +46,11 @@
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include "src/core/json/json.h"
/* --- Constants. --- */ /* --- Constants. --- */
/* 1 hour max. */ /* 1 hour max. */
const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0}; const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0};
#define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
#define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256" #define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256"
#define GRPC_JWT_TYPE "JWT" #define GRPC_JWT_TYPE "JWT"
@ -66,7 +60,7 @@ static grpc_jwt_encode_and_sign_override g_jwt_encode_and_sign_override = NULL;
/* --- grpc_auth_json_key. --- */ /* --- grpc_auth_json_key. --- */
static const char *json_get_string_property(grpc_json *json, static const char *json_get_string_property(const grpc_json *json,
const char *prop_name) { const char *prop_name) {
grpc_json *child; grpc_json *child;
for (child = json->child; child != NULL; child = child->next) { for (child = json->child; child != NULL; child = child->next) {
@ -79,7 +73,8 @@ static const char *json_get_string_property(grpc_json *json,
return child->value; return child->value;
} }
static int set_json_key_string_property(grpc_json *json, const char *prop_name, static int set_json_key_string_property(const grpc_json *json,
const char *prop_name,
char **json_key_field) { char **json_key_field) {
const char *prop_value = json_get_string_property(json, prop_name); const char *prop_value = json_get_string_property(json, prop_name);
if (prop_value == NULL) return 0; if (prop_value == NULL) return 0;
@ -92,11 +87,8 @@ int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key) {
strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID); strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID);
} }
grpc_auth_json_key grpc_auth_json_key_create_from_string( grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json) {
const char *json_string) {
grpc_auth_json_key result; grpc_auth_json_key result;
char *scratchpad = gpr_strdup(json_string);
grpc_json *json = grpc_json_parse_string(scratchpad);
BIO *bio = NULL; BIO *bio = NULL;
const char *prop_value; const char *prop_value;
int success = 0; int success = 0;
@ -104,7 +96,7 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string(
memset(&result, 0, sizeof(grpc_auth_json_key)); memset(&result, 0, sizeof(grpc_auth_json_key));
result.type = GRPC_AUTH_JSON_TYPE_INVALID; result.type = GRPC_AUTH_JSON_TYPE_INVALID;
if (json == NULL) { if (json == NULL) {
gpr_log(GPR_ERROR, "Invalid json string %s", json_string); gpr_log(GPR_ERROR, "Invalid json.");
goto end; goto end;
} }
@ -142,8 +134,16 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string(
end: end:
if (bio != NULL) BIO_free(bio); if (bio != NULL) BIO_free(bio);
if (json != NULL) grpc_json_destroy(json);
if (!success) grpc_auth_json_key_destruct(&result); if (!success) grpc_auth_json_key_destruct(&result);
return result;
}
grpc_auth_json_key grpc_auth_json_key_create_from_string(
const char *json_string) {
char *scratchpad = gpr_strdup(json_string);
grpc_json *json = grpc_json_parse_string(scratchpad);
grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json);
if (json != NULL) grpc_json_destroy(json);
gpr_free(scratchpad); gpr_free(scratchpad);
return result; return result;
} }
@ -207,7 +207,7 @@ static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
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_CLOCK_REALTIME);
gpr_timespec expiration = gpr_time_add(now, token_lifetime); gpr_timespec expiration = gpr_time_add(now, token_lifetime);
char now_str[GPR_LTOA_MIN_BUFSIZE]; char now_str[GPR_LTOA_MIN_BUFSIZE];
char expiration_str[GPR_LTOA_MIN_BUFSIZE]; char expiration_str[GPR_LTOA_MIN_BUFSIZE];
@ -218,8 +218,8 @@ static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
gpr_ltoa(now.tv_sec, now_str); gpr_ltoa(now.tv_sec, now_str);
gpr_ltoa(expiration.tv_sec, expiration_str); gpr_ltoa(expiration.tv_sec, expiration_str);
child = create_child(NULL, json, "iss", json_key->client_email, child =
GRPC_JSON_STRING); create_child(NULL, json, "iss", json_key->client_email, GRPC_JSON_STRING);
if (scope != NULL) { if (scope != NULL) {
child = create_child(child, json, "scope", scope, GRPC_JSON_STRING); child = create_child(child, json, "scope", scope, GRPC_JSON_STRING);
} else { } else {
@ -342,18 +342,16 @@ int grpc_auth_refresh_token_is_valid(
strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID); strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID);
} }
grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
const char *json_string) { const grpc_json *json) {
grpc_auth_refresh_token result; grpc_auth_refresh_token result;
char *scratchpad = gpr_strdup(json_string);
grpc_json *json = grpc_json_parse_string(scratchpad);
const char *prop_value; const char *prop_value;
int success = 0; int success = 0;
memset(&result, 0, sizeof(grpc_auth_refresh_token)); memset(&result, 0, sizeof(grpc_auth_refresh_token));
result.type = GRPC_AUTH_JSON_TYPE_INVALID; result.type = GRPC_AUTH_JSON_TYPE_INVALID;
if (json == NULL) { if (json == NULL) {
gpr_log(GPR_ERROR, "Invalid json string %s", json_string); gpr_log(GPR_ERROR, "Invalid json.");
goto end; goto end;
} }
@ -374,8 +372,17 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
success = 1; success = 1;
end: end:
if (json != NULL) grpc_json_destroy(json);
if (!success) grpc_auth_refresh_token_destruct(&result); if (!success) grpc_auth_refresh_token_destruct(&result);
return result;
}
grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
const char *json_string) {
char *scratchpad = gpr_strdup(json_string);
grpc_json *json = grpc_json_parse_string(scratchpad);
grpc_auth_refresh_token result =
grpc_auth_refresh_token_create_from_json(json);
if (json != NULL) grpc_json_destroy(json);
gpr_free(scratchpad); gpr_free(scratchpad);
return result; return result;
} }
@ -396,4 +403,3 @@ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) {
refresh_token->refresh_token = NULL; refresh_token->refresh_token = NULL;
} }
} }

@ -37,10 +37,16 @@
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include "src/core/json/json.h"
/* --- Constants. --- */ /* --- Constants. --- */
#define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token" #define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
#define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
/* --- auth_json_key parsing. --- */ /* --- auth_json_key parsing. --- */
typedef struct { typedef struct {
@ -59,6 +65,10 @@ int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key);
grpc_auth_json_key grpc_auth_json_key_create_from_string( grpc_auth_json_key grpc_auth_json_key_create_from_string(
const char *json_string); const char *json_string);
/* Creates a json_key object from parsed json. Returns an invalid object if a
parsing error has been encountered. */
grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json);
/* Destructs the object. */ /* Destructs the object. */
void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key); void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key);
@ -97,6 +107,11 @@ int grpc_auth_refresh_token_is_valid(
grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
const char *json_string); const char *json_string);
/* Creates a refresh token object from parsed json. Returns an invalid object if
a parsing error has been encountered. */
grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
const grpc_json *json);
/* Destructs the object. */ /* Destructs the object. */
void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token); void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token);

@ -189,7 +189,6 @@ struct grpc_jwt_claims {
gpr_slice buffer; gpr_slice buffer;
}; };
void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) { void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) {
grpc_json_destroy(claims->json); grpc_json_destroy(claims->json);
gpr_slice_unref(claims->buffer); gpr_slice_unref(claims->buffer);
@ -286,12 +285,14 @@ grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
GPR_ASSERT(claims != NULL); GPR_ASSERT(claims != NULL);
skewed_now = gpr_time_add(gpr_now(), grpc_jwt_verifier_clock_skew); skewed_now =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
if (gpr_time_cmp(skewed_now, claims->nbf) < 0) { if (gpr_time_cmp(skewed_now, claims->nbf) < 0) {
gpr_log(GPR_ERROR, "JWT is not valid yet."); gpr_log(GPR_ERROR, "JWT is not valid yet.");
return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
} }
skewed_now = gpr_time_sub(gpr_now(), grpc_jwt_verifier_clock_skew); skewed_now =
gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
if (gpr_time_cmp(skewed_now, claims->exp) > 0) { if (gpr_time_cmp(skewed_now, claims->exp) > 0) {
gpr_log(GPR_ERROR, "JWT is expired."); gpr_log(GPR_ERROR, "JWT is expired.");
return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE; return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
@ -327,10 +328,10 @@ typedef struct {
/* Takes ownership of the header, claims and signature. */ /* Takes ownership of the header, claims and signature. */
static verifier_cb_ctx *verifier_cb_ctx_create( static verifier_cb_ctx *verifier_cb_ctx_create(
grpc_jwt_verifier *verifier, grpc_pollset *pollset, grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header,
jose_header * header, grpc_jwt_claims *claims, const char *audience, grpc_jwt_claims *claims, const char *audience, gpr_slice signature,
gpr_slice signature, const char *signed_jwt, size_t signed_jwt_len, const char *signed_jwt, size_t signed_jwt_len, void *user_data,
void *user_data, grpc_jwt_verification_done_cb cb) { grpc_jwt_verification_done_cb cb) {
verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx)); verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx));
memset(ctx, 0, sizeof(verifier_cb_ctx)); memset(ctx, 0, sizeof(verifier_cb_ctx));
ctx->verifier = verifier; ctx->verifier = verifier;
@ -604,7 +605,7 @@ end:
static void on_openid_config_retrieved(void *user_data, static void on_openid_config_retrieved(void *user_data,
const grpc_httpcli_response *response) { const grpc_httpcli_response *response) {
const grpc_json* cur; const grpc_json *cur;
grpc_json *json = json_from_http(response); grpc_json *json = json_from_http(response);
verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data; verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
grpc_httpcli_request req; grpc_httpcli_request req;
@ -632,9 +633,10 @@ static void on_openid_config_retrieved(void *user_data,
} else { } else {
*(req.host + (req.path - jwks_uri)) = '\0'; *(req.host + (req.path - jwks_uri)) = '\0';
} }
grpc_httpcli_get(&ctx->verifier->http_ctx, ctx->pollset, &req, grpc_httpcli_get(
gpr_time_add(gpr_now(), grpc_jwt_verifier_max_delay), &ctx->verifier->http_ctx, ctx->pollset, &req,
on_keys_retrieved, ctx); gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
on_keys_retrieved, ctx);
grpc_json_destroy(json); grpc_json_destroy(json);
gpr_free(req.host); gpr_free(req.host);
return; return;
@ -645,8 +647,8 @@ error:
verifier_cb_ctx_destroy(ctx); verifier_cb_ctx_destroy(ctx);
} }
static email_key_mapping *verifier_get_mapping( static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v,
grpc_jwt_verifier *v, const char *email_domain) { const char *email_domain) {
size_t i; size_t i;
if (v->mappings == NULL) return NULL; if (v->mappings == NULL) return NULL;
for (i = 0; i < v->num_mappings; i++) { for (i = 0; i < v->num_mappings; i++) {
@ -733,9 +735,10 @@ static void retrieve_key_and_verify(verifier_cb_ctx *ctx) {
http_cb = on_openid_config_retrieved; http_cb = on_openid_config_retrieved;
} }
grpc_httpcli_get(&ctx->verifier->http_ctx, ctx->pollset, &req, grpc_httpcli_get(
gpr_time_add(gpr_now(), grpc_jwt_verifier_max_delay), &ctx->verifier->http_ctx, ctx->pollset, &req,
http_cb, ctx); gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
http_cb, ctx);
gpr_free(req.host); gpr_free(req.host);
gpr_free(req.path); gpr_free(req.path);
return; return;
@ -764,7 +767,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
dot = strchr(cur, '.'); dot = strchr(cur, '.');
if (dot == NULL) goto error; if (dot == NULL) goto error;
json = parse_json_part_from_jwt(cur, dot - cur, &header_buffer); json = parse_json_part_from_jwt(cur, dot - cur, &header_buffer);
if (json == NULL) goto error; if (json == NULL) goto error;
header = jose_header_from_json(json, header_buffer); header = jose_header_from_json(json, header_buffer);
if (header == NULL) goto error; if (header == NULL) goto error;
@ -772,7 +775,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier,
dot = strchr(cur, '.'); dot = strchr(cur, '.');
if (dot == NULL) goto error; if (dot == NULL) goto error;
json = parse_json_part_from_jwt(cur, dot - cur, &claims_buffer); json = parse_json_part_from_jwt(cur, dot - cur, &claims_buffer);
if (json == NULL) goto error; if (json == NULL) goto error;
claims = grpc_jwt_claims_from_json(json, claims_buffer); claims = grpc_jwt_claims_from_json(json, claims_buffer);
if (claims == NULL) goto error; if (claims == NULL) goto error;
@ -827,4 +830,3 @@ void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) {
} }
gpr_free(v); gpr_free(v);
} }

@ -69,12 +69,20 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call,
return GRPC_CALL_OK; return GRPC_CALL_OK;
} }
const grpc_auth_context *grpc_call_auth_context(grpc_call *call) { grpc_auth_context *grpc_call_auth_context(grpc_call *call) {
void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY); void *sec_ctx = grpc_call_context_get(call, GRPC_CONTEXT_SECURITY);
if (sec_ctx == NULL) return NULL; if (sec_ctx == NULL) return NULL;
return grpc_call_is_client(call) return grpc_call_is_client(call)
? ((grpc_client_security_context *)sec_ctx)->auth_context ? GRPC_AUTH_CONTEXT_REF(
: ((grpc_server_security_context *)sec_ctx)->auth_context; ((grpc_client_security_context *)sec_ctx)->auth_context,
"grpc_call_auth_context client")
: GRPC_AUTH_CONTEXT_REF(
((grpc_server_security_context *)sec_ctx)->auth_context,
"grpc_call_auth_context server");
}
void grpc_auth_context_release(grpc_auth_context *context) {
GRPC_AUTH_CONTEXT_UNREF(context, "grpc_auth_context_unref");
} }
/* --- grpc_client_security_context --- */ /* --- grpc_client_security_context --- */

@ -36,6 +36,10 @@
#include "src/core/security/credentials.h" #include "src/core/security/credentials.h"
#ifdef __cplusplus
extern "C" {
#endif
/* --- grpc_auth_context --- /* --- grpc_auth_context ---
High level authentication context object. Can optionally be chained. */ High level authentication context object. Can optionally be chained. */
@ -103,5 +107,9 @@ typedef struct {
grpc_server_security_context *grpc_server_security_context_create(void); grpc_server_security_context *grpc_server_security_context_create(void);
void grpc_server_security_context_destroy(void *ctx); void grpc_server_security_context_destroy(void *ctx);
#ifdef __cplusplus
}
#endif
#endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */ #endif /* GRPC_INTERNAL_CORE_SECURITY_SECURITY_CONTEXT_H */

@ -157,7 +157,7 @@ static void record_stats(census_ht* store, census_op_id op_id,
key.ptr = gpr_strdup(key.ptr); key.ptr = gpr_strdup(key.ptr);
census_ht_insert(store, key, (void*)window_stats); census_ht_insert(store, key, (void*)window_stats);
} }
census_window_stats_add(window_stats, gpr_now(), stats); census_window_stats_add(window_stats, gpr_now(GPR_CLOCK_REALTIME), stats);
} else { } else {
census_internal_unlock_trace_store(); census_internal_unlock_trace_store();
} }
@ -185,7 +185,7 @@ static void get_stats(census_ht* store, census_aggregated_rpc_stats* data) {
if (store != NULL) { if (store != NULL) {
size_t n; size_t n;
unsigned i, j; unsigned i, j;
gpr_timespec now = gpr_now(); gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
census_ht_kv* kv = census_ht_get_all_elements(store, &n); census_ht_kv* kv = census_ht_get_all_elements(store, &n);
if (kv != NULL) { if (kv != NULL) {
data->num_entries = n; data->num_entries = n;

@ -94,7 +94,7 @@ census_op_id census_tracing_start_op(void) {
g_id++; g_id++;
memcpy(&ret->id, &g_id, sizeof(census_op_id)); memcpy(&ret->id, &g_id, sizeof(census_op_id));
ret->rpc_stats.cnt = 1; ret->rpc_stats.cnt = 1;
ret->ts = gpr_now(); ret->ts = gpr_now(GPR_CLOCK_REALTIME);
census_ht_insert(g_trace_store, op_id_as_key(&ret->id), (void*)ret); census_ht_insert(g_trace_store, op_id_as_key(&ret->id), (void*)ret);
gpr_log(GPR_DEBUG, "Start tracing for id %lu", g_id); gpr_log(GPR_DEBUG, "Start tracing for id %lu", g_id);
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
@ -122,7 +122,7 @@ void census_tracing_print(census_op_id op_id, const char* anno_txt) {
trace = census_ht_find(g_trace_store, op_id_as_key(&op_id)); trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
if (trace != NULL) { if (trace != NULL) {
census_trace_annotation* anno = gpr_malloc(sizeof(census_trace_annotation)); census_trace_annotation* anno = gpr_malloc(sizeof(census_trace_annotation));
anno->ts = gpr_now(); anno->ts = gpr_now(GPR_CLOCK_REALTIME);
{ {
char* d = anno->txt; char* d = anno->txt;
const char* s = anno_txt; const char* s = anno_txt;
@ -143,8 +143,8 @@ void census_tracing_end_op(census_op_id op_id) {
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
trace = census_ht_find(g_trace_store, op_id_as_key(&op_id)); trace = census_ht_find(g_trace_store, op_id_as_key(&op_id));
if (trace != NULL) { if (trace != NULL) {
trace->rpc_stats.elapsed_time_ms = trace->rpc_stats.elapsed_time_ms = gpr_timespec_to_micros(
gpr_timespec_to_micros(gpr_time_sub(gpr_now(), trace->ts)); gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), trace->ts));
gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us", gpr_log(GPR_DEBUG, "End tracing for id %lu, method %s, latency %f us",
op_id_2_uint64(&op_id), trace->method, op_id_2_uint64(&op_id), trace->method,
trace->rpc_stats.elapsed_time_ms); trace->rpc_stats.elapsed_time_ms);
@ -194,8 +194,8 @@ const char* census_get_trace_method_name(const census_trace_obj* trace) {
static census_trace_annotation* dup_annotation_chain( static census_trace_annotation* dup_annotation_chain(
census_trace_annotation* from) { census_trace_annotation* from) {
census_trace_annotation *ret = NULL; census_trace_annotation* ret = NULL;
census_trace_annotation **to = &ret; census_trace_annotation** to = &ret;
for (; from != NULL; from = from->next) { for (; from != NULL; from = from->next) {
*to = gpr_malloc(sizeof(census_trace_annotation)); *to = gpr_malloc(sizeof(census_trace_annotation));
memcpy(*to, from, sizeof(census_trace_annotation)); memcpy(*to, from, sizeof(census_trace_annotation));
@ -223,9 +223,9 @@ census_trace_obj** census_get_active_ops(int* num_active_ops) {
size_t n = 0; size_t n = 0;
census_ht_kv* all_kvs = census_ht_get_all_elements(g_trace_store, &n); census_ht_kv* all_kvs = census_ht_get_all_elements(g_trace_store, &n);
*num_active_ops = (int)n; *num_active_ops = (int)n;
if (n != 0 ) { if (n != 0) {
size_t i = 0; size_t i = 0;
ret = gpr_malloc(sizeof(census_trace_obj *) * n); ret = gpr_malloc(sizeof(census_trace_obj*) * n);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
ret[i] = trace_obj_dup((census_trace_obj*)all_kvs[i].v); ret[i] = trace_obj_dup((census_trace_obj*)all_kvs[i].v);
} }

@ -90,11 +90,11 @@
// Record a new event, taking 15.3ms, transferring 1784 bytes. // Record a new event, taking 15.3ms, transferring 1784 bytes.
stat.latency = 0.153; stat.latency = 0.153;
stat.bytes = 1784; stat.bytes = 1784;
census_window_stats_add(stats, gpr_now(), &stat); census_window_stats_add(stats, gpr_now(GPR_CLOCK_REALTIME), &stat);
// Get sums and print them out // Get sums and print them out
result[kMinInterval].statistic = &sums[kMinInterval]; result[kMinInterval].statistic = &sums[kMinInterval];
result[kHourInterval].statistic = &sums[kHourInterval]; result[kHourInterval].statistic = &sums[kHourInterval];
census_window_stats_get_sums(stats, gpr_now(), result); census_window_stats_get_sums(stats, gpr_now(GPR_CLOCK_REALTIME), result);
printf("%d events/min, average time %gs, average bytes %g\n", printf("%d events/min, average time %gs, average bytes %g\n",
result[kMinInterval].count, result[kMinInterval].count,
(my_stat*)result[kMinInterval].statistic->latency / (my_stat*)result[kMinInterval].statistic->latency /
@ -170,4 +170,4 @@ void census_window_stats_get_sums(const struct census_window_stats* wstats,
assertion failure). This function is thread-compatible. */ assertion failure). This function is thread-compatible. */
void census_window_stats_destroy(struct census_window_stats* wstats); void census_window_stats_destroy(struct census_window_stats* wstats);
#endif /* GRPC_INTERNAL_CORE_STATISTICS_WINDOW_STATS_H */ #endif /* GRPC_INTERNAL_CORE_STATISTICS_WINDOW_STATS_H */

@ -121,8 +121,8 @@ void gpr_cancellable_cancel(gpr_cancellable *c) {
} else { } else {
gpr_event ev; gpr_event ev;
gpr_event_init(&ev); gpr_event_init(&ev);
gpr_event_wait(&ev, gpr_event_wait(&ev, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_add(gpr_now(), gpr_time_from_micros(1000))); gpr_time_from_micros(1000)));
} }
} }
} while (failures != 0); } while (failures != 0);

@ -76,7 +76,7 @@ void gpr_default_log(gpr_log_func_args *args) {
char *prefix; char *prefix;
const char *display_file; const char *display_file;
char time_buffer[64]; char time_buffer[64];
gpr_timespec now = gpr_now(); gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
struct tm tm; struct tm tm;
final_slash = strrchr(args->file, '/'); final_slash = strrchr(args->file, '/');

@ -75,7 +75,7 @@ void gpr_default_log(gpr_log_func_args *args) {
char *final_slash; char *final_slash;
const char *display_file; const char *display_file;
char time_buffer[64]; char time_buffer[64];
gpr_timespec now = gpr_now(); gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
struct tm tm; struct tm tm;
final_slash = strrchr(args->file, '/'); final_slash = strrchr(args->file, '/');

@ -82,7 +82,7 @@ void gpr_log(const char *file, int line, gpr_log_severity severity,
/* Simple starter implementation */ /* Simple starter implementation */
void gpr_default_log(gpr_log_func_args *args) { void gpr_default_log(gpr_log_func_args *args) {
char time_buffer[64]; char time_buffer[64];
gpr_timespec now = gpr_now(); gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
struct tm tm; struct tm tm;
if (localtime_s(&tm, &now.tv_sec)) { if (localtime_s(&tm, &now.tv_sec)) {

@ -86,7 +86,7 @@ int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) {
if (gpr_time_cmp(abs_deadline, gpr_inf_future) == 0) { if (gpr_time_cmp(abs_deadline, gpr_inf_future) == 0) {
SleepConditionVariableCS(cv, &mu->cs, INFINITE); SleepConditionVariableCS(cv, &mu->cs, INFINITE);
} else { } else {
gpr_timespec now = gpr_now(); gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
gpr_int64 now_ms = now.tv_sec * 1000 + now.tv_nsec / 1000000; gpr_int64 now_ms = now.tv_sec * 1000 + now.tv_nsec / 1000000;
gpr_int64 deadline_ms = gpr_int64 deadline_ms =
abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000; abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000;

@ -55,22 +55,52 @@ static gpr_timespec gpr_from_timespec(struct timespec ts) {
return rv; return rv;
} }
gpr_timespec gpr_now(void) { /** maps gpr_clock_type --> clockid_t for clock_gettime */
static clockid_t clockid_for_gpr_clock[] = {CLOCK_MONOTONIC, CLOCK_REALTIME};
void gpr_time_init(void) {}
gpr_timespec gpr_now(gpr_clock_type clock) {
struct timespec now; struct timespec now;
clock_gettime(CLOCK_REALTIME, &now); clock_gettime(clockid_for_gpr_clock[clock], &now);
return gpr_from_timespec(now); return gpr_from_timespec(now);
} }
#else #else
/* For some reason Apple's OSes haven't implemented clock_gettime. */ /* For some reason Apple's OSes haven't implemented clock_gettime. */
#include <sys/time.h> #include <sys/time.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
static double g_time_scale;
static uint64_t g_time_start;
void gpr_time_init(void) {
mach_timebase_info_data_t tb = {0, 1};
mach_timebase_info(&tb);
g_time_scale = tb.numer;
g_time_scale /= tb.denom;
g_time_start = mach_absolute_time();
}
gpr_timespec gpr_now(void) { gpr_timespec gpr_now(gpr_clock_type clock) {
gpr_timespec now; gpr_timespec now;
struct timeval now_tv; struct timeval now_tv;
gettimeofday(&now_tv, NULL); double now_dbl;
now.tv_sec = now_tv.tv_sec;
now.tv_nsec = now_tv.tv_usec * 1000; switch (clock) {
case GPR_CLOCK_REALTIME:
gettimeofday(&now_tv, NULL);
now.tv_sec = now_tv.tv_sec;
now.tv_nsec = now_tv.tv_usec * 1000;
break;
case GPR_CLOCK_MONOTONIC:
now_dbl = (mach_absolute_time() - g_time_start) * g_time_scale;
now.tv_sec = now_dbl * 1e-9;
now.tv_nsec = now_dbl - now.tv_sec * 1e9;
break;
}
return now; return now;
} }
#endif #endif
@ -83,7 +113,7 @@ void gpr_sleep_until(gpr_timespec until) {
for (;;) { for (;;) {
/* We could simplify by using clock_nanosleep instead, but it might be /* We could simplify by using clock_nanosleep instead, but it might be
* slightly less portable. */ * slightly less portable. */
now = gpr_now(); now = gpr_now(GPR_CLOCK_REALTIME);
if (gpr_time_cmp(until, now) <= 0) { if (gpr_time_cmp(until, now) <= 0) {
return; return;
} }

@ -40,12 +40,34 @@
#include <grpc/support/time.h> #include <grpc/support/time.h>
#include <sys/timeb.h> #include <sys/timeb.h>
gpr_timespec gpr_now(void) { static LARGE_INTEGER g_start_time;
static double g_time_scale;
void gpr_time_init(void) {
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&g_start_time);
g_time_scale = 1.0 / frequency.QuadPart;
}
gpr_timespec gpr_now(gpr_clock_type clock) {
gpr_timespec now_tv; gpr_timespec now_tv;
struct _timeb now_tb; struct _timeb now_tb;
_ftime_s(&now_tb); LARGE_INTEGER timestamp;
now_tv.tv_sec = now_tb.time; double now_dbl;
now_tv.tv_nsec = now_tb.millitm * 1000000; switch (clock) {
case GPR_CLOCK_REALTIME:
_ftime_s(&now_tb);
now_tv.tv_sec = now_tb.time;
now_tv.tv_nsec = now_tb.millitm * 1000000;
break;
case GPR_CLOCK_MONOTONIC:
QueryPerformanceCounter(&timestamp);
now_dbl = (timestamp.QuadPart - g_start_time.QuadPart) * g_time_scale;
now_tv.tv_sec = (time_t)now_dbl;
now_tv.tv_nsec = (int)((now_dbl - (double)now_tv.tv_sec) * 1e9);
break;
}
return now_tv; return now_tv;
} }
@ -57,13 +79,14 @@ void gpr_sleep_until(gpr_timespec until) {
for (;;) { for (;;) {
/* We could simplify by using clock_nanosleep instead, but it might be /* We could simplify by using clock_nanosleep instead, but it might be
* slightly less portable. */ * slightly less portable. */
now = gpr_now(); now = gpr_now(GPR_CLOCK_REALTIME);
if (gpr_time_cmp(until, now) <= 0) { if (gpr_time_cmp(until, now) <= 0) {
return; return;
} }
delta = gpr_time_sub(until, now); delta = gpr_time_sub(until, now);
sleep_millis = (DWORD)delta.tv_sec * GPR_MS_PER_SEC + delta.tv_nsec / GPR_NS_PER_MS; sleep_millis =
(DWORD)delta.tv_sec * GPR_MS_PER_SEC + delta.tv_nsec / GPR_NS_PER_MS;
Sleep(sleep_millis); Sleep(sleep_millis);
} }
} }

@ -49,6 +49,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
/** The maximum number of completions possible.
Based upon the maximum number of individually queueable ops in the batch
api:
- initial metadata send
- message send
- status/close send (depending on client/server)
- initial metadata recv
- message recv
- status/close recv (depending on client/server) */
#define MAX_CONCURRENT_COMPLETIONS 6
typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state; typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state;
typedef enum { typedef enum {
@ -135,6 +146,7 @@ struct grpc_call {
grpc_mdctx *metadata_context; grpc_mdctx *metadata_context;
/* TODO(ctiller): share with cq if possible? */ /* TODO(ctiller): share with cq if possible? */
gpr_mu mu; gpr_mu mu;
gpr_mu completion_mu;
/* how far through the stream have we read? */ /* how far through the stream have we read? */
read_state read_state; read_state read_state;
@ -162,6 +174,8 @@ struct grpc_call {
gpr_uint8 error_status_set; gpr_uint8 error_status_set;
/** should the alarm be cancelled */ /** should the alarm be cancelled */
gpr_uint8 cancel_alarm; gpr_uint8 cancel_alarm;
/** bitmask of allocated completion events in completions */
gpr_uint8 allocated_completions;
/* flags with bits corresponding to write states allowing us to determine /* flags with bits corresponding to write states allowing us to determine
what was sent */ what was sent */
@ -250,6 +264,9 @@ struct grpc_call {
grpc_iomgr_closure on_done_recv; grpc_iomgr_closure on_done_recv;
grpc_iomgr_closure on_done_send; grpc_iomgr_closure on_done_send;
grpc_iomgr_closure on_done_bind; grpc_iomgr_closure on_done_bind;
/** completion events - for completion queue use */
grpc_cq_completion completions[MAX_CONCURRENT_COMPLETIONS];
}; };
#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) #define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
@ -286,6 +303,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size); gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
memset(call, 0, sizeof(grpc_call)); memset(call, 0, sizeof(grpc_call));
gpr_mu_init(&call->mu); gpr_mu_init(&call->mu);
gpr_mu_init(&call->completion_mu);
call->channel = channel; call->channel = channel;
call->cq = cq; call->cq = cq;
if (cq) { if (cq) {
@ -349,6 +367,29 @@ grpc_completion_queue *grpc_call_get_completion_queue(grpc_call *call) {
return call->cq; return call->cq;
} }
static grpc_cq_completion *allocate_completion(grpc_call *call) {
gpr_uint8 i;
gpr_mu_lock(&call->completion_mu);
for (i = 0; i < GPR_ARRAY_SIZE(call->completions); i++) {
if (call->allocated_completions & (1u << i)) {
continue;
}
call->allocated_completions |= 1u << i;
gpr_mu_unlock(&call->completion_mu);
return &call->completions[i];
}
gpr_log(GPR_ERROR, "should never reach here");
abort();
}
static void done_completion(void *call, grpc_cq_completion *completion) {
grpc_call *c = call;
gpr_mu_lock(&c->completion_mu);
c->allocated_completions &= ~(1u << (completion - c->completions));
gpr_mu_unlock(&c->completion_mu);
GRPC_CALL_INTERNAL_UNREF(c, "completion", 1);
}
#ifdef GRPC_CALL_REF_COUNT_DEBUG #ifdef GRPC_CALL_REF_COUNT_DEBUG
void grpc_call_internal_ref(grpc_call *c, const char *reason) { void grpc_call_internal_ref(grpc_call *c, const char *reason) {
gpr_log(GPR_DEBUG, "CALL: ref %p %d -> %d [%s]", c, gpr_log(GPR_DEBUG, "CALL: ref %p %d -> %d [%s]", c,
@ -365,6 +406,7 @@ static void destroy_call(void *call, int ignored_success) {
grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c));
GRPC_CHANNEL_INTERNAL_UNREF(c->channel, "call"); GRPC_CHANNEL_INTERNAL_UNREF(c->channel, "call");
gpr_mu_destroy(&c->mu); gpr_mu_destroy(&c->mu);
gpr_mu_destroy(&c->completion_mu);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (c->status[i].details) { if (c->status[i].details) {
GRPC_MDSTR_UNREF(c->status[i].details); GRPC_MDSTR_UNREF(c->status[i].details);
@ -1201,7 +1243,8 @@ static void set_deadline_alarm(grpc_call *call, gpr_timespec deadline) {
} }
GRPC_CALL_INTERNAL_REF(call, "alarm"); GRPC_CALL_INTERNAL_REF(call, "alarm");
call->have_alarm = 1; call->have_alarm = 1;
grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); grpc_alarm_init(&call->alarm, deadline, call_alarm, call,
gpr_now(GPR_CLOCK_REALTIME));
} }
/* we offset status by a small amount when storing it into transport metadata /* we offset status by a small amount when storing it into transport metadata
@ -1329,11 +1372,13 @@ static void set_cancelled_value(grpc_status_code status, void *dest) {
} }
static void finish_batch(grpc_call *call, int success, void *tag) { static void finish_batch(grpc_call *call, int success, void *tag) {
grpc_cq_end_op(call->cq, tag, call, success); grpc_cq_end_op(call->cq, tag, success, done_completion, call,
allocate_completion(call));
} }
static void finish_batch_with_close(grpc_call *call, int success, void *tag) { static void finish_batch_with_close(grpc_call *call, int success, void *tag) {
grpc_cq_end_op(call->cq, tag, call, 1); grpc_cq_end_op(call->cq, tag, 1, done_completion, call,
allocate_completion(call));
} }
static int are_write_flags_valid(gpr_uint32 flags) { static int are_write_flags_valid(gpr_uint32 flags) {
@ -1356,8 +1401,10 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, tag); GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, tag);
if (nops == 0) { if (nops == 0) {
grpc_cq_begin_op(call->cq, call); grpc_cq_begin_op(call->cq);
grpc_cq_end_op(call->cq, tag, call, 1); GRPC_CALL_INTERNAL_REF(call, "completion");
grpc_cq_end_op(call->cq, tag, 1, done_completion, call,
allocate_completion(call));
return GRPC_CALL_OK; return GRPC_CALL_OK;
} }
@ -1479,7 +1526,8 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
} }
} }
grpc_cq_begin_op(call->cq, call); GRPC_CALL_INTERNAL_REF(call, "completion");
grpc_cq_begin_op(call->cq);
return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_func, tag); return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_func, tag);
} }

@ -91,6 +91,7 @@ grpc_channel *grpc_channel_create_from_filters(
size_t size = size_t size =
sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters); sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters);
grpc_channel *channel = gpr_malloc(size); grpc_channel *channel = gpr_malloc(size);
memset(channel, 0, sizeof(*channel));
GPR_ASSERT(grpc_is_initialized() && "call grpc_init()"); GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
channel->is_client = is_client; channel->is_client = is_client;
/* decremented by grpc_channel_destroy */ /* decremented by grpc_channel_destroy */

@ -45,34 +45,20 @@
#include <grpc/support/atm.h> #include <grpc/support/atm.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#define NUM_TAG_BUCKETS 31
/* A single event: extends grpc_event to form a linked list with a destruction
function (on_finish) that is hidden from outside this module */
typedef struct event {
grpc_event base;
struct event *queue_next;
struct event *queue_prev;
struct event *bucket_next;
struct event *bucket_prev;
} event;
/* Completion queue structure */ /* Completion queue structure */
struct grpc_completion_queue { struct grpc_completion_queue {
/* When refs drops to zero, we are in shutdown mode, and will be destroyable /** completed events */
once all queued events are drained */ grpc_cq_completion completed_head;
gpr_refcount refs; grpc_cq_completion *completed_tail;
/* Once owning_refs drops to zero, we will destroy the cq */ /** Number of pending events (+1 if we're not shutdown) */
gpr_refcount pending_events;
/** Once owning_refs drops to zero, we will destroy the cq */
gpr_refcount owning_refs; gpr_refcount owning_refs;
/* the set of low level i/o things that concern this cq */ /** the set of low level i/o things that concern this cq */
grpc_pollset pollset; grpc_pollset pollset;
/* 0 initially, 1 once we've begun shutting down */ /** 0 initially, 1 once we've begun shutting down */
int shutdown; int shutdown;
int shutdown_called; int shutdown_called;
/* Head of a linked list of queued events (prev points to the last element) */
event *queue;
/* Fixed size chained hash table of events for pluck() */
event *buckets[NUM_TAG_BUCKETS];
int is_server_cq; int is_server_cq;
}; };
@ -80,19 +66,20 @@ grpc_completion_queue *grpc_completion_queue_create(void) {
grpc_completion_queue *cc = gpr_malloc(sizeof(grpc_completion_queue)); grpc_completion_queue *cc = gpr_malloc(sizeof(grpc_completion_queue));
memset(cc, 0, sizeof(*cc)); memset(cc, 0, sizeof(*cc));
/* Initial ref is dropped by grpc_completion_queue_shutdown */ /* Initial ref is dropped by grpc_completion_queue_shutdown */
gpr_ref_init(&cc->refs, 1); gpr_ref_init(&cc->pending_events, 1);
/* One for destroy(), one for pollset_shutdown */ /* One for destroy(), one for pollset_shutdown */
gpr_ref_init(&cc->owning_refs, 2); gpr_ref_init(&cc->owning_refs, 2);
grpc_pollset_init(&cc->pollset); grpc_pollset_init(&cc->pollset);
cc->completed_tail = &cc->completed_head;
cc->completed_head.next = (gpr_uintptr)cc->completed_tail;
return cc; return cc;
} }
#ifdef GRPC_CQ_REF_COUNT_DEBUG #ifdef GRPC_CQ_REF_COUNT_DEBUG
void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason, void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
const char *file, int line) { const char *file, int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p ref %d -> %d %s", gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p ref %d -> %d %s", cc,
cc, (int)cc->owning_refs.count, (int)cc->owning_refs.count + 1, (int)cc->owning_refs.count, (int)cc->owning_refs.count + 1, reason);
reason);
#else #else
void grpc_cq_internal_ref(grpc_completion_queue *cc) { void grpc_cq_internal_ref(grpc_completion_queue *cc) {
#endif #endif
@ -107,186 +94,135 @@ static void on_pollset_destroy_done(void *arg) {
#ifdef GRPC_CQ_REF_COUNT_DEBUG #ifdef GRPC_CQ_REF_COUNT_DEBUG
void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason, void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason,
const char *file, int line) { const char *file, int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", cc,
cc, (int)cc->owning_refs.count, (int)cc->owning_refs.count - 1, (int)cc->owning_refs.count, (int)cc->owning_refs.count - 1, reason);
reason);
#else #else
void grpc_cq_internal_unref(grpc_completion_queue *cc) { void grpc_cq_internal_unref(grpc_completion_queue *cc) {
#endif #endif
if (gpr_unref(&cc->owning_refs)) { if (gpr_unref(&cc->owning_refs)) {
GPR_ASSERT(cc->queue == NULL); GPR_ASSERT(cc->completed_head.next == (gpr_uintptr)&cc->completed_head);
grpc_pollset_destroy(&cc->pollset); grpc_pollset_destroy(&cc->pollset);
gpr_free(cc); gpr_free(cc);
} }
} }
/* Create and append an event to the queue. Returns the event so that its data void grpc_cq_begin_op(grpc_completion_queue *cc) {
members can be filled in. gpr_ref(&cc->pending_events);
Requires GRPC_POLLSET_MU(&cc->pollset) locked. */
static event *add_locked(grpc_completion_queue *cc, grpc_completion_type type,
void *tag, grpc_call *call) {
event *ev = gpr_malloc(sizeof(event));
gpr_uintptr bucket = ((gpr_uintptr)tag) % NUM_TAG_BUCKETS;
ev->base.type = type;
ev->base.tag = tag;
if (cc->queue == NULL) {
cc->queue = ev->queue_next = ev->queue_prev = ev;
} else {
ev->queue_next = cc->queue;
ev->queue_prev = cc->queue->queue_prev;
ev->queue_next->queue_prev = ev->queue_prev->queue_next = ev;
}
if (cc->buckets[bucket] == NULL) {
cc->buckets[bucket] = ev->bucket_next = ev->bucket_prev = ev;
} else {
ev->bucket_next = cc->buckets[bucket];
ev->bucket_prev = cc->buckets[bucket]->bucket_prev;
ev->bucket_next->bucket_prev = ev->bucket_prev->bucket_next = ev;
}
grpc_pollset_kick(&cc->pollset);
return ev;
}
void grpc_cq_begin_op(grpc_completion_queue *cc, grpc_call *call) {
gpr_ref(&cc->refs);
if (call) GRPC_CALL_INTERNAL_REF(call, "cq");
} }
/* Signal the end of an operation - if this is the last waiting-to-be-queued /* Signal the end of an operation - if this is the last waiting-to-be-queued
event, then enter shutdown mode */ event, then enter shutdown mode */
void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, grpc_call *call, /* Queue a GRPC_OP_COMPLETED operation */
int success) { void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, int success,
event *ev; void (*done)(void *done_arg, grpc_cq_completion *storage),
int shutdown = 0; void *done_arg, grpc_cq_completion *storage) {
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); int shutdown = gpr_unref(&cc->pending_events);
ev = add_locked(cc, GRPC_OP_COMPLETE, tag, call);
ev->base.success = success; storage->tag = tag;
if (gpr_unref(&cc->refs)) { storage->done = done;
storage->done_arg = done_arg;
storage->next =
((gpr_uintptr)&cc->completed_head) | ((gpr_uintptr)(success != 0));
if (!shutdown) {
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
cc->completed_tail->next =
((gpr_uintptr)storage) | (1u & (gpr_uintptr)cc->completed_tail->next);
cc->completed_tail = storage;
grpc_pollset_kick(&cc->pollset);
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
} else {
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
cc->completed_tail->next =
((gpr_uintptr)storage) | (1u & (gpr_uintptr)cc->completed_tail->next);
cc->completed_tail = storage;
GPR_ASSERT(!cc->shutdown); GPR_ASSERT(!cc->shutdown);
GPR_ASSERT(cc->shutdown_called); GPR_ASSERT(cc->shutdown_called);
cc->shutdown = 1; cc->shutdown = 1;
shutdown = 1; gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
}
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
if (call) GRPC_CALL_INTERNAL_UNREF(call, "cq", 0);
if (shutdown) {
grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc); grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
} }
} }
/* Create a GRPC_QUEUE_SHUTDOWN event without queuing it anywhere */
static event *create_shutdown_event(void) {
event *ev = gpr_malloc(sizeof(event));
ev->base.type = GRPC_QUEUE_SHUTDOWN;
ev->base.tag = NULL;
return ev;
}
grpc_event grpc_completion_queue_next(grpc_completion_queue *cc, grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
gpr_timespec deadline) { gpr_timespec deadline) {
event *ev = NULL;
grpc_event ret; grpc_event ret;
GRPC_CQ_INTERNAL_REF(cc, "next"); GRPC_CQ_INTERNAL_REF(cc, "next");
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
for (;;) { for (;;) {
if (cc->queue != NULL) { if (cc->completed_tail != &cc->completed_head) {
gpr_uintptr bucket; grpc_cq_completion *c = (grpc_cq_completion *)cc->completed_head.next;
ev = cc->queue; cc->completed_head.next = c->next & ~(gpr_uintptr)1;
bucket = ((gpr_uintptr)ev->base.tag) % NUM_TAG_BUCKETS; if (c == cc->completed_tail) {
cc->queue = ev->queue_next; cc->completed_tail = &cc->completed_head;
ev->queue_next->queue_prev = ev->queue_prev;
ev->queue_prev->queue_next = ev->queue_next;
ev->bucket_next->bucket_prev = ev->bucket_prev;
ev->bucket_prev->bucket_next = ev->bucket_next;
if (ev == cc->buckets[bucket]) {
cc->buckets[bucket] = ev->bucket_next;
if (ev == cc->buckets[bucket]) {
cc->buckets[bucket] = NULL;
}
}
if (cc->queue == ev) {
cc->queue = NULL;
} }
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
ret.type = GRPC_OP_COMPLETE;
ret.success = c->next & 1u;
ret.tag = c->tag;
c->done(c->done_arg, c);
break; break;
} }
if (cc->shutdown) { if (cc->shutdown) {
ev = create_shutdown_event(); gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
memset(&ret, 0, sizeof(ret));
ret.type = GRPC_QUEUE_SHUTDOWN;
break; break;
} }
if (!grpc_pollset_work(&cc->pollset, deadline)) { if (!grpc_pollset_work(&cc->pollset, deadline)) {
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
memset(&ret, 0, sizeof(ret)); memset(&ret, 0, sizeof(ret));
ret.type = GRPC_QUEUE_TIMEOUT; ret.type = GRPC_QUEUE_TIMEOUT;
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret); break;
GRPC_CQ_INTERNAL_UNREF(cc, "next");
return ret;
} }
} }
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
ret = ev->base;
gpr_free(ev);
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret); GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
GRPC_CQ_INTERNAL_UNREF(cc, "next"); GRPC_CQ_INTERNAL_UNREF(cc, "next");
return ret; return ret;
} }
static event *pluck_event(grpc_completion_queue *cc, void *tag) {
gpr_uintptr bucket = ((gpr_uintptr)tag) % NUM_TAG_BUCKETS;
event *ev = cc->buckets[bucket];
if (ev == NULL) return NULL;
do {
if (ev->base.tag == tag) {
ev->queue_next->queue_prev = ev->queue_prev;
ev->queue_prev->queue_next = ev->queue_next;
ev->bucket_next->bucket_prev = ev->bucket_prev;
ev->bucket_prev->bucket_next = ev->bucket_next;
if (ev == cc->buckets[bucket]) {
cc->buckets[bucket] = ev->bucket_next;
if (ev == cc->buckets[bucket]) {
cc->buckets[bucket] = NULL;
}
}
if (cc->queue == ev) {
cc->queue = ev->queue_next;
if (cc->queue == ev) {
cc->queue = NULL;
}
}
return ev;
}
ev = ev->bucket_next;
} while (ev != cc->buckets[bucket]);
return NULL;
}
grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
gpr_timespec deadline) { gpr_timespec deadline) {
event *ev = NULL;
grpc_event ret; grpc_event ret;
grpc_cq_completion *c;
grpc_cq_completion *prev;
GRPC_CQ_INTERNAL_REF(cc, "pluck"); GRPC_CQ_INTERNAL_REF(cc, "pluck");
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
for (;;) { for (;;) {
if ((ev = pluck_event(cc, tag))) { prev = &cc->completed_head;
break; while ((c = (grpc_cq_completion *)(prev->next & ~(gpr_uintptr)1)) !=
&cc->completed_head) {
if (c->tag == tag) {
prev->next =
(prev->next & (gpr_uintptr)1) | (c->next & ~(gpr_uintptr)1);
if (c == cc->completed_tail) {
cc->completed_tail = prev;
}
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
ret.type = GRPC_OP_COMPLETE;
ret.success = c->next & 1u;
ret.tag = c->tag;
c->done(c->done_arg, c);
goto done;
}
prev = c;
} }
if (cc->shutdown) { if (cc->shutdown) {
ev = create_shutdown_event(); gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
memset(&ret, 0, sizeof(ret));
ret.type = GRPC_QUEUE_SHUTDOWN;
break; break;
} }
if (!grpc_pollset_work(&cc->pollset, deadline)) { if (!grpc_pollset_work(&cc->pollset, deadline)) {
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
memset(&ret, 0, sizeof(ret)); memset(&ret, 0, sizeof(ret));
ret.type = GRPC_QUEUE_TIMEOUT; ret.type = GRPC_QUEUE_TIMEOUT;
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret); break;
GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
return ret;
} }
} }
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); done:
ret = ev->base;
gpr_free(ev);
GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret); GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
GRPC_CQ_INTERNAL_UNREF(cc, "pluck"); GRPC_CQ_INTERNAL_UNREF(cc, "pluck");
return ret; return ret;
@ -303,7 +239,7 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
cc->shutdown_called = 1; cc->shutdown_called = 1;
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
if (gpr_unref(&cc->refs)) { if (gpr_unref(&cc->pending_events)) {
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
GPR_ASSERT(!cc->shutdown); GPR_ASSERT(!cc->shutdown);
cc->shutdown = 1; cc->shutdown = 1;
@ -324,8 +260,8 @@ grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) {
void grpc_cq_hack_spin_pollset(grpc_completion_queue *cc) { void grpc_cq_hack_spin_pollset(grpc_completion_queue *cc) {
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
grpc_pollset_kick(&cc->pollset); grpc_pollset_kick(&cc->pollset);
grpc_pollset_work(&cc->pollset, grpc_pollset_work(&cc->pollset, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_add(gpr_now(), gpr_time_from_millis(100))); gpr_time_from_millis(100)));
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
} }

@ -39,6 +39,17 @@
#include "src/core/iomgr/pollset.h" #include "src/core/iomgr/pollset.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
typedef struct grpc_cq_completion {
/** user supplied tag */
void *tag;
/** done callback - called when this queue element is no longer
needed by the completion queue */
void (*done)(void *done_arg, struct grpc_cq_completion *c);
void *done_arg;
/** next pointer; low bit is used to indicate success or not */
gpr_uintptr next;
} grpc_cq_completion;
#ifdef GRPC_CQ_REF_COUNT_DEBUG #ifdef GRPC_CQ_REF_COUNT_DEBUG
void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason, void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason,
const char *file, int line); const char *file, int line);
@ -57,11 +68,12 @@ void grpc_cq_internal_unref(grpc_completion_queue *cc);
/* Flag that an operation is beginning: the completion channel will not finish /* Flag that an operation is beginning: the completion channel will not finish
shutdown until a corrensponding grpc_cq_end_* call is made */ shutdown until a corrensponding grpc_cq_end_* call is made */
void grpc_cq_begin_op(grpc_completion_queue *cc, grpc_call *call); void grpc_cq_begin_op(grpc_completion_queue *cc);
/* Queue a GRPC_OP_COMPLETED operation */ /* Queue a GRPC_OP_COMPLETED operation */
void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, grpc_call *call, void grpc_cq_end_op(grpc_completion_queue *cc, void *tag, int success,
int success); void (*done)(void *done_arg, grpc_cq_completion *storage),
void *done_arg, grpc_cq_completion *storage);
grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc); grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc);

@ -35,6 +35,7 @@
#include <grpc/census.h> #include <grpc/census.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/time.h>
#include "src/core/channel/channel_stack.h" #include "src/core/channel/channel_stack.h"
#include "src/core/client_config/resolver_registry.h" #include "src/core/client_config/resolver_registry.h"
#include "src/core/client_config/resolvers/dns_resolver.h" #include "src/core/client_config/resolvers/dns_resolver.h"
@ -64,6 +65,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) {
gpr_time_init();
grpc_resolver_registry_init("dns:///"); grpc_resolver_registry_init("dns:///");
grpc_register_resolver_type("dns", grpc_dns_resolver_factory_create()); grpc_register_resolver_type("dns", grpc_dns_resolver_factory_create());
#ifdef GPR_POSIX_SOCKET #ifdef GPR_POSIX_SOCKET

@ -72,12 +72,14 @@ typedef struct {
typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type; typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type;
typedef struct { typedef struct requested_call {
requested_call_type type; requested_call_type type;
struct requested_call *next;
void *tag; void *tag;
grpc_completion_queue *cq_bound_to_call; grpc_completion_queue *cq_bound_to_call;
grpc_completion_queue *cq_for_notification; grpc_completion_queue *cq_for_notification;
grpc_call **call; grpc_call **call;
grpc_cq_completion completion;
union { union {
struct { struct {
grpc_call_details *details; grpc_call_details *details;
@ -92,17 +94,11 @@ typedef struct {
} data; } data;
} requested_call; } requested_call;
typedef struct {
requested_call *calls;
size_t count;
size_t capacity;
} requested_call_array;
struct registered_method { struct registered_method {
char *method; char *method;
char *host; char *host;
call_data *pending; call_data *pending;
requested_call_array requested; requested_call *requests;
registered_method *next; registered_method *next;
}; };
@ -131,6 +127,7 @@ struct channel_data {
typedef struct shutdown_tag { typedef struct shutdown_tag {
void *tag; void *tag;
grpc_completion_queue *cq; grpc_completion_queue *cq;
grpc_cq_completion completion;
} shutdown_tag; } shutdown_tag;
struct grpc_server { struct grpc_server {
@ -153,7 +150,7 @@ struct grpc_server {
gpr_mu mu_call; /* mutex for call-specific state */ gpr_mu mu_call; /* mutex for call-specific state */
registered_method *registered_methods; registered_method *registered_methods;
requested_call_array requested_calls; requested_call *requests;
gpr_uint8 shutdown; gpr_uint8 shutdown;
gpr_uint8 shutdown_published; gpr_uint8 shutdown_published;
@ -166,6 +163,9 @@ struct grpc_server {
listener *listeners; listener *listeners;
int listeners_destroyed; int listeners_destroyed;
gpr_refcount internal_refcount; gpr_refcount internal_refcount;
/** when did we print the last shutdown progress message */
gpr_timespec last_shutdown_message_time;
}; };
typedef enum { typedef enum {
@ -270,7 +270,8 @@ static void send_shutdown(grpc_channel *channel, int send_goaway,
} }
static void channel_broadcaster_shutdown(channel_broadcaster *cb, static void channel_broadcaster_shutdown(channel_broadcaster *cb,
int send_goaway, int force_disconnect) { int send_goaway,
int force_disconnect) {
size_t i; size_t i;
for (i = 0; i < cb->num_channels; i++) { for (i = 0; i < cb->num_channels; i++) {
@ -329,22 +330,6 @@ static int call_list_remove(call_data *call, call_list list) {
return 1; return 1;
} }
static void requested_call_array_destroy(requested_call_array *array) {
gpr_free(array->calls);
}
static requested_call *requested_call_array_add(requested_call_array *array) {
requested_call *rc;
if (array->count == array->capacity) {
array->capacity = GPR_MAX(array->capacity + 8, array->capacity * 2);
array->calls =
gpr_realloc(array->calls, sizeof(requested_call) * array->capacity);
}
rc = &array->calls[array->count++];
memset(rc, 0, sizeof(*rc));
return rc;
}
static void server_ref(grpc_server *server) { static void server_ref(grpc_server *server) {
gpr_ref(&server->internal_refcount); gpr_ref(&server->internal_refcount);
} }
@ -356,12 +341,10 @@ static void server_delete(grpc_server *server) {
gpr_mu_destroy(&server->mu_global); gpr_mu_destroy(&server->mu_global);
gpr_mu_destroy(&server->mu_call); gpr_mu_destroy(&server->mu_call);
gpr_free(server->channel_filters); gpr_free(server->channel_filters);
requested_call_array_destroy(&server->requested_calls);
while ((rm = server->registered_methods) != NULL) { while ((rm = server->registered_methods) != NULL) {
server->registered_methods = rm->next; server->registered_methods = rm->next;
gpr_free(rm->method); gpr_free(rm->method);
gpr_free(rm->host); gpr_free(rm->host);
requested_call_array_destroy(&rm->requested);
gpr_free(rm); gpr_free(rm);
} }
for (i = 0; i < server->cq_count; i++) { for (i = 0; i < server->cq_count; i++) {
@ -409,23 +392,24 @@ static void destroy_channel(channel_data *chand) {
static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem, static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
call_data **pending_root, call_data **pending_root,
requested_call_array *array) { requested_call **requests) {
requested_call rc; requested_call *rc;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
gpr_mu_lock(&server->mu_call); gpr_mu_lock(&server->mu_call);
if (array->count == 0) { rc = *requests;
if (rc == NULL) {
gpr_mu_lock(&calld->mu_state); gpr_mu_lock(&calld->mu_state);
calld->state = PENDING; calld->state = PENDING;
gpr_mu_unlock(&calld->mu_state); gpr_mu_unlock(&calld->mu_state);
call_list_join(pending_root, calld, PENDING_START); call_list_join(pending_root, calld, PENDING_START);
gpr_mu_unlock(&server->mu_call); gpr_mu_unlock(&server->mu_call);
} else { } else {
rc = array->calls[--array->count]; *requests = rc->next;
gpr_mu_lock(&calld->mu_state); gpr_mu_lock(&calld->mu_state);
calld->state = ACTIVATED; calld->state = ACTIVATED;
gpr_mu_unlock(&calld->mu_state); gpr_mu_unlock(&calld->mu_state);
gpr_mu_unlock(&server->mu_call); gpr_mu_unlock(&server->mu_call);
begin_call(server, calld, &rc); begin_call(server, calld, rc);
} }
} }
@ -441,14 +425,14 @@ static void start_new_rpc(grpc_call_element *elem) {
/* TODO(ctiller): unify these two searches */ /* TODO(ctiller): unify these two searches */
/* check for an exact match with host */ /* check for an exact match with host */
hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash); hash = GRPC_MDSTR_KV_HASH(calld->host->hash, calld->path->hash);
for (i = 0; i < chand->registered_method_max_probes; i++) { for (i = 0; i <= chand->registered_method_max_probes; i++) {
rm = &chand->registered_methods[(hash + i) % rm = &chand->registered_methods[(hash + i) %
chand->registered_method_slots]; chand->registered_method_slots];
if (!rm) break; if (!rm) break;
if (rm->host != calld->host) continue; if (rm->host != calld->host) continue;
if (rm->method != calld->path) continue; if (rm->method != calld->path) continue;
finish_start_new_rpc(server, elem, &rm->server_registered_method->pending, finish_start_new_rpc(server, elem, &rm->server_registered_method->pending,
&rm->server_registered_method->requested); &rm->server_registered_method->requests);
return; return;
} }
/* check for a wildcard method definition (no host set) */ /* check for a wildcard method definition (no host set) */
@ -460,12 +444,12 @@ static void start_new_rpc(grpc_call_element *elem) {
if (rm->host != NULL) continue; if (rm->host != NULL) continue;
if (rm->method != calld->path) continue; if (rm->method != calld->path) continue;
finish_start_new_rpc(server, elem, &rm->server_registered_method->pending, finish_start_new_rpc(server, elem, &rm->server_registered_method->pending,
&rm->server_registered_method->requested); &rm->server_registered_method->requests);
return; return;
} }
} }
finish_start_new_rpc(server, elem, &server->lists[PENDING_START], finish_start_new_rpc(server, elem, &server->lists[PENDING_START],
&server->requested_calls); &server->requests);
} }
static void kill_zombie(void *elem, int success) { static void kill_zombie(void *elem, int success) {
@ -481,26 +465,47 @@ static int num_listeners(grpc_server *server) {
return n; return n;
} }
static void done_shutdown_event(void *server, grpc_cq_completion *completion) {
server_unref(server);
}
static int num_channels(grpc_server *server) {
channel_data *chand;
int n = 0;
for (chand = server->root_channel_data.next;
chand != &server->root_channel_data; chand = chand->next) {
n++;
}
return n;
}
static void maybe_finish_shutdown(grpc_server *server) { static void maybe_finish_shutdown(grpc_server *server) {
size_t i; size_t i;
if (!server->shutdown || server->shutdown_published) { if (!server->shutdown || server->shutdown_published) {
return; return;
} }
if (server->root_channel_data.next != &server->root_channel_data) { if (server->root_channel_data.next != &server->root_channel_data ||
gpr_log(GPR_DEBUG, server->listeners_destroyed < num_listeners(server)) {
"Waiting for all channels to close before destroying server"); if (gpr_time_cmp(
return; gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), server->last_shutdown_message_time),
} gpr_time_from_seconds(1)) >= 0) {
if (server->listeners_destroyed < num_listeners(server)) { server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
gpr_log(GPR_DEBUG, "Waiting for all listeners to be destroyed (@ %d/%d)", gpr_log(GPR_DEBUG,
server->listeners_destroyed, num_listeners(server)); "Waiting for %d channels and %d/%d listeners to be destroyed"
" before shutting down server",
num_channels(server),
num_listeners(server) - server->listeners_destroyed,
num_listeners(server));
}
return; return;
} }
server->shutdown_published = 1; server->shutdown_published = 1;
for (i = 0; i < server->num_shutdown_tags; i++) { for (i = 0; i < server->num_shutdown_tags; i++) {
grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, server_ref(server);
NULL, 1); grpc_cq_end_op(server->shutdown_tags[i].cq, server->shutdown_tags[i].tag, 1,
done_shutdown_event, server,
&server->shutdown_tags[i].completion);
} }
} }
@ -924,15 +929,14 @@ void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
void grpc_server_shutdown_and_notify(grpc_server *server, void grpc_server_shutdown_and_notify(grpc_server *server,
grpc_completion_queue *cq, void *tag) { grpc_completion_queue *cq, void *tag) {
listener *l; listener *l;
requested_call_array requested_calls; requested_call *requests = NULL;
size_t i;
registered_method *rm; registered_method *rm;
shutdown_tag *sdt; shutdown_tag *sdt;
channel_broadcaster broadcaster; channel_broadcaster broadcaster;
/* lock, and gather up some stuff to do */ /* lock, and gather up some stuff to do */
gpr_mu_lock(&server->mu_global); gpr_mu_lock(&server->mu_global);
grpc_cq_begin_op(cq, NULL); grpc_cq_begin_op(cq);
server->shutdown_tags = server->shutdown_tags =
gpr_realloc(server->shutdown_tags, gpr_realloc(server->shutdown_tags,
sizeof(shutdown_tag) * (server->num_shutdown_tags + 1)); sizeof(shutdown_tag) * (server->num_shutdown_tags + 1));
@ -944,27 +948,21 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
return; return;
} }
server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME);
channel_broadcaster_init(server, &broadcaster); channel_broadcaster_init(server, &broadcaster);
/* collect all unregistered then registered calls */ /* collect all unregistered then registered calls */
gpr_mu_lock(&server->mu_call); gpr_mu_lock(&server->mu_call);
requested_calls = server->requested_calls; requests = server->requests;
memset(&server->requested_calls, 0, sizeof(server->requested_calls)); server->requests = NULL;
for (rm = server->registered_methods; rm; rm = rm->next) { for (rm = server->registered_methods; rm; rm = rm->next) {
if (requested_calls.count + rm->requested.count > while (rm->requests != NULL) {
requested_calls.capacity) { requested_call *c = rm->requests;
requested_calls.capacity = rm->requests = c->next;
GPR_MAX(requested_calls.count + rm->requested.count, c->next = requests;
2 * requested_calls.capacity); requests = c;
requested_calls.calls =
gpr_realloc(requested_calls.calls, sizeof(*requested_calls.calls) *
requested_calls.capacity);
} }
memcpy(requested_calls.calls + requested_calls.count, rm->requested.calls,
sizeof(*requested_calls.calls) * rm->requested.count);
requested_calls.count += rm->requested.count;
gpr_free(rm->requested.calls);
memset(&rm->requested, 0, sizeof(rm->requested));
} }
gpr_mu_unlock(&server->mu_call); gpr_mu_unlock(&server->mu_call);
@ -973,10 +971,11 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
gpr_mu_unlock(&server->mu_global); gpr_mu_unlock(&server->mu_global);
/* terminate all the requested calls */ /* terminate all the requested calls */
for (i = 0; i < requested_calls.count; i++) { while (requests != NULL) {
fail_call(server, &requested_calls.calls[i]); requested_call *next = requests->next;
fail_call(server, requests);
requests = next;
} }
gpr_free(requested_calls.calls);
/* Shutdown listeners */ /* Shutdown listeners */
for (l = server->listeners; l; l = l->next) { for (l = server->listeners; l; l = l->next) {
@ -1038,7 +1037,7 @@ void grpc_server_add_listener(grpc_server *server, void *arg,
static grpc_call_error queue_call_request(grpc_server *server, static grpc_call_error queue_call_request(grpc_server *server,
requested_call *rc) { requested_call *rc) {
call_data *calld = NULL; call_data *calld = NULL;
requested_call_array *requested_calls = NULL; requested_call **requests = NULL;
gpr_mu_lock(&server->mu_call); gpr_mu_lock(&server->mu_call);
if (server->shutdown) { if (server->shutdown) {
gpr_mu_unlock(&server->mu_call); gpr_mu_unlock(&server->mu_call);
@ -1049,12 +1048,12 @@ static grpc_call_error queue_call_request(grpc_server *server,
case BATCH_CALL: case BATCH_CALL:
calld = calld =
call_list_remove_head(&server->lists[PENDING_START], PENDING_START); call_list_remove_head(&server->lists[PENDING_START], PENDING_START);
requested_calls = &server->requested_calls; requests = &server->requests;
break; break;
case REGISTERED_CALL: case REGISTERED_CALL:
calld = call_list_remove_head( calld = call_list_remove_head(
&rc->data.registered.registered_method->pending, PENDING_START); &rc->data.registered.registered_method->pending, PENDING_START);
requested_calls = &rc->data.registered.registered_method->requested; requests = &rc->data.registered.registered_method->requests;
break; break;
} }
if (calld != NULL) { if (calld != NULL) {
@ -1066,7 +1065,8 @@ static grpc_call_error queue_call_request(grpc_server *server,
begin_call(server, calld, rc); begin_call(server, calld, rc);
return GRPC_CALL_OK; return GRPC_CALL_OK;
} else { } else {
*requested_call_array_add(requested_calls) = *rc; rc->next = *requests;
*requests = rc;
gpr_mu_unlock(&server->mu_call); gpr_mu_unlock(&server->mu_call);
return GRPC_CALL_OK; return GRPC_CALL_OK;
} }
@ -1077,22 +1077,23 @@ grpc_call_error grpc_server_request_call(
grpc_metadata_array *initial_metadata, grpc_metadata_array *initial_metadata,
grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag) { grpc_completion_queue *cq_for_notification, void *tag) {
requested_call rc; requested_call *rc = gpr_malloc(sizeof(*rc));
GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details, GRPC_SERVER_LOG_REQUEST_CALL(GPR_INFO, server, call, details,
initial_metadata, cq_bound_to_call, initial_metadata, cq_bound_to_call,
cq_for_notification, tag); cq_for_notification, tag);
if (!grpc_cq_is_server_cq(cq_for_notification)) { if (!grpc_cq_is_server_cq(cq_for_notification)) {
gpr_free(rc);
return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
} }
grpc_cq_begin_op(cq_for_notification, NULL); grpc_cq_begin_op(cq_for_notification);
rc.type = BATCH_CALL; rc->type = BATCH_CALL;
rc.tag = tag; rc->tag = tag;
rc.cq_bound_to_call = cq_bound_to_call; rc->cq_bound_to_call = cq_bound_to_call;
rc.cq_for_notification = cq_for_notification; rc->cq_for_notification = cq_for_notification;
rc.call = call; rc->call = call;
rc.data.batch.details = details; rc->data.batch.details = details;
rc.data.batch.initial_metadata = initial_metadata; rc->data.batch.initial_metadata = initial_metadata;
return queue_call_request(server, &rc); return queue_call_request(server, rc);
} }
grpc_call_error grpc_server_request_registered_call( grpc_call_error grpc_server_request_registered_call(
@ -1100,22 +1101,23 @@ grpc_call_error grpc_server_request_registered_call(
grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload, grpc_metadata_array *initial_metadata, grpc_byte_buffer **optional_payload,
grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag) { grpc_completion_queue *cq_for_notification, void *tag) {
requested_call rc; requested_call *rc = gpr_malloc(sizeof(*rc));
registered_method *registered_method = rm; registered_method *registered_method = rm;
if (!grpc_cq_is_server_cq(cq_for_notification)) { if (!grpc_cq_is_server_cq(cq_for_notification)) {
gpr_free(rc);
return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
} }
grpc_cq_begin_op(cq_for_notification, NULL); grpc_cq_begin_op(cq_for_notification);
rc.type = REGISTERED_CALL; rc->type = REGISTERED_CALL;
rc.tag = tag; rc->tag = tag;
rc.cq_bound_to_call = cq_bound_to_call; rc->cq_bound_to_call = cq_bound_to_call;
rc.cq_for_notification = cq_for_notification; rc->cq_for_notification = cq_for_notification;
rc.call = call; rc->call = call;
rc.data.registered.registered_method = registered_method; rc->data.registered.registered_method = registered_method;
rc.data.registered.deadline = deadline; rc->data.registered.deadline = deadline;
rc.data.registered.initial_metadata = initial_metadata; rc->data.registered.initial_metadata = initial_metadata;
rc.data.registered.optional_payload = optional_payload; rc->data.registered.optional_payload = optional_payload;
return queue_call_request(server, &rc); return queue_call_request(server, rc);
} }
static void publish_registered_or_batch(grpc_call *call, int success, static void publish_registered_or_batch(grpc_call *call, int success,
@ -1182,8 +1184,11 @@ static void begin_call(grpc_server *server, call_data *calld,
} }
GRPC_CALL_INTERNAL_REF(calld->call, "server"); GRPC_CALL_INTERNAL_REF(calld->call, "server");
grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish, grpc_call_start_ioreq_and_call_back(calld->call, req, r - req, publish, rc);
rc->tag); }
static void done_request_event(void *req, grpc_cq_completion *c) {
gpr_free(req);
} }
static void fail_call(grpc_server *server, requested_call *rc) { static void fail_call(grpc_server *server, requested_call *rc) {
@ -1196,15 +1201,19 @@ static void fail_call(grpc_server *server, requested_call *rc) {
rc->data.registered.initial_metadata->count = 0; rc->data.registered.initial_metadata->count = 0;
break; break;
} }
grpc_cq_end_op(rc->cq_for_notification, rc->tag, NULL, 0); grpc_cq_end_op(rc->cq_for_notification, rc->tag, 0, done_request_event, rc,
&rc->completion);
} }
static void publish_registered_or_batch(grpc_call *call, int success, static void publish_registered_or_batch(grpc_call *call, int success,
void *tag) { void *prc) {
grpc_call_element *elem = grpc_call_element *elem =
grpc_call_stack_element(grpc_call_get_call_stack(call), 0); grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
requested_call *rc = prc;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
grpc_cq_end_op(calld->cq_new, tag, call, success); grpc_cq_end_op(calld->cq_new, rc->tag, success, done_request_event, rc,
&rc->completion);
GRPC_CALL_INTERNAL_UNREF(call, "server", 0);
} }
const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) { const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {

@ -0,0 +1,41 @@
/*
*
* 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.
*
*/
/* This file is autogenerated from:
templates/src/core/surface/version.c.template */
#include <grpc/grpc.h>
const char *grpc_version_string(void) {
return "0.10.0.0";
}

@ -212,7 +212,8 @@ void grpc_chttp2_publish_reads(
} }
if (stream_parsing->saw_rst_stream) { if (stream_parsing->saw_rst_stream) {
stream_global->cancelled = 1; stream_global->cancelled = 1;
stream_global->cancelled_status = grpc_chttp2_http2_error_to_grpc_status(stream_parsing->rst_stream_reason); stream_global->cancelled_status = grpc_chttp2_http2_error_to_grpc_status(
stream_parsing->rst_stream_reason);
if (stream_parsing->rst_stream_reason == GRPC_CHTTP2_NO_ERROR) { if (stream_parsing->rst_stream_reason == GRPC_CHTTP2_NO_ERROR) {
stream_global->published_cancelled = 1; stream_global->published_cancelled = 1;
} }
@ -606,7 +607,7 @@ static void on_header(void *tp, grpc_mdelem *md) {
} }
grpc_chttp2_incoming_metadata_buffer_set_deadline( grpc_chttp2_incoming_metadata_buffer_set_deadline(
&stream_parsing->incoming_metadata, &stream_parsing->incoming_metadata,
gpr_time_add(gpr_now(), *cached_timeout)); gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), *cached_timeout));
GRPC_MDELEM_UNREF(md); GRPC_MDELEM_UNREF(md);
} else { } else {
grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata, grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,

@ -437,7 +437,8 @@ static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline,
framer_state *st) { framer_state *st) {
char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE];
grpc_mdelem *mdelem; grpc_mdelem *mdelem;
grpc_chttp2_encode_timeout(gpr_time_sub(deadline, gpr_now()), timeout_str); grpc_chttp2_encode_timeout(
gpr_time_sub(deadline, gpr_now(GPR_CLOCK_REALTIME)), timeout_str);
mdelem = grpc_mdelem_from_metadata_strings( mdelem = grpc_mdelem_from_metadata_strings(
c->mdctx, GRPC_MDSTR_REF(c->timeout_key_str), c->mdctx, GRPC_MDSTR_REF(c->timeout_key_str),
grpc_mdstr_from_string(c->mdctx, timeout_str)); grpc_mdstr_from_string(c->mdctx, timeout_str));

@ -891,11 +891,19 @@ static void update_global_window(void *args, gpr_uint32 id, void *stream) {
grpc_chttp2_stream *s = stream; grpc_chttp2_stream *s = stream;
grpc_chttp2_transport_global *transport_global = &t->global; grpc_chttp2_transport_global *transport_global = &t->global;
grpc_chttp2_stream_global *stream_global = &s->global; grpc_chttp2_stream_global *stream_global = &s->global;
int was_zero;
int is_zero;
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("settings", transport_global, stream_global, GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("settings", transport_global, stream_global,
outgoing_window, outgoing_window,
t->parsing.initial_window_update); t->parsing.initial_window_update);
was_zero = stream_global->outgoing_window <= 0;
stream_global->outgoing_window += t->parsing.initial_window_update; stream_global->outgoing_window += t->parsing.initial_window_update;
is_zero = stream_global->outgoing_window <= 0;
if (was_zero && !is_zero) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
}
} }
static void read_error_locked(grpc_chttp2_transport *t) { static void read_error_locked(grpc_chttp2_transport *t) {

@ -87,6 +87,7 @@ typedef struct internal_metadata {
gpr_atm refcnt; gpr_atm refcnt;
/* private only data */ /* private only data */
gpr_mu mu_user_data;
void *user_data; void *user_data;
void (*destroy_user_data)(void *user_data); void (*destroy_user_data)(void *user_data);
@ -183,7 +184,7 @@ grpc_mdctx *grpc_mdctx_create(void) {
/* This seed is used to prevent remote connections from controlling hash table /* This seed is used to prevent remote connections from controlling hash table
* collisions. It needs to be somewhat unpredictable to a remote connection. * collisions. It needs to be somewhat unpredictable to a remote connection.
*/ */
return grpc_mdctx_create_with_seed(gpr_now().tv_nsec); return grpc_mdctx_create_with_seed(gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
} }
static void discard_metadata(grpc_mdctx *ctx) { static void discard_metadata(grpc_mdctx *ctx) {
@ -200,6 +201,7 @@ static void discard_metadata(grpc_mdctx *ctx) {
if (cur->user_data) { if (cur->user_data) {
cur->destroy_user_data(cur->user_data); cur->destroy_user_data(cur->user_data);
} }
gpr_mu_destroy(&cur->mu_user_data);
gpr_free(cur); gpr_free(cur);
cur = next; cur = next;
ctx->mdtab_free--; ctx->mdtab_free--;
@ -467,6 +469,7 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx,
md->user_data = NULL; md->user_data = NULL;
md->destroy_user_data = NULL; md->destroy_user_data = NULL;
md->bucket_next = ctx->mdtab[hash % ctx->mdtab_capacity]; md->bucket_next = ctx->mdtab[hash % ctx->mdtab_capacity];
gpr_mu_init(&md->mu_user_data);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifdef GRPC_METADATA_REFCOUNT_DEBUG
gpr_log(GPR_DEBUG, "ELM NEW:%p:%d: '%s' = '%s'", md, gpr_log(GPR_DEBUG, "ELM NEW:%p:%d: '%s' = '%s'", md,
gpr_atm_no_barrier_load(&md->refcnt), gpr_atm_no_barrier_load(&md->refcnt),
@ -581,18 +584,29 @@ size_t grpc_mdctx_get_mdtab_free_test_only(grpc_mdctx *ctx) {
void *grpc_mdelem_get_user_data(grpc_mdelem *md, void *grpc_mdelem_get_user_data(grpc_mdelem *md,
void (*if_destroy_func)(void *)) { void (*if_destroy_func)(void *)) {
internal_metadata *im = (internal_metadata *)md; internal_metadata *im = (internal_metadata *)md;
return im->destroy_user_data == if_destroy_func ? im->user_data : NULL; void *result;
gpr_mu_lock(&im->mu_user_data);
result = im->destroy_user_data == if_destroy_func ? im->user_data : NULL;
gpr_mu_unlock(&im->mu_user_data);
return result;
} }
void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *), void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
void *user_data) { void *user_data) {
internal_metadata *im = (internal_metadata *)md; internal_metadata *im = (internal_metadata *)md;
GPR_ASSERT((user_data == NULL) == (destroy_func == NULL)); GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
gpr_mu_lock(&im->mu_user_data);
if (im->destroy_user_data) { if (im->destroy_user_data) {
im->destroy_user_data(im->user_data); /* user data can only be set once */
gpr_mu_unlock(&im->mu_user_data);
if (destroy_func != NULL) {
destroy_func(user_data);
}
return;
} }
im->destroy_user_data = destroy_func; im->destroy_user_data = destroy_func;
im->user_data = user_data; im->user_data = user_data;
gpr_mu_unlock(&im->mu_user_data);
} }
gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) { gpr_slice grpc_mdstr_as_base64_encoded_and_huffman_compressed(grpc_mdstr *gs) {

@ -36,6 +36,7 @@
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc++/credentials.h> #include <grpc++/credentials.h>
#include <grpc++/time.h> #include <grpc++/time.h>
#include "src/cpp/common/create_auth_context.h"
namespace grpc { namespace grpc {
@ -75,6 +76,13 @@ void ClientContext::set_call(grpc_call* call,
} }
} }
std::shared_ptr<const AuthContext> ClientContext::auth_context() const {
if (auth_context_.get() == nullptr) {
auth_context_ = CreateAuthContext(call_);
}
return auth_context_;
}
void ClientContext::TryCancel() { void ClientContext::TryCancel() {
if (call_) { if (call_) {
grpc_call_cancel(call_); grpc_call_cancel(call_);

@ -0,0 +1,42 @@
/*
*
* 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 <memory>
#include <grpc/grpc.h>
#include <grpc++/auth_context.h>
namespace grpc {
std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call);
} // namespace grpc

@ -0,0 +1,45 @@
/*
*
* 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 <memory>
#include <grpc/grpc.h>
#include <grpc++/auth_context.h>
namespace grpc {
std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call) {
(void)call;
return std::shared_ptr<const AuthContext>();
}
} // namespace grpc

@ -0,0 +1,80 @@
/*
*
* 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/cpp/common/secure_auth_context.h"
#include <grpc/grpc_security.h>
namespace grpc {
SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx) : ctx_(ctx) {}
SecureAuthContext::~SecureAuthContext() { grpc_auth_context_release(ctx_); }
std::vector<grpc::string> SecureAuthContext::GetPeerIdentity() const {
if (!ctx_) {
return std::vector<grpc::string>();
}
grpc_auth_property_iterator iter = grpc_auth_context_peer_identity(ctx_);
std::vector<grpc::string> identity;
const grpc_auth_property* property = nullptr;
while ((property = grpc_auth_property_iterator_next(&iter))) {
identity.push_back(grpc::string(property->value, property->value_length));
}
return identity;
}
grpc::string SecureAuthContext::GetPeerIdentityPropertyName() const {
if (!ctx_) {
return "";
}
const char* name = grpc_auth_context_peer_identity_property_name(ctx_);
return name == nullptr ? "" : name;
}
std::vector<grpc::string> SecureAuthContext::FindPropertyValues(
const grpc::string& name) const {
if (!ctx_) {
return std::vector<grpc::string>();
}
grpc_auth_property_iterator iter =
grpc_auth_context_find_properties_by_name(ctx_, name.c_str());
const grpc_auth_property* property = nullptr;
std::vector<grpc::string> values;
while ((property = grpc_auth_property_iterator_next(&iter))) {
values.push_back(grpc::string(property->value, property->value_length));
}
return values;
}
} // namespace grpc

@ -0,0 +1,62 @@
/*
*
* 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_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
#define GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
#include <grpc++/auth_context.h>
struct grpc_auth_context;
namespace grpc {
class SecureAuthContext GRPC_FINAL : public AuthContext {
public:
SecureAuthContext(grpc_auth_context* ctx);
~SecureAuthContext() GRPC_OVERRIDE;
std::vector<grpc::string> GetPeerIdentity() const GRPC_OVERRIDE;
grpc::string GetPeerIdentityPropertyName() const GRPC_OVERRIDE;
std::vector<grpc::string> FindPropertyValues(const grpc::string& name) const
GRPC_OVERRIDE;
private:
grpc_auth_context* ctx_;
};
} // namespace grpc
#endif // GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H

@ -0,0 +1,50 @@
/*
*
* 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 <memory>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc++/auth_context.h>
#include "src/cpp/common/secure_auth_context.h"
namespace grpc {
std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call) {
if (call == nullptr) {
return std::shared_ptr<const AuthContext>();
}
return std::shared_ptr<const AuthContext>(
new SecureAuthContext(grpc_call_auth_context(call)));
}
} // namespace grpc

@ -118,7 +118,7 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
has_request_payload_(mrd->has_request_payload_), has_request_payload_(mrd->has_request_payload_),
request_payload_(mrd->request_payload_), request_payload_(mrd->request_payload_),
method_(mrd->method_) { method_(mrd->method_) {
ctx_.call_ = mrd->call_; ctx_.set_call(mrd->call_);
ctx_.cq_ = &cq_; ctx_.cq_ = &cq_;
GPR_ASSERT(mrd->in_flight_); GPR_ASSERT(mrd->in_flight_);
mrd->in_flight_ = false; mrd->in_flight_ = false;
@ -326,7 +326,7 @@ bool Server::BaseAsyncRequest::FinalizeResult(void** tag, bool* status) {
} }
} }
grpc_metadata_array_destroy(&initial_metadata_array_); grpc_metadata_array_destroy(&initial_metadata_array_);
context_->call_ = call_; context_->set_call(call_);
context_->cq_ = call_cq_; context_->cq_ = call_cq_;
Call call(call_, server_, call_cq_, server_->max_message_size_); Call call(call_, server_, call_cq_, server_->max_message_size_);
if (*status && call_) { if (*status && call_) {

@ -39,6 +39,8 @@
#include <grpc++/impl/sync.h> #include <grpc++/impl/sync.h>
#include <grpc++/time.h> #include <grpc++/time.h>
#include "src/cpp/common/create_auth_context.h"
namespace grpc { namespace grpc {
// CompletionOp // CompletionOp
@ -146,4 +148,9 @@ bool ServerContext::IsCancelled() {
return completion_op_ && completion_op_->CheckCancelled(cq_); return completion_op_ && completion_op_->CheckCancelled(cq_);
} }
void ServerContext::set_call(grpc_call* call) {
call_ = call;
auth_context_ = CreateAuthContext(call);
}
} // namespace grpc } // namespace grpc

@ -5,19 +5,19 @@
<title>gRPC C# Auth</title> <title>gRPC C# Auth</title>
<summary>Auth library for C# implementation of gRPC - an RPC library and framework</summary> <summary>Auth library for C# implementation of gRPC - an RPC library and framework</summary>
<description>Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info.</description> <description>Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
<version>0.5.1</version> <version>0.6.0</version>
<authors>Google Inc.</authors> <authors>Google Inc.</authors>
<owners>grpc-packages</owners> <owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl> <projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Release 0.5.1 of gRPC C#</releaseNotes> <releaseNotes>Release 0.6.0 of gRPC C#</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright> <copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2 Auth OAuth2</tags> <tags>gRPC RPC Protocol HTTP/2 Auth OAuth2</tags>
<dependencies> <dependencies>
<dependency id="BouncyCastle" version="1.7.0" /> <dependency id="BouncyCastle" version="1.7.0" />
<dependency id="Google.Apis.Auth" version="1.9.1" /> <dependency id="Google.Apis.Auth" version="1.9.1" />
<dependency id="Grpc.Core" version="0.5.1" /> <dependency id="Grpc.Core" version="0.6.0" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

@ -9,6 +9,6 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]
[assembly: InternalsVisibleTo("Grpc.Auth.Tests")] [assembly: InternalsVisibleTo("Grpc.Auth.Tests")]

@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]

@ -33,8 +33,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Collections.Immutable"> <Reference Include="System.Collections.Immutable, Version=1.1.36.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Interactive.Async"> <Reference Include="System.Interactive.Async">
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath> <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
@ -130,4 +131,4 @@
</Target> </Target>
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" /> <Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" />
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" /> <Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" />
</Project> </Project>

@ -5,19 +5,19 @@
<title>gRPC C# Core</title> <title>gRPC C# Core</title>
<summary>Core C# implementation of gRPC - an RPC library and framework</summary> <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.</description> <description>Core C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
<version>0.5.1</version> <version>0.6.0</version>
<authors>Google Inc.</authors> <authors>Google Inc.</authors>
<owners>grpc-packages</owners> <owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl> <projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Release 0.5.1 of gRPC C#</releaseNotes> <releaseNotes>Release 0.6.0 of gRPC C#</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright> <copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags> <tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies> <dependencies>
<dependency id="Microsoft.Bcl.Immutable" version="1.0.34" /> <dependency id="System.Collections.Immutable" version="1.1.36" />
<dependency id="Ix-Async" version="1.2.3" /> <dependency id="Ix-Async" version="1.2.3" />
<dependency id="grpc.native.csharp_ext" version="0.9.1" /> <dependency id="grpc.native.csharp_ext" version="0.10.0" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

@ -9,6 +9,6 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]
[assembly: InternalsVisibleTo("Grpc.Core.Tests")] [assembly: InternalsVisibleTo("Grpc.Core.Tests")]

@ -3,5 +3,5 @@
<package id="grpc.dependencies.openssl.redist" version="1.0.2.2" targetFramework="net45" /> <package id="grpc.dependencies.openssl.redist" version="1.0.2.2" targetFramework="net45" />
<package id="grpc.dependencies.zlib.redist" version="1.2.8.9" targetFramework="net45" /> <package id="grpc.dependencies.zlib.redist" version="1.2.8.9" targetFramework="net45" />
<package id="Ix-Async" version="1.2.3" targetFramework="net45" /> <package id="Ix-Async" version="1.2.3" targetFramework="net45" />
<package id="Microsoft.Bcl.Immutable" version="1.0.34" targetFramework="net45" /> <package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
</packages> </packages>

@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]

@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]

@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]

@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]

@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]

@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]

@ -54,6 +54,10 @@
<Reference Include="Google.ProtocolBuffers"> <Reference Include="Google.ProtocolBuffers">
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath> <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Collections.Immutable, Version=1.1.36.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Interactive.Async"> <Reference Include="System.Interactive.Async">
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath> <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference> </Reference>
@ -69,9 +73,6 @@
<Reference Include="Newtonsoft.Json"> <Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Collections.Immutable">
<HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />

@ -9,4 +9,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] [assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.5.*")] [assembly: AssemblyVersion("0.6.*")]

@ -7,8 +7,8 @@
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" /> <package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" /> <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" /> <package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
<package id="Microsoft.Bcl.Immutable" version="1.0.34" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" /> <package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" /> <package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" /> <package id="NUnit" version="2.6.4" targetFramework="net45" />
<package id="System.Collections.Immutable" version="1.1.36" targetFramework="net45" />
</packages> </packages>

@ -5,13 +5,13 @@
<title>gRPC C# Tools</title> <title>gRPC C# Tools</title>
<summary>Tools for C# implementation of gRPC - an RPC library and framework</summary> <summary>Tools for C# implementation of gRPC - an RPC library and framework</summary>
<description>Precompiled Windows binaries for generating protocol buffer messages and gRPC client/server code</description> <description>Precompiled Windows binaries for generating protocol buffer messages and gRPC client/server code</description>
<version>0.5.1</version> <version>0.6.0</version>
<authors>Google Inc.</authors> <authors>Google Inc.</authors>
<owners>grpc-packages</owners> <owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl> <projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version 0.5.1</releaseNotes> <releaseNotes>protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version 0.6.0</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright> <copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags> <tags>gRPC RPC Protocol HTTP/2</tags>
</metadata> </metadata>

@ -5,17 +5,17 @@
<title>gRPC C#</title> <title>gRPC C#</title>
<summary>C# implementation of gRPC - an RPC library and framework</summary> <summary>C# implementation of gRPC - an RPC library and framework</summary>
<description>C# implementation of gRPC - an RPC library and framework. See project site for more info.</description> <description>C# implementation of gRPC - an RPC library and framework. See project site for more info.</description>
<version>0.5.1</version> <version>0.6.0</version>
<authors>Google Inc.</authors> <authors>Google Inc.</authors>
<owners>grpc-packages</owners> <owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl> <projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance> <requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Release 0.5.1 of gRPC C#</releaseNotes> <releaseNotes>Release 0.6.0 of gRPC C#</releaseNotes>
<copyright>Copyright 2015, Google Inc.</copyright> <copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags> <tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies> <dependencies>
<dependency id="Grpc.Core" version="0.5.1" /> <dependency id="Grpc.Core" version="0.6.0" />
</dependencies> </dependencies>
</metadata> </metadata>
<files/> <files/>

@ -379,7 +379,7 @@ grpcsharp_channel_args_destroy(grpc_channel_args *args) {
/* Timespec */ /* Timespec */
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(void) { return gpr_now(); } GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(void) { return gpr_now(GPR_CLOCK_REALTIME); }
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_future(void) { GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_future(void) {
return gpr_inf_future; return gpr_inf_future;

@ -0,0 +1,70 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
'use strict';
var grpc = require('../');
var _ = require('lodash');
var health_proto = grpc.load(__dirname + '/health.proto');
var HealthClient = health_proto.grpc.health.v1alpha.Health;
function HealthImplementation(statusMap) {
this.statusMap = _.clone(statusMap);
}
HealthImplementation.prototype.setStatus = function(host, service, status) {
if (!this.statusMap[host]) {
this.statusMap[host] = {};
}
this.statusMap[host][service] = status;
};
HealthImplementation.prototype.check = function(call, callback){
var host = call.request.host;
var service = call.request.service;
var status = _.get(this.statusMap, [host, service], null);
if (status === null) {
callback({code:grpc.status.NOT_FOUND});
} else {
callback(null, {status: status});
}
};
module.exports = {
Client: HealthClient,
service: HealthClient.service,
Implementation: HealthImplementation
};

@ -0,0 +1,50 @@
// 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.
syntax = "proto3";
package grpc.health.v1alpha;
message HealthCheckRequest {
string host = 1;
string service = 2;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
}
ServingStatus status = 1;
}
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
}

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

@ -634,7 +634,8 @@ function makeServerConstructor(service_attr_map) {
} }
var serialize = attrs.responseSerialize; var serialize = attrs.responseSerialize;
var deserialize = attrs.requestDeserialize; var deserialize = attrs.requestDeserialize;
server.register(attrs.path, service_handlers[service_name][name], server.register(attrs.path, _.bind(service_handlers[service_name][name],
service_handlers[service_name]),
serialize, deserialize, method_type); serialize, deserialize, method_type);
}); });
}, this); }, this);

@ -0,0 +1,103 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
'use strict';
var assert = require('assert');
var health = require('../health_check/health.js');
var grpc = require('../');
describe('Health Checking', function() {
var statusMap = {
'': {
'': 'SERVING',
'grpc.test.TestService': 'NOT_SERVING',
},
virtual_host: {
'grpc.test.TestService': 'SERVING'
}
};
var HealthServer = grpc.buildServer([health.service]);
var healthServer = new HealthServer({
'grpc.health.v1alpha.Health': new health.Implementation(statusMap)
});
var healthClient;
before(function() {
var port_num = healthServer.bind('0.0.0.0:0');
healthServer.listen();
healthClient = new health.Client('localhost:' + port_num);
});
after(function() {
healthServer.shutdown();
});
it('should say an enabled service is SERVING', function(done) {
healthClient.check({service: ''}, function(err, response) {
assert.ifError(err);
assert.strictEqual(response.status, 'SERVING');
done();
});
});
it('should say that a disabled service is NOT_SERVING', function(done) {
healthClient.check({service: 'grpc.test.TestService'},
function(err, response) {
assert.ifError(err);
assert.strictEqual(response.status, 'NOT_SERVING');
done();
});
});
it('should say that a service on another host is SERVING', function(done) {
healthClient.check({host: 'virtual_host', service: 'grpc.test.TestService'},
function(err, response) {
assert.ifError(err);
assert.strictEqual(response.status, 'SERVING');
done();
});
});
it('should get NOT_FOUND if the service is not registered', function(done) {
healthClient.check({service: 'not_registered'}, function(err, response) {
assert(err);
assert.strictEqual(err.code, grpc.status.NOT_FOUND);
done();
});
});
it('should get NOT_FOUND if the host is not registered', function(done) {
healthClient.check({host: 'wrong_host', service: 'grpc.test.TestService'},
function(err, response) {
assert(err);
assert.strictEqual(err.code, grpc.status.NOT_FOUND);
done();
});
});
});

@ -4,7 +4,7 @@ gRPC PHP Extension
# Requirements # Requirements
* PHP 5.5+ * PHP 5.5+
* [gRPC core library](https://github.com/grpc/grpc) 0.9.1 * [gRPC core library](https://github.com/grpc/grpc) 0.10.0
# Installation # Installation
@ -55,7 +55,7 @@ $ sudo pecl install grpc
Note: before a stable release, you may need to do Note: before a stable release, you may need to do
```sh ```sh
$ sudo pecl install grpc-0.5.0 $ sudo pecl install grpc-0.5.1
``` ```
OR OR

@ -10,11 +10,11 @@
<email>grpc-packages@google.com</email> <email>grpc-packages@google.com</email>
<active>yes</active> <active>yes</active>
</lead> </lead>
<date>2015-06-16</date> <date>2015-07-09</date>
<time>20:12:55</time> <time>21:47:27</time>
<version> <version>
<release>0.5.0</release> <release>0.5.1</release>
<api>0.5.0</api> <api>0.5.1</api>
</version> </version>
<stability> <stability>
<release>alpha</release> <release>alpha</release>
@ -22,7 +22,7 @@
</stability> </stability>
<license>BSD</license> <license>BSD</license>
<notes> <notes>
First alpha release Update to wrap gRPC C Core version 0.10.0
</notes> </notes>
<contents> <contents>
<dir baseinstalldir="/" name="/"> <dir baseinstalldir="/" name="/">
@ -34,15 +34,15 @@ First alpha release
<file baseinstalldir="/" md5sum="f1b66029daeced20b47cf00cc6523fc8" name="channel.h" role="src" /> <file baseinstalldir="/" md5sum="f1b66029daeced20b47cf00cc6523fc8" name="channel.h" role="src" />
<file baseinstalldir="/" md5sum="81a1193e93d8b6602add8ac360de565b" name="completion_queue.c" role="src" /> <file baseinstalldir="/" md5sum="81a1193e93d8b6602add8ac360de565b" name="completion_queue.c" role="src" />
<file baseinstalldir="/" md5sum="f10b5bb232d74a6878e829e2e76cdaa2" name="completion_queue.h" role="src" /> <file baseinstalldir="/" md5sum="f10b5bb232d74a6878e829e2e76cdaa2" name="completion_queue.h" role="src" />
<file baseinstalldir="/" md5sum="a9181ed994a072ac5f41e7c9705c170f" name="config.m4" role="src" /> <file baseinstalldir="/" md5sum="a22f8eac0164761058cc4d9eb2ceb069" name="config.m4" role="src" />
<file baseinstalldir="/" md5sum="8c3f1e11dac623001378bfd53b554f08" name="credentials.c" role="src" /> <file baseinstalldir="/" md5sum="8c3f1e11dac623001378bfd53b554f08" name="credentials.c" role="src" />
<file baseinstalldir="/" md5sum="6988d6e97c19c8f8e3eb92371cf8246b" name="credentials.h" role="src" /> <file baseinstalldir="/" md5sum="6988d6e97c19c8f8e3eb92371cf8246b" name="credentials.h" role="src" />
<file baseinstalldir="/" md5sum="38a1bc979d810c36ebc2a52d4b7b5319" name="CREDITS" role="doc" /> <file baseinstalldir="/" md5sum="38a1bc979d810c36ebc2a52d4b7b5319" name="CREDITS" role="doc" />
<file baseinstalldir="/" md5sum="3f35b472bbdef5a788cd90617d7d0847" name="LICENSE" role="doc" /> <file baseinstalldir="/" md5sum="3f35b472bbdef5a788cd90617d7d0847" name="LICENSE" role="doc" />
<file baseinstalldir="/" md5sum="6aaa7a290122d230f2d8c4e4e05da4a9" name="php_grpc.c" role="src" /> <file baseinstalldir="/" md5sum="6aaa7a290122d230f2d8c4e4e05da4a9" name="php_grpc.c" role="src" />
<file baseinstalldir="/" md5sum="673b07859d9f69232f8a754c56780686" name="php_grpc.h" role="src" /> <file baseinstalldir="/" md5sum="673b07859d9f69232f8a754c56780686" name="php_grpc.h" role="src" />
<file baseinstalldir="/" md5sum="4d4d3382f8d10cae2e4378468e5516b9" name="README.md" role="doc" /> <file baseinstalldir="/" md5sum="c1d0b42fd77b7d6740bf7744bee90af5" name="README.md" role="doc" />
<file baseinstalldir="/" md5sum="53fda0ee6937f6ddc8e271886018d441" name="server.c" role="src" /> <file baseinstalldir="/" md5sum="30997dd423403e1f8ad09dcee598e5c4" name="server.c" role="src" />
<file baseinstalldir="/" md5sum="4b730f06d14cbbb0642bdbd194749595" name="server.h" role="src" /> <file baseinstalldir="/" md5sum="4b730f06d14cbbb0642bdbd194749595" name="server.h" role="src" />
<file baseinstalldir="/" md5sum="f6930beafb6c0e061899262f2f077e98" name="server_credentials.c" role="src" /> <file baseinstalldir="/" md5sum="f6930beafb6c0e061899262f2f077e98" name="server_credentials.c" role="src" />
<file baseinstalldir="/" md5sum="9c4b4cc06356a8a39a16a085a9b85996" name="server_credentials.h" role="src" /> <file baseinstalldir="/" md5sum="9c4b4cc06356a8a39a16a085a9b85996" name="server_credentials.h" role="src" />
@ -78,5 +78,20 @@ First alpha release
First alpha release First alpha release
</notes> </notes>
</release> </release>
<release>
<version>
<release>0.5.1</release>
<api>0.5.1</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2015-07-09</date>
<license>BSD</license>
<notes>
Update to wrap gRPC C Core version 0.10.0
</notes>
</release>
</changelog> </changelog>
</package> </package>

@ -208,7 +208,7 @@ PHP_METHOD(Timeval, similar) {
* @return Timeval The current time * @return Timeval The current time
*/ */
PHP_METHOD(Timeval, now) { PHP_METHOD(Timeval, now) {
zval *now = grpc_php_wrap_timeval(gpr_now()); zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME));
RETURN_DESTROY_ZVAL(now); RETURN_DESTROY_ZVAL(now);
} }

@ -45,7 +45,7 @@ _PACKAGE_DATA = {
'credentials/server1.pem',] 'credentials/server1.pem',]
} }
_INSTALL_REQUIRES = ['oauth2client>=1.4.7', 'grpcio>=0.4.0a4'] _INSTALL_REQUIRES = ['oauth2client>=1.4.7', 'grpcio>=0.10.0a0']
setuptools.setup( setuptools.setup(
name='interop', name='interop',

@ -1,3 +1,4 @@
MANIFEST MANIFEST
grpcio.egg-info/ grpcio.egg-info/
build/
dist/ dist/

@ -0,0 +1,5 @@
*.a
*.so
*.dll
*.pyc
*.pyd

@ -0,0 +1,7 @@
*.h
*.c
*.a
*.so
*.dll
*.pyc
*.pyd

@ -0,0 +1,52 @@
GRPC Python Cython layer
========================
Package for the GRPC Python Cython layer.
What is Cython?
---------------
Cython is both a superset of the Python language with extensions for dealing
with C types and a tool that transpiles this superset into C code. It provides
convenient means of statically typing expressions and of converting Python
strings to pointers (among other niceties), thus dramatically smoothing the
Python/C interop by allowing fluid use of APIs in both from the same source.
See the wonderful `Cython website`_.
Why Cython?
-----------
- **Python 2 and 3 support**
Cython generated C code has precompiler macros to target both Python 2 and
Python 3 C APIs, even while acting as a superset of just the Python 2
language (e.g. using ``basestring``).
- **Significantly less semantic noise**
A lot of CPython code is just glue, especially human-error-prone
``Py_INCREF``-ing and ``Py_DECREF``-ing around error handlers and such.
Cython takes care of that automagically.
- **Possible PyPy support**
One of the major developments in Cython over the past few years was the
addition of support for PyPy. We might soon be able to provide such support
ourselves through our use of Cython.
- **Less Python glue code**
There existed several adapter layers in and around the original CPython code
to smooth the surface exposed to Python due to how much trouble it was to
make such a smooth surface via the CPython API alone. Cython makes writing
such a surface incredibly easy, so these adapter layers may be removed.
Implications for Users
----------------------
Nothing additional will be required for users. PyPI packages will contain
Cython generated C code and thus not necessitate a Cython installation.
Implications for GRPC Developers
--------------------------------
A typical edit-compile-debug cycle now requires Cython. We install Cython in
the ``virtualenv`` generated for the Python tests in this repository, so
initial test runs may take an extra 2+ minutes to complete. Subsequent test
runs won't reinstall ``Cython`` (unless required versions change and the
``virtualenv`` doesn't have installed versions that satisfy the change).
.. _`Cython website`: http://cython.org/

@ -0,0 +1,28 @@
# 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.

@ -0,0 +1,28 @@
# 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.

@ -0,0 +1,37 @@
# 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.
from grpc._cython._cygrpc cimport grpc
cdef class Call:
cdef grpc.grpc_call *c_call
cdef list references

@ -0,0 +1,82 @@
# 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.
cimport cpython
from grpc._cython._cygrpc cimport records
cdef class Call:
def __cinit__(self):
# Create an *empty* call
self.c_call = NULL
self.references = []
def start_batch(self, operations, tag):
if not self.is_valid:
raise ValueError("invalid call object cannot be used from Python")
cdef records.Operations cy_operations = records.Operations(operations)
cdef records.OperationTag operation_tag = records.OperationTag(tag)
operation_tag.operation_call = self
operation_tag.batch_operations = cy_operations
cpython.Py_INCREF(operation_tag)
return grpc.grpc_call_start_batch(
self.c_call, cy_operations.c_ops, cy_operations.c_nops,
<cpython.PyObject *>operation_tag)
def cancel(self,
grpc.grpc_status_code error_code=grpc.GRPC_STATUS__DO_NOT_USE,
details=None):
if not self.is_valid:
raise ValueError("invalid call object cannot be used from Python")
if (details is None) != (error_code == grpc.GRPC_STATUS__DO_NOT_USE):
raise ValueError("if error_code is specified, so must details "
"(and vice-versa)")
if isinstance(details, bytes):
pass
elif isinstance(details, basestring):
details = details.encode()
else:
raise TypeError("expected details to be str or bytes")
if error_code != grpc.GRPC_STATUS__DO_NOT_USE:
self.references.append(details)
return grpc.grpc_call_cancel_with_status(self.c_call, error_code, details)
else:
return grpc.grpc_call_cancel(self.c_call)
def __dealloc__(self):
if self.c_call != NULL:
grpc.grpc_call_destroy(self.c_call)
# The object *should* always be valid from Python. Used for debugging.
@property
def is_valid(self):
return self.c_call != NULL

@ -0,0 +1,36 @@
# 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.
from grpc._cython._cygrpc cimport grpc
cdef class Channel:
cdef grpc.grpc_channel *c_channel
cdef list references

@ -0,0 +1,84 @@
# 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.
from grpc._cython._cygrpc cimport call
from grpc._cython._cygrpc cimport completion_queue
from grpc._cython._cygrpc cimport credentials
from grpc._cython._cygrpc cimport records
cdef class Channel:
def __cinit__(self, target, records.ChannelArgs arguments=None,
credentials.ClientCredentials client_credentials=None):
cdef grpc.grpc_channel_args *c_arguments = NULL
self.c_channel = NULL
self.references = []
if arguments is not None:
c_arguments = &arguments.c_args
if isinstance(target, bytes):
pass
elif isinstance(target, basestring):
target = target.encode()
else:
raise TypeError("expected target to be str or bytes")
if client_credentials is None:
self.c_channel = grpc.grpc_channel_create(target, c_arguments)
else:
self.c_channel = grpc.grpc_secure_channel_create(
client_credentials.c_credentials, target, c_arguments)
self.references.append(client_credentials)
self.references.append(target)
self.references.append(arguments)
def create_call(self, completion_queue.CompletionQueue queue not None,
method, host, records.Timespec deadline not None):
if queue.is_shutting_down:
raise ValueError("queue must not be shutting down or shutdown")
if isinstance(method, bytes):
pass
elif isinstance(method, basestring):
method = method.encode()
else:
raise TypeError("expected method to be str or bytes")
if isinstance(host, bytes):
pass
elif isinstance(host, basestring):
host = host.encode()
else:
raise TypeError("expected host to be str or bytes")
cdef call.Call operation_call = call.Call()
operation_call.references = [self, method, host, queue]
operation_call.c_call = grpc.grpc_channel_create_call(
self.c_channel, queue.c_completion_queue, method, host, deadline.c_time)
return operation_call
def __dealloc__(self):
if self.c_channel != NULL:
grpc.grpc_channel_destroy(self.c_channel)

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

Loading…
Cancel
Save