Merge github.com:grpc/grpc into better-profile

pull/4032/head
Craig Tiller 9 years ago
commit d653b39471
  1. 441
      Makefile
  2. 7
      binding.gyp
  3. 52
      build.yaml
  4. 20
      doc/PROTOCOL-HTTP2.md
  5. 8
      doc/grpc-auth-support.md
  6. 2
      doc/interop-test-descriptions.md
  7. 2
      examples/cpp/cpptutorial.md
  8. 2
      examples/cpp/helloworld/README.md
  9. 6
      examples/cpp/helloworld/greeter_async_client.cc
  10. 6
      examples/cpp/helloworld/greeter_client.cc
  11. 3
      examples/cpp/route_guide/route_guide_client.cc
  12. 2
      examples/node/README.md
  13. 2
      examples/python/helloworld/greeter_server.py
  14. 4
      include/grpc++/channel.h
  15. 17
      include/grpc++/client_context.h
  16. 6
      include/grpc++/create_channel.h
  17. 87
      include/grpc++/security/credentials.h
  18. 5
      include/grpc++/support/channel_arguments.h
  19. 1
      include/grpc++/support/time.h
  20. 6
      include/grpc/grpc.h
  21. 59
      include/grpc/grpc_security.h
  22. 141
      reports/interop_html_report.template
  23. 15
      src/core/client_config/subchannel.c
  24. 6
      src/core/client_config/subchannel.h
  25. 3
      src/core/iomgr/pollset_windows.c
  26. 20
      src/core/iomgr/tcp_server.h
  27. 150
      src/core/iomgr/tcp_server_posix.c
  28. 121
      src/core/iomgr/tcp_server_windows.c
  29. 30
      src/core/security/client_auth_filter.c
  30. 599
      src/core/security/credentials.c
  31. 171
      src/core/security/credentials.h
  32. 54
      src/core/security/google_default_credentials.c
  33. 33
      src/core/security/security_connector.c
  34. 11
      src/core/security/security_connector.h
  35. 14
      src/core/security/security_context.c
  36. 2
      src/core/security/security_context.h
  37. 4
      src/core/security/server_secure_chttp2.c
  38. 2
      src/core/support/slice_buffer.c
  39. 4
      src/core/support/time_win32.c
  40. 1
      src/core/surface/byte_buffer_reader.c
  41. 3
      src/core/surface/call.c
  42. 8
      src/core/surface/secure_channel_create.c
  43. 4
      src/core/surface/server_chttp2.c
  44. 2
      src/core/surface/version.c
  45. 112
      src/core/transport/chttp2/hpack_encoder.c
  46. 24
      src/core/transport/chttp2/hpack_encoder.h
  47. 98
      src/core/transport/chttp2/hpack_parser.c
  48. 115
      src/core/transport/chttp2/hpack_table.c
  49. 32
      src/core/transport/chttp2/hpack_table.h
  50. 6
      src/core/transport/chttp2/internal.h
  51. 7
      src/core/transport/chttp2/parsing.c
  52. 9
      src/core/transport/chttp2/writing.c
  53. 38
      src/core/transport/chttp2_transport.c
  54. 28
      src/core/tsi/test_creds/server1.pem
  55. 8
      src/cpp/client/client_context.cc
  56. 6
      src/cpp/client/create_channel.cc
  57. 4
      src/cpp/client/credentials.cc
  58. 14
      src/cpp/client/insecure_credentials.cc
  59. 82
      src/cpp/client/secure_credentials.cc
  60. 32
      src/cpp/client/secure_credentials.h
  61. 4
      src/csharp/Grpc.Core.Tests/FakeCredentials.cs
  62. 10
      src/csharp/Grpc.Core/CallCredentials.cs
  63. 4
      src/csharp/Grpc.Core/Channel.cs
  64. 16
      src/csharp/Grpc.Core/ChannelCredentials.cs
  65. 5
      src/csharp/Grpc.Core/Grpc.Core.csproj
  66. 64
      src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs
  67. 4
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  68. 24
      src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs
  69. 6
      src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
  70. 6
      src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
  71. 2
      src/csharp/Grpc.Core/Profiling/IProfiler.cs
  72. 3
      src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs
  73. 13
      src/csharp/Grpc.Core/Profiling/Profilers.cs
  74. 3
      src/csharp/Grpc.IntegrationTesting.QpsWorker/.gitignore
  75. 60
      src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
  76. 46
      src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs
  77. 11
      src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs
  78. 76
      src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
  79. 153
      src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
  80. 2362
      src/csharp/Grpc.IntegrationTesting/Control.cs
  81. 67
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  82. 153
      src/csharp/Grpc.IntegrationTesting/Histogram.cs
  83. 104
      src/csharp/Grpc.IntegrationTesting/HistogramTest.cs
  84. 67
      src/csharp/Grpc.IntegrationTesting/IClientRunner.cs
  85. 72
      src/csharp/Grpc.IntegrationTesting/IServerRunner.cs
  86. 580
      src/csharp/Grpc.IntegrationTesting/Payloads.cs
  87. 108
      src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
  88. 117
      src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs
  89. 124
      src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
  90. 44
      src/csharp/Grpc.IntegrationTesting/Services.cs
  91. 198
      src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
  92. 5
      src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
  93. 744
      src/csharp/Grpc.IntegrationTesting/Stats.cs
  94. 78
      src/csharp/Grpc.IntegrationTesting/WallClockStopwatch.cs
  95. 96
      src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
  96. 28
      src/csharp/Grpc.IntegrationTesting/data/server1.pem
  97. 96
      src/csharp/Grpc.sln
  98. 38
      src/csharp/ext/grpc_csharp_ext.c
  99. 6
      src/csharp/generate_proto_csharp.sh
  100. 2
      src/node/ext/call.cc
  101. Some files were not shown because too many files have changed in this diff Show More

File diff suppressed because one or more lines are too long

@ -347,11 +347,12 @@
"src/node/ext/node_grpc.cc",
"src/node/ext/server.cc",
"src/node/ext/server_credentials.cc",
"src/node/ext/timeval.cc"
"src/node/ext/timeval.cc",
],
"dependencies": [
"grpc"
"grpc",
"gpr",
]
}
},
]
}

@ -5,7 +5,7 @@ settings:
'#': The public version number of the library.
version:
major: 0
minor: 11
minor: 12
micro: 0
build: 0
filegroups:
@ -1887,6 +1887,20 @@ targets:
- mac
- linux
- posix
- name: metrics_client
build: test
run: false
language: c++
headers:
- test/cpp/util/metrics_server.h
src:
- test/proto/metrics.proto
- test/cpp/interop/metrics_client.cc
deps:
- grpc++
- grpc
- gpr
- grpc++_test_config
- name: mock_test
build: test
language: c++
@ -2127,13 +2141,16 @@ targets:
- test/cpp/interop/client_helper.h
- test/cpp/interop/interop_client.h
- test/cpp/interop/stress_interop_client.h
- test/cpp/util/metrics_server.h
src:
- test/proto/empty.proto
- test/proto/messages.proto
- test/proto/metrics.proto
- test/proto/test.proto
- test/cpp/interop/interop_client.cc
- test/cpp/interop/stress_interop_client.cc
- test/cpp/interop/stress_test.cc
- test/cpp/util/metrics_server.cc
deps:
- grpc++_test_util
- grpc_test_util
@ -2224,3 +2241,36 @@ vspackages:
props: false
redist: false
version: 1.7.0.1
node_modules:
- deps:
- grpc
- gpr
headers:
- src/node/ext/byte_buffer.h
- src/node/ext/call.h
- src/node/ext/call_credentials.h
- src/node/ext/channel.h
- src/node/ext/channel_credentials.h
- src/node/ext/completion_queue_async_worker.h
- src/node/ext/server.h
- src/node/ext/server_credentials.h
- src/node/ext/timeval.h
js:
- src/node/index.js
- src/node/src/client.js
- src/node/src/common.js
- src/node/src/credentials.js
- src/node/src/metadata.js
- src/node/src/server.js
name: grpc_node
src:
- src/node/ext/byte_buffer.cc
- src/node/ext/call.cc
- src/node/ext/call_credentials.cc
- src/node/ext/channel.cc
- src/node/ext/channel_credentials.cc
- src/node/ext/completion_queue_async_worker.cc
- src/node/ext/node_grpc.cc
- src/node/ext/server.cc
- src/node/ext/server_credentials.cc
- src/node/ext/timeval.cc

@ -44,8 +44,9 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
* **Message-Type** → "grpc-message-type" {_type name for message schema_}
* **Custom-Metadata** → Binary-Header / ASCII-Header
* **Binary-Header** → {Header-Name "-bin" } {_base64 encoded value_}
* **ASCII-Header** → Header-Name {_value_}
* **ASCII-Header** → Header-Name ASCII-Value
* **Header-Name** → 1\*( %x30-39 / %x61-7A / "\_" / "-") ; 0-9 a-z \_ -
* **ASCII-Value** → 1\*( %x20-%x7E ) ; space and printable ASCII
HTTP2 requires that reserved headers, ones starting with ":" appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**.
@ -56,6 +57,23 @@ If **Timeout** is omitted a server should assume an infinite timeout. Client imp
Note that HTTP2 does not allow arbitrary octet sequences for header values so binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values. Applications define binary headers by having their names end with "-bin". Runtime libraries use this suffix to detect binary headers and properly apply base64 encoding & decoding as headers are sent and received.
**Custom-Metadata** header order is not guaranteed to be preserved except for
values with duplicate header names. Duplicate header names may have their values
joined with "," as the delimiter and be considered semantically equivalent.
Implementations must split **Binary-Header**s on "," before decoding the
Base64-encoded values.
**ASCII-Value** should not have leading or trailing whitespace. If it contains
leading or trailing whitespace, it may be stripped. The **ASCII-Value**
character range defined is more strict than HTTP. Implementations must not error
due to receiving an invalid **ASCII-Value** that's a valid **field-value** in
HTTP, but the precise behavior is not strictly defined: they may throw the value
away or accept the value. If accepted, care must be taken to make sure that the
application is permitted to echo the value back as metadata. For example, if the
metadata is provided to the application as a list in a request, the application
should not trigger an error by providing that same list as the metadata in the
response.
Servers may limit the size of **Request-Headers**, with a default of 8 KiB
suggested. Implementations are encouraged to compute total header size like
HTTP/2's `SETTINGS_MAX_HEADER_LIST_SIZE`: the sum of all header fields, for each

@ -36,9 +36,9 @@ authenticate the server and encrypt all data.
```cpp
SslCredentialsOptions ssl_opts; // Options to override SSL params, empty by default
// Create the credentials object by providing service account key in constructor
std::unique_ptr<Credentials> creds = CredentialsFactory::SslCredentials(ssl_opts);
std::shared_ptr<ChannelCredentials> creds = SslCredentials(ssl_opts);
// Create a channel using the credentials created in the previous step
std::shared_ptr<ChannelInterface> channel = CreateChannel(server_name, creds, channel_args);
std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
// Create a stub on the channel
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
// Make actual RPC calls on the stub.
@ -55,9 +55,9 @@ passed to the factory method.
gRPC applications can use a simple API to create a credential that works in various deployment scenarios.
```cpp
std::unique_ptr<Credentials> creds = CredentialsFactory::GoogleDefaultCredentials();
std::shared_ptr<ChannelCredentials> creds = GoogleDefaultCredentials();
// Create a channel, stub and make RPC calls (same as in the previous example)
std::shared_ptr<ChannelInterface> channel = CreateChannel(server_name, creds, channel_args);
std::shared_ptr<Channel> channel = CreateChannel(server_name, creds);
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
grpc::Status s = stub->sayHello(&context, *request, response);
```

@ -4,7 +4,7 @@ Interoperability Test Case Descriptions
Client and server use
[test.proto](https://github.com/grpc/grpc/blob/master/test/proto/test.proto)
and the [gRPC over HTTP/2 v2
protocol](doc/PROTOCOL-HTTP2.md).
protocol](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md).
Client
------

@ -245,7 +245,7 @@ To call service methods, we first need to create a *stub*.
First we need to create a gRPC *channel* for our stub, specifying the server address and port we want to connect to without SSL:
```cpp
grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials());
grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials());
```
Now we can use the channel to create our stub using the `NewStub` method provided in the `RouteGuide` class we generated from our .proto.

@ -94,7 +94,7 @@ $ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
arguments as follows
```
auto channel = CreateChannel("localhost:50051", InsecureCredentials());
auto channel = CreateChannel("localhost:50051", InsecureChannelCredentials());
```
- Create a stub. A stub implements the rpc methods of a service and in the

@ -114,9 +114,9 @@ int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// are created. This channel models a connection to an endpoint (in this case,
// localhost at port 50051). We indicate that the channel isn't authenticated
// (use of InsecureCredentials()).
GreeterClient greeter(
grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()));
// (use of InsecureChannelCredentials()).
GreeterClient greeter(grpc::CreateChannel(
"localhost:50051", grpc::InsecureChannelCredentials()));
std::string user("world");
std::string reply = greeter.SayHello(user); // The actual RPC call!
std::cout << "Greeter received: " << reply << std::endl;

@ -84,9 +84,9 @@ int main(int argc, char** argv) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// are created. This channel models a connection to an endpoint (in this case,
// localhost at port 50051). We indicate that the channel isn't authenticated
// (use of InsecureCredentials()).
GreeterClient greeter(
grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()));
// (use of InsecureChannelCredentials()).
GreeterClient greeter(grpc::CreateChannel(
"localhost:50051", grpc::InsecureChannelCredentials()));
std::string user("world");
std::string reply = greeter.SayHello(user);
std::cout << "Greeter received: " << reply << std::endl;

@ -234,7 +234,8 @@ int main(int argc, char** argv) {
// Expect only arg: --db_path=path/to/route_guide_db.json.
std::string db = routeguide::GetDbFileContent(argc, argv);
RouteGuideClient guide(
grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()),
grpc::CreateChannel("localhost:50051",
grpc::InsecureChannelCredentials()),
db);
std::cout << "-------------- GetFeature --------------" << std::endl;

@ -4,7 +4,7 @@ gRPC in 3 minutes (Node.js)
PREREQUISITES
-------------
- `node`: This requires Node 10.x or greater.
- `node`: This requires Node 0.10.x or greater.
- [homebrew][] on Mac OS X. This simplifies the installation of the gRPC C core.
INSTALL

@ -50,7 +50,7 @@ def serve():
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop()
server.stop(0)
if __name__ == '__main__':
serve()

@ -47,8 +47,8 @@ namespace grpc {
class CallOpSetInterface;
class ChannelArguments;
class CompletionQueue;
class Credentials;
class SecureCredentials;
class ChannelCredentials;
class SecureChannelCredentials;
template <class R>
class ClientReader;

@ -53,15 +53,16 @@
#include <memory>
#include <string>
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc++/impl/sync.h>
#include <grpc++/security/auth_context.h>
#include <grpc++/support/config.h>
#include <grpc++/support/status.h>
#include <grpc++/support/string_ref.h>
#include <grpc++/support/time.h>
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
struct census_context;
@ -69,7 +70,7 @@ namespace grpc {
class Channel;
class CompletionQueue;
class Credentials;
class CallCredentials;
class RpcMethod;
template <class R>
class ClientReader;
@ -244,7 +245,7 @@ class ClientContext {
/// call.
///
/// \see https://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md
void set_credentials(const std::shared_ptr<Credentials>& creds) {
void set_credentials(const std::shared_ptr<CallCredentials>& creds) {
creds_ = creds;
}
@ -315,10 +316,12 @@ class ClientContext {
bool initial_metadata_received_;
std::shared_ptr<Channel> channel_;
grpc::mutex mu_;
grpc_call* call_;
bool call_canceled_;
gpr_timespec deadline_;
grpc::string authority_;
std::shared_ptr<Credentials> creds_;
std::shared_ptr<CallCredentials> creds_;
mutable std::shared_ptr<const AuthContext> auth_context_;
struct census_context* census_context_;
std::multimap<grpc::string, grpc::string> send_initial_metadata_;

@ -49,7 +49,8 @@ namespace grpc {
/// an object or is invalid, a lame channel is returned.
/// \param args Options for channel creation.
std::shared_ptr<Channel> CreateChannel(
const grpc::string& target, const std::shared_ptr<Credentials>& creds);
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds);
/// Create a new \em custom \a Channel pointing to \a target
///
@ -61,7 +62,8 @@ std::shared_ptr<Channel> CreateChannel(
/// an object or is invalid, a lame channel is returned.
/// \param args Options for channel creation.
std::shared_ptr<Channel> CreateCustomChannel(
const grpc::string& target, const std::shared_ptr<Credentials>& creds,
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds,
const ChannelArguments& args);
} // namespace grpc

@ -45,37 +45,60 @@
namespace grpc {
class ChannelArguments;
class Channel;
class SecureCredentials;
/// A credentials object encapsulates all the state needed by a client to
/// authenticate with a server and make various assertions, e.g., about the
/// client’s identity, role, or whether it is authorized to make a particular
/// call.
class SecureChannelCredentials;
class CallCredentials;
class SecureCallCredentials;
/// A channel credentials object encapsulates all the state needed by a client
/// to authenticate with a server for a given channel.
/// It can make various assertions, e.g., about the client’s identity, role
/// for all the calls on that channel.
///
/// \see https://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md
class Credentials : public GrpcLibrary {
class ChannelCredentials : public GrpcLibrary {
public:
~Credentials() GRPC_OVERRIDE;
/// Apply this instance's credentials to \a call.
virtual bool ApplyToCall(grpc_call* call) = 0;
~ChannelCredentials() GRPC_OVERRIDE;
protected:
friend std::shared_ptr<Credentials> CompositeCredentials(
const std::shared_ptr<Credentials>& creds1,
const std::shared_ptr<Credentials>& creds2);
friend std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
const std::shared_ptr<ChannelCredentials>& channel_creds,
const std::shared_ptr<CallCredentials>& call_creds);
virtual SecureCredentials* AsSecureCredentials() = 0;
virtual SecureChannelCredentials* AsSecureCredentials() = 0;
private:
friend std::shared_ptr<Channel> CreateCustomChannel(
const grpc::string& target, const std::shared_ptr<Credentials>& creds,
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds,
const ChannelArguments& args);
virtual std::shared_ptr<Channel> CreateChannel(
const grpc::string& target, const ChannelArguments& args) = 0;
};
/// A call credentials object encapsulates the state needed by a client to
/// authenticate with a server for a given call on a channel.
///
/// \see https://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md
class CallCredentials : public GrpcLibrary {
public:
~CallCredentials() GRPC_OVERRIDE;
/// Apply this instance's credentials to \a call.
virtual bool ApplyToCall(grpc_call* call) = 0;
protected:
friend std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
const std::shared_ptr<ChannelCredentials>& channel_creds,
const std::shared_ptr<CallCredentials>& call_creds);
friend std::shared_ptr<CallCredentials> CompositeCallCredentials(
const std::shared_ptr<CallCredentials>& creds1,
const std::shared_ptr<CallCredentials>& creds2);
virtual SecureCallCredentials* AsSecureCredentials() = 0;
};
/// Options used to build SslCredentials.
struct SslCredentialsOptions {
/// The buffer containing the PEM encoding of the server root certificates. If
@ -106,10 +129,10 @@ struct SslCredentialsOptions {
/// Using these credentials to connect to any other service may result in this
/// service being able to impersonate your client for requests to Google
/// services.
std::shared_ptr<Credentials> GoogleDefaultCredentials();
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials();
/// Builds SSL Credentials given SSL specific options
std::shared_ptr<Credentials> SslCredentials(
std::shared_ptr<ChannelCredentials> SslCredentials(
const SslCredentialsOptions& options);
/// Builds credentials for use when running in GCE
@ -118,14 +141,14 @@ std::shared_ptr<Credentials> SslCredentials(
/// Using these credentials to connect to any other service may result in this
/// service being able to impersonate your client for requests to Google
/// services.
std::shared_ptr<Credentials> GoogleComputeEngineCredentials();
std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials();
/// 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> ServiceAccountJWTAccessCredentials(
std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
const grpc::string& json_key, long token_lifetime_seconds);
/// Builds refresh token credentials.
@ -136,7 +159,7 @@ std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials(
/// Using these credentials to connect to any other service may result in this
/// service being able to impersonate your client for requests to Google
/// services.
std::shared_ptr<Credentials> GoogleRefreshTokenCredentials(
std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
const grpc::string& json_refresh_token);
/// Builds access token credentials.
@ -147,7 +170,7 @@ std::shared_ptr<Credentials> GoogleRefreshTokenCredentials(
/// Using these credentials to connect to any other service may result in this
/// service being able to impersonate your client for requests to Google
/// services.
std::shared_ptr<Credentials> AccessTokenCredentials(
std::shared_ptr<CallCredentials> AccessTokenCredentials(
const grpc::string& access_token);
/// Builds IAM credentials.
@ -156,17 +179,23 @@ std::shared_ptr<Credentials> AccessTokenCredentials(
/// Using these credentials to connect to any other service may result in this
/// service being able to impersonate your client for requests to Google
/// services.
std::shared_ptr<Credentials> GoogleIAMCredentials(
std::shared_ptr<CallCredentials> GoogleIAMCredentials(
const grpc::string& authorization_token,
const grpc::string& authority_selector);
/// Combines two credentials objects into a composite credentials
std::shared_ptr<Credentials> CompositeCredentials(
const std::shared_ptr<Credentials>& creds1,
const std::shared_ptr<Credentials>& creds2);
/// Combines a channel credentials and a call credentials into a composite
/// channel credentials.
std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
const std::shared_ptr<ChannelCredentials>& channel_creds,
const std::shared_ptr<CallCredentials>& call_creds);
/// Combines two call credentials objects into a composite call credentials.
std::shared_ptr<CallCredentials> CompositeCallCredentials(
const std::shared_ptr<CallCredentials>& creds1,
const std::shared_ptr<CallCredentials>& creds2);
/// Credentials for an unencrypted, unauthenticated channel
std::shared_ptr<Credentials> InsecureCredentials();
std::shared_ptr<ChannelCredentials> InsecureChannelCredentials();
// User defined metadata credentials.
class MetadataCredentialsPlugin {
@ -183,7 +212,7 @@ class MetadataCredentialsPlugin {
std::multimap<grpc::string, grpc::string>* metadata) = 0;
};
std::shared_ptr<Credentials> MetadataCredentialsFromPlugin(
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin> plugin);
} // namespace grpc

@ -70,7 +70,8 @@ class ChannelArguments {
void SetChannelArgs(grpc_channel_args* channel_args) const;
// gRPC specific channel argument setters
/// Set target name override for SSL host name checking.
/// Set target name override for SSL host name checking. This option is for
/// testing only and should never be used in production.
void SetSslTargetNameOverride(const grpc::string& name);
// TODO(yangg) add flow control options
/// Set the compression algorithm for the channel.
@ -83,7 +84,7 @@ class ChannelArguments {
void SetString(const grpc::string& key, const grpc::string& value);
private:
friend class SecureCredentials;
friend class SecureChannelCredentials;
friend class testing::ChannelArgumentsTest;
// Returns empty string when it is not set.

@ -35,6 +35,7 @@
#define GRPCXX_SUPPORT_TIME_H
#include <grpc++/support/config.h>
#include <grpc/support/time.h>
namespace grpc {

@ -127,6 +127,12 @@ typedef struct {
/** Initial sequence number for http2 transports */
#define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \
"grpc.http2.initial_sequence_number"
/** How much memory to use for hpack decoding */
#define GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER \
"grpc.http2.hpack_table_size.decoder"
/** How much memory to use for hpack encoding */
#define GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER \
"grpc.http2.hpack_table_size.encoder"
/** Default authority to pass if none specified on call construction */
#define GRPC_ARG_DEFAULT_AUTHORITY "grpc.default_authority"
/** Primary user agent: goes at the start of the user-agent metadata

@ -41,15 +41,16 @@
extern "C" {
#endif
/* --- grpc_credentials object. ---
/* --- grpc_channel_credentials object. ---
A credentials object represents a way to authenticate a client. */
A channel credentials object represents a way to authenticate a client on a
channel. */
typedef struct grpc_credentials grpc_credentials;
typedef struct grpc_channel_credentials grpc_channel_credentials;
/* Releases a credentials object.
/* Releases a channel credentials object.
The creator of the credentials object is responsible for its release. */
void grpc_credentials_release(grpc_credentials *creds);
void grpc_channel_credentials_release(grpc_channel_credentials *creds);
/* Environment variable that points to the google default application
credentials json key or refresh token. Used in the
@ -59,7 +60,7 @@ void grpc_credentials_release(grpc_credentials *creds);
/* Creates default credentials to connect to a google gRPC service.
WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak. */
grpc_credentials *grpc_google_default_credentials_create(void);
grpc_channel_credentials *grpc_google_default_credentials_create(void);
/* Environment variable that points to the default SSL roots file. This file
must be a PEM encoded file with all the roots such as the one that can be
@ -88,19 +89,37 @@ typedef struct {
- pem_key_cert_pair is a pointer on the object containing client's private
key and certificate chain. This parameter can be NULL if the client does
not have such a key/cert pair. */
grpc_credentials *grpc_ssl_credentials_create(
grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
void *reserved);
/* Creates a composite credentials object. */
grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
grpc_credentials *creds2,
void *reserved);
/* --- grpc_call_credentials object.
A call credentials object represents a way to authenticate on a particular
call. These credentials can be composed with a channel credentials object
so that they are sent with every call on this channel. */
typedef struct grpc_call_credentials grpc_call_credentials;
/* Releases a call credentials object.
The creator of the credentials object is responsible for its release. */
void grpc_call_credentials_release(grpc_call_credentials *creds);
/* Creates a composite channel credentials object. */
grpc_channel_credentials *grpc_composite_channel_credentials_create(
grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
void *reserved);
/* Creates a composite call credentials object. */
grpc_call_credentials *grpc_composite_call_credentials_create(
grpc_call_credentials *creds1, grpc_call_credentials *creds2,
void *reserved);
/* Creates a compute engine credentials object for connecting to Google.
WARNING: Do NOT use this credentials to connect to a non-google service as
this could result in an oauth2 token leak. */
grpc_credentials *grpc_google_compute_engine_credentials_create(void *reserved);
grpc_call_credentials *grpc_google_compute_engine_credentials_create(
void *reserved);
extern const gpr_timespec grpc_max_auth_token_lifetime;
@ -109,7 +128,7 @@ extern const gpr_timespec grpc_max_auth_token_lifetime;
- 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_service_account_jwt_access_credentials_create(
grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
const char *json_key, gpr_timespec token_lifetime, void *reserved);
/* Creates an Oauth2 Refresh Token credentials object for connecting to Google.
@ -118,16 +137,16 @@ grpc_credentials *grpc_service_account_jwt_access_credentials_create(
this could result in an oauth2 token leak.
- json_refresh_token is the JSON string containing the refresh token itself
along with a client_id and client_secret. */
grpc_credentials *grpc_google_refresh_token_credentials_create(
grpc_call_credentials *grpc_google_refresh_token_credentials_create(
const char *json_refresh_token, void *reserved);
/* Creates an Oauth2 Access Token credentials with an access token that was
aquired by an out of band mechanism. */
grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
void *reserved);
grpc_call_credentials *grpc_access_token_credentials_create(
const char *access_token, void *reserved);
/* Creates an IAM credentials object for connecting to Google. */
grpc_credentials *grpc_google_iam_credentials_create(
grpc_call_credentials *grpc_google_iam_credentials_create(
const char *authorization_token, const char *authority_selector,
void *reserved);
@ -168,13 +187,13 @@ typedef struct {
} grpc_metadata_credentials_plugin;
/* Creates a credentials object from a plugin. */
grpc_credentials *grpc_metadata_credentials_create_from_plugin(
grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
grpc_metadata_credentials_plugin plugin, void *reserved);
/* --- Secure channel creation. --- */
/* Creates a secure channel using the passed-in credentials. */
grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
const char *target,
const grpc_channel_args *args,
void *reserved);
@ -218,7 +237,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
/* Sets a credentials to a call. Can only be called on the client side before
grpc_call_start_batch. */
grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_credentials *creds);
grpc_call_credentials *creds);
/* --- Authentication Context. --- */

@ -0,0 +1,141 @@
<!DOCTYPE html>
<html lang="en">
<head><title>Interop Test Result</title></head>
<body>
<%def name="fill_one_test_result(shortname, resultset)">
% if shortname in resultset:
## Because interop tests does not have runs_per_test flag, each test is
## run once. So there should only be one element for each result.
<% result = resultset[shortname][0] %>
% if result.state == 'PASSED':
<td bgcolor="green">PASS</td>
% else:
<%
tooltip = ''
if result.returncode > 0 or result.message:
if result.returncode > 0:
tooltip = 'returncode: %d ' % result.returncode
if result.message:
tooltip = '%smessage: %s' % (tooltip, result.message)
%>
% if result.state == 'FAILED':
<td bgcolor="red">
% if tooltip:
<a href="#" data-toggle="tooltip" data-placement="auto" title="${tooltip | h}">FAIL</a></td>
% else:
FAIL</td>
% endif
% elif result.state == 'TIMEOUT':
<td bgcolor="yellow">
% if tooltip:
<a href="#" data-toggle="tooltip" data-placement="auto" title="${tooltip | h}">TIMEOUT</a></td>
% else:
TIMEOUT</td>
% endif
% endif
% endif
% else:
<td bgcolor="magenta">Not implemented</td>
% endif
</%def>
% if num_failures > 1:
<p><h2><font color="red">${num_failures} tests failed!</font></h2></p>
% elif num_failures:
<p><h2><font color="red">${num_failures} test failed!</font></h2></p>
% else:
<p><h2><font color="green">All tests passed!</font></h2></p>
% endif
% if cloud_to_prod:
## Each column header is the client language.
<h2>Cloud to Prod</h2>
<table style="width:100%" border="1">
<tr bgcolor="#00BFFF">
<th>Client languages &#9658;<br/>Test Cases &#9660;</th>
% for client_lang in client_langs:
<th>${client_lang}</th>
% endfor
</tr>
% for test_case in test_cases + auth_test_cases:
<tr><td><b>${test_case}</b></td>
% for client_lang in client_langs:
<%
if test_case in auth_test_cases:
shortname = 'cloud_to_prod_auth:%s:%s' % (client_lang, test_case)
else:
shortname = 'cloud_to_prod:%s:%s' % (client_lang, test_case)
%>
${fill_one_test_result(shortname, resultset)}
% endfor
</tr>
% endfor
</table>
% endif
% if http2_interop:
## Each column header is the server language.
<h2>HTTP/2 Interop</h2>
<table style="width:100%" border="1">
<tr bgcolor="#00BFFF">
<th>Servers &#9658;<br/>Test Cases &#9660;</th>
% for server_lang in server_langs:
<th>${server_lang}</th>
% endfor
% if cloud_to_prod:
<th>prod</th>
% endif
</tr>
% for test_case in http2_cases:
<tr><td><b>${test_case}</b></td>
## Fill up the cells with test result.
% for server_lang in server_langs:
<%
shortname = 'cloud_to_cloud:http2:%s_server:%s' % (
server_lang, test_case)
%>
${fill_one_test_result(shortname, resultset)}
% endfor
% if cloud_to_prod:
<% shortname = 'cloud_to_prod:http2:%s' % test_case %>
${fill_one_test_result(shortname, resultset)}
% endif
</tr>
% endfor
</table>
% endif
% if server_langs:
% for test_case in test_cases:
## Each column header is the client language.
<h2>${test_case}</h2>
<table style="width:100%" border="1">
<tr bgcolor="#00BFFF">
<th>Client languages &#9658;<br/>Server languages &#9660;</th>
% for client_lang in client_langs:
<th>${client_lang}</th>
% endfor
</tr>
## Each row head is the server language.
% for server_lang in server_langs:
<tr>
<td><b>${server_lang}</b></td>
% for client_lang in client_langs:
<%
shortname = 'cloud_to_cloud:%s:%s_server:%s' % (
client_lang, server_lang, test_case)
%>
${fill_one_test_result(shortname, resultset)}
% endfor
</tr>
% endfor
</table>
% endfor
% endif
<script>
$(document).ready(function(){$('[data-toggle="tooltip"]').tooltip();});
</script>
</body>
</html>

@ -697,10 +697,25 @@ static double generate_uniform_random_number(grpc_subchannel *c) {
/* Update backoff_delta and next_attempt in subchannel */
static void update_reconnect_parameters(grpc_subchannel *c) {
size_t i;
gpr_int32 backoff_delta_millis, jitter;
gpr_int32 max_backoff_millis =
GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000;
double jitter_range;
if (c->args) {
for (i = 0; i < c->args->num_args; i++) {
if (0 == strcmp(c->args->args[i].key,
"grpc.testing.fixed_reconnect_backoff")) {
GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
c->next_attempt = gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_millis(c->args->args[i].value.integer, GPR_TIMESPAN));
return;
}
}
}
backoff_delta_millis =
(gpr_int32)(gpr_time_to_millis(c->backoff_delta) *
GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER);

@ -77,10 +77,10 @@ void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
/** construct a subchannel call (possibly asynchronously).
*
* If the returned status is 1, the call will return immediately and \a target
* will point to a connected \a subchannel_call instance. Note that \a notify
* If the returned status is 1, the call will return immediately and \a target
* will point to a connected \a subchannel_call instance. Note that \a notify
* will \em not be invoked in this case.
* Otherwise, if the returned status is 0, the subchannel call will be created
* Otherwise, if the returned status is 0, the subchannel call will be created
* asynchronously, invoking the \a notify callback upon completion. */
int grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx,
grpc_subchannel *subchannel,

@ -126,7 +126,8 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {}
void grpc_pollset_reset(grpc_pollset *pollset) {
GPR_ASSERT(pollset->shutting_down);
GPR_ASSERT(!has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET));
GPR_ASSERT(
!has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET));
pollset->shutting_down = 0;
pollset->is_iocp_worker = 0;
pollset->kicked_without_pollers = 0;

@ -39,6 +39,9 @@
/* Forward decl of grpc_tcp_server */
typedef struct grpc_tcp_server grpc_tcp_server;
/* Forward decl of grpc_tcp_listener */
typedef struct grpc_tcp_listener grpc_tcp_listener;
/* Called for newly connected TCP connections. */
typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *ep);
@ -51,19 +54,18 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
grpc_pollset **pollsets, size_t pollset_count,
grpc_tcp_server_cb on_accept_cb, void *cb_arg);
/* Add a port to the server, returning port number on success, or negative
on failure.
/* Add a port to the server, returning the newly created listener on success,
or a null pointer on failure.
The :: and 0.0.0.0 wildcard addresses are treated identically, accepting
both IPv4 and IPv6 connections, but :: is the preferred style. This usually
creates one socket, but possibly two on systems which support IPv6,
but not dualstack sockets.
For raw access to the underlying sockets, see grpc_tcp_server_get_fd(). */
but not dualstack sockets. */
/* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle
all of the multiple socket port matching logic in one place */
int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
size_t addr_len);
grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
const void *addr,
size_t addr_len);
/* Returns the file descriptor of the Nth listening socket on this server,
or -1 if the index is out of bounds.
@ -75,4 +77,8 @@ int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned index);
void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
grpc_closure *closure);
int grpc_tcp_listener_get_port(grpc_tcp_listener *listener);
void grpc_tcp_listener_ref(grpc_tcp_listener *listener);
void grpc_tcp_listener_unref(grpc_tcp_listener *listener);
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H */

@ -67,14 +67,13 @@
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#define INIT_PORT_CAP 2
#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
static gpr_once s_init_max_accept_queue_size;
static int s_max_accept_queue_size;
/* one listening port */
typedef struct {
struct grpc_tcp_listener {
int fd;
grpc_fd *emfd;
grpc_tcp_server *server;
@ -84,9 +83,18 @@ typedef struct {
struct sockaddr_un un;
} addr;
size_t addr_len;
int port;
grpc_closure read_closure;
grpc_closure destroyed_closure;
} server_port;
gpr_refcount refs;
struct grpc_tcp_listener *next;
/* When we add a listener, more than one can be created, mainly because of
IPv6. A sibling will still be in the normal list, but will be flagged
as such. Any action, such as ref or unref, will affect all of the
siblings in the list. */
struct grpc_tcp_listener *sibling;
int is_sibling;
};
static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) {
struct stat st;
@ -112,10 +120,9 @@ struct grpc_tcp_server {
/* is this server shutting down? (boolean) */
int shutdown;
/* all listening ports */
server_port *ports;
size_t nports;
size_t port_capacity;
/* linked list of server ports */
grpc_tcp_listener *head;
unsigned nports;
/* shutdown callback */
grpc_closure *shutdown_complete;
@ -134,9 +141,8 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
s->shutdown = 0;
s->on_accept_cb = NULL;
s->on_accept_cb_arg = NULL;
s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
s->head = NULL;
s->nports = 0;
s->port_capacity = INIT_PORT_CAP;
return s;
}
@ -145,7 +151,12 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
gpr_mu_destroy(&s->mu);
gpr_free(s->ports);
while (s->head) {
grpc_tcp_listener *sp = s->head;
s->head = sp->next;
grpc_tcp_listener_unref(sp);
}
gpr_free(s);
}
@ -166,8 +177,6 @@ static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, int success) {
events will be received on them - at this point it's safe to destroy
things */
static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
size_t i;
/* delete ALL the things */
gpr_mu_lock(&s->mu);
@ -176,9 +185,9 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
return;
}
if (s->nports) {
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
if (s->head) {
grpc_tcp_listener *sp;
for (sp = s->head; sp; sp = sp->next) {
if (sp->addr.sockaddr.sa_family == AF_UNIX) {
unlink_if_unix_domain_socket(&sp->addr.un);
}
@ -196,7 +205,6 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
grpc_closure *closure) {
size_t i;
gpr_mu_lock(&s->mu);
GPR_ASSERT(!s->shutdown);
@ -206,8 +214,9 @@ void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
/* shutdown all fd's */
if (s->active_ports) {
for (i = 0; i < s->nports; i++) {
grpc_fd_shutdown(exec_ctx, s->ports[i].emfd);
grpc_tcp_listener *sp;
for (sp = s->head; sp; sp = sp->next) {
grpc_fd_shutdown(exec_ctx, sp->emfd);
}
gpr_mu_unlock(&s->mu);
} else {
@ -298,7 +307,7 @@ error:
/* event manager callback when reads are ready */
static void on_read(grpc_exec_ctx *exec_ctx, void *arg, int success) {
server_port *sp = arg;
grpc_tcp_listener *sp = arg;
grpc_fd *fdobj;
size_t i;
@ -364,9 +373,10 @@ error:
}
}
static int add_socket_to_server(grpc_tcp_server *s, int fd,
const struct sockaddr *addr, size_t addr_len) {
server_port *sp;
static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
const struct sockaddr *addr,
size_t addr_len) {
grpc_tcp_listener *sp = NULL;
int port;
char *addr_str;
char *name;
@ -376,32 +386,35 @@ static int add_socket_to_server(grpc_tcp_server *s, int fd,
grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
gpr_mu_lock(&s->mu);
s->nports++;
GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
/* append it to the list under a lock */
if (s->nports == s->port_capacity) {
s->port_capacity *= 2;
s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity);
}
sp = &s->ports[s->nports++];
sp = gpr_malloc(sizeof(grpc_tcp_listener));
sp->next = s->head;
s->head = sp;
sp->server = s;
sp->fd = fd;
sp->emfd = grpc_fd_create(fd, name);
memcpy(sp->addr.untyped, addr, addr_len);
sp->addr_len = addr_len;
sp->port = port;
sp->is_sibling = 0;
sp->sibling = NULL;
gpr_ref_init(&sp->refs, 1);
GPR_ASSERT(sp->emfd);
gpr_mu_unlock(&s->mu);
gpr_free(addr_str);
gpr_free(name);
}
return port;
return sp;
}
int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
size_t addr_len) {
int allocated_port1 = -1;
int allocated_port2 = -1;
unsigned i;
grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
const void *addr,
size_t addr_len) {
int allocated_port = -1;
grpc_tcp_listener *sp;
grpc_tcp_listener *sp2 = NULL;
int fd;
grpc_dualstack_mode dsmode;
struct sockaddr_in6 addr6_v4mapped;
@ -420,9 +433,9 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
/* Check if this is a wildcard port, and if so, try to keep the port the same
as some previously created listener. */
if (grpc_sockaddr_get_port(addr) == 0) {
for (i = 0; i < s->nports; i++) {
for (sp = s->head; sp; sp = sp->next) {
sockname_len = sizeof(sockname_temp);
if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp,
if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
&sockname_len)) {
port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
if (port > 0) {
@ -436,6 +449,8 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
}
}
sp = NULL;
if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
addr = (const struct sockaddr *)&addr6_v4mapped;
addr_len = sizeof(addr6_v4mapped);
@ -449,14 +464,16 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
addr = (struct sockaddr *)&wild6;
addr_len = sizeof(wild6);
fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
allocated_port1 = add_socket_to_server(s, fd, addr, addr_len);
sp = add_socket_to_server(s, fd, addr, addr_len);
allocated_port = sp->port;
if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
goto done;
}
/* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
if (port == 0 && allocated_port1 > 0) {
grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1);
if (port == 0 && allocated_port > 0) {
grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port);
sp2 = sp;
}
addr = (struct sockaddr *)&wild4;
addr_len = sizeof(wild4);
@ -471,22 +488,31 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
addr = (struct sockaddr *)&addr4_copy;
addr_len = sizeof(addr4_copy);
}
allocated_port2 = add_socket_to_server(s, fd, addr, addr_len);
sp = add_socket_to_server(s, fd, addr, addr_len);
sp->sibling = sp2;
if (sp2) sp2->is_sibling = 1;
done:
gpr_free(allocated_addr);
return allocated_port1 >= 0 ? allocated_port1 : allocated_port2;
return sp;
}
int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned port_index) {
return (port_index < s->nports) ? s->ports[port_index].fd : -1;
grpc_tcp_listener *sp;
for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--);
if (port_index == 0 && sp) {
return sp->fd;
} else {
return -1;
}
}
void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
grpc_pollset **pollsets, size_t pollset_count,
grpc_tcp_server_cb on_accept_cb,
void *on_accept_cb_arg) {
size_t i, j;
size_t i;
grpc_tcp_listener *sp;
GPR_ASSERT(on_accept_cb);
gpr_mu_lock(&s->mu);
GPR_ASSERT(!s->on_accept_cb);
@ -495,17 +521,41 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
s->on_accept_cb_arg = on_accept_cb_arg;
s->pollsets = pollsets;
s->pollset_count = pollset_count;
for (i = 0; i < s->nports; i++) {
for (j = 0; j < pollset_count; j++) {
grpc_pollset_add_fd(exec_ctx, pollsets[j], s->ports[i].emfd);
for (sp = s->head; sp; sp = sp->next) {
for (i = 0; i < pollset_count; i++) {
grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
}
s->ports[i].read_closure.cb = on_read;
s->ports[i].read_closure.cb_arg = &s->ports[i];
grpc_fd_notify_on_read(exec_ctx, s->ports[i].emfd,
&s->ports[i].read_closure);
sp->read_closure.cb = on_read;
sp->read_closure.cb_arg = sp;
grpc_fd_notify_on_read(exec_ctx, sp->emfd,
&sp->read_closure);
s->active_ports++;
}
gpr_mu_unlock(&s->mu);
}
int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) {
grpc_tcp_listener *sp = listener;
return sp->port;
}
void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {
grpc_tcp_listener *sp = listener;
gpr_ref(&sp->refs);
}
void grpc_tcp_listener_unref(grpc_tcp_listener *listener) {
grpc_tcp_listener *sp = listener;
if (sp->is_sibling) return;
if (gpr_unref(&sp->refs)) {
grpc_tcp_listener *sibling = sp->sibling;
while (sibling) {
sp = sibling;
sibling = sp->sibling;
gpr_free(sp);
}
gpr_free(listener);
}
}
#endif

@ -35,7 +35,8 @@
#ifdef GPR_WINSOCK_SOCKET
#define _GNU_SOURCE
#include <io.h>
#include "src/core/iomgr/sockaddr_utils.h"
#include <grpc/support/alloc.h>
@ -51,25 +52,29 @@
#include "src/core/iomgr/tcp_server.h"
#include "src/core/iomgr/tcp_windows.h"
#define INIT_PORT_CAP 2
#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
/* one listening port */
typedef struct server_port {
struct grpc_tcp_listener {
/* This seemingly magic number comes from AcceptEx's documentation. each
address buffer needs to have at least 16 more bytes at their end. */
gpr_uint8 addresses[(sizeof(struct sockaddr_in6) + 16) * 2];
/* This will hold the socket for the next accept. */
SOCKET new_socket;
/* The listener winsocked. */
/* The listener winsocket. */
grpc_winsocket *socket;
/* The actual TCP port number. */
int port;
grpc_tcp_server *server;
/* The cached AcceptEx for that port. */
LPFN_ACCEPTEX AcceptEx;
int shutting_down;
/* closure for socket notification of accept being ready */
grpc_closure on_accept;
} server_port;
gpr_refcount refs;
/* linked list */
struct grpc_tcp_listener *next;
};
/* the overall server */
struct grpc_tcp_server {
@ -82,10 +87,8 @@ struct grpc_tcp_server {
/* active port count: how many ports are actually still listening */
int active_ports;
/* all listening ports */
server_port *ports;
size_t nports;
size_t port_capacity;
/* linked list of server ports */
grpc_tcp_listener *head;
/* shutdown callback */
grpc_closure *shutdown_complete;
@ -99,9 +102,7 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
s->active_ports = 0;
s->on_accept_cb = NULL;
s->on_accept_cb_arg = NULL;
s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
s->nports = 0;
s->port_capacity = INIT_PORT_CAP;
s->head = NULL;
s->shutdown_complete = NULL;
return s;
}
@ -109,26 +110,26 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
static void dont_care_about_shutdown_completion(void *arg) {}
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
size_t i;
grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1);
/* Now that the accepts have been aborted, we can destroy the sockets.
The IOCP won't get notified on these, so we can flag them as already
closed by the system. */
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
while (s->head) {
grpc_tcp_listener *sp = s->head;
s->head = sp->next;
sp->next = NULL;
grpc_winsocket_destroy(sp->socket);
grpc_tcp_listener_unref(sp);
}
gpr_free(s->ports);
gpr_free(s);
}
/* Public function. Stops and destroys a grpc_tcp_server. */
void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
grpc_closure *shutdown_complete) {
size_t i;
int immediately_done = 0;
grpc_tcp_listener *sp;
gpr_mu_lock(&s->mu);
s->shutdown_complete = shutdown_complete;
@ -138,8 +139,7 @@ void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
if (s->active_ports == 0) {
immediately_done = 1;
}
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
for (sp = s->head; sp; sp = sp->next) {
sp->shutting_down = 1;
grpc_winsocket_shutdown(sp->socket);
}
@ -199,7 +199,7 @@ error:
}
static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
server_port *sp) {
grpc_tcp_listener *sp) {
int notify = 0;
sp->shutting_down = 0;
gpr_mu_lock(&sp->server->mu);
@ -216,7 +216,7 @@ static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
/* In order to do an async accept, we need to create a socket first which
will be the one assigned to the new incoming connection. */
static void start_accept(grpc_exec_ctx *exec_ctx, server_port *port) {
static void start_accept(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *port) {
SOCKET sock = INVALID_SOCKET;
char *message;
char *utf8_message;
@ -276,7 +276,7 @@ failure:
/* Event manager callback when reads are ready. */
static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, int from_iocp) {
server_port *sp = arg;
grpc_tcp_listener *sp = arg;
SOCKET sock = sp->new_socket;
grpc_winsocket_callback_info *info = &sp->socket->read_info;
grpc_endpoint *ep = NULL;
@ -351,16 +351,17 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, int from_iocp) {
start_accept(exec_ctx, sp);
}
static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
const struct sockaddr *addr, size_t addr_len) {
server_port *sp;
static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
const struct sockaddr *addr,
size_t addr_len) {
grpc_tcp_listener *sp = NULL;
int port;
int status;
GUID guid = WSAID_ACCEPTEX;
DWORD ioctl_num_bytes;
LPFN_ACCEPTEX AcceptEx;
if (sock == INVALID_SOCKET) return -1;
if (sock == INVALID_SOCKET) return NULL;
/* We need to grab the AcceptEx pointer for that port, as it may be
interface-dependent. We'll cache it to avoid doing that again. */
@ -373,37 +374,35 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
gpr_free(utf8_message);
closesocket(sock);
return -1;
return NULL;
}
port = prepare_socket(sock, addr, addr_len);
if (port >= 0) {
gpr_mu_lock(&s->mu);
GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
/* append it to the list under a lock */
if (s->nports == s->port_capacity) {
/* too many ports, and we need to store their address in a closure */
/* TODO(ctiller): make server_port a linked list */
abort();
}
sp = &s->ports[s->nports++];
sp = gpr_malloc(sizeof(grpc_tcp_listener));
sp->next = s->head;
s->head = sp;
sp->server = s;
sp->socket = grpc_winsocket_create(sock, "listener");
sp->shutting_down = 0;
sp->AcceptEx = AcceptEx;
sp->new_socket = INVALID_SOCKET;
sp->port = port;
gpr_ref_init(&sp->refs, 1);
grpc_closure_init(&sp->on_accept, on_accept, sp);
GPR_ASSERT(sp->socket);
gpr_mu_unlock(&s->mu);
}
return port;
return sp;
}
int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
size_t addr_len) {
int allocated_port = -1;
unsigned i;
grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
const void *addr,
size_t addr_len) {
grpc_tcp_listener *sp;
SOCKET sock;
struct sockaddr_in6 addr6_v4mapped;
struct sockaddr_in6 wildcard;
@ -415,9 +414,9 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
/* Check if this is a wildcard port, and if so, try to keep the port the same
as some previously created listener. */
if (grpc_sockaddr_get_port(addr) == 0) {
for (i = 0; i < s->nports; i++) {
for (sp = s->head; sp; sp = sp->next) {
sockname_len = sizeof(sockname_temp);
if (0 == getsockname(s->ports[i].socket->socket,
if (0 == getsockname(sp->socket->socket,
(struct sockaddr *)&sockname_temp, &sockname_len)) {
port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
if (port > 0) {
@ -452,33 +451,55 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
gpr_free(utf8_message);
}
allocated_port = add_socket_to_server(s, sock, addr, addr_len);
sp = add_socket_to_server(s, sock, addr, addr_len);
gpr_free(allocated_addr);
return allocated_port;
return sp;
}
SOCKET
grpc_tcp_server_get_socket(grpc_tcp_server *s, unsigned index) {
return (index < s->nports) ? s->ports[index].socket->socket : INVALID_SOCKET;
int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned port_index) {
grpc_tcp_listener *sp;
for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--);
if (port_index == 0 && sp) {
return _open_osfhandle(sp->socket->socket, 0);
} else {
return -1;
}
}
void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
grpc_pollset **pollset, size_t pollset_count,
grpc_tcp_server_cb on_accept_cb,
void *on_accept_cb_arg) {
size_t i;
grpc_tcp_listener *sp;
GPR_ASSERT(on_accept_cb);
gpr_mu_lock(&s->mu);
GPR_ASSERT(!s->on_accept_cb);
GPR_ASSERT(s->active_ports == 0);
s->on_accept_cb = on_accept_cb;
s->on_accept_cb_arg = on_accept_cb_arg;
for (i = 0; i < s->nports; i++) {
start_accept(exec_ctx, s->ports + i);
for (sp = s->head; sp; sp = sp->next) {
start_accept(exec_ctx, sp);
s->active_ports++;
}
gpr_mu_unlock(&s->mu);
}
int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) {
grpc_tcp_listener *sp = listener;
return sp->port;
}
void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {
grpc_tcp_listener *sp = listener;
gpr_ref(&sp->refs);
}
void grpc_tcp_listener_unref(grpc_tcp_listener *listener) {
grpc_tcp_listener *sp = listener;
if (gpr_unref(&sp->refs)) {
gpr_free(listener);
}
}
#endif /* GPR_WINSOCK_SOCKET */

@ -50,7 +50,7 @@
/* We can have a per-call credentials. */
typedef struct {
grpc_credentials *creds;
grpc_call_credentials *creds;
grpc_mdstr *host;
grpc_mdstr *method;
/* pollset bound to this call; if we need to make external
@ -143,39 +143,35 @@ static void send_security_metadata(grpc_exec_ctx *exec_ctx,
channel_data *chand = elem->channel_data;
grpc_client_security_context *ctx =
(grpc_client_security_context *)op->context[GRPC_CONTEXT_SECURITY].value;
grpc_credentials *channel_creds =
grpc_call_credentials *channel_call_creds =
chand->security_connector->request_metadata_creds;
int channel_creds_has_md =
(channel_creds != NULL) &&
grpc_credentials_has_request_metadata(channel_creds);
int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL) &&
grpc_credentials_has_request_metadata(ctx->creds);
int call_creds_has_md = (ctx != NULL) && (ctx->creds != NULL);
if (!channel_creds_has_md && !call_creds_has_md) {
if (channel_call_creds == NULL && !call_creds_has_md) {
/* Skip sending metadata altogether. */
grpc_call_next_op(exec_ctx, elem, op);
return;
}
if (channel_creds_has_md && call_creds_has_md) {
calld->creds =
grpc_composite_credentials_create(channel_creds, ctx->creds, NULL);
if (channel_call_creds != NULL && call_creds_has_md) {
calld->creds = grpc_composite_call_credentials_create(channel_call_creds,
ctx->creds, NULL);
if (calld->creds == NULL) {
bubble_up_error(exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT,
"Incompatible credentials set on channel and call.");
return;
}
} else {
calld->creds =
grpc_credentials_ref(call_creds_has_md ? ctx->creds : channel_creds);
calld->creds = grpc_call_credentials_ref(
call_creds_has_md ? ctx->creds : channel_call_creds);
}
build_service_url(chand->security_connector->base.url_scheme, calld);
calld->op = *op; /* Copy op (originates from the caller's stack). */
GPR_ASSERT(calld->pollset);
grpc_credentials_get_request_metadata(exec_ctx, calld->creds, calld->pollset,
calld->service_url,
on_credentials_metadata, elem);
grpc_call_credentials_get_request_metadata(exec_ctx, calld->creds,
calld->pollset, calld->service_url,
on_credentials_metadata, elem);
}
static void on_host_checked(grpc_exec_ctx *exec_ctx, void *user_data,
@ -282,7 +278,7 @@ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
call_data *calld = elem->call_data;
grpc_credentials_unref(calld->creds);
grpc_call_credentials_unref(calld->creds);
if (calld->host != NULL) {
GRPC_MDSTR_UNREF(calld->host);
}

@ -54,18 +54,18 @@
/* -- Common. -- */
struct grpc_credentials_metadata_request {
grpc_credentials *creds;
grpc_call_credentials *creds;
grpc_credentials_metadata_cb cb;
void *user_data;
};
static grpc_credentials_metadata_request *
grpc_credentials_metadata_request_create(grpc_credentials *creds,
grpc_credentials_metadata_request_create(grpc_call_credentials *creds,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_credentials_metadata_request *r =
gpr_malloc(sizeof(grpc_credentials_metadata_request));
r->creds = grpc_credentials_ref(creds);
r->creds = grpc_call_credentials_ref(creds);
r->cb = cb;
r->user_data = user_data;
return r;
@ -73,44 +73,56 @@ grpc_credentials_metadata_request_create(grpc_credentials *creds,
static void grpc_credentials_metadata_request_destroy(
grpc_credentials_metadata_request *r) {
grpc_credentials_unref(r->creds);
grpc_call_credentials_unref(r->creds);
gpr_free(r);
}
grpc_credentials *grpc_credentials_ref(grpc_credentials *creds) {
grpc_channel_credentials *grpc_channel_credentials_ref(
grpc_channel_credentials *creds) {
if (creds == NULL) return NULL;
gpr_ref(&creds->refcount);
return creds;
}
void grpc_credentials_unref(grpc_credentials *creds) {
void grpc_channel_credentials_unref(grpc_channel_credentials *creds) {
if (creds == NULL) return;
if (gpr_unref(&creds->refcount)) {
creds->vtable->destruct(creds);
if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
gpr_free(creds);
}
}
void grpc_credentials_release(grpc_credentials *creds) {
GRPC_API_TRACE("grpc_credentials_release(creds=%p)", 1, (creds));
grpc_credentials_unref(creds);
void grpc_channel_credentials_release(grpc_channel_credentials *creds) {
GRPC_API_TRACE("grpc_channel_credentials_release(creds=%p)", 1, (creds));
grpc_channel_credentials_unref(creds);
}
int grpc_credentials_has_request_metadata(grpc_credentials *creds) {
if (creds == NULL) return 0;
return creds->vtable->has_request_metadata(creds);
grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds) {
if (creds == NULL) return NULL;
gpr_ref(&creds->refcount);
return creds;
}
void grpc_call_credentials_unref(grpc_call_credentials *creds) {
if (creds == NULL) return;
if (gpr_unref(&creds->refcount)) {
if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
gpr_free(creds);
}
}
int grpc_credentials_has_request_metadata_only(grpc_credentials *creds) {
if (creds == NULL) return 0;
return creds->vtable->has_request_metadata_only(creds);
void grpc_call_credentials_release(grpc_call_credentials *creds) {
GRPC_API_TRACE("grpc_call_credentials_release(creds=%p)", 1, (creds));
grpc_call_credentials_unref(creds);
}
void grpc_credentials_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
if (creds == NULL || !grpc_credentials_has_request_metadata(creds) ||
creds->vtable->get_request_metadata == NULL) {
void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
if (creds == NULL || creds->vtable->get_request_metadata == NULL) {
if (cb != NULL) {
cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
}
@ -120,19 +132,17 @@ void grpc_credentials_get_request_metadata(
user_data);
}
grpc_security_status grpc_credentials_create_security_connector(
grpc_credentials *creds, const char *target, const grpc_channel_args *args,
grpc_credentials *request_metadata_creds,
grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
grpc_security_status grpc_channel_credentials_create_security_connector(
grpc_channel_credentials *channel_creds, const char *target,
const grpc_channel_args *args, grpc_channel_security_connector **sc,
grpc_channel_args **new_args) {
*new_args = NULL;
if (creds == NULL || creds->vtable->create_security_connector == NULL ||
grpc_credentials_has_request_metadata_only(creds)) {
gpr_log(GPR_ERROR,
"Invalid credentials for creating a security connector.");
if (channel_creds == NULL) {
return GRPC_SECURITY_ERROR;
}
return creds->vtable->create_security_connector(
creds, target, args, request_metadata_creds, sc, new_args);
GPR_ASSERT(channel_creds->vtable->create_security_connector != NULL);
return channel_creds->vtable->create_security_connector(
channel_creds, NULL, target, args, sc, new_args);
}
grpc_server_credentials *grpc_server_credentials_ref(
@ -145,7 +155,7 @@ grpc_server_credentials *grpc_server_credentials_ref(
void grpc_server_credentials_unref(grpc_server_credentials *creds) {
if (creds == NULL) return;
if (gpr_unref(&creds->refcount)) {
creds->vtable->destruct(creds);
if (creds->vtable->destruct != NULL) creds->vtable->destruct(creds);
if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
creds->processor.destroy(creds->processor.state);
}
@ -224,7 +234,7 @@ grpc_server_credentials *grpc_find_server_credentials_in_args(
/* -- Ssl credentials. -- */
static void ssl_destruct(grpc_credentials *creds) {
static void ssl_destruct(grpc_channel_credentials *creds) {
grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
@ -253,15 +263,9 @@ static void ssl_server_destruct(grpc_server_credentials *creds) {
if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
}
static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; }
static int ssl_has_request_metadata_only(const grpc_credentials *creds) {
return 0;
}
static grpc_security_status ssl_create_security_connector(
grpc_credentials *creds, const char *target, const grpc_channel_args *args,
grpc_credentials *request_metadata_creds,
grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
const char *target, const grpc_channel_args *args,
grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
grpc_security_status status = GRPC_SECURITY_OK;
@ -278,7 +282,7 @@ static grpc_security_status ssl_create_security_connector(
}
}
status = grpc_ssl_channel_security_connector_create(
request_metadata_creds, &c->config, target, overridden_target_name, sc);
call_creds, &c->config, target, overridden_target_name, sc);
if (status != GRPC_SECURITY_OK) {
return status;
}
@ -295,9 +299,8 @@ static grpc_security_status ssl_server_create_security_connector(
return grpc_ssl_server_security_connector_create(&c->config, sc);
}
static grpc_credentials_vtable ssl_vtable = {
ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
ssl_create_security_connector};
static grpc_channel_credentials_vtable ssl_vtable = {
ssl_destruct, ssl_create_security_connector};
static grpc_server_credentials_vtable ssl_server_vtable = {
ssl_server_destruct, ssl_server_create_security_connector};
@ -362,7 +365,7 @@ static void ssl_build_server_config(
}
}
grpc_credentials *grpc_ssl_credentials_create(
grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
void *reserved) {
grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
@ -373,7 +376,7 @@ grpc_credentials *grpc_ssl_credentials_create(
3, (pem_root_certs, pem_key_cert_pair, reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_ssl_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
c->base.vtable = &ssl_vtable;
gpr_ref_init(&c->base.refcount, 1);
ssl_build_config(pem_root_certs, pem_key_cert_pair, &c->config);
@ -393,7 +396,7 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
force_client_auth, reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_ssl_server_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &ssl_server_vtable;
ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
@ -415,7 +418,7 @@ static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
}
static void jwt_destruct(grpc_credentials *creds) {
static void jwt_destruct(grpc_call_credentials *creds) {
grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
grpc_auth_json_key_destruct(&c->key);
@ -423,15 +426,12 @@ static void jwt_destruct(grpc_credentials *creds) {
gpr_mu_destroy(&c->cache_mu);
}
static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
static int jwt_has_request_metadata_only(const grpc_credentials *creds) {
return 1;
}
static void jwt_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
static void jwt_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_service_account_jwt_access_credentials *c =
(grpc_service_account_jwt_access_credentials *)creds;
gpr_timespec refresh_threshold = gpr_time_from_seconds(
@ -483,11 +483,10 @@ static void jwt_get_request_metadata(
}
}
static grpc_credentials_vtable jwt_vtable = {
jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only,
jwt_get_request_metadata, NULL};
static grpc_call_credentials_vtable jwt_vtable = {jwt_destruct,
jwt_get_request_metadata};
grpc_credentials *
grpc_call_credentials *
grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
grpc_auth_json_key key, gpr_timespec token_lifetime) {
grpc_service_account_jwt_access_credentials *c;
@ -497,7 +496,7 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
}
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;
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT;
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &jwt_vtable;
c->key = key;
@ -507,7 +506,7 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
return &c->base;
}
grpc_credentials *grpc_service_account_jwt_access_credentials_create(
grpc_call_credentials *grpc_service_account_jwt_access_credentials_create(
const char *json_key, gpr_timespec token_lifetime, void *reserved) {
GRPC_API_TRACE(
"grpc_service_account_jwt_access_credentials_create("
@ -524,7 +523,7 @@ grpc_credentials *grpc_service_account_jwt_access_credentials_create(
/* -- Oauth2TokenFetcher credentials -- */
static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
static void oauth2_token_fetcher_destruct(grpc_call_credentials *creds) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
grpc_credentials_md_store_unref(c->access_token_md);
@ -532,16 +531,6 @@ static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
grpc_httpcli_context_destroy(&c->httpcli_context);
}
static int oauth2_token_fetcher_has_request_metadata(
const grpc_credentials *creds) {
return 1;
}
static int oauth2_token_fetcher_has_request_metadata_only(
const grpc_credentials *creds) {
return 1;
}
grpc_credentials_status
grpc_oauth2_token_fetcher_credentials_parse_server_response(
const grpc_httpcli_response *response, grpc_credentials_md_store **token_md,
@ -659,8 +648,9 @@ static void on_oauth2_token_fetcher_http_response(
}
static void oauth2_token_fetcher_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_exec_ctx *exec_ctx, grpc_call_credentials *creds,
grpc_pollset *pollset, const char *service_url,
grpc_credentials_metadata_cb cb, void *user_data) {
grpc_oauth2_token_fetcher_credentials *c =
(grpc_oauth2_token_fetcher_credentials *)creds;
gpr_timespec refresh_threshold = gpr_time_from_seconds(
@ -693,7 +683,7 @@ static void oauth2_token_fetcher_get_request_metadata(
static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
grpc_fetch_oauth2_func fetch_func) {
memset(c, 0, sizeof(grpc_oauth2_token_fetcher_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
gpr_ref_init(&c->base.refcount, 1);
gpr_mu_init(&c->mu);
c->token_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
@ -703,10 +693,8 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
/* -- GoogleComputeEngine credentials. -- */
static grpc_credentials_vtable compute_engine_vtable = {
oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata,
oauth2_token_fetcher_has_request_metadata_only,
oauth2_token_fetcher_get_request_metadata, NULL};
static grpc_call_credentials_vtable compute_engine_vtable = {
oauth2_token_fetcher_destruct, oauth2_token_fetcher_get_request_metadata};
static void compute_engine_fetch_oauth2(
grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
@ -723,7 +711,7 @@ static void compute_engine_fetch_oauth2(
response_cb, metadata_req);
}
grpc_credentials *grpc_google_compute_engine_credentials_create(
grpc_call_credentials *grpc_google_compute_engine_credentials_create(
void *reserved) {
grpc_oauth2_token_fetcher_credentials *c =
gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials));
@ -737,17 +725,15 @@ grpc_credentials *grpc_google_compute_engine_credentials_create(
/* -- GoogleRefreshToken credentials. -- */
static void refresh_token_destruct(grpc_credentials *creds) {
static void refresh_token_destruct(grpc_call_credentials *creds) {
grpc_google_refresh_token_credentials *c =
(grpc_google_refresh_token_credentials *)creds;
grpc_auth_refresh_token_destruct(&c->refresh_token);
oauth2_token_fetcher_destruct(&c->base.base);
}
static grpc_credentials_vtable refresh_token_vtable = {
refresh_token_destruct, oauth2_token_fetcher_has_request_metadata,
oauth2_token_fetcher_has_request_metadata_only,
oauth2_token_fetcher_get_request_metadata, NULL};
static grpc_call_credentials_vtable refresh_token_vtable = {
refresh_token_destruct, oauth2_token_fetcher_get_request_metadata};
static void refresh_token_fetch_oauth2(
grpc_exec_ctx *exec_ctx, grpc_credentials_metadata_request *metadata_req,
@ -773,7 +759,8 @@ static void refresh_token_fetch_oauth2(
gpr_free(body);
}
grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_call_credentials *
grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_auth_refresh_token refresh_token) {
grpc_google_refresh_token_credentials *c;
if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
@ -788,7 +775,7 @@ grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
return &c->base.base;
}
grpc_credentials *grpc_google_refresh_token_credentials_create(
grpc_call_credentials *grpc_google_refresh_token_credentials_create(
const char *json_refresh_token, void *reserved) {
GRPC_API_TRACE(
"grpc_refresh_token_credentials_create(json_refresh_token=%s, "
@ -801,20 +788,11 @@ grpc_credentials *grpc_google_refresh_token_credentials_create(
/* -- Metadata-only credentials. -- */
static void md_only_test_destruct(grpc_credentials *creds) {
static void md_only_test_destruct(grpc_call_credentials *creds) {
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
grpc_credentials_md_store_unref(c->md_store);
}
static int md_only_test_has_request_metadata(const grpc_credentials *creds) {
return 1;
}
static int md_only_test_has_request_metadata_only(
const grpc_credentials *creds) {
return 1;
}
static void on_simulated_token_fetch_done(void *user_data) {
grpc_credentials_metadata_request *r =
(grpc_credentials_metadata_request *)user_data;
@ -826,9 +804,12 @@ static void on_simulated_token_fetch_done(void *user_data) {
grpc_exec_ctx_finish(&exec_ctx);
}
static void md_only_test_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
static void md_only_test_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
if (c->is_async) {
@ -841,18 +822,15 @@ static void md_only_test_get_request_metadata(
}
}
static grpc_credentials_vtable md_only_test_vtable = {
md_only_test_destruct, md_only_test_has_request_metadata,
md_only_test_has_request_metadata_only, md_only_test_get_request_metadata,
NULL};
static grpc_call_credentials_vtable md_only_test_vtable = {
md_only_test_destruct, md_only_test_get_request_metadata};
grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
const char *md_value,
int is_async) {
grpc_call_credentials *grpc_md_only_test_credentials_create(
const char *md_key, const char *md_value, int is_async) {
grpc_md_only_test_credentials *c =
gpr_malloc(sizeof(grpc_md_only_test_credentials));
memset(c, 0, sizeof(grpc_md_only_test_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
c->base.vtable = &md_only_test_vtable;
gpr_ref_init(&c->base.refcount, 1);
c->md_store = grpc_credentials_md_store_create(1);
@ -863,34 +841,26 @@ grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
/* -- Oauth2 Access Token credentials. -- */
static void access_token_destruct(grpc_credentials *creds) {
static void access_token_destruct(grpc_call_credentials *creds) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
grpc_credentials_md_store_unref(c->access_token_md);
}
static int access_token_has_request_metadata(const grpc_credentials *creds) {
return 1;
}
static int access_token_has_request_metadata_only(
const grpc_credentials *creds) {
return 1;
}
static void access_token_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
static void access_token_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
cb(exec_ctx, user_data, c->access_token_md->entries, 1, GRPC_CREDENTIALS_OK);
}
static grpc_credentials_vtable access_token_vtable = {
access_token_destruct, access_token_has_request_metadata,
access_token_has_request_metadata_only, access_token_get_request_metadata,
NULL};
static grpc_call_credentials_vtable access_token_vtable = {
access_token_destruct, access_token_get_request_metadata};
grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
void *reserved) {
grpc_call_credentials *grpc_access_token_credentials_create(
const char *access_token, void *reserved) {
grpc_access_token_credentials *c =
gpr_malloc(sizeof(grpc_access_token_credentials));
char *token_md_value;
@ -900,7 +870,7 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
2, (access_token, reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_access_token_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2;
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
c->base.vtable = &access_token_vtable;
gpr_ref_init(&c->base.refcount, 1);
c->access_token_md = grpc_credentials_md_store_create(1);
@ -913,31 +883,11 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
/* -- Fake transport security credentials. -- */
static void fake_transport_security_credentials_destruct(
grpc_credentials *creds) {
/* Nothing to do here. */
}
static void fake_transport_security_server_credentials_destruct(
grpc_server_credentials *creds) {
/* Nothing to do here. */
}
static int fake_transport_security_has_request_metadata(
const grpc_credentials *creds) {
return 0;
}
static int fake_transport_security_has_request_metadata_only(
const grpc_credentials *creds) {
return 0;
}
static grpc_security_status fake_transport_security_create_security_connector(
grpc_credentials *c, const char *target, const grpc_channel_args *args,
grpc_credentials *request_metadata_creds,
grpc_channel_credentials *c, grpc_call_credentials *call_creds,
const char *target, const grpc_channel_args *args,
grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
*sc = grpc_fake_channel_security_connector_create(request_metadata_creds, 1);
*sc = grpc_fake_channel_security_connector_create(call_creds, 1);
return GRPC_SECURITY_OK;
}
@ -948,21 +898,19 @@ fake_transport_security_server_create_security_connector(
return GRPC_SECURITY_OK;
}
static grpc_credentials_vtable fake_transport_security_credentials_vtable = {
fake_transport_security_credentials_destruct,
fake_transport_security_has_request_metadata,
fake_transport_security_has_request_metadata_only, NULL,
fake_transport_security_create_security_connector};
static grpc_channel_credentials_vtable
fake_transport_security_credentials_vtable = {
NULL, fake_transport_security_create_security_connector};
static grpc_server_credentials_vtable
fake_transport_security_server_credentials_vtable = {
fake_transport_security_server_credentials_destruct,
fake_transport_security_server_create_security_connector};
NULL, fake_transport_security_server_create_security_connector};
grpc_credentials *grpc_fake_transport_security_credentials_create(void) {
grpc_credentials *c = gpr_malloc(sizeof(grpc_credentials));
memset(c, 0, sizeof(grpc_credentials));
c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
grpc_channel_credentials *grpc_fake_transport_security_credentials_create(
void) {
grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials));
memset(c, 0, sizeof(grpc_channel_credentials));
c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
c->vtable = &fake_transport_security_credentials_vtable;
gpr_ref_init(&c->refcount, 1);
return c;
@ -972,69 +920,46 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
void) {
grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
memset(c, 0, sizeof(grpc_server_credentials));
c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
gpr_ref_init(&c->refcount, 1);
c->vtable = &fake_transport_security_server_credentials_vtable;
return c;
}
/* -- Composite credentials. -- */
/* -- Composite call credentials. -- */
typedef struct {
grpc_composite_credentials *composite_creds;
grpc_composite_call_credentials *composite_creds;
size_t creds_index;
grpc_credentials_md_store *md_elems;
char *service_url;
void *user_data;
grpc_pollset *pollset;
grpc_credentials_metadata_cb cb;
} grpc_composite_credentials_metadata_context;
} grpc_composite_call_credentials_metadata_context;
static void composite_destruct(grpc_credentials *creds) {
grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
static void composite_call_destruct(grpc_call_credentials *creds) {
grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
size_t i;
for (i = 0; i < c->inner.num_creds; i++) {
grpc_credentials_unref(c->inner.creds_array[i]);
grpc_call_credentials_unref(c->inner.creds_array[i]);
}
gpr_free(c->inner.creds_array);
}
static int composite_has_request_metadata(const grpc_credentials *creds) {
const grpc_composite_credentials *c =
(const grpc_composite_credentials *)creds;
size_t i;
for (i = 0; i < c->inner.num_creds; i++) {
if (grpc_credentials_has_request_metadata(c->inner.creds_array[i])) {
return 1;
}
}
return 0;
}
static int composite_has_request_metadata_only(const grpc_credentials *creds) {
const grpc_composite_credentials *c =
(const grpc_composite_credentials *)creds;
size_t i;
for (i = 0; i < c->inner.num_creds; i++) {
if (!grpc_credentials_has_request_metadata_only(c->inner.creds_array[i])) {
return 0;
}
}
return 1;
}
static void composite_md_context_destroy(
grpc_composite_credentials_metadata_context *ctx) {
static void composite_call_md_context_destroy(
grpc_composite_call_credentials_metadata_context *ctx) {
grpc_credentials_md_store_unref(ctx->md_elems);
if (ctx->service_url != NULL) gpr_free(ctx->service_url);
gpr_free(ctx);
}
static void composite_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_credentials_md *md_elems, size_t num_md,
grpc_credentials_status status) {
grpc_composite_credentials_metadata_context *ctx =
(grpc_composite_credentials_metadata_context *)user_data;
static void composite_call_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_credentials_md *md_elems,
size_t num_md,
grpc_credentials_status status) {
grpc_composite_call_credentials_metadata_context *ctx =
(grpc_composite_call_credentials_metadata_context *)user_data;
if (status != GRPC_CREDENTIALS_OK) {
ctx->cb(exec_ctx, ctx->user_data, NULL, 0, status);
return;
@ -1050,158 +975,114 @@ static void composite_metadata_cb(grpc_exec_ctx *exec_ctx, void *user_data,
}
/* See if we need to get some more metadata. */
while (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
grpc_credentials *inner_creds =
if (ctx->creds_index < ctx->composite_creds->inner.num_creds) {
grpc_call_credentials *inner_creds =
ctx->composite_creds->inner.creds_array[ctx->creds_index++];
if (grpc_credentials_has_request_metadata(inner_creds)) {
grpc_credentials_get_request_metadata(exec_ctx, inner_creds, ctx->pollset,
ctx->service_url,
composite_metadata_cb, ctx);
return;
}
grpc_call_credentials_get_request_metadata(exec_ctx, inner_creds,
ctx->pollset, ctx->service_url,
composite_call_metadata_cb, ctx);
return;
}
/* We're done!. */
ctx->cb(exec_ctx, ctx->user_data, ctx->md_elems->entries,
ctx->md_elems->num_entries, GRPC_CREDENTIALS_OK);
composite_md_context_destroy(ctx);
composite_call_md_context_destroy(ctx);
}
static void composite_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
grpc_composite_credentials_metadata_context *ctx;
if (!grpc_credentials_has_request_metadata(creds)) {
cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK);
return;
}
ctx = gpr_malloc(sizeof(grpc_composite_credentials_metadata_context));
memset(ctx, 0, sizeof(grpc_composite_credentials_metadata_context));
static void composite_call_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
grpc_composite_call_credentials_metadata_context *ctx;
ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
ctx->service_url = gpr_strdup(service_url);
ctx->user_data = user_data;
ctx->cb = cb;
ctx->composite_creds = c;
ctx->pollset = pollset;
ctx->md_elems = grpc_credentials_md_store_create(c->inner.num_creds);
while (ctx->creds_index < c->inner.num_creds) {
grpc_credentials *inner_creds = c->inner.creds_array[ctx->creds_index++];
if (grpc_credentials_has_request_metadata(inner_creds)) {
grpc_credentials_get_request_metadata(exec_ctx, inner_creds, pollset,
service_url, composite_metadata_cb,
ctx);
return;
}
}
GPR_ASSERT(0); /* Should have exited before. */
}
static grpc_security_status composite_create_security_connector(
grpc_credentials *creds, const char *target, const grpc_channel_args *args,
grpc_credentials *request_metadata_creds,
grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
if (c->connector_creds == NULL) {
gpr_log(GPR_ERROR,
"Cannot create security connector, missing connector credentials.");
return GRPC_SECURITY_ERROR;
}
return grpc_credentials_create_security_connector(c->connector_creds, target,
args, creds, sc, new_args);
grpc_call_credentials_get_request_metadata(
exec_ctx, c->inner.creds_array[ctx->creds_index++], pollset, service_url,
composite_call_metadata_cb, ctx);
}
static grpc_credentials_vtable composite_credentials_vtable = {
composite_destruct, composite_has_request_metadata,
composite_has_request_metadata_only, composite_get_request_metadata,
composite_create_security_connector};
static grpc_call_credentials_vtable composite_call_credentials_vtable = {
composite_call_destruct, composite_call_get_request_metadata};
static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) {
grpc_credentials_array result;
grpc_credentials *creds = *creds_addr;
static grpc_call_credentials_array get_creds_array(
grpc_call_credentials **creds_addr) {
grpc_call_credentials_array result;
grpc_call_credentials *creds = *creds_addr;
result.creds_array = creds_addr;
result.num_creds = 1;
if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
result = *grpc_composite_credentials_get_credentials(creds);
if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
result = *grpc_composite_call_credentials_get_credentials(creds);
}
return result;
}
grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1,
grpc_credentials *creds2,
void *reserved) {
grpc_call_credentials *grpc_composite_call_credentials_create(
grpc_call_credentials *creds1, grpc_call_credentials *creds2,
void *reserved) {
size_t i;
size_t creds_array_byte_size;
grpc_credentials_array creds1_array;
grpc_credentials_array creds2_array;
grpc_composite_credentials *c;
grpc_call_credentials_array creds1_array;
grpc_call_credentials_array creds2_array;
grpc_composite_call_credentials *c;
GRPC_API_TRACE(
"grpc_composite_credentials_create(creds1=%p, creds2=%p, "
"grpc_composite_call_credentials_create(creds1=%p, creds2=%p, "
"reserved=%p)",
3, (creds1, creds2, reserved));
GPR_ASSERT(reserved == NULL);
GPR_ASSERT(creds1 != NULL);
GPR_ASSERT(creds2 != NULL);
c = gpr_malloc(sizeof(grpc_composite_credentials));
memset(c, 0, sizeof(grpc_composite_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_COMPOSITE;
c->base.vtable = &composite_credentials_vtable;
c = gpr_malloc(sizeof(grpc_composite_call_credentials));
memset(c, 0, sizeof(grpc_composite_call_credentials));
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
c->base.vtable = &composite_call_credentials_vtable;
gpr_ref_init(&c->base.refcount, 1);
creds1_array = get_creds_array(&creds1);
creds2_array = get_creds_array(&creds2);
c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
creds_array_byte_size = c->inner.num_creds * sizeof(grpc_credentials *);
creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *);
c->inner.creds_array = gpr_malloc(creds_array_byte_size);
memset(c->inner.creds_array, 0, creds_array_byte_size);
for (i = 0; i < creds1_array.num_creds; i++) {
grpc_credentials *cur_creds = creds1_array.creds_array[i];
if (!grpc_credentials_has_request_metadata_only(cur_creds)) {
if (c->connector_creds == NULL) {
c->connector_creds = cur_creds;
} else {
gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials.");
goto fail;
}
}
c->inner.creds_array[i] = grpc_credentials_ref(cur_creds);
grpc_call_credentials *cur_creds = creds1_array.creds_array[i];
c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
}
for (i = 0; i < creds2_array.num_creds; i++) {
grpc_credentials *cur_creds = creds2_array.creds_array[i];
if (!grpc_credentials_has_request_metadata_only(cur_creds)) {
if (c->connector_creds == NULL) {
c->connector_creds = cur_creds;
} else {
gpr_log(GPR_ERROR, "Cannot compose multiple connector credentials.");
goto fail;
}
}
grpc_call_credentials *cur_creds = creds2_array.creds_array[i];
c->inner.creds_array[i + creds1_array.num_creds] =
grpc_credentials_ref(cur_creds);
grpc_call_credentials_ref(cur_creds);
}
return &c->base;
fail:
grpc_credentials_unref(&c->base);
return NULL;
}
const grpc_credentials_array *grpc_composite_credentials_get_credentials(
grpc_credentials *creds) {
const grpc_composite_credentials *c =
(const grpc_composite_credentials *)creds;
GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0);
const grpc_call_credentials_array *
grpc_composite_call_credentials_get_credentials(grpc_call_credentials *creds) {
const grpc_composite_call_credentials *c =
(const grpc_composite_call_credentials *)creds;
GPR_ASSERT(strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0);
return &c->inner;
}
grpc_credentials *grpc_credentials_contains_type(
grpc_credentials *creds, const char *type,
grpc_credentials **composite_creds) {
grpc_call_credentials *grpc_credentials_contains_type(
grpc_call_credentials *creds, const char *type,
grpc_call_credentials **composite_creds) {
size_t i;
if (strcmp(creds->type, type) == 0) {
if (composite_creds != NULL) *composite_creds = NULL;
return creds;
} else if (strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0) {
const grpc_credentials_array *inner_creds_array =
grpc_composite_credentials_get_credentials(creds);
} else if (strcmp(creds->type, GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE) == 0) {
const grpc_call_credentials_array *inner_creds_array =
grpc_composite_call_credentials_get_credentials(creds);
for (i = 0; i < inner_creds_array->num_creds; i++) {
if (strcmp(type, inner_creds_array->creds_array[i]->type) == 0) {
if (composite_creds != NULL) *composite_creds = creds;
@ -1214,30 +1095,26 @@ grpc_credentials *grpc_credentials_contains_type(
/* -- IAM credentials. -- */
static void iam_destruct(grpc_credentials *creds) {
static void iam_destruct(grpc_call_credentials *creds) {
grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
grpc_credentials_md_store_unref(c->iam_md);
}
static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; }
static int iam_has_request_metadata_only(const grpc_credentials *creds) {
return 1;
}
static void iam_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
static void iam_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
cb(exec_ctx, user_data, c->iam_md->entries, c->iam_md->num_entries,
GRPC_CREDENTIALS_OK);
}
static grpc_credentials_vtable iam_vtable = {
iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only,
iam_get_request_metadata, NULL};
static grpc_call_credentials_vtable iam_vtable = {iam_destruct,
iam_get_request_metadata};
grpc_credentials *grpc_google_iam_credentials_create(
grpc_call_credentials *grpc_google_iam_credentials_create(
const char *token, const char *authority_selector, void *reserved) {
grpc_google_iam_credentials *c;
GRPC_API_TRACE(
@ -1249,7 +1126,7 @@ grpc_credentials *grpc_google_iam_credentials_create(
GPR_ASSERT(authority_selector != NULL);
c = gpr_malloc(sizeof(grpc_google_iam_credentials));
memset(c, 0, sizeof(grpc_google_iam_credentials));
c->base.type = GRPC_CREDENTIALS_TYPE_IAM;
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
c->base.vtable = &iam_vtable;
gpr_ref_init(&c->base.refcount, 1);
c->iam_md = grpc_credentials_md_store_create(2);
@ -1267,21 +1144,13 @@ typedef struct {
grpc_credentials_metadata_cb cb;
} grpc_metadata_plugin_request;
static void plugin_destruct(grpc_credentials *creds) {
static void plugin_destruct(grpc_call_credentials *creds) {
grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
c->plugin.destroy(c->plugin.state);
}
}
static int plugin_has_request_metadata(const grpc_credentials *creds) {
return 1;
}
static int plugin_has_request_metadata_only(const grpc_credentials *creds) {
return 1;
}
static void plugin_md_request_metadata_ready(void *request,
const grpc_metadata *md,
size_t num_md,
@ -1320,9 +1189,12 @@ static void plugin_md_request_metadata_ready(void *request,
grpc_exec_ctx_finish(&exec_ctx);
}
static void plugin_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) {
static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
if (c->plugin.get_metadata != NULL) {
grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
@ -1336,18 +1208,75 @@ static void plugin_get_request_metadata(
}
}
static grpc_credentials_vtable plugin_vtable = {
plugin_destruct, plugin_has_request_metadata,
plugin_has_request_metadata_only, plugin_get_request_metadata, NULL};
static grpc_call_credentials_vtable plugin_vtable = {
plugin_destruct, plugin_get_request_metadata};
grpc_credentials *grpc_metadata_credentials_create_from_plugin(
grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
grpc_metadata_credentials_plugin plugin, void *reserved) {
grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1,
(reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(*c));
c->base.type = GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN;
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN;
c->base.vtable = &plugin_vtable;
gpr_ref_init(&c->base.refcount, 1);
c->plugin = plugin;
return &c->base;
}
/* -- Composite channel credentials. -- */
static void composite_channel_destruct(grpc_channel_credentials *creds) {
grpc_composite_channel_credentials *c =
(grpc_composite_channel_credentials *)creds;
grpc_channel_credentials_unref(c->inner_creds);
grpc_call_credentials_unref(c->call_creds);
}
static grpc_security_status composite_channel_create_security_connector(
grpc_channel_credentials *creds, grpc_call_credentials *call_creds,
const char *target, const grpc_channel_args *args,
grpc_channel_security_connector **sc, grpc_channel_args **new_args) {
grpc_composite_channel_credentials *c =
(grpc_composite_channel_credentials *)creds;
grpc_security_status status = GRPC_SECURITY_ERROR;
GPR_ASSERT(c->inner_creds != NULL && c->call_creds != NULL &&
c->inner_creds->vtable != NULL &&
c->inner_creds->vtable->create_security_connector != NULL);
/* If we are passed a call_creds, create a call composite to pass it
downstream. */
if (call_creds != NULL) {
grpc_call_credentials *composite_call_creds =
grpc_composite_call_credentials_create(c->call_creds, call_creds, NULL);
status = c->inner_creds->vtable->create_security_connector(
c->inner_creds, composite_call_creds, target, args, sc, new_args);
grpc_call_credentials_unref(composite_call_creds);
} else {
status = c->inner_creds->vtable->create_security_connector(
c->inner_creds, c->call_creds, target, args, sc, new_args);
}
return status;
}
static grpc_channel_credentials_vtable composite_channel_credentials_vtable = {
composite_channel_destruct, composite_channel_create_security_connector};
grpc_channel_credentials *grpc_composite_channel_credentials_create(
grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
void *reserved) {
grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c));
memset(c, 0, sizeof(*c));
GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL);
GRPC_API_TRACE(
"grpc_composite_channel_credentials_create(channel_creds=%p, "
"call_creds=%p, reserved=%p)",
3, (channel_creds, call_creds, reserved));
c->base.type = channel_creds->type;
c->base.vtable = &composite_channel_credentials_vtable;
gpr_ref_init(&c->base.refcount, 1);
c->inner_creds = grpc_channel_credentials_ref(channel_creds);
c->call_creds = grpc_call_credentials_ref(call_creds);
return &c->base;
}

@ -54,15 +54,17 @@ typedef enum {
#define GRPC_FAKE_TRANSPORT_SECURITY_TYPE "fake"
#define GRPC_CREDENTIALS_TYPE_SSL "Ssl"
#define GRPC_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
#define GRPC_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
#define GRPC_CREDENTIALS_TYPE_JWT "Jwt"
#define GRPC_CREDENTIALS_TYPE_IAM "Iam"
#define GRPC_CREDENTIALS_TYPE_COMPOSITE "Composite"
#define GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY "FakeTransportSecurity"
#define GRPC_AUTHORIZATION_METADATA_KEY "Authorization"
#define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl"
#define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \
"FakeTransportSecurity"
#define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
#define GRPC_CALL_CREDENTIALS_TYPE_METADATA_PLUGIN "Plugin"
#define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
#define GRPC_CALL_CREDENTIALS_TYPE_IAM "Iam"
#define GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE "Composite"
#define GRPC_AUTHORIZATION_METADATA_KEY "authorization"
#define GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY \
"x-goog-iam-authorization-token"
#define GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY "x-goog-iam-authority-selector"
@ -87,6 +89,41 @@ typedef enum {
#define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \
"client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token"
/* --- Google utils --- */
/* It is the caller's responsibility to gpr_free the result if not NULL. */
char *grpc_get_well_known_google_credentials_file_path(void);
/* --- grpc_channel_credentials. --- */
typedef struct {
void (*destruct)(grpc_channel_credentials *c);
grpc_security_status (*create_security_connector)(
grpc_channel_credentials *c, grpc_call_credentials *call_creds,
const char *target, const grpc_channel_args *args,
grpc_channel_security_connector **sc, grpc_channel_args **new_args);
} grpc_channel_credentials_vtable;
struct grpc_channel_credentials {
const grpc_channel_credentials_vtable *vtable;
const char *type;
gpr_refcount refcount;
};
grpc_channel_credentials *grpc_channel_credentials_ref(
grpc_channel_credentials *creds);
void grpc_channel_credentials_unref(grpc_channel_credentials *creds);
/* Creates a security connector for the channel. May also create new channel
args for the channel to be used in place of the passed in const args if
returned non NULL. In that case the caller is responsible for destroying
new_args after channel creation. */
grpc_security_status grpc_channel_credentials_create_security_connector(
grpc_channel_credentials *creds, const char *target,
const grpc_channel_args *args, grpc_channel_security_connector **sc,
grpc_channel_args **new_args);
/* --- grpc_credentials_md. --- */
typedef struct {
@ -113,16 +150,7 @@ grpc_credentials_md_store *grpc_credentials_md_store_ref(
grpc_credentials_md_store *store);
void grpc_credentials_md_store_unref(grpc_credentials_md_store *store);
/* --- grpc_credentials. --- */
/* Creates a fake transport security credentials object for testing. */
grpc_credentials *grpc_fake_transport_security_credentials_create(void);
/* Creates a fake server transport security credentials object for testing. */
grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
void);
/* It is the caller's responsibility to gpr_free the result if not NULL. */
char *grpc_get_well_known_google_credentials_file_path(void);
/* --- grpc_call_credentials. --- */
typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx,
void *user_data,
@ -131,57 +159,45 @@ typedef void (*grpc_credentials_metadata_cb)(grpc_exec_ctx *exec_ctx,
grpc_credentials_status status);
typedef struct {
void (*destruct)(grpc_credentials *c);
int (*has_request_metadata)(const grpc_credentials *c);
int (*has_request_metadata_only)(const grpc_credentials *c);
void (*get_request_metadata)(grpc_exec_ctx *exec_ctx, grpc_credentials *c,
grpc_pollset *pollset, const char *service_url,
void (*destruct)(grpc_call_credentials *c);
void (*get_request_metadata)(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *c, grpc_pollset *pollset,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data);
grpc_security_status (*create_security_connector)(
grpc_credentials *c, const char *target, const grpc_channel_args *args,
grpc_credentials *request_metadata_creds,
grpc_channel_security_connector **sc, grpc_channel_args **new_args);
} grpc_credentials_vtable;
} grpc_call_credentials_vtable;
struct grpc_credentials {
const grpc_credentials_vtable *vtable;
struct grpc_call_credentials {
const grpc_call_credentials_vtable *vtable;
const char *type;
gpr_refcount refcount;
};
grpc_credentials *grpc_credentials_ref(grpc_credentials *creds);
void grpc_credentials_unref(grpc_credentials *creds);
int grpc_credentials_has_request_metadata(grpc_credentials *creds);
int grpc_credentials_has_request_metadata_only(grpc_credentials *creds);
void grpc_credentials_get_request_metadata(
grpc_exec_ctx *exec_ctx, grpc_credentials *creds, grpc_pollset *pollset,
const char *service_url, grpc_credentials_metadata_cb cb, void *user_data);
/* Creates a security connector for the channel. May also create new channel
args for the channel to be used in place of the passed in const args if
returned non NULL. In that case the caller is responsible for destroying
new_args after channel creation. */
grpc_security_status grpc_credentials_create_security_connector(
grpc_credentials *creds, const char *target, const grpc_channel_args *args,
grpc_credentials *request_metadata_creds,
grpc_channel_security_connector **sc, grpc_channel_args **new_args);
grpc_call_credentials *grpc_call_credentials_ref(grpc_call_credentials *creds);
void grpc_call_credentials_unref(grpc_call_credentials *creds);
void grpc_call_credentials_get_request_metadata(grpc_exec_ctx *exec_ctx,
grpc_call_credentials *creds,
grpc_pollset *pollset,
const char *service_url,
grpc_credentials_metadata_cb cb,
void *user_data);
typedef struct {
grpc_credentials **creds_array;
grpc_call_credentials **creds_array;
size_t num_creds;
} grpc_credentials_array;
} grpc_call_credentials_array;
const grpc_credentials_array *grpc_composite_credentials_get_credentials(
grpc_credentials *composite_creds);
const grpc_call_credentials_array *
grpc_composite_call_credentials_get_credentials(
grpc_call_credentials *composite_creds);
/* Returns creds if creds is of the specified type or the inner creds of the
specified type (if found), if the creds is of type COMPOSITE.
If composite_creds is not NULL, *composite_creds will point to creds if of
type COMPOSITE in case of success. */
grpc_credentials *grpc_credentials_contains_type(
grpc_credentials *creds, const char *type,
grpc_credentials **composite_creds);
grpc_call_credentials *grpc_credentials_contains_type(
grpc_call_credentials *creds, const char *type,
grpc_call_credentials **composite_creds);
/* Exposed for testing only. */
grpc_credentials_status
@ -192,19 +208,19 @@ void grpc_flush_cached_google_default_credentials(void);
/* Metadata-only credentials with the specified key and value where
asynchronicity can be simulated for testing. */
grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
const char *md_value,
int is_async);
grpc_call_credentials *grpc_md_only_test_credentials_create(
const char *md_key, const char *md_value, int is_async);
/* Private constructor for jwt credentials from an already parsed json key.
Takes ownership of the key. */
grpc_credentials *
grpc_call_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
refresh token. Takes ownership of the refresh token. */
grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_call_credentials *
grpc_refresh_token_credentials_create_from_auth_refresh_token(
grpc_auth_refresh_token token);
/* --- grpc_server_credentials. --- */
@ -237,10 +253,18 @@ grpc_server_credentials *grpc_server_credentials_from_arg(const grpc_arg *arg);
grpc_server_credentials *grpc_find_server_credentials_in_args(
const grpc_channel_args *args);
/* -- Fake transport security credentials. -- */
/* Creates a fake transport security credentials object for testing. */
grpc_channel_credentials *grpc_fake_transport_security_credentials_create(void);
/* Creates a fake server transport security credentials object for testing. */
grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
void);
/* -- Ssl credentials. -- */
typedef struct {
grpc_credentials base;
grpc_channel_credentials base;
grpc_ssl_config config;
} grpc_ssl_credentials;
@ -249,10 +273,18 @@ typedef struct {
grpc_ssl_server_config config;
} grpc_ssl_server_credentials;
/* -- Channel composite credentials. -- */
typedef struct {
grpc_channel_credentials base;
grpc_channel_credentials *inner_creds;
grpc_call_credentials *call_creds;
} grpc_composite_channel_credentials;
/* -- Jwt credentials -- */
typedef struct {
grpc_credentials base;
grpc_call_credentials base;
/* Have a simple cache for now with just 1 entry. We could have a map based on
the service_url for a more sophisticated one. */
@ -283,7 +315,7 @@ typedef void (*grpc_fetch_oauth2_func)(grpc_exec_ctx *exec_ctx,
gpr_timespec deadline);
typedef struct {
grpc_credentials base;
grpc_call_credentials base;
gpr_mu mu;
grpc_credentials_md_store *access_token_md;
gpr_timespec token_expiration;
@ -301,14 +333,14 @@ typedef struct {
/* -- Oauth2 Access Token credentials. -- */
typedef struct {
grpc_credentials base;
grpc_call_credentials base;
grpc_credentials_md_store *access_token_md;
} grpc_access_token_credentials;
/* -- Metadata-only Test credentials. -- */
typedef struct {
grpc_credentials base;
grpc_call_credentials base;
grpc_credentials_md_store *md_store;
int is_async;
} grpc_md_only_test_credentials;
@ -316,22 +348,21 @@ typedef struct {
/* -- GoogleIAM credentials. -- */
typedef struct {
grpc_credentials base;
grpc_call_credentials base;
grpc_credentials_md_store *iam_md;
} grpc_google_iam_credentials;
/* -- Composite credentials. -- */
typedef struct {
grpc_credentials base;
grpc_credentials_array inner;
grpc_credentials *connector_creds;
} grpc_composite_credentials;
grpc_call_credentials base;
grpc_call_credentials_array inner;
} grpc_composite_call_credentials;
/* -- Plugin credentials. -- */
typedef struct {
grpc_credentials base;
grpc_call_credentials base;
grpc_metadata_credentials_plugin plugin;
grpc_credentials_md_store *plugin_md;
} grpc_plugin_credentials;

@ -50,7 +50,7 @@
/* -- Default credentials. -- */
static grpc_credentials *default_credentials = NULL;
static grpc_channel_credentials *default_credentials = NULL;
static int compute_engine_detection_done = 0;
static gpr_mu g_mu;
static gpr_once g_once = GPR_ONCE_INIT;
@ -138,11 +138,11 @@ static int is_stack_running_on_compute_engine(void) {
}
/* Takes ownership of creds_path if not NULL. */
static grpc_credentials *create_default_creds_from_path(char *creds_path) {
static grpc_call_credentials *create_default_creds_from_path(char *creds_path) {
grpc_json *json = NULL;
grpc_auth_json_key key;
grpc_auth_refresh_token token;
grpc_credentials *result = NULL;
grpc_call_credentials *result = NULL;
gpr_slice creds_data = gpr_empty_slice();
int file_ok = 0;
if (creds_path == NULL) goto end;
@ -176,9 +176,9 @@ end:
return result;
}
grpc_credentials *grpc_google_default_credentials_create(void) {
grpc_credentials *result = NULL;
int serving_cached_credentials = 0;
grpc_channel_credentials *grpc_google_default_credentials_create(void) {
grpc_channel_credentials *result = NULL;
grpc_call_credentials *call_creds = NULL;
GRPC_API_TRACE("grpc_google_default_credentials_create(void)", 0, ());
@ -187,20 +187,19 @@ grpc_credentials *grpc_google_default_credentials_create(void) {
gpr_mu_lock(&g_mu);
if (default_credentials != NULL) {
result = grpc_credentials_ref(default_credentials);
serving_cached_credentials = 1;
result = grpc_channel_credentials_ref(default_credentials);
goto end;
}
/* First, try the environment variable. */
result = create_default_creds_from_path(
call_creds = create_default_creds_from_path(
gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR));
if (result != NULL) goto end;
if (call_creds != NULL) goto end;
/* Then the well-known file. */
result = create_default_creds_from_path(
call_creds = create_default_creds_from_path(
grpc_get_well_known_google_credentials_file_path());
if (result != NULL) goto end;
if (call_creds != NULL) goto end;
/* At last try to see if we're on compute engine (do the detection only once
since it requires a network test). */
@ -208,21 +207,28 @@ grpc_credentials *grpc_google_default_credentials_create(void) {
int need_compute_engine_creds = is_stack_running_on_compute_engine();
compute_engine_detection_done = 1;
if (need_compute_engine_creds) {
result = grpc_google_compute_engine_credentials_create(NULL);
call_creds = grpc_google_compute_engine_credentials_create(NULL);
}
}
end:
if (!serving_cached_credentials && result != NULL) {
/* Blend with default ssl credentials and add a global reference so that it
can be cached and re-served. */
grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL);
default_credentials = grpc_credentials_ref(
grpc_composite_credentials_create(ssl_creds, result, NULL));
GPR_ASSERT(default_credentials != NULL);
grpc_credentials_unref(ssl_creds);
grpc_credentials_unref(result);
result = default_credentials;
if (result == NULL) {
if (call_creds != NULL) {
/* Blend with default ssl credentials and add a global reference so that
it
can be cached and re-served. */
grpc_channel_credentials *ssl_creds =
grpc_ssl_credentials_create(NULL, NULL, NULL);
default_credentials = grpc_channel_credentials_ref(
grpc_composite_channel_credentials_create(ssl_creds, call_creds,
NULL));
GPR_ASSERT(default_credentials != NULL);
grpc_channel_credentials_unref(ssl_creds);
grpc_call_credentials_unref(call_creds);
result = default_credentials;
} else {
gpr_log(GPR_ERROR, "Could not create google default credentials.");
}
}
gpr_mu_unlock(&g_mu);
return result;
@ -232,7 +238,7 @@ void grpc_flush_cached_google_default_credentials(void) {
gpr_once_init(&g_once, init_default_credentials);
gpr_mu_lock(&g_mu);
if (default_credentials != NULL) {
grpc_credentials_unref(default_credentials);
grpc_channel_credentials_unref(default_credentials);
default_credentials = NULL;
}
gpr_mu_unlock(&g_mu);

@ -203,16 +203,6 @@ grpc_security_connector *grpc_find_security_connector_in_args(
return NULL;
}
static int check_request_metadata_creds(grpc_credentials *creds) {
if (creds != NULL && !grpc_credentials_has_request_metadata(creds)) {
gpr_log(GPR_ERROR,
"Incompatible credentials for channel security connector: needs to "
"set request metadata.");
return 0;
}
return 1;
}
/* -- Fake implementation. -- */
typedef struct {
@ -222,7 +212,7 @@ typedef struct {
static void fake_channel_destroy(grpc_security_connector *sc) {
grpc_channel_security_connector *c = (grpc_channel_security_connector *)sc;
grpc_credentials_unref(c->request_metadata_creds);
grpc_call_credentials_unref(c->request_metadata_creds);
GRPC_AUTH_CONTEXT_UNREF(sc->auth_context, "connector");
gpr_free(sc);
}
@ -306,7 +296,8 @@ static grpc_security_connector_vtable fake_server_vtable = {
fake_server_destroy, fake_server_do_handshake, fake_check_peer};
grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
grpc_credentials *request_metadata_creds, int call_host_check_is_async) {
grpc_call_credentials *request_metadata_creds,
int call_host_check_is_async) {
grpc_fake_channel_security_connector *c =
gpr_malloc(sizeof(grpc_fake_channel_security_connector));
memset(c, 0, sizeof(grpc_fake_channel_security_connector));
@ -314,8 +305,8 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
c->base.base.is_client_side = 1;
c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
c->base.base.vtable = &fake_channel_vtable;
GPR_ASSERT(check_request_metadata_creds(request_metadata_creds));
c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
c->base.request_metadata_creds =
grpc_call_credentials_ref(request_metadata_creds);
c->base.check_call_host = fake_channel_check_call_host;
c->call_host_check_is_async = call_host_check_is_async;
return &c->base;
@ -349,7 +340,7 @@ typedef struct {
static void ssl_channel_destroy(grpc_security_connector *sc) {
grpc_ssl_channel_security_connector *c =
(grpc_ssl_channel_security_connector *)sc;
grpc_credentials_unref(c->base.request_metadata_creds);
grpc_call_credentials_unref(c->base.request_metadata_creds);
if (c->handshaker_factory != NULL) {
tsi_ssl_handshaker_factory_destroy(c->handshaker_factory);
}
@ -580,9 +571,9 @@ size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) {
}
grpc_security_status grpc_ssl_channel_security_connector_create(
grpc_credentials *request_metadata_creds, const grpc_ssl_config *config,
const char *target_name, const char *overridden_target_name,
grpc_channel_security_connector **sc) {
grpc_call_credentials *request_metadata_creds,
const grpc_ssl_config *config, const char *target_name,
const char *overridden_target_name, grpc_channel_security_connector **sc) {
size_t num_alpn_protocols = grpc_chttp2_num_alpn_versions();
const unsigned char **alpn_protocol_strings =
gpr_malloc(sizeof(const char *) * num_alpn_protocols);
@ -606,9 +597,6 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
gpr_log(GPR_ERROR, "An ssl channel needs a config and a target name.");
goto error;
}
if (!check_request_metadata_creds(request_metadata_creds)) {
goto error;
}
if (config->pem_root_certs == NULL) {
pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
if (pem_root_certs == NULL || pem_root_certs_size == 0) {
@ -627,7 +615,8 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
c->base.base.vtable = &ssl_channel_vtable;
c->base.base.is_client_side = 1;
c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
c->base.request_metadata_creds = grpc_credentials_ref(request_metadata_creds);
c->base.request_metadata_creds =
grpc_call_credentials_ref(request_metadata_creds);
c->base.check_call_host = ssl_channel_check_call_host;
gpr_split_host_port(target_name, &c->target_name, &port);
gpr_free(port);

@ -145,7 +145,7 @@ typedef struct grpc_channel_security_connector grpc_channel_security_connector;
struct grpc_channel_security_connector {
grpc_security_connector base; /* requires is_client_side to be non 0. */
grpc_credentials *request_metadata_creds;
grpc_call_credentials *request_metadata_creds;
grpc_security_status (*check_call_host)(grpc_exec_ctx *exec_ctx,
grpc_channel_security_connector *sc,
const char *host,
@ -167,7 +167,8 @@ grpc_security_status grpc_channel_security_connector_check_call_host(
/* For TESTING ONLY!
Creates a fake connector that emulates real channel security. */
grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
grpc_credentials *request_metadata_creds, int call_host_check_is_async);
grpc_call_credentials *request_metadata_creds,
int call_host_check_is_async);
/* For TESTING ONLY!
Creates a fake connector that emulates real server security. */
@ -197,9 +198,9 @@ typedef struct {
specific error code otherwise.
*/
grpc_security_status grpc_ssl_channel_security_connector_create(
grpc_credentials *request_metadata_creds, const grpc_ssl_config *config,
const char *target_name, const char *overridden_target_name,
grpc_channel_security_connector **sc);
grpc_call_credentials *request_metadata_creds,
const grpc_ssl_config *config, const char *target_name,
const char *overridden_target_name, grpc_channel_security_connector **sc);
/* Gets the default ssl roots. */
size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs);

@ -46,7 +46,7 @@
/* --- grpc_call --- */
grpc_call_error grpc_call_set_credentials(grpc_call *call,
grpc_credentials *creds) {
grpc_call_credentials *creds) {
grpc_client_security_context *ctx = NULL;
GRPC_API_TRACE("grpc_call_set_credentials(call=%p, creds=%p)", 2,
(call, creds));
@ -54,20 +54,16 @@ grpc_call_error grpc_call_set_credentials(grpc_call *call,
gpr_log(GPR_ERROR, "Method is client-side only.");
return GRPC_CALL_ERROR_NOT_ON_SERVER;
}
if (creds != NULL && !grpc_credentials_has_request_metadata_only(creds)) {
gpr_log(GPR_ERROR, "Incompatible credentials to set on a call.");
return GRPC_CALL_ERROR;
}
ctx = (grpc_client_security_context *)grpc_call_context_get(
call, GRPC_CONTEXT_SECURITY);
if (ctx == NULL) {
ctx = grpc_client_security_context_create();
ctx->creds = grpc_credentials_ref(creds);
ctx->creds = grpc_call_credentials_ref(creds);
grpc_call_context_set(call, GRPC_CONTEXT_SECURITY, ctx,
grpc_client_security_context_destroy);
} else {
grpc_credentials_unref(ctx->creds);
ctx->creds = grpc_credentials_ref(creds);
grpc_call_credentials_unref(ctx->creds);
ctx->creds = grpc_call_credentials_ref(creds);
}
return GRPC_CALL_OK;
}
@ -101,7 +97,7 @@ grpc_client_security_context *grpc_client_security_context_create(void) {
void grpc_client_security_context_destroy(void *ctx) {
grpc_client_security_context *c = (grpc_client_security_context *)ctx;
grpc_credentials_unref(c->creds);
grpc_call_credentials_unref(c->creds);
GRPC_AUTH_CONTEXT_UNREF(c->auth_context, "client_security_context");
gpr_free(ctx);
}

@ -85,7 +85,7 @@ void grpc_auth_property_reset(grpc_auth_property *property);
Internal client-side security context. */
typedef struct {
grpc_credentials *creds;
grpc_call_credentials *creds;
grpc_auth_context *auth_context;
} grpc_client_security_context;

@ -249,9 +249,11 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
}
for (i = 0; i < resolved->naddrs; i++) {
port_temp = grpc_tcp_server_add_port(
grpc_tcp_listener *listener;
listener = grpc_tcp_server_add_port(
tcp, (struct sockaddr *)&resolved->addrs[i].addr,
resolved->addrs[i].len);
port_temp = grpc_tcp_listener_get_port(listener);
if (port_temp >= 0) {
if (port_num == -1) {
port_num = port_temp;

@ -220,7 +220,7 @@ void gpr_slice_buffer_move_first(gpr_slice_buffer *src, size_t n,
return;
}
src_idx = 0;
for (;;) {
while (src_idx < src->capacity) {
gpr_slice slice = src->slices[src_idx];
size_t slice_len = GPR_SLICE_LENGTH(slice);
if (n > slice_len) {

@ -66,14 +66,12 @@ gpr_timespec gpr_now(gpr_clock_type clock) {
now_tv.tv_nsec = now_tb.millitm * 1000000;
break;
case GPR_CLOCK_MONOTONIC:
case GPR_CLOCK_PRECISE:
QueryPerformanceCounter(&timestamp);
now_dbl = (timestamp.QuadPart - g_start_time.QuadPart) * g_time_scale;
now_tv.tv_sec = (time_t)now_dbl;
now_tv.tv_nsec = (int)((now_dbl - (double)now_tv.tv_sec) * 1e9);
break;
case GPR_CLOCK_PRECISE:
gpr_precise_clock_now(&now_tv);
break;
}
return now_tv;
}

@ -121,4 +121,3 @@ gpr_slice grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader) {
}
return out_slice;
}

@ -922,7 +922,8 @@ static batch_control *allocate_batch_control(grpc_call *call) {
size_t i;
for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) {
if ((call->used_batches & (1 << i)) == 0) {
call->used_batches |= (gpr_uint8)(1 << i);
call->used_batches =
(gpr_uint8)(call->used_batches | (gpr_uint8)(1 << i));
return &call->active_batches[i];
}
}

@ -230,7 +230,7 @@ static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
Asynchronously: - resolve target
- connect to it (trying alternatives as presented)
- perform handshakes */
grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
const char *target,
const grpc_channel_args *args,
void *reserved) {
@ -261,9 +261,9 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
"Security connector exists in channel args.");
}
if (grpc_credentials_create_security_connector(
creds, target, args, NULL, &security_connector,
&new_args_from_connector) != GRPC_SECURITY_OK) {
if (grpc_channel_credentials_create_security_connector(
creds, target, args, &security_connector, &new_args_from_connector) !=
GRPC_SECURITY_OK) {
grpc_exec_ctx_finish(&exec_ctx);
return grpc_lame_client_channel_create(
target, GRPC_STATUS_INVALID_ARGUMENT,

@ -107,9 +107,11 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
}
for (i = 0; i < resolved->naddrs; i++) {
port_temp = grpc_tcp_server_add_port(
grpc_tcp_listener *listener;
listener = grpc_tcp_server_add_port(
tcp, (struct sockaddr *)&resolved->addrs[i].addr,
resolved->addrs[i].len);
port_temp = grpc_tcp_listener_get_port(listener);
if (port_temp >= 0) {
if (port_num == -1) {
port_num = port_temp;

@ -36,4 +36,4 @@
#include <grpc/grpc.h>
const char *grpc_version_string(void) { return "0.11.0.0"; }
const char *grpc_version_string(void) { return "0.12.0.0"; }

@ -36,8 +36,10 @@
#include <assert.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
#include "src/core/transport/chttp2/bin_encoder.h"
#include "src/core/transport/chttp2/hpack_table.h"
#include "src/core/transport/chttp2/timeout_encoding.h"
@ -154,6 +156,18 @@ static gpr_uint8 *add_tiny_header_data(framer_state *st, size_t len) {
return gpr_slice_buffer_tiny_add(st->output, len);
}
static void evict_entry(grpc_chttp2_hpack_compressor *c) {
c->tail_remote_index++;
GPR_ASSERT(c->tail_remote_index > 0);
GPR_ASSERT(c->table_size >=
c->table_elem_size[c->tail_remote_index % c->cap_table_elems]);
GPR_ASSERT(c->table_elems > 0);
c->table_size = (gpr_uint16)(
c->table_size -
c->table_elem_size[c->tail_remote_index % c->cap_table_elems]);
c->table_elems--;
}
/* add an element to the decoder table */
static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem) {
gpr_uint32 key_hash = elem->key->hash;
@ -164,26 +178,21 @@ static void add_elem(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem) {
GPR_ASSERT(elem_size < 65536);
if (elem_size > c->max_table_size) {
while (c->table_size > 0) {
evict_entry(c);
}
return;
}
/* Reserve space for this element in the remote table: if this overflows
the current table, drop elements until it fits, matching the decompressor
algorithm */
/* TODO(ctiller): constant */
while (c->table_size + elem_size > 4096) {
c->tail_remote_index++;
GPR_ASSERT(c->tail_remote_index > 0);
GPR_ASSERT(c->table_size >=
c->table_elem_size[c->tail_remote_index %
GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS]);
GPR_ASSERT(c->table_elems > 0);
c->table_size =
(gpr_uint16)(c->table_size -
c->table_elem_size[c->tail_remote_index %
GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS]);
c->table_elems--;
while (c->table_size + elem_size > c->max_table_size) {
evict_entry(c);
}
GPR_ASSERT(c->table_elems < GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS);
c->table_elem_size[new_index % GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS] =
(gpr_uint16)elem_size;
GPR_ASSERT(c->table_elems < c->max_table_size);
c->table_elem_size[new_index % c->cap_table_elems] = (gpr_uint16)elem_size;
c->table_size = (gpr_uint16)(c->table_size + elem_size);
c->table_elems++;
@ -329,6 +338,14 @@ static void emit_lithdr_noidx_v(grpc_chttp2_hpack_compressor *c,
add_header_data(st, gpr_slice_ref(value_slice));
}
static void emit_advertise_table_size_change(grpc_chttp2_hpack_compressor *c,
framer_state *st) {
gpr_uint32 len = GRPC_CHTTP2_VARINT_LENGTH(c->max_table_size, 3);
GRPC_CHTTP2_WRITE_VARINT(c->max_table_size, 3, 0x20,
add_tiny_header_data(st, len), len);
c->advertise_table_size_change = 0;
}
static gpr_uint32 dynidx(grpc_chttp2_hpack_compressor *c,
gpr_uint32 elem_index) {
return 1 + GRPC_CHTTP2_LAST_STATIC_ENTRY + c->tail_remote_index +
@ -447,11 +464,23 @@ gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id) {
return slice;
}
static gpr_uint32 elems_for_bytes(gpr_uint32 bytes) {
return (bytes + 31) / 32;
}
void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c,
grpc_mdctx *ctx) {
memset(c, 0, sizeof(*c));
c->mdctx = ctx;
c->timeout_key_str = grpc_mdstr_from_string(ctx, "grpc-timeout");
c->max_table_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
c->cap_table_elems = elems_for_bytes(c->max_table_size);
c->max_table_elems = c->cap_table_elems;
c->max_usable_size = GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE;
c->table_elem_size =
gpr_malloc(sizeof(*c->table_elem_size) * c->cap_table_elems);
memset(c->table_elem_size, 0,
sizeof(*c->table_elem_size) * c->cap_table_elems);
}
void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
@ -461,6 +490,54 @@ void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
if (c->entries_elems[i]) GRPC_MDELEM_UNREF(c->entries_elems[i]);
}
GRPC_MDSTR_UNREF(c->timeout_key_str);
gpr_free(c->table_elem_size);
}
void grpc_chttp2_hpack_compressor_set_max_usable_size(
grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size) {
c->max_usable_size = max_table_size;
grpc_chttp2_hpack_compressor_set_max_table_size(
c, GPR_MIN(c->max_table_size, max_table_size));
}
static void rebuild_elems(grpc_chttp2_hpack_compressor *c, gpr_uint32 new_cap) {
gpr_uint16 *table_elem_size = gpr_malloc(sizeof(*table_elem_size) * new_cap);
gpr_uint32 i;
memset(table_elem_size, 0, sizeof(*table_elem_size) * new_cap);
GPR_ASSERT(c->table_elems <= new_cap);
for (i = 0; i < c->table_elems; i++) {
gpr_uint32 ofs = c->tail_remote_index + i + 1;
table_elem_size[ofs % new_cap] = c->table_elem_size[ofs % c->cap_table_elems];
}
c->cap_table_elems = new_cap;
gpr_free(c->table_elem_size);
c->table_elem_size = table_elem_size;
}
void grpc_chttp2_hpack_compressor_set_max_table_size(
grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size) {
max_table_size = GPR_MIN(max_table_size, c->max_usable_size);
if (max_table_size == c->max_table_size) {
return;
}
while (c->table_size > 0 && c->table_size > max_table_size) {
evict_entry(c);
}
c->max_table_size = max_table_size;
c->max_table_elems = elems_for_bytes(max_table_size);
if (c->max_table_elems > c->cap_table_elems) {
rebuild_elems(c, GPR_MAX(c->max_table_elems, 2 * c->cap_table_elems));
} else if (c->max_table_elems < c->cap_table_elems / 3) {
gpr_uint32 new_cap = GPR_MAX(c->max_table_elems, 16);
if (new_cap != c->cap_table_elems) {
rebuild_elems(c, new_cap);
}
}
c->advertise_table_size_change = 1;
gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size);
}
void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c,
@ -483,6 +560,9 @@ void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c,
slot. THIS MAY NOT BE THE SAME ELEMENT (if a decoder table slot got
updated). After this loop, we'll do a batch unref of elements. */
begin_frame(&st);
if (c->advertise_table_size_change != 0) {
emit_advertise_table_size_change(c, &st);
}
grpc_metadata_batch_assert_ok(metadata);
for (l = metadata->list.head; l; l = l->next) {
hpack_enc(c, l->md, &st);

@ -43,14 +43,26 @@
#define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256
#define GRPC_CHTTP2_HPACKC_NUM_VALUES 256
#define GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS (4096 / 32)
/* initial table size, per spec */
#define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096
/* maximum table size we'll actually use */
#define GRPC_CHTTP2_HPACKC_MAX_TABLE_SIZE (1024 * 1024)
typedef struct {
gpr_uint32 filter_elems_sum;
gpr_uint32 max_table_size;
gpr_uint32 max_table_elems;
gpr_uint32 cap_table_elems;
/** if non-zero, advertise to the decoder that we'll start using a table
of this size */
gpr_uint8 advertise_table_size_change;
/** maximum number of bytes we'll use for the decode table (to guard against
peers ooming us by setting decode table size high) */
gpr_uint32 max_usable_size;
/* one before the lowest usable table index */
gpr_uint32 tail_remote_index;
gpr_uint16 table_size;
gpr_uint16 table_elems;
gpr_uint32 table_size;
gpr_uint32 table_elems;
/* filter tables for elems: this tables provides an approximate
popularity count for particular hashes, and are used to determine whether
@ -71,12 +83,16 @@ typedef struct {
gpr_uint32 indices_keys[GRPC_CHTTP2_HPACKC_NUM_VALUES];
gpr_uint32 indices_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
gpr_uint16 table_elem_size[GRPC_CHTTP2_HPACKC_MAX_TABLE_ELEMS];
gpr_uint16 *table_elem_size;
} grpc_chttp2_hpack_compressor;
void grpc_chttp2_hpack_compressor_init(grpc_chttp2_hpack_compressor *c,
grpc_mdctx *mdctx);
void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c);
void grpc_chttp2_hpack_compressor_set_max_table_size(
grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size);
void grpc_chttp2_hpack_compressor_set_max_usable_size(
grpc_chttp2_hpack_compressor *c, gpr_uint32 max_table_size);
void grpc_chttp2_encode_header(grpc_chttp2_hpack_compressor *c, gpr_uint32 id,
grpc_metadata_batch *metadata, int is_eof,

@ -74,6 +74,8 @@ static int parse_begin(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
const gpr_uint8 *end);
static int parse_error(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
const gpr_uint8 *end);
static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
const gpr_uint8 *end);
static int parse_string_prefix(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end);
@ -156,7 +158,7 @@ static const grpc_chttp2_hpack_parser_state first_byte_action[] = {
parse_lithdr_incidx_x, parse_lithdr_incidx_v, parse_lithdr_notidx,
parse_lithdr_notidx_x, parse_lithdr_notidx_v, parse_lithdr_nvridx,
parse_lithdr_nvridx_x, parse_lithdr_nvridx_v, parse_max_tbl_size,
parse_max_tbl_size_x, parse_error};
parse_max_tbl_size_x, parse_illegal_op};
/* indexes the first byte to a parse state function - generated by
gen_hpack_tables.c */
@ -169,7 +171,7 @@ static const gpr_uint8 first_byte_lut[256] = {
LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX,
LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX, LITHDR_NVRIDX_X,
ILLEGAL, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE,
MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE,
MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE,
MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE,
MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE, MAX_TBL_SIZE,
@ -622,13 +624,15 @@ static const gpr_uint8 inverse_base64[256] = {
};
/* emission helpers */
static void on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
int add_to_table) {
static int on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
int add_to_table) {
if (add_to_table) {
GRPC_MDELEM_REF(md);
grpc_chttp2_hptbl_add(&p->table, md);
if (!grpc_chttp2_hptbl_add(&p->table, md)) {
return 0;
}
}
p->on_header(p->on_header_user_data, md);
return 1;
}
static grpc_mdstr *take_string(grpc_chttp2_hpack_parser *p,
@ -714,9 +718,12 @@ static int parse_stream_dep0(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
static int finish_indexed_field(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
if (md == NULL) {
gpr_log(GPR_ERROR, "Invalid HPACK index received: %d", p->index);
return 0;
}
GRPC_MDELEM_REF(md);
on_hdr(p, md, 0);
return parse_begin(p, cur, end);
return on_hdr(p, md, 0) && parse_begin(p, cur, end);
}
/* parse an indexed field with index < 127 */
@ -742,21 +749,21 @@ static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
static int finish_lithdr_incidx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)),
1);
return parse_begin(p, cur, end);
return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)),
1) &&
parse_begin(p, cur, end);
}
/* finish a literal header with incremental indexing with no index */
static int finish_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
take_string(p, &p->key),
take_string(p, &p->value)),
1);
return parse_begin(p, cur, end);
return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
take_string(p, &p->key),
take_string(p, &p->value)),
1) &&
parse_begin(p, cur, end);
}
/* parse a literal header with incremental indexing; index < 63 */
@ -795,21 +802,21 @@ static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
static int finish_lithdr_notidx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)),
0);
return parse_begin(p, cur, end);
return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)),
0) &&
parse_begin(p, cur, end);
}
/* finish a literal header without incremental indexing with index = 0 */
static int finish_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
take_string(p, &p->key),
take_string(p, &p->value)),
0);
return parse_begin(p, cur, end);
return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
take_string(p, &p->key),
take_string(p, &p->value)),
0) &&
parse_begin(p, cur, end);
}
/* parse a literal header without incremental indexing; index < 15 */
@ -848,21 +855,21 @@ static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
static int finish_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
grpc_mdelem *md = grpc_chttp2_hptbl_lookup(&p->table, p->index);
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)),
0);
return parse_begin(p, cur, end);
return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
GRPC_MDSTR_REF(md->key),
take_string(p, &p->value)),
0) &&
parse_begin(p, cur, end);
}
/* finish a literal header that is never indexed with an extra value */
static int finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
take_string(p, &p->key),
take_string(p, &p->value)),
0);
return parse_begin(p, cur, end);
return on_hdr(p, grpc_mdelem_from_metadata_strings(p->table.mdctx,
take_string(p, &p->key),
take_string(p, &p->value)),
0) &&
parse_begin(p, cur, end);
}
/* parse a literal header that is never indexed; index < 15 */
@ -901,14 +908,14 @@ static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
static int finish_max_tbl_size(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) {
gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index);
abort(); /* not implemented */
return parse_begin(p, cur, end);
return grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index) &&
parse_begin(p, cur, end);
}
/* parse a max table size change, max size < 15 */
static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
const gpr_uint8 *end) {
p->index = (*cur) & 0xf;
p->index = (*cur) & 0x1f;
return finish_max_tbl_size(p, cur + 1, end);
}
@ -918,7 +925,7 @@ static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p,
static const grpc_chttp2_hpack_parser_state and_then[] = {
finish_max_tbl_size};
p->next_state = and_then;
p->index = 0xf;
p->index = 0x1f;
p->parsing.value = &p->index;
return parse_value0(p, cur + 1, end);
}
@ -930,6 +937,13 @@ static int parse_error(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
return 0;
}
static int parse_illegal_op(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
const gpr_uint8 *end) {
GPR_ASSERT(cur != end);
gpr_log(GPR_DEBUG, "Illegal hpack op code %d", *cur);
return parse_error(p, cur, end);
}
/* parse the 1st byte of a varint into p->parsing.value
no overflow is possible */
static int parse_value0(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,

@ -36,7 +36,9 @@
#include <assert.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/support/murmur_hash.h"
static struct {
@ -169,12 +171,22 @@ static struct {
{"www-authenticate", ""},
};
static gpr_uint32 entries_for_bytes(gpr_uint32 bytes) {
return (bytes + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) /
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
}
void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl, grpc_mdctx *mdctx) {
size_t i;
memset(tbl, 0, sizeof(*tbl));
tbl->mdctx = mdctx;
tbl->max_bytes = GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE;
tbl->current_table_bytes = tbl->max_bytes =
GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE;
tbl->max_entries = tbl->cap_entries =
entries_for_bytes(tbl->current_table_bytes);
tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries);
memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries);
for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
tbl->static_ents[i - 1] = grpc_mdelem_from_strings(
mdctx, static_table[i].key, static_table[i].value);
@ -187,9 +199,9 @@ void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl) {
GRPC_MDELEM_UNREF(tbl->static_ents[i]);
}
for (i = 0; i < tbl->num_ents; i++) {
GRPC_MDELEM_UNREF(
tbl->ents[(tbl->first_ent + i) % GRPC_CHTTP2_MAX_TABLE_COUNT]);
GRPC_MDELEM_UNREF(tbl->ents[(tbl->first_ent + i) % tbl->cap_entries]);
}
gpr_free(tbl->ents);
}
grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
@ -201,8 +213,8 @@ grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
/* Otherwise, find the value in the list of valid entries */
tbl_index -= (GRPC_CHTTP2_LAST_STATIC_ENTRY + 1);
if (tbl_index < tbl->num_ents) {
gpr_uint32 offset = (tbl->num_ents - 1u - tbl_index + tbl->first_ent) %
GRPC_CHTTP2_MAX_TABLE_COUNT;
gpr_uint32 offset =
(tbl->num_ents - 1u - tbl_index + tbl->first_ent) % tbl->cap_entries;
return tbl->ents[offset];
}
/* Invalid entry: return error */
@ -216,21 +228,81 @@ static void evict1(grpc_chttp2_hptbl *tbl) {
GPR_SLICE_LENGTH(first_ent->value->slice) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
GPR_ASSERT(elem_bytes <= tbl->mem_used);
tbl->mem_used = (gpr_uint16)(tbl->mem_used - elem_bytes);
tbl->first_ent =
(gpr_uint16)((tbl->first_ent + 1) % GRPC_CHTTP2_MAX_TABLE_COUNT);
tbl->mem_used -= (gpr_uint32)elem_bytes;
tbl->first_ent = ((tbl->first_ent + 1) % tbl->cap_entries);
tbl->num_ents--;
GRPC_MDELEM_UNREF(first_ent);
}
void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
static void rebuild_ents(grpc_chttp2_hptbl *tbl, gpr_uint32 new_cap) {
grpc_mdelem **ents = gpr_malloc(sizeof(*ents) * new_cap);
gpr_uint32 i;
for (i = 0; i < tbl->num_ents; i++) {
ents[i] = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
}
gpr_free(tbl->ents);
tbl->ents = ents;
tbl->cap_entries = new_cap;
tbl->first_ent = 0;
}
void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
gpr_uint32 max_bytes) {
if (tbl->max_bytes == max_bytes) {
return;
}
gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes);
while (tbl->mem_used > max_bytes) {
evict1(tbl);
}
tbl->max_bytes = max_bytes;
}
int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
gpr_uint32 bytes) {
if (tbl->current_table_bytes == bytes) {
return 1;
}
if (bytes > tbl->max_bytes) {
gpr_log(GPR_ERROR,
"Attempt to make hpack table %d bytes when max is %d bytes", bytes,
tbl->max_bytes);
return 0;
}
gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes);
while (tbl->mem_used > bytes) {
evict1(tbl);
}
tbl->current_table_bytes = bytes;
tbl->max_entries = entries_for_bytes(bytes);
if (tbl->max_entries > tbl->cap_entries) {
rebuild_ents(tbl, GPR_MAX(tbl->max_entries, 2 * tbl->cap_entries));
} else if (tbl->max_entries < tbl->cap_entries / 3) {
gpr_uint32 new_cap = GPR_MAX(tbl->max_entries, 16u);
if (new_cap != tbl->cap_entries) {
rebuild_ents(tbl, new_cap);
}
}
return 1;
}
int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
/* determine how many bytes of buffer this entry represents */
size_t elem_bytes = GPR_SLICE_LENGTH(md->key->slice) +
GPR_SLICE_LENGTH(md->value->slice) +
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD;
if (tbl->current_table_bytes > tbl->max_bytes) {
gpr_log(GPR_ERROR,
"HPACK max table size reduced to %d but not reflected by hpack "
"stream (still at %d)",
tbl->max_bytes, tbl->current_table_bytes);
return 0;
}
/* we can't add elements bigger than the max table size */
if (elem_bytes > tbl->max_bytes) {
if (elem_bytes > tbl->current_table_bytes) {
/* HPACK draft 10 section 4.4 states:
* If the size of the new entry is less than or equal to the maximum
* size, that entry is added to the table. It is not an error to
@ -243,44 +315,43 @@ void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
while (tbl->num_ents) {
evict1(tbl);
}
return;
return 1;
}
/* evict entries to ensure no overflow */
while (elem_bytes > (size_t)tbl->max_bytes - tbl->mem_used) {
while (elem_bytes > (size_t)tbl->current_table_bytes - tbl->mem_used) {
evict1(tbl);
}
/* copy the finalized entry in */
tbl->ents[tbl->last_ent] = md;
tbl->ents[(tbl->first_ent + tbl->num_ents) % tbl->cap_entries] =
GRPC_MDELEM_REF(md);
/* update accounting values */
tbl->last_ent =
(gpr_uint16)((tbl->last_ent + 1) % GRPC_CHTTP2_MAX_TABLE_COUNT);
tbl->num_ents++;
tbl->mem_used = (gpr_uint16)(tbl->mem_used + elem_bytes);
tbl->mem_used += (gpr_uint32)elem_bytes;
return 1;
}
grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
const grpc_chttp2_hptbl *tbl, grpc_mdelem *md) {
grpc_chttp2_hptbl_find_result r = {0, 0};
gpr_uint16 i;
gpr_uint32 i;
/* See if the string is in the static table */
for (i = 0; i < GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
grpc_mdelem *ent = tbl->static_ents[i];
if (md->key != ent->key) continue;
r.index = (gpr_uint16)(i + 1);
r.index = i + 1u;
r.has_value = md->value == ent->value;
if (r.has_value) return r;
}
/* Scan the dynamic table */
for (i = 0; i < tbl->num_ents; i++) {
gpr_uint16 idx =
(gpr_uint16)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
grpc_mdelem *ent =
tbl->ents[(tbl->first_ent + i) % GRPC_CHTTP2_MAX_TABLE_COUNT];
gpr_uint32 idx =
(gpr_uint32)(tbl->num_ents - i + GRPC_CHTTP2_LAST_STATIC_ENTRY);
grpc_mdelem *ent = tbl->ents[(tbl->first_ent + i) % tbl->cap_entries];
if (md->key != ent->key) continue;
r.index = idx;
r.has_value = md->value == ent->value;

@ -49,47 +49,59 @@
#define GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE
/* Per entry overhead bytes as per the spec */
#define GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD 32
#if 0
/* Maximum number of entries we could possibly fit in the table, given defined
overheads */
#define GRPC_CHTTP2_MAX_TABLE_COUNT \
((GRPC_CHTTP2_MAX_HPACK_TABLE_SIZE + GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD - 1) / \
GRPC_CHTTP2_HPACK_ENTRY_OVERHEAD)
#endif
/* hpack decoder table */
typedef struct {
grpc_mdctx *mdctx;
/* the first used entry in ents */
gpr_uint16 first_ent;
/* the last used entry in ents */
gpr_uint16 last_ent;
gpr_uint32 first_ent;
/* how many entries are in the table */
gpr_uint16 num_ents;
gpr_uint32 num_ents;
/* the amount of memory used by the table, according to the hpack algorithm */
gpr_uint16 mem_used;
gpr_uint32 mem_used;
/* the max memory allowed to be used by the table, according to the hpack
algorithm */
gpr_uint16 max_bytes;
gpr_uint32 max_bytes;
/* the currently agreed size of the table, according to the hpack algorithm */
gpr_uint32 current_table_bytes;
/* Maximum number of entries we could possibly fit in the table, given defined
overheads */
gpr_uint32 max_entries;
/* Number of entries allocated in ents */
gpr_uint32 cap_entries;
/* a circular buffer of headers - this is stored in the opposite order to
what hpack specifies, in order to simplify table management a little...
meaning lookups need to SUBTRACT from the end position */
grpc_mdelem *ents[GRPC_CHTTP2_MAX_TABLE_COUNT];
grpc_mdelem **ents;
grpc_mdelem *static_ents[GRPC_CHTTP2_LAST_STATIC_ENTRY];
} grpc_chttp2_hptbl;
/* initialize a hpack table */
void grpc_chttp2_hptbl_init(grpc_chttp2_hptbl *tbl, grpc_mdctx *mdctx);
void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl *tbl);
void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl *tbl,
gpr_uint32 max_bytes);
int grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl *tbl,
gpr_uint32 bytes);
/* lookup a table entry based on its hpack index */
grpc_mdelem *grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl *tbl,
gpr_uint32 index);
/* add a table entry to the index */
void grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl, grpc_mdelem *md);
int grpc_chttp2_hptbl_add(grpc_chttp2_hptbl *tbl,
grpc_mdelem *md) GRPC_MUST_USE_RESULT;
/* Find a key/value pair in the table... returns the index in the table of the
most similar entry, or 0 if the value was not found */
typedef struct {
gpr_uint16 index;
gpr_uint8 has_value;
gpr_uint32 index;
int has_value;
} grpc_chttp2_hptbl_find_result;
grpc_chttp2_hptbl_find_result grpc_chttp2_hptbl_find(
const grpc_chttp2_hptbl *tbl, grpc_mdelem *md);

@ -227,6 +227,9 @@ struct grpc_chttp2_transport_parsing {
/** was a goaway frame received? */
gpr_uint8 goaway_received;
/** the last sent max_table_size setting */
gpr_uint32 last_sent_max_table_size;
/** initial window change */
gpr_int64 initial_window_update;
@ -483,7 +486,8 @@ struct grpc_chttp2_stream {
/** Someone is unlocking the transport mutex: check to see if writes
are required, and schedule them if so */
int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global,
grpc_chttp2_transport_writing *writing);
grpc_chttp2_transport_writing *writing,
int is_parsing);
void grpc_chttp2_perform_writes(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing,
grpc_endpoint *endpoint);

@ -78,6 +78,9 @@ void grpc_chttp2_prepare_to_read(
GPR_TIMER_BEGIN("grpc_chttp2_prepare_to_read", 0);
transport_parsing->next_stream_id = transport_global->next_stream_id;
transport_parsing->last_sent_max_table_size =
transport_global->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE];
/* update the parsing view of incoming window */
while (grpc_chttp2_list_pop_unannounced_incoming_window_available(
@ -127,6 +130,7 @@ void grpc_chttp2_publish_reads(
transport_global->settings[GRPC_SENT_SETTINGS],
GRPC_CHTTP2_NUM_SETTINGS * sizeof(gpr_uint32));
transport_parsing->settings_ack_received = 0;
transport_global->sent_local_settings = 0;
}
/* move goaway to the global state if we received one (it will be
@ -819,6 +823,9 @@ static int init_settings_frame_parser(
}
if (transport_parsing->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
transport_parsing->settings_ack_received = 1;
grpc_chttp2_hptbl_set_max_bytes(
&transport_parsing->hpack_parser.table,
transport_parsing->last_sent_max_table_size);
}
transport_parsing->parser = grpc_chttp2_settings_parser_parse;
transport_parsing->parser_data = &transport_parsing->simple.settings;

@ -45,7 +45,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
int grpc_chttp2_unlocking_check_writes(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_transport_writing *transport_writing) {
grpc_chttp2_transport_writing *transport_writing, int is_parsing) {
grpc_chttp2_stream_global *stream_global;
grpc_chttp2_stream_writing *stream_writing;
@ -55,8 +55,13 @@ int grpc_chttp2_unlocking_check_writes(
gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf);
GPR_ASSERT(transport_global->qbuf.count == 0);
grpc_chttp2_hpack_compressor_set_max_table_size(
&transport_writing->hpack_compressor,
transport_global->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]);
if (transport_global->dirtied_local_settings &&
!transport_global->sent_local_settings) {
!transport_global->sent_local_settings && !is_parsing) {
gpr_slice_buffer_add(
&transport_writing->outbuf,
grpc_chttp2_settings_create(

@ -338,6 +338,31 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->global.next_stream_id =
(gpr_uint32)channel_args->args[i].value.integer;
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER)) {
if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
} else if (channel_args->args[i].value.integer < 0) {
gpr_log(GPR_DEBUG, "%s: must be non-negative",
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
} else {
push_setting(t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
(gpr_uint32)channel_args->args[i].value.integer);
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
} else if (channel_args->args[i].value.integer < 0) {
gpr_log(GPR_DEBUG, "%s: must be non-negative",
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
} else {
grpc_chttp2_hpack_compressor_set_max_usable_size(
&t->writing.hpack_compressor,
(gpr_uint32)channel_args->args[i].value.integer);
}
}
}
}
@ -563,7 +588,8 @@ static void lock(grpc_chttp2_transport *t) { gpr_mu_lock(&t->mu); }
static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
GPR_TIMER_BEGIN("unlock", 0);
if (!t->writing_active && !t->closed &&
grpc_chttp2_unlocking_check_writes(&t->global, &t->writing)) {
grpc_chttp2_unlocking_check_writes(&t->global, &t->writing,
t->parsing_active)) {
t->writing_active = 1;
REF_TRANSPORT(t, "writing");
grpc_exec_ctx_enqueue(exec_ctx, &t->writing_action, 1);
@ -735,6 +761,8 @@ static int contains_non_ok_status(
return 0;
}
static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, int success) {}
static void perform_stream_op_locked(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, grpc_transport_stream_op *op) {
@ -743,6 +771,9 @@ static void perform_stream_op_locked(
GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
on_complete = op->on_complete;
if (on_complete == NULL) {
on_complete = grpc_closure_create(do_nothing, NULL);
}
/* use final_data as a barrier until enqueue time; the inital counter is
dropped at the end of this function */
on_complete->final_data = 2;
@ -806,7 +837,7 @@ static void perform_stream_op_locked(
}
if (stream_global->write_closed) {
grpc_chttp2_complete_closure_step(
exec_ctx, &stream_global->send_trailing_metadata_finished,
exec_ctx, &stream_global->send_trailing_metadata_finished,
grpc_metadata_batch_is_empty(op->send_trailing_metadata));
} else if (stream_global->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding
@ -1033,7 +1064,8 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx,
to the upper layers - drop what we've got, and then publish
what we want - which is safe because we haven't told anyone
about the metadata yet */
if (!stream_global->published_trailing_metadata || stream_global->recv_trailing_metadata_finished != NULL) {
if (!stream_global->published_trailing_metadata ||
stream_global->recv_trailing_metadata_finished != NULL) {
grpc_mdctx *mdctx =
TRANSPORT_FROM_GLOBAL(transport_global)->metadata_context;
char status_string[GPR_LTOA_MIN_BUFSIZE];

@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
-----END CERTIFICATE-----

@ -48,6 +48,7 @@ namespace grpc {
ClientContext::ClientContext()
: initial_metadata_received_(false),
call_(nullptr),
call_canceled_(false),
deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),
propagate_from_call_(nullptr) {}
@ -72,6 +73,7 @@ void ClientContext::AddMetadata(const grpc::string& meta_key,
void ClientContext::set_call(grpc_call* call,
const std::shared_ptr<Channel>& channel) {
grpc::unique_lock<grpc::mutex> lock(mu_);
GPR_ASSERT(call_ == nullptr);
call_ = call;
channel_ = channel;
@ -79,6 +81,9 @@ void ClientContext::set_call(grpc_call* call,
grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED,
"Failed to set credentials to rpc.", nullptr);
}
if (call_canceled_) {
grpc_call_cancel(call_, nullptr);
}
}
void ClientContext::set_compression_algorithm(
@ -101,8 +106,11 @@ std::shared_ptr<const AuthContext> ClientContext::auth_context() const {
}
void ClientContext::TryCancel() {
grpc::unique_lock<grpc::mutex> lock(mu_);
if (call_) {
grpc_call_cancel(call_, nullptr);
} else {
call_canceled_ = true;
}
}

@ -44,12 +44,14 @@ namespace grpc {
class ChannelArguments;
std::shared_ptr<Channel> CreateChannel(
const grpc::string& target, const std::shared_ptr<Credentials>& creds) {
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds) {
return CreateCustomChannel(target, creds, ChannelArguments());
}
std::shared_ptr<Channel> CreateCustomChannel(
const grpc::string& target, const std::shared_ptr<Credentials>& creds,
const grpc::string& target,
const std::shared_ptr<ChannelCredentials>& creds,
const ChannelArguments& args) {
GrpcLibrary init_lib; // We need to call init in case of a bad creds.
ChannelArguments cp_args = args;

@ -35,6 +35,8 @@
namespace grpc {
Credentials::~Credentials() {}
ChannelCredentials::~ChannelCredentials() {}
CallCredentials::~CallCredentials() {}
} // namespace grpc

@ -43,7 +43,7 @@
namespace grpc {
namespace {
class InsecureCredentialsImpl GRPC_FINAL : public Credentials {
class InsecureChannelCredentialsImpl GRPC_FINAL : public ChannelCredentials {
public:
std::shared_ptr<grpc::Channel> CreateChannel(
const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE {
@ -54,15 +54,15 @@ class InsecureCredentialsImpl GRPC_FINAL : public Credentials {
grpc_insecure_channel_create(target.c_str(), &channel_args, nullptr));
}
// InsecureCredentials should not be applied to a call.
bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE { return false; }
SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return nullptr; }
SecureChannelCredentials* AsSecureCredentials() GRPC_OVERRIDE {
return nullptr;
}
};
} // namespace
std::shared_ptr<Credentials> InsecureCredentials() {
return std::shared_ptr<Credentials>(new InsecureCredentialsImpl());
std::shared_ptr<ChannelCredentials> InsecureChannelCredentials() {
return std::shared_ptr<ChannelCredentials>(
new InsecureChannelCredentialsImpl());
}
} // namespace grpc

@ -40,7 +40,7 @@
namespace grpc {
std::shared_ptr<grpc::Channel> SecureCredentials::CreateChannel(
std::shared_ptr<grpc::Channel> SecureChannelCredentials::CreateChannel(
const string& target, const grpc::ChannelArguments& args) {
grpc_channel_args channel_args;
args.SetChannelArgs(&channel_args);
@ -50,96 +50,104 @@ std::shared_ptr<grpc::Channel> SecureCredentials::CreateChannel(
nullptr));
}
bool SecureCredentials::ApplyToCall(grpc_call* call) {
bool SecureCallCredentials::ApplyToCall(grpc_call* call) {
return grpc_call_set_credentials(call, c_creds_) == GRPC_CALL_OK;
}
namespace {
std::shared_ptr<Credentials> WrapCredentials(grpc_credentials* creds) {
return creds == nullptr
? nullptr
: std::shared_ptr<Credentials>(new SecureCredentials(creds));
std::shared_ptr<ChannelCredentials> WrapChannelCredentials(
grpc_channel_credentials* creds) {
return creds == nullptr ? nullptr : std::shared_ptr<ChannelCredentials>(
new SecureChannelCredentials(creds));
}
std::shared_ptr<CallCredentials> WrapCallCredentials(
grpc_call_credentials* creds) {
return creds == nullptr ? nullptr : std::shared_ptr<CallCredentials>(
new SecureCallCredentials(creds));
}
} // namespace
std::shared_ptr<Credentials> GoogleDefaultCredentials() {
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
GrpcLibrary init; // To call grpc_init().
return WrapCredentials(grpc_google_default_credentials_create());
return WrapChannelCredentials(grpc_google_default_credentials_create());
}
// Builds SSL Credentials given SSL specific options
std::shared_ptr<Credentials> SslCredentials(
std::shared_ptr<ChannelCredentials> SslCredentials(
const SslCredentialsOptions& options) {
GrpcLibrary init; // To call grpc_init().
grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
grpc_credentials* c_creds = grpc_ssl_credentials_create(
grpc_channel_credentials* c_creds = grpc_ssl_credentials_create(
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr);
return WrapCredentials(c_creds);
return WrapChannelCredentials(c_creds);
}
// Builds credentials for use when running in GCE
std::shared_ptr<Credentials> GoogleComputeEngineCredentials() {
std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
GrpcLibrary init; // To call grpc_init().
return WrapCredentials(
return WrapCallCredentials(
grpc_google_compute_engine_credentials_create(nullptr));
}
// Builds JWT credentials.
std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials(
std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
const grpc::string& json_key, long token_lifetime_seconds) {
GrpcLibrary init; // To call grpc_init().
if (token_lifetime_seconds <= 0) {
gpr_log(GPR_ERROR,
"Trying to create JWTCredentials with non-positive lifetime");
return WrapCredentials(nullptr);
return WrapCallCredentials(nullptr);
}
gpr_timespec lifetime =
gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN);
return WrapCredentials(grpc_service_account_jwt_access_credentials_create(
return WrapCallCredentials(grpc_service_account_jwt_access_credentials_create(
json_key.c_str(), lifetime, nullptr));
}
// Builds refresh token credentials.
std::shared_ptr<Credentials> GoogleRefreshTokenCredentials(
std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
const grpc::string& json_refresh_token) {
GrpcLibrary init; // To call grpc_init().
return WrapCredentials(grpc_google_refresh_token_credentials_create(
return WrapCallCredentials(grpc_google_refresh_token_credentials_create(
json_refresh_token.c_str(), nullptr));
}
// Builds access token credentials.
std::shared_ptr<Credentials> AccessTokenCredentials(
std::shared_ptr<CallCredentials> AccessTokenCredentials(
const grpc::string& access_token) {
GrpcLibrary init; // To call grpc_init().
return WrapCredentials(
return WrapCallCredentials(
grpc_access_token_credentials_create(access_token.c_str(), nullptr));
}
// Builds IAM credentials.
std::shared_ptr<Credentials> GoogleIAMCredentials(
std::shared_ptr<CallCredentials> GoogleIAMCredentials(
const grpc::string& authorization_token,
const grpc::string& authority_selector) {
GrpcLibrary init; // To call grpc_init().
return WrapCredentials(grpc_google_iam_credentials_create(
return WrapCallCredentials(grpc_google_iam_credentials_create(
authorization_token.c_str(), authority_selector.c_str(), nullptr));
}
// Combines two credentials objects into a composite credentials.
std::shared_ptr<Credentials> CompositeCredentials(
const std::shared_ptr<Credentials>& creds1,
const std::shared_ptr<Credentials>& creds2) {
// Note that we are not saving shared_ptrs to the two credentials
// passed in here. This is OK because the underlying C objects (i.e.,
// creds1 and creds2) into grpc_composite_credentials_create will see their
// refcounts incremented.
SecureCredentials* s1 = creds1->AsSecureCredentials();
SecureCredentials* s2 = creds2->AsSecureCredentials();
if (s1 && s2) {
return WrapCredentials(grpc_composite_credentials_create(
s1->GetRawCreds(), s2->GetRawCreds(), nullptr));
// Combines one channel credentials and one call credentials into a channel
// composite credentials.
std::shared_ptr<ChannelCredentials> CompositeChannelCredentials(
const std::shared_ptr<ChannelCredentials>& channel_creds,
const std::shared_ptr<CallCredentials>& call_creds) {
// Note that we are not saving shared_ptrs to the two credentials passed in
// here. This is OK because the underlying C objects (i.e., channel_creds and
// call_creds) into grpc_composite_credentials_create will see their refcounts
// incremented.
SecureChannelCredentials* s_channel_creds =
channel_creds->AsSecureCredentials();
SecureCallCredentials* s_call_creds = call_creds->AsSecureCredentials();
if (s_channel_creds && s_call_creds) {
return WrapChannelCredentials(grpc_composite_channel_credentials_create(
s_channel_creds->GetRawCreds(), s_call_creds->GetRawCreds(), nullptr));
}
return nullptr;
}
@ -193,7 +201,7 @@ MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
std::unique_ptr<MetadataCredentialsPlugin> plugin)
: thread_pool_(CreateDefaultThreadPool()), plugin_(std::move(plugin)) {}
std::shared_ptr<Credentials> MetadataCredentialsFromPlugin(
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin> plugin) {
GrpcLibrary init; // To call grpc_init().
MetadataCredentialsPluginWrapper* wrapper =
@ -201,7 +209,7 @@ std::shared_ptr<Credentials> MetadataCredentialsFromPlugin(
grpc_metadata_credentials_plugin c_plugin = {
MetadataCredentialsPluginWrapper::GetMetadata,
MetadataCredentialsPluginWrapper::Destroy, wrapper};
return WrapCredentials(
return WrapCallCredentials(
grpc_metadata_credentials_create_from_plugin(c_plugin, nullptr));
}

@ -43,19 +43,37 @@
namespace grpc {
class SecureCredentials GRPC_FINAL : public Credentials {
class SecureChannelCredentials GRPC_FINAL : public ChannelCredentials {
public:
explicit SecureCredentials(grpc_credentials* c_creds) : c_creds_(c_creds) {}
~SecureCredentials() GRPC_OVERRIDE { grpc_credentials_release(c_creds_); }
grpc_credentials* GetRawCreds() { return c_creds_; }
bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE;
explicit SecureChannelCredentials(grpc_channel_credentials* c_creds)
: c_creds_(c_creds) {}
~SecureChannelCredentials() GRPC_OVERRIDE {
grpc_channel_credentials_release(c_creds_);
}
grpc_channel_credentials* GetRawCreds() { return c_creds_; }
std::shared_ptr<grpc::Channel> CreateChannel(
const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE;
SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
SecureChannelCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
private:
grpc_channel_credentials* const c_creds_;
};
class SecureCallCredentials GRPC_FINAL : public CallCredentials {
public:
explicit SecureCallCredentials(grpc_call_credentials* c_creds)
: c_creds_(c_creds) {}
~SecureCallCredentials() GRPC_OVERRIDE {
grpc_call_credentials_release(c_creds_);
}
grpc_call_credentials* GetRawCreds() { return c_creds_; }
bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE;
SecureCallCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
private:
grpc_credentials* const c_creds_;
grpc_call_credentials* const c_creds_;
};
class MetadataCredentialsPluginWrapper GRPC_FINAL {

@ -57,7 +57,7 @@ namespace Grpc.Core.Tests
get { return composable; }
}
internal override CredentialsSafeHandle ToNativeCredentials()
internal override ChannelCredentialsSafeHandle ToNativeCredentials()
{
return null;
}
@ -65,7 +65,7 @@ namespace Grpc.Core.Tests
internal class FakeCallCredentials : CallCredentials
{
internal override CredentialsSafeHandle ToNativeCredentials()
internal override CallCredentialsSafeHandle ToNativeCredentials()
{
return null;
}

@ -78,7 +78,7 @@ namespace Grpc.Core
/// Creates native object for the credentials.
/// </summary>
/// <returns>The native credentials.</returns>
internal abstract CredentialsSafeHandle ToNativeCredentials();
internal abstract CallCredentialsSafeHandle ToNativeCredentials();
}
/// <summary>
@ -98,7 +98,7 @@ namespace Grpc.Core
this.interceptor = Preconditions.CheckNotNull(interceptor);
}
internal override CredentialsSafeHandle ToNativeCredentials()
internal override CallCredentialsSafeHandle ToNativeCredentials()
{
NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor);
return plugin.Credentials;
@ -123,14 +123,14 @@ namespace Grpc.Core
this.credentials = new List<CallCredentials>(credentials);
}
internal override CredentialsSafeHandle ToNativeCredentials()
internal override CallCredentialsSafeHandle ToNativeCredentials()
{
return ToNativeRecursive(0);
}
// Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier.
// In practice, we won't usually see composites from more than two credentials anyway.
private CredentialsSafeHandle ToNativeRecursive(int startIndex)
private CallCredentialsSafeHandle ToNativeRecursive(int startIndex)
{
if (startIndex == credentials.Count - 1)
{
@ -140,7 +140,7 @@ namespace Grpc.Core
using (var cred1 = credentials[startIndex].ToNativeCredentials())
using (var cred2 = ToNativeRecursive(startIndex + 1))
{
var nativeComposite = CredentialsSafeHandle.CreateComposite(cred1, cred2);
var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2);
if (nativeComposite.IsInvalid)
{
throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials.");

@ -75,8 +75,8 @@ namespace Grpc.Core
this.options = options != null ? new List<ChannelOption>(options) : new List<ChannelOption>();
EnsureUserAgentChannelOption(this.options);
using (CredentialsSafeHandle nativeCredentials = credentials.ToNativeCredentials())
using (ChannelArgsSafeHandle nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options))
using (var nativeCredentials = credentials.ToNativeCredentials())
using (var nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options))
{
if (nativeCredentials != null)
{

@ -76,7 +76,7 @@ namespace Grpc.Core
/// should be created.
/// </summary>
/// <returns>The native credentials.</returns>
internal abstract CredentialsSafeHandle ToNativeCredentials();
internal abstract ChannelCredentialsSafeHandle ToNativeCredentials();
/// <summary>
/// Returns <c>true</c> if this credential type allows being composed by <c>CompositeCredentials</c>.
@ -88,7 +88,7 @@ namespace Grpc.Core
private sealed class InsecureCredentialsImpl : ChannelCredentials
{
internal override CredentialsSafeHandle ToNativeCredentials()
internal override ChannelCredentialsSafeHandle ToNativeCredentials()
{
return null;
}
@ -160,9 +160,9 @@ namespace Grpc.Core
get { return true; }
}
internal override CredentialsSafeHandle ToNativeCredentials()
internal override ChannelCredentialsSafeHandle ToNativeCredentials()
{
return CredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair);
return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair);
}
}
@ -188,12 +188,12 @@ namespace Grpc.Core
Preconditions.CheckArgument(channelCredentials.IsComposable, "Supplied channel credentials do not allow composition.");
}
internal override CredentialsSafeHandle ToNativeCredentials()
internal override ChannelCredentialsSafeHandle ToNativeCredentials()
{
using (var cred1 = channelCredentials.ToNativeCredentials())
using (var cred2 = callCredentials.ToNativeCredentials())
using (var channelCreds = channelCredentials.ToNativeCredentials())
using (var callCreds = callCredentials.ToNativeCredentials())
{
var nativeComposite = CredentialsSafeHandle.CreateComposite(cred1, cred2);
var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCreds, callCreds);
if (nativeComposite.IsInvalid)
{
throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials.");

@ -80,7 +80,6 @@
<Compile Include="ServerServiceDefinition.cs" />
<Compile Include="Utils\AsyncStreamExtensions.cs" />
<Compile Include="Utils\BenchmarkUtil.cs" />
<Compile Include="Internal\CredentialsSafeHandle.cs" />
<Compile Include="ChannelCredentials.cs" />
<Compile Include="Internal\ChannelArgsSafeHandle.cs" />
<Compile Include="Internal\AsyncCompletion.cs" />
@ -119,6 +118,8 @@
<Compile Include="CompressionLevel.cs" />
<Compile Include="WriteOptions.cs" />
<Compile Include="ContextPropagationToken.cs" />
<Compile Include="Internal\CallCredentialsSafeHandle.cs" />
<Compile Include="Internal\ChannelCredentialsSafeHandle.cs" />
<Compile Include="Profiling\ProfilerEntry.cs" />
<Compile Include="Profiling\ProfilerScope.cs" />
<Compile Include="Profiling\IProfiler.cs" />
@ -157,4 +158,4 @@
<ItemGroup>
<Folder Include="Profiling\" />
</ItemGroup>
</Project>
</Project>

@ -0,0 +1,64 @@
#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 System.Threading;
using System.Threading.Tasks;
namespace Grpc.Core.Internal
{
/// <summary>
/// grpc_call_credentials from <c>grpc/grpc_security.h</c>
/// </summary>
internal class CallCredentialsSafeHandle : SafeHandleZeroIsInvalid
{
[DllImport("grpc_csharp_ext.dll")]
static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_call_credentials_release(IntPtr credentials);
private CallCredentialsSafeHandle()
{
}
public static CallCredentialsSafeHandle CreateComposite(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2)
{
return grpcsharp_composite_call_credentials_create(creds1, creds2);
}
protected override bool ReleaseHandle()
{
grpcsharp_call_credentials_release(handle);
return true;
}
}
}

@ -100,7 +100,7 @@ namespace Grpc.Core.Internal
BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_set_credentials(CallSafeHandle call, CredentialsSafeHandle credentials);
static extern GRPCCallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials);
[DllImport("grpc_csharp_ext.dll")]
static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call);
@ -117,7 +117,7 @@ namespace Grpc.Core.Internal
this.completionRegistry = completionRegistry;
}
public void SetCredentials(CredentialsSafeHandle credentials)
public void SetCredentials(CallCredentialsSafeHandle credentials)
{
grpcsharp_call_set_credentials(this, credentials).CheckOk();
}

@ -36,31 +36,31 @@ using System.Threading.Tasks;
namespace Grpc.Core.Internal
{
/// <summary>
/// grpc_credentials from <c>grpc/grpc_security.h</c>
/// grpc_channel_credentials from <c>grpc/grpc_security.h</c>
/// </summary>
internal class CredentialsSafeHandle : SafeHandleZeroIsInvalid
internal class ChannelCredentialsSafeHandle : SafeHandleZeroIsInvalid
{
[DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
static extern CredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey);
static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey);
[DllImport("grpc_csharp_ext.dll")]
static extern CredentialsSafeHandle grpcsharp_composite_credentials_create(CredentialsSafeHandle creds1, CredentialsSafeHandle creds2);
static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_credentials_release(IntPtr credentials);
static extern void grpcsharp_channel_credentials_release(IntPtr credentials);
private CredentialsSafeHandle()
private ChannelCredentialsSafeHandle()
{
}
public static CredentialsSafeHandle CreateNullCredentials()
public static ChannelCredentialsSafeHandle CreateNullCredentials()
{
var creds = new CredentialsSafeHandle();
var creds = new ChannelCredentialsSafeHandle();
creds.SetHandle(IntPtr.Zero);
return creds;
}
public static CredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair)
public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair)
{
if (keyCertPair != null)
{
@ -72,14 +72,14 @@ namespace Grpc.Core.Internal
}
}
public static CredentialsSafeHandle CreateComposite(CredentialsSafeHandle creds1, CredentialsSafeHandle creds2)
public static ChannelCredentialsSafeHandle CreateComposite(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds)
{
return grpcsharp_composite_credentials_create(creds1, creds2);
return grpcsharp_composite_channel_credentials_create(channelCreds, callCreds);
}
protected override bool ReleaseHandle()
{
grpcsharp_credentials_release(handle);
grpcsharp_channel_credentials_release(handle);
return true;
}
}

@ -45,7 +45,7 @@ namespace Grpc.Core.Internal
static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs);
[DllImport("grpc_csharp_ext.dll")]
static extern ChannelSafeHandle grpcsharp_secure_channel_create(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs);
static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs);
[DllImport("grpc_csharp_ext.dll")]
static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
@ -75,7 +75,7 @@ namespace Grpc.Core.Internal
return grpcsharp_insecure_channel_create(target, channelArgs);
}
public static ChannelSafeHandle CreateSecure(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs)
public static ChannelSafeHandle CreateSecure(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs)
{
// Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle.
// Doing so would make object finalizer crash if we end up abandoning the handle.
@ -83,7 +83,7 @@ namespace Grpc.Core.Internal
return grpcsharp_secure_channel_create(credentials, target, channelArgs);
}
public CallSafeHandle CreateCall(CompletionRegistry registry, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CredentialsSafeHandle credentials)
public CallSafeHandle CreateCall(CompletionRegistry registry, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CallCredentialsSafeHandle credentials)
{
using (Profilers.ForCurrentThread().NewScope("ChannelSafeHandle.CreateCall"))
{

@ -46,7 +46,7 @@ namespace Grpc.Core.Internal
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeMetadataCredentialsPlugin>();
[DllImport("grpc_csharp_ext.dll")]
static extern CredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor);
static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor);
[DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);
@ -54,7 +54,7 @@ namespace Grpc.Core.Internal
AsyncAuthInterceptor interceptor;
GCHandle gcHandle;
NativeMetadataInterceptor nativeInterceptor;
CredentialsSafeHandle credentials;
CallCredentialsSafeHandle credentials;
public NativeMetadataCredentialsPlugin(AsyncAuthInterceptor interceptor)
{
@ -66,7 +66,7 @@ namespace Grpc.Core.Internal
this.credentials = grpcsharp_metadata_credentials_create_from_plugin(nativeInterceptor);
}
public CredentialsSafeHandle Credentials
public CallCredentialsSafeHandle Credentials
{
get { return credentials; }
}

@ -41,7 +41,9 @@ namespace Grpc.Core.Profiling
internal interface IProfiler
{
void Begin(string tag);
void End(string tag);
void Mark(string tag);
}
}

@ -40,7 +40,8 @@ namespace Grpc.Core.Profiling
{
internal struct ProfilerEntry
{
public enum Type {
public enum Type
{
BEGIN,
END,
MARK

@ -40,12 +40,12 @@ namespace Grpc.Core.Profiling
{
internal static class Profilers
{
static readonly NopProfiler defaultProfiler = new NopProfiler();
static readonly NopProfiler DefaultProfiler = new NopProfiler();
static readonly ThreadLocal<IProfiler> profilers = new ThreadLocal<IProfiler>();
public static IProfiler ForCurrentThread()
{
return profilers.Value ?? defaultProfiler;
return profilers.Value ?? DefaultProfiler;
}
public static void SetForCurrentThread(IProfiler profiler)
@ -89,15 +89,18 @@ namespace Grpc.Core.Profiling
this.entries = new ProfilerEntry[capacity];
}
public void Begin(string tag) {
public void Begin(string tag)
{
AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.BEGIN, tag));
}
public void End(string tag) {
public void End(string tag)
{
AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.END, tag));
}
public void Mark(string tag) {
public void Mark(string tag)
{
AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.MARK, tag));
}

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Grpc.IntegrationTesting.QpsWorker</RootNamespace>
<AssemblyName>Grpc.IntegrationTesting.QpsWorker</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\ReleaseSigned</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
<Name>Grpc.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Grpc.IntegrationTesting\Grpc.IntegrationTesting.csproj">
<Project>{C61154BA-DD4A-4838-8420-0162A28925E0}</Project>
<Name>Grpc.IntegrationTesting</Name>
</ProjectReference>
</ItemGroup>
</Project>

@ -0,0 +1,46 @@
#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 Grpc.IntegrationTesting;
namespace Grpc.IntegrationTesting
{
class Program
{
public static void Main(string[] args)
{
QpsWorker.Run(args);
}
}
}

@ -0,0 +1,11 @@
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Grpc.IntegrationTesting.QpsWorker")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

@ -0,0 +1,76 @@
#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.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
namespace Grpc.Testing
{
/// <summary>
/// Implementation of BenchmarkService server
/// </summary>
public class BenchmarkServiceImpl : BenchmarkService.IBenchmarkService
{
private readonly int responseSize;
public BenchmarkServiceImpl(int responseSize)
{
this.responseSize = responseSize;
}
public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
{
var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) };
return Task.FromResult(response);
}
public async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context)
{
await requestStream.ForEachAsync(async request =>
{
var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) };
await responseStream.WriteAsync(response);
});
}
private static Payload CreateZerosPayload(int size)
{
return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
}
}
}

@ -0,0 +1,153 @@
#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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using NUnit.Framework;
using Grpc.Testing;
namespace Grpc.IntegrationTesting
{
/// <summary>
/// Helper methods to start client runners for performance testing.
/// </summary>
public static class ClientRunners
{
/// <summary>
/// Creates a started client runner.
/// </summary>
public static IClientRunner CreateStarted(ClientConfig config)
{
string target = config.ServerTargets.Single();
Grpc.Core.Utils.Preconditions.CheckArgument(config.LoadParams.LoadCase == LoadParams.LoadOneofCase.ClosedLoop);
var credentials = config.SecurityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure;
var channel = new Channel(target, credentials);
switch (config.RpcType)
{
case RpcType.UNARY:
return new SyncUnaryClientRunner(channel,
config.PayloadConfig.SimpleParams.ReqSize,
config.HistogramParams);
case RpcType.STREAMING:
default:
throw new ArgumentException("Unsupported RpcType.");
}
}
}
/// <summary>
/// Client that starts synchronous unary calls in a closed loop.
/// </summary>
public class SyncUnaryClientRunner : IClientRunner
{
const double SecondsToNanos = 1e9;
readonly Channel channel;
readonly int payloadSize;
readonly Histogram histogram;
readonly BenchmarkService.IBenchmarkServiceClient client;
readonly Task runnerTask;
readonly CancellationTokenSource stoppedCts;
readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
public SyncUnaryClientRunner(Channel channel, int payloadSize, HistogramParams histogramParams)
{
this.channel = Grpc.Core.Utils.Preconditions.CheckNotNull(channel);
this.payloadSize = payloadSize;
this.histogram = new Histogram(histogramParams.Resolution, histogramParams.MaxPossible);
this.stoppedCts = new CancellationTokenSource();
this.client = BenchmarkService.NewClient(channel);
this.runnerTask = Task.Factory.StartNew(Run, TaskCreationOptions.LongRunning);
}
public ClientStats GetStats(bool reset)
{
var histogramData = histogram.GetSnapshot(reset);
var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds;
// TODO: populate user time and system time
return new ClientStats
{
Latencies = histogramData,
TimeElapsed = secondsElapsed,
TimeUser = 0,
TimeSystem = 0
};
}
public async Task StopAsync()
{
stoppedCts.Cancel();
await runnerTask;
await channel.ShutdownAsync();
}
private void Run()
{
var request = new SimpleRequest
{
Payload = CreateZerosPayload(payloadSize)
};
var stopwatch = new Stopwatch();
while (!stoppedCts.Token.IsCancellationRequested)
{
stopwatch.Restart();
client.UnaryCall(request);
stopwatch.Stop();
// spec requires data point in nanoseconds.
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
}
}
private static Payload CreateZerosPayload(int size)
{
return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
}
}
}

File diff suppressed because it is too large Load Diff

@ -38,55 +38,46 @@
<AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
<Reference Include="CommandLine">
<HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth">
<HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth.PlatformServices, Version=1.9.3.19383, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Google.Apis.Auth.PlatformServices">
<HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Core, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Google.Apis.Core">
<HintPath>..\packages\Google.Apis.Core.1.9.3\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
@ -104,6 +95,22 @@
<Compile Include="TestGrpc.cs" />
<Compile Include="SslCredentialsTest.cs" />
<Compile Include="Test.cs" />
<Compile Include="IClientRunner.cs" />
<Compile Include="ClientRunners.cs" />
<Compile Include="IServerRunner.cs" />
<Compile Include="ServerRunners.cs" />
<Compile Include="RunnerClientServerTest.cs" />
<Compile Include="Control.cs" />
<Compile Include="Payloads.cs" />
<Compile Include="Services.cs" />
<Compile Include="ServicesGrpc.cs" />
<Compile Include="Stats.cs" />
<Compile Include="BenchmarkServiceImpl.cs" />
<Compile Include="Histogram.cs" />
<Compile Include="HistogramTest.cs" />
<Compile Include="WorkerServiceImpl.cs" />
<Compile Include="QpsWorker.cs" />
<Compile Include="WallClockStopwatch.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

@ -0,0 +1,153 @@
#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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using NUnit.Framework;
using Grpc.Testing;
namespace Grpc.IntegrationTesting
{
/// <summary>
/// Basic implementation of histogram based on grpc/support/histogram.h.
/// </summary>
public class Histogram
{
readonly object myLock = new object();
readonly double multiplier;
readonly double oneOnLogMultiplier;
readonly double maxPossible;
readonly uint[] buckets;
int count;
double sum;
double sumOfSquares;
double min;
double max;
public Histogram(double resolution, double maxPossible)
{
Grpc.Core.Utils.Preconditions.CheckArgument(resolution > 0);
Grpc.Core.Utils.Preconditions.CheckArgument(maxPossible > 0);
this.maxPossible = maxPossible;
this.multiplier = 1.0 + resolution;
this.oneOnLogMultiplier = 1.0 / Math.Log(1.0 + resolution);
this.buckets = new uint[FindBucket(maxPossible) + 1];
ResetUnsafe();
}
public void AddObservation(double value)
{
lock (myLock)
{
AddObservationUnsafe(value);
}
}
/// <summary>
/// Gets snapshot of stats and reset
/// </summary>
public HistogramData GetSnapshot(bool reset = false)
{
lock (myLock)
{
return GetSnapshotUnsafe(reset);
}
}
/// <summary>
/// Finds bucket index to which given observation should go.
/// </summary>
private int FindBucket(double value)
{
value = Math.Max(value, 1.0);
value = Math.Min(value, this.maxPossible);
return (int)(Math.Log(value) * oneOnLogMultiplier);
}
private void AddObservationUnsafe(double value)
{
this.count++;
this.sum += value;
this.sumOfSquares += value * value;
this.min = Math.Min(this.min, value);
this.max = Math.Max(this.max, value);
this.buckets[FindBucket(value)]++;
}
private HistogramData GetSnapshotUnsafe(bool reset)
{
var data = new HistogramData
{
Count = count,
Sum = sum,
SumOfSquares = sumOfSquares,
MinSeen = min,
MaxSeen = max,
Bucket = { buckets }
};
if (reset)
{
ResetUnsafe();
}
return data;
}
private void ResetUnsafe()
{
this.count = 0;
this.sum = 0;
this.sumOfSquares = 0;
this.min = double.PositiveInfinity;
this.max = double.NegativeInfinity;
for (int i = 0; i < this.buckets.Length; i++)
{
this.buckets[i] = 0;
}
}
}
}

@ -0,0 +1,104 @@
#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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
{
public class HistogramTest
{
[Test]
public void Simple()
{
var hist = new Histogram(0.01, 60e9);
hist.AddObservation(10000);
hist.AddObservation(10000);
hist.AddObservation(11000);
hist.AddObservation(11000);
var data = hist.GetSnapshot();
Assert.AreEqual(4, data.Count);
Assert.AreEqual(42000.0, data.Sum, 1e-6);
Assert.AreEqual(10000, data.MinSeen);
Assert.AreEqual(11000, data.MaxSeen);
Assert.AreEqual(2.0*10000*10000 + 2.0*11000*11000, data.SumOfSquares, 1e-6);
// 1.01^925 < 10000 < 1.01^926
Assert.AreEqual(2, data.Bucket[925]);
Assert.AreEqual(2, data.Bucket[935]);
}
[Test]
public void ExtremeObservations()
{
var hist = new Histogram(0.01, 60e9);
hist.AddObservation(-0.5); // should be in the first bucket
hist.AddObservation(1e12); // should be in the last bucket
var data = hist.GetSnapshot();
Assert.AreEqual(1, data.Bucket[0]);
Assert.AreEqual(1, data.Bucket[data.Bucket.Count - 1]);
}
[Test]
public void Reset()
{
var hist = new Histogram(0.01, 60e9);
hist.AddObservation(10000);
hist.AddObservation(11000);
var data = hist.GetSnapshot(true); // snapshot contains data before reset
Assert.AreEqual(2, data.Count);
Assert.AreEqual(10000, data.MinSeen);
Assert.AreEqual(11000, data.MaxSeen);
data = hist.GetSnapshot(); // snapshot contains state after reset
Assert.AreEqual(0, data.Count);
Assert.AreEqual(double.PositiveInfinity, data.MinSeen);
Assert.AreEqual(double.NegativeInfinity, data.MaxSeen);
Assert.AreEqual(0, data.Sum);
Assert.AreEqual(0, data.SumOfSquares);
CollectionAssert.AreEqual(new uint[data.Bucket.Count], data.Bucket);
}
}
}

@ -0,0 +1,67 @@
#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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using NUnit.Framework;
using Grpc.Testing;
namespace Grpc.IntegrationTesting
{
/// <summary>
/// Abstract client runner.
/// </summary>
public interface IClientRunner
{
/// <summary>
/// Gets stats snapshot.
/// </summary>
/// <returns>The stats.</returns>
ClientStats GetStats(bool reset);
/// <summary>
/// Asynchronously stops the client.
/// </summary>
/// <returns>Task that finishes when client has come to a full stop.</returns>
Task StopAsync();
}
}

@ -0,0 +1,72 @@
#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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using NUnit.Framework;
using Grpc.Testing;
namespace Grpc.IntegrationTesting
{
/// <summary>
/// Abstract server runner.
/// </summary>
public interface IServerRunner
{
/// <summary>
/// Port on which the server is listening.
/// </summary>
int BoundPort { get; }
/// <summary>
/// Gets server stats.
/// </summary>
/// <returns>The stats.</returns>
ServerStats GetStats(bool reset);
/// <summary>
/// Asynchronously stops the server.
/// </summary>
/// <returns>Task that finishes when server has shutdown.</returns>
Task StopAsync();
}
}

@ -0,0 +1,580 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: test/proto/benchmarks/payloads.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static partial class Payloads {
#region Descriptor
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static Payloads() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CiR0ZXN0L3Byb3RvL2JlbmNobWFya3MvcGF5bG9hZHMucHJvdG8SDGdycGMu",
"dGVzdGluZyI3ChBCeXRlQnVmZmVyUGFyYW1zEhAKCHJlcV9zaXplGAEgASgF",
"EhEKCXJlc3Bfc2l6ZRgCIAEoBSI4ChFTaW1wbGVQcm90b1BhcmFtcxIQCghy",
"ZXFfc2l6ZRgBIAEoBRIRCglyZXNwX3NpemUYAiABKAUiFAoSQ29tcGxleFBy",
"b3RvUGFyYW1zIsoBCg1QYXlsb2FkQ29uZmlnEjgKDmJ5dGVidWZfcGFyYW1z",
"GAEgASgLMh4uZ3JwYy50ZXN0aW5nLkJ5dGVCdWZmZXJQYXJhbXNIABI4Cg1z",
"aW1wbGVfcGFyYW1zGAIgASgLMh8uZ3JwYy50ZXN0aW5nLlNpbXBsZVByb3Rv",
"UGFyYW1zSAASOgoOY29tcGxleF9wYXJhbXMYAyABKAsyIC5ncnBjLnRlc3Rp",
"bmcuQ29tcGxleFByb3RvUGFyYW1zSABCCQoHcGF5bG9hZGIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ByteBufferParams), new[]{ "ReqSize", "RespSize" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleProtoParams), new[]{ "ReqSize", "RespSize" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ComplexProtoParams), null, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.PayloadConfig), new[]{ "BytebufParams", "SimpleParams", "ComplexParams" }, new[]{ "Payload" }, null, null)
}));
}
#endregion
}
#region Messages
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class ByteBufferParams : pb::IMessage<ByteBufferParams> {
private static readonly pb::MessageParser<ByteBufferParams> _parser = new pb::MessageParser<ByteBufferParams>(() => new ByteBufferParams());
public static pb::MessageParser<ByteBufferParams> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[0]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public ByteBufferParams() {
OnConstruction();
}
partial void OnConstruction();
public ByteBufferParams(ByteBufferParams other) : this() {
reqSize_ = other.reqSize_;
respSize_ = other.respSize_;
}
public ByteBufferParams Clone() {
return new ByteBufferParams(this);
}
public const int ReqSizeFieldNumber = 1;
private int reqSize_;
public int ReqSize {
get { return reqSize_; }
set {
reqSize_ = value;
}
}
public const int RespSizeFieldNumber = 2;
private int respSize_;
public int RespSize {
get { return respSize_; }
set {
respSize_ = value;
}
}
public override bool Equals(object other) {
return Equals(other as ByteBufferParams);
}
public bool Equals(ByteBufferParams other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (ReqSize != other.ReqSize) return false;
if (RespSize != other.RespSize) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
if (RespSize != 0) hash ^= RespSize.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (ReqSize != 0) {
output.WriteRawTag(8);
output.WriteInt32(ReqSize);
}
if (RespSize != 0) {
output.WriteRawTag(16);
output.WriteInt32(RespSize);
}
}
public int CalculateSize() {
int size = 0;
if (ReqSize != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize);
}
if (RespSize != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
}
return size;
}
public void MergeFrom(ByteBufferParams other) {
if (other == null) {
return;
}
if (other.ReqSize != 0) {
ReqSize = other.ReqSize;
}
if (other.RespSize != 0) {
RespSize = other.RespSize;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 8: {
ReqSize = input.ReadInt32();
break;
}
case 16: {
RespSize = input.ReadInt32();
break;
}
}
}
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class SimpleProtoParams : pb::IMessage<SimpleProtoParams> {
private static readonly pb::MessageParser<SimpleProtoParams> _parser = new pb::MessageParser<SimpleProtoParams>(() => new SimpleProtoParams());
public static pb::MessageParser<SimpleProtoParams> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[1]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public SimpleProtoParams() {
OnConstruction();
}
partial void OnConstruction();
public SimpleProtoParams(SimpleProtoParams other) : this() {
reqSize_ = other.reqSize_;
respSize_ = other.respSize_;
}
public SimpleProtoParams Clone() {
return new SimpleProtoParams(this);
}
public const int ReqSizeFieldNumber = 1;
private int reqSize_;
public int ReqSize {
get { return reqSize_; }
set {
reqSize_ = value;
}
}
public const int RespSizeFieldNumber = 2;
private int respSize_;
public int RespSize {
get { return respSize_; }
set {
respSize_ = value;
}
}
public override bool Equals(object other) {
return Equals(other as SimpleProtoParams);
}
public bool Equals(SimpleProtoParams other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (ReqSize != other.ReqSize) return false;
if (RespSize != other.RespSize) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
if (RespSize != 0) hash ^= RespSize.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (ReqSize != 0) {
output.WriteRawTag(8);
output.WriteInt32(ReqSize);
}
if (RespSize != 0) {
output.WriteRawTag(16);
output.WriteInt32(RespSize);
}
}
public int CalculateSize() {
int size = 0;
if (ReqSize != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize);
}
if (RespSize != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
}
return size;
}
public void MergeFrom(SimpleProtoParams other) {
if (other == null) {
return;
}
if (other.ReqSize != 0) {
ReqSize = other.ReqSize;
}
if (other.RespSize != 0) {
RespSize = other.RespSize;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 8: {
ReqSize = input.ReadInt32();
break;
}
case 16: {
RespSize = input.ReadInt32();
break;
}
}
}
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class ComplexProtoParams : pb::IMessage<ComplexProtoParams> {
private static readonly pb::MessageParser<ComplexProtoParams> _parser = new pb::MessageParser<ComplexProtoParams>(() => new ComplexProtoParams());
public static pb::MessageParser<ComplexProtoParams> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[2]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public ComplexProtoParams() {
OnConstruction();
}
partial void OnConstruction();
public ComplexProtoParams(ComplexProtoParams other) : this() {
}
public ComplexProtoParams Clone() {
return new ComplexProtoParams(this);
}
public override bool Equals(object other) {
return Equals(other as ComplexProtoParams);
}
public bool Equals(ComplexProtoParams other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
return true;
}
public override int GetHashCode() {
int hash = 1;
return hash;
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
}
public void WriteTo(pb::CodedOutputStream output) {
}
public int CalculateSize() {
int size = 0;
return size;
}
public void MergeFrom(ComplexProtoParams other) {
if (other == null) {
return;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
}
}
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class PayloadConfig : pb::IMessage<PayloadConfig> {
private static readonly pb::MessageParser<PayloadConfig> _parser = new pb::MessageParser<PayloadConfig>(() => new PayloadConfig());
public static pb::MessageParser<PayloadConfig> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[3]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public PayloadConfig() {
OnConstruction();
}
partial void OnConstruction();
public PayloadConfig(PayloadConfig other) : this() {
switch (other.PayloadCase) {
case PayloadOneofCase.BytebufParams:
BytebufParams = other.BytebufParams.Clone();
break;
case PayloadOneofCase.SimpleParams:
SimpleParams = other.SimpleParams.Clone();
break;
case PayloadOneofCase.ComplexParams:
ComplexParams = other.ComplexParams.Clone();
break;
}
}
public PayloadConfig Clone() {
return new PayloadConfig(this);
}
public const int BytebufParamsFieldNumber = 1;
public global::Grpc.Testing.ByteBufferParams BytebufParams {
get { return payloadCase_ == PayloadOneofCase.BytebufParams ? (global::Grpc.Testing.ByteBufferParams) payload_ : null; }
set {
payload_ = value;
payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.BytebufParams;
}
}
public const int SimpleParamsFieldNumber = 2;
public global::Grpc.Testing.SimpleProtoParams SimpleParams {
get { return payloadCase_ == PayloadOneofCase.SimpleParams ? (global::Grpc.Testing.SimpleProtoParams) payload_ : null; }
set {
payload_ = value;
payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.SimpleParams;
}
}
public const int ComplexParamsFieldNumber = 3;
public global::Grpc.Testing.ComplexProtoParams ComplexParams {
get { return payloadCase_ == PayloadOneofCase.ComplexParams ? (global::Grpc.Testing.ComplexProtoParams) payload_ : null; }
set {
payload_ = value;
payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.ComplexParams;
}
}
private object payload_;
public enum PayloadOneofCase {
None = 0,
BytebufParams = 1,
SimpleParams = 2,
ComplexParams = 3,
}
private PayloadOneofCase payloadCase_ = PayloadOneofCase.None;
public PayloadOneofCase PayloadCase {
get { return payloadCase_; }
}
public void ClearPayload() {
payloadCase_ = PayloadOneofCase.None;
payload_ = null;
}
public override bool Equals(object other) {
return Equals(other as PayloadConfig);
}
public bool Equals(PayloadConfig other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (!object.Equals(BytebufParams, other.BytebufParams)) return false;
if (!object.Equals(SimpleParams, other.SimpleParams)) return false;
if (!object.Equals(ComplexParams, other.ComplexParams)) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (payloadCase_ == PayloadOneofCase.BytebufParams) hash ^= BytebufParams.GetHashCode();
if (payloadCase_ == PayloadOneofCase.SimpleParams) hash ^= SimpleParams.GetHashCode();
if (payloadCase_ == PayloadOneofCase.ComplexParams) hash ^= ComplexParams.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (payloadCase_ == PayloadOneofCase.BytebufParams) {
output.WriteRawTag(10);
output.WriteMessage(BytebufParams);
}
if (payloadCase_ == PayloadOneofCase.SimpleParams) {
output.WriteRawTag(18);
output.WriteMessage(SimpleParams);
}
if (payloadCase_ == PayloadOneofCase.ComplexParams) {
output.WriteRawTag(26);
output.WriteMessage(ComplexParams);
}
}
public int CalculateSize() {
int size = 0;
if (payloadCase_ == PayloadOneofCase.BytebufParams) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(BytebufParams);
}
if (payloadCase_ == PayloadOneofCase.SimpleParams) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(SimpleParams);
}
if (payloadCase_ == PayloadOneofCase.ComplexParams) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(ComplexParams);
}
return size;
}
public void MergeFrom(PayloadConfig other) {
if (other == null) {
return;
}
switch (other.PayloadCase) {
case PayloadOneofCase.BytebufParams:
BytebufParams = other.BytebufParams;
break;
case PayloadOneofCase.SimpleParams:
SimpleParams = other.SimpleParams;
break;
case PayloadOneofCase.ComplexParams:
ComplexParams = other.ComplexParams;
break;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 10: {
global::Grpc.Testing.ByteBufferParams subBuilder = new global::Grpc.Testing.ByteBufferParams();
if (payloadCase_ == PayloadOneofCase.BytebufParams) {
subBuilder.MergeFrom(BytebufParams);
}
input.ReadMessage(subBuilder);
BytebufParams = subBuilder;
break;
}
case 18: {
global::Grpc.Testing.SimpleProtoParams subBuilder = new global::Grpc.Testing.SimpleProtoParams();
if (payloadCase_ == PayloadOneofCase.SimpleParams) {
subBuilder.MergeFrom(SimpleParams);
}
input.ReadMessage(subBuilder);
SimpleParams = subBuilder;
break;
}
case 26: {
global::Grpc.Testing.ComplexProtoParams subBuilder = new global::Grpc.Testing.ComplexProtoParams();
if (payloadCase_ == PayloadOneofCase.ComplexParams) {
subBuilder.MergeFrom(ComplexParams);
}
input.ReadMessage(subBuilder);
ComplexParams = subBuilder;
break;
}
}
}
}
}
#endregion
}
#endregion Designer generated code

@ -0,0 +1,108 @@
#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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CommandLine;
using CommandLine.Text;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
{
public class QpsWorker
{
private class ServerOptions
{
[Option("driver_port", DefaultValue = 0)]
public int DriverPort { get; set; }
[HelpOption]
public string GetUsage()
{
var help = new HelpText
{
Heading = "gRPC C# performance testing worker",
AddDashesToOption = true
};
help.AddPreOptionsLine("Usage:");
help.AddOptions(this);
return help;
}
}
ServerOptions options;
private QpsWorker(ServerOptions options)
{
this.options = options;
}
public static void Run(string[] args)
{
var options = new ServerOptions();
if (!Parser.Default.ParseArguments(args, options))
{
Environment.Exit(1);
}
var workerServer = new QpsWorker(options);
workerServer.Run();
}
private void Run()
{
string host = "0.0.0.0";
int port = options.DriverPort;
var server = new Server
{
Services = { WorkerService.BindService(new WorkerServiceImpl()) },
Ports = { new ServerPort(host, options.DriverPort, ServerCredentials.Insecure )}
};
int boundPort = server.Ports.Single().BoundPort;
Console.WriteLine("Running qps worker server on " + string.Format("{0}:{1}", host, boundPort));
server.Start();
server.ShutdownTask.Wait();
}
}
}

@ -0,0 +1,117 @@
#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.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
{
/// <summary>
/// Runs performance tests in-process.
/// </summary>
public class RunnerClientServerTest
{
const string Host = "localhost";
IServerRunner serverRunner;
[TestFixtureSetUp]
public void Init()
{
var serverConfig = new ServerConfig
{
ServerType = ServerType.ASYNC_SERVER,
Host = Host,
PayloadConfig = new PayloadConfig
{
SimpleParams = new SimpleProtoParams
{
RespSize = 100
}
}
};
serverRunner = ServerRunners.CreateStarted(serverConfig);
}
[TestFixtureTearDown]
public void Cleanup()
{
serverRunner.StopAsync().Wait();
}
// Test attribute commented out to prevent running as part of the default test suite.
//[Test]
//[Category("Performance")]
public async Task ClientServerRunner()
{
var config = new ClientConfig
{
ServerTargets = { string.Format("{0}:{1}", Host, serverRunner.BoundPort) },
RpcType = RpcType.UNARY,
LoadParams = new LoadParams { ClosedLoop = new ClosedLoopParams() },
PayloadConfig = new PayloadConfig
{
SimpleParams = new SimpleProtoParams
{
ReqSize = 100
}
},
HistogramParams = new HistogramParams
{
Resolution = 0.01,
MaxPossible = 60e9
}
};
var runner = ClientRunners.CreateStarted(config);
System.Console.WriteLine("Warming up");
await Task.Delay(3000);
runner.GetStats(true); // throw away warm-up data
System.Console.WriteLine("Benchmarking");
await Task.Delay(3000);
var stats = runner.GetStats(true);
await runner.StopAsync();
System.Console.WriteLine(stats);
System.Console.WriteLine("avg micros/call " + (long) (stats.Latencies.Sum / stats.Latencies.Count / 1000.0));
}
}
}

@ -0,0 +1,124 @@
#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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using NUnit.Framework;
using Grpc.Testing;
namespace Grpc.IntegrationTesting
{
/// <summary>
/// Helper methods to start server runners for performance testing.
/// </summary>
public static class ServerRunners
{
/// <summary>
/// Creates a started server runner.
/// </summary>
public static IServerRunner CreateStarted(ServerConfig config)
{
Grpc.Core.Utils.Preconditions.CheckArgument(config.ServerType == ServerType.ASYNC_SERVER);
var credentials = config.SecurityParams != null ? TestCredentials.CreateSslServerCredentials() : ServerCredentials.Insecure;
// TODO: qps_driver needs to setup payload properly...
int responseSize = config.PayloadConfig != null ? config.PayloadConfig.SimpleParams.RespSize : 0;
var server = new Server
{
Services = { BenchmarkService.BindService(new BenchmarkServiceImpl(responseSize)) },
Ports = { new ServerPort(config.Host, config.Port, credentials) }
};
server.Start();
return new ServerRunnerImpl(server);
}
}
/// <summary>
/// Server runner.
/// </summary>
public class ServerRunnerImpl : IServerRunner
{
readonly Server server;
readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
public ServerRunnerImpl(Server server)
{
this.server = Grpc.Core.Utils.Preconditions.CheckNotNull(server);
}
public int BoundPort
{
get
{
return server.Ports.Single().BoundPort;
}
}
/// <summary>
/// Gets server stats.
/// </summary>
/// <returns>The stats.</returns>
public ServerStats GetStats(bool reset)
{
var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds;
// TODO: populate user time and system time
return new ServerStats
{
TimeElapsed = secondsElapsed,
TimeUser = 0,
TimeSystem = 0
};
}
/// <summary>
/// Asynchronously stops the server.
/// </summary>
/// <returns>Task that finishes when server has shutdown.</returns>
public Task StopAsync()
{
return server.ShutdownAsync();
}
}
}

@ -0,0 +1,44 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: test/proto/benchmarks/services.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static partial class Services {
#region Descriptor
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static Services() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CiR0ZXN0L3Byb3RvL2JlbmNobWFya3Mvc2VydmljZXMucHJvdG8SDGdycGMu",
"dGVzdGluZxoZdGVzdC9wcm90by9tZXNzYWdlcy5wcm90bxojdGVzdC9wcm90",
"by9iZW5jaG1hcmtzL2NvbnRyb2wucHJvdG8yqgEKEEJlbmNobWFya1NlcnZp",
"Y2USRgoJVW5hcnlDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3Qa",
"HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2USTgoNU3RyZWFtaW5nQ2Fs",
"bBIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5n",
"LlNpbXBsZVJlc3BvbnNlKAEwATKdAQoNV29ya2VyU2VydmljZRJFCglSdW5T",
"ZXJ2ZXISGC5ncnBjLnRlc3RpbmcuU2VydmVyQXJncxoaLmdycGMudGVzdGlu",
"Zy5TZXJ2ZXJTdGF0dXMoATABEkUKCVJ1bkNsaWVudBIYLmdycGMudGVzdGlu",
"Zy5DbGllbnRBcmdzGhouZ3JwYy50ZXN0aW5nLkNsaWVudFN0YXR1cygBMAFi",
"BnByb3RvMw=="));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { global::Grpc.Testing.Messages.Descriptor, global::Grpc.Testing.Control.Descriptor, },
new pbr::GeneratedCodeInfo(null, null));
}
#endregion
}
}
#endregion Designer generated code

@ -0,0 +1,198 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: test/proto/benchmarks/services.proto
#region Designer generated code
using System;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
namespace Grpc.Testing {
public static class BenchmarkService
{
static readonly string __ServiceName = "grpc.testing.BenchmarkService";
static readonly Marshaller<global::Grpc.Testing.SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom);
static readonly Marshaller<global::Grpc.Testing.SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom);
static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_UnaryCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
MethodType.Unary,
__ServiceName,
"UnaryCall",
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
MethodType.DuplexStreaming,
__ServiceName,
"StreamingCall",
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
// service descriptor
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.Services.Descriptor.Services[0]; }
}
// client interface
public interface IBenchmarkServiceClient
{
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options);
AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(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, CallOptions options);
AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options);
}
// server-side interface
public interface IBenchmarkService
{
Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context);
Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context);
}
// client stub
public class BenchmarkServiceClient : ClientBase, IBenchmarkServiceClient
{
public BenchmarkServiceClient(Channel channel) : base(channel)
{
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.BlockingUnaryCall(call, request);
}
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(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.AsyncUnaryCall(call, request);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_StreamingCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
{
var call = CreateCall(__Method_StreamingCall, options);
return Calls.AsyncDuplexStreamingCall(call);
}
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(IBenchmarkService serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
}
// creates a new client
public static BenchmarkServiceClient NewClient(Channel channel)
{
return new BenchmarkServiceClient(channel);
}
}
public static class WorkerService
{
static readonly string __ServiceName = "grpc.testing.WorkerService";
static readonly Marshaller<global::Grpc.Testing.ServerArgs> __Marshaller_ServerArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerArgs.Parser.ParseFrom);
static readonly Marshaller<global::Grpc.Testing.ServerStatus> __Marshaller_ServerStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerStatus.Parser.ParseFrom);
static readonly Marshaller<global::Grpc.Testing.ClientArgs> __Marshaller_ClientArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientArgs.Parser.ParseFrom);
static readonly Marshaller<global::Grpc.Testing.ClientStatus> __Marshaller_ClientStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientStatus.Parser.ParseFrom);
static readonly Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> __Method_RunServer = new Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus>(
MethodType.DuplexStreaming,
__ServiceName,
"RunServer",
__Marshaller_ServerArgs,
__Marshaller_ServerStatus);
static readonly Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> __Method_RunClient = new Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus>(
MethodType.DuplexStreaming,
__ServiceName,
"RunClient",
__Marshaller_ClientArgs,
__Marshaller_ClientStatus);
// service descriptor
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.Services.Descriptor.Services[1]; }
}
// client interface
public interface IWorkerServiceClient
{
AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options);
AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options);
}
// server-side interface
public interface IWorkerService
{
Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context);
Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context);
}
// client stub
public class WorkerServiceClient : ClientBase, IWorkerServiceClient
{
public WorkerServiceClient(Channel channel) : base(channel)
{
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_RunServer, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
{
var call = CreateCall(__Method_RunServer, options);
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_RunClient, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
{
var call = CreateCall(__Method_RunClient, options);
return Calls.AsyncDuplexStreamingCall(call);
}
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(IWorkerService serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_RunServer, serviceImpl.RunServer)
.AddMethod(__Method_RunClient, serviceImpl.RunClient).Build();
}
// creates a new client
public static WorkerServiceClient NewClient(Channel channel)
{
return new WorkerServiceClient(channel);
}
}
}
#endregion

@ -1,7 +1,10 @@
<StyleCopSettings Version="105">
<SourceFileList>
<SourceFile>Messages.cs</SourceFile>
<SourceFile>Empty.cs</SourceFile>
<SourceFile>Control.cs</SourceFile>
<SourceFile>Messages.cs</SourceFile>
<SourceFile>Payloads.cs</SourceFile>
<SourceFile>Stats.cs</SourceFile>
<Settings>
<GlobalSettings>
<BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>

@ -0,0 +1,744 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: test/proto/benchmarks/stats.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static partial class Stats {
#region Descriptor
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static Stats() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CiF0ZXN0L3Byb3RvL2JlbmNobWFya3Mvc3RhdHMucHJvdG8SDGdycGMudGVz",
"dGluZyJLCgtTZXJ2ZXJTdGF0cxIUCgx0aW1lX2VsYXBzZWQYASABKAESEQoJ",
"dGltZV91c2VyGAIgASgBEhMKC3RpbWVfc3lzdGVtGAMgASgBIjsKD0hpc3Rv",
"Z3JhbVBhcmFtcxISCgpyZXNvbHV0aW9uGAEgASgBEhQKDG1heF9wb3NzaWJs",
"ZRgCIAEoASJ3Cg1IaXN0b2dyYW1EYXRhEg4KBmJ1Y2tldBgBIAMoDRIQCght",
"aW5fc2VlbhgCIAEoARIQCghtYXhfc2VlbhgDIAEoARILCgNzdW0YBCABKAES",
"FgoOc3VtX29mX3NxdWFyZXMYBSABKAESDQoFY291bnQYBiABKAEiewoLQ2xp",
"ZW50U3RhdHMSLgoJbGF0ZW5jaWVzGAEgASgLMhsuZ3JwYy50ZXN0aW5nLkhp",
"c3RvZ3JhbURhdGESFAoMdGltZV9lbGFwc2VkGAIgASgBEhEKCXRpbWVfdXNl",
"chgDIAEoARITCgt0aW1lX3N5c3RlbRgEIAEoAWIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStats), new[]{ "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramParams), new[]{ "Resolution", "MaxPossible" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramData), new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStats), new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null)
}));
}
#endregion
}
#region Messages
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class ServerStats : pb::IMessage<ServerStats> {
private static readonly pb::MessageParser<ServerStats> _parser = new pb::MessageParser<ServerStats>(() => new ServerStats());
public static pb::MessageParser<ServerStats> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[0]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public ServerStats() {
OnConstruction();
}
partial void OnConstruction();
public ServerStats(ServerStats other) : this() {
timeElapsed_ = other.timeElapsed_;
timeUser_ = other.timeUser_;
timeSystem_ = other.timeSystem_;
}
public ServerStats Clone() {
return new ServerStats(this);
}
public const int TimeElapsedFieldNumber = 1;
private double timeElapsed_;
public double TimeElapsed {
get { return timeElapsed_; }
set {
timeElapsed_ = value;
}
}
public const int TimeUserFieldNumber = 2;
private double timeUser_;
public double TimeUser {
get { return timeUser_; }
set {
timeUser_ = value;
}
}
public const int TimeSystemFieldNumber = 3;
private double timeSystem_;
public double TimeSystem {
get { return timeSystem_; }
set {
timeSystem_ = value;
}
}
public override bool Equals(object other) {
return Equals(other as ServerStats);
}
public bool Equals(ServerStats other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (TimeElapsed != other.TimeElapsed) return false;
if (TimeUser != other.TimeUser) return false;
if (TimeSystem != other.TimeSystem) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (TimeElapsed != 0D) {
output.WriteRawTag(9);
output.WriteDouble(TimeElapsed);
}
if (TimeUser != 0D) {
output.WriteRawTag(17);
output.WriteDouble(TimeUser);
}
if (TimeSystem != 0D) {
output.WriteRawTag(25);
output.WriteDouble(TimeSystem);
}
}
public int CalculateSize() {
int size = 0;
if (TimeElapsed != 0D) {
size += 1 + 8;
}
if (TimeUser != 0D) {
size += 1 + 8;
}
if (TimeSystem != 0D) {
size += 1 + 8;
}
return size;
}
public void MergeFrom(ServerStats other) {
if (other == null) {
return;
}
if (other.TimeElapsed != 0D) {
TimeElapsed = other.TimeElapsed;
}
if (other.TimeUser != 0D) {
TimeUser = other.TimeUser;
}
if (other.TimeSystem != 0D) {
TimeSystem = other.TimeSystem;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 9: {
TimeElapsed = input.ReadDouble();
break;
}
case 17: {
TimeUser = input.ReadDouble();
break;
}
case 25: {
TimeSystem = input.ReadDouble();
break;
}
}
}
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class HistogramParams : pb::IMessage<HistogramParams> {
private static readonly pb::MessageParser<HistogramParams> _parser = new pb::MessageParser<HistogramParams>(() => new HistogramParams());
public static pb::MessageParser<HistogramParams> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[1]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public HistogramParams() {
OnConstruction();
}
partial void OnConstruction();
public HistogramParams(HistogramParams other) : this() {
resolution_ = other.resolution_;
maxPossible_ = other.maxPossible_;
}
public HistogramParams Clone() {
return new HistogramParams(this);
}
public const int ResolutionFieldNumber = 1;
private double resolution_;
public double Resolution {
get { return resolution_; }
set {
resolution_ = value;
}
}
public const int MaxPossibleFieldNumber = 2;
private double maxPossible_;
public double MaxPossible {
get { return maxPossible_; }
set {
maxPossible_ = value;
}
}
public override bool Equals(object other) {
return Equals(other as HistogramParams);
}
public bool Equals(HistogramParams other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Resolution != other.Resolution) return false;
if (MaxPossible != other.MaxPossible) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (Resolution != 0D) hash ^= Resolution.GetHashCode();
if (MaxPossible != 0D) hash ^= MaxPossible.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (Resolution != 0D) {
output.WriteRawTag(9);
output.WriteDouble(Resolution);
}
if (MaxPossible != 0D) {
output.WriteRawTag(17);
output.WriteDouble(MaxPossible);
}
}
public int CalculateSize() {
int size = 0;
if (Resolution != 0D) {
size += 1 + 8;
}
if (MaxPossible != 0D) {
size += 1 + 8;
}
return size;
}
public void MergeFrom(HistogramParams other) {
if (other == null) {
return;
}
if (other.Resolution != 0D) {
Resolution = other.Resolution;
}
if (other.MaxPossible != 0D) {
MaxPossible = other.MaxPossible;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 9: {
Resolution = input.ReadDouble();
break;
}
case 17: {
MaxPossible = input.ReadDouble();
break;
}
}
}
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class HistogramData : pb::IMessage<HistogramData> {
private static readonly pb::MessageParser<HistogramData> _parser = new pb::MessageParser<HistogramData>(() => new HistogramData());
public static pb::MessageParser<HistogramData> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[2]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public HistogramData() {
OnConstruction();
}
partial void OnConstruction();
public HistogramData(HistogramData other) : this() {
bucket_ = other.bucket_.Clone();
minSeen_ = other.minSeen_;
maxSeen_ = other.maxSeen_;
sum_ = other.sum_;
sumOfSquares_ = other.sumOfSquares_;
count_ = other.count_;
}
public HistogramData Clone() {
return new HistogramData(this);
}
public const int BucketFieldNumber = 1;
private static readonly pb::FieldCodec<uint> _repeated_bucket_codec
= pb::FieldCodec.ForUInt32(10);
private readonly pbc::RepeatedField<uint> bucket_ = new pbc::RepeatedField<uint>();
public pbc::RepeatedField<uint> Bucket {
get { return bucket_; }
}
public const int MinSeenFieldNumber = 2;
private double minSeen_;
public double MinSeen {
get { return minSeen_; }
set {
minSeen_ = value;
}
}
public const int MaxSeenFieldNumber = 3;
private double maxSeen_;
public double MaxSeen {
get { return maxSeen_; }
set {
maxSeen_ = value;
}
}
public const int SumFieldNumber = 4;
private double sum_;
public double Sum {
get { return sum_; }
set {
sum_ = value;
}
}
public const int SumOfSquaresFieldNumber = 5;
private double sumOfSquares_;
public double SumOfSquares {
get { return sumOfSquares_; }
set {
sumOfSquares_ = value;
}
}
public const int CountFieldNumber = 6;
private double count_;
public double Count {
get { return count_; }
set {
count_ = value;
}
}
public override bool Equals(object other) {
return Equals(other as HistogramData);
}
public bool Equals(HistogramData other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if(!bucket_.Equals(other.bucket_)) return false;
if (MinSeen != other.MinSeen) return false;
if (MaxSeen != other.MaxSeen) return false;
if (Sum != other.Sum) return false;
if (SumOfSquares != other.SumOfSquares) return false;
if (Count != other.Count) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
hash ^= bucket_.GetHashCode();
if (MinSeen != 0D) hash ^= MinSeen.GetHashCode();
if (MaxSeen != 0D) hash ^= MaxSeen.GetHashCode();
if (Sum != 0D) hash ^= Sum.GetHashCode();
if (SumOfSquares != 0D) hash ^= SumOfSquares.GetHashCode();
if (Count != 0D) hash ^= Count.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
}
public void WriteTo(pb::CodedOutputStream output) {
bucket_.WriteTo(output, _repeated_bucket_codec);
if (MinSeen != 0D) {
output.WriteRawTag(17);
output.WriteDouble(MinSeen);
}
if (MaxSeen != 0D) {
output.WriteRawTag(25);
output.WriteDouble(MaxSeen);
}
if (Sum != 0D) {
output.WriteRawTag(33);
output.WriteDouble(Sum);
}
if (SumOfSquares != 0D) {
output.WriteRawTag(41);
output.WriteDouble(SumOfSquares);
}
if (Count != 0D) {
output.WriteRawTag(49);
output.WriteDouble(Count);
}
}
public int CalculateSize() {
int size = 0;
size += bucket_.CalculateSize(_repeated_bucket_codec);
if (MinSeen != 0D) {
size += 1 + 8;
}
if (MaxSeen != 0D) {
size += 1 + 8;
}
if (Sum != 0D) {
size += 1 + 8;
}
if (SumOfSquares != 0D) {
size += 1 + 8;
}
if (Count != 0D) {
size += 1 + 8;
}
return size;
}
public void MergeFrom(HistogramData other) {
if (other == null) {
return;
}
bucket_.Add(other.bucket_);
if (other.MinSeen != 0D) {
MinSeen = other.MinSeen;
}
if (other.MaxSeen != 0D) {
MaxSeen = other.MaxSeen;
}
if (other.Sum != 0D) {
Sum = other.Sum;
}
if (other.SumOfSquares != 0D) {
SumOfSquares = other.SumOfSquares;
}
if (other.Count != 0D) {
Count = other.Count;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 10:
case 8: {
bucket_.AddEntriesFrom(input, _repeated_bucket_codec);
break;
}
case 17: {
MinSeen = input.ReadDouble();
break;
}
case 25: {
MaxSeen = input.ReadDouble();
break;
}
case 33: {
Sum = input.ReadDouble();
break;
}
case 41: {
SumOfSquares = input.ReadDouble();
break;
}
case 49: {
Count = input.ReadDouble();
break;
}
}
}
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class ClientStats : pb::IMessage<ClientStats> {
private static readonly pb::MessageParser<ClientStats> _parser = new pb::MessageParser<ClientStats>(() => new ClientStats());
public static pb::MessageParser<ClientStats> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[3]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public ClientStats() {
OnConstruction();
}
partial void OnConstruction();
public ClientStats(ClientStats other) : this() {
Latencies = other.latencies_ != null ? other.Latencies.Clone() : null;
timeElapsed_ = other.timeElapsed_;
timeUser_ = other.timeUser_;
timeSystem_ = other.timeSystem_;
}
public ClientStats Clone() {
return new ClientStats(this);
}
public const int LatenciesFieldNumber = 1;
private global::Grpc.Testing.HistogramData latencies_;
public global::Grpc.Testing.HistogramData Latencies {
get { return latencies_; }
set {
latencies_ = value;
}
}
public const int TimeElapsedFieldNumber = 2;
private double timeElapsed_;
public double TimeElapsed {
get { return timeElapsed_; }
set {
timeElapsed_ = value;
}
}
public const int TimeUserFieldNumber = 3;
private double timeUser_;
public double TimeUser {
get { return timeUser_; }
set {
timeUser_ = value;
}
}
public const int TimeSystemFieldNumber = 4;
private double timeSystem_;
public double TimeSystem {
get { return timeSystem_; }
set {
timeSystem_ = value;
}
}
public override bool Equals(object other) {
return Equals(other as ClientStats);
}
public bool Equals(ClientStats other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (!object.Equals(Latencies, other.Latencies)) return false;
if (TimeElapsed != other.TimeElapsed) return false;
if (TimeUser != other.TimeUser) return false;
if (TimeSystem != other.TimeSystem) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (latencies_ != null) hash ^= Latencies.GetHashCode();
if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.Default.Format(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (latencies_ != null) {
output.WriteRawTag(10);
output.WriteMessage(Latencies);
}
if (TimeElapsed != 0D) {
output.WriteRawTag(17);
output.WriteDouble(TimeElapsed);
}
if (TimeUser != 0D) {
output.WriteRawTag(25);
output.WriteDouble(TimeUser);
}
if (TimeSystem != 0D) {
output.WriteRawTag(33);
output.WriteDouble(TimeSystem);
}
}
public int CalculateSize() {
int size = 0;
if (latencies_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies);
}
if (TimeElapsed != 0D) {
size += 1 + 8;
}
if (TimeUser != 0D) {
size += 1 + 8;
}
if (TimeSystem != 0D) {
size += 1 + 8;
}
return size;
}
public void MergeFrom(ClientStats other) {
if (other == null) {
return;
}
if (other.latencies_ != null) {
if (latencies_ == null) {
latencies_ = new global::Grpc.Testing.HistogramData();
}
Latencies.MergeFrom(other.Latencies);
}
if (other.TimeElapsed != 0D) {
TimeElapsed = other.TimeElapsed;
}
if (other.TimeUser != 0D) {
TimeUser = other.TimeUser;
}
if (other.TimeSystem != 0D) {
TimeSystem = other.TimeSystem;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 10: {
if (latencies_ == null) {
latencies_ = new global::Grpc.Testing.HistogramData();
}
input.ReadMessage(latencies_);
break;
}
case 17: {
TimeElapsed = input.ReadDouble();
break;
}
case 25: {
TimeUser = input.ReadDouble();
break;
}
case 33: {
TimeSystem = input.ReadDouble();
break;
}
}
}
}
}
#endregion
}
#endregion Designer generated code

@ -0,0 +1,78 @@
#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.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using NUnit.Framework;
using Grpc.Testing;
namespace Grpc.IntegrationTesting
{
/// <summary>
/// Snapshottable wall clock stopwatch.
/// </summary>
public class WallClockStopwatch
{
long startTicks;
public WallClockStopwatch()
{
this.startTicks = DateTime.UtcNow.Ticks;
}
public TimeSpan GetElapsedSnapshot(bool reset)
{
var utcNow = DateTime.UtcNow;
long oldStartTicks;
if (reset)
{
oldStartTicks = Interlocked.Exchange(ref this.startTicks, utcNow.Ticks);
}
else
{
oldStartTicks = this.startTicks;
}
return utcNow - new DateTime(oldStartTicks, DateTimeKind.Utc);
}
}
}

@ -0,0 +1,96 @@
#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.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.IntegrationTesting;
namespace Grpc.Testing
{
/// <summary>
/// Implementation of WorkerService server
/// </summary>
public class WorkerServiceImpl : WorkerService.IWorkerService
{
public async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
{
Grpc.Core.Utils.Preconditions.CheckState(await requestStream.MoveNext());
var serverConfig = requestStream.Current.Setup;
var runner = ServerRunners.CreateStarted(serverConfig);
await responseStream.WriteAsync(new ServerStatus
{
Stats = runner.GetStats(false),
Port = runner.BoundPort,
Cores = 0, // TODO: set number of cores
});
while (await requestStream.MoveNext())
{
var reset = requestStream.Current.Mark.Reset;
await responseStream.WriteAsync(new ServerStatus
{
Stats = runner.GetStats(reset)
});
}
await runner.StopAsync();
}
public async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context)
{
Grpc.Core.Utils.Preconditions.CheckState(await requestStream.MoveNext());
var clientConfig = requestStream.Current.Setup;
var runner = ClientRunners.CreateStarted(clientConfig);
await responseStream.WriteAsync(new ClientStatus
{
Stats = runner.GetStats(false)
});
while (await requestStream.MoveNext())
{
var reset = requestStream.Current.Mark.Reset;
await responseStream.WriteAsync(new ClientStatus
{
Stats = runner.GetStats(reset)
});
}
await runner.StopAsync();
}
}
}

@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5
MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl
c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs
JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO
RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30
3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL
BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6
b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ
KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS
wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e
aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s=
MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
-----END CERTIFICATE-----

@ -1,6 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
# Visual Studio 2012
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Examples", "Grpc.Examples\Grpc.Examples.csproj", "{7DC1433E-3225-42C7-B7EA-546D56E27A4B}"
@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck", "Grpc.He
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck.Tests", "Grpc.HealthCheck.Tests\Grpc.HealthCheck.Tests.csproj", "{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.QpsWorker", "Grpc.IntegrationTesting.QpsWorker\Grpc.IntegrationTesting.QpsWorker.csproj", "{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -39,72 +41,78 @@ Global
ReleaseSigned|Any CPU = ReleaseSigned|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.Build.0 = Release|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.Build.0 = Release|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.Build.0 = Release|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.Build.0 = Release|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.Build.0 = Release|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.Build.0 = Release|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.Build.0 = Release|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.Build.0 = Release|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.Build.0 = Release|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.Build.0 = Release|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.Build.0 = Release|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.Build.0 = Release|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.Build.0 = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|Any CPU.Build.0 = Release|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.Build.0 = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Release|Any CPU.Build.0 = Release|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.Build.0 = Release|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.Build.0 = Release|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.Build.0 = Release|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -112,6 +120,8 @@ Global
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection

@ -785,9 +785,10 @@ grpcsharp_call_send_initial_metadata(grpc_call *call,
NULL);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_set_credentials(grpc_call *call,
grpc_credentials *creds) {
return grpc_call_set_credentials(call, creds);
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_set_credentials(
grpc_call *call,
grpc_call_credentials *creds) {
return grpc_call_set_credentials(call, creds);
}
/* Server */
@ -834,7 +835,7 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq,
/* Security */
GPR_EXPORT grpc_credentials *GPR_CALLTYPE
GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE
grpcsharp_ssl_credentials_create(const char *pem_root_certs,
const char *key_cert_pair_cert_chain,
const char *key_cert_pair_private_key) {
@ -850,12 +851,19 @@ grpcsharp_ssl_credentials_create(const char *pem_root_certs,
}
}
GPR_EXPORT void GPR_CALLTYPE grpcsharp_credentials_release(grpc_credentials *creds) {
grpc_credentials_release(creds);
GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_credentials_release(
grpc_channel_credentials *creds) {
grpc_channel_credentials_release(creds);
}
GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_credentials_release(
grpc_call_credentials *creds) {
grpc_call_credentials_release(creds);
}
GPR_EXPORT grpc_channel *GPR_CALLTYPE
grpcsharp_secure_channel_create(grpc_credentials *creds, const char *target,
grpcsharp_secure_channel_create(grpc_channel_credentials *creds,
const char *target,
const grpc_channel_args *args) {
return grpc_secure_channel_create(creds, target, args, NULL);
}
@ -897,10 +905,16 @@ grpcsharp_server_add_secure_http2_port(grpc_server *server, const char *addr,
return grpc_server_add_secure_http2_port(server, addr, creds);
}
GPR_EXPORT grpc_credentials *GPR_CALLTYPE grpcsharp_composite_credentials_create(
grpc_credentials *creds1,
grpc_credentials *creds2) {
return grpc_composite_credentials_create(creds1, creds2, NULL);
GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE grpcsharp_composite_channel_credentials_create(
grpc_channel_credentials *channel_creds,
grpc_call_credentials *call_creds) {
return grpc_composite_channel_credentials_create(channel_creds, call_creds, NULL);
}
GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_composite_call_credentials_create(
grpc_call_credentials *creds1,
grpc_call_credentials *creds2) {
return grpc_composite_call_credentials_create(creds1, creds2, NULL);
}
/* Metadata credentials plugin */
@ -929,7 +943,7 @@ static void grpcsharp_metadata_credentials_destroy_handler(void *state) {
interceptor(state, NULL, NULL, NULL, 1);
}
GPR_EXPORT grpc_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin(
GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin(
grpcsharp_metadata_interceptor_func metadata_interceptor) {
grpc_metadata_credentials_plugin plugin;
plugin.get_metadata = grpcsharp_get_metadata_handler;

@ -35,14 +35,14 @@ cd $(dirname $0)
PROTOC=../../bins/opt/protobuf/protoc
PLUGIN=protoc-gen-grpc=../../bins/opt/grpc_csharp_plugin
EXAMPLES_DIR=Grpc.Examples
INTEROP_DIR=Grpc.IntegrationTesting
TESTING_DIR=Grpc.IntegrationTesting
HEALTHCHECK_DIR=Grpc.HealthCheck
$PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \
-I $EXAMPLES_DIR/proto $EXAMPLES_DIR/proto/math.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$INTEROP_DIR --grpc_out=$INTEROP_DIR \
-I ../.. ../../test/proto/*.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
-I ../.. ../../test/proto/*.proto ../../test/proto/benchmarks/*.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \
-I $HEALTHCHECK_DIR/proto $HEALTHCHECK_DIR/proto/health.proto

@ -757,7 +757,7 @@ NAN_METHOD(Call::SetCredentials) {
Call *call = ObjectWrap::Unwrap<Call>(info.This());
CallCredentials *creds_object = ObjectWrap::Unwrap<CallCredentials>(
Nan::To<Object>(info[0]).ToLocalChecked());
grpc_credentials *creds = creds_object->GetWrappedCredentials();
grpc_call_credentials *creds = creds_object->GetWrappedCredentials();
grpc_call_error error = GRPC_CALL_ERROR;
if (creds) {
error = grpc_call_set_credentials(call->wrapped_call, creds);

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

Loading…
Cancel
Save