Merge branch 'master' into deepend

pull/2647/head
Vijay Pai 10 years ago
commit f0c66c6365
  1. 18
      BUILD
  2. 2
      INSTALL
  3. 6
      Makefile
  4. 10
      build.json
  5. 1
      composer.json
  6. 13
      gRPC.podspec
  7. 6
      include/grpc++/credentials.h
  8. 2
      include/grpc++/impl/sync_no_cxx11.h
  9. 11
      include/grpc/census.h
  10. 16
      include/grpc/grpc.h
  11. 4
      include/grpc/grpc_security.h
  12. 6
      include/grpc/support/host_port.h
  13. 12
      src/compiler/csharp_generator.cc
  14. 38
      src/core/census/record_stat.c
  15. 46
      src/core/census/rpc_stat_id.h
  16. 5
      src/core/channel/channel_stack.c
  17. 5
      src/core/channel/channel_stack.h
  18. 23
      src/core/channel/client_channel.c
  19. 3
      src/core/channel/compress_filter.c
  20. 6
      src/core/channel/connected_channel.c
  21. 16
      src/core/channel/http_client_filter.c
  22. 3
      src/core/channel/http_server_filter.c
  23. 1
      src/core/channel/noop_filter.c
  24. 4
      src/core/client_config/README.md
  25. 299
      src/core/client_config/resolvers/sockaddr_resolver.c
  26. 6
      src/core/client_config/resolvers/sockaddr_resolver.h
  27. 195
      src/core/client_config/resolvers/unix_resolver_posix.c
  28. 6
      src/core/client_config/subchannel.c
  29. 3
      src/core/client_config/subchannel.h
  30. 4
      src/core/iomgr/endpoint.c
  31. 3
      src/core/iomgr/endpoint.h
  32. 8
      src/core/iomgr/endpoint_pair_posix.c
  33. 4
      src/core/iomgr/endpoint_pair_windows.c
  34. 1
      src/core/iomgr/iomgr.c
  35. 33
      src/core/iomgr/sockaddr_utils.c
  36. 2
      src/core/iomgr/sockaddr_utils.h
  37. 12
      src/core/iomgr/tcp_client_posix.c
  38. 5
      src/core/iomgr/tcp_client_windows.c
  39. 28
      src/core/iomgr/tcp_posix.c
  40. 3
      src/core/iomgr/tcp_posix.h
  41. 7
      src/core/iomgr/tcp_server_posix.c
  42. 12
      src/core/iomgr/tcp_server_windows.c
  43. 13
      src/core/iomgr/tcp_windows.c
  44. 2
      src/core/iomgr/tcp_windows.h
  45. 8
      src/core/security/client_auth_filter.c
  46. 23
      src/core/security/credentials.c
  47. 5
      src/core/security/credentials.h
  48. 5
      src/core/security/google_default_credentials.c
  49. 7
      src/core/security/secure_endpoint.c
  50. 8
      src/core/security/server_auth_filter.c
  51. 10
      src/core/support/host_port.c
  52. 8
      src/core/surface/call.c
  53. 15
      src/core/surface/channel.c
  54. 2
      src/core/surface/channel.h
  55. 3
      src/core/surface/channel_create.c
  56. 7
      src/core/surface/init.c
  57. 18
      src/core/surface/lame_client.c
  58. 7
      src/core/surface/secure_channel_create.c
  59. 20
      src/core/surface/server.c
  60. 2
      src/core/transport/chttp2/frame_data.c
  61. 22
      src/core/transport/chttp2/internal.h
  62. 5
      src/core/transport/chttp2/parsing.c
  63. 68
      src/core/transport/chttp2/stream_lists.c
  64. 94
      src/core/transport/chttp2/writing.c
  65. 33
      src/core/transport/chttp2_transport.c
  66. 4
      src/core/transport/transport.c
  67. 3
      src/core/transport/transport.h
  68. 3
      src/core/transport/transport_impl.h
  69. 10
      src/core/transport/transport_op_string.c
  70. 2
      src/cpp/client/create_channel.cc
  71. 8
      src/cpp/client/secure_credentials.cc
  72. 3
      src/cpp/util/time.cc
  73. 3
      src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
  74. 202
      src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
  75. 207
      src/csharp/Grpc.Core.Tests/TimeoutsTest.cs
  76. 101
      src/csharp/Grpc.Core.Tests/TimespecTest.cs
  77. 15
      src/csharp/Grpc.Core/Call.cs
  78. 18
      src/csharp/Grpc.Core/Calls.cs
  79. 6
      src/csharp/Grpc.Core/ClientBase.cs
  80. 16
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  81. 20
      src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
  82. 10
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  83. 10
      src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
  84. 16
      src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
  85. 183
      src/csharp/Grpc.Core/Internal/Timespec.cs
  86. 54
      src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
  87. 30
      src/csharp/Grpc.Examples/MathGrpc.cs
  88. 9
      src/csharp/Grpc.Examples/MathServiceImpl.cs
  89. 12
      src/csharp/Grpc.HealthCheck/HealthGrpc.cs
  90. 48
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
  91. 16
      src/csharp/ext/grpc_csharp_ext.c
  92. 1
      src/node/ext/timeval.cc
  93. 2
      src/php/composer.json
  94. 5
      src/php/lib/Grpc/BaseStub.php
  95. 3
      src/python/src/grpc/_adapter/_c/types/client_credentials.c
  96. 1
      src/python/src/grpc/_adapter/_c/utility.c
  97. 3
      src/python/src/grpc/_cython/_cygrpc/credentials.pyx
  98. 2
      src/python/src/grpc/_cython/_cygrpc/grpc.pxd
  99. 6
      src/ruby/ext/grpc/rb_grpc.c
  100. 13
      src/ruby/ext/grpc/rb_server.c
  101. Some files were not shown because too many files have changed in this diff Show More

18
BUILD

@ -168,7 +168,7 @@ cc_library(
"src/core/client_config/resolver_factory.h",
"src/core/client_config/resolver_registry.h",
"src/core/client_config/resolvers/dns_resolver.h",
"src/core/client_config/resolvers/unix_resolver_posix.h",
"src/core/client_config/resolvers/sockaddr_resolver.h",
"src/core/client_config/subchannel.h",
"src/core/client_config/subchannel_factory.h",
"src/core/client_config/uri_parser.h",
@ -246,6 +246,7 @@ cc_library(
"src/core/transport/transport.h",
"src/core/transport/transport_impl.h",
"src/core/census/context.h",
"src/core/census/rpc_stat_id.h",
"src/core/httpcli/format_request.c",
"src/core/httpcli/httpcli.c",
"src/core/httpcli/httpcli_security_connector.c",
@ -287,7 +288,7 @@ cc_library(
"src/core/client_config/resolver_factory.c",
"src/core/client_config/resolver_registry.c",
"src/core/client_config/resolvers/dns_resolver.c",
"src/core/client_config/resolvers/unix_resolver_posix.c",
"src/core/client_config/resolvers/sockaddr_resolver.c",
"src/core/client_config/subchannel.c",
"src/core/client_config/subchannel_factory.c",
"src/core/client_config/uri_parser.c",
@ -381,6 +382,7 @@ cc_library(
"src/core/transport/transport_op_string.c",
"src/core/census/context.c",
"src/core/census/initialize.c",
"src/core/census/record_stat.c",
],
hdrs = [
"include/grpc/grpc_security.h",
@ -424,7 +426,7 @@ cc_library(
"src/core/client_config/resolver_factory.h",
"src/core/client_config/resolver_registry.h",
"src/core/client_config/resolvers/dns_resolver.h",
"src/core/client_config/resolvers/unix_resolver_posix.h",
"src/core/client_config/resolvers/sockaddr_resolver.h",
"src/core/client_config/subchannel.h",
"src/core/client_config/subchannel_factory.h",
"src/core/client_config/uri_parser.h",
@ -502,6 +504,7 @@ cc_library(
"src/core/transport/transport.h",
"src/core/transport/transport_impl.h",
"src/core/census/context.h",
"src/core/census/rpc_stat_id.h",
"src/core/surface/init_unsecure.c",
"src/core/census/grpc_context.c",
"src/core/channel/channel_args.c",
@ -520,7 +523,7 @@ cc_library(
"src/core/client_config/resolver_factory.c",
"src/core/client_config/resolver_registry.c",
"src/core/client_config/resolvers/dns_resolver.c",
"src/core/client_config/resolvers/unix_resolver_posix.c",
"src/core/client_config/resolvers/sockaddr_resolver.c",
"src/core/client_config/subchannel.c",
"src/core/client_config/subchannel_factory.c",
"src/core/client_config/uri_parser.c",
@ -614,6 +617,7 @@ cc_library(
"src/core/transport/transport_op_string.c",
"src/core/census/context.c",
"src/core/census/initialize.c",
"src/core/census/record_stat.c",
],
hdrs = [
"include/grpc/byte_buffer.h",
@ -1002,7 +1006,7 @@ objc_library(
"src/core/client_config/resolver_factory.c",
"src/core/client_config/resolver_registry.c",
"src/core/client_config/resolvers/dns_resolver.c",
"src/core/client_config/resolvers/unix_resolver_posix.c",
"src/core/client_config/resolvers/sockaddr_resolver.c",
"src/core/client_config/subchannel.c",
"src/core/client_config/subchannel_factory.c",
"src/core/client_config/uri_parser.c",
@ -1096,6 +1100,7 @@ objc_library(
"src/core/transport/transport_op_string.c",
"src/core/census/context.c",
"src/core/census/initialize.c",
"src/core/census/record_stat.c",
],
hdrs = [
"include/grpc/grpc_security.h",
@ -1141,7 +1146,7 @@ objc_library(
"src/core/client_config/resolver_factory.h",
"src/core/client_config/resolver_registry.h",
"src/core/client_config/resolvers/dns_resolver.h",
"src/core/client_config/resolvers/unix_resolver_posix.h",
"src/core/client_config/resolvers/sockaddr_resolver.h",
"src/core/client_config/subchannel.h",
"src/core/client_config/subchannel_factory.h",
"src/core/client_config/uri_parser.h",
@ -1219,6 +1224,7 @@ objc_library(
"src/core/transport/transport.h",
"src/core/transport/transport_impl.h",
"src/core/census/context.h",
"src/core/census/rpc_stat_id.h",
],
includes = [
"include",

@ -117,7 +117,7 @@ most Mac installations. Do the "git submodule" command listed above.
Then execute the following for all the needed build dependencies
$ sudo /opt/local/bin/port install autoconf automake libtool gflags cmake
$ mkdir ~/gtest
$ mkdir ~/gtest-svn
$ svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
$ mkdir mybuild
$ cd mybuild

@ -3520,7 +3520,7 @@ LIBGRPC_SRC = \
src/core/client_config/resolver_factory.c \
src/core/client_config/resolver_registry.c \
src/core/client_config/resolvers/dns_resolver.c \
src/core/client_config/resolvers/unix_resolver_posix.c \
src/core/client_config/resolvers/sockaddr_resolver.c \
src/core/client_config/subchannel.c \
src/core/client_config/subchannel_factory.c \
src/core/client_config/uri_parser.c \
@ -3614,6 +3614,7 @@ LIBGRPC_SRC = \
src/core/transport/transport_op_string.c \
src/core/census/context.c \
src/core/census/initialize.c \
src/core/census/record_stat.c \
PUBLIC_HEADERS_C += \
include/grpc/grpc_security.h \
@ -3784,7 +3785,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/client_config/resolver_factory.c \
src/core/client_config/resolver_registry.c \
src/core/client_config/resolvers/dns_resolver.c \
src/core/client_config/resolvers/unix_resolver_posix.c \
src/core/client_config/resolvers/sockaddr_resolver.c \
src/core/client_config/subchannel.c \
src/core/client_config/subchannel_factory.c \
src/core/client_config/uri_parser.c \
@ -3878,6 +3879,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/transport/transport_op_string.c \
src/core/census/context.c \
src/core/census/initialize.c \
src/core/census/record_stat.c \
PUBLIC_HEADERS_C += \
include/grpc/byte_buffer.h \

@ -18,11 +18,13 @@
"include/grpc/census.h"
],
"headers": [
"src/core/census/context.h"
"src/core/census/context.h",
"src/core/census/rpc_stat_id.h"
],
"src": [
"src/core/census/context.c",
"src/core/census/initialize.c"
"src/core/census/initialize.c",
"src/core/census/record_stat.c"
]
},
{
@ -131,7 +133,7 @@
"src/core/client_config/resolver_factory.h",
"src/core/client_config/resolver_registry.h",
"src/core/client_config/resolvers/dns_resolver.h",
"src/core/client_config/resolvers/unix_resolver_posix.h",
"src/core/client_config/resolvers/sockaddr_resolver.h",
"src/core/client_config/subchannel.h",
"src/core/client_config/subchannel_factory.h",
"src/core/client_config/uri_parser.h",
@ -227,7 +229,7 @@
"src/core/client_config/resolver_factory.c",
"src/core/client_config/resolver_registry.c",
"src/core/client_config/resolvers/dns_resolver.c",
"src/core/client_config/resolvers/unix_resolver_posix.c",
"src/core/client_config/resolvers/sockaddr_resolver.c",
"src/core/client_config/subchannel.c",
"src/core/client_config/subchannel_factory.c",
"src/core/client_config/uri_parser.c",

@ -2,6 +2,7 @@
"name": "grpc/grpc",
"type": "library",
"description": "gRPC library for PHP",
"version": "0.5.1",
"keywords": ["rpc"],
"homepage": "http://grpc.io",
"license": "BSD-3-Clause",

@ -170,7 +170,7 @@ Pod::Spec.new do |s|
'src/core/client_config/resolver_factory.h',
'src/core/client_config/resolver_registry.h',
'src/core/client_config/resolvers/dns_resolver.h',
'src/core/client_config/resolvers/unix_resolver_posix.h',
'src/core/client_config/resolvers/sockaddr_resolver.h',
'src/core/client_config/subchannel.h',
'src/core/client_config/subchannel_factory.h',
'src/core/client_config/uri_parser.h',
@ -248,6 +248,7 @@ Pod::Spec.new do |s|
'src/core/transport/transport.h',
'src/core/transport/transport_impl.h',
'src/core/census/context.h',
'src/core/census/rpc_stat_id.h',
'grpc/grpc_security.h',
'grpc/byte_buffer.h',
'grpc/byte_buffer_reader.h',
@ -296,7 +297,7 @@ Pod::Spec.new do |s|
'src/core/client_config/resolver_factory.c',
'src/core/client_config/resolver_registry.c',
'src/core/client_config/resolvers/dns_resolver.c',
'src/core/client_config/resolvers/unix_resolver_posix.c',
'src/core/client_config/resolvers/sockaddr_resolver.c',
'src/core/client_config/subchannel.c',
'src/core/client_config/subchannel_factory.c',
'src/core/client_config/uri_parser.c',
@ -389,7 +390,8 @@ Pod::Spec.new do |s|
'src/core/transport/transport.c',
'src/core/transport/transport_op_string.c',
'src/core/census/context.c',
'src/core/census/initialize.c'
'src/core/census/initialize.c',
'src/core/census/record_stat.c'
ss.private_header_files = 'src/core/support/env.h',
'src/core/support/file.h',
@ -434,7 +436,7 @@ Pod::Spec.new do |s|
'src/core/client_config/resolver_factory.h',
'src/core/client_config/resolver_registry.h',
'src/core/client_config/resolvers/dns_resolver.h',
'src/core/client_config/resolvers/unix_resolver_posix.h',
'src/core/client_config/resolvers/sockaddr_resolver.h',
'src/core/client_config/subchannel.h',
'src/core/client_config/subchannel_factory.h',
'src/core/client_config/uri_parser.h',
@ -511,7 +513,8 @@ Pod::Spec.new do |s|
'src/core/transport/stream_op.h',
'src/core/transport/transport.h',
'src/core/transport/transport_impl.h',
'src/core/census/context.h'
'src/core/census/context.h',
'src/core/census/rpc_stat_id.h'
ss.header_mappings_dir = '.'

@ -106,13 +106,13 @@ std::shared_ptr<Credentials> ServiceAccountCredentials(
const grpc::string& json_key, const grpc::string& scope,
long token_lifetime_seconds);
// Builds JWT credentials.
// Builds Service Account JWT Access credentials.
// json_key is the JSON key string containing the client's private key.
// token_lifetime_seconds is the lifetime in seconds of each Json Web Token
// (JWT) created with this credentials. It should not exceed
// grpc_max_auth_token_lifetime or will be cropped to this value.
std::shared_ptr<Credentials> JWTCredentials(const grpc::string& json_key,
long token_lifetime_seconds);
std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials(
const grpc::string& json_key, long token_lifetime_seconds);
// Builds refresh token credentials.
// json_refresh_token is the JSON string containing the refresh token along

@ -87,7 +87,7 @@ class condition_variable {
~condition_variable() { gpr_cv_destroy(&cv_); }
void wait(lock_guard<mutex> &mu) {
mu.locked = false;
gpr_cv_wait(&cv_, &mu.mu_.mu_, gpr_inf_future);
gpr_cv_wait(&cv_, &mu.mu_.mu_, gpr_inf_future(GPR_CLOCK_REALTIME);
mu.locked = true;
}
void notify_one() { gpr_cv_signal(&cv_); }

@ -100,6 +100,17 @@ int census_context_deserialize(const char *buffer, census_context **context);
* future census calls will result in undefined behavior. */
void census_context_destroy(census_context *context);
/* A census statistic to be recorded comprises two parts: an ID for the
* particular statistic and the value to be recorded against it. */
typedef struct {
int id;
double value;
} census_stat;
/* Record new stats against the given context. */
void census_record_stat(census_context *context, census_stat *stats,
size_t nstats);
#ifdef __cplusplus
}
#endif

@ -433,6 +433,20 @@ grpc_call *grpc_channel_create_registered_call(
grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
size_t nops, void *tag);
/** Returns a newly allocated string representing the endpoint to which this
call is communicating with. The string is in the uri format accepted by
grpc_channel_create.
The returned string should be disposed of with gpr_free().
WARNING: this value is never authenticated or subject to any security
related code. It must not be used for any authentication related
functionality. Instead, use grpc_auth_context. */
char *grpc_call_get_peer(grpc_call *call);
/** Return a newly allocated string representing the target a channel was
created for. */
char *grpc_channel_get_target(grpc_channel *channel);
/** Create a client channel to 'target'. Additional channel level configuration
MAY be provided by grpc_channel_args, though the expectation is that most
clients will want to simply pass NULL. See grpc_channel_args definition for
@ -442,7 +456,7 @@ grpc_channel *grpc_channel_create(const char *target,
const grpc_channel_args *args);
/** Create a lame client: this client fails every operation attempted on it. */
grpc_channel *grpc_lame_client_channel_create(void);
grpc_channel *grpc_lame_client_channel_create(const char *target);
/** Close and destroy a grpc channel */
void grpc_channel_destroy(grpc_channel *channel);

@ -119,8 +119,8 @@ grpc_credentials *grpc_service_account_credentials_create(
- token_lifetime is the lifetime of each Json Web Token (JWT) created with
this credentials. It should not exceed grpc_max_auth_token_lifetime or
will be cropped to this value. */
grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
gpr_timespec token_lifetime);
grpc_credentials *grpc_service_account_jwt_access_credentials_create(
const char *json_key, gpr_timespec token_lifetime);
/* Creates an Oauth2 Refresh Token credentials object. May return NULL if the
input is invalid.

@ -52,8 +52,10 @@ int gpr_join_host_port(char **out, const char *host, int port);
/* Given a name in the form "host:port" or "[ho:st]:port", split into hostname
and port number, into newly allocated strings, which must later be
destroyed using gpr_free(). */
void gpr_split_host_port(const char *name, char **host, char **port);
destroyed using gpr_free().
Return 1 on success, 0 on failure. Guarantees *host and *port == NULL on
failure. */
int gpr_split_host_port(const char *name, char **host, char **port);
#ifdef __cplusplus
}

@ -269,7 +269,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
"$response$ $methodname$($request$ request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));\n",
"$response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
@ -280,7 +280,7 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
"$returntype$ $methodname$($request_maybe$Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));\n",
"$returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
@ -332,13 +332,13 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
"public $response$ $methodname$($request$ request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"public $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers);\n",
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers, deadline);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request, cancellationToken);\n");
@ -351,13 +351,13 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
"public $returntype$ $methodname$($request_maybe$Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"public $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers);\n",
out->Print("var call = CreateCall($servicenamefield$, $methodfield$, headers, deadline);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
switch (GetMethodType(method)) {

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

@ -0,0 +1,46 @@
/*
*
* 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 CENSUS_RPC_STAT_ID_H
#define CENSUS_RPC_STAT_ID_H
/* Stats ID's used for RPC measurements. */
#define CENSUS_INVALID_STAT_ID 0 /* ID 0 is always invalid */
#define CENSUS_RPC_CLIENT_REQUESTS 1 /* Count of client requests sent. */
#define CENSUS_RPC_SERVER_REQUESTS 2 /* Count of server requests sent. */
#define CENSUS_RPC_CLIENT_ERRORS 3 /* Client error counts. */
#define CENSUS_RPC_SERVER_ERRORS 4 /* Server error counts. */
#define CENSUS_RPC_CLIENT_LATENCY 5 /* Client side request latency. */
#define CENSUS_RPC_SERVER_LATENCY 6 /* Server side request latency. */
#endif /* CENSUS_RPC_STAT_ID_H */

@ -191,6 +191,11 @@ void grpc_call_next_op(grpc_call_element *elem, grpc_transport_stream_op *op) {
next_elem->filter->start_transport_stream_op(next_elem, op);
}
char *grpc_call_next_get_peer(grpc_call_element *elem) {
grpc_call_element *next_elem = elem + 1;
return next_elem->filter->get_peer(next_elem);
}
void grpc_channel_next_op(grpc_channel_element *elem, grpc_transport_op *op) {
grpc_channel_element *next_elem = elem + 1;
next_elem->filter->start_transport_op(next_elem, op);

@ -104,6 +104,9 @@ typedef struct {
The filter does not need to do any chaining */
void (*destroy_channel_elem)(grpc_channel_element *elem);
/* Implement grpc_call_get_peer() */
char *(*get_peer)(grpc_call_element *elem);
/* The name of this filter */
const char *name;
} grpc_channel_filter;
@ -173,6 +176,8 @@ void grpc_call_next_op(grpc_call_element *elem, grpc_transport_stream_op *op);
/* Call the next operation (depending on call directionality) in a channel
stack */
void grpc_channel_next_op(grpc_channel_element *elem, grpc_transport_op *op);
/* Pass through a request to get_peer to the next child element */
char *grpc_call_next_get_peer(grpc_call_element *elem);
/* Given the top element of a channel stack, get the channel stack itself */
grpc_channel_stack *grpc_channel_stack_from_top_element(

@ -265,6 +265,26 @@ static grpc_iomgr_closure *merge_into_waiting_op(
return consumed_op;
}
static char *cc_get_peer(grpc_call_element *elem) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_subchannel_call *subchannel_call;
char *result;
gpr_mu_lock(&calld->mu_state);
if (calld->state == CALL_ACTIVE) {
subchannel_call = calld->subchannel_call;
GRPC_SUBCHANNEL_CALL_REF(subchannel_call, "get_peer");
gpr_mu_unlock(&calld->mu_state);
result = grpc_subchannel_call_get_peer(subchannel_call);
GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, "get_peer");
return result;
} else {
gpr_mu_unlock(&calld->mu_state);
return grpc_channel_get_target(chand->master);
}
}
static void perform_transport_stream_op(grpc_call_element *elem,
grpc_transport_stream_op *op,
int continuation) {
@ -440,7 +460,7 @@ static void cc_on_config_changed(void *arg, int iomgr_success) {
while (wakeup_closures) {
grpc_iomgr_closure *next = wakeup_closures->next;
grpc_iomgr_add_callback(wakeup_closures);
wakeup_closures->cb(wakeup_closures->cb_arg, 1);
wakeup_closures = next;
}
@ -590,6 +610,7 @@ const grpc_channel_filter grpc_client_channel_filter = {
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
cc_get_peer,
"client-channel",
};

@ -174,6 +174,8 @@ static void process_send_ops(grpc_call_element *elem,
size_t i;
int did_compress = 0;
/* In streaming calls, we need to reset the previously accumulated slices */
gpr_slice_buffer_reset_and_unref(&calld->slices);
for (i = 0; i < send_ops->nops; ++i) {
grpc_stream_op *sop = &send_ops->ops[i];
switch (sop->type) {
@ -322,4 +324,5 @@ const grpc_channel_filter grpc_compress_filter = {
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
grpc_call_next_get_peer,
"compress"};

@ -119,6 +119,11 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
grpc_transport_destroy(cd->transport);
}
static char *con_get_peer(grpc_call_element *elem) {
channel_data *chand = elem->channel_data;
return grpc_transport_get_peer(chand->transport);
}
const grpc_channel_filter grpc_connected_channel_filter = {
con_start_transport_stream_op,
con_start_transport_op,
@ -128,6 +133,7 @@ const grpc_channel_filter grpc_connected_channel_filter = {
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
con_get_peer,
"connected",
};

@ -98,6 +98,18 @@ static void hc_on_recv(void *user_data, int success) {
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
}
static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
grpc_call_element *elem = user_data;
channel_data *channeld = elem->channel_data;
/* eat the things we'd like to set ourselves */
if (md->key == channeld->method->key) return NULL;
if (md->key == channeld->scheme->key) return NULL;
if (md->key == channeld->te_trailers->key) return NULL;
if (md->key == channeld->content_type->key) return NULL;
if (md->key == channeld->user_agent->key) return NULL;
return md;
}
static void hc_mutate_op(grpc_call_element *elem,
grpc_transport_stream_op *op) {
/* grab pointers to our data from the call element */
@ -111,6 +123,7 @@ static void hc_mutate_op(grpc_call_element *elem,
grpc_stream_op *op = &ops[i];
if (op->type != GRPC_OP_METADATA) continue;
calld->sent_initial_metadata = 1;
grpc_metadata_batch_filter(&op->data.metadata, client_strip_filter, elem);
/* Send : prefixed headers, which have to be before any application
layer headers. */
grpc_metadata_batch_add_head(&op->data.metadata, &calld->method,
@ -267,4 +280,5 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
const grpc_channel_filter grpc_http_client_filter = {
hc_start_transport_op, grpc_channel_next_op, sizeof(call_data),
init_call_elem, destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem, "http-client"};
init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer,
"http-client"};

@ -280,4 +280,5 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
const grpc_channel_filter grpc_http_server_filter = {
hs_start_transport_op, grpc_channel_next_op, sizeof(call_data),
init_call_elem, destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem, "http-server"};
init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer,
"http-server"};

@ -127,4 +127,5 @@ const grpc_channel_filter grpc_no_op_filter = {noop_start_transport_stream_op,
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
grpc_call_next_get_peer,
"no-op"};

@ -60,3 +60,7 @@ unix:path - the unix scheme is used to create and connect to unix domain
sockets - the authority must be empty, and the path
represents the absolute or relative path to the desired
socket
ipv4:host:port - a pre-resolved ipv4 dotted decimal address/port combination
ipv6:[host]:port - a pre-resolved ipv6 address/port combination

@ -0,0 +1,299 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/port_platform.h>
#include "src/core/client_config/resolvers/sockaddr_resolver.h"
#include <stdio.h>
#include <string.h>
#ifdef GPR_POSIX_SOCKET
#include <sys/un.h>
#endif
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/string_util.h>
#include "src/core/client_config/lb_policies/pick_first.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/support/string.h"
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** refcount */
gpr_refcount refs;
/** subchannel factory */
grpc_subchannel_factory *subchannel_factory;
/** load balancing policy factory */
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels);
/** the address that we've 'resolved' */
struct sockaddr_storage addr;
int addr_len;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** have we published? */
int published;
/** pending next completion, or NULL */
grpc_iomgr_closure *next_completion;
/** target config address for next completion */
grpc_client_config **target_config;
} sockaddr_resolver;
static void sockaddr_destroy(grpc_resolver *r);
static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r);
static void sockaddr_shutdown(grpc_resolver *r);
static void sockaddr_channel_saw_error(grpc_resolver *r,
struct sockaddr *failing_address,
int failing_address_len);
static void sockaddr_next(grpc_resolver *r, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
static const grpc_resolver_vtable sockaddr_resolver_vtable = {
sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error,
sockaddr_next};
static void sockaddr_shutdown(grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
/* TODO(ctiller): add delayed callback */
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
}
gpr_mu_unlock(&r->mu);
}
static void sockaddr_channel_saw_error(grpc_resolver *resolver,
struct sockaddr *sa, int len) {}
static void sockaddr_next(grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_config = target_config;
sockaddr_maybe_finish_next_locked(r);
gpr_mu_unlock(&r->mu);
}
static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r) {
grpc_client_config *cfg;
grpc_lb_policy *lb_policy;
grpc_subchannel *subchannel;
grpc_subchannel_args args;
if (r->next_completion != NULL && !r->published) {
cfg = grpc_client_config_create();
memset(&args, 0, sizeof(args));
args.addr = (struct sockaddr *)&r->addr;
args.addr_len = r->addr_len;
subchannel =
grpc_subchannel_factory_create_subchannel(r->subchannel_factory, &args);
lb_policy = r->lb_policy_factory(&subchannel, 1);
grpc_client_config_set_lb_policy(cfg, lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "unix");
r->published = 1;
*r->target_config = cfg;
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
}
}
static void sockaddr_destroy(grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_subchannel_factory_unref(r->subchannel_factory);
gpr_free(r);
}
#ifdef GPR_POSIX_SOCKET
static int parse_unix(grpc_uri *uri, struct sockaddr_storage *addr, int *len) {
struct sockaddr_un *un = (struct sockaddr_un *)addr;
un->sun_family = AF_UNIX;
strcpy(un->sun_path, uri->path);
*len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
return 1;
}
#endif
static int parse_ipv4(grpc_uri *uri, struct sockaddr_storage *addr, int *len) {
const char *host_port = uri->path;
char *host;
char *port;
int port_num;
int result = 0;
struct sockaddr_in *in = (struct sockaddr_in *)addr;
if (*host_port == '/') ++host_port;
if (!gpr_split_host_port(host_port, &host, &port)) {
return 0;
}
memset(in, 0, sizeof(*in));
*len = sizeof(*in);
in->sin_family = AF_INET;
if (inet_pton(AF_INET, host, &in->sin_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv4 address: '%s'", host);
goto done;
}
if (port != NULL) {
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
port_num > 65535) {
gpr_log(GPR_ERROR, "invalid ipv4 port: '%s'", port);
goto done;
}
in->sin_port = htons(port_num);
} else {
gpr_log(GPR_ERROR, "no port given for ipv4 scheme");
goto done;
}
result = 1;
done:
gpr_free(host);
gpr_free(port);
return result;
}
static int parse_ipv6(grpc_uri *uri, struct sockaddr_storage *addr, int *len) {
const char *host_port = uri->path;
char *host;
char *port;
int port_num;
int result = 0;
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)addr;
if (*host_port == '/') ++host_port;
if (!gpr_split_host_port(host_port, &host, &port)) {
return 0;
}
memset(in6, 0, sizeof(*in6));
*len = sizeof(*in6);
in6->sin6_family = AF_INET6;
if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
goto done;
}
if (port != NULL) {
if (sscanf(port, "%d", &port_num) != 1 || port_num < 0 ||
port_num > 65535) {
gpr_log(GPR_ERROR, "invalid ipv6 port: '%s'", port);
goto done;
}
in6->sin6_port = htons(port_num);
} else {
gpr_log(GPR_ERROR, "no port given for ipv6 scheme");
goto done;
}
result = 1;
done:
gpr_free(host);
gpr_free(port);
return result;
}
static grpc_resolver *sockaddr_create(
grpc_uri *uri,
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels),
grpc_subchannel_factory *subchannel_factory,
int parse(grpc_uri *uri, struct sockaddr_storage *dst, int *len)) {
sockaddr_resolver *r;
if (0 != strcmp(uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based uri's not supported");
return NULL;
}
r = gpr_malloc(sizeof(sockaddr_resolver));
memset(r, 0, sizeof(*r));
if (!parse(uri, &r->addr, &r->addr_len)) {
gpr_free(r);
return NULL;
}
gpr_ref_init(&r->refs, 1);
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
r->subchannel_factory = subchannel_factory;
r->lb_policy_factory = lb_policy_factory;
grpc_subchannel_factory_ref(subchannel_factory);
return &r->base;
}
/*
* FACTORY
*/
static void sockaddr_factory_ref(grpc_resolver_factory *factory) {}
static void sockaddr_factory_unref(grpc_resolver_factory *factory) {}
#define DECL_FACTORY(name) \
static grpc_resolver *name##_factory_create_resolver( \
grpc_resolver_factory *factory, grpc_uri *uri, \
grpc_subchannel_factory *subchannel_factory) { \
return sockaddr_create(uri, grpc_create_pick_first_lb_policy, \
subchannel_factory, parse_##name); \
} \
static const grpc_resolver_factory_vtable name##_factory_vtable = { \
sockaddr_factory_ref, sockaddr_factory_unref, \
name##_factory_create_resolver}; \
static grpc_resolver_factory name##_resolver_factory = { \
&name##_factory_vtable}; \
grpc_resolver_factory *grpc_##name##_resolver_factory_create() { \
return &name##_resolver_factory; \
}
#ifdef GPR_POSIX_SOCKET
DECL_FACTORY(unix)
#endif
DECL_FACTORY(ipv4)
DECL_FACTORY(ipv6)

@ -38,7 +38,13 @@
#include "src/core/client_config/resolver_factory.h"
grpc_resolver_factory *grpc_ipv4_resolver_factory_create(void);
grpc_resolver_factory *grpc_ipv6_resolver_factory_create(void);
#ifdef GPR_POSIX_SOCKET
/** Create a unix resolver factory */
grpc_resolver_factory *grpc_unix_resolver_factory_create(void);
#endif
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_UNIX_RESOLVER_H */

@ -1,195 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/port_platform.h>
#ifdef GPR_POSIX_SOCKET
#include "src/core/client_config/resolvers/unix_resolver_posix.h"
#include <string.h>
#include <sys/un.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/client_config/lb_policies/pick_first.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/support/string.h"
typedef struct {
/** base class: must be first */
grpc_resolver base;
/** refcount */
gpr_refcount refs;
/** subchannel factory */
grpc_subchannel_factory *subchannel_factory;
/** load balancing policy factory */
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels);
/** the address that we've 'resolved' */
struct sockaddr_un addr;
int addr_len;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** have we published? */
int published;
/** pending next completion, or NULL */
grpc_iomgr_closure *next_completion;
/** target config address for next completion */
grpc_client_config **target_config;
} unix_resolver;
static void unix_destroy(grpc_resolver *r);
static void unix_maybe_finish_next_locked(unix_resolver *r);
static void unix_shutdown(grpc_resolver *r);
static void unix_channel_saw_error(grpc_resolver *r,
struct sockaddr *failing_address,
int failing_address_len);
static void unix_next(grpc_resolver *r, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
static const grpc_resolver_vtable unix_resolver_vtable = {
unix_destroy, unix_shutdown, unix_channel_saw_error, unix_next};
static void unix_shutdown(grpc_resolver *resolver) {
unix_resolver *r = (unix_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
/* TODO(ctiller): add delayed callback */
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
}
gpr_mu_unlock(&r->mu);
}
static void unix_channel_saw_error(grpc_resolver *resolver, struct sockaddr *sa,
int len) {}
static void unix_next(grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete) {
unix_resolver *r = (unix_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_config = target_config;
unix_maybe_finish_next_locked(r);
gpr_mu_unlock(&r->mu);
}
static void unix_maybe_finish_next_locked(unix_resolver *r) {
grpc_client_config *cfg;
grpc_lb_policy *lb_policy;
grpc_subchannel *subchannel;
grpc_subchannel_args args;
if (r->next_completion != NULL && !r->published) {
cfg = grpc_client_config_create();
memset(&args, 0, sizeof(args));
args.addr = (struct sockaddr *)&r->addr;
args.addr_len = r->addr_len;
subchannel =
grpc_subchannel_factory_create_subchannel(r->subchannel_factory, &args);
lb_policy = r->lb_policy_factory(&subchannel, 1);
grpc_client_config_set_lb_policy(cfg, lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "unix");
r->published = 1;
*r->target_config = cfg;
grpc_iomgr_add_callback(r->next_completion);
r->next_completion = NULL;
}
}
static void unix_destroy(grpc_resolver *gr) {
unix_resolver *r = (unix_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_subchannel_factory_unref(r->subchannel_factory);
gpr_free(r);
}
static grpc_resolver *unix_create(
grpc_uri *uri,
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels),
grpc_subchannel_factory *subchannel_factory) {
unix_resolver *r;
if (0 != strcmp(uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based uri's not supported");
return NULL;
}
r = gpr_malloc(sizeof(unix_resolver));
memset(r, 0, sizeof(*r));
gpr_ref_init(&r->refs, 1);
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &unix_resolver_vtable);
r->subchannel_factory = subchannel_factory;
r->lb_policy_factory = lb_policy_factory;
r->addr.sun_family = AF_UNIX;
strcpy(r->addr.sun_path, uri->path);
r->addr_len = strlen(r->addr.sun_path) + sizeof(r->addr.sun_family) + 1;
grpc_subchannel_factory_ref(subchannel_factory);
return &r->base;
}
/*
* FACTORY
*/
static void unix_factory_ref(grpc_resolver_factory *factory) {}
static void unix_factory_unref(grpc_resolver_factory *factory) {}
static grpc_resolver *unix_factory_create_resolver(
grpc_resolver_factory *factory, grpc_uri *uri,
grpc_subchannel_factory *subchannel_factory) {
return unix_create(uri, grpc_create_pick_first_lb_policy, subchannel_factory);
}
static const grpc_resolver_factory_vtable unix_factory_vtable = {
unix_factory_ref, unix_factory_unref, unix_factory_create_resolver};
static grpc_resolver_factory unix_resolver_factory = {&unix_factory_vtable};
grpc_resolver_factory *grpc_unix_resolver_factory_create() {
return &unix_resolver_factory;
}
#endif

@ -640,6 +640,12 @@ void grpc_subchannel_call_unref(
}
}
char *grpc_subchannel_call_get_peer(grpc_subchannel_call *call) {
grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
return top_elem->filter->get_peer(top_elem);
}
void grpc_subchannel_call_process_op(grpc_subchannel_call *call,
grpc_transport_stream_op *op) {
grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);

@ -100,6 +100,9 @@ void grpc_subchannel_del_interested_party(grpc_subchannel *channel,
void grpc_subchannel_call_process_op(grpc_subchannel_call *subchannel_call,
grpc_transport_stream_op *op);
/** continue querying for peer */
char *grpc_subchannel_call_get_peer(grpc_subchannel_call *subchannel_call);
struct grpc_subchannel_args {
/** Channel filters for this channel - wrapped factories will likely
want to mutate this */

@ -53,3 +53,7 @@ void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) {
void grpc_endpoint_shutdown(grpc_endpoint *ep) { ep->vtable->shutdown(ep); }
void grpc_endpoint_destroy(grpc_endpoint *ep) { ep->vtable->destroy(ep); }
char *grpc_endpoint_get_peer(grpc_endpoint *ep) {
return ep->vtable->get_peer(ep);
}

@ -72,12 +72,15 @@ struct grpc_endpoint_vtable {
void (*add_to_pollset)(grpc_endpoint *ep, grpc_pollset *pollset);
void (*shutdown)(grpc_endpoint *ep);
void (*destroy)(grpc_endpoint *ep);
char *(*get_peer)(grpc_endpoint *ep);
};
/* When data is available on the connection, calls the callback with slices. */
void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb,
void *user_data);
char *grpc_endpoint_get_peer(grpc_endpoint *ep);
/* Write slices out to the socket.
If the connection is ready for more data after the end of the call, it

@ -66,12 +66,12 @@ grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name,
create_sockets(sv);
gpr_asprintf(&final_name, "%s:client", name);
p.client =
grpc_tcp_create(grpc_fd_create(sv[1], final_name), read_slice_size);
p.client = grpc_tcp_create(grpc_fd_create(sv[1], final_name), read_slice_size,
"socketpair-server");
gpr_free(final_name);
gpr_asprintf(&final_name, "%s:server", name);
p.server =
grpc_tcp_create(grpc_fd_create(sv[0], final_name), read_slice_size);
p.server = grpc_tcp_create(grpc_fd_create(sv[0], final_name), read_slice_size,
"socketpair-client");
gpr_free(final_name);
return p;
}

@ -81,8 +81,8 @@ grpc_endpoint_pair grpc_iomgr_create_endpoint_pair(const char *name, size_t read
SOCKET sv[2];
grpc_endpoint_pair p;
create_sockets(sv);
p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client"));
p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server"));
p.client = grpc_tcp_create(grpc_winsocket_create(sv[1], "endpoint:client"), "endpoint:server");
p.server = grpc_tcp_create(grpc_winsocket_create(sv[0], "endpoint:server"), "endpoint:client");
return p;
}

@ -88,6 +88,7 @@ void grpc_kick_poller(void) {
void grpc_iomgr_init(void) {
gpr_thd_id id;
g_shutdown = 0;
gpr_mu_init(&g_mu);
gpr_cv_init(&g_rcv);
grpc_alarm_list_init(gpr_now(GPR_CLOCK_MONOTONIC));

@ -36,12 +36,18 @@
#include <errno.h>
#include <string.h>
#include "src/core/support/string.h"
#ifdef GPR_POSIX_SOCKET
#include <sys/un.h>
#endif
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h>
#include "src/core/support/string.h"
static const gpr_uint8 kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0xff, 0xff};
@ -161,6 +167,31 @@ int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
return ret;
}
char *grpc_sockaddr_to_uri(const struct sockaddr *addr) {
char *temp;
char *result;
switch (addr->sa_family) {
case AF_INET:
grpc_sockaddr_to_string(&temp, addr, 0);
gpr_asprintf(&result, "ipv4:%s", temp);
gpr_free(temp);
return result;
case AF_INET6:
grpc_sockaddr_to_string(&temp, addr, 0);
gpr_asprintf(&result, "ipv6:%s", temp);
gpr_free(temp);
return result;
#ifdef GPR_POSIX_SOCKET
case AF_UNIX:
gpr_asprintf(&result, "unix:%s", ((struct sockaddr_un *)addr)->sun_path);
return result;
#endif
}
return NULL;
}
int grpc_sockaddr_get_port(const struct sockaddr *addr) {
switch (addr->sa_family) {
case AF_INET:

@ -84,4 +84,6 @@ int grpc_sockaddr_set_port(const struct sockaddr *addr, int port);
int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
int normalize);
char *grpc_sockaddr_to_uri(const struct sockaddr *addr);
#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_UTILS_H */

@ -64,6 +64,7 @@ typedef struct {
int refs;
grpc_iomgr_closure write_closure;
grpc_pollset_set *interested_parties;
char *addr_str;
} async_connect;
static int prepare_socket(const struct sockaddr *addr, int fd) {
@ -99,6 +100,7 @@ static void on_alarm(void *acp, int success) {
gpr_mu_unlock(&ac->mu);
if (done) {
gpr_mu_destroy(&ac->mu);
gpr_free(ac->addr_str);
gpr_free(ac);
}
}
@ -158,7 +160,8 @@ static void on_writable(void *acp, int success) {
}
} else {
grpc_pollset_set_del_fd(ac->interested_parties, ac->fd);
ep = grpc_tcp_create(ac->fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE);
ep = grpc_tcp_create(ac->fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE,
ac->addr_str);
goto finish;
}
} else {
@ -179,6 +182,7 @@ finish:
gpr_mu_unlock(&ac->mu);
if (done) {
gpr_mu_destroy(&ac->mu);
gpr_free(ac->addr_str);
gpr_free(ac);
}
cb(cb_arg, ep);
@ -223,13 +227,13 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
err = connect(fd, addr, addr_len);
} while (err < 0 && errno == EINTR);
grpc_sockaddr_to_string(&addr_str, addr, 1);
addr_str = grpc_sockaddr_to_uri(addr);
gpr_asprintf(&name, "tcp-client:%s", addr_str);
fdobj = grpc_fd_create(fd, name);
if (err >= 0) {
cb(arg, grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
cb(arg, grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str));
goto done;
}
@ -247,6 +251,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
ac->cb_arg = arg;
ac->fd = fdobj;
ac->interested_parties = interested_parties;
ac->addr_str = addr_str;
addr_str = NULL;
gpr_mu_init(&ac->mu);
ac->refs = 2;
ac->write_closure.cb = on_writable;

@ -58,6 +58,7 @@ typedef struct {
grpc_winsocket *socket;
gpr_timespec deadline;
grpc_alarm alarm;
char *addr_name;
int refs;
int aborted;
} async_connect;
@ -67,6 +68,7 @@ static void async_connect_cleanup(async_connect *ac) {
gpr_mu_unlock(&ac->mu);
if (done) {
gpr_mu_destroy(&ac->mu);
gpr_free(ac->addr_name);
gpr_free(ac);
}
}
@ -107,7 +109,7 @@ static void on_connect(void *acp, int from_iocp) {
gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
gpr_free(utf8_message);
} else if (!aborted) {
ep = grpc_tcp_create(ac->socket);
ep = grpc_tcp_create(ac->socket, ac->addr_name);
}
} else {
gpr_log(GPR_ERROR, "on_connect is shutting down");
@ -213,6 +215,7 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
ac->socket = socket;
gpr_mu_init(&ac->mu);
ac->refs = 2;
ac->addr_name = grpc_sockaddr_to_uri(addr);
ac->aborted = 0;
grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac,

@ -44,15 +44,17 @@
#include <sys/socket.h>
#include <unistd.h>
#include "src/core/support/string.h"
#include "src/core/debug/trace.h"
#include "src/core/profiling/timers.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/slice.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#include "src/core/support/string.h"
#include "src/core/debug/trace.h"
#include "src/core/profiling/timers.h"
#ifdef GPR_HAVE_MSG_NOSIGNAL
#define SENDMSG_FLAGS MSG_NOSIGNAL
#else
@ -282,6 +284,8 @@ typedef struct {
grpc_iomgr_closure write_closure;
grpc_iomgr_closure handle_read_closure;
char *peer_string;
} grpc_tcp;
static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success);
@ -296,6 +300,7 @@ static void grpc_tcp_unref(grpc_tcp *tcp) {
int refcount_zero = gpr_unref(&tcp->refcount);
if (refcount_zero) {
grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan");
gpr_free(tcp->peer_string);
gpr_free(tcp);
}
}
@ -314,7 +319,7 @@ static void call_read_cb(grpc_tcp *tcp, gpr_slice *slices, size_t nslices,
gpr_log(GPR_DEBUG, "read: status=%d", status);
for (i = 0; i < nslices; i++) {
char *dump = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG, "READ: %s", dump);
gpr_log(GPR_DEBUG, "READ %p: %s", tcp, dump);
gpr_free(dump);
}
}
@ -443,7 +448,7 @@ static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb,
grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure);
} else {
tcp->handle_read_closure.cb_arg = tcp;
grpc_iomgr_add_callback(&tcp->handle_read_closure);
grpc_iomgr_add_delayed_callback(&tcp->handle_read_closure, 1);
}
}
@ -567,13 +572,20 @@ static void grpc_tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) {
grpc_pollset_add_fd(pollset, tcp->em_fd);
}
static char *grpc_tcp_get_peer(grpc_endpoint *ep) {
grpc_tcp *tcp = (grpc_tcp *)ep;
return gpr_strdup(tcp->peer_string);
}
static const grpc_endpoint_vtable vtable = {
grpc_tcp_notify_on_read, grpc_tcp_write, grpc_tcp_add_to_pollset,
grpc_tcp_shutdown, grpc_tcp_destroy};
grpc_tcp_notify_on_read, grpc_tcp_write, grpc_tcp_add_to_pollset,
grpc_tcp_shutdown, grpc_tcp_destroy, grpc_tcp_get_peer};
grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size) {
grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size,
const char *peer_string) {
grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp));
tcp->base.vtable = &vtable;
tcp->peer_string = gpr_strdup(peer_string);
tcp->fd = em_fd->fd;
tcp->read_cb = NULL;
tcp->write_cb = NULL;

@ -53,6 +53,7 @@ extern int grpc_tcp_trace;
/* Create a tcp endpoint given a file desciptor and a read slice size.
Takes ownership of fd. */
grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size);
grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size,
const char *peer_string);
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_POSIX_H */

@ -332,7 +332,7 @@ static void on_read(void *arg, int success) {
grpc_set_socket_no_sigpipe_if_possible(fd);
grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
addr_str = grpc_sockaddr_to_uri((struct sockaddr *)&addr);
gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
fdobj = grpc_fd_create(fd, name);
@ -342,8 +342,9 @@ static void on_read(void *arg, int success) {
for (i = 0; i < sp->server->pollset_count; i++) {
grpc_pollset_add_fd(sp->server->pollsets[i], fdobj);
}
sp->server->cb(sp->server->cb_arg,
grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
sp->server->cb(
sp->server->cb_arg,
grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str));
gpr_free(name);
gpr_free(addr_str);

@ -243,6 +243,10 @@ static void on_accept(void *arg, int from_iocp) {
SOCKET sock = sp->new_socket;
grpc_winsocket_callback_info *info = &sp->socket->read_info;
grpc_endpoint *ep = NULL;
struct sockaddr_storage peer_name;
char *peer_name_string;
char *fd_name;
int peer_name_len = sizeof(peer_name);
DWORD transfered_bytes;
DWORD flags;
BOOL wsa_success;
@ -277,8 +281,12 @@ static void on_accept(void *arg, int from_iocp) {
}
} else {
if (!sp->shutting_down) {
/* TODO(ctiller): add sockaddr address to label */
ep = grpc_tcp_create(grpc_winsocket_create(sock, "server"));
getpeername(sock, (struct sockaddr*)&peer_name, &peer_name_len);
peer_name_string = grpc_sockaddr_to_uri((struct sockaddr*)&peer_name);
gpr_asprintf(&fd_name, "tcp_server:%s", peer_name_string);
ep = grpc_tcp_create(grpc_winsocket_create(sock, fd_name), peer_name_string);
gpr_free(fd_name);
gpr_free(peer_name_string);
}
}

@ -96,6 +96,8 @@ typedef struct grpc_tcp {
to protect ourselves when requesting a shutdown. */
gpr_mu mu;
int shutting_down;
char *peer_string;
} grpc_tcp;
static void tcp_ref(grpc_tcp *tcp) {
@ -107,6 +109,7 @@ static void tcp_unref(grpc_tcp *tcp) {
gpr_slice_buffer_destroy(&tcp->write_slices);
grpc_winsocket_orphan(tcp->socket);
gpr_mu_destroy(&tcp->mu);
gpr_free(tcp->peer_string);
gpr_free(tcp);
}
}
@ -393,11 +396,16 @@ static void win_destroy(grpc_endpoint *ep) {
tcp_unref(tcp);
}
static char *win_get_peer(grpc_endpoint *ep) {
grpc_tcp *tcp = (grpc_tcp *)ep;
return gpr_strdup(tcp->peer_string);
}
static grpc_endpoint_vtable vtable = {
win_notify_on_read, win_write, win_add_to_pollset, win_shutdown, win_destroy
win_notify_on_read, win_write, win_add_to_pollset, win_shutdown, win_destroy, win_get_peer
};
grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket) {
grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) {
grpc_tcp *tcp = (grpc_tcp *) gpr_malloc(sizeof(grpc_tcp));
memset(tcp, 0, sizeof(grpc_tcp));
tcp->base.vtable = &vtable;
@ -405,6 +413,7 @@ grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket) {
gpr_mu_init(&tcp->mu);
gpr_slice_buffer_init(&tcp->write_slices);
gpr_ref_init(&tcp->refcount, 1);
tcp->peer_string = gpr_strdup(peer_string);
return &tcp->base;
}

@ -50,7 +50,7 @@
/* Create a tcp endpoint given a winsock handle.
* Takes ownership of the handle.
*/
grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket);
grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string);
int grpc_tcp_prepare_socket(SOCKET sock);

@ -344,6 +344,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
}
const grpc_channel_filter grpc_client_auth_filter = {
auth_start_transport_op, grpc_channel_next_op, sizeof(call_data),
init_call_elem, destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem, "client-auth"};
auth_start_transport_op, grpc_channel_next_op,
sizeof(call_data), init_call_elem,
destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem,
grpc_call_next_get_peer, "client-auth"};

@ -315,7 +315,7 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
/* -- Jwt credentials -- */
static void jwt_reset_cache(grpc_jwt_credentials *c) {
static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
if (c->cached.jwt_md != NULL) {
grpc_credentials_md_store_unref(c->cached.jwt_md);
c->cached.jwt_md = NULL;
@ -328,7 +328,8 @@ static void jwt_reset_cache(grpc_jwt_credentials *c) {
}
static void jwt_destroy(grpc_credentials *creds) {
grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds;
grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
grpc_auth_json_key_destruct(&c->key);
jwt_reset_cache(c);
gpr_mu_destroy(&c->cache_mu);
@ -346,7 +347,8 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_jwt_credentials *c = (grpc_jwt_credentials *)creds;
grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
gpr_timespec refresh_threshold = gpr_time_from_seconds(
GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN);
@ -399,15 +401,16 @@ static grpc_credentials_vtable jwt_vtable = {
jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
jwt_get_request_metadata, NULL};
grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key(
grpc_credentials *
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key key, gpr_timespec token_lifetime) {
grpc_jwt_credentials *c;
grpc_service_account_jwt_access_credentials *c;
if (!grpc_auth_json_key_is_valid(&key)) {
gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
return NULL;
}
c = gpr_malloc(sizeof(grpc_jwt_credentials));
memset(c, 0, sizeof(grpc_jwt_credentials));
c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_JWT;
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &jwt_vtable;
@ -418,9 +421,9 @@ grpc_credentials *grpc_jwt_credentials_create_from_auth_json_key(
return &c->base;
}
grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
gpr_timespec token_lifetime) {
return grpc_jwt_credentials_create_from_auth_json_key(
grpc_credentials *grpc_service_account_jwt_access_credentials_create(
const char *json_key, gpr_timespec token_lifetime) {
return grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key_create_from_string(json_key), token_lifetime);
}

@ -188,7 +188,8 @@ grpc_credentials *grpc_fake_oauth2_credentials_create(
/* 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_credentials *
grpc_service_account_jwt_access_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
@ -240,7 +241,7 @@ typedef struct {
grpc_auth_json_key key;
gpr_timespec jwt_lifetime;
} grpc_jwt_credentials;
} grpc_service_account_jwt_access_credentials;
/* -- Oauth2TokenFetcher credentials --

@ -140,8 +140,9 @@ static grpc_credentials *create_default_creds_from_path(char *creds_path) {
/* 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);
result =
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
key, grpc_max_auth_token_lifetime);
goto end;
}

@ -331,9 +331,14 @@ static void endpoint_add_to_pollset(grpc_endpoint *secure_ep,
grpc_endpoint_add_to_pollset(ep->wrapped_ep, pollset);
}
static char *endpoint_get_peer(grpc_endpoint *secure_ep) {
secure_endpoint *ep = (secure_endpoint *)secure_ep;
return grpc_endpoint_get_peer(ep->wrapped_ep);
}
static const grpc_endpoint_vtable vtable = {
endpoint_notify_on_read, endpoint_write, endpoint_add_to_pollset,
endpoint_shutdown, endpoint_unref};
endpoint_shutdown, endpoint_unref, endpoint_get_peer};
grpc_endpoint *grpc_secure_endpoint_create(
struct tsi_frame_protector *protector, grpc_endpoint *transport,

@ -120,6 +120,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
}
const grpc_channel_filter grpc_server_auth_filter = {
auth_start_transport_op, grpc_channel_next_op, sizeof(call_data),
init_call_elem, destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem, "server-auth"};
auth_start_transport_op, grpc_channel_next_op,
sizeof(call_data), init_call_elem,
destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem,
grpc_call_next_get_peer, "server-auth"};

@ -50,7 +50,7 @@ int gpr_join_host_port(char **out, const char *host, int port) {
}
}
void gpr_split_host_port(const char *name, char **host, char **port) {
int gpr_split_host_port(const char *name, char **host, char **port) {
const char *host_start;
size_t host_len;
const char *port_start;
@ -63,7 +63,7 @@ void gpr_split_host_port(const char *name, char **host, char **port) {
const char *rbracket = strchr(name, ']');
if (rbracket == NULL) {
/* Unmatched [ */
return;
return 0;
}
if (rbracket[1] == '\0') {
/* ]<end> */
@ -73,14 +73,14 @@ void gpr_split_host_port(const char *name, char **host, char **port) {
port_start = rbracket + 2;
} else {
/* ]<invalid> */
return;
return 0;
}
host_start = name + 1;
host_len = (size_t)(rbracket - host_start);
if (memchr(host_start, ':', host_len) == NULL) {
/* Require all bracketed hosts to contain a colon, because a hostname or
IPv4 address should never use brackets. */
return;
return 0;
}
} else {
const char *colon = strchr(name, ':');
@ -105,4 +105,6 @@ void gpr_split_host_port(const char *name, char **host, char **port) {
if (port_start != NULL) {
*port = gpr_strdup(port_start);
}
return 1;
}

@ -1253,6 +1253,11 @@ static void execute_op(grpc_call *call, grpc_transport_stream_op *op) {
elem->filter->start_transport_stream_op(elem, op);
}
char *grpc_call_get_peer(grpc_call *call) {
grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0);
return elem->filter->get_peer(elem);
}
grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
return CALL_FROM_TOP_ELEM(elem);
}
@ -1368,7 +1373,8 @@ static void recv_metadata(grpc_call *call, grpc_metadata_batch *md) {
l->md = 0;
}
}
if (gpr_time_cmp(md->deadline, gpr_inf_future(GPR_CLOCK_REALTIME)) != 0) {
if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) !=
0) {
set_deadline_alarm(call, md->deadline);
}
if (!is_trailing) {

@ -36,12 +36,14 @@
#include <stdlib.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/iomgr/iomgr.h"
#include "src/core/support/string.h"
#include "src/core/surface/call.h"
#include "src/core/surface/init.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
/** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS.
* Avoids needing to take a metadata context lock for sending status
@ -73,6 +75,7 @@ struct grpc_channel {
gpr_mu registered_call_mu;
registered_call *registered_calls;
grpc_iomgr_closure destroy_closure;
char *target;
};
#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1))
@ -85,13 +88,14 @@ struct grpc_channel {
#define DEFAULT_MAX_MESSAGE_LENGTH (100 * 1024 * 1024)
grpc_channel *grpc_channel_create_from_filters(
const grpc_channel_filter **filters, size_t num_filters,
const char *target, const grpc_channel_filter **filters, size_t num_filters,
const grpc_channel_args *args, grpc_mdctx *mdctx, int is_client) {
size_t i;
size_t size =
sizeof(grpc_channel) + grpc_channel_stack_size(filters, num_filters);
grpc_channel *channel = gpr_malloc(size);
memset(channel, 0, sizeof(*channel));
channel->target = gpr_strdup(target);
GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
channel->is_client = is_client;
/* decremented by grpc_channel_destroy */
@ -137,6 +141,10 @@ grpc_channel *grpc_channel_create_from_filters(
return channel;
}
char *grpc_channel_get_target(grpc_channel *channel) {
return gpr_strdup(channel->target);
}
static grpc_call *grpc_channel_create_call_internal(
grpc_channel *channel, grpc_completion_queue *cq, grpc_mdelem *path_mdelem,
grpc_mdelem *authority_mdelem, gpr_timespec deadline) {
@ -222,6 +230,7 @@ static void destroy_channel(void *p, int ok) {
}
grpc_mdctx_unref(channel->metadata_context);
gpr_mu_destroy(&channel->registered_call_mu);
gpr_free(channel->target);
gpr_free(channel);
}

@ -38,7 +38,7 @@
#include "src/core/client_config/subchannel_factory.h"
grpc_channel *grpc_channel_create_from_filters(
const grpc_channel_filter **filters, size_t count,
const char *target, const grpc_channel_filter **filters, size_t count,
const grpc_channel_args *args, grpc_mdctx *mdctx, int is_client);
/** Get a (borrowed) pointer to this channels underlying channel stack */

@ -179,7 +179,8 @@ grpc_channel *grpc_channel_create(const char *target,
return NULL;
}
channel = grpc_channel_create_from_filters(filters, n, args, mdctx, 1);
channel =
grpc_channel_create_from_filters(target, filters, n, args, mdctx, 1);
grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel),
resolver);
GRPC_RESOLVER_UNREF(resolver, "create");

@ -39,6 +39,7 @@
#include "src/core/channel/channel_stack.h"
#include "src/core/client_config/resolver_registry.h"
#include "src/core/client_config/resolvers/dns_resolver.h"
#include "src/core/client_config/resolvers/sockaddr_resolver.h"
#include "src/core/debug/trace.h"
#include "src/core/iomgr/iomgr.h"
#include "src/core/profiling/timers.h"
@ -47,10 +48,6 @@
#include "src/core/surface/surface_trace.h"
#include "src/core/transport/chttp2_transport.h"
#ifdef GPR_POSIX_SOCKET
#include "src/core/client_config/resolvers/unix_resolver_posix.h"
#endif
static gpr_once g_basic_init = GPR_ONCE_INIT;
static gpr_mu g_init_mu;
static int g_initializations;
@ -68,6 +65,8 @@ void grpc_init(void) {
gpr_time_init();
grpc_resolver_registry_init("dns:///");
grpc_register_resolver_type("dns", grpc_dns_resolver_factory_create());
grpc_register_resolver_type("ipv4", grpc_ipv4_resolver_factory_create());
grpc_register_resolver_type("ipv6", grpc_ipv6_resolver_factory_create());
#ifdef GPR_POSIX_SOCKET
grpc_register_resolver_type("unix", grpc_unix_resolver_factory_create());
#endif

@ -47,7 +47,10 @@ typedef struct {
grpc_linked_mdelem details;
} call_data;
typedef struct { grpc_mdctx *mdctx; } channel_data;
typedef struct {
grpc_mdctx *mdctx;
grpc_channel *master;
} channel_data;
static void lame_start_transport_stream_op(grpc_call_element *elem,
grpc_transport_stream_op *op) {
@ -82,6 +85,11 @@ static void lame_start_transport_stream_op(grpc_call_element *elem,
}
}
static char *lame_get_peer(grpc_call_element *elem) {
channel_data *chand = elem->channel_data;
return grpc_channel_get_target(chand->master);
}
static void lame_start_transport_op(grpc_channel_element *elem,
grpc_transport_op *op) {
if (op->on_connectivity_state_change) {
@ -112,6 +120,7 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
GPR_ASSERT(is_first);
GPR_ASSERT(is_last);
chand->mdctx = mdctx;
chand->master = master;
}
static void destroy_channel_elem(grpc_channel_element *elem) {}
@ -125,11 +134,12 @@ static const grpc_channel_filter lame_filter = {
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
lame_get_peer,
"lame-client",
};
grpc_channel *grpc_lame_client_channel_create(void) {
grpc_channel *grpc_lame_client_channel_create(const char *target) {
static const grpc_channel_filter *filters[] = {&lame_filter};
return grpc_channel_create_from_filters(filters, 1, NULL, grpc_mdctx_create(),
1);
return grpc_channel_create_from_filters(target, filters, 1, NULL,
grpc_mdctx_create(), 1);
}

@ -196,13 +196,13 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
if (grpc_find_security_connector_in_args(args) != NULL) {
gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
return grpc_lame_client_channel_create();
return grpc_lame_client_channel_create(target);
}
if (grpc_credentials_create_security_connector(
creds, target, args, NULL, &connector, &new_args_from_connector) !=
GRPC_SECURITY_OK) {
return grpc_lame_client_channel_create();
return grpc_lame_client_channel_create(target);
}
mdctx = grpc_mdctx_create();
@ -231,7 +231,8 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
return NULL;
}
channel = grpc_channel_create_from_filters(filters, n, args_copy, mdctx, 1);
channel =
grpc_channel_create_from_filters(target, filters, n, args_copy, mdctx, 1);
grpc_client_channel_set_resolver(grpc_channel_get_channel_stack(channel),
resolver);
GRPC_RESOLVER_UNREF(resolver, "create");

@ -400,6 +400,15 @@ static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem,
call_data *calld = elem->call_data;
int request_id;
if (gpr_atm_acq_load(&server->shutdown_flag)) {
gpr_mu_lock(&calld->mu_state);
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
grpc_iomgr_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_iomgr_add_callback(&calld->kill_zombie_closure);
return;
}
request_id = gpr_stack_lockfree_pop(request_matcher->requests);
if (request_id == -1) {
gpr_mu_lock(&server->mu_call);
@ -530,6 +539,7 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
static void server_on_recv(void *ptr, int success) {
grpc_call_element *elem = ptr;
call_data *calld = elem->call_data;
gpr_timespec op_deadline;
if (success && !calld->got_initial_metadata) {
size_t i;
@ -539,8 +549,9 @@ static void server_on_recv(void *ptr, int success) {
grpc_stream_op *op = &ops[i];
if (op->type != GRPC_OP_METADATA) continue;
grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
if (0 != gpr_time_cmp(op->data.metadata.deadline,
gpr_inf_future(GPR_CLOCK_REALTIME))) {
op_deadline = op->data.metadata.deadline;
if (0 !=
gpr_time_cmp(op_deadline, gpr_inf_future(op_deadline.clock_type))) {
calld->deadline = op->data.metadata.deadline;
}
calld->got_initial_metadata = 1;
@ -722,6 +733,7 @@ static const grpc_channel_filter server_surface_filter = {
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
grpc_call_next_get_peer,
"server",
};
@ -878,8 +890,8 @@ void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport,
grpc_transport_perform_op(transport, &op);
}
channel =
grpc_channel_create_from_filters(filters, num_filters, args, mdctx, 0);
channel = grpc_channel_create_from_filters(NULL, filters, num_filters, args,
mdctx, 0);
chand = (channel_data *)grpc_channel_stack_element(
grpc_channel_get_channel_stack(channel), 0)
->channel_data;

@ -92,7 +92,7 @@ grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
p->frame_type = *cur;
switch (p->frame_type) {
case 0:
/* noop */
p->is_frame_compressed = 0; /* GPR_FALSE */
break;
case 1:
p->is_frame_compressed = 1; /* GPR_TRUE */

@ -60,7 +60,6 @@ typedef enum {
GRPC_CHTTP2_LIST_WRITABLE,
GRPC_CHTTP2_LIST_WRITING,
GRPC_CHTTP2_LIST_WRITTEN,
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE,
GRPC_CHTTP2_LIST_PARSING_SEEN,
GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING,
@ -286,6 +285,7 @@ struct grpc_chttp2_transport {
grpc_endpoint *ep;
grpc_mdctx *metadata_context;
gpr_refcount refs;
char *peer_string;
gpr_mu mu;
@ -382,6 +382,8 @@ typedef struct {
gpr_uint8 published_cancelled;
/** is this stream in the stream map? (boolean) */
gpr_uint8 in_stream_map;
/** is this stream actively being written? */
gpr_uint8 writing_now;
/** stream state already published to the upper layer */
grpc_stream_state published_state;
@ -474,11 +476,17 @@ void grpc_chttp2_publish_reads(grpc_chttp2_transport_global *global,
void grpc_chttp2_list_add_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
void grpc_chttp2_list_add_first_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_remove_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
void grpc_chttp2_list_add_incoming_window_updated(
grpc_chttp2_transport_global *transport_global,
@ -510,18 +518,6 @@ int grpc_chttp2_list_pop_written_stream(
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_add_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_remove_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
void grpc_chttp2_list_add_parsing_seen_stream(
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing);

@ -182,8 +182,7 @@ void grpc_chttp2_publish_reads(
stream_global->max_recv_bytes -=
stream_parsing->incoming_window_delta;
stream_parsing->incoming_window_delta = 0;
grpc_chttp2_list_add_writable_window_update_stream(transport_global,
stream_global);
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
}
/* update outgoing flow control window */
@ -607,7 +606,7 @@ static void on_header(void *tp, grpc_mdelem *md) {
}
grpc_chttp2_incoming_metadata_buffer_set_deadline(
&stream_parsing->incoming_metadata,
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), *cached_timeout));
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
GRPC_MDELEM_UNREF(md);
} else {
grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,

@ -108,6 +108,23 @@ static void stream_list_maybe_remove(grpc_chttp2_transport *t,
}
}
static void stream_list_add_head(grpc_chttp2_transport *t,
grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
grpc_chttp2_stream *old_head;
GPR_ASSERT(!s->included[id]);
old_head = t->lists[id].head;
s->links[id].next = old_head;
s->links[id].prev = NULL;
if (old_head) {
old_head->links[id].prev = s;
} else {
t->lists[id].tail = s;
}
t->lists[id].head = s;
s->included[id] = 1;
}
static void stream_list_add_tail(grpc_chttp2_transport *t,
grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
@ -119,7 +136,6 @@ static void stream_list_add_tail(grpc_chttp2_transport *t,
if (old_tail) {
old_tail->links[id].next = s;
} else {
s->links[id].prev = NULL;
t->lists[id].head = s;
}
t->lists[id].tail = s;
@ -144,6 +160,18 @@ void grpc_chttp2_list_add_writable_stream(
STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE);
}
void grpc_chttp2_list_add_first_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
GPR_ASSERT(stream_global->id != 0);
gpr_log(GPR_DEBUG, "add:%d:%d:%d:%d", stream_global->id,
stream_global->write_state, stream_global->in_stream_map,
stream_global->read_closed);
stream_list_add_head(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE);
}
int grpc_chttp2_list_pop_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
@ -157,6 +185,14 @@ int grpc_chttp2_list_pop_writable_stream(
return r;
}
void grpc_chttp2_list_remove_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE);
}
void grpc_chttp2_list_add_writing_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing *stream_writing) {
@ -202,36 +238,6 @@ int grpc_chttp2_list_pop_written_stream(
return r;
}
void grpc_chttp2_list_add_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
GPR_ASSERT(stream_global->id != 0);
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
}
int grpc_chttp2_list_pop_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
*stream_global = &stream->global;
*stream_writing = &stream->writing;
return r;
}
void grpc_chttp2_list_remove_writable_window_update_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE);
}
void grpc_chttp2_list_add_parsing_seen_stream(
grpc_chttp2_transport_parsing *transport_parsing,
grpc_chttp2_stream_parsing *stream_parsing) {

@ -44,6 +44,7 @@ int grpc_chttp2_unlocking_check_writes(
grpc_chttp2_transport_writing *transport_writing) {
grpc_chttp2_stream_global *stream_global;
grpc_chttp2_stream_writing *stream_writing;
grpc_chttp2_stream_global *first_reinserted_stream = NULL;
gpr_uint32 window_delta;
/* simple writes are queued to qbuf, and flushed here */
@ -64,50 +65,54 @@ int grpc_chttp2_unlocking_check_writes(
}
/* for each grpc_chttp2_stream that's become writable, frame it's data
(according to
available window sizes) and add to the output buffer */
while (grpc_chttp2_list_pop_writable_stream(transport_global,
transport_writing, &stream_global,
&stream_writing)) {
(according to available window sizes) and add to the output buffer */
while (grpc_chttp2_list_pop_writable_stream(
transport_global, transport_writing, &stream_global, &stream_writing)) {
if (stream_global == first_reinserted_stream) {
/* prevent infinite loop */
grpc_chttp2_list_add_first_writable_stream(transport_global,
stream_global);
break;
}
stream_writing->id = stream_global->id;
window_delta = grpc_chttp2_preencode(
stream_global->outgoing_sopb->ops, &stream_global->outgoing_sopb->nops,
GPR_MIN(transport_global->outgoing_window,
stream_global->outgoing_window),
&stream_writing->sopb);
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"write", transport_global, outgoing_window, -(gpr_int64)window_delta);
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global,
outgoing_window, -(gpr_int64)window_delta);
transport_global->outgoing_window -= window_delta;
stream_global->outgoing_window -= window_delta;
if (stream_global->write_state == GRPC_WRITE_STATE_QUEUED_CLOSE &&
stream_global->outgoing_sopb->nops == 0) {
if (!transport_global->is_client && !stream_global->read_closed) {
stream_writing->send_closed = GRPC_SEND_CLOSED_WITH_RST_STREAM;
} else {
stream_writing->send_closed = GRPC_SEND_CLOSED;
stream_writing->send_closed = GRPC_DONT_SEND_CLOSED;
GPR_ASSERT(!stream_global->writing_now);
if (stream_global->outgoing_sopb) {
window_delta =
grpc_chttp2_preencode(stream_global->outgoing_sopb->ops,
&stream_global->outgoing_sopb->nops,
GPR_MIN(transport_global->outgoing_window,
stream_global->outgoing_window),
&stream_writing->sopb);
GRPC_CHTTP2_FLOWCTL_TRACE_TRANSPORT(
"write", transport_global, outgoing_window, -(gpr_int64)window_delta);
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global,
outgoing_window,
-(gpr_int64)window_delta);
transport_global->outgoing_window -= window_delta;
stream_global->outgoing_window -= window_delta;
if (stream_global->write_state == GRPC_WRITE_STATE_QUEUED_CLOSE &&
stream_global->outgoing_sopb->nops == 0) {
if (!transport_global->is_client && !stream_global->read_closed) {
stream_writing->send_closed = GRPC_SEND_CLOSED_WITH_RST_STREAM;
} else {
stream_writing->send_closed = GRPC_SEND_CLOSED;
}
}
}
if (stream_writing->sopb.nops > 0 ||
stream_writing->send_closed != GRPC_DONT_SEND_CLOSED) {
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
}
if (stream_global->outgoing_window > 0 &&
stream_global->outgoing_sopb->nops != 0) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
if (stream_global->outgoing_window > 0 &&
stream_global->outgoing_sopb->nops != 0) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
if (first_reinserted_stream == NULL &&
transport_global->outgoing_window == 0) {
first_reinserted_stream = stream_global;
}
}
}
}
/* for each grpc_chttp2_stream that wants to update its window, add that
* window here */
while (grpc_chttp2_list_pop_writable_window_update_stream(transport_global,
transport_writing,
&stream_global,
&stream_writing)) {
stream_writing->id = stream_global->id;
if (!stream_global->read_closed && stream_global->unannounced_incoming_window > 0) {
stream_writing->announce_window = stream_global->unannounced_incoming_window;
GRPC_CHTTP2_FLOWCTL_TRACE_STREAM("write", transport_global, stream_global,
@ -118,6 +123,11 @@ int grpc_chttp2_unlocking_check_writes(
stream_global->unannounced_incoming_window = 0;
grpc_chttp2_list_add_incoming_window_updated(transport_global,
stream_global);
stream_global->writing_now = 1;
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
} else if (stream_writing->sopb.nops > 0 ||
stream_writing->send_closed != GRPC_DONT_SEND_CLOSED) {
stream_global->writing_now = 1;
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
}
}
@ -205,6 +215,8 @@ void grpc_chttp2_cleanup_writing(
while (grpc_chttp2_list_pop_written_stream(
transport_global, transport_writing, &stream_global, &stream_writing)) {
GPR_ASSERT(stream_global->writing_now);
stream_global->writing_now = 0;
if (stream_global->outgoing_sopb != NULL &&
stream_global->outgoing_sopb->nops == 0) {
stream_global->outgoing_sopb = NULL;
@ -216,9 +228,9 @@ void grpc_chttp2_cleanup_writing(
if (!transport_global->is_client) {
stream_global->read_closed = 1;
}
grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global);
}
grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global);
}
transport_writing->outbuf.count = 0;
transport_writing->outbuf.length = 0;

@ -168,6 +168,7 @@ static void destruct_transport(grpc_chttp2_transport *t) {
grpc_mdctx_unref(t->metadata_context);
gpr_free(t->peer_string);
gpr_free(t);
}
@ -217,6 +218,7 @@ static void init_transport(grpc_chttp2_transport *t,
gpr_ref_init(&t->refs, 2);
gpr_mu_init(&t->mu);
grpc_mdctx_ref(mdctx);
t->peer_string = grpc_endpoint_get_peer(ep);
t->metadata_context = mdctx;
t->endpoint_reading = 1;
t->global.next_stream_id = is_client ? 1 : 2;
@ -393,12 +395,16 @@ static void destroy_stream(grpc_transport *gt, grpc_stream *gs) {
}
grpc_chttp2_list_remove_incoming_window_updated(&t->global, &s->global);
grpc_chttp2_list_remove_writable_window_update_stream(&t->global, &s->global);
grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
gpr_mu_unlock(&t->mu);
for (i = 0; i < STREAM_LIST_COUNT; i++) {
GPR_ASSERT(!s->included[i]);
if (s->included[i]) {
gpr_log(GPR_ERROR, "%s stream %d still included in list %d",
t->global.is_client ? "client" : "server", s->global.id, i);
abort();
}
}
GPR_ASSERT(s->global.outgoing_sopb == NULL);
@ -574,8 +580,6 @@ static void maybe_start_some_streams(
grpc_chttp2_list_add_incoming_window_updated(transport_global,
stream_global);
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
grpc_chttp2_list_add_writable_window_update_stream(transport_global,
stream_global);
}
/* cancel out streams that will never be started */
@ -641,8 +645,7 @@ static void perform_stream_op_locked(
if (stream_global->id != 0) {
grpc_chttp2_list_add_read_write_state_changed(transport_global,
stream_global);
grpc_chttp2_list_add_writable_window_update_stream(transport_global,
stream_global);
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
}
}
@ -750,6 +753,7 @@ static void remove_stream(grpc_chttp2_transport *t, gpr_uint32 id) {
if (!s) {
s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
}
grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
GPR_ASSERT(s);
s->global.in_stream_map = 0;
if (t->parsing.incoming_stream == &s->parsing) {
@ -831,6 +835,9 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
if (!stream_global->publish_sopb) {
continue;
}
if (stream_global->writing_now) {
continue;
}
/* FIXME(ctiller): we include in_stream_map in our computation of
whether the stream is write-closed. This is completely bogus,
but has the effect of delaying stream-closed until the stream
@ -1069,9 +1076,17 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *reason,
* INTEGRATION GLUE
*/
static const grpc_transport_vtable vtable = {
sizeof(grpc_chttp2_stream), init_stream, perform_stream_op,
perform_transport_op, destroy_stream, destroy_transport};
static char *chttp2_get_peer(grpc_transport *t) {
return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string);
}
static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
init_stream,
perform_stream_op,
perform_transport_op,
destroy_stream,
destroy_transport,
chttp2_get_peer};
grpc_transport *grpc_create_chttp2_transport(
const grpc_channel_args *channel_args, grpc_endpoint *ep, grpc_mdctx *mdctx,

@ -65,6 +65,10 @@ void grpc_transport_destroy_stream(grpc_transport *transport,
transport->vtable->destroy_stream(transport, stream);
}
char *grpc_transport_get_peer(grpc_transport *transport) {
return transport->vtable->get_peer(transport);
}
void grpc_transport_stream_op_finish_with_failure(
grpc_transport_stream_op *op) {
if (op->send_ops) {

@ -182,4 +182,7 @@ void grpc_transport_close(grpc_transport *transport);
/* Destroy the transport */
void grpc_transport_destroy(grpc_transport *transport);
/* Get the transports peer */
char *grpc_transport_get_peer(grpc_transport *transport);
#endif /* GRPC_INTERNAL_CORE_TRANSPORT_TRANSPORT_H */

@ -58,6 +58,9 @@ typedef struct grpc_transport_vtable {
/* implementation of grpc_transport_destroy */
void (*destroy)(grpc_transport *self);
/* implementation of grpc_transport_get_peer */
char *(*get_peer)(grpc_transport *self);
} grpc_transport_vtable;
/* an instance of a grpc transport */

@ -116,10 +116,9 @@ char *grpc_transport_stream_op_string(grpc_transport_stream_op *op) {
if (op->send_ops) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = 0;
gpr_strvec_add(&b, gpr_strdup("SEND"));
if (op->is_last_send) {
gpr_strvec_add(&b, gpr_strdup("_LAST"));
}
gpr_asprintf(&tmp, "SEND%s:%p", op->is_last_send ? "_LAST" : "",
op->on_done_send);
gpr_strvec_add(&b, tmp);
gpr_strvec_add(&b, gpr_strdup("["));
gpr_strvec_add(&b, grpc_sopb_string(op->send_ops));
gpr_strvec_add(&b, gpr_strdup("]"));
@ -128,7 +127,8 @@ char *grpc_transport_stream_op_string(grpc_transport_stream_op *op) {
if (op->recv_ops) {
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = 0;
gpr_asprintf(&tmp, "RECV:max_recv_bytes=%d", op->max_recv_bytes);
gpr_asprintf(&tmp, "RECV:%p:max_recv_bytes=%d", op->on_done_recv,
op->max_recv_bytes);
gpr_strvec_add(&b, tmp);
}

@ -52,6 +52,6 @@ std::shared_ptr<ChannelInterface> CreateChannel(
user_agent_prefix.str());
return creds ? creds->CreateChannel(target, cp_args)
: std::shared_ptr<ChannelInterface>(
new Channel(target, grpc_lame_client_channel_create()));
new Channel(target, grpc_lame_client_channel_create(NULL)));
}
} // namespace grpc

@ -99,8 +99,8 @@ std::shared_ptr<Credentials> ServiceAccountCredentials(
}
// Builds JWT credentials.
std::shared_ptr<Credentials> JWTCredentials(const grpc::string& json_key,
long token_lifetime_seconds) {
std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials(
const grpc::string& json_key, long token_lifetime_seconds) {
if (token_lifetime_seconds <= 0) {
gpr_log(GPR_ERROR,
"Trying to create JWTCredentials with non-positive lifetime");
@ -108,8 +108,8 @@ std::shared_ptr<Credentials> JWTCredentials(const grpc::string& json_key,
}
gpr_timespec lifetime =
gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN);
return WrapCredentials(
grpc_jwt_credentials_create(json_key.c_str(), lifetime));
return WrapCredentials(grpc_service_account_jwt_access_credentials_create(
json_key.c_str(), lifetime));
}
// Builds refresh token credentials.

@ -79,9 +79,10 @@ void TimepointHR2Timespec(const high_resolution_clock::time_point& from,
}
system_clock::time_point Timespec2Timepoint(gpr_timespec t) {
if (gpr_time_cmp(t, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) {
if (gpr_time_cmp(t, gpr_inf_future(t.clock_type)) == 0) {
return system_clock::time_point::max();
}
t = gpr_convert_clock_type(t, GPR_CLOCK_REALTIME);
system_clock::time_point tp;
tp += duration_cast<system_clock::time_point::duration>(seconds(t.tv_sec));
tp +=

@ -44,13 +44,14 @@
<Compile Include="ClientServerTest.cs" />
<Compile Include="ServerTest.cs" />
<Compile Include="GrpcEnvironmentTest.cs" />
<Compile Include="TimespecTest.cs" />
<Compile Include="PInvokeTest.cs" />
<Compile Include="Internal\MetadataArraySafeHandleTest.cs" />
<Compile Include="Internal\CompletionQueueSafeHandleTest.cs" />
<Compile Include="Internal\CompletionQueueEventTest.cs" />
<Compile Include="Internal\ChannelArgsSafeHandleTest.cs" />
<Compile Include="ChannelOptionsTest.cs" />
<Compile Include="Internal\TimespecTest.cs" />
<Compile Include="TimeoutsTest.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

@ -0,0 +1,202 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Runtime.InteropServices;
using Grpc.Core.Internal;
using NUnit.Framework;
namespace Grpc.Core.Internal.Tests
{
public class TimespecTest
{
[Test]
public void Now_IsInUtc()
{
Assert.AreEqual(DateTimeKind.Utc, Timespec.Now.ToDateTime().Kind);
}
[Test]
public void Now_AgreesWithUtcNow()
{
var timespec = Timespec.Now;
var utcNow = DateTime.UtcNow;
TimeSpan difference = utcNow - timespec.ToDateTime();
// This test is inherently a race - but the two timestamps
// should really be way less that a minute apart.
Assert.IsTrue(difference.TotalSeconds < 60);
}
[Test]
public void InfFuture()
{
var timespec = Timespec.InfFuture;
}
[Test]
public void InfPast()
{
var timespec = Timespec.InfPast;
}
[Test]
public void TimespecSizeIsNativeSize()
{
Assert.AreEqual(Timespec.NativeSize, Marshal.SizeOf(typeof(Timespec)));
}
[Test]
public void ToDateTime()
{
Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
new Timespec(IntPtr.Zero, 0).ToDateTime());
Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 10, DateTimeKind.Utc).AddTicks(50),
new Timespec(new IntPtr(10), 5000).ToDateTime());
Assert.AreEqual(new DateTime(2015, 7, 21, 4, 21, 48, DateTimeKind.Utc),
new Timespec(new IntPtr(1437452508), 0).ToDateTime());
// before epoch
Assert.AreEqual(new DateTime(1969, 12, 31, 23, 59, 55, DateTimeKind.Utc).AddTicks(10),
new Timespec(new IntPtr(-5), 1000).ToDateTime());
// infinity
Assert.AreEqual(DateTime.MaxValue, Timespec.InfFuture.ToDateTime());
Assert.AreEqual(DateTime.MinValue, Timespec.InfPast.ToDateTime());
// nanos are rounded to ticks are rounded up
Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(1),
new Timespec(IntPtr.Zero, 99).ToDateTime());
// Illegal inputs
Assert.Throws(typeof(InvalidOperationException),
() => new Timespec(new IntPtr(0), -2).ToDateTime());
Assert.Throws(typeof(InvalidOperationException),
() => new Timespec(new IntPtr(0), 1000 * 1000 * 1000).ToDateTime());
Assert.Throws(typeof(InvalidOperationException),
() => new Timespec(new IntPtr(0), 0, GPRClockType.Monotonic).ToDateTime());
}
[Test]
public void ToDateTime_ReturnsUtc()
{
Assert.AreEqual(DateTimeKind.Utc, new Timespec(new IntPtr(1437452508), 0).ToDateTime().Kind);
Assert.AreNotEqual(DateTimeKind.Unspecified, new Timespec(new IntPtr(1437452508), 0).ToDateTime().Kind);
}
[Test]
public void ToDateTime_Overflow()
{
// we can only get overflow in ticks arithmetic on 64-bit
if (IntPtr.Size == 8)
{
var timespec = new Timespec(new IntPtr(long.MaxValue - 100), 0);
Assert.AreNotEqual(Timespec.InfFuture, timespec);
Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime());
Assert.AreEqual(DateTime.MinValue, new Timespec(new IntPtr(long.MinValue + 100), 0).ToDateTime());
}
else
{
Console.WriteLine("Test cannot be run on this platform, skipping the test.");
}
}
[Test]
public void ToDateTime_OutOfDateTimeRange()
{
// we can only get out of range on 64-bit, on 32 bit the max
// timestamp is ~ Jan 19 2038, which is far within range of DateTime
// same case for min value.
if (IntPtr.Size == 8)
{
// DateTime range goes up to year 9999, 20000 years from now should
// be out of range.
long seconds = 20000L * 365L * 24L * 3600L;
var timespec = new Timespec(new IntPtr(seconds), 0);
Assert.AreNotEqual(Timespec.InfFuture, timespec);
Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime());
Assert.AreEqual(DateTime.MinValue, new Timespec(new IntPtr(-seconds), 0).ToDateTime());
}
else
{
Console.WriteLine("Test cannot be run on this platform, skipping the test");
}
}
[Test]
public void FromDateTime()
{
Assert.AreEqual(new Timespec(IntPtr.Zero, 0),
Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
Assert.AreEqual(new Timespec(new IntPtr(10), 5000),
Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 10, DateTimeKind.Utc).AddTicks(50)));
Assert.AreEqual(new Timespec(new IntPtr(1437452508), 0),
Timespec.FromDateTime(new DateTime(2015, 7, 21, 4, 21, 48, DateTimeKind.Utc)));
// before epoch
Assert.AreEqual(new Timespec(new IntPtr(-5), 1000),
Timespec.FromDateTime(new DateTime(1969, 12, 31, 23, 59, 55, DateTimeKind.Utc).AddTicks(10)));
// infinity
Assert.AreEqual(Timespec.InfFuture, Timespec.FromDateTime(DateTime.MaxValue));
Assert.AreEqual(Timespec.InfPast, Timespec.FromDateTime(DateTime.MinValue));
// illegal inputs
Assert.Throws(typeof(ArgumentException),
() => Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified)));
}
[Test]
public void FromDateTime_OutOfTimespecRange()
{
// we can only get overflow in Timespec on 32-bit
if (IntPtr.Size == 4)
{
Assert.AreEqual(Timespec.InfFuture, Timespec.FromDateTime(new DateTime(2040, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
Assert.AreEqual(Timespec.InfPast, Timespec.FromDateTime(new DateTime(1800, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
}
else
{
Console.WriteLine("Test cannot be run on this platform, skipping the test.");
}
}
}
}

@ -0,0 +1,207 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
using NUnit.Framework;
namespace Grpc.Core.Tests
{
/// <summary>
/// Tests for Deadline support.
/// </summary>
public class TimeoutsTest
{
const string Host = "localhost";
const string ServiceName = "/tests.Test";
static readonly Method<string, string> TestMethod = new Method<string, string>(
MethodType.Unary,
"/tests.Test/Test",
Marshallers.StringMarshaller,
Marshallers.StringMarshaller);
static readonly ServerServiceDefinition ServiceDefinition = ServerServiceDefinition.CreateBuilder(ServiceName)
.AddMethod(TestMethod, TestMethodHandler)
.Build();
// provides a way how to retrieve an out-of-band result value from server handler
static TaskCompletionSource<string> stringFromServerHandlerTcs;
Server server;
Channel channel;
[SetUp]
public void Init()
{
server = new Server();
server.AddServiceDefinition(ServiceDefinition);
int port = server.AddListeningPort(Host, Server.PickUnusedPort);
server.Start();
channel = new Channel(Host, port);
stringFromServerHandlerTcs = new TaskCompletionSource<string>();
}
[TearDown]
public void Cleanup()
{
channel.Dispose();
server.ShutdownAsync().Wait();
}
[TestFixtureTearDown]
public void CleanupClass()
{
GrpcEnvironment.Shutdown();
}
[Test]
public void InfiniteDeadline()
{
// no deadline specified, check server sees infinite deadline
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty);
Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(internalCall, "RETURN_DEADLINE", CancellationToken.None));
// DateTime.MaxValue deadline specified, check server sees infinite deadline
var internalCall2 = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, DateTime.MaxValue);
Assert.AreEqual("DATETIME_MAXVALUE", Calls.BlockingUnaryCall(internalCall2, "RETURN_DEADLINE", CancellationToken.None));
}
[Test]
public void DeadlineTransferredToServer()
{
var remainingTimeClient = TimeSpan.FromDays(7);
var deadline = DateTime.UtcNow + remainingTimeClient;
Thread.Sleep(1000);
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline);
var serverDeadlineTicksString = Calls.BlockingUnaryCall(internalCall, "RETURN_DEADLINE", CancellationToken.None);
var serverDeadline = new DateTime(long.Parse(serverDeadlineTicksString), DateTimeKind.Utc);
// A fairly relaxed check that the deadline set by client and deadline seen by server
// are in agreement. C core takes care of the work with transferring deadline over the wire,
// so we don't need an exact check here.
Assert.IsTrue(Math.Abs((deadline - serverDeadline).TotalMilliseconds) < 5000);
}
[Test]
public void DeadlineInThePast()
{
var deadline = DateTime.MinValue;
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline);
try
{
Calls.BlockingUnaryCall(internalCall, "TIMEOUT", CancellationToken.None);
Assert.Fail();
}
catch (RpcException e)
{
Assert.AreEqual(StatusCode.DeadlineExceeded, e.Status.StatusCode);
}
}
[Test]
public void DeadlineExceededStatusOnTimeout()
{
var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5));
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline);
try
{
Calls.BlockingUnaryCall(internalCall, "TIMEOUT", CancellationToken.None);
Assert.Fail();
}
catch (RpcException e)
{
Assert.AreEqual(StatusCode.DeadlineExceeded, e.Status.StatusCode);
}
}
[Test]
public void ServerReceivesCancellationOnTimeout()
{
var deadline = DateTime.UtcNow.Add(TimeSpan.FromSeconds(5));
var internalCall = new Call<string, string>(ServiceName, TestMethod, channel, Metadata.Empty, deadline);
try
{
Calls.BlockingUnaryCall(internalCall, "CHECK_CANCELLATION_RECEIVED", CancellationToken.None);
Assert.Fail();
}
catch (RpcException e)
{
Assert.AreEqual(StatusCode.DeadlineExceeded, e.Status.StatusCode);
}
Assert.AreEqual("CANCELLED", stringFromServerHandlerTcs.Task.Result);
}
private static async Task<string> TestMethodHandler(string request, ServerCallContext context)
{
if (request == "TIMEOUT")
{
await Task.Delay(60000);
return "";
}
if (request == "RETURN_DEADLINE")
{
if (context.Deadline == DateTime.MaxValue)
{
return "DATETIME_MAXVALUE";
}
return context.Deadline.Ticks.ToString();
}
if (request == "CHECK_CANCELLATION_RECEIVED")
{
// wait until cancellation token is fired.
var tcs = new TaskCompletionSource<object>();
context.CancellationToken.Register(() => { tcs.SetResult(null); });
await tcs.Task;
stringFromServerHandlerTcs.SetResult("CANCELLED");
return "";
}
return "";
}
}
}

@ -1,101 +0,0 @@
#region Copyright notice and license
// 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.
#endregion
using System;
using System.Runtime.InteropServices;
using Grpc.Core.Internal;
using NUnit.Framework;
namespace Grpc.Core.Internal.Tests
{
public class TimespecTest
{
[Test]
public void Now()
{
var timespec = Timespec.Now;
}
[Test]
public void InfFuture()
{
var timespec = Timespec.InfFuture;
}
[Test]
public void TimespecSizeIsNativeSize()
{
Assert.AreEqual(Timespec.NativeSize, Marshal.SizeOf(typeof(Timespec)));
}
[Test]
public void ToDateTime()
{
Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
new Timespec(IntPtr.Zero, 0).ToDateTime());
Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 10, DateTimeKind.Utc).AddTicks(50),
new Timespec(new IntPtr(10), 5000).ToDateTime());
Assert.AreEqual(new DateTime(2015, 7, 21, 4, 21, 48, DateTimeKind.Utc),
new Timespec(new IntPtr(1437452508), 0).ToDateTime());
}
[Test]
public void Add()
{
var t = new Timespec { tv_sec = new IntPtr(12345), tv_nsec = 123456789 };
var result = t.Add(TimeSpan.FromTicks(TimeSpan.TicksPerSecond * 10));
Assert.AreEqual(result.tv_sec, new IntPtr(12355));
Assert.AreEqual(result.tv_nsec, 123456789);
}
[Test]
public void Add_Nanos()
{
var t = new Timespec { tv_sec = new IntPtr(12345), tv_nsec = 123456789 };
var result = t.Add(TimeSpan.FromTicks(10));
Assert.AreEqual(result.tv_sec, new IntPtr(12345));
Assert.AreEqual(result.tv_nsec, 123456789 + 1000);
}
[Test]
public void Add_NanosOverflow()
{
var t = new Timespec { tv_sec = new IntPtr(12345), tv_nsec = 999999999 };
var result = t.Add(TimeSpan.FromTicks(TimeSpan.TicksPerSecond * 10 + 10));
Assert.AreEqual(result.tv_sec, new IntPtr(12356));
Assert.AreEqual(result.tv_nsec, 999);
}
}
}

@ -47,14 +47,21 @@ namespace Grpc.Core
readonly Marshaller<TResponse> responseMarshaller;
readonly Channel channel;
readonly Metadata headers;
readonly DateTime deadline;
public Call(string serviceName, Method<TRequest, TResponse> method, Channel channel, Metadata headers)
: this(serviceName, method, channel, headers, DateTime.MaxValue)
{
}
public Call(string serviceName, Method<TRequest, TResponse> method, Channel channel, Metadata headers, DateTime deadline)
{
this.name = method.GetFullName(serviceName);
this.requestMarshaller = method.RequestMarshaller;
this.responseMarshaller = method.ResponseMarshaller;
this.channel = Preconditions.CheckNotNull(channel);
this.headers = Preconditions.CheckNotNull(headers);
this.deadline = deadline;
}
public Channel Channel
@ -87,6 +94,14 @@ namespace Grpc.Core
}
}
public DateTime Deadline
{
get
{
return this.deadline;
}
}
public Marshaller<TRequest> RequestMarshaller
{
get

@ -50,7 +50,7 @@ namespace Grpc.Core
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
// TODO(jtattermusch): this gives a race that cancellation can be requested before the call even starts.
RegisterCancellationCallback(asyncCall, token);
return asyncCall.UnaryCall(call.Channel, call.Name, req, call.Headers);
return asyncCall.UnaryCall(call.Channel, call.Name, req, call.Headers, call.Deadline);
}
public static AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
@ -58,8 +58,8 @@ namespace Grpc.Core
where TResponse : class
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name);
var asyncResult = asyncCall.UnaryCallAsync(req, call.Headers);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline));
var asyncResult = asyncCall.UnaryCallAsync(req, call.Headers, call.Deadline);
RegisterCancellationCallback(asyncCall, token);
return new AsyncUnaryCall<TResponse>(asyncResult, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
}
@ -69,8 +69,8 @@ namespace Grpc.Core
where TResponse : class
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name);
asyncCall.StartServerStreamingCall(req, call.Headers);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline));
asyncCall.StartServerStreamingCall(req, call.Headers, call.Deadline);
RegisterCancellationCallback(asyncCall, token);
var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall);
return new AsyncServerStreamingCall<TResponse>(responseStream, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
@ -81,8 +81,8 @@ namespace Grpc.Core
where TResponse : class
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name);
var resultTask = asyncCall.ClientStreamingCallAsync(call.Headers);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline));
var resultTask = asyncCall.ClientStreamingCallAsync(call.Headers, call.Deadline);
RegisterCancellationCallback(asyncCall, token);
var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
return new AsyncClientStreamingCall<TRequest, TResponse>(requestStream, resultTask, asyncCall.GetStatus, asyncCall.GetTrailers, asyncCall.Cancel);
@ -93,8 +93,8 @@ namespace Grpc.Core
where TResponse : class
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name);
asyncCall.StartDuplexStreamingCall(call.Headers);
asyncCall.Initialize(call.Channel, call.Channel.CompletionQueue, call.Name, Timespec.FromDateTime(call.Deadline));
asyncCall.StartDuplexStreamingCall(call.Headers, call.Deadline);
RegisterCancellationCallback(asyncCall, token);
var requestStream = new ClientRequestStream<TRequest, TResponse>(asyncCall);
var responseStream = new ClientResponseStream<TRequest, TResponse>(asyncCall);

@ -76,7 +76,7 @@ namespace Grpc.Core
/// <summary>
/// Creates a new call to given method.
/// </summary>
protected Call<TRequest, TResponse> CreateCall<TRequest, TResponse>(string serviceName, Method<TRequest, TResponse> method, Metadata metadata)
protected Call<TRequest, TResponse> CreateCall<TRequest, TResponse>(string serviceName, Method<TRequest, TResponse> method, Metadata metadata, DateTime? deadline)
where TRequest : class
where TResponse : class
{
@ -87,8 +87,8 @@ namespace Grpc.Core
interceptor(metadata);
metadata.Freeze();
}
metadata = metadata ?? Metadata.Empty;
return new Call<TRequest, TResponse>(serviceName, method, channel, metadata);
return new Call<TRequest, TResponse>(serviceName, method, channel,
metadata ?? Metadata.Empty, deadline ?? DateTime.MaxValue);
}
}
}

@ -61,10 +61,10 @@ namespace Grpc.Core.Internal
{
}
public void Initialize(Channel channel, CompletionQueueSafeHandle cq, string methodName)
public void Initialize(Channel channel, CompletionQueueSafeHandle cq, string methodName, Timespec deadline)
{
this.channel = channel;
var call = CallSafeHandle.Create(channel.Handle, channel.CompletionRegistry, cq, methodName, channel.Target, Timespec.InfFuture);
var call = channel.Handle.CreateCall(channel.CompletionRegistry, cq, methodName, channel.Target, deadline);
channel.Environment.DebugStats.ActiveClientCalls.Increment();
InitializeInternal(call);
}
@ -76,7 +76,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Blocking unary request - unary response call.
/// </summary>
public TResponse UnaryCall(Channel channel, string methodName, TRequest msg, Metadata headers)
public TResponse UnaryCall(Channel channel, string methodName, TRequest msg, Metadata headers, DateTime deadline)
{
using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
{
@ -86,7 +86,7 @@ namespace Grpc.Core.Internal
lock (myLock)
{
Initialize(channel, cq, methodName);
Initialize(channel, cq, methodName, Timespec.FromDateTime(deadline));
started = true;
halfcloseRequested = true;
readingDone = true;
@ -126,7 +126,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Starts a unary request - unary response call.
/// </summary>
public Task<TResponse> UnaryCallAsync(TRequest msg, Metadata headers)
public Task<TResponse> UnaryCallAsync(TRequest msg, Metadata headers, DateTime deadline)
{
lock (myLock)
{
@ -151,7 +151,7 @@ namespace Grpc.Core.Internal
/// Starts a streamed request - unary response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
public Task<TResponse> ClientStreamingCallAsync(Metadata headers)
public Task<TResponse> ClientStreamingCallAsync(Metadata headers, DateTime deadline)
{
lock (myLock)
{
@ -173,7 +173,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Starts a unary request - streamed response call.
/// </summary>
public void StartServerStreamingCall(TRequest msg, Metadata headers)
public void StartServerStreamingCall(TRequest msg, Metadata headers, DateTime deadline)
{
lock (myLock)
{
@ -196,7 +196,7 @@ namespace Grpc.Core.Internal
/// Starts a streaming request - streaming response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
public void StartDuplexStreamingCall(Metadata headers)
public void StartDuplexStreamingCall(Metadata headers, DateTime deadline)
{
lock (myLock)
{

@ -48,6 +48,7 @@ namespace Grpc.Core.Internal
internal class AsyncCallServer<TRequest, TResponse> : AsyncCallBase<TResponse, TRequest>
{
readonly TaskCompletionSource<object> finishedServersideTcs = new TaskCompletionSource<object>();
readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
readonly GrpcEnvironment environment;
public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer, GrpcEnvironment environment) : base(serializer, deserializer)
@ -118,6 +119,18 @@ namespace Grpc.Core.Internal
}
}
/// <summary>
/// Gets cancellation token that gets cancelled once close completion
/// is received and the cancelled flag is set.
/// </summary>
public CancellationToken CancellationToken
{
get
{
return cancellationTokenSource.Token;
}
}
protected override void OnReleaseResources()
{
environment.DebugStats.ActiveServerCalls.Decrement();
@ -138,6 +151,8 @@ namespace Grpc.Core.Internal
{
// Once we cancel, we don't have to care that much
// about reads and writes.
// TODO(jtattermusch): is this still necessary?
Cancel();
}
@ -145,6 +160,11 @@ namespace Grpc.Core.Internal
}
// TODO(jtattermusch): handle error
if (cancelled)
{
cancellationTokenSource.Cancel();
}
finishedServersideTcs.SetResult(null);
}
}

@ -45,9 +45,6 @@ namespace Grpc.Core.Internal
const uint GRPC_WRITE_BUFFER_HINT = 1;
CompletionRegistry completionRegistry;
[DllImport("grpc_csharp_ext.dll")]
static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_cancel(CallSafeHandle call);
@ -98,13 +95,6 @@ namespace Grpc.Core.Internal
{
}
public static CallSafeHandle Create(ChannelSafeHandle channel, CompletionRegistry registry, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline)
{
var result = grpcsharp_channel_create_call(channel, cq, method, host, deadline);
result.SetCompletionRegistry(registry);
return result;
}
public void SetCompletionRegistry(CompletionRegistry completionRegistry)
{
this.completionRegistry = completionRegistry;

@ -46,6 +46,9 @@ namespace Grpc.Core.Internal
[DllImport("grpc_csharp_ext.dll")]
static extern ChannelSafeHandle grpcsharp_secure_channel_create(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs);
[DllImport("grpc_csharp_ext.dll")]
static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_channel_destroy(IntPtr channel);
@ -63,6 +66,13 @@ namespace Grpc.Core.Internal
return grpcsharp_secure_channel_create(credentials, target, channelArgs);
}
public CallSafeHandle CreateCall(CompletionRegistry registry, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline)
{
var result = grpcsharp_channel_create_call(this, cq, method, host, deadline);
result.SetCompletionRegistry(registry);
return result;
}
protected override bool ReleaseHandle()
{
grpcsharp_channel_destroy(handle);

@ -72,7 +72,7 @@ namespace Grpc.Core.Internal
var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Status status;
var context = HandlerUtils.NewContext(newRpc);
var context = HandlerUtils.NewContext(newRpc, asyncCall.CancellationToken);
try
{
Preconditions.CheckArgument(await requestStream.MoveNext());
@ -126,7 +126,7 @@ namespace Grpc.Core.Internal
var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Status status;
var context = HandlerUtils.NewContext(newRpc);
var context = HandlerUtils.NewContext(newRpc, asyncCall.CancellationToken);
try
{
Preconditions.CheckArgument(await requestStream.MoveNext());
@ -180,7 +180,7 @@ namespace Grpc.Core.Internal
var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Status status;
var context = HandlerUtils.NewContext(newRpc);
var context = HandlerUtils.NewContext(newRpc, asyncCall.CancellationToken);
try
{
var result = await handler(requestStream, context);
@ -238,7 +238,7 @@ namespace Grpc.Core.Internal
var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Status status;
var context = HandlerUtils.NewContext(newRpc);
var context = HandlerUtils.NewContext(newRpc, asyncCall.CancellationToken);
try
{
await handler(requestStream, responseStream, context);
@ -295,11 +295,13 @@ namespace Grpc.Core.Internal
return new Status(StatusCode.Unknown, "Exception was thrown by handler.");
}
public static ServerCallContext NewContext(ServerRpcNew newRpc)
public static ServerCallContext NewContext(ServerRpcNew newRpc, CancellationToken cancellationToken)
{
DateTime realtimeDeadline = newRpc.Deadline.ToClockType(GPRClockType.Realtime).ToDateTime();
return new ServerCallContext(
newRpc.Method, newRpc.Host, newRpc.Deadline.ToDateTime(),
newRpc.RequestMetadata, CancellationToken.None);
newRpc.Method, newRpc.Host, realtimeDeadline,
newRpc.RequestMetadata, cancellationToken);
}
}
}

@ -32,6 +32,8 @@ using System;
using System.Runtime.InteropServices;
using System.Threading;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
/// <summary>
@ -40,32 +42,43 @@ namespace Grpc.Core.Internal
[StructLayout(LayoutKind.Sequential)]
internal struct Timespec
{
const int NanosPerSecond = 1000 * 1000 * 1000;
const int NanosPerTick = 100;
const long NanosPerSecond = 1000 * 1000 * 1000;
const long NanosPerTick = 100;
const long TicksPerSecond = NanosPerSecond / NanosPerTick;
static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
[DllImport("grpc_csharp_ext.dll")]
static extern Timespec gprsharp_now();
static extern Timespec gprsharp_now(GPRClockType clockType);
[DllImport("grpc_csharp_ext.dll")]
static extern Timespec gprsharp_inf_future(GPRClockType clockType);
[DllImport("grpc_csharp_ext.dll")]
static extern Timespec gprsharp_inf_past(GPRClockType clockType);
[DllImport("grpc_csharp_ext.dll")]
static extern Timespec gprsharp_inf_future();
static extern Timespec gprsharp_convert_clock_type(Timespec t, GPRClockType targetClock);
[DllImport("grpc_csharp_ext.dll")]
static extern int gprsharp_sizeof_timespec();
public Timespec(IntPtr tv_sec, int tv_nsec)
public Timespec(IntPtr tv_sec, int tv_nsec) : this(tv_sec, tv_nsec, GPRClockType.Realtime)
{
}
public Timespec(IntPtr tv_sec, int tv_nsec, GPRClockType clock_type)
{
this.tv_sec = tv_sec;
this.tv_nsec = tv_nsec;
this.clock_type = GPRClockType.Realtime;
this.clock_type = clock_type;
}
// NOTE: on linux 64bit sizeof(gpr_timespec) = 16, on windows 32bit sizeof(gpr_timespec) = 8
// so IntPtr seems to have the right size to work on both.
public System.IntPtr tv_sec;
public int tv_nsec;
public GPRClockType clock_type;
private System.IntPtr tv_sec;
private int tv_nsec;
private GPRClockType clock_type;
/// <summary>
/// Timespec a long time in the future.
@ -74,54 +87,164 @@ namespace Grpc.Core.Internal
{
get
{
return gprsharp_inf_future();
return gprsharp_inf_future(GPRClockType.Realtime);
}
}
/// <summary>
/// Timespec a long time in the past.
/// </summary>
public static Timespec InfPast
{
get
{
return gprsharp_inf_past(GPRClockType.Realtime);
}
}
/// <summary>
/// Return Timespec representing the current time.
/// </summary>
public static Timespec Now
{
get
{
return gprsharp_now();
return gprsharp_now(GPRClockType.Realtime);
}
}
public DateTime ToDateTime()
/// <summary>
/// Seconds since unix epoch.
/// </summary>
public IntPtr TimevalSeconds
{
return UnixEpoch.AddTicks(tv_sec.ToInt64() * (NanosPerSecond / NanosPerTick) + tv_nsec / NanosPerTick);
get
{
return tv_sec;
}
}
internal static int NativeSize
/// <summary>
/// The nanoseconds part of timeval.
/// </summary>
public int TimevalNanos
{
get
{
return gprsharp_sizeof_timespec();
return tv_nsec;
}
}
/// <summary>
/// Creates a GPR deadline from current instant and given timeout.
/// Converts the timespec to desired clock type.
/// </summary>
/// <returns>The from timeout.</returns>
public static Timespec DeadlineFromTimeout(TimeSpan timeout)
public Timespec ToClockType(GPRClockType targetClock)
{
return gprsharp_convert_clock_type(this, targetClock);
}
/// <summary>
/// Converts Timespec to DateTime.
/// Timespec needs to be of type GPRClockType.Realtime and needs to represent a legal value.
/// DateTime has lower resolution (100ns), so rounding can occurs.
/// Value are always rounded up to the nearest DateTime value in the future.
///
/// For Timespec.InfFuture or if timespec is after the largest representable DateTime, DateTime.MaxValue is returned.
/// For Timespec.InfPast or if timespec is before the lowest representable DateTime, DateTime.MinValue is returned.
///
/// Unless DateTime.MaxValue or DateTime.MinValue is returned, the resulting DateTime is always in UTC
/// (DateTimeKind.Utc)
/// </summary>
public DateTime ToDateTime()
{
if (timeout == Timeout.InfiniteTimeSpan)
Preconditions.CheckState(tv_nsec >= 0 && tv_nsec < NanosPerSecond);
Preconditions.CheckState(clock_type == GPRClockType.Realtime);
// fast path for InfFuture
if (this.Equals(InfFuture))
{
return DateTime.MaxValue;
}
// fast path for InfPast
if (this.Equals(InfPast))
{
return DateTime.MinValue;
}
try
{
// convert nanos to ticks, round up to the nearest tick
long ticksFromNanos = tv_nsec / NanosPerTick + ((tv_nsec % NanosPerTick != 0) ? 1 : 0);
long ticksTotal = checked(tv_sec.ToInt64() * TicksPerSecond + ticksFromNanos);
return UnixEpoch.AddTicks(ticksTotal);
}
catch (OverflowException)
{
// ticks out of long range
return tv_sec.ToInt64() > 0 ? DateTime.MaxValue : DateTime.MinValue;
}
catch (ArgumentOutOfRangeException)
{
// resulting date time would be larger than MaxValue
return tv_sec.ToInt64() > 0 ? DateTime.MaxValue : DateTime.MinValue;
}
}
/// <summary>
/// Creates DateTime to Timespec.
/// DateTime has to be in UTC (DateTimeKind.Utc) unless it's DateTime.MaxValue or DateTime.MinValue.
/// For DateTime.MaxValue of date time after the largest representable Timespec, Timespec.InfFuture is returned.
/// For DateTime.MinValue of date time before the lowest representable Timespec, Timespec.InfPast is returned.
/// </summary>
/// <returns>The date time.</returns>
/// <param name="dateTime">Date time.</param>
public static Timespec FromDateTime(DateTime dateTime)
{
if (dateTime == DateTime.MaxValue)
{
return Timespec.InfFuture;
}
return Timespec.Now.Add(timeout);
if (dateTime == DateTime.MinValue)
{
return Timespec.InfPast;
}
Preconditions.CheckArgument(dateTime.Kind == DateTimeKind.Utc, "dateTime");
try
{
TimeSpan timeSpan = dateTime - UnixEpoch;
long ticks = timeSpan.Ticks;
long seconds = ticks / TicksPerSecond;
int nanos = (int)((ticks % TicksPerSecond) * NanosPerTick);
if (nanos < 0)
{
// correct the result based on C# modulo semantics for negative dividend
seconds--;
nanos += (int)NanosPerSecond;
}
// new IntPtr possibly throws OverflowException
return new Timespec(new IntPtr(seconds), nanos);
}
catch (OverflowException)
{
return dateTime > UnixEpoch ? Timespec.InfFuture : Timespec.InfPast;
}
catch (ArgumentOutOfRangeException)
{
return dateTime > UnixEpoch ? Timespec.InfFuture : Timespec.InfPast;
}
}
public Timespec Add(TimeSpan timeSpan)
internal static int NativeSize
{
long nanos = (long)tv_nsec + (timeSpan.Ticks % TimeSpan.TicksPerSecond) * NanosPerTick;
long overflow_sec = (nanos > NanosPerSecond) ? 1 : 0;
Timespec result;
result.tv_nsec = (int)(nanos % NanosPerSecond);
result.tv_sec = new IntPtr(tv_sec.ToInt64() + (timeSpan.Ticks / TimeSpan.TicksPerSecond) + overflow_sec);
result.clock_type = GPRClockType.Realtime;
return result;
get
{
return gprsharp_sizeof_timespec();
}
}
}
}

@ -132,6 +132,60 @@ namespace math.Tests
}).Wait();
}
[Test]
public void FibWithCancel()
{
Task.Run(async () =>
{
var cts = new CancellationTokenSource();
using (var call = client.Fib(new FibArgs.Builder { Limit = 0 }.Build(),
cancellationToken: cts.Token))
{
List<long> responses = new List<long>();
try
{
while (await call.ResponseStream.MoveNext())
{
if (responses.Count == 0)
{
cts.CancelAfter(500); // make sure we cancel soon
}
responses.Add(call.ResponseStream.Current.Num_);
}
Assert.Fail();
}
catch (RpcException e)
{
Assert.IsTrue(responses.Count > 0);
Assert.AreEqual(StatusCode.Cancelled, e.Status.StatusCode);
}
}
}).Wait();
}
[Test]
public void FibWithDeadline()
{
Task.Run(async () =>
{
using (var call = client.Fib(new FibArgs.Builder { Limit = 0 }.Build(),
deadline: DateTime.UtcNow.AddMilliseconds(500)))
{
try
{
await call.ResponseStream.ToList();
Assert.Fail();
}
catch (RpcException e)
{
Assert.AreEqual(StatusCode.DeadlineExceeded, e.Status.StatusCode);
}
}
}).Wait();
}
// TODO: test Fib with limit=0 and cancellation
[Test]
public void Sum()

@ -44,11 +44,11 @@ namespace math {
// client interface
public interface IMathClient
{
global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
}
// server-side interface
@ -66,29 +66,29 @@ namespace math {
public MathClient(Channel channel) : base(channel)
{
}
public global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Div, headers);
var call = CreateCall(__ServiceName, __Method_Div, headers, deadline);
return Calls.BlockingUnaryCall(call, request, cancellationToken);
}
public AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Div, headers);
var call = CreateCall(__ServiceName, __Method_Div, headers, deadline);
return Calls.AsyncUnaryCall(call, request, cancellationToken);
}
public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_DivMany, headers);
var call = CreateCall(__ServiceName, __Method_DivMany, headers, deadline);
return Calls.AsyncDuplexStreamingCall(call, cancellationToken);
}
public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Fib, headers);
var call = CreateCall(__ServiceName, __Method_Fib, headers, deadline);
return Calls.AsyncServerStreamingCall(call, request, cancellationToken);
}
public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Sum, headers);
var call = CreateCall(__ServiceName, __Method_Sum, headers, deadline);
return Calls.AsyncClientStreamingCall(call, cancellationToken);
}
}

@ -54,8 +54,13 @@ namespace math
{
if (request.Limit <= 0)
{
// TODO(jtattermusch): support cancellation
throw new NotImplementedException("Not implemented yet");
// keep streaming the sequence until cancelled.
IEnumerator<Num> fibEnumerator = FibInternal(long.MaxValue).GetEnumerator();
while (!context.CancellationToken.IsCancellationRequested && fibEnumerator.MoveNext())
{
await responseStream.WriteAsync(fibEnumerator.Current);
await Task.Delay(100);
}
}
if (request.Limit > 0)

@ -24,8 +24,8 @@ namespace Grpc.Health.V1Alpha {
// client interface
public interface IHealthClient
{
global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
}
// server-side interface
@ -40,14 +40,14 @@ namespace Grpc.Health.V1Alpha {
public HealthClient(Channel channel) : base(channel)
{
}
public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public global::Grpc.Health.V1Alpha.HealthCheckResponse Check(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Check, headers);
var call = CreateCall(__ServiceName, __Method_Check, headers, deadline);
return Calls.BlockingUnaryCall(call, request, cancellationToken);
}
public AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncUnaryCall<global::Grpc.Health.V1Alpha.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1Alpha.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_Check, headers);
var call = CreateCall(__ServiceName, __Method_Check, headers, deadline);
return Calls.AsyncUnaryCall(call, request, cancellationToken);
}
}

@ -59,14 +59,14 @@ namespace grpc.testing {
// client interface
public interface ITestServiceClient
{
global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken));
global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
}
// server-side interface
@ -86,44 +86,44 @@ namespace grpc.testing {
public TestServiceClient(Channel channel) : base(channel)
{
}
public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_EmptyCall, headers);
var call = CreateCall(__ServiceName, __Method_EmptyCall, headers, deadline);
return Calls.BlockingUnaryCall(call, request, cancellationToken);
}
public AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_EmptyCall, headers);
var call = CreateCall(__ServiceName, __Method_EmptyCall, headers, deadline);
return Calls.AsyncUnaryCall(call, request, cancellationToken);
}
public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_UnaryCall, headers);
var call = CreateCall(__ServiceName, __Method_UnaryCall, headers, deadline);
return Calls.BlockingUnaryCall(call, request, cancellationToken);
}
public AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_UnaryCall, headers);
var call = CreateCall(__ServiceName, __Method_UnaryCall, headers, deadline);
return Calls.AsyncUnaryCall(call, request, cancellationToken);
}
public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_StreamingOutputCall, headers);
var call = CreateCall(__ServiceName, __Method_StreamingOutputCall, headers, deadline);
return Calls.AsyncServerStreamingCall(call, request, cancellationToken);
}
public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_StreamingInputCall, headers);
var call = CreateCall(__ServiceName, __Method_StreamingInputCall, headers, deadline);
return Calls.AsyncClientStreamingCall(call, cancellationToken);
}
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_FullDuplexCall, headers);
var call = CreateCall(__ServiceName, __Method_FullDuplexCall, headers, deadline);
return Calls.AsyncDuplexStreamingCall(call, cancellationToken);
}
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, CancellationToken cancellationToken = default(CancellationToken))
public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_HalfDuplexCall, headers);
var call = CreateCall(__ServiceName, __Method_HalfDuplexCall, headers, deadline);
return Calls.AsyncDuplexStreamingCall(call, cancellationToken);
}
}

@ -433,10 +433,20 @@ grpcsharp_channel_args_destroy(grpc_channel_args *args) {
/* Timespec */
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(void) { return gpr_now(GPR_CLOCK_REALTIME); }
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(gpr_clock_type clock_type) {
return gpr_now(clock_type);
}
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_future(gpr_clock_type clock_type) {
return gpr_inf_future(clock_type);
}
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_past(gpr_clock_type clock_type) {
return gpr_inf_past(clock_type);
}
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_future(void) {
return gpr_inf_future(GPR_CLOCK_REALTIME);
GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock) {
return gpr_convert_clock_type(t, target_clock);
}
GPR_EXPORT gpr_int32 GPR_CALLTYPE gprsharp_sizeof_timespec(void) {

@ -52,6 +52,7 @@ gpr_timespec MillisecondsToTimespec(double millis) {
}
double TimespecToMilliseconds(gpr_timespec timespec) {
timespec = gpr_convert_clock_type(timespec, GPR_CLOCK_REALTIME);
if (gpr_time_cmp(timespec, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) {
return std::numeric_limits<double>::infinity();
} else if (gpr_time_cmp(timespec, gpr_inf_past(GPR_CLOCK_REALTIME)) == 0) {

@ -1,7 +1,7 @@
{
"name": "grpc/grpc",
"description": "gRPC library for PHP",
"version": "0.5.0",
"version": "0.5.1",
"homepage": "http://grpc.io",
"license": "BSD-3-Clause",
"repositories": [

@ -60,7 +60,10 @@ class BaseStub {
}
unset($opts['update_metadata']);
}
$package_config = json_decode(
file_get_contents(dirname(__FILE__) . '/../../composer.json'), true);
$opts['grpc.primary_user_agent'] =
'grpc-php/' . $package_config['version'];
$this->channel = new Channel($hostname, $opts);
}

@ -208,6 +208,7 @@ ClientCredentials *pygrpc_ClientCredentials_service_account(
return self;
}
/* TODO: Rename this credentials to something like service_account_jwt_access */
ClientCredentials *pygrpc_ClientCredentials_jwt(
PyTypeObject *type, PyObject *args, PyObject *kwargs) {
ClientCredentials *self;
@ -219,7 +220,7 @@ ClientCredentials *pygrpc_ClientCredentials_jwt(
return NULL;
}
self = (ClientCredentials *)type->tp_alloc(type, 0);
self->c_creds = grpc_jwt_credentials_create(
self->c_creds = grpc_service_account_jwt_access_credentials_create(
json_key, pygrpc_cast_double_to_gpr_timespec(lifetime));
if (!self->c_creds) {
Py_DECREF(self);

@ -374,6 +374,7 @@ PyObject *pygrpc_consume_ops(grpc_op *op, size_t nops) {
}
double pygrpc_cast_gpr_timespec_to_double(gpr_timespec timespec) {
timespec = gpr_convert_clock_type(timespec, GPR_CLOCK_REALTIME);
return timespec.tv_sec + 1e-9*timespec.tv_nsec;
}

@ -126,6 +126,7 @@ def client_credentials_service_account(
credentials.references.extend([json_key, scope])
return credentials
#TODO rename to something like client_credentials_service_account_jwt_access.
def client_credentials_jwt(json_key, records.Timespec token_lifetime not None):
if isinstance(json_key, bytes):
pass
@ -134,7 +135,7 @@ def client_credentials_jwt(json_key, records.Timespec token_lifetime not None):
else:
raise TypeError("expected json_key to be str or bytes")
cdef ClientCredentials credentials = ClientCredentials()
credentials.c_credentials = grpc.grpc_jwt_credentials_create(
credentials.c_credentials = grpc.grpc_service_account_jwt_access_credentials_create(
json_key, token_lifetime.c_time)
credentials.references.append(json_key)
return credentials

@ -313,7 +313,7 @@ cdef extern from "grpc/grpc_security.h":
grpc_credentials *grpc_compute_engine_credentials_create()
grpc_credentials *grpc_service_account_credentials_create(
const char *json_key, const char *scope, gpr_timespec token_lifetime)
grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
grpc_credentials *grpc_service_account_jwt_access_credentials_create(const char *json_key,
gpr_timespec token_lifetime)
grpc_credentials *grpc_refresh_token_credentials_create(
const char *json_refresh_token)

@ -209,10 +209,12 @@ static ID id_to_s;
/* Converts a wrapped time constant to a standard time. */
static VALUE grpc_rb_time_val_to_time(VALUE self) {
gpr_timespec *time_const = NULL;
gpr_timespec real_time;
TypedData_Get_Struct(self, gpr_timespec, &grpc_rb_timespec_data_type,
time_const);
return rb_funcall(rb_cTime, id_at, 2, INT2NUM(time_const->tv_sec),
INT2NUM(time_const->tv_nsec));
real_time = gpr_convert_clock_type(*time_const, GPR_CLOCK_REALTIME);
return rb_funcall(rb_cTime, id_at, 2, INT2NUM(real_time.tv_sec),
INT2NUM(real_time.tv_nsec));
}
/* Invokes inspect on the ctime version of the time val. */

@ -213,6 +213,7 @@ static VALUE grpc_rb_server_request_call(VALUE self, VALUE cqueue,
grpc_call_error err;
request_call_stack st;
VALUE result;
gpr_timespec deadline;
TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
if (s->wrapped == NULL) {
rb_raise(rb_eRuntimeError, "destroyed!");
@ -245,15 +246,13 @@ static VALUE grpc_rb_server_request_call(VALUE self, VALUE cqueue,
}
/* build the NewServerRpc struct result */
deadline = gpr_convert_clock_type(st.details.deadline, GPR_CLOCK_REALTIME);
result = rb_struct_new(
grpc_rb_sNewServerRpc,
rb_str_new2(st.details.method),
grpc_rb_sNewServerRpc, rb_str_new2(st.details.method),
rb_str_new2(st.details.host),
rb_funcall(rb_cTime, id_at, 2, INT2NUM(st.details.deadline.tv_sec),
INT2NUM(st.details.deadline.tv_nsec)),
grpc_rb_md_ary_to_h(&st.md_ary),
grpc_rb_wrap_call(call),
NULL);
rb_funcall(rb_cTime, id_at, 2, INT2NUM(deadline.tv_sec),
INT2NUM(deadline.tv_nsec)),
grpc_rb_md_ary_to_h(&st.md_ary), grpc_rb_wrap_call(call), NULL);
grpc_request_call_stack_cleanup(&st);
return result;
}

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

Loading…
Cancel
Save