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

pull/1408/head
David Garcia Quintas 10 years ago
commit 45d54e4581
  1. 8570
      Makefile
  2. 53
      gRPC.podspec
  3. 7
      include/grpc++/channel_interface.h
  4. 5
      include/grpc++/server.h
  5. 2
      src/core/support/alloc.c
  6. 2
      src/core/support/time_win32.c
  7. 29
      src/core/surface/completion_queue.c
  8. 3
      src/core/surface/completion_queue.h
  9. 5
      src/core/surface/server.c
  10. 1
      src/cpp/client/channel.h
  11. 9
      src/cpp/server/server.cc
  12. 3
      src/cpp/server/server_builder.cc
  13. 3
      src/csharp/Grpc.Auth/.gitignore
  14. 124
      src/csharp/Grpc.Auth/GoogleCredential.cs
  15. 93
      src/csharp/Grpc.Auth/Grpc.Auth.csproj
  16. 104
      src/csharp/Grpc.Auth/OAuth2InterceptorFactory.cs
  17. 14
      src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs
  18. 15
      src/csharp/Grpc.Auth/app.config
  19. 12
      src/csharp/Grpc.Auth/packages.config
  20. 3
      src/csharp/Grpc.Core/Grpc.Core.csproj
  21. 2
      src/csharp/Grpc.Core/RpcException.cs
  22. 5
      src/csharp/Grpc.Core/Status.cs
  23. 5
      src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
  24. 15
      src/csharp/Grpc.IntegrationTesting.Client/app.config
  25. 5
      src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
  26. 15
      src/csharp/Grpc.IntegrationTesting.Server/app.config
  27. 40
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  28. 69
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  29. 15
      src/csharp/Grpc.IntegrationTesting/app.config
  30. 7
      src/csharp/Grpc.IntegrationTesting/packages.config
  31. 6
      src/csharp/Grpc.sln
  32. 20
      src/objective-c/examples/Sample/Podfile.lock
  33. 1
      src/objective-c/examples/Sample/Pods/Headers/Public/GRPCClient/GRPCCall.h
  34. 1
      src/objective-c/examples/Sample/Pods/Headers/Public/GRPCClient/GRPCMethodName.h
  35. 1
      src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXImmediateWriter.h
  36. 1
      src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXMappingWriter.h
  37. 1
      src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriteable.h
  38. 1
      src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Immediate.h
  39. 1
      src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter+Transformations.h
  40. 1
      src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/GRXWriter.h
  41. 1
      src/objective-c/examples/Sample/Pods/Headers/Public/RxLibrary/NSEnumerator+GRXUtil.h
  42. 14
      src/objective-c/examples/Sample/Pods/Local Podspecs/GRPCClient.podspec
  43. 13
      src/objective-c/examples/Sample/Pods/Local Podspecs/RxLibrary.podspec
  44. 20
      src/objective-c/examples/Sample/Pods/Manifest.lock
  45. 22200
      src/objective-c/examples/Sample/Pods/Pods.xcodeproj/project.pbxproj
  46. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-GRPCClient/Pods-GRPCClient-Private.xcconfig
  47. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-GRPCClient/Pods-GRPCClient-dummy.m
  48. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-GRPCClient/Pods-GRPCClient-prefix.pch
  49. 0
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-GRPCClient/Pods-GRPCClient.xcconfig
  50. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-Private.xcconfig
  51. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-dummy.m
  52. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary-prefix.pch
  53. 0
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-RxLibrary/Pods-RxLibrary.xcconfig
  54. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-GRPCClient/Pods-Sample-GRPCClient-Private.xcconfig
  55. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-GRPCClient/Pods-Sample-GRPCClient-dummy.m
  56. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-GRPCClient/Pods-Sample-GRPCClient-prefix.pch
  57. 0
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-GRPCClient/Pods-Sample-GRPCClient.xcconfig
  58. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-Private.xcconfig
  59. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-dummy.m
  60. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary-prefix.pch
  61. 0
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample-RxLibrary/Pods-Sample-RxLibrary.xcconfig
  62. 3
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.markdown
  63. 29
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-acknowledgements.plist
  64. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-dummy.m
  65. 20
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-environment.h
  66. 74
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh
  67. 6
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig
  68. 6
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig
  69. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-GRPCClient/Pods-SampleTests-GRPCClient-Private.xcconfig
  70. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-GRPCClient/Pods-SampleTests-GRPCClient-dummy.m
  71. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-GRPCClient/Pods-SampleTests-GRPCClient-prefix.pch
  72. 0
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-GRPCClient/Pods-SampleTests-GRPCClient.xcconfig
  73. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-Private.xcconfig
  74. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-dummy.m
  75. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary-prefix.pch
  76. 0
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests-RxLibrary/Pods-SampleTests-RxLibrary.xcconfig
  77. 3
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.markdown
  78. 29
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-acknowledgements.plist
  79. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-dummy.m
  80. 20
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-environment.h
  81. 74
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests-resources.sh
  82. 6
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.debug.xcconfig
  83. 6
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods-SampleTests/Pods-SampleTests.release.xcconfig
  84. 3
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown
  85. 29
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-acknowledgements.plist
  86. 5
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-dummy.m
  87. 20
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-environment.h
  88. 74
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods-resources.sh
  89. 6
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.debug.xcconfig
  90. 6
      src/objective-c/examples/Sample/Pods/Target Support Files/Pods/Pods.release.xcconfig
  91. 3
      src/objective-c/examples/Sample/README.md
  92. 10
      src/objective-c/examples/Sample/Sample.xcworkspace/contents.xcworkspacedata
  93. 89
      src/objective-c/examples/Sample/SampleTests/RemoteProtoTests.m
  94. 5
      src/python/src/grpc/_adapter/_c_test.py
  95. 237
      src/python/src/grpc/_adapter/_call.c
  96. 28
      src/python/src/grpc/_adapter/_call.h
  97. 171
      src/python/src/grpc/_adapter/_completion_queue.c
  98. 8
      src/python/src/grpc/_adapter/_low_test.py
  99. 20
      src/python/src/grpc/_adapter/_server.c
  100. 4
      src/python/src/grpc/_adapter/_server.h
  101. Some files were not shown because too many files have changed in this diff Show More

8570
Makefile

File diff suppressed because it is too large Load Diff

@ -16,7 +16,9 @@ Pod::Spec.new do |s|
rs.summary = 'Reactive Extensions library for iOS.'
rs.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
rs.source_files = 'src/objective-c/RxLibrary/*.{h,m}', 'src/objective-c/RxLibrary/transformations/*.{h,m}', 'src/objective-c/RxLibrary/private/*.{h,m}'
rs.source_files = 'src/objective-c/RxLibrary/*.{h,m}',
'src/objective-c/RxLibrary/transformations/*.{h,m}',
'src/objective-c/RxLibrary/private/*.{h,m}'
rs.private_header_files = 'src/objective-c/RxLibrary/private/*.h'
end
@ -36,35 +38,38 @@ Pod::Spec.new do |s|
cs.requires_arc = false
cs.libraries = 'z'
cs.dependency 'OpenSSL', '~> 1.0.200'
# This is a workaround for Cocoapods Issue #1437.
# It renames time.h and string.h to grpc_time.h and grpc_string.h.
cs.prepare_command = <<-CMD
DIR_TIME="grpc/support"
BAD_TIME="$DIR_TIME/time.h"
GOOD_TIME="$DIR_TIME/grpc_time.h"
if [ -f "include/$BAD_TIME" ];
then
grep -rl "$BAD_TIME" include/grpc src/core | xargs sed -i '' -e s@$BAD_TIME@$GOOD_TIME@g
mv "include/$BAD_TIME" "include/$GOOD_TIME"
fi
DIR_STRING="src/core/support"
BAD_STRING="$DIR_STRING/string.h"
GOOD_STRING="$DIR_STRING/grpc_string.h"
if [ -f "$BAD_STRING" ];
then
grep -rl "$BAD_STRING" include/grpc src/core | xargs sed -i '' -e s@$BAD_STRING@$GOOD_STRING@g
mv "$BAD_STRING" "$GOOD_STRING"
fi
CMD
end
# This is a workaround for Cocoapods Issue #1437.
# It renames time.h and string.h to grpc_time.h and grpc_string.h.
# It needs to be here (top-level) instead of in the C-Core subspec because Cocoapods doesn't run
# prepare_command's of subspecs.
s.prepare_command = <<-CMD
DIR_TIME="grpc/support"
BAD_TIME="$DIR_TIME/time.h"
GOOD_TIME="$DIR_TIME/grpc_time.h"
if [ -f "include/$BAD_TIME" ];
then
grep -rl "$BAD_TIME" include/grpc src/core | xargs sed -i '' -e s@$BAD_TIME@$GOOD_TIME@g
mv "include/$BAD_TIME" "include/$GOOD_TIME"
fi
DIR_STRING="src/core/support"
BAD_STRING="$DIR_STRING/string.h"
GOOD_STRING="$DIR_STRING/grpc_string.h"
if [ -f "$BAD_STRING" ];
then
grep -rl "$BAD_STRING" include/grpc src/core | xargs sed -i '' -e s@$BAD_STRING@$GOOD_STRING@g
mv "$BAD_STRING" "$GOOD_STRING"
fi
CMD
s.subspec 'GRPCClient' do |gs|
gs.summary = 'Objective-C wrapper around the core gRPC library.'
gs.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
gs.source_files = 'src/objective-c/GRPCClient/*.{h,m}', 'src/objective-c/GRPCClient/private/*.{h,m}'
gs.source_files = 'src/objective-c/GRPCClient/*.{h,m}',
'src/objective-c/GRPCClient/private/*.{h,m}'
gs.private_header_files = 'src/objective-c/GRPCClient/private/*.h'
gs.dependency 'gRPC/C-Core'

@ -34,6 +34,8 @@
#ifndef GRPCXX_CHANNEL_INTERFACE_H
#define GRPCXX_CHANNEL_INTERFACE_H
#include <memory>
#include <grpc++/status.h>
#include <grpc++/impl/call.h>
@ -47,11 +49,12 @@ class CompletionQueue;
class RpcMethod;
class CallInterface;
class ChannelInterface : public CallHook {
class ChannelInterface : public CallHook,
public std::enable_shared_from_this<ChannelInterface> {
public:
virtual ~ChannelInterface() {}
virtual void *RegisterMethod(const char *method_name) = 0;
virtual void* RegisterMethod(const char* method_name) = 0;
virtual Call CreateCall(const RpcMethod& method, ClientContext* context,
CompletionQueue* cq) = 0;
};

@ -80,7 +80,6 @@ class Server GRPC_FINAL : public GrpcLibrary,
// ServerBuilder use only
Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned);
Server() = delete;
// Register a service. This call does not take ownership of the service.
// The service must exist for the lifetime of the Server instance.
bool RegisterService(RpcService* service);
@ -118,7 +117,7 @@ class Server GRPC_FINAL : public GrpcLibrary,
int num_running_cb_;
grpc::condition_variable callback_cv_;
std::list<SyncRequest> sync_methods_;
std::list<SyncRequest>* sync_methods_;
// Pointer to the c grpc server.
grpc_server* const server_;
@ -126,6 +125,8 @@ class Server GRPC_FINAL : public GrpcLibrary,
ThreadPoolInterface* thread_pool_;
// Whether the thread pool is created and owned by the server.
bool thread_pool_owned_;
private:
Server() : server_(NULL) { abort(); }
};
} // namespace grpc

@ -55,7 +55,7 @@ void *gpr_realloc(void *p, size_t size) {
}
void *gpr_malloc_aligned(size_t size, size_t alignment_log) {
size_t alignment = 1 << alignment_log;
size_t alignment = ((size_t)1) << alignment_log;
size_t extra = alignment - 1 + sizeof(void *);
void *p = gpr_malloc(size + extra);
void **ret = (void **)(((gpr_uintptr)p + extra) & ~(alignment - 1));

@ -64,7 +64,7 @@ void gpr_sleep_until(gpr_timespec until) {
}
delta = gpr_time_sub(until, now);
sleep_millis = delta.tv_sec * GPR_MS_PER_SEC + delta.tv_nsec / GPR_NS_PER_MS;
sleep_millis = (DWORD)delta.tv_sec * GPR_MS_PER_SEC + delta.tv_nsec / GPR_NS_PER_MS;
Sleep(sleep_millis);
}
}

@ -67,6 +67,8 @@ struct grpc_completion_queue {
/* When refs drops to zero, we are in shutdown mode, and will be destroyable
once all queued events are drained */
gpr_refcount refs;
/* Once owning_refs drops to zero, we will destroy the cq */
gpr_refcount owning_refs;
/* the set of low level i/o things that concern this cq */
grpc_pollset pollset;
/* 0 initially, 1 once we've begun shutting down */
@ -91,11 +93,29 @@ grpc_completion_queue *grpc_completion_queue_create(void) {
memset(cc, 0, sizeof(*cc));
/* Initial ref is dropped by grpc_completion_queue_shutdown */
gpr_ref_init(&cc->refs, 1);
gpr_ref_init(&cc->owning_refs, 1);
grpc_pollset_init(&cc->pollset);
cc->allow_polling = 1;
return cc;
}
void grpc_cq_internal_ref(grpc_completion_queue *cc) {
gpr_ref(&cc->owning_refs);
}
static void on_pollset_destroy_done(void *arg) {
grpc_completion_queue *cc = arg;
grpc_pollset_destroy(&cc->pollset);
gpr_free(cc);
}
void grpc_cq_internal_unref(grpc_completion_queue *cc) {
if (gpr_unref(&cc->owning_refs)) {
GPR_ASSERT(cc->queue == NULL);
grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
}
}
void grpc_completion_queue_dont_poll_test_only(grpc_completion_queue *cc) {
cc->allow_polling = 0;
}
@ -394,15 +414,8 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
}
}
static void on_pollset_destroy_done(void *arg) {
grpc_completion_queue *cc = arg;
grpc_pollset_destroy(&cc->pollset);
gpr_free(cc);
}
void grpc_completion_queue_destroy(grpc_completion_queue *cc) {
GPR_ASSERT(cc->queue == NULL);
grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
grpc_cq_internal_unref(cc);
}
void grpc_event_finish(grpc_event *base) {

@ -43,6 +43,9 @@
grpc_event_finish */
typedef void (*grpc_event_finish_func)(void *user_data, grpc_op_error error);
void grpc_cq_internal_ref(grpc_completion_queue *cc);
void grpc_cq_internal_unref(grpc_completion_queue *cc);
/* Flag that an operation is beginning: the completion channel will not finish
shutdown until a corrensponding grpc_cq_end_* call is made */
void grpc_cq_begin_op(grpc_completion_queue *cc, grpc_call *call,

@ -262,6 +262,7 @@ static void server_ref(grpc_server *server) {
static void server_unref(grpc_server *server) {
registered_method *rm;
size_t i;
if (gpr_unref(&server->internal_refcount)) {
grpc_channel_args_destroy(server->channel_args);
gpr_mu_destroy(&server->mu);
@ -275,6 +276,9 @@ static void server_unref(grpc_server *server) {
requested_call_array_destroy(&rm->requested);
gpr_free(rm);
}
for (i = 0; i < server->cq_count; i++) {
grpc_cq_internal_unref(server->cqs[i]);
}
gpr_free(server->cqs);
gpr_free(server->pollsets);
gpr_free(server->shutdown_tags);
@ -601,6 +605,7 @@ static void addcq(grpc_server *server, grpc_completion_queue *cq) {
for (i = 0; i < server->cq_count; i++) {
if (server->cqs[i] == cq) return;
}
grpc_cq_internal_ref(cq);
n = server->cq_count++;
server->cqs = gpr_realloc(server->cqs,
server->cq_count * sizeof(grpc_completion_queue *));

@ -51,7 +51,6 @@ class Credentials;
class StreamContextInterface;
class Channel GRPC_FINAL : public GrpcLibrary,
public std::enable_shared_from_this<Channel>,
public ChannelInterface {
public:
Channel(const grpc::string& target, grpc_channel* c_channel);

@ -180,6 +180,7 @@ Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned)
: started_(false),
shutdown_(false),
num_running_cb_(0),
sync_methods_(new std::list<SyncRequest>),
server_(grpc_server_create(cq_.cq(), nullptr)),
thread_pool_(thread_pool),
thread_pool_owned_(thread_pool_owned) {}
@ -196,6 +197,7 @@ Server::~Server() {
if (thread_pool_owned_) {
delete thread_pool_;
}
delete sync_methods_;
}
bool Server::RegisterService(RpcService* service) {
@ -208,7 +210,8 @@ bool Server::RegisterService(RpcService* service) {
method->name());
return false;
}
sync_methods_.emplace_back(method, tag);
SyncRequest request(method, tag);
sync_methods_->emplace_back(request);
}
return true;
}
@ -250,8 +253,8 @@ bool Server::Start() {
grpc_server_start(server_);
// Start processing rpcs.
if (!sync_methods_.empty()) {
for (auto m = sync_methods_.begin(); m != sync_methods_.end(); m++) {
if (!sync_methods_->empty()) {
for (auto m = sync_methods_->begin(); m != sync_methods_->end(); m++) {
m->Request(server_);
}

@ -66,7 +66,8 @@ void ServerBuilder::RegisterAsyncGenericService(AsyncGenericService* service) {
void ServerBuilder::AddListeningPort(const grpc::string& addr,
std::shared_ptr<ServerCredentials> creds,
int* selected_port) {
ports_.push_back(Port{addr, creds, selected_port});
Port port = {addr, creds, selected_port};
ports_.push_back(port);
}
void ServerBuilder::SetThreadPool(ThreadPoolInterface* thread_pool) {

@ -0,0 +1,3 @@
bin
obj
*.nupkg

@ -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.IO;
using System.Security.Cryptography;
using Google.Apis.Auth.OAuth2;
using Mono.Security.Cryptography;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace Grpc.Auth
{
// TODO(jtattermusch): Remove this class once possible.
/// <summary>
/// A temporary placeholder for Google credential from
/// Google Auth library for .NET. It emulates the usage pattern
/// for Usable auth.
/// </summary>
public class GoogleCredential
{
private const string GoogleApplicationCredentialsEnvName = "GOOGLE_APPLICATION_CREDENTIALS";
private const string ClientEmailFieldName = "client_email";
private const string PrivateKeyFieldName = "private_key";
private ServiceCredential credential;
private GoogleCredential(ServiceCredential credential)
{
this.credential = credential;
}
public static GoogleCredential GetApplicationDefault()
{
return new GoogleCredential(null);
}
public bool IsCreateScopedRequired
{
get
{
return true;
}
}
public GoogleCredential CreateScoped(IEnumerable<string> scopes)
{
var credsPath = Environment.GetEnvironmentVariable(GoogleApplicationCredentialsEnvName);
if (credsPath == null)
{
// Default to ComputeCredentials if path to JSON key is not set.
// ComputeCredential is not scoped actually, but for our use case it's
// fine to treat is as such.
return new GoogleCredential(new ComputeCredential(new ComputeCredential.Initializer()));
}
JObject o1 = JObject.Parse(File.ReadAllText(credsPath));
string clientEmail = o1.GetValue(ClientEmailFieldName).Value<string>();
string privateKeyString = o1.GetValue(PrivateKeyFieldName).Value<string>();
var privateKey = ParsePrivateKeyFromString(privateKeyString);
var serviceCredential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(clientEmail)
{
Scopes = scopes,
Key = privateKey
});
return new GoogleCredential(serviceCredential);
}
internal ServiceCredential InternalCredential
{
get
{
return credential;
}
}
private RSACryptoServiceProvider ParsePrivateKeyFromString(string base64PrivateKey)
{
// TODO(jtattermusch): temporary code to create RSACryptoServiceProvider.
base64PrivateKey = base64PrivateKey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("\n", "").Replace("-----END PRIVATE KEY-----", "");
PKCS8.PrivateKeyInfo PKI = new PKCS8.PrivateKeyInfo(Convert.FromBase64String(base64PrivateKey));
RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(PKI.GetBytes());
RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(key);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters);
return rsa;
}
}
}

@ -0,0 +1,93 @@
<?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>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>Grpc.Auth</RootNamespace>
<AssemblyName>Grpc.Auth</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>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<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.1\lib\net40\Google.Apis.Auth.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth.PlatformServices">
<HintPath>..\packages\Google.Apis.Auth.1.9.1\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Core">
<HintPath>..\packages\Google.Apis.Core.1.9.1\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
</Reference>
<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">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<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="Mono.Security">
<HintPath>..\packages\Mono.Security.3.2.3.0\lib\net45\Mono.Security.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Extensions">
<HintPath>..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives">
<HintPath>..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="GoogleCredential.cs" />
<Compile Include="OAuth2InterceptorFactory.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>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
</Project>

@ -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.Diagnostics;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Util;
using Grpc.Core;
using Grpc.Core.Utils;
namespace Grpc.Auth
{
public static class OAuth2InterceptorFactory
{
/// <summary>
/// Creates OAuth2 interceptor.
/// </summary>
public static HeaderInterceptorDelegate Create(GoogleCredential googleCredential)
{
var interceptor = new OAuth2Interceptor(googleCredential.InternalCredential, SystemClock.Default);
return new HeaderInterceptorDelegate(interceptor.InterceptHeaders);
}
/// <summary>
/// Injects OAuth2 authorization header into initial metadata (= request headers).
/// </summary>
private class OAuth2Interceptor
{
private const string AuthorizationHeader = "Authorization";
private const string Schema = "Bearer";
private ServiceCredential credential;
private IClock clock;
public OAuth2Interceptor(ServiceCredential credential, IClock clock)
{
this.credential = credential;
this.clock = clock;
}
/// <summary>
/// Gets access token and requests refreshing it if is going to expire soon.
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public string GetAccessToken(CancellationToken cancellationToken)
{
if (credential.Token == null || credential.Token.IsExpired(clock))
{
// TODO(jtattermusch): Parallel requests will spawn multiple requests to refresh the token once the token expires.
// TODO(jtattermusch): Rethink synchronous wait to obtain the result.
if (!credential.RequestAccessTokenAsync(cancellationToken).Result)
{
throw new InvalidOperationException("The access token has expired but we can't refresh it");
}
}
return credential.Token.AccessToken;
}
public void InterceptHeaders(Metadata.Builder headerBuilder)
{
var accessToken = GetAccessToken(CancellationToken.None);
headerBuilder.Add(new Metadata.MetadataEntry(AuthorizationHeader, Schema + " " + accessToken));
}
}
}
}

@ -0,0 +1,14 @@
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Grpc.Auth")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.2.*")]
[assembly: InternalsVisibleTo("Grpc.Auth.Tests")]

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.2.28.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
<package id="Google.Apis.Auth" version="1.9.1" targetFramework="net45" />
<package id="Google.Apis.Core" version="1.9.1" targetFramework="net45" />
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" />
<package id="Mono.Security" version="3.2.3.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" />
</packages>

@ -34,8 +34,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.0.34.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="System.Collections.Immutable">
<HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
</ItemGroup>

@ -42,7 +42,7 @@ namespace Grpc.Core
{
private readonly Status status;
public RpcException(Status status)
public RpcException(Status status) : base(status.ToString())
{
this.status = status;
}

@ -69,5 +69,10 @@ namespace Grpc.Core
return detail;
}
}
public override string ToString()
{
return string.Format("Status(StatusCode={0}, Detail=\"{1}\")", statusCode, detail);
}
}
}

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?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>
@ -46,4 +46,7 @@
<Name>Grpc.IntegrationTesting</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
</Project>

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.2.28.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?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>
@ -46,4 +46,7 @@
<Name>Grpc.IntegrationTesting</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
</Project>

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.2.28.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -32,6 +32,21 @@
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="Google.Apis.Auth.PlatformServices">
<HintPath>..\packages\Google.Apis.Auth.1.9.1\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Core">
<HintPath>..\packages\Google.Apis.Core.1.9.1\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
</Reference>
<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">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<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="nunit.framework">
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
</Reference>
@ -39,8 +54,19 @@
<Reference Include="Google.ProtocolBuffers">
<HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath>
</Reference>
<Reference Include="System.Collections.Immutable, Version=1.0.34.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Extensions">
<HintPath>..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives">
<HintPath>..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System.Collections.Immutable">
<HintPath>..\packages\Microsoft.Bcl.Immutable.1.0.34\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
</ItemGroup>
@ -61,8 +87,13 @@
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
<Name>Grpc.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Grpc.Auth\Grpc.Auth.csproj">
<Project>{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}</Project>
<Name>Grpc.Auth</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="proto\test.proto" />
<None Include="proto\empty.proto" />
@ -83,4 +114,9 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
</Project>

@ -33,12 +33,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Google.ProtocolBuffers;
using grpc.testing;
using Grpc.Auth;
using Grpc.Core;
using Grpc.Core.Utils;
using NUnit.Framework;
@ -47,6 +46,11 @@ namespace Grpc.IntegrationTesting
{
public class InteropClient
{
private const string ServiceAccountUser = "155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk@developer.gserviceaccount.com";
private const string ComputeEngineUser = "155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel@developer.gserviceaccount.com";
private const string AuthScope = "https://www.googleapis.com/auth/xapi.zoo";
private const string AuthScopeResponse = "xapi.zoo";
private class ClientOptions
{
public bool help;
@ -115,7 +119,18 @@ namespace Grpc.IntegrationTesting
using (Channel channel = new Channel(addr, credentials, channelArgs))
{
TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel);
var stubConfig = StubConfiguration.Default;
if (options.testCase == "service_account_creds" || options.testCase == "compute_engine_creds")
{
var credential = GoogleCredential.GetApplicationDefault();
if (credential.IsCreateScopedRequired)
{
credential = credential.CreateScoped(new[] { AuthScope });
}
stubConfig = new StubConfiguration(OAuth2InterceptorFactory.Create(credential));
}
TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel, stubConfig);
RunTestCase(options.testCase, client);
}
@ -144,6 +159,12 @@ namespace Grpc.IntegrationTesting
case "empty_stream":
RunEmptyStream(client);
break;
case "service_account_creds":
RunServiceAccountCreds(client);
break;
case "compute_engine_creds":
RunComputeEngineCreds(client);
break;
case "benchmark_empty_unary":
RunBenchmarkEmptyUnary(client);
break;
@ -287,6 +308,46 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunServiceAccountCreds(TestServiceGrpc.ITestServiceClient client)
{
Console.WriteLine("running service_account_creds");
var request = SimpleRequest.CreateBuilder()
.SetResponseType(PayloadType.COMPRESSABLE)
.SetResponseSize(314159)
.SetPayload(CreateZerosPayload(271828))
.SetFillUsername(true)
.SetFillOauthScope(true)
.Build();
var response = client.UnaryCall(request);
Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
Assert.AreEqual(314159, response.Payload.Body.Length);
Assert.AreEqual(AuthScopeResponse, response.OauthScope);
Assert.AreEqual(ServiceAccountUser, response.Username);
Console.WriteLine("Passed!");
}
public static void RunComputeEngineCreds(TestServiceGrpc.ITestServiceClient client)
{
Console.WriteLine("running compute_engine_creds");
var request = SimpleRequest.CreateBuilder()
.SetResponseType(PayloadType.COMPRESSABLE)
.SetResponseSize(314159)
.SetPayload(CreateZerosPayload(271828))
.SetFillUsername(true)
.SetFillOauthScope(true)
.Build();
var response = client.UnaryCall(request);
Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
Assert.AreEqual(314159, response.Payload.Body.Length);
Assert.AreEqual(AuthScopeResponse, response.OauthScope);
Assert.AreEqual(ComputeEngineUser, response.Username);
Console.WriteLine("Passed!");
}
// This is not an official interop test, but it's useful.
public static void RunBenchmarkEmptyUnary(TestServiceGrpc.ITestServiceClient client)
{

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.2.28.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Apis.Auth" version="1.9.1" targetFramework="net45" />
<package id="Google.Apis.Core" version="1.9.1" targetFramework="net45" />
<package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" />
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
<package id="Microsoft.Bcl.Immutable" version="1.0.34" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" />
</packages>

@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.Ser
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Examples.MathServer", "Grpc.Examples.MathServer\Grpc.Examples.MathServer.csproj", "{BF62FE08-373A-43D6-9D73-41CAA38B7011}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Auth", "Grpc.Auth\Grpc.Auth.csproj", "{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
@ -49,6 +51,10 @@ Global
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|x86.Build.0 = Debug|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.ActiveCfg = Release|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.Build.0 = Release|x86
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.ActiveCfg = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|x86.Build.0 = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.ActiveCfg = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|x86.Build.0 = Release|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.ActiveCfg = Debug|x86
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.Build.0 = Debug|x86
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.ActiveCfg = Release|x86

@ -1,20 +0,0 @@
PODS:
- GRPCClient (0.0.1):
- RxLibrary (~> 0.0)
- RxLibrary (0.0.1)
DEPENDENCIES:
- GRPCClient (from `../../GRPCClient`)
- RxLibrary (from `../../RxLibrary`)
EXTERNAL SOURCES:
GRPCClient:
:path: ../../GRPCClient
RxLibrary:
:path: ../../RxLibrary
SPEC CHECKSUMS:
GRPCClient: 05c58faab99661384178bb7c5f93b60c2bfc89f8
RxLibrary: 70cfcf1573ec16a375b4fe61d976a3188aab9303
COCOAPODS: 0.35.0

@ -1 +0,0 @@
../../../../../../GRPCClient/GRPCCall.h

@ -1 +0,0 @@
../../../../../../GRPCClient/GRPCMethodName.h

@ -1 +0,0 @@
../../../../../../RxLibrary/GRXImmediateWriter.h

@ -1 +0,0 @@
../../../../../../RxLibrary/transformations/GRXMappingWriter.h

@ -1 +0,0 @@
../../../../../../RxLibrary/GRXWriteable.h

@ -1 +0,0 @@
../../../../../../RxLibrary/GRXWriter+Immediate.h

@ -1 +0,0 @@
../../../../../../RxLibrary/GRXWriter+Transformations.h

@ -1 +0,0 @@
../../../../../../RxLibrary/GRXWriter.h

@ -1 +0,0 @@
../../../../../../RxLibrary/NSEnumerator+GRXUtil.h

@ -1,14 +0,0 @@
Pod::Spec.new do |s|
s.name = 'GRPCClient'
s.version = '0.0.1'
s.summary = 'Generic gRPC client library for iOS'
s.author = {
'Jorge Canizales' => 'jcanizales@google.com'
}
s.source_files = '*.{h,m}', 'private/*.{h,m}'
s.private_header_files = 'private/*.h'
s.platform = :ios
s.ios.deployment_target = '6.0'
s.requires_arc = true
s.dependency 'RxLibrary', '~> 0.0'
end

@ -1,13 +0,0 @@
Pod::Spec.new do |s|
s.name = 'RxLibrary'
s.version = '0.0.1'
s.summary = 'Reactive Extensions library for iOS'
s.author = {
'Jorge Canizales' => 'jcanizales@google.com'
}
s.source_files = '*.{h,m}', 'transformations/*.{h,m}', 'private/*.{h,m}'
s.private_header_files = 'private/*.h'
s.platform = :ios
s.ios.deployment_target = '6.0'
s.requires_arc = true
end

@ -1,20 +0,0 @@
PODS:
- GRPCClient (0.0.1):
- RxLibrary (~> 0.0)
- RxLibrary (0.0.1)
DEPENDENCIES:
- GRPCClient (from `../../GRPCClient`)
- RxLibrary (from `../../RxLibrary`)
EXTERNAL SOURCES:
GRPCClient:
:path: ../../GRPCClient
RxLibrary:
:path: ../../RxLibrary
SPEC CHECKSUMS:
GRPCClient: 05c58faab99661384178bb7c5f93b60c2bfc89f8
RxLibrary: 70cfcf1573ec16a375b4fe61d976a3188aab9303
COCOAPODS: 0.35.0

File diff suppressed because it is too large Load Diff

@ -1,5 +0,0 @@
#include "Pods-GRPCClient.xcconfig"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/GRPCClient" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC
PODS_ROOT = ${SRCROOT}

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_GRPCClient : NSObject
@end
@implementation PodsDummy_Pods_GRPCClient
@end

@ -1,5 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "Pods-environment.h"

@ -1,5 +0,0 @@
#include "Pods-RxLibrary.xcconfig"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/RxLibrary" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC
PODS_ROOT = ${SRCROOT}

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_RxLibrary : NSObject
@end
@implementation PodsDummy_Pods_RxLibrary
@end

@ -1,5 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "Pods-environment.h"

@ -1,5 +0,0 @@
#include "Pods-Sample-GRPCClient.xcconfig"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/GRPCClient" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC
PODS_ROOT = ${SRCROOT}

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_Sample_GRPCClient : NSObject
@end
@implementation PodsDummy_Pods_Sample_GRPCClient
@end

@ -1,5 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "Pods-Sample-environment.h"

@ -1,5 +0,0 @@
#include "Pods-Sample-RxLibrary.xcconfig"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/RxLibrary" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC
PODS_ROOT = ${SRCROOT}

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_Sample_RxLibrary : NSObject
@end
@implementation PodsDummy_Pods_Sample_RxLibrary
@end

@ -1,5 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "Pods-Sample-environment.h"

@ -1,3 +0,0 @@
# Acknowledgements
This application makes use of the following third party libraries:
Generated by CocoaPods - http://cocoapods.org

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>FooterText</key>
<string>This application makes use of the following third party libraries:</string>
<key>Title</key>
<string>Acknowledgements</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Generated by CocoaPods - http://cocoapods.org</string>
<key>Title</key>
<string></string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Acknowledgements</string>
<key>Title</key>
<string>Acknowledgements</string>
</dict>
</plist>

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_Sample : NSObject
@end
@implementation PodsDummy_Pods_Sample
@end

@ -1,20 +0,0 @@
// To check if a library is compiled with CocoaPods you
// can use the `COCOAPODS` macro definition which is
// defined in the xcconfigs so it is available in
// headers also when they are imported in the client
// project.
// GRPCClient
#define COCOAPODS_POD_AVAILABLE_GRPCClient
#define COCOAPODS_VERSION_MAJOR_GRPCClient 0
#define COCOAPODS_VERSION_MINOR_GRPCClient 0
#define COCOAPODS_VERSION_PATCH_GRPCClient 1
// RxLibrary
#define COCOAPODS_POD_AVAILABLE_RxLibrary
#define COCOAPODS_VERSION_MAJOR_RxLibrary 0
#define COCOAPODS_VERSION_MINOR_RxLibrary 0
#define COCOAPODS_VERSION_PATCH_RxLibrary 1

@ -1,74 +0,0 @@
#!/bin/sh
set -e
mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"
install_resource()
{
case $1 in
*.storyboard)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.xib)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.framework)
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*.xcdatamodel)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
;;
*.xcdatamodeld)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
;;
*.xcmappingmodel)
echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
;;
*.xcassets)
;;
/*)
echo "$1"
echo "$1" >> "$RESOURCES_TO_COPY"
;;
*)
echo "${PODS_ROOT}/$1"
echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
;;
esac
}
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
if [[ "${ACTION}" == "install" ]]; then
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
rm -f "$RESOURCES_TO_COPY"
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ]
then
case "${TARGETED_DEVICE_FAMILY}" in
1,2)
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
;;
1)
TARGET_DEVICE_ARGS="--target-device iphone"
;;
2)
TARGET_DEVICE_ARGS="--target-device ipad"
;;
*)
TARGET_DEVICE_ARGS="--target-device mac"
;;
esac
find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi

@ -1,6 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GRPCClient" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC -l"Pods-Sample-GRPCClient" -l"Pods-Sample-RxLibrary"
OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
PODS_ROOT = ${SRCROOT}/Pods

@ -1,6 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GRPCClient" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC -l"Pods-Sample-GRPCClient" -l"Pods-Sample-RxLibrary"
OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
PODS_ROOT = ${SRCROOT}/Pods

@ -1,5 +0,0 @@
#include "Pods-SampleTests-GRPCClient.xcconfig"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/GRPCClient" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC
PODS_ROOT = ${SRCROOT}

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_SampleTests_GRPCClient : NSObject
@end
@implementation PodsDummy_Pods_SampleTests_GRPCClient
@end

@ -1,5 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "Pods-SampleTests-environment.h"

@ -1,5 +0,0 @@
#include "Pods-SampleTests-RxLibrary.xcconfig"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/RxLibrary" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC
PODS_ROOT = ${SRCROOT}

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_SampleTests_RxLibrary : NSObject
@end
@implementation PodsDummy_Pods_SampleTests_RxLibrary
@end

@ -1,5 +0,0 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "Pods-SampleTests-environment.h"

@ -1,3 +0,0 @@
# Acknowledgements
This application makes use of the following third party libraries:
Generated by CocoaPods - http://cocoapods.org

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>FooterText</key>
<string>This application makes use of the following third party libraries:</string>
<key>Title</key>
<string>Acknowledgements</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Generated by CocoaPods - http://cocoapods.org</string>
<key>Title</key>
<string></string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Acknowledgements</string>
<key>Title</key>
<string>Acknowledgements</string>
</dict>
</plist>

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods_SampleTests : NSObject
@end
@implementation PodsDummy_Pods_SampleTests
@end

@ -1,20 +0,0 @@
// To check if a library is compiled with CocoaPods you
// can use the `COCOAPODS` macro definition which is
// defined in the xcconfigs so it is available in
// headers also when they are imported in the client
// project.
// GRPCClient
#define COCOAPODS_POD_AVAILABLE_GRPCClient
#define COCOAPODS_VERSION_MAJOR_GRPCClient 0
#define COCOAPODS_VERSION_MINOR_GRPCClient 0
#define COCOAPODS_VERSION_PATCH_GRPCClient 1
// RxLibrary
#define COCOAPODS_POD_AVAILABLE_RxLibrary
#define COCOAPODS_VERSION_MAJOR_RxLibrary 0
#define COCOAPODS_VERSION_MINOR_RxLibrary 0
#define COCOAPODS_VERSION_PATCH_RxLibrary 1

@ -1,74 +0,0 @@
#!/bin/sh
set -e
mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"
install_resource()
{
case $1 in
*.storyboard)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.xib)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.framework)
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*.xcdatamodel)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
;;
*.xcdatamodeld)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
;;
*.xcmappingmodel)
echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
;;
*.xcassets)
;;
/*)
echo "$1"
echo "$1" >> "$RESOURCES_TO_COPY"
;;
*)
echo "${PODS_ROOT}/$1"
echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
;;
esac
}
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
if [[ "${ACTION}" == "install" ]]; then
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
rm -f "$RESOURCES_TO_COPY"
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ]
then
case "${TARGETED_DEVICE_FAMILY}" in
1,2)
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
;;
1)
TARGET_DEVICE_ARGS="--target-device iphone"
;;
2)
TARGET_DEVICE_ARGS="--target-device ipad"
;;
*)
TARGET_DEVICE_ARGS="--target-device mac"
;;
esac
find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi

@ -1,6 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GRPCClient" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC -l"Pods-SampleTests-GRPCClient" -l"Pods-SampleTests-RxLibrary"
OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
PODS_ROOT = ${SRCROOT}/Pods

@ -1,6 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GRPCClient" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC -l"Pods-SampleTests-GRPCClient" -l"Pods-SampleTests-RxLibrary"
OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
PODS_ROOT = ${SRCROOT}/Pods

@ -1,3 +0,0 @@
# Acknowledgements
This application makes use of the following third party libraries:
Generated by CocoaPods - http://cocoapods.org

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>FooterText</key>
<string>This application makes use of the following third party libraries:</string>
<key>Title</key>
<string>Acknowledgements</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Generated by CocoaPods - http://cocoapods.org</string>
<key>Title</key>
<string></string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Acknowledgements</string>
<key>Title</key>
<string>Acknowledgements</string>
</dict>
</plist>

@ -1,5 +0,0 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_Pods : NSObject
@end
@implementation PodsDummy_Pods
@end

@ -1,20 +0,0 @@
// To check if a library is compiled with CocoaPods you
// can use the `COCOAPODS` macro definition which is
// defined in the xcconfigs so it is available in
// headers also when they are imported in the client
// project.
// GRPCClient
#define COCOAPODS_POD_AVAILABLE_GRPCClient
#define COCOAPODS_VERSION_MAJOR_GRPCClient 0
#define COCOAPODS_VERSION_MINOR_GRPCClient 0
#define COCOAPODS_VERSION_PATCH_GRPCClient 1
// RxLibrary
#define COCOAPODS_POD_AVAILABLE_RxLibrary
#define COCOAPODS_VERSION_MAJOR_RxLibrary 0
#define COCOAPODS_VERSION_MINOR_RxLibrary 0
#define COCOAPODS_VERSION_PATCH_RxLibrary 1

@ -1,74 +0,0 @@
#!/bin/sh
set -e
mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
> "$RESOURCES_TO_COPY"
install_resource()
{
case $1 in
*.storyboard)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.xib)
echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
;;
*.framework)
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
;;
*.xcdatamodel)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
;;
*.xcdatamodeld)
echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
;;
*.xcmappingmodel)
echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
;;
*.xcassets)
;;
/*)
echo "$1"
echo "$1" >> "$RESOURCES_TO_COPY"
;;
*)
echo "${PODS_ROOT}/$1"
echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
;;
esac
}
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
if [[ "${ACTION}" == "install" ]]; then
rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi
rm -f "$RESOURCES_TO_COPY"
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ]
then
case "${TARGETED_DEVICE_FAMILY}" in
1,2)
TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
;;
1)
TARGET_DEVICE_ARGS="--target-device iphone"
;;
2)
TARGET_DEVICE_ARGS="--target-device ipad"
;;
*)
TARGET_DEVICE_ARGS="--target-device mac"
;;
esac
find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
fi

@ -1,6 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GRPCClient" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC -l"Pods-GRPCClient" -l"Pods-RxLibrary"
OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
PODS_ROOT = ${SRCROOT}/Pods

@ -1,6 +0,0 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GRPCClient" "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GRPCClient" -isystem "${PODS_ROOT}/Headers/Public/RxLibrary"
OTHER_LDFLAGS = -ObjC -l"Pods-GRPCClient" -l"Pods-RxLibrary"
OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS)
PODS_ROOT = ${SRCROOT}/Pods

@ -1,2 +1 @@
When contributing changes to this sample, use Cocoapods to manage the workspace
file and everything under the Pods directory.
This sample app requires the use of Cocoapods. After installing Cocoapods, run `pod install` in this directory to recreate its dependencies. (This will compile OpenSSL, which takes some time).

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Sample.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

@ -34,6 +34,7 @@
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import <gRPC/GRXWriter+Immediate.h>
#import <RemoteTest/Messages.pb.h>
#import <RemoteTest/Test.pb.h>
@ -48,43 +49,85 @@
_service = [[RMTTestService alloc] initWithHost:@"grpc-test.sandbox.google.com"];
}
- (void)testEmptyRPC {
__weak XCTestExpectation *noRPCError = [self expectationWithDescription:@"RPC succeeded."];
__weak XCTestExpectation *responded = [self expectationWithDescription:@"Response received."];
// Tests as described here: https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md
[_service emptyCallWithRequest:[RMTEmpty defaultInstance]
handler:^(RMTEmpty *response, NSError *error) {
- (void)testEmptyUnaryRPC {
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"];
RMTEmpty *request = [RMTEmpty defaultInstance];
[_service emptyCallWithRequest:request handler:^(RMTEmpty *response, NSError *error) {
XCTAssertNil(error, @"Finished with unexpected error: %@", error);
[noRPCError fulfill];
XCTAssertNotNil(response, @"nil response received.");
[responded fulfill];
id expectedResponse = [RMTEmpty defaultInstance];
XCTAssertEqualObjects(response, expectedResponse);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:2. handler:nil];
}
- (void)testSimpleProtoRPC {
__weak XCTestExpectation *noRPCError = [self expectationWithDescription:@"RPC succeeded."];
__weak XCTestExpectation *responded = [self expectationWithDescription:@"Response received."];
__weak XCTestExpectation *validResponse = [self expectationWithDescription:@"Valid response."];
- (void)testLargeUnaryRPC {
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"];
RMTSimpleRequest *request = [[[[[[RMTSimpleRequestBuilder alloc] init]
setResponseSize:100]
setFillUsername:YES]
setFillOauthScope:YES]
setResponseType:RMTPayloadTypeCompressable]
setResponseSize:314159]
setPayloadBuilder:[[[RMTPayloadBuilder alloc] init]
setBody:[NSMutableData dataWithLength:271828]]]
build];
[_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
XCTAssertNil(error, @"Finished with unexpected error: %@", error);
[noRPCError fulfill];
XCTAssertNotNil(response, @"nil response received.");
[responded fulfill];
// We expect empty strings, not nil:
XCTAssertNotNil(response.username, @"Response's username is nil.");
XCTAssertNotNil(response.oauthScope, @"Response's OAuth scope is nil.");
[validResponse fulfill];
id expectedResponse = [[[[RMTSimpleResponseBuilder alloc] init]
setPayloadBuilder:[[[[RMTPayloadBuilder alloc] init]
setType:RMTPayloadTypeCompressable]
setBody:[NSMutableData dataWithLength:314159]]]
build];
XCTAssertEqualObjects(response, expectedResponse);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:2. handler:nil];
[self waitForExpectationsWithTimeout:4. handler:nil];
}
- (void)testClientStreamingRPC {
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"];
id request1 = [[[[RMTStreamingInputCallRequestBuilder alloc] init]
setPayloadBuilder:[[[RMTPayloadBuilder alloc] init]
setBody:[NSMutableData dataWithLength:27182]]]
build];
id request2 = [[[[RMTStreamingInputCallRequestBuilder alloc] init]
setPayloadBuilder:[[[RMTPayloadBuilder alloc] init]
setBody:[NSMutableData dataWithLength:8]]]
build];
id request3 = [[[[RMTStreamingInputCallRequestBuilder alloc] init]
setPayloadBuilder:[[[RMTPayloadBuilder alloc] init]
setBody:[NSMutableData dataWithLength:1828]]]
build];
id request4 = [[[[RMTStreamingInputCallRequestBuilder alloc] init]
setPayloadBuilder:[[[RMTPayloadBuilder alloc] init]
setBody:[NSMutableData dataWithLength:45904]]]
build];
id<GRXWriter> writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]];
[_service streamingInputCallWithRequestsWriter:writer
handler:^(RMTStreamingInputCallResponse *response, NSError *error) {
XCTAssertNil(error, @"Finished with unexpected error: %@", error);
id expectedResponse = [[[[RMTStreamingInputCallResponseBuilder alloc] init]
setAggregatedPayloadSize:74922]
build];
XCTAssertEqualObjects(response, expectedResponse);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:4. handler:nil];
}
@end

@ -83,8 +83,11 @@ class _CTest(unittest.TestCase):
_c.init()
channel = _c.Channel('%s:%d' % (host, 12345), None)
call = _c.Call(channel, method, host, time.time() + _TIMEOUT)
completion_queue = _c.CompletionQueue()
call = _c.Call(channel, completion_queue, method, host,
time.time() + _TIMEOUT)
del call
del completion_queue
del channel
_c.shut_down()

@ -36,90 +36,166 @@
#include <math.h>
#include <Python.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include "grpc/_adapter/_channel.h"
#include "grpc/_adapter/_completion_queue.h"
#include "grpc/_adapter/_error.h"
#include "grpc/_adapter/_tag.h"
static int pygrpc_call_init(Call *self, PyObject *args, PyObject *kwds) {
const PyObject *channel;
static PyObject *pygrpc_call_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
Call *self = (Call *)type->tp_alloc(type, 0);
Channel *channel;
CompletionQueue *completion_queue;
const char *method;
const char *host;
double deadline;
static char *kwlist[] = {"channel", "method", "host", "deadline", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!ssd:Call", kwlist,
&pygrpc_ChannelType, &channel, &method,
&host, &deadline)) {
return -1;
static char *kwlist[] = {"channel", "completion_queue",
"method", "host", "deadline", NULL};
if (!PyArg_ParseTupleAndKeywords(
args, kwds, "O!O!ssd:Call", kwlist,
&pygrpc_ChannelType, &channel,
&pygrpc_CompletionQueueType, &completion_queue,
&method, &host, &deadline)) {
return NULL;
}
/* TODO(nathaniel): Hoist the gpr_timespec <-> PyFloat arithmetic into its own
* function with its own test coverage.
*/
self->c_call = grpc_channel_create_call_old(
((Channel *)channel)->c_channel, method, host,
self->c_call = grpc_channel_create_call(
channel->c_channel, completion_queue->c_completion_queue, method, host,
gpr_time_from_nanos(deadline * GPR_NS_PER_SEC));
return 0;
self->completion_queue = completion_queue;
Py_INCREF(self->completion_queue);
self->channel = channel;
Py_INCREF(self->channel);
grpc_call_details_init(&self->call_details);
grpc_metadata_array_init(&self->recv_metadata);
grpc_metadata_array_init(&self->recv_trailing_metadata);
self->send_metadata = NULL;
self->send_metadata_count = 0;
self->send_trailing_metadata = NULL;
self->send_trailing_metadata_count = 0;
self->send_message = NULL;
self->recv_message = NULL;
self->adding_to_trailing = 0;
return (PyObject *)self;
}
static void pygrpc_call_dealloc(Call *self) {
if (self->c_call != NULL) {
grpc_call_destroy(self->c_call);
}
Py_XDECREF(self->completion_queue);
Py_XDECREF(self->channel);
Py_XDECREF(self->server);
grpc_call_details_destroy(&self->call_details);
grpc_metadata_array_destroy(&self->recv_metadata);
grpc_metadata_array_destroy(&self->recv_trailing_metadata);
if (self->send_message) {
grpc_byte_buffer_destroy(self->send_message);
}
if (self->recv_message) {
grpc_byte_buffer_destroy(self->recv_message);
}
gpr_free(self->status_details);
gpr_free(self->send_metadata);
gpr_free(self->send_trailing_metadata);
self->ob_type->tp_free((PyObject *)self);
}
static const PyObject *pygrpc_call_invoke(Call *self, PyObject *args) {
const PyObject *completion_queue;
const PyObject *metadata_tag;
const PyObject *finish_tag;
PyObject *completion_queue;
PyObject *metadata_tag;
PyObject *finish_tag;
grpc_call_error call_error;
const PyObject *result;
pygrpc_tag *c_init_metadata_tag;
pygrpc_tag *c_metadata_tag;
pygrpc_tag *c_finish_tag;
grpc_op send_initial_metadata;
grpc_op recv_initial_metadata;
grpc_op recv_status_on_client;
if (!(PyArg_ParseTuple(args, "O!OO:invoke", &pygrpc_CompletionQueueType,
&completion_queue, &metadata_tag, &finish_tag))) {
return NULL;
}
call_error = grpc_call_invoke_old(
self->c_call, ((CompletionQueue *)completion_queue)->c_completion_queue,
(void *)metadata_tag, (void *)finish_tag, 0);
send_initial_metadata.op = GRPC_OP_SEND_INITIAL_METADATA;
send_initial_metadata.data.send_initial_metadata.metadata = self->send_metadata;
send_initial_metadata.data.send_initial_metadata.count = self->send_metadata_count;
recv_initial_metadata.op = GRPC_OP_RECV_INITIAL_METADATA;
recv_initial_metadata.data.recv_initial_metadata = &self->recv_metadata;
recv_status_on_client.op = GRPC_OP_RECV_STATUS_ON_CLIENT;
recv_status_on_client.data.recv_status_on_client.trailing_metadata = &self->recv_trailing_metadata;
recv_status_on_client.data.recv_status_on_client.status = &self->status;
recv_status_on_client.data.recv_status_on_client.status_details = &self->status_details;
recv_status_on_client.data.recv_status_on_client.status_details_capacity = &self->status_details_capacity;
c_init_metadata_tag = pygrpc_tag_new(PYGRPC_INITIAL_METADATA, NULL, self);
c_metadata_tag = pygrpc_tag_new(PYGRPC_CLIENT_METADATA_READ, metadata_tag, self);
c_finish_tag = pygrpc_tag_new(PYGRPC_FINISHED_CLIENT, finish_tag, self);
call_error = grpc_call_start_batch(self->c_call, &send_initial_metadata, 1, c_init_metadata_tag);
result = pygrpc_translate_call_error(call_error);
if (result == NULL) {
pygrpc_tag_destroy(c_init_metadata_tag);
pygrpc_tag_destroy(c_metadata_tag);
pygrpc_tag_destroy(c_finish_tag);
return result;
}
call_error = grpc_call_start_batch(self->c_call, &recv_initial_metadata, 1, c_metadata_tag);
result = pygrpc_translate_call_error(call_error);
if (result == NULL) {
pygrpc_tag_destroy(c_metadata_tag);
pygrpc_tag_destroy(c_finish_tag);
return result;
}
call_error = grpc_call_start_batch(self->c_call, &recv_status_on_client, 1, c_finish_tag);
result = pygrpc_translate_call_error(call_error);
if (result != NULL) {
Py_INCREF(metadata_tag);
Py_INCREF(finish_tag);
if (result == NULL) {
pygrpc_tag_destroy(c_finish_tag);
return result;
}
return result;
}
static const PyObject *pygrpc_call_write(Call *self, PyObject *args) {
const char *bytes;
int length;
const PyObject *tag;
PyObject *tag;
gpr_slice slice;
grpc_byte_buffer *byte_buffer;
grpc_call_error call_error;
const PyObject *result;
pygrpc_tag *c_tag;
grpc_op op;
if (!(PyArg_ParseTuple(args, "s#O:write", &bytes, &length, &tag))) {
return NULL;
}
c_tag = pygrpc_tag_new(PYGRPC_WRITE_ACCEPTED, tag, self);
slice = gpr_slice_from_copied_buffer(bytes, length);
byte_buffer = grpc_byte_buffer_create(&slice, 1);
gpr_slice_unref(slice);
call_error =
grpc_call_start_write_old(self->c_call, byte_buffer, (void *)tag, 0);
if (self->send_message) {
grpc_byte_buffer_destroy(self->send_message);
}
self->send_message = byte_buffer;
op.op = GRPC_OP_SEND_MESSAGE;
op.data.send_message = self->send_message;
grpc_byte_buffer_destroy(byte_buffer);
call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag);
result = pygrpc_translate_call_error(call_error);
if (result != NULL) {
Py_INCREF(tag);
if (result == NULL) {
pygrpc_tag_destroy(c_tag);
}
return result;
}
@ -127,36 +203,42 @@ static const PyObject *pygrpc_call_write(Call *self, PyObject *args) {
static const PyObject *pygrpc_call_complete(Call *self, PyObject *tag) {
grpc_call_error call_error;
const PyObject *result;
pygrpc_tag *c_tag = pygrpc_tag_new(PYGRPC_FINISH_ACCEPTED, tag, self);
grpc_op op;
call_error = grpc_call_writes_done_old(self->c_call, (void *)tag);
op.op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag);
result = pygrpc_translate_call_error(call_error);
if (result != NULL) {
Py_INCREF(tag);
if (result == NULL) {
pygrpc_tag_destroy(c_tag);
}
return result;
}
static const PyObject *pygrpc_call_accept(Call *self, PyObject *args) {
const PyObject *completion_queue;
const PyObject *tag;
PyObject *completion_queue;
PyObject *tag;
grpc_call_error call_error;
const PyObject *result;
pygrpc_tag *c_tag;
grpc_op op;
if (!(PyArg_ParseTuple(args, "O!O:accept", &pygrpc_CompletionQueueType,
&completion_queue, &tag))) {
return NULL;
}
call_error = grpc_call_server_accept_old(
self->c_call, ((CompletionQueue *)completion_queue)->c_completion_queue,
(void *)tag);
result = pygrpc_translate_call_error(call_error);
op.op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op.data.recv_close_on_server.cancelled = &self->cancelled;
c_tag = pygrpc_tag_new(PYGRPC_FINISHED_SERVER, tag, self);
if (result != NULL) {
Py_INCREF(tag);
call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag);
result = pygrpc_translate_call_error(call_error);
if (result == NULL) {
pygrpc_tag_destroy(c_tag);
}
return result;
}
@ -171,24 +253,52 @@ static const PyObject *pygrpc_call_add_metadata(Call *self, PyObject *args) {
metadata.key = key;
metadata.value = value;
metadata.value_length = value_length;
return pygrpc_translate_call_error(
grpc_call_add_metadata_old(self->c_call, &metadata, 0));
if (self->adding_to_trailing) {
self->send_trailing_metadata = gpr_realloc(self->send_trailing_metadata, (self->send_trailing_metadata_count + 1) * sizeof(grpc_metadata));
self->send_trailing_metadata[self->send_trailing_metadata_count] = metadata;
self->send_trailing_metadata_count = self->send_trailing_metadata_count + 1;
} else {
self->send_metadata = gpr_realloc(self->send_metadata, (self->send_metadata_count + 1) * sizeof(grpc_metadata));
self->send_metadata[self->send_metadata_count] = metadata;
self->send_metadata_count = self->send_metadata_count + 1;
}
return pygrpc_translate_call_error(GRPC_CALL_OK);
}
static const PyObject *pygrpc_call_premetadata(Call *self) {
return pygrpc_translate_call_error(
grpc_call_server_end_initial_metadata_old(self->c_call, 0));
grpc_op op;
grpc_call_error call_error;
const PyObject *result;
pygrpc_tag *c_tag = pygrpc_tag_new(PYGRPC_INITIAL_METADATA, NULL, self);
op.op = GRPC_OP_SEND_INITIAL_METADATA;
op.data.send_initial_metadata.metadata = self->send_metadata;
op.data.send_initial_metadata.count = self->send_metadata_count;
self->adding_to_trailing = 1;
call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag);
result = pygrpc_translate_call_error(call_error);
if (result == NULL) {
pygrpc_tag_destroy(c_tag);
}
return result;
}
static const PyObject *pygrpc_call_read(Call *self, PyObject *tag) {
grpc_op op;
grpc_call_error call_error;
const PyObject *result;
pygrpc_tag *c_tag = pygrpc_tag_new(PYGRPC_READ, tag, self);
call_error = grpc_call_start_read_old(self->c_call, (void *)tag);
op.op = GRPC_OP_RECV_MESSAGE;
if (self->recv_message) {
grpc_byte_buffer_destroy(self->recv_message);
self->recv_message = NULL;
}
op.data.recv_message = &self->recv_message;
call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag);
result = pygrpc_translate_call_error(call_error);
if (result != NULL) {
Py_INCREF(tag);
if (result == NULL) {
pygrpc_tag_destroy(c_tag);
}
return result;
}
@ -197,15 +307,18 @@ static const PyObject *pygrpc_call_status(Call *self, PyObject *args) {
PyObject *status;
PyObject *code;
PyObject *details;
const PyObject *tag;
PyObject *tag;
grpc_status_code c_code;
char *c_message;
grpc_call_error call_error;
const PyObject *result;
pygrpc_tag *c_tag;
grpc_op op;
if (!(PyArg_ParseTuple(args, "OO:status", &status, &tag))) {
return NULL;
}
c_tag = pygrpc_tag_new(PYGRPC_FINISH_ACCEPTED, tag, self);
code = PyObject_GetAttrString(status, "code");
if (code == NULL) {
@ -227,13 +340,21 @@ static const PyObject *pygrpc_call_status(Call *self, PyObject *args) {
if (c_message == NULL) {
return NULL;
}
call_error = grpc_call_start_write_status_old(self->c_call, c_code, c_message,
(void *)tag);
if (self->status_details) {
gpr_free(self->status_details);
}
self->status_details = gpr_malloc(strlen(c_message)+1);
strcpy(self->status_details, c_message);
op.op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op.data.send_status_from_server.trailing_metadata_count = self->send_trailing_metadata_count;
op.data.send_status_from_server.trailing_metadata = self->send_trailing_metadata;
op.data.send_status_from_server.status = c_code;
op.data.send_status_from_server.status_details = self->status_details;
call_error = grpc_call_start_batch(self->c_call, &op, 1, c_tag);
result = pygrpc_translate_call_error(call_error);
if (result != NULL) {
Py_INCREF(tag);
if (result == NULL) {
pygrpc_tag_destroy(c_tag);
}
return result;
}
@ -301,9 +422,9 @@ PyTypeObject pygrpc_CallType = {
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)pygrpc_call_init, /* tp_init */
0, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
pygrpc_call_new, /* tp_new */
};
int pygrpc_add_call(PyObject *module) {

@ -37,8 +37,36 @@
#include <Python.h>
#include <grpc/grpc.h>
#include "grpc/_adapter/_completion_queue.h"
#include "grpc/_adapter/_channel.h"
#include "grpc/_adapter/_server.h"
typedef struct {
PyObject_HEAD
CompletionQueue *completion_queue;
Channel *channel;
Server *server;
/* Legacy state. */
grpc_call_details call_details;
grpc_metadata_array recv_metadata;
grpc_metadata_array recv_trailing_metadata;
grpc_metadata *send_metadata;
size_t send_metadata_count;
grpc_metadata *send_trailing_metadata;
size_t send_trailing_metadata_count;
int adding_to_trailing;
grpc_byte_buffer *send_message;
grpc_byte_buffer *recv_message;
grpc_status_code status;
char *status_details;
size_t status_details_capacity;
int cancelled;
grpc_call *c_call;
} Call;

@ -38,6 +38,7 @@
#include <grpc/support/alloc.h>
#include "grpc/_adapter/_call.h"
#include "grpc/_adapter/_tag.h"
static PyObject *status_class;
static PyObject *service_acceptance_class;
@ -138,74 +139,70 @@ static PyObject *pygrpc_stop_event_args(grpc_event *c_event) {
}
static PyObject *pygrpc_write_event_args(grpc_event *c_event) {
PyObject *write_accepted =
c_event->data.write_accepted == GRPC_OP_OK ? Py_True : Py_False;
return PyTuple_Pack(8, write_event_kind, (PyObject *)c_event->tag,
pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag);
PyObject *user_tag = tag->user_tag;
PyObject *write_accepted = Py_True;
return PyTuple_Pack(8, write_event_kind, user_tag,
write_accepted, Py_None, Py_None, Py_None, Py_None,
Py_None);
}
static PyObject *pygrpc_complete_event_args(grpc_event *c_event) {
PyObject *complete_accepted =
c_event->data.finish_accepted == GRPC_OP_OK ? Py_True : Py_False;
return PyTuple_Pack(8, complete_event_kind, (PyObject *)c_event->tag,
pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag);
PyObject *user_tag = tag->user_tag;
PyObject *complete_accepted = Py_True;
return PyTuple_Pack(8, complete_event_kind, user_tag,
Py_None, complete_accepted, Py_None, Py_None, Py_None,
Py_None);
}
static PyObject *pygrpc_service_event_args(grpc_event *c_event) {
if (c_event->data.server_rpc_new.method == NULL) {
pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag);
PyObject *user_tag = tag->user_tag;
if (tag->call->call_details.method == NULL) {
return PyTuple_Pack(
8, service_event_kind, c_event->tag, Py_None, Py_None, Py_None, Py_None,
8, service_event_kind, user_tag, Py_None, Py_None, Py_None, Py_None,
Py_None, Py_None);
} else {
PyObject *method = NULL;
PyObject *host = NULL;
PyObject *service_deadline = NULL;
Call *call = NULL;
PyObject *service_acceptance = NULL;
PyObject *metadata = NULL;
PyObject *event_args = NULL;
method = PyBytes_FromString(c_event->data.server_rpc_new.method);
method = PyBytes_FromString(tag->call->call_details.method);
if (method == NULL) {
goto error;
}
host = PyBytes_FromString(c_event->data.server_rpc_new.host);
host = PyBytes_FromString(tag->call->call_details.host);
if (host == NULL) {
goto error;
}
service_deadline =
pygrpc_as_py_time(&c_event->data.server_rpc_new.deadline);
pygrpc_as_py_time(&tag->call->call_details.deadline);
if (service_deadline == NULL) {
goto error;
}
call = PyObject_New(Call, &pygrpc_CallType);
if (call == NULL) {
goto error;
}
call->c_call = c_event->call;
service_acceptance =
PyObject_CallFunctionObjArgs(service_acceptance_class, call, method,
host, service_deadline, NULL);
PyObject_CallFunctionObjArgs(service_acceptance_class, tag->call,
method, host, service_deadline, NULL);
if (service_acceptance == NULL) {
goto error;
}
metadata = pygrpc_metadata_collection_get(
c_event->data.server_rpc_new.metadata_elements,
c_event->data.server_rpc_new.metadata_count);
tag->call->recv_metadata.metadata,
tag->call->recv_metadata.count);
event_args = PyTuple_Pack(8, service_event_kind,
(PyObject *)c_event->tag, Py_None, Py_None,
user_tag, Py_None, Py_None,
service_acceptance, Py_None, Py_None,
metadata);
Py_DECREF(service_acceptance);
Py_DECREF(metadata);
error:
Py_XDECREF(call);
Py_XDECREF(method);
Py_XDECREF(host);
Py_XDECREF(service_deadline);
@ -215,8 +212,10 @@ error:
}
static PyObject *pygrpc_read_event_args(grpc_event *c_event) {
if (c_event->data.read == NULL) {
return PyTuple_Pack(8, read_event_kind, (PyObject *)c_event->tag,
pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag);
PyObject *user_tag = tag->user_tag;
if (tag->call->recv_message == NULL) {
return PyTuple_Pack(8, read_event_kind, user_tag,
Py_None, Py_None, Py_None, Py_None, Py_None, Py_None);
} else {
size_t length;
@ -227,8 +226,8 @@ static PyObject *pygrpc_read_event_args(grpc_event *c_event) {
PyObject *bytes;
PyObject *event_args;
length = grpc_byte_buffer_length(c_event->data.read);
reader = grpc_byte_buffer_reader_create(c_event->data.read);
length = grpc_byte_buffer_length(tag->call->recv_message);
reader = grpc_byte_buffer_reader_create(tag->call->recv_message);
c_bytes = gpr_malloc(length);
offset = 0;
while (grpc_byte_buffer_reader_next(reader, &slice)) {
@ -242,7 +241,7 @@ static PyObject *pygrpc_read_event_args(grpc_event *c_event) {
if (bytes == NULL) {
return NULL;
}
event_args = PyTuple_Pack(8, read_event_kind, (PyObject *)c_event->tag,
event_args = PyTuple_Pack(8, read_event_kind, user_tag,
Py_None, Py_None, Py_None, bytes, Py_None,
Py_None);
Py_DECREF(bytes);
@ -251,32 +250,65 @@ static PyObject *pygrpc_read_event_args(grpc_event *c_event) {
}
static PyObject *pygrpc_metadata_event_args(grpc_event *c_event) {
pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag);
PyObject *user_tag = tag->user_tag;
PyObject *metadata = pygrpc_metadata_collection_get(
c_event->data.client_metadata_read.elements,
c_event->data.client_metadata_read.count);
tag->call->recv_metadata.metadata,
tag->call->recv_metadata.count);
PyObject* result = PyTuple_Pack(
8, metadata_event_kind, (PyObject *)c_event->tag, Py_None, Py_None,
8, metadata_event_kind, user_tag, Py_None, Py_None,
Py_None, Py_None, Py_None, metadata);
Py_DECREF(metadata);
return result;
}
static PyObject *pygrpc_finished_event_args(grpc_event *c_event) {
static PyObject *pygrpc_finished_server_event_args(grpc_event *c_event) {
PyObject *code;
PyObject *details;
PyObject *status;
PyObject *event_args;
pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag);
PyObject *user_tag = tag->user_tag;
code = pygrpc_status_code(tag->call->cancelled ? GRPC_STATUS_CANCELLED : GRPC_STATUS_OK);
if (code == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Unrecognized status code!");
return NULL;
}
details = PyBytes_FromString("");
if (details == NULL) {
return NULL;
}
status = PyObject_CallFunctionObjArgs(status_class, code, details, NULL);
Py_DECREF(details);
if (status == NULL) {
return NULL;
}
event_args = PyTuple_Pack(8, finish_event_kind, user_tag,
Py_None, Py_None, Py_None, Py_None, status,
Py_None);
Py_DECREF(status);
return event_args;
}
static PyObject *pygrpc_finished_client_event_args(grpc_event *c_event) {
PyObject *code;
PyObject *details;
PyObject *status;
PyObject *event_args;
PyObject *metadata;
pygrpc_tag *tag = (pygrpc_tag *)(c_event->tag);
PyObject *user_tag = tag->user_tag;
code = pygrpc_status_code(c_event->data.finished.status);
code = pygrpc_status_code(tag->call->status);
if (code == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Unrecognized status code!");
return NULL;
}
if (c_event->data.finished.details == NULL) {
if (tag->call->status_details == NULL) {
details = PyBytes_FromString("");
} else {
details = PyBytes_FromString(c_event->data.finished.details);
details = PyBytes_FromString(tag->call->status_details);
}
if (details == NULL) {
return NULL;
@ -287,9 +319,9 @@ static PyObject *pygrpc_finished_event_args(grpc_event *c_event) {
return NULL;
}
metadata = pygrpc_metadata_collection_get(
c_event->data.finished.metadata_elements,
c_event->data.finished.metadata_count);
event_args = PyTuple_Pack(8, finish_event_kind, (PyObject *)c_event->tag,
tag->call->recv_trailing_metadata.metadata,
tag->call->recv_trailing_metadata.count);
event_args = PyTuple_Pack(8, finish_event_kind, user_tag,
Py_None, Py_None, Py_None, Py_None, status,
metadata);
Py_DECREF(status);
@ -348,28 +380,51 @@ static PyObject *pygrpc_completion_queue_get(CompletionQueue *self,
Py_RETURN_NONE;
}
pygrpc_tag *tag = (pygrpc_tag *)c_event->tag;
switch (c_event->type) {
case GRPC_QUEUE_SHUTDOWN:
event_args = pygrpc_stop_event_args(c_event);
break;
case GRPC_WRITE_ACCEPTED:
event_args = pygrpc_write_event_args(c_event);
break;
case GRPC_FINISH_ACCEPTED:
event_args = pygrpc_complete_event_args(c_event);
break;
case GRPC_SERVER_RPC_NEW:
event_args = pygrpc_service_event_args(c_event);
break;
case GRPC_READ:
event_args = pygrpc_read_event_args(c_event);
break;
case GRPC_CLIENT_METADATA_READ:
event_args = pygrpc_metadata_event_args(c_event);
break;
case GRPC_FINISHED:
event_args = pygrpc_finished_event_args(c_event);
case GRPC_OP_COMPLETE: {
if (!tag) {
PyErr_SetString(PyExc_Exception, "Unrecognized event type!");
return NULL;
}
switch (tag->type) {
case PYGRPC_INITIAL_METADATA:
if (tag) {
pygrpc_tag_destroy(tag);
}
grpc_event_finish(c_event);
return pygrpc_completion_queue_get(self, args);
case PYGRPC_WRITE_ACCEPTED:
event_args = pygrpc_write_event_args(c_event);
break;
case PYGRPC_FINISH_ACCEPTED:
event_args = pygrpc_complete_event_args(c_event);
break;
case PYGRPC_SERVER_RPC_NEW:
event_args = pygrpc_service_event_args(c_event);
break;
case PYGRPC_READ:
event_args = pygrpc_read_event_args(c_event);
break;
case PYGRPC_CLIENT_METADATA_READ:
event_args = pygrpc_metadata_event_args(c_event);
break;
case PYGRPC_FINISHED_CLIENT:
event_args = pygrpc_finished_client_event_args(c_event);
break;
case PYGRPC_FINISHED_SERVER:
event_args = pygrpc_finished_server_event_args(c_event);
break;
default:
PyErr_SetString(PyExc_Exception, "Unrecognized op event type!");
return NULL;
}
break;
}
default:
PyErr_SetString(PyExc_Exception, "Unrecognized event type!");
return NULL;
@ -382,7 +437,9 @@ static PyObject *pygrpc_completion_queue_get(CompletionQueue *self,
event = PyObject_CallObject(event_class, event_args);
Py_DECREF(event_args);
Py_XDECREF((PyObject *)c_event->tag);
if (tag) {
pygrpc_tag_destroy(tag);
}
grpc_event_finish(c_event);
return event;

@ -56,7 +56,7 @@ class LonelyClientTest(unittest.TestCase):
completion_queue = _low.CompletionQueue()
channel = _low.Channel('%s:%d' % (host, port), None)
client_call = _low.Call(channel, method, host, deadline)
client_call = _low.Call(channel, completion_queue, method, host, deadline)
client_call.invoke(completion_queue, metadata_tag, finish_tag)
first_event = completion_queue.get(after_deadline)
@ -138,7 +138,8 @@ class EchoTest(unittest.TestCase):
server_data = []
client_data = []
client_call = _low.Call(self.channel, method, self.host, deadline)
client_call = _low.Call(self.channel, self.client_completion_queue,
method, self.host, deadline)
client_call.add_metadata(client_metadata_key, client_metadata_value)
client_call.add_metadata(client_binary_metadata_key,
client_binary_metadata_value)
@ -335,7 +336,8 @@ class CancellationTest(unittest.TestCase):
server_data = []
client_data = []
client_call = _low.Call(self.channel, method, self.host, deadline)
client_call = _low.Call(self.channel, self.client_completion_queue,
method, self.host, deadline)
client_call.invoke(self.client_completion_queue, metadata_tag, finish_tag)

@ -36,12 +36,14 @@
#include <Python.h>
#include <grpc/grpc.h>
#include "grpc/_adapter/_call.h"
#include "grpc/_adapter/_completion_queue.h"
#include "grpc/_adapter/_error.h"
#include "grpc/_adapter/_server_credentials.h"
#include "grpc/_adapter/_tag.h"
static int pygrpc_server_init(Server *self, PyObject *args, PyObject *kwds) {
const PyObject *completion_queue;
CompletionQueue *completion_queue;
static char *kwlist[] = {"completion_queue", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!:Server", kwlist,
@ -50,7 +52,9 @@ static int pygrpc_server_init(Server *self, PyObject *args, PyObject *kwds) {
return -1;
}
self->c_server = grpc_server_create(
((CompletionQueue *)completion_queue)->c_completion_queue, NULL);
completion_queue->c_completion_queue, NULL);
self->completion_queue = completion_queue;
Py_INCREF(completion_queue);
return 0;
}
@ -58,6 +62,7 @@ static void pygrpc_server_dealloc(Server *self) {
if (self->c_server != NULL) {
grpc_server_destroy(self->c_server);
}
Py_XDECREF(self->completion_queue);
self->ob_type->tp_free((PyObject *)self);
}
@ -109,8 +114,15 @@ static PyObject *pygrpc_server_start(Server *self) {
static const PyObject *pygrpc_server_service(Server *self, PyObject *tag) {
grpc_call_error call_error;
const PyObject *result;
call_error = grpc_server_request_call_old(self->c_server, (void *)tag);
pygrpc_tag *c_tag = pygrpc_tag_new_server_rpc_call(tag);
c_tag->call->completion_queue = self->completion_queue;
c_tag->call->server = self;
Py_INCREF(c_tag->call->completion_queue);
Py_INCREF(c_tag->call->server);
call_error = grpc_server_request_call(
self->c_server, &c_tag->call->c_call, &c_tag->call->call_details,
&c_tag->call->recv_metadata, self->completion_queue->c_completion_queue,
c_tag);
result = pygrpc_translate_call_error(call_error);
if (result != NULL) {

@ -37,8 +37,12 @@
#include <Python.h>
#include <grpc/grpc.h>
#include "grpc/_adapter/_completion_queue.h"
typedef struct {
PyObject_HEAD
CompletionQueue *completion_queue;
grpc_server *c_server;
} Server;

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

Loading…
Cancel
Save