Merge branch 'master' of github.com:google/grpc into freebsd

Conflicts:
	Makefile
	templates/Makefile.template
pull/1047/head
Nicolas "Pixel" Noble 10 years ago
commit f0863b0227
  1. 201
      Makefile
  2. 22
      build.json
  3. 2
      examples/pubsub/publisher_test.cc
  4. 2
      examples/pubsub/subscriber_test.cc
  5. 80
      include/grpc++/async_generic_service.h
  6. 7
      include/grpc++/async_unary_call.h
  7. 82
      include/grpc++/byte_buffer.h
  8. 4
      include/grpc++/channel_interface.h
  9. 30
      include/grpc++/client_context.h
  10. 43
      include/grpc++/completion_queue.h
  11. 7
      include/grpc++/config.h
  12. 18
      include/grpc++/credentials.h
  13. 62
      include/grpc++/generic_stub.h
  14. 73
      include/grpc++/impl/call.h
  15. 8
      include/grpc++/impl/client_unary_call.h
  16. 10
      include/grpc++/server.h
  17. 11
      include/grpc++/server_builder.h
  18. 2
      include/grpc++/server_context.h
  19. 74
      include/grpc++/slice.h
  20. 2
      include/grpc/support/atm.h
  21. 28
      include/grpc/support/atm_win32.h
  22. 2
      include/grpc/support/cpu.h
  23. 23
      include/grpc/support/port_platform.h
  24. 29
      src/compiler/python_generator.cc
  25. 19
      src/core/channel/http_server_filter.c
  26. 51
      src/core/channel/metadata_buffer.c
  27. 5
      src/core/iomgr/sockaddr_win32.h
  28. 3
      src/core/iomgr/tcp_server_windows.c
  29. 4
      src/core/iomgr/tcp_windows.c
  30. 2183
      src/core/security/roots.pem
  31. 53
      src/core/support/cpu_iphone.c
  32. 2
      src/core/support/cpu_posix.c
  33. 15
      src/core/support/env_win32.c
  34. 2
      src/core/support/file_win32.c
  35. 8
      src/core/support/log_win32.c
  36. 6
      src/core/support/string_win32.c
  37. 1
      src/core/support/sync_win32.c
  38. 4
      src/core/support/time_win32.c
  39. 10
      src/cpp/client/channel.h
  40. 18
      src/cpp/client/channel_arguments.cc
  41. 8
      src/cpp/client/client_context.cc
  42. 8
      src/cpp/client/client_unary_call.cc
  43. 9
      src/cpp/client/create_channel.cc
  44. 32
      src/cpp/client/secure_credentials.cc
  45. 95
      src/cpp/common/call.cc
  46. 15
      src/cpp/common/completion_queue.cc
  47. 22
      src/cpp/proto/proto_utils.cc
  48. 6
      src/cpp/proto/proto_utils.h
  49. 50
      src/cpp/server/async_generic_service.cc
  50. 16
      src/cpp/server/async_server_context.cc
  51. 3
      src/cpp/server/insecure_server_credentials.cc
  52. 12
      src/cpp/server/secure_server_credentials.cc
  53. 73
      src/cpp/server/server.cc
  54. 25
      src/cpp/server/server_builder.cc
  55. 4
      src/cpp/server/thread_pool.cc
  56. 2
      src/cpp/server/thread_pool.h
  57. 76
      src/cpp/util/byte_buffer.cc
  58. 48
      src/cpp/util/slice.cc
  59. 4
      src/cpp/util/status.cc
  60. 4
      src/cpp/util/time.cc
  61. 4
      src/cpp/util/time.h
  62. 20
      src/csharp/Grpc.Core.Tests/ClientServerTest.cs
  63. 4
      src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
  64. 62
      src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs
  65. 2
      src/csharp/Grpc.Core.Tests/ServerTest.cs
  66. 55
      src/csharp/Grpc.Core/Call.cs
  67. 30
      src/csharp/Grpc.Core/Calls.cs
  68. 7
      src/csharp/Grpc.Core/Grpc.Core.csproj
  69. 37
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  70. 33
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  71. 72
      src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs
  72. 4
      src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
  73. 5
      src/csharp/Grpc.Core/Marshaller.cs
  74. 126
      src/csharp/Grpc.Core/Metadata.cs
  75. 8
      src/csharp/Grpc.Core/Server.cs
  76. 15
      src/csharp/Grpc.Core/ServerServiceDefinition.cs
  77. 73
      src/csharp/Grpc.Core/Stub/AbstractStub.cs
  78. 64
      src/csharp/Grpc.Core/Stub/StubConfiguration.cs
  79. 11
      src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
  80. 36
      src/csharp/Grpc.Examples/MathGrpc.cs
  81. 3
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  82. 2
      src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
  83. 4
      src/csharp/Grpc.IntegrationTesting/InteropServer.cs
  84. 41
      src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
  85. 162
      src/csharp/ext/grpc_csharp_ext.c
  86. 34
      src/node/ext/call.cc
  87. 2
      src/node/package.json
  88. 4
      src/node/test/call_test.js
  89. 18
      src/node/test/end_to_end_test.js
  90. 5
      src/python/interop/interop/_insecure_interop_test.py
  91. 6
      src/python/interop/interop/_secure_interop_test.py
  92. 7
      src/python/interop/interop/client.py
  93. 40
      src/python/interop/interop/methods.py
  94. 5
      src/python/interop/interop/server.py
  95. 6
      src/python/src/grpc/_adapter/_face_test_case.py
  96. 81
      src/python/src/grpc/_adapter/_links_test.py
  97. 20
      src/python/src/grpc/_adapter/_lonely_rear_link_test.py
  98. 2
      src/python/src/grpc/_adapter/_test_links.py
  99. 60
      src/python/src/grpc/_adapter/fore.py
  100. 48
      src/python/src/grpc/_adapter/rear.py
  101. Some files were not shown because too many files have changed in this diff Show More

File diff suppressed because one or more lines are too long

@ -12,7 +12,9 @@
{
"name": "grpc++_base",
"public_headers": [
"include/grpc++/async_generic_service.h",
"include/grpc++/async_unary_call.h",
"include/grpc++/byte_buffer.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
"include/grpc++/client_context.h",
@ -30,6 +32,7 @@
"include/grpc++/server_builder.h",
"include/grpc++/server_context.h",
"include/grpc++/server_credentials.h",
"include/grpc++/slice.h",
"include/grpc++/status.h",
"include/grpc++/status_code_enum.h",
"include/grpc++/stream.h",
@ -54,12 +57,15 @@
"src/cpp/common/completion_queue.cc",
"src/cpp/common/rpc_method.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc",
"src/cpp/server/insecure_server_credentials.cc",
"src/cpp/server/server.cc",
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
"src/cpp/server/thread_pool.cc",
"src/cpp/util/byte_buffer.cc",
"src/cpp/util/slice.cc",
"src/cpp/util/status.cc",
"src/cpp/util/time.cc"
]
@ -1698,6 +1704,22 @@
"gpr"
]
},
{
"name": "generic_end2end_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/end2end/generic_end2end_test.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "grpc_cpp_plugin",
"build": "protoc",

@ -107,7 +107,7 @@ class PublisherTest : public ::testing::Test {
int port = grpc_pick_unused_port_or_die();
server_address_ << "localhost:" << port;
ServerBuilder builder;
builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials());
builder.AddListeningPort(server_address_.str(), grpc::InsecureServerCredentials());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();

@ -105,7 +105,7 @@ class SubscriberTest : public ::testing::Test {
int port = grpc_pick_unused_port_or_die();
server_address_ << "localhost:" << port;
ServerBuilder builder;
builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials());
builder.AddListeningPort(server_address_.str(), grpc::InsecureServerCredentials());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();

@ -0,0 +1,80 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPCXX_ASYNC_GENERIC_SERVICE_H
#define GRPCXX_ASYNC_GENERIC_SERVICE_H
#include <grpc++/byte_buffer.h>
#include <grpc++/stream.h>
struct grpc_server;
namespace grpc {
typedef ServerAsyncReaderWriter<ByteBuffer, ByteBuffer>
GenericServerAsyncReaderWriter;
class GenericServerContext GRPC_FINAL : public ServerContext {
public:
const grpc::string& method() const { return method_; }
const grpc::string& host() const { return host_; }
private:
friend class Server;
grpc::string method_;
grpc::string host_;
};
class AsyncGenericService GRPC_FINAL {
public:
// TODO(yangg) Once we can add multiple completion queues to the server
// in c core, add a CompletionQueue* argument to the ctor here.
// TODO(yangg) support methods list.
AsyncGenericService(const grpc::string& methods) : server_(nullptr) {}
void RequestCall(GenericServerContext* ctx,
GenericServerAsyncReaderWriter* reader_writer,
CompletionQueue* cq, void* tag);
// The new rpc event should be obtained from this completion queue.
CompletionQueue* completion_queue();
private:
friend class Server;
Server* server_;
};
} // namespace grpc
#endif // GRPCXX_ASYNC_GENERIC_SERVICE_H

@ -48,10 +48,9 @@ template <class R>
class ClientAsyncResponseReader GRPC_FINAL {
public:
ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const grpc::protobuf::Message& request, void* tag)
: context_(context),
call_(channel->CreateCall(method, context, cq)) {
const RpcMethod& method, ClientContext* context,
const grpc::protobuf::Message& request, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
init_buf_.AddSendMessage(request);

@ -0,0 +1,82 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPCXX_BYTE_BUFFER_H
#define GRPCXX_BYTE_BUFFER_H
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpc++/config.h>
#include <grpc++/slice.h>
#include <vector>
namespace grpc {
class ByteBuffer GRPC_FINAL {
public:
ByteBuffer() : buffer_(nullptr) {}
ByteBuffer(Slice* slices, size_t nslices);
~ByteBuffer() {
if (buffer_) {
grpc_byte_buffer_destroy(buffer_);
}
}
void Dump(std::vector<Slice>* slices);
void Clear();
size_t Length();
private:
friend class CallOpBuffer;
// takes ownership
void set_buffer(grpc_byte_buffer* buf) {
if (buffer_) {
gpr_log(GPR_ERROR, "Overriding existing buffer");
Clear();
}
buffer_ = buf;
}
grpc_byte_buffer* buffer() const { return buffer_; }
grpc_byte_buffer* buffer_;
};
} // namespace grpc
#endif // GRPCXX_BYTE_BUFFER_H

@ -51,8 +51,8 @@ class ChannelInterface : public CallHook {
public:
virtual ~ChannelInterface() {}
virtual Call CreateCall(const RpcMethod &method, ClientContext *context,
CompletionQueue *cq) = 0;
virtual Call CreateCall(const RpcMethod& method, ClientContext* context,
CompletionQueue* cq) = 0;
};
} // namespace grpc

@ -74,8 +74,8 @@ class ClientContext {
ClientContext();
~ClientContext();
void AddMetadata(const grpc::string &meta_key,
const grpc::string &meta_value);
void AddMetadata(const grpc::string& meta_key,
const grpc::string& meta_value);
const std::multimap<grpc::string, grpc::string>& GetServerInitialMetadata() {
GPR_ASSERT(initial_metadata_received_);
@ -87,19 +87,17 @@ class ClientContext {
return trailing_metadata_;
}
void set_absolute_deadline(const system_clock::time_point &deadline);
void set_absolute_deadline(const system_clock::time_point& deadline);
system_clock::time_point absolute_deadline();
void set_authority(const grpc::string& authority) {
authority_ = authority;
}
void set_authority(const grpc::string& authority) { authority_ = authority; }
void TryCancel();
private:
// Disallow copy and assign.
ClientContext(const ClientContext &);
ClientContext &operator=(const ClientContext &);
ClientContext(const ClientContext&);
ClientContext& operator=(const ClientContext&);
friend class CallOpBuffer;
friend class Channel;
@ -118,24 +116,22 @@ class ClientContext {
template <class R>
friend class ::grpc::ClientAsyncResponseReader;
grpc_call *call() { return call_; }
void set_call(grpc_call *call) {
grpc_call* call() { return call_; }
void set_call(grpc_call* call) {
GPR_ASSERT(call_ == nullptr);
call_ = call;
}
grpc_completion_queue *cq() { return cq_; }
void set_cq(grpc_completion_queue *cq) { cq_ = cq; }
grpc_completion_queue* cq() { return cq_; }
void set_cq(grpc_completion_queue* cq) { cq_ = cq; }
gpr_timespec RawDeadline() { return absolute_deadline_; }
grpc::string authority() {
return authority_;
}
grpc::string authority() { return authority_; }
bool initial_metadata_received_;
grpc_call *call_;
grpc_completion_queue *cq_;
grpc_call* call_;
grpc_completion_queue* cq_;
gpr_timespec absolute_deadline_;
grpc::string authority_;
std::multimap<grpc::string, grpc::string> send_initial_metadata_;

@ -34,6 +34,7 @@
#ifndef GRPCXX_COMPLETION_QUEUE_H
#define GRPCXX_COMPLETION_QUEUE_H
#include <chrono>
#include <grpc++/impl/client_unary_call.h>
struct grpc_completion_queue;
@ -65,26 +66,38 @@ class CompletionQueueTag {
// to do)
// If this function returns false, the tag is dropped and not returned
// from the completion queue
virtual bool FinalizeResult(void **tag, bool *status) = 0;
virtual bool FinalizeResult(void** tag, bool* status) = 0;
};
// grpc_completion_queue wrapper class
class CompletionQueue {
public:
CompletionQueue();
explicit CompletionQueue(grpc_completion_queue *take);
explicit CompletionQueue(grpc_completion_queue* take);
~CompletionQueue();
// Blocking read from queue.
// Returns true if an event was received, false if the queue is ready
// for destruction.
bool Next(void **tag, bool *ok);
// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT
enum NextStatus { SHUTDOWN, GOT_EVENT, TIMEOUT };
// Nonblocking (until deadline) read from queue.
// Cannot rely on result of tag or ok if return is TIMEOUT
NextStatus AsyncNext(void** tag, bool* ok,
std::chrono::system_clock::time_point deadline);
// Blocking (until deadline) read from queue.
// Returns false if the queue is ready for destruction, true if event
bool Next(void** tag, bool* ok) {
return (
AsyncNext(tag, ok, (std::chrono::system_clock::time_point::max)()) !=
SHUTDOWN);
}
// Shutdown has to be called, and the CompletionQueue can only be
// destructed when false is returned from Next().
void Shutdown();
grpc_completion_queue *cq() { return cq_; }
grpc_completion_queue* cq() { return cq_; }
private:
// Friend synchronous wrappers so that they can access Pluck(), which is
@ -103,20 +116,20 @@ class CompletionQueue {
friend class ::grpc::ServerReaderWriter;
friend class ::grpc::Server;
friend class ::grpc::ServerContext;
friend Status BlockingUnaryCall(ChannelInterface *channel,
const RpcMethod &method,
ClientContext *context,
const grpc::protobuf::Message &request,
grpc::protobuf::Message *result);
friend Status BlockingUnaryCall(ChannelInterface* channel,
const RpcMethod& method,
ClientContext* context,
const grpc::protobuf::Message& request,
grpc::protobuf::Message* result);
// Wraps grpc_completion_queue_pluck.
// Cannot be mixed with calls to Next().
bool Pluck(CompletionQueueTag *tag);
bool Pluck(CompletionQueueTag* tag);
// Does a single polling pluck on tag
void TryPluck(CompletionQueueTag *tag);
void TryPluck(CompletionQueueTag* tag);
grpc_completion_queue *cq_; // owned
grpc_completion_queue* cq_; // owned
};
} // namespace grpc

@ -59,11 +59,12 @@
#ifndef GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM
#include <google/protobuf/io/zero_copy_stream.h>
#define GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM ::google::protobuf::io::ZeroCopyOutputStream
#define GRPC_CUSTOM_ZEROCOPYINPUTSTREAM ::google::protobuf::io::ZeroCopyInputStream
#define GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM \
::google::protobuf::io::ZeroCopyOutputStream
#define GRPC_CUSTOM_ZEROCOPYINPUTSTREAM \
::google::protobuf::io::ZeroCopyInputStream
#endif
namespace grpc {
typedef GRPC_CUSTOM_STRING string;

@ -50,8 +50,8 @@ class Credentials {
protected:
friend std::unique_ptr<Credentials> CompositeCredentials(
const std::unique_ptr<Credentials>& creds1,
const std::unique_ptr<Credentials>& creds2);
const std::unique_ptr<Credentials>& creds1,
const std::unique_ptr<Credentials>& creds2);
virtual SecureCredentials* AsSecureCredentials() = 0;
@ -105,6 +105,20 @@ std::unique_ptr<Credentials> ServiceAccountCredentials(
const grpc::string& json_key, const grpc::string& scope,
std::chrono::seconds token_lifetime);
// Builds JWT credentials.
// json_key is the JSON key string containing the client's private key.
// token_lifetime is the lifetime of each Json Web Token (JWT) created with
// this credentials. It should not exceed grpc_max_auth_token_lifetime or
// will be cropped to this value.
std::unique_ptr<Credentials> JWTCredentials(
const grpc::string& json_key, std::chrono::seconds token_lifetime);
// Builds refresh token credentials.
// json_refresh_token is the JSON string containing the refresh token along
// with a client_id and client_secret.
std::unique_ptr<Credentials> RefreshTokenCredentials(
const grpc::string& json_refresh_token);
// Builds IAM credentials.
std::unique_ptr<Credentials> IAMCredentials(
const grpc::string& authorization_token,

@ -0,0 +1,62 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPCXX_GENERIC_STUB_H
#define GRPCXX_GENERIC_STUB_H
#include <grpc++/byte_buffer.h>
#include <grpc++/stream.h>
namespace grpc {
typedef ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
GenericClientAsyncReaderWriter;
// Generic stubs provide a type-unsafe interface to call gRPC methods
// by name.
class GenericStub GRPC_FINAL {
public:
explicit GenericStub(std::shared_ptr<ChannelInterface> channel)
: channel_(channel) {}
// begin a call to a named method
std::unique_ptr<GenericClientAsyncReaderWriter> Call(
ClientContext* context, const grpc::string& method);
private:
std::shared_ptr<ChannelInterface> channel_;
};
} // namespace grpc
#endif // GRPCXX_GENERIC_STUB_H

@ -35,9 +35,9 @@
#define GRPCXX_IMPL_CALL_H
#include <grpc/grpc.h>
#include <grpc++/completion_queue.h>
#include <grpc++/config.h>
#include <grpc++/status.h>
#include <grpc++/completion_queue.h>
#include <memory>
#include <map>
@ -47,6 +47,7 @@ struct grpc_op;
namespace grpc {
class ByteBuffer;
class Call;
class CallOpBuffer : public CompletionQueueTag {
@ -54,85 +55,89 @@ class CallOpBuffer : public CompletionQueueTag {
CallOpBuffer();
~CallOpBuffer();
void Reset(void *next_return_tag);
void Reset(void* next_return_tag);
// Does not take ownership.
void AddSendInitialMetadata(
std::multimap<grpc::string, grpc::string> *metadata);
void AddSendInitialMetadata(ClientContext *ctx);
void AddRecvInitialMetadata(ClientContext *ctx);
void AddSendMessage(const grpc::protobuf::Message &message);
void AddRecvMessage(grpc::protobuf::Message *message);
std::multimap<grpc::string, grpc::string>* metadata);
void AddSendInitialMetadata(ClientContext* ctx);
void AddRecvInitialMetadata(ClientContext* ctx);
void AddSendMessage(const grpc::protobuf::Message& message);
void AddSendMessage(const ByteBuffer& message);
void AddRecvMessage(grpc::protobuf::Message* message);
void AddRecvMessage(ByteBuffer* message);
void AddClientSendClose();
void AddClientRecvStatus(ClientContext *ctx, Status *status);
void AddServerSendStatus(std::multimap<grpc::string, grpc::string> *metadata,
const Status &status);
void AddServerRecvClose(bool *cancelled);
void AddClientRecvStatus(ClientContext* ctx, Status* status);
void AddServerSendStatus(std::multimap<grpc::string, grpc::string>* metadata,
const Status& status);
void AddServerRecvClose(bool* cancelled);
// INTERNAL API:
// Convert to an array of grpc_op elements
void FillOps(grpc_op *ops, size_t *nops);
void FillOps(grpc_op* ops, size_t* nops);
// Called by completion queue just prior to returning from Next() or Pluck()
bool FinalizeResult(void **tag, bool *status) GRPC_OVERRIDE;
bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE;
bool got_message;
private:
void *return_tag_;
void* return_tag_;
// Send initial metadata
bool send_initial_metadata_;
size_t initial_metadata_count_;
grpc_metadata *initial_metadata_;
grpc_metadata* initial_metadata_;
// Recv initial metadta
std::multimap<grpc::string, grpc::string> *recv_initial_metadata_;
std::multimap<grpc::string, grpc::string>* recv_initial_metadata_;
grpc_metadata_array recv_initial_metadata_arr_;
// Send message
const grpc::protobuf::Message *send_message_;
grpc_byte_buffer *send_message_buf_;
const grpc::protobuf::Message* send_message_;
const ByteBuffer* send_message_buffer_;
grpc_byte_buffer* send_buf_;
// Recv message
grpc::protobuf::Message *recv_message_;
grpc_byte_buffer *recv_message_buf_;
grpc::protobuf::Message* recv_message_;
ByteBuffer* recv_message_buffer_;
grpc_byte_buffer* recv_buf_;
// Client send close
bool client_send_close_;
// Client recv status
std::multimap<grpc::string, grpc::string> *recv_trailing_metadata_;
Status *recv_status_;
std::multimap<grpc::string, grpc::string>* recv_trailing_metadata_;
Status* recv_status_;
grpc_metadata_array recv_trailing_metadata_arr_;
grpc_status_code status_code_;
char *status_details_;
char* status_details_;
size_t status_details_capacity_;
// Server send status
const Status *send_status_;
const Status* send_status_;
size_t trailing_metadata_count_;
grpc_metadata *trailing_metadata_;
grpc_metadata* trailing_metadata_;
int cancelled_buf_;
bool *recv_closed_;
bool* recv_closed_;
};
// Channel and Server implement this to allow them to hook performing ops
class CallHook {
public:
virtual ~CallHook() {}
virtual void PerformOpsOnCall(CallOpBuffer *ops, Call *call) = 0;
virtual void PerformOpsOnCall(CallOpBuffer* ops, Call* call) = 0;
};
// Straightforward wrapping of the C call object
class Call GRPC_FINAL {
public:
/* call is owned by the caller */
Call(grpc_call *call, CallHook *call_hook_, CompletionQueue *cq);
Call(grpc_call* call, CallHook* call_hook_, CompletionQueue* cq);
void PerformOps(CallOpBuffer *buffer);
void PerformOps(CallOpBuffer* buffer);
grpc_call *call() { return call_; }
CompletionQueue *cq() { return cq_; }
grpc_call* call() { return call_; }
CompletionQueue* cq() { return cq_; }
private:
CallHook *call_hook_;
CompletionQueue *cq_;
grpc_call *call_;
CallHook* call_hook_;
CompletionQueue* cq_;
grpc_call* call_;
};
} // namespace grpc

@ -45,10 +45,10 @@ class RpcMethod;
class Status;
// Wrapper that performs a blocking unary call
Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
const grpc::protobuf::Message &request,
grpc::protobuf::Message *result);
Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context,
const grpc::protobuf::Message& request,
grpc::protobuf::Message* result);
} // namespace grpc

@ -49,6 +49,8 @@ struct grpc_server;
namespace grpc {
class AsynchronousService;
class GenericServerContext;
class AsyncGenericService;
class RpcService;
class RpcServiceMethod;
class ServerCredentials;
@ -69,6 +71,7 @@ class Server GRPC_FINAL : private CallHook,
void Wait();
private:
friend class AsyncGenericService;
friend class ServerBuilder;
class SyncRequest;
@ -81,8 +84,9 @@ class Server GRPC_FINAL : private CallHook,
// The service must exist for the lifetime of the Server instance.
bool RegisterService(RpcService* service);
bool RegisterAsyncService(AsynchronousService* service);
void RegisterAsyncGenericService(AsyncGenericService* service);
// Add a listening port. Can be called multiple times.
int AddPort(const grpc::string& addr, ServerCredentials* creds);
int AddListeningPort(const grpc::string& addr, ServerCredentials* creds);
// Start the server.
bool Start();
@ -98,6 +102,10 @@ class Server GRPC_FINAL : private CallHook,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) GRPC_OVERRIDE;
void RequestAsyncGenericCall(GenericServerContext* context,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag);
// Completion queue.
CompletionQueue cq_;

@ -41,6 +41,7 @@
namespace grpc {
class AsyncGenericService;
class AsynchronousService;
class CompletionQueue;
class RpcService;
@ -64,10 +65,13 @@ class ServerBuilder {
// instance returned by BuildAndStart().
void RegisterAsyncService(AsynchronousService* service);
// Register a generic service.
void RegisterAsyncGenericService(AsyncGenericService* service);
// Add a listening port. Can be called multiple times.
void AddPort(const grpc::string& addr,
std::shared_ptr<ServerCredentials> creds,
int* selected_port = nullptr);
void AddListeningPort(const grpc::string& addr,
std::shared_ptr<ServerCredentials> creds,
int* selected_port = nullptr);
// Set the thread pool used for running appliation rpc handlers.
// Does not take ownership.
@ -87,6 +91,7 @@ class ServerBuilder {
std::vector<AsynchronousService*> async_services_;
std::vector<Port> ports_;
std::shared_ptr<ServerCredentials> creds_;
AsyncGenericService* generic_service_;
ThreadPoolInterface* thread_pool_;
};

@ -66,7 +66,7 @@ class CompletionQueue;
class Server;
// Interface of server side rpc context.
class ServerContext GRPC_FINAL {
class ServerContext {
public:
ServerContext(); // for async calls
~ServerContext();

@ -0,0 +1,74 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPCXX_SLICE_H
#define GRPCXX_SLICE_H
#include <grpc/support/slice.h>
#include <grpc++/config.h>
namespace grpc {
class Slice GRPC_FINAL {
public:
// construct empty slice
Slice();
// destructor - drops one ref
~Slice();
// construct slice from grpc slice, adding a ref
enum AddRef { ADD_REF };
Slice(gpr_slice slice, AddRef);
// construct slice from grpc slice, stealing a ref
enum StealRef { STEAL_REF };
Slice(gpr_slice slice, StealRef);
// copy constructor - adds a ref
Slice(const Slice& other);
// assignment - ref count is unchanged
Slice& operator=(Slice other) {
std::swap(slice_, other.slice_);
return *this;
}
size_t size() const { return GPR_SLICE_LENGTH(slice_); }
const gpr_uint8* begin() const { return GPR_SLICE_START_PTR(slice_); }
const gpr_uint8* end() const { return GPR_SLICE_END_PTR(slice_); }
private:
friend class ByteBuffer;
gpr_slice slice_;
};
} // namespace grpc
#endif // GRPCXX_SLICE_H

@ -83,7 +83,7 @@
#include <grpc/support/atm_gcc_atomic.h>
#elif defined(GPR_GCC_SYNC)
#include <grpc/support/atm_gcc_sync.h>
#elif defined(GPR_WIN32)
#elif defined(GPR_WIN32_ATOMIC)
#include <grpc/support/atm_win32.h>
#else
#error could not determine platform for atm

@ -51,7 +51,7 @@ static __inline gpr_atm gpr_atm_acq_load(const gpr_atm *p) {
static __inline gpr_atm gpr_atm_no_barrier_load(const gpr_atm *p) {
/* TODO(dklempner): Can we implement something better here? */
gpr_atm_acq_load(p);
return gpr_atm_acq_load(p);
}
static __inline void gpr_atm_rel_store(gpr_atm *p, gpr_atm value) {
@ -63,25 +63,31 @@ static __inline int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
/* InterlockedCompareExchangePointerNoFence() not available on vista or
windows7 */
#ifdef GPR_ARCH_64
return o == (gpr_atm)InterlockedCompareExchangeAcquire64(p, n, o);
return o == (gpr_atm)InterlockedCompareExchangeAcquire64((volatile LONGLONG *) p,
(LONGLONG) n, (LONGLONG) o);
#else
return o == (gpr_atm)InterlockedCompareExchangeAcquire(p, n, o);
return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG *) p,
(LONG) n, (LONG) o);
#endif
}
static __inline int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
#ifdef GPR_ARCH_64
return o == (gpr_atm)InterlockedCompareExchangeAcquire64(p, n, o);
return o == (gpr_atm)InterlockedCompareExchangeAcquire64((volatile LONGLONG) p,
(LONGLONG) n, (LONGLONG) o);
#else
return o == (gpr_atm)InterlockedCompareExchangeAcquire(p, n, o);
return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG *) p,
(LONG) n, (LONG) o);
#endif
}
static __inline int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
#ifdef GPR_ARCH_64
return o == (gpr_atm)InterlockedCompareExchangeRelease64(p, n, o);
return o == (gpr_atm)InterlockedCompareExchangeRelease64((volatile LONGLONG *) p,
(LONGLONG) n, (LONGLONG) o);
#else
return o == (gpr_atm)InterlockedCompareExchangeRelease(p, n, o);
return o == (gpr_atm)InterlockedCompareExchangeRelease((volatile LONG *) p,
(LONG) n, (LONG) o);
#endif
}
@ -101,11 +107,15 @@ static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta) {
#ifdef GPR_ARCH_64
do {
old = *p;
} while (old != (gpr_atm)InterlockedCompareExchange64(p, old + delta, old));
} while (old != (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG *) p,
(LONGLONG) old + delta,
(LONGLONG) old));
#else
do {
old = *p;
} while (old != (gpr_atm)InterlockedCompareExchange(p, old + delta, old));
} while (old != (gpr_atm)InterlockedCompareExchange((volatile LONG *) p,
(LONG) old + delta,
(LONG) old));
#endif
return old;
}

@ -41,7 +41,7 @@ extern "C" {
/* Interface providing CPU information for currently running system */
/* Return the number of CPU cores on the current system. Will return 0 if
if information is not available. */
the information is not available. */
unsigned gpr_cpu_num_cores(void);
/* Return the CPU on which the current thread is executing; N.B. This should

@ -43,11 +43,21 @@
#define GPR_ARCH_64 1
#define GPR_GETPID_IN_PROCESS_H 1
#define GPR_WINSOCK_SOCKET 1
#ifdef __GNUC__
#define GPR_GCC_ATOMIC 1
#else
#define GPR_WIN32_ATOMIC 1
#endif
#elif defined(_WIN32) || defined(WIN32)
#define GPR_ARCH_32 1
#define GPR_WIN32 1
#define GPR_GETPID_IN_PROCESS_H 1
#define GPR_WINSOCK_SOCKET 1
#ifdef __GNUC__
#define GPR_GCC_ATOMIC 1
#else
#define GPR_WIN32_ATOMIC 1
#endif
#elif defined(ANDROID) || defined(__ANDROID__)
#define GPR_ANDROID 1
#define GPR_ARCH_32 1
@ -114,10 +124,15 @@
#define GPR_ARCH_32 1
#endif /* _LP64 */
#elif defined(__APPLE__)
#include <TargetConditionals.h>
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#if TARGET_OS_IPHONE
#define GPR_CPU_IPHONE 1
#else /* TARGET_OS_IPHONE */
#define GPR_CPU_POSIX 1
#endif
#define GPR_GCC_ATOMIC 1
#define GPR_POSIX_LOG 1
#define GPR_POSIX_MULTIPOLL_WITH_POLL 1
@ -191,16 +206,16 @@
#endif
/* Validate platform combinations */
#if defined(GPR_GCC_ATOMIC) + defined(GPR_GCC_SYNC) + defined(GPR_WIN32) != 1
#error Must define exactly one of GPR_GCC_ATOMIC, GPR_GCC_SYNC, GPR_WIN32
#if defined(GPR_GCC_ATOMIC) + defined(GPR_GCC_SYNC) + defined(GPR_WIN32_ATOMIC) != 1
#error Must define exactly one of GPR_GCC_ATOMIC, GPR_GCC_SYNC, GPR_WIN32_ATOMIC
#endif
#if defined(GPR_ARCH_32) + defined(GPR_ARCH_64) != 1
#error Must define exactly one of GPR_ARCH_32, GPR_ARCH_64
#endif
#if defined(GPR_CPU_LINUX) + defined(GPR_CPU_POSIX) + defined(GPR_WIN32) != 1
#error Must define exactly one of GPR_CPU_LINUX, GPR_CPU_POSIX, GPR_WIN32
#if defined(GPR_CPU_LINUX) + defined(GPR_CPU_POSIX) + defined(GPR_WIN32) + defined(GPR_CPU_IPHONE) != 1
#error Must define exactly one of GPR_CPU_LINUX, GPR_CPU_POSIX, GPR_WIN32, GPR_CPU_IPHONE
#endif
#if defined(GPR_POSIX_MULTIPOLL_WITH_POLL) && !defined(GPR_POSIX_SOCKET)

@ -229,7 +229,8 @@ bool GetModuleAndMessagePath(const Descriptor* type,
return true;
}
bool PrintServerFactory(const ServiceDescriptor* service, Printer* out) {
bool PrintServerFactory(const std::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) {
out->Print("def early_adopter_create_$Service$_server(servicer, port, "
"root_certificates, key_chain_pairs):\n",
"Service", service->name());
@ -293,17 +294,18 @@ bool PrintServerFactory(const ServiceDescriptor* service, Printer* out) {
out->Print("),\n");
}
out->Print("}\n");
// out->Print("return implementations.insecure_server("
// "method_service_descriptions, port)\n");
out->Print(
"return implementations.secure_server("
"method_service_descriptions, port, root_certificates,"
" key_chain_pairs)\n");
"\"$PackageQualifiedServiceName$\","
" method_service_descriptions, port, root_certificates,"
" key_chain_pairs)\n",
"PackageQualifiedServiceName", package_qualified_service_name);
}
return true;
}
bool PrintStubFactory(const ServiceDescriptor* service, Printer* out) {
bool PrintStubFactory(const std::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) {
map<std::string, std::string> dict = ListToDict({
"Service", service->name(),
});
@ -369,7 +371,9 @@ bool PrintStubFactory(const ServiceDescriptor* service, Printer* out) {
out->Print("}\n");
out->Print(
"return implementations.insecure_stub("
"method_invocation_descriptions, host, port)\n");
"\"$PackageQualifiedServiceName$\","
" method_invocation_descriptions, host, port)\n",
"PackageQualifiedServiceName", package_qualified_service_name);
}
return true;
}
@ -377,7 +381,7 @@ bool PrintStubFactory(const ServiceDescriptor* service, Printer* out) {
bool PrintPreamble(const FileDescriptor* file, Printer* out) {
out->Print("import abc\n");
out->Print("from grpc.early_adopter import implementations\n");
out->Print("from grpc.early_adopter import utilities\n");
out->Print("from grpc.framework.alpha import utilities\n");
return true;
}
@ -392,13 +396,18 @@ pair<bool, std::string> GetServices(const FileDescriptor* file) {
if (!PrintPreamble(file, &out)) {
return make_pair(false, "");
}
auto package = file->package();
if (!package.empty()) {
package = package.append(".");
}
for (int i = 0; i < file->service_count(); ++i) {
auto service = file->service(i);
auto package_qualified_service_name = package + service->name();
if (!(PrintServicer(service, &out) &&
PrintServer(service, &out) &&
PrintStub(service, &out) &&
PrintServerFactory(service, &out) &&
PrintStubFactory(service, &out))) {
PrintServerFactory(package_qualified_service_name, service, &out) &&
PrintStubFactory(package_qualified_service_name, service, &out))) {
return make_pair(false, "");
}
}

@ -66,6 +66,10 @@ typedef struct channel_data {
grpc_mdelem *status_ok;
grpc_mdelem *status_not_found;
grpc_mdstr *path_key;
grpc_mdstr *authority_key;
grpc_mdstr *host_key;
grpc_mdctx *mdctx;
size_t gettable_count;
gettable *gettables;
@ -181,6 +185,15 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
}
calld->path = op->data.metadata;
op->done_cb(op->user_data, GRPC_OP_OK);
} else if (op->data.metadata->key == channeld->host_key) {
/* translate host to :authority since :authority may be
omitted */
grpc_mdelem *authority = grpc_mdelem_from_metadata_strings(
channeld->mdctx, channeld->authority_key, op->data.metadata->value);
grpc_mdelem_unref(op->data.metadata);
op->data.metadata = authority;
/* pass the event up */
grpc_call_next_op(elem, op);
} else {
/* pass the event up */
grpc_call_next_op(elem, op);
@ -305,9 +318,13 @@ static void init_channel_elem(grpc_channel_element *elem,
channeld->https_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "https");
channeld->grpc_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "grpc");
channeld->path_key = grpc_mdstr_from_string(mdctx, ":path");
channeld->authority_key = grpc_mdstr_from_string(mdctx, ":authority");
channeld->host_key = grpc_mdstr_from_string(mdctx, "host");
channeld->content_type =
grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
channeld->mdctx = mdctx;
/* initialize http download support */
channeld->gettable_count = 0;
channeld->gettables = NULL;
@ -357,6 +374,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
grpc_mdelem_unref(channeld->grpc_scheme);
grpc_mdelem_unref(channeld->content_type);
grpc_mdstr_unref(channeld->path_key);
grpc_mdstr_unref(channeld->authority_key);
grpc_mdstr_unref(channeld->host_key);
}
const grpc_channel_filter grpc_http_server_filter = {

@ -147,54 +147,3 @@ void grpc_metadata_buffer_flush(grpc_metadata_buffer *buffer,
gpr_free(impl);
*buffer = NULL;
}
size_t grpc_metadata_buffer_count(const grpc_metadata_buffer *buffer) {
return *buffer ? (*buffer)->elems : 0;
}
typedef struct {
grpc_metadata_buffer_impl *impl;
} elems_hdr;
grpc_metadata *grpc_metadata_buffer_extract_elements(
grpc_metadata_buffer *buffer) {
grpc_metadata_buffer_impl *impl;
elems_hdr *hdr;
qelem *src;
grpc_metadata *out;
size_t i;
impl = *buffer;
if (!impl) {
return NULL;
}
hdr = gpr_malloc(sizeof(elems_hdr) + impl->elems * sizeof(grpc_metadata));
src = ELEMS(impl);
out = (grpc_metadata *)(hdr + 1);
hdr->impl = impl;
for (i = 0; i < impl->elems; i++) {
out[i].key = (char *)grpc_mdstr_as_c_string(src[i].md->key);
out[i].value = (char *)grpc_mdstr_as_c_string(src[i].md->value);
out[i].value_length = GPR_SLICE_LENGTH(src[i].md->value->slice);
}
/* clear out buffer (it's not possible to extract elements twice */
*buffer = NULL;
return out;
}
void grpc_metadata_buffer_cleanup_elements(void *elements,
grpc_op_error error) {
elems_hdr *hdr = ((elems_hdr *)elements) - 1;
if (!elements) {
return;
}
grpc_metadata_buffer_destroy(&hdr->impl, error);
gpr_free(hdr);
}

@ -38,4 +38,9 @@
#include <winsock2.h>
#include <mswsock.h>
#ifdef __MINGW32__
/* mingw seems to be missing that definition. */
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
#endif
#endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_WIN32_H */

@ -53,9 +53,6 @@
#define INIT_PORT_CAP 2
#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
static gpr_once s_init_max_accept_queue_size;
static int s_max_accept_queue_size;
/* one listening port */
typedef struct server_port {
gpr_uint8 addresses[sizeof(struct sockaddr_in6) * 2 + 32];

@ -172,7 +172,7 @@ static void win_notify_on_read(grpc_endpoint *ep,
tcp->read_slice = gpr_slice_malloc(8192);
buffer.len = GPR_SLICE_LENGTH(tcp->read_slice);
buffer.buf = GPR_SLICE_START_PTR(tcp->read_slice);
buffer.buf = (char *)GPR_SLICE_START_PTR(tcp->read_slice);
gpr_log(GPR_DEBUG, "win_notify_on_read: calling WSARecv without overlap");
status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags,
@ -284,7 +284,7 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
for (i = 0; i < tcp->write_slices.count; i++) {
buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices.slices[i]);
buffers[i].buf = GPR_SLICE_START_PTR(tcp->write_slices.slices[i]);
buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices.slices[i]);
}
gpr_log(GPR_DEBUG, "win_write: calling WSASend without overlap");

File diff suppressed because it is too large Load Diff

@ -0,0 +1,53 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/port_platform.h>
#ifdef GPR_CPU_IPHONE
/* Probably 2 instead of 1, but see comment on gpr_cpu_current_cpu. */
unsigned gpr_cpu_num_cores(void) {
return 1;
}
/* Most code that's using this is using it to shard across work queues. So
unless profiling shows it's a problem or there appears a way to detect the
currently running CPU core, let's have it shard the default way.
Note that the interface in cpu.h lets gpr_cpu_num_cores return 0, but doing
it makes it impossible for gpr_cpu_current_cpu to satisfy its stated range,
and some code might be relying on it. */
unsigned gpr_cpu_current_cpu(void) {
return 0;
}
#endif /* GPR_CPU_IPHONE */

@ -74,4 +74,4 @@ unsigned gpr_cpu_current_cpu(void) {
return shard_ptr(&magic_thread_local);
}
#endif /* GPR_CPU_LINUX */
#endif /* GPR_CPU_POSIX */

@ -36,6 +36,7 @@
#ifdef GPR_WIN32
#include "src/core/support/env.h"
#include "src/core/support/string.h"
#include <stdlib.h>
@ -43,14 +44,16 @@
#include <grpc/support/log.h>
char *gpr_getenv(const char *name) {
size_t required_size;
size_t size;
char *result = NULL;
char *duplicated;
errno_t err;
getenv_s(&required_size, NULL, 0, name);
if (required_size == 0) return NULL;
result = gpr_malloc(required_size);
getenv_s(&required_size, result, required_size, name);
return result;
err = _dupenv_s(&result, &size, name);
if (err) return NULL;
duplicated = gpr_strdup(result);
free(result);
return duplicated;
}
void gpr_setenv(const char *name, const char *value) {

@ -72,7 +72,7 @@ FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) {
if (_tfopen_s(&result, tmp_filename, TEXT("wb+")) != 0) goto end;
end:
if (result && tmp_filename) {
if (result && tmp_filename_out) {
*tmp_filename_out = gpr_tchar_to_char(tmp_filename);
}

@ -43,6 +43,7 @@
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "src/core/support/string.h"
#include "src/core/support/string_win32.h"
void gpr_log(const char *file, int line, gpr_log_severity severity,
@ -55,7 +56,7 @@ void gpr_log(const char *file, int line, gpr_log_severity severity,
va_start(args, format);
ret = _vscprintf(format, args);
va_end(args);
if (!(0 <= ret && ret < ~(size_t)0)) {
if (ret < 0) {
message = NULL;
} else {
/* Allocate a new buffer, with space for the NUL terminator. */
@ -66,7 +67,7 @@ void gpr_log(const char *file, int line, gpr_log_severity severity,
va_start(args, format);
ret = vsnprintf_s(message, strp_buflen, _TRUNCATE, format, args);
va_end(args);
if (ret != strp_buflen - 1) {
if ((size_t)ret != strp_buflen - 1) {
/* This should never happen. */
gpr_free(message);
message = NULL;
@ -90,7 +91,7 @@ void gpr_default_log(gpr_log_func_args *args) {
strcpy(time_buffer, "error:strftime");
}
fprintf(stderr, "%s%s.%09u %5u %s:%d] %s\n",
fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n",
gpr_log_severity_string(args->severity), time_buffer,
(int)(now.tv_nsec), GetCurrentThreadId(),
args->file, args->line, args->message);
@ -105,6 +106,7 @@ char *gpr_format_message(DWORD messageid) {
NULL, messageid,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)(&tmessage), 0, NULL);
if (status == 0) return gpr_strdup("Unable to retreive error string");
message = gpr_tchar_to_char(tmessage);
LocalFree(tmessage);
return message;

@ -44,6 +44,8 @@
#include <grpc/support/alloc.h>
#include "src/core/support/string.h"
int gpr_asprintf(char **strp, const char *format, ...) {
va_list args;
int ret;
@ -53,7 +55,7 @@ int gpr_asprintf(char **strp, const char *format, ...) {
va_start(args, format);
ret = _vscprintf(format, args);
va_end(args);
if (!(0 <= ret && ret < ~(size_t)0)) {
if (ret < 0) {
*strp = NULL;
return -1;
}
@ -69,7 +71,7 @@ int gpr_asprintf(char **strp, const char *format, ...) {
va_start(args, format);
ret = vsnprintf_s(*strp, strp_buflen, _TRUNCATE, format, args);
va_end(args);
if (ret == strp_buflen - 1) {
if ((size_t)ret == strp_buflen - 1) {
return ret;
}

@ -37,6 +37,7 @@
#ifdef GPR_WIN32
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#include <windows.h>
#include <grpc/support/log.h>

@ -42,8 +42,8 @@
gpr_timespec gpr_now(void) {
gpr_timespec now_tv;
struct __timeb32 now_tb;
_ftime32_s(&now_tb);
struct _timeb now_tb;
_ftime_s(&now_tb);
now_tv.tv_sec = now_tb.time;
now_tv.tv_nsec = now_tb.millitm * 1000000;
return now_tv;

@ -51,16 +51,16 @@ class StreamContextInterface;
class Channel GRPC_FINAL : public ChannelInterface {
public:
Channel(const grpc::string &target, grpc_channel *c_channel);
Channel(const grpc::string& target, grpc_channel* c_channel);
~Channel() GRPC_OVERRIDE;
virtual Call CreateCall(const RpcMethod &method, ClientContext *context,
CompletionQueue *cq) GRPC_OVERRIDE;
virtual void PerformOpsOnCall(CallOpBuffer *ops, Call *call) GRPC_OVERRIDE;
virtual Call CreateCall(const RpcMethod& method, ClientContext* context,
CompletionQueue* cq) GRPC_OVERRIDE;
virtual void PerformOpsOnCall(CallOpBuffer* ops, Call* call) GRPC_OVERRIDE;
private:
const grpc::string target_;
grpc_channel *const c_channel_; // owned
grpc_channel* const c_channel_; // owned
};
} // namespace grpc

@ -37,7 +37,7 @@
namespace grpc {
void ChannelArguments::SetSslTargetNameOverride(const grpc::string &name) {
void ChannelArguments::SetSslTargetNameOverride(const grpc::string& name) {
SetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, name);
}
@ -50,32 +50,32 @@ grpc::string ChannelArguments::GetSslTargetNameOverride() const {
return "";
}
void ChannelArguments::SetInt(const grpc::string &key, int value) {
void ChannelArguments::SetInt(const grpc::string& key, int value) {
grpc_arg arg;
arg.type = GRPC_ARG_INTEGER;
strings_.push_back(key);
arg.key = const_cast<char *>(strings_.back().c_str());
arg.key = const_cast<char*>(strings_.back().c_str());
arg.value.integer = value;
args_.push_back(arg);
}
void ChannelArguments::SetString(const grpc::string &key,
const grpc::string &value) {
void ChannelArguments::SetString(const grpc::string& key,
const grpc::string& value) {
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
strings_.push_back(key);
arg.key = const_cast<char *>(strings_.back().c_str());
arg.key = const_cast<char*>(strings_.back().c_str());
strings_.push_back(value);
arg.value.string = const_cast<char *>(strings_.back().c_str());
arg.value.string = const_cast<char*>(strings_.back().c_str());
args_.push_back(arg);
}
void ChannelArguments::SetChannelArgs(grpc_channel_args *channel_args) const {
void ChannelArguments::SetChannelArgs(grpc_channel_args* channel_args) const {
channel_args->num_args = args_.size();
if (channel_args->num_args > 0) {
channel_args->args = const_cast<grpc_arg *>(&args_[0]);
channel_args->args = const_cast<grpc_arg*>(&args_[0]);
}
}

@ -53,7 +53,7 @@ ClientContext::~ClientContext() {
if (cq_) {
grpc_completion_queue_shutdown(cq_);
// Drain cq_.
grpc_event *ev;
grpc_event* ev;
grpc_completion_type t;
do {
ev = grpc_completion_queue_next(cq_, gpr_inf_future);
@ -65,7 +65,7 @@ ClientContext::~ClientContext() {
}
void ClientContext::set_absolute_deadline(
const system_clock::time_point &deadline) {
const system_clock::time_point& deadline) {
Timepoint2Timespec(deadline, &absolute_deadline_);
}
@ -73,8 +73,8 @@ system_clock::time_point ClientContext::absolute_deadline() {
return Timespec2Timepoint(absolute_deadline_);
}
void ClientContext::AddMetadata(const grpc::string &meta_key,
const grpc::string &meta_value) {
void ClientContext::AddMetadata(const grpc::string& meta_key,
const grpc::string& meta_value) {
send_initial_metadata_.insert(std::make_pair(meta_key, meta_value));
}

@ -42,10 +42,10 @@
namespace grpc {
// Wrapper that performs a blocking unary call
Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
const grpc::protobuf::Message &request,
grpc::protobuf::Message *result) {
Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context,
const grpc::protobuf::Message& request,
grpc::protobuf::Message* result) {
CompletionQueue cq;
Call call(channel->CreateCall(method, context, &cq));
CallOpBuffer buf;

@ -41,9 +41,10 @@ namespace grpc {
class ChannelArguments;
std::shared_ptr<ChannelInterface> CreateChannel(
const grpc::string &target, const std::unique_ptr<Credentials> &creds,
const ChannelArguments &args) {
return creds ? creds->CreateChannel(target, args) :
std::shared_ptr<ChannelInterface>(new Channel(target, grpc_lame_client_channel_create()));
const grpc::string& target, const std::unique_ptr<Credentials>& creds,
const ChannelArguments& args) {
return creds ? creds->CreateChannel(target, args)
: std::shared_ptr<ChannelInterface>(
new Channel(target, grpc_lame_client_channel_create()));
}
} // namespace grpc

@ -55,7 +55,8 @@ class SecureCredentials GRPC_FINAL : public Credentials {
args.SetChannelArgs(&channel_args);
return std::shared_ptr<ChannelInterface>(new Channel(
args.GetSslTargetNameOverride().empty()
? target : args.GetSslTargetNameOverride(),
? target
: args.GetSslTargetNameOverride(),
grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args)));
}
@ -98,12 +99,37 @@ std::unique_ptr<Credentials> ComputeEngineCredentials() {
std::unique_ptr<Credentials> ServiceAccountCredentials(
const grpc::string& json_key, const grpc::string& scope,
std::chrono::seconds token_lifetime) {
gpr_timespec lifetime = gpr_time_from_seconds(
token_lifetime.count() > 0 ? token_lifetime.count() : 0);
if (token_lifetime.count() <= 0) {
gpr_log(GPR_ERROR,
"Trying to create ServiceAccountCredentials "
"with non-positive lifetime");
return WrapCredentials(nullptr);
}
gpr_timespec lifetime = gpr_time_from_seconds(token_lifetime.count());
return WrapCredentials(grpc_service_account_credentials_create(
json_key.c_str(), scope.c_str(), lifetime));
}
// Builds JWT credentials.
std::unique_ptr<Credentials> JWTCredentials(
const grpc::string& json_key, std::chrono::seconds token_lifetime) {
if (token_lifetime.count() <= 0) {
gpr_log(GPR_ERROR,
"Trying to create JWTCredentials with non-positive lifetime");
return WrapCredentials(nullptr);
}
gpr_timespec lifetime = gpr_time_from_seconds(token_lifetime.count());
return WrapCredentials(
grpc_jwt_credentials_create(json_key.c_str(), lifetime));
}
// Builds refresh token credentials.
std::unique_ptr<Credentials> RefreshTokenCredentials(
const grpc::string& json_refresh_token) {
return WrapCredentials(
grpc_refresh_token_credentials_create(json_refresh_token.c_str()));
}
// Builds IAM credentials.
std::unique_ptr<Credentials> IAMCredentials(
const grpc::string& authorization_token,

@ -31,8 +31,10 @@
*
*/
#include <grpc/support/alloc.h>
#include <grpc++/impl/call.h>
#include <grpc/support/alloc.h>
#include <grpc++/byte_buffer.h>
#include <grpc++/client_context.h>
#include <grpc++/channel_interface.h>
@ -46,15 +48,15 @@ CallOpBuffer::CallOpBuffer()
initial_metadata_count_(0),
initial_metadata_(nullptr),
recv_initial_metadata_(nullptr),
recv_initial_metadata_arr_{0, 0, nullptr},
send_message_(nullptr),
send_message_buf_(nullptr),
send_message_buffer_(nullptr),
send_buf_(nullptr),
recv_message_(nullptr),
recv_message_buf_(nullptr),
recv_message_buffer_(nullptr),
recv_buf_(nullptr),
client_send_close_(false),
recv_trailing_metadata_(nullptr),
recv_status_(nullptr),
recv_trailing_metadata_arr_{0, 0, nullptr},
status_code_(GRPC_STATUS_OK),
status_details_(nullptr),
status_details_capacity_(0),
@ -62,7 +64,12 @@ CallOpBuffer::CallOpBuffer()
trailing_metadata_count_(0),
trailing_metadata_(nullptr),
cancelled_buf_(0),
recv_closed_(nullptr) {}
recv_closed_(nullptr) {
memset(&recv_trailing_metadata_arr_, 0, sizeof(recv_trailing_metadata_arr_));
memset(&recv_initial_metadata_arr_, 0, sizeof(recv_initial_metadata_arr_));
recv_trailing_metadata_arr_.metadata = nullptr;
recv_initial_metadata_arr_.metadata = nullptr;
}
void CallOpBuffer::Reset(void* next_return_tag) {
return_tag_ = next_return_tag;
@ -74,18 +81,20 @@ void CallOpBuffer::Reset(void* next_return_tag) {
recv_initial_metadata_ = nullptr;
recv_initial_metadata_arr_.count = 0;
send_message_ = nullptr;
if (send_message_buf_) {
grpc_byte_buffer_destroy(send_message_buf_);
send_message_buf_ = nullptr;
if (send_buf_ && send_message_) {
grpc_byte_buffer_destroy(send_buf_);
}
send_message_ = nullptr;
send_message_buffer_ = nullptr;
send_buf_ = nullptr;
recv_message_ = nullptr;
got_message = false;
if (recv_message_buf_) {
grpc_byte_buffer_destroy(recv_message_buf_);
recv_message_buf_ = nullptr;
if (recv_buf_ && recv_message_) {
grpc_byte_buffer_destroy(recv_buf_);
}
recv_message_ = nullptr;
recv_message_buffer_ = nullptr;
recv_buf_ = nullptr;
client_send_close_ = false;
@ -106,11 +115,11 @@ CallOpBuffer::~CallOpBuffer() {
gpr_free(status_details_);
gpr_free(recv_initial_metadata_arr_.metadata);
gpr_free(recv_trailing_metadata_arr_.metadata);
if (recv_message_buf_) {
grpc_byte_buffer_destroy(recv_message_buf_);
if (recv_buf_ && recv_message_) {
grpc_byte_buffer_destroy(recv_buf_);
}
if (send_message_buf_) {
grpc_byte_buffer_destroy(send_message_buf_);
if (send_buf_ && send_message_) {
grpc_byte_buffer_destroy(send_buf_);
}
}
@ -166,11 +175,19 @@ void CallOpBuffer::AddSendMessage(const grpc::protobuf::Message& message) {
send_message_ = &message;
}
void CallOpBuffer::AddSendMessage(const ByteBuffer& message) {
send_message_buffer_ = &message;
}
void CallOpBuffer::AddRecvMessage(grpc::protobuf::Message* message) {
recv_message_ = message;
recv_message_->Clear();
}
void CallOpBuffer::AddRecvMessage(ByteBuffer* message) {
recv_message_buffer_ = message;
}
void CallOpBuffer::AddClientSendClose() { client_send_close_ = true; }
void CallOpBuffer::AddServerRecvClose(bool* cancelled) {
@ -206,19 +223,23 @@ void CallOpBuffer::FillOps(grpc_op* ops, size_t* nops) {
ops[*nops].data.recv_initial_metadata = &recv_initial_metadata_arr_;
(*nops)++;
}
if (send_message_) {
bool success = SerializeProto(*send_message_, &send_message_buf_);
if (!success) {
abort();
// TODO handle parse failure
if (send_message_ || send_message_buffer_) {
if (send_message_) {
bool success = SerializeProto(*send_message_, &send_buf_);
if (!success) {
abort();
// TODO handle parse failure
}
} else {
send_buf_ = send_message_buffer_->buffer();
}
ops[*nops].op = GRPC_OP_SEND_MESSAGE;
ops[*nops].data.send_message = send_message_buf_;
ops[*nops].data.send_message = send_buf_;
(*nops)++;
}
if (recv_message_) {
if (recv_message_ || recv_message_buffer_) {
ops[*nops].op = GRPC_OP_RECV_MESSAGE;
ops[*nops].data.recv_message = &recv_message_buf_;
ops[*nops].data.recv_message = &recv_buf_;
(*nops)++;
}
if (client_send_close_) {
@ -256,9 +277,11 @@ void CallOpBuffer::FillOps(grpc_op* ops, size_t* nops) {
bool CallOpBuffer::FinalizeResult(void** tag, bool* status) {
// Release send buffers.
if (send_message_buf_) {
grpc_byte_buffer_destroy(send_message_buf_);
send_message_buf_ = nullptr;
if (send_buf_ && send_message_) {
if (send_message_) {
grpc_byte_buffer_destroy(send_buf_);
}
send_buf_ = nullptr;
}
if (initial_metadata_) {
gpr_free(initial_metadata_);
@ -275,12 +298,16 @@ bool CallOpBuffer::FinalizeResult(void** tag, bool* status) {
FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_);
}
// Parse received message if any.
if (recv_message_) {
if (recv_message_buf_) {
if (recv_message_ || recv_message_buffer_) {
if (recv_buf_) {
got_message = *status;
*status = *status && DeserializeProto(recv_message_buf_, recv_message_);
grpc_byte_buffer_destroy(recv_message_buf_);
recv_message_buf_ = nullptr;
if (recv_message_) {
*status = *status && DeserializeProto(recv_buf_, recv_message_);
grpc_byte_buffer_destroy(recv_buf_);
} else {
recv_message_buffer_->set_buffer(recv_buf_);
}
recv_buf_ = nullptr;
} else {
// Read failed
got_message = false;

@ -57,19 +57,26 @@ class EventDeleter {
}
};
bool CompletionQueue::Next(void** tag, bool* ok) {
CompletionQueue::NextStatus
CompletionQueue::AsyncNext(void** tag, bool* ok,
std::chrono::system_clock::time_point deadline) {
std::unique_ptr<grpc_event, EventDeleter> ev;
gpr_timespec gpr_deadline;
Timepoint2Timespec(deadline, &gpr_deadline);
for (;;) {
ev.reset(grpc_completion_queue_next(cq_, gpr_inf_future));
ev.reset(grpc_completion_queue_next(cq_, gpr_deadline));
if (!ev) { /* got a NULL back because deadline passed */
return TIMEOUT;
}
if (ev->type == GRPC_QUEUE_SHUTDOWN) {
return false;
return SHUTDOWN;
}
auto cq_tag = static_cast<CompletionQueueTag*>(ev->tag);
*ok = ev->data.op_complete == GRPC_OP_OK;
*tag = cq_tag;
if (cq_tag->FinalizeResult(tag, ok)) {
return true;
return GOT_EVENT;
}
}
}

@ -45,7 +45,7 @@ const int kMaxBufferLength = 8192;
class GrpcBufferWriter GRPC_FINAL
: public ::grpc::protobuf::io::ZeroCopyOutputStream {
public:
explicit GrpcBufferWriter(grpc_byte_buffer **bp,
explicit GrpcBufferWriter(grpc_byte_buffer** bp,
int block_size = kMaxBufferLength)
: block_size_(block_size), byte_count_(0), have_backup_(false) {
*bp = grpc_byte_buffer_create(NULL, 0);
@ -58,7 +58,7 @@ class GrpcBufferWriter GRPC_FINAL
}
}
bool Next(void **data, int *size) GRPC_OVERRIDE {
bool Next(void** data, int* size) GRPC_OVERRIDE {
if (have_backup_) {
slice_ = backup_slice_;
have_backup_ = false;
@ -89,7 +89,7 @@ class GrpcBufferWriter GRPC_FINAL
private:
const int block_size_;
gpr_int64 byte_count_;
gpr_slice_buffer *slice_buffer_;
gpr_slice_buffer* slice_buffer_;
bool have_backup_;
gpr_slice backup_slice_;
gpr_slice slice_;
@ -98,7 +98,7 @@ class GrpcBufferWriter GRPC_FINAL
class GrpcBufferReader GRPC_FINAL
: public ::grpc::protobuf::io::ZeroCopyInputStream {
public:
explicit GrpcBufferReader(grpc_byte_buffer *buffer)
explicit GrpcBufferReader(grpc_byte_buffer* buffer)
: byte_count_(0), backup_count_(0) {
reader_ = grpc_byte_buffer_reader_create(buffer);
}
@ -106,7 +106,7 @@ class GrpcBufferReader GRPC_FINAL
grpc_byte_buffer_reader_destroy(reader_);
}
bool Next(const void **data, int *size) GRPC_OVERRIDE {
bool Next(const void** data, int* size) GRPC_OVERRIDE {
if (backup_count_ > 0) {
*data = GPR_SLICE_START_PTR(slice_) + GPR_SLICE_LENGTH(slice_) -
backup_count_;
@ -123,12 +123,10 @@ class GrpcBufferReader GRPC_FINAL
return true;
}
void BackUp(int count) GRPC_OVERRIDE {
backup_count_ = count;
}
void BackUp(int count) GRPC_OVERRIDE { backup_count_ = count; }
bool Skip(int count) GRPC_OVERRIDE {
const void *data;
const void* data;
int size;
while (Next(&data, &size)) {
if (size >= count) {
@ -149,18 +147,18 @@ class GrpcBufferReader GRPC_FINAL
private:
gpr_int64 byte_count_;
gpr_int64 backup_count_;
grpc_byte_buffer_reader *reader_;
grpc_byte_buffer_reader* reader_;
gpr_slice slice_;
};
namespace grpc {
bool SerializeProto(const grpc::protobuf::Message &msg, grpc_byte_buffer **bp) {
bool SerializeProto(const grpc::protobuf::Message& msg, grpc_byte_buffer** bp) {
GrpcBufferWriter writer(bp);
return msg.SerializeToZeroCopyStream(&writer);
}
bool DeserializeProto(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg) {
bool DeserializeProto(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg) {
GrpcBufferReader reader(buffer);
return msg->ParseFromZeroCopyStream(&reader);
}

@ -43,11 +43,11 @@ namespace grpc {
// Serialize the msg into a buffer created inside the function. The caller
// should destroy the returned buffer when done with it. If serialization fails,
// false is returned and buffer is left unchanged.
bool SerializeProto(const grpc::protobuf::Message &msg,
grpc_byte_buffer **buffer);
bool SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** buffer);
// The caller keeps ownership of buffer and msg.
bool DeserializeProto(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg);
bool DeserializeProto(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg);
} // namespace grpc

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

@ -42,7 +42,7 @@
namespace grpc {
AsyncServerContext::AsyncServerContext(
grpc_call *call, const grpc::string &method, const grpc::string &host,
grpc_call* call, const grpc::string& method, const grpc::string& host,
system_clock::time_point absolute_deadline)
: method_(method),
host_(host),
@ -52,22 +52,22 @@ AsyncServerContext::AsyncServerContext(
AsyncServerContext::~AsyncServerContext() { grpc_call_destroy(call_); }
void AsyncServerContext::Accept(grpc_completion_queue *cq) {
void AsyncServerContext::Accept(grpc_completion_queue* cq) {
GPR_ASSERT(grpc_call_server_accept_old(call_, cq, this) == GRPC_CALL_OK);
GPR_ASSERT(grpc_call_server_end_initial_metadata_old(
call_, GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK);
}
bool AsyncServerContext::StartRead(grpc::protobuf::Message *request) {
bool AsyncServerContext::StartRead(grpc::protobuf::Message* request) {
GPR_ASSERT(request);
request_ = request;
grpc_call_error err = grpc_call_start_read_old(call_, this);
return err == GRPC_CALL_OK;
}
bool AsyncServerContext::StartWrite(const grpc::protobuf::Message &response,
bool AsyncServerContext::StartWrite(const grpc::protobuf::Message& response,
int flags) {
grpc_byte_buffer *buffer = nullptr;
grpc_byte_buffer* buffer = nullptr;
if (!SerializeProto(response, &buffer)) {
return false;
}
@ -76,16 +76,16 @@ bool AsyncServerContext::StartWrite(const grpc::protobuf::Message &response,
return err == GRPC_CALL_OK;
}
bool AsyncServerContext::StartWriteStatus(const Status &status) {
bool AsyncServerContext::StartWriteStatus(const Status& status) {
grpc_call_error err = grpc_call_start_write_status_old(
call_, static_cast<grpc_status_code>(status.code()),
status.details().empty() ? nullptr
: const_cast<char *>(status.details().c_str()),
: const_cast<char*>(status.details().c_str()),
this);
return err == GRPC_CALL_OK;
}
bool AsyncServerContext::ParseRead(grpc_byte_buffer *read_buffer) {
bool AsyncServerContext::ParseRead(grpc_byte_buffer* read_buffer) {
GPR_ASSERT(request_);
bool success = DeserializeProto(read_buffer, request_);
request_ = nullptr;

@ -46,7 +46,8 @@ class InsecureServerCredentialsImpl GRPC_FINAL : public ServerCredentials {
} // namespace
std::shared_ptr<ServerCredentials> InsecureServerCredentials() {
return std::shared_ptr<ServerCredentials>(new InsecureServerCredentialsImpl());
return std::shared_ptr<ServerCredentials>(
new InsecureServerCredentialsImpl());
}
} // namespace grpc

@ -40,7 +40,8 @@ namespace grpc {
namespace {
class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
public:
explicit SecureServerCredentials(grpc_server_credentials* creds) : creds_(creds) {}
explicit SecureServerCredentials(grpc_server_credentials* creds)
: creds_(creds) {}
~SecureServerCredentials() GRPC_OVERRIDE {
grpc_server_credentials_release(creds_);
}
@ -56,16 +57,17 @@ class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
} // namespace
std::shared_ptr<ServerCredentials> SslServerCredentials(
const SslServerCredentialsOptions &options) {
const SslServerCredentialsOptions& options) {
std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs;
for (const auto &key_cert_pair : options.pem_key_cert_pairs) {
for (const auto& key_cert_pair : options.pem_key_cert_pairs) {
pem_key_cert_pairs.push_back(
{key_cert_pair.private_key.c_str(), key_cert_pair.cert_chain.c_str()});
}
grpc_server_credentials *c_creds = grpc_ssl_server_credentials_create(
grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create(
options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
&pem_key_cert_pairs[0], pem_key_cert_pairs.size());
return std::shared_ptr<ServerCredentials>(new SecureServerCredentials(c_creds));
return std::shared_ptr<ServerCredentials>(
new SecureServerCredentials(c_creds));
}
} // namespace grpc

@ -36,8 +36,10 @@
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc++/completion_queue.h>
#include <grpc++/async_generic_service.h>
#include <grpc++/impl/rpc_service_method.h>
#include <grpc++/impl/service_type.h>
#include <grpc++/server_context.h>
@ -179,12 +181,12 @@ Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned)
thread_pool_owned_(thread_pool_owned) {}
Server::~Server() {
std::unique_lock<std::mutex> lock(mu_);
if (started_ && !shutdown_) {
lock.unlock();
Shutdown();
} else {
lock.unlock();
{
std::unique_lock<std::mutex> lock(mu_);
if (started_ && !shutdown_) {
lock.unlock();
Shutdown();
}
}
grpc_server_destroy(server_);
if (thread_pool_owned_) {
@ -226,7 +228,14 @@ bool Server::RegisterAsyncService(AsynchronousService* service) {
return true;
}
int Server::AddPort(const grpc::string& addr, ServerCredentials* creds) {
void Server::RegisterAsyncGenericService(AsyncGenericService* service) {
GPR_ASSERT(service->server_ == nullptr &&
"Can only register an async generic service against one server.");
service->server_ = this;
}
int Server::AddListeningPort(const grpc::string& addr,
ServerCredentials* creds) {
GPR_ASSERT(!started_);
return creds->AddPortToServer(addr, server_);
}
@ -289,13 +298,33 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag {
stream_(stream),
cq_(cq),
ctx_(ctx),
generic_ctx_(nullptr),
server_(server),
call_(nullptr),
payload_(nullptr) {
memset(&array_, 0, sizeof(array_));
grpc_call_details_init(&call_details_);
grpc_server_request_registered_call(
server->server_, registered_method, &call_, &deadline_, &array_,
request ? &payload_ : nullptr, cq->cq(), this);
server->server_, registered_method, &call_, &call_details_.deadline,
&array_, request ? &payload_ : nullptr, cq->cq(), this);
}
AsyncRequest(Server* server, GenericServerContext* ctx,
ServerAsyncStreamingInterface* stream, CompletionQueue* cq,
void* tag)
: tag_(tag),
request_(nullptr),
stream_(stream),
cq_(cq),
ctx_(nullptr),
generic_ctx_(ctx),
server_(server),
call_(nullptr),
payload_(nullptr) {
memset(&array_, 0, sizeof(array_));
grpc_call_details_init(&call_details_);
grpc_server_request_call(server->server_, &call_, &call_details_, &array_,
cq->cq(), this);
}
~AsyncRequest() {
@ -315,20 +344,29 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag {
*status = false;
}
}
ServerContext* ctx = ctx_ ? ctx_ : generic_ctx_;
GPR_ASSERT(ctx);
if (*status) {
ctx_->deadline_ = Timespec2Timepoint(deadline_);
ctx->deadline_ = Timespec2Timepoint(call_details_.deadline);
for (size_t i = 0; i < array_.count; i++) {
ctx_->client_metadata_.insert(std::make_pair(
ctx->client_metadata_.insert(std::make_pair(
grpc::string(array_.metadata[i].key),
grpc::string(
array_.metadata[i].value,
array_.metadata[i].value + array_.metadata[i].value_length)));
}
if (generic_ctx_) {
// TODO(yangg) remove the copy here.
generic_ctx_->method_ = call_details_.method;
generic_ctx_->host_ = call_details_.host;
gpr_free(call_details_.method);
gpr_free(call_details_.host);
}
}
ctx_->call_ = call_;
ctx->call_ = call_;
Call call(call_, server_, cq_);
if (orig_status && call_) {
ctx_->BeginCompletionOp(&call);
ctx->BeginCompletionOp(&call);
}
// just the pointers inside call are copied here
stream_->BindCall(&call);
@ -342,9 +380,10 @@ class Server::AsyncRequest GRPC_FINAL : public CompletionQueueTag {
ServerAsyncStreamingInterface* const stream_;
CompletionQueue* const cq_;
ServerContext* const ctx_;
GenericServerContext* const generic_ctx_;
Server* const server_;
grpc_call* call_;
gpr_timespec deadline_;
grpc_call_details call_details_;
grpc_metadata_array array_;
grpc_byte_buffer* payload_;
};
@ -356,6 +395,12 @@ void Server::RequestAsyncCall(void* registered_method, ServerContext* context,
new AsyncRequest(this, registered_method, context, request, stream, cq, tag);
}
void Server::RequestAsyncGenericCall(GenericServerContext* context,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) {
new AsyncRequest(this, context, stream, cq, tag);
}
void Server::ScheduleCallback() {
{
std::unique_lock<std::mutex> lock(mu_);

@ -41,7 +41,8 @@
namespace grpc {
ServerBuilder::ServerBuilder() : thread_pool_(nullptr) {}
ServerBuilder::ServerBuilder()
: generic_service_(nullptr), thread_pool_(nullptr) {}
void ServerBuilder::RegisterService(SynchronousService* service) {
services_.push_back(service->service());
@ -51,9 +52,20 @@ void ServerBuilder::RegisterAsyncService(AsynchronousService* service) {
async_services_.push_back(service);
}
void ServerBuilder::AddPort(const grpc::string& addr,
std::shared_ptr<ServerCredentials> creds,
int* selected_port) {
void ServerBuilder::RegisterAsyncGenericService(AsyncGenericService* service) {
if (generic_service_) {
gpr_log(GPR_ERROR,
"Adding multiple AsyncGenericService is unsupported for now. "
"Dropping the service %p",
service);
return;
}
generic_service_ = service;
}
void ServerBuilder::AddListeningPort(const grpc::string& addr,
std::shared_ptr<ServerCredentials> creds,
int* selected_port) {
ports_.push_back(Port{addr, creds, selected_port});
}
@ -84,8 +96,11 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
return nullptr;
}
}
if (generic_service_) {
server->RegisterAsyncGenericService(generic_service_);
}
for (auto& port : ports_) {
int r = server->AddPort(port.addr, port.creds.get());
int r = server->AddListeningPort(port.addr, port.creds.get());
if (!r) return nullptr;
if (port.selected_port != nullptr) {
*port.selected_port = r;

@ -66,12 +66,12 @@ ThreadPool::~ThreadPool() {
shutdown_ = true;
cv_.notify_all();
}
for (auto &t : threads_) {
for (auto& t : threads_) {
t.join();
}
}
void ThreadPool::ScheduleCallback(const std::function<void()> &callback) {
void ThreadPool::ScheduleCallback(const std::function<void()>& callback) {
std::lock_guard<std::mutex> lock(mu_);
callbacks_.push(callback);
cv_.notify_one();

@ -50,7 +50,7 @@ class ThreadPool GRPC_FINAL : public ThreadPoolInterface {
explicit ThreadPool(int num_threads);
~ThreadPool();
void ScheduleCallback(const std::function<void()> &callback) GRPC_OVERRIDE;
void ScheduleCallback(const std::function<void()>& callback) GRPC_OVERRIDE;
private:
std::mutex mu_;

@ -0,0 +1,76 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc++/byte_buffer.h>
namespace grpc {
ByteBuffer::ByteBuffer(Slice* slices, size_t nslices) {
// TODO(yangg) maybe expose some core API to simplify this
std::vector<gpr_slice> c_slices(nslices);
for (size_t i = 0; i < nslices; i++) {
c_slices[i] = slices[i].slice_;
}
buffer_ = grpc_byte_buffer_create(c_slices.data(), nslices);
}
void ByteBuffer::Clear() {
if (buffer_) {
grpc_byte_buffer_destroy(buffer_);
buffer_ = nullptr;
}
}
void ByteBuffer::Dump(std::vector<Slice>* slices) {
slices->clear();
if (!buffer_) {
return;
}
grpc_byte_buffer_reader* reader = grpc_byte_buffer_reader_create(buffer_);
gpr_slice s;
while (grpc_byte_buffer_reader_next(reader, &s)) {
slices->push_back(Slice(s, Slice::STEAL_REF));
gpr_slice_unref(s);
}
grpc_byte_buffer_reader_destroy(reader);
}
size_t ByteBuffer::Length() {
if (buffer_) {
return grpc_byte_buffer_length(buffer_);
} else {
return 0;
}
}
} // namespace grpc

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

@ -35,7 +35,7 @@
namespace grpc {
const Status &Status::OK = Status();
const Status &Status::Cancelled = Status(StatusCode::CANCELLED);
const Status& Status::OK = Status();
const Status& Status::Cancelled = Status(StatusCode::CANCELLED);
} // namespace grpc

@ -43,8 +43,8 @@ using std::chrono::system_clock;
namespace grpc {
// TODO(yangg) prevent potential overflow.
void Timepoint2Timespec(const system_clock::time_point &from,
gpr_timespec *to) {
void Timepoint2Timespec(const system_clock::time_point& from,
gpr_timespec* to) {
system_clock::duration deadline = from.time_since_epoch();
seconds secs = duration_cast<seconds>(deadline);
nanoseconds nsecs = duration_cast<nanoseconds>(deadline - secs);

@ -41,8 +41,8 @@
namespace grpc {
// from and to should be absolute time.
void Timepoint2Timespec(const std::chrono::system_clock::time_point &from,
gpr_timespec *to);
void Timepoint2Timespec(const std::chrono::system_clock::time_point& from,
gpr_timespec* to);
std::chrono::system_clock::time_point Timespec2Timepoint(gpr_timespec t);

@ -46,6 +46,8 @@ namespace Grpc.Core.Tests
{
string host = "localhost";
string serviceName = "/tests.Test";
Method<string, string> unaryEchoStringMethod = new Method<string, string>(
MethodType.Unary,
"/tests.Test/UnaryEchoString",
@ -69,15 +71,15 @@ namespace Grpc.Core.Tests
{
Server server = new Server();
server.AddServiceDefinition(
ServerServiceDefinition.CreateBuilder("someService")
ServerServiceDefinition.CreateBuilder(serviceName)
.AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build());
int port = server.AddPort(host + ":0");
int port = server.AddListeningPort(host + ":0");
server.Start();
using (Channel channel = new Channel(host + ":" + port))
{
var call = new Call<string, string>(unaryEchoStringMethod, channel);
var call = new Call<string, string>(serviceName, unaryEchoStringMethod, channel, Metadata.Empty);
Assert.AreEqual("ABC", Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)));
@ -92,15 +94,15 @@ namespace Grpc.Core.Tests
{
Server server = new Server();
server.AddServiceDefinition(
ServerServiceDefinition.CreateBuilder("someService")
ServerServiceDefinition.CreateBuilder(serviceName)
.AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build());
int port = server.AddPort(host + ":0");
int port = server.AddListeningPort(host + ":0");
server.Start();
using (Channel channel = new Channel(host + ":" + port))
{
var call = new Call<string, string>(unaryEchoStringMethod, channel);
var call = new Call<string, string>(serviceName, unaryEchoStringMethod, channel, Metadata.Empty);
BenchmarkUtil.RunBenchmark(100, 1000,
() => { Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)); });
}
@ -113,14 +115,14 @@ namespace Grpc.Core.Tests
{
Server server = new Server();
server.AddServiceDefinition(
ServerServiceDefinition.CreateBuilder("someService").Build());
ServerServiceDefinition.CreateBuilder(serviceName).Build());
int port = server.AddPort(host + ":0");
int port = server.AddListeningPort(host + ":0");
server.Start();
using (Channel channel = new Channel(host + ":" + port))
{
var call = new Call<string, string>(unaryEchoStringMethod, channel);
var call = new Call<string, string>(serviceName, unaryEchoStringMethod, channel, Metadata.Empty);
try
{

@ -42,6 +42,7 @@
<Compile Include="GrpcEnvironmentTest.cs" />
<Compile Include="TimespecTest.cs" />
<Compile Include="PInvokeTest.cs" />
<Compile Include="Internal\MetadataArraySafeHandleTest.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
@ -56,4 +57,7 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Folder Include="Internal\" />
</ItemGroup>
</Project>

@ -0,0 +1,62 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
using NUnit.Framework;
namespace Grpc.Core.Internal.Tests
{
public class MetadataArraySafeHandleTest
{
[Test]
public void CreateEmptyAndDestroy()
{
var metadata = Metadata.CreateBuilder().Build();
var nativeMetadata = MetadataArraySafeHandle.Create(metadata);
nativeMetadata.Dispose();
}
[Test]
public void CreateAndDestroy()
{
var metadata = Metadata.CreateBuilder()
.Add(new Metadata.MetadataEntry("host", "somehost"))
.Add(new Metadata.MetadataEntry("header2", "header value")).Build();
var nativeMetadata = MetadataArraySafeHandle.Create(metadata);
nativeMetadata.Dispose();
}
}
}

@ -47,7 +47,7 @@ namespace Grpc.Core.Tests
GrpcEnvironment.Initialize();
Server server = new Server();
server.AddPort("localhost:0");
server.AddListeningPort("localhost:0");
server.Start();
server.ShutdownAsync().Wait();

@ -33,65 +33,70 @@
using System;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
public class Call<TRequest, TResponse>
{
readonly string methodName;
readonly Func<TRequest, byte[]> requestSerializer;
readonly Func<byte[], TResponse> responseDeserializer;
readonly string name;
readonly Marshaller<TRequest> requestMarshaller;
readonly Marshaller<TResponse> responseMarshaller;
readonly Channel channel;
readonly Metadata headers;
public Call(string methodName,
Func<TRequest, byte[]> requestSerializer,
Func<byte[], TResponse> responseDeserializer,
TimeSpan timeout,
Channel channel)
public Call(string serviceName, Method<TRequest, TResponse> method, Channel channel, Metadata headers)
{
this.methodName = methodName;
this.requestSerializer = requestSerializer;
this.responseDeserializer = responseDeserializer;
this.channel = channel;
this.name = Preconditions.CheckNotNull(serviceName) + "/" + method.Name;
this.requestMarshaller = method.RequestMarshaller;
this.responseMarshaller = method.ResponseMarshaller;
this.channel = Preconditions.CheckNotNull(channel);
this.headers = Preconditions.CheckNotNull(headers);
}
public Call(Method<TRequest, TResponse> method, Channel channel)
public Channel Channel
{
this.methodName = method.Name;
this.requestSerializer = method.RequestMarshaller.Serializer;
this.responseDeserializer = method.ResponseMarshaller.Deserializer;
this.channel = channel;
get
{
return this.channel;
}
}
public Channel Channel
/// <summary>
/// Full methods name including the service name.
/// </summary>
public string Name
{
get
{
return this.channel;
return name;
}
}
public string MethodName
/// <summary>
/// Headers to send at the beginning of the call.
/// </summary>
public Metadata Headers
{
get
{
return this.methodName;
return headers;
}
}
public Func<TRequest, byte[]> RequestSerializer
public Marshaller<TRequest> RequestMarshaller
{
get
{
return this.requestSerializer;
return requestMarshaller;
}
}
public Func<byte[], TResponse> ResponseDeserializer
public Marshaller<TResponse> ResponseMarshaller
{
get
{
return this.responseDeserializer;
return responseMarshaller;
}
}
}

@ -45,30 +45,29 @@ namespace Grpc.Core
{
public static TResponse BlockingUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
return asyncCall.UnaryCall(call.Channel, call.MethodName, req);
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
return asyncCall.UnaryCall(call.Channel, call.Name, req, call.Headers);
}
public static async Task<TResponse> AsyncUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName);
return await asyncCall.UnaryCallAsync(req);
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
return await asyncCall.UnaryCallAsync(req, call.Headers);
}
public static void AsyncServerStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, IObserver<TResponse> outputs, CancellationToken token)
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName);
asyncCall.StartServerStreamingCall(req, outputs);
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
asyncCall.StartServerStreamingCall(req, outputs, call.Headers);
}
public static ClientStreamingAsyncResult<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, CancellationToken token)
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName);
var task = asyncCall.ClientStreamingCallAsync();
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
var task = asyncCall.ClientStreamingCallAsync(call.Headers);
var inputs = new ClientStreamingInputObserver<TRequest, TResponse>(asyncCall);
return new ClientStreamingAsyncResult<TRequest, TResponse>(task, inputs);
}
@ -80,10 +79,9 @@ namespace Grpc.Core
public static IObserver<TRequest> DuplexStreamingCall<TRequest, TResponse>(Call<TRequest, TResponse> call, IObserver<TResponse> outputs, CancellationToken token)
{
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName);
asyncCall.StartDuplexStreamingCall(outputs);
var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer);
asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name);
asyncCall.StartDuplexStreamingCall(outputs, call.Headers);
return new ClientStreamingInputObserver<TRequest, TResponse>(asyncCall);
}

@ -79,6 +79,10 @@
<Compile Include="Utils\Preconditions.cs" />
<Compile Include="Internal\ServerCredentialsSafeHandle.cs" />
<Compile Include="ServerCredentials.cs" />
<Compile Include="Metadata.cs" />
<Compile Include="Internal\MetadataArraySafeHandle.cs" />
<Compile Include="Stub\AbstractStub.cs" />
<Compile Include="Stub\StubConfiguration.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
@ -96,4 +100,7 @@
<Otherwise />
</Choose>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Folder Include="Stub\" />
</ItemGroup>
</Project>

@ -77,7 +77,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Blocking unary request - unary response call.
/// </summary>
public TResponse UnaryCall(Channel channel, string methodName, TRequest msg)
public TResponse UnaryCall(Channel channel, string methodName, TRequest msg, Metadata headers)
{
using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
{
@ -92,7 +92,11 @@ namespace Grpc.Core.Internal
halfcloseRequested = true;
readingDone = true;
}
call.BlockingUnary(cq, payload, unaryResponseHandler);
using (var metadataArray = MetadataArraySafeHandle.Create(headers))
{
call.BlockingUnary(cq, payload, unaryResponseHandler, metadataArray);
}
try
{
@ -109,7 +113,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Starts a unary request - unary response call.
/// </summary>
public Task<TResponse> UnaryCallAsync(TRequest msg)
public Task<TResponse> UnaryCallAsync(TRequest msg, Metadata headers)
{
lock (myLock)
{
@ -122,8 +126,10 @@ namespace Grpc.Core.Internal
byte[] payload = UnsafeSerialize(msg);
unaryResponseTcs = new TaskCompletionSource<TResponse>();
call.StartUnary(payload, unaryResponseHandler);
using (var metadataArray = MetadataArraySafeHandle.Create(headers))
{
call.StartUnary(payload, unaryResponseHandler, metadataArray);
}
return unaryResponseTcs.Task;
}
}
@ -132,7 +138,7 @@ namespace Grpc.Core.Internal
/// Starts a streamed request - unary response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
public Task<TResponse> ClientStreamingCallAsync()
public Task<TResponse> ClientStreamingCallAsync(Metadata headers)
{
lock (myLock)
{
@ -142,7 +148,10 @@ namespace Grpc.Core.Internal
readingDone = true;
unaryResponseTcs = new TaskCompletionSource<TResponse>();
call.StartClientStreaming(unaryResponseHandler);
using (var metadataArray = MetadataArraySafeHandle.Create(headers))
{
call.StartClientStreaming(unaryResponseHandler, metadataArray);
}
return unaryResponseTcs.Task;
}
@ -151,7 +160,7 @@ namespace Grpc.Core.Internal
/// <summary>
/// Starts a unary request - streamed response call.
/// </summary>
public void StartServerStreamingCall(TRequest msg, IObserver<TResponse> readObserver)
public void StartServerStreamingCall(TRequest msg, IObserver<TResponse> readObserver, Metadata headers)
{
lock (myLock)
{
@ -165,7 +174,10 @@ namespace Grpc.Core.Internal
byte[] payload = UnsafeSerialize(msg);
call.StartServerStreaming(payload, finishedHandler);
using (var metadataArray = MetadataArraySafeHandle.Create(headers))
{
call.StartServerStreaming(payload, finishedHandler, metadataArray);
}
StartReceiveMessage();
}
@ -175,7 +187,7 @@ namespace Grpc.Core.Internal
/// Starts a streaming request - streaming response call.
/// Use StartSendMessage and StartSendCloseFromClient to stream requests.
/// </summary>
public void StartDuplexStreamingCall(IObserver<TResponse> readObserver)
public void StartDuplexStreamingCall(IObserver<TResponse> readObserver, Metadata headers)
{
lock (myLock)
{
@ -185,7 +197,10 @@ namespace Grpc.Core.Internal
this.readObserver = readObserver;
call.StartDuplexStreaming(finishedHandler);
using (var metadataArray = MetadataArraySafeHandle.Create(headers))
{
call.StartDuplexStreaming(finishedHandler, metadataArray);
}
StartReceiveMessage();
}

@ -57,25 +57,28 @@ namespace Grpc.Core.Internal
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_unary(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_call_blocking_unary(CallSafeHandle call, CompletionQueueSafeHandle dedicatedCq,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_server_streaming(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
byte[] send_buffer, UIntPtr send_buffer_len,
MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
MetadataArraySafeHandle metadataArray);
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_send_message(CallSafeHandle call,
@ -109,29 +112,29 @@ namespace Grpc.Core.Internal
return grpcsharp_channel_create_call(channel, cq, method, host, deadline);
}
public void StartUnary(byte[] payload, CompletionCallbackDelegate callback)
public void StartUnary(byte[] payload, CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong)payload.Length)));
AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong)payload.Length), metadataArray));
}
public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback)
public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong)payload.Length));
grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong)payload.Length), metadataArray);
}
public void StartClientStreaming(CompletionCallbackDelegate callback)
public void StartClientStreaming(CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
AssertCallOk(grpcsharp_call_start_client_streaming(this, callback));
AssertCallOk(grpcsharp_call_start_client_streaming(this, callback, metadataArray));
}
public void StartServerStreaming(byte[] payload, CompletionCallbackDelegate callback)
public void StartServerStreaming(byte[] payload, CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong)payload.Length)));
AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong)payload.Length), metadataArray));
}
public void StartDuplexStreaming(CompletionCallbackDelegate callback)
public void StartDuplexStreaming(CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray)
{
AssertCallOk(grpcsharp_call_start_duplex_streaming(this, callback));
AssertCallOk(grpcsharp_call_start_duplex_streaming(this, callback, metadataArray));
}
public void StartSendMessage(byte[] payload, CompletionCallbackDelegate callback)

@ -0,0 +1,72 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace Grpc.Core.Internal
{
/// <summary>
/// grpc_metadata_array from <grpc/grpc.h>
/// </summary>
internal class MetadataArraySafeHandle : SafeHandleZeroIsInvalid
{
[DllImport("grpc_csharp_ext.dll")]
static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity);
[DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_metadata_array_destroy_full(IntPtr array);
private MetadataArraySafeHandle()
{
}
public static MetadataArraySafeHandle Create(Metadata metadata)
{
var entries = metadata.Entries;
var metadataArray = grpcsharp_metadata_array_create(new UIntPtr((ulong)entries.Count));
for (int i = 0; i < entries.Count; i++)
{
grpcsharp_metadata_array_add(metadataArray, entries[i].Key, entries[i].ValueBytes, new UIntPtr((ulong)entries[i].ValueBytes.Length));
}
return metadataArray;
}
protected override bool ReleaseHandle()
{
grpcsharp_metadata_array_destroy_full(handle);
return true;
}
}
}

@ -80,12 +80,12 @@ namespace Grpc.Core.Internal
return grpcsharp_server_create(cq, args);
}
public int AddPort(string addr)
public int AddListeningPort(string addr)
{
return grpcsharp_server_add_http2_port(this, addr);
}
public int AddPort(string addr, ServerCredentialsSafeHandle credentials)
public int AddListeningPort(string addr, ServerCredentialsSafeHandle credentials)
{
return grpcsharp_server_add_secure_http2_port(this, addr, credentials);
}

@ -32,6 +32,7 @@
#endregion
using System;
using Grpc.Core.Utils;
namespace Grpc.Core
{
@ -45,8 +46,8 @@ namespace Grpc.Core
public Marshaller(Func<T, byte[]> serializer, Func<byte[], T> deserializer)
{
this.serializer = serializer;
this.deserializer = deserializer;
this.serializer = Preconditions.CheckNotNull(serializer);
this.deserializer = Preconditions.CheckNotNull(deserializer);
}
public Func<T, byte[]> Serializer

@ -0,0 +1,126 @@
#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.Collections.Immutable;
using System.Runtime.InteropServices;
using System.Text;
namespace Grpc.Core
{
/// <summary>
/// gRPC call metadata.
/// </summary>
public class Metadata
{
public static readonly Metadata Empty = new Metadata(ImmutableList<MetadataEntry>.Empty);
readonly ImmutableList<MetadataEntry> entries;
public Metadata(ImmutableList<MetadataEntry> entries)
{
this.entries = entries;
}
public ImmutableList<MetadataEntry> Entries
{
get
{
return this.entries;
}
}
public static Builder CreateBuilder()
{
return new Builder();
}
public struct MetadataEntry
{
readonly string key;
readonly byte[] valueBytes;
public MetadataEntry(string key, byte[] valueBytes)
{
this.key = key;
this.valueBytes = valueBytes;
}
public MetadataEntry(string key, string value)
{
this.key = key;
this.valueBytes = Encoding.ASCII.GetBytes(value);
}
public string Key
{
get
{
return this.key;
}
}
// TODO: using ByteString would guarantee immutability.
public byte[] ValueBytes
{
get
{
return this.valueBytes;
}
}
}
public class Builder
{
readonly List<Metadata.MetadataEntry> entries = new List<Metadata.MetadataEntry>();
public List<MetadataEntry> Entries
{
get
{
return entries;
}
}
public Builder Add(MetadataEntry entry)
{
entries.Add(entry);
return this;
}
public Metadata Build()
{
return new Metadata(entries.ToImmutableList());
}
}
}
}

@ -76,17 +76,17 @@ namespace Grpc.Core
}
// only call before Start()
public int AddPort(string addr)
public int AddListeningPort(string addr)
{
return handle.AddPort(addr);
return handle.AddListeningPort(addr);
}
// only call before Start()
public int AddPort(string addr, ServerCredentials credentials)
public int AddListeningPort(string addr, ServerCredentials credentials)
{
using (var nativeCredentials = credentials.ToNativeCredentials())
{
return handle.AddPort(addr, nativeCredentials);
return handle.AddListeningPort(addr, nativeCredentials);
}
}

@ -43,12 +43,10 @@ namespace Grpc.Core
/// </summary>
public class ServerServiceDefinition
{
readonly string serviceName;
readonly ImmutableDictionary<string, IServerCallHandler> callHandlers;
private ServerServiceDefinition(string serviceName, ImmutableDictionary<string, IServerCallHandler> callHandlers)
private ServerServiceDefinition(ImmutableDictionary<string, IServerCallHandler> callHandlers)
{
this.serviceName = serviceName;
this.callHandlers = callHandlers;
}
@ -79,7 +77,7 @@ namespace Grpc.Core
Method<TRequest, TResponse> method,
UnaryRequestServerMethod<TRequest, TResponse> handler)
{
callHandlers.Add(method.Name, ServerCalls.UnaryRequestCall(method, handler));
callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.UnaryRequestCall(method, handler));
return this;
}
@ -87,13 +85,18 @@ namespace Grpc.Core
Method<TRequest, TResponse> method,
StreamingRequestServerMethod<TRequest, TResponse> handler)
{
callHandlers.Add(method.Name, ServerCalls.StreamingRequestCall(method, handler));
callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.StreamingRequestCall(method, handler));
return this;
}
public ServerServiceDefinition Build()
{
return new ServerServiceDefinition(serviceName, callHandlers.ToImmutableDictionary());
return new ServerServiceDefinition(callHandlers.ToImmutableDictionary());
}
private string GetFullMethodName(string serviceName, string methodName)
{
return serviceName + "/" + methodName;
}
}
}

@ -0,0 +1,73 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using Grpc.Core.Internal;
namespace Grpc.Core
{
// TODO: support adding timeout to methods.
/// <summary>
/// Base for client-side stubs.
/// </summary>
public abstract class AbstractStub<TStub, TConfig>
where TConfig : StubConfiguration
{
readonly Channel channel;
readonly TConfig config;
public AbstractStub(Channel channel, TConfig config)
{
this.channel = channel;
this.config = config;
}
public Channel Channel
{
get
{
return this.channel;
}
}
/// <summary>
/// Creates a new call to given method.
/// </summary>
protected Call<TRequest, TResponse> CreateCall<TRequest, TResponse>(string serviceName, Method<TRequest, TResponse> method)
{
var headerBuilder = Metadata.CreateBuilder();
config.HeaderInterceptor(headerBuilder);
return new Call<TRequest, TResponse>(serviceName, method, channel, headerBuilder.Build());
}
}
}

@ -0,0 +1,64 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
public delegate void HeaderInterceptorDelegate(Metadata.Builder headerBuilder);
public class StubConfiguration
{
/// <summary>
/// The default stub configuration.
/// </summary>
public static readonly StubConfiguration Default = new StubConfiguration((headerBuilder) => { });
readonly HeaderInterceptorDelegate headerInterceptor;
public StubConfiguration(HeaderInterceptorDelegate headerInterceptor)
{
this.headerInterceptor = Preconditions.CheckNotNull(headerInterceptor);
}
public HeaderInterceptorDelegate HeaderInterceptor
{
get
{
return headerInterceptor;
}
}
}
}

@ -58,10 +58,17 @@ namespace math.Tests
server = new Server();
server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl()));
int port = server.AddPort(host + ":0");
int port = server.AddListeningPort(host + ":0");
server.Start();
channel = new Channel(host + ":" + port);
client = MathGrpc.NewStub(channel);
// TODO: get rid of the custom header here once we have dedicated tests
// for header support.
var stubConfig = new StubConfiguration((headerBuilder) =>
{
headerBuilder.Add(new Metadata.MetadataEntry("customHeader", "abcdef"));
});
client = MathGrpc.NewStub(channel, stubConfig);
}
[TestFixtureTearDown]

@ -45,6 +45,8 @@ namespace math
/// </summary>
public class MathGrpc
{
static readonly string ServiceName = "/math.Math";
static readonly Marshaller<DivArgs> DivArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom);
static readonly Marshaller<DivReply> DivReplyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom);
static readonly Marshaller<Num> NumMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom);
@ -52,25 +54,25 @@ namespace math
static readonly Method<DivArgs, DivReply> DivMethod = new Method<DivArgs, DivReply>(
MethodType.Unary,
"/math.Math/Div",
"Div",
DivArgsMarshaller,
DivReplyMarshaller);
static readonly Method<FibArgs, Num> FibMethod = new Method<FibArgs, Num>(
MethodType.ServerStreaming,
"/math.Math/Fib",
"Fib",
FibArgsMarshaller,
NumMarshaller);
static readonly Method<Num, Num> SumMethod = new Method<Num, Num>(
MethodType.ClientStreaming,
"/math.Math/Sum",
"Sum",
NumMarshaller,
NumMarshaller);
static readonly Method<DivArgs, DivReply> DivManyMethod = new Method<DivArgs, DivReply>(
MethodType.DuplexStreaming,
"/math.Math/DivMany",
"DivMany",
DivArgsMarshaller,
DivReplyMarshaller);
@ -87,42 +89,43 @@ namespace math
IObserver<DivArgs> DivMany(IObserver<DivReply> responseObserver, CancellationToken token = default(CancellationToken));
}
public class MathServiceClientStub : IMathServiceClient
public class MathServiceClientStub : AbstractStub<MathServiceClientStub, StubConfiguration>, IMathServiceClient
{
readonly Channel channel;
public MathServiceClientStub(Channel channel) : this(channel, StubConfiguration.Default)
{
}
public MathServiceClientStub(Channel channel)
public MathServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config)
{
this.channel = channel;
}
public DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<DivArgs, DivReply>(DivMethod, channel);
var call = CreateCall(ServiceName, DivMethod);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<DivArgs, DivReply>(DivMethod, channel);
var call = CreateCall(ServiceName, DivMethod);
return Calls.AsyncUnaryCall(call, request, token);
}
public void Fib(FibArgs request, IObserver<Num> responseObserver, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<FibArgs, Num>(FibMethod, channel);
var call = CreateCall(ServiceName, FibMethod);
Calls.AsyncServerStreamingCall(call, request, responseObserver, token);
}
public ClientStreamingAsyncResult<Num, Num> Sum(CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<Num, Num>(SumMethod, channel);
var call = CreateCall(ServiceName, SumMethod);
return Calls.AsyncClientStreamingCall(call, token);
}
public IObserver<DivArgs> DivMany(IObserver<DivReply> responseObserver, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<DivArgs, DivReply>(DivManyMethod, channel);
var call = CreateCall(ServiceName, DivManyMethod);
return Calls.DuplexStreamingCall(call, responseObserver, token);
}
}
@ -141,7 +144,7 @@ namespace math
public static ServerServiceDefinition BindService(IMathService serviceImpl)
{
return ServerServiceDefinition.CreateBuilder("/math.Math/")
return ServerServiceDefinition.CreateBuilder(ServiceName)
.AddMethod(DivMethod, serviceImpl.Div)
.AddMethod(FibMethod, serviceImpl.Fib)
.AddMethod(SumMethod, serviceImpl.Sum)
@ -152,5 +155,10 @@ namespace math
{
return new MathServiceClientStub(channel);
}
public static IMathServiceClient NewStub(Channel channel, StubConfiguration config)
{
return new MathServiceClientStub(channel, config);
}
}
}

@ -39,8 +39,7 @@
<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.1.34.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="System.Collections.Immutable">
<HintPath>..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
</ItemGroup>

@ -59,7 +59,7 @@ namespace Grpc.IntegrationTesting
server = new Server();
server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl()));
int port = server.AddPort(host + ":0", TestCredentials.CreateTestServerCredentials());
int port = server.AddListeningPort(host + ":0", TestCredentials.CreateTestServerCredentials());
server.Start();
var channelArgs = ChannelArgs.CreateBuilder()

@ -96,11 +96,11 @@ namespace Grpc.IntegrationTesting
string addr = "0.0.0.0:" + options.port;
if (options.useTls)
{
server.AddPort(addr, TestCredentials.CreateTestServerCredentials());
server.AddListeningPort(addr, TestCredentials.CreateTestServerCredentials());
}
else
{
server.AddPort(addr);
server.AddListeningPort(addr);
}
Console.WriteLine("Running server on " + addr);
server.Start();

@ -44,6 +44,8 @@ namespace grpc.testing
/// </summary>
public class TestServiceGrpc
{
static readonly string ServiceName = "/grpc.testing.TestService";
static readonly Marshaller<Empty> EmptyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom);
static readonly Marshaller<SimpleRequest> SimpleRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom);
static readonly Marshaller<SimpleResponse> SimpleResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom);
@ -54,37 +56,37 @@ namespace grpc.testing
static readonly Method<Empty, Empty> EmptyCallMethod = new Method<Empty, Empty>(
MethodType.Unary,
"/grpc.testing.TestService/EmptyCall",
"EmptyCall",
EmptyMarshaller,
EmptyMarshaller);
static readonly Method<SimpleRequest, SimpleResponse> UnaryCallMethod = new Method<SimpleRequest, SimpleResponse>(
MethodType.Unary,
"/grpc.testing.TestService/UnaryCall",
"UnaryCall",
SimpleRequestMarshaller,
SimpleResponseMarshaller);
static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> StreamingOutputCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.ServerStreaming,
"/grpc.testing.TestService/StreamingOutputCall",
"StreamingOutputCall",
StreamingOutputCallRequestMarshaller,
StreamingOutputCallResponseMarshaller);
static readonly Method<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCallMethod = new Method<StreamingInputCallRequest, StreamingInputCallResponse>(
MethodType.ClientStreaming,
"/grpc.testing.TestService/StreamingInputCall",
"StreamingInputCall",
StreamingInputCallRequestMarshaller,
StreamingInputCallResponseMarshaller);
static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
"/grpc.testing.TestService/FullDuplexCall",
"FullDuplexCall",
StreamingOutputCallRequestMarshaller,
StreamingOutputCallResponseMarshaller);
static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
"/grpc.testing.TestService/HalfDuplexCall",
"HalfDuplexCall",
StreamingOutputCallRequestMarshaller,
StreamingOutputCallResponseMarshaller);
@ -107,60 +109,61 @@ namespace grpc.testing
IObserver<StreamingOutputCallRequest> HalfDuplexCall(IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken));
}
public class TestServiceClientStub : ITestServiceClient
public class TestServiceClientStub : AbstractStub<TestServiceClientStub, StubConfiguration>, ITestServiceClient
{
readonly Channel channel;
public TestServiceClientStub(Channel channel) : base(channel, StubConfiguration.Default)
{
}
public TestServiceClientStub(Channel channel)
public TestServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config)
{
this.channel = channel;
}
public Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<Empty, Empty>(EmptyCallMethod, channel);
var call = CreateCall(ServiceName, EmptyCallMethod);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<Empty, Empty>(EmptyCallMethod, channel);
var call = CreateCall(ServiceName, EmptyCallMethod);
return Calls.AsyncUnaryCall(call, request, token);
}
public SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<SimpleRequest, SimpleResponse>(UnaryCallMethod, channel);
var call = CreateCall(ServiceName, UnaryCallMethod);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<SimpleRequest, SimpleResponse>(UnaryCallMethod, channel);
var call = CreateCall(ServiceName, UnaryCallMethod);
return Calls.AsyncUnaryCall(call, request, token);
}
public void StreamingOutputCall(StreamingOutputCallRequest request, IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(StreamingOutputCallMethod, channel);
var call = CreateCall(ServiceName, StreamingOutputCallMethod);
Calls.AsyncServerStreamingCall(call, request, responseObserver, token);
}
public ClientStreamingAsyncResult<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<StreamingInputCallRequest, StreamingInputCallResponse>(StreamingInputCallMethod, channel);
var call = CreateCall(ServiceName, StreamingInputCallMethod);
return Calls.AsyncClientStreamingCall(call, token);
}
public IObserver<StreamingOutputCallRequest> FullDuplexCall(IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(FullDuplexCallMethod, channel);
var call = CreateCall(ServiceName, FullDuplexCallMethod);
return Calls.DuplexStreamingCall(call, responseObserver, token);
}
public IObserver<StreamingOutputCallRequest> HalfDuplexCall(IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken))
{
var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(HalfDuplexCallMethod, channel);
var call = CreateCall(ServiceName, HalfDuplexCallMethod);
return Calls.DuplexStreamingCall(call, responseObserver, token);
}
}
@ -183,7 +186,7 @@ namespace grpc.testing
public static ServerServiceDefinition BindService(ITestService serviceImpl)
{
return ServerServiceDefinition.CreateBuilder("/grpc.testing.TestService/")
return ServerServiceDefinition.CreateBuilder(ServiceName)
.AddMethod(EmptyCallMethod, serviceImpl.EmptyCall)
.AddMethod(UnaryCallMethod, serviceImpl.UnaryCall)
.AddMethod(StreamingOutputCallMethod, serviceImpl.StreamingOutputCall)

@ -102,34 +102,114 @@ grpcsharp_batch_context *grpcsharp_batch_context_create() {
return ctx;
}
/**
* Destroys metadata array including keys and values.
/*
* Destroys array->metadata.
* The array pointer itself is not freed.
*/
void grpcsharp_metadata_array_destroy_metadata_only(
grpc_metadata_array *array) {
gpr_free(array->metadata);
}
/*
* Destroys keys, values and array->metadata.
* The array pointer itself is not freed.
*/
void grpcsharp_metadata_array_destroy_metadata_including_entries(
grpc_metadata_array *array) {
size_t i;
if (array->metadata) {
for (i = 0; i < array->count; i++) {
gpr_free((void *)array->metadata[i].key);
gpr_free((void *)array->metadata[i].value);
}
}
gpr_free(array->metadata);
}
/*
* Fully destroys the metadata array.
*/
GPR_EXPORT void GPR_CALLTYPE
grpcsharp_metadata_array_destroy_full(grpc_metadata_array *array) {
if (!array) {
return;
}
grpcsharp_metadata_array_destroy_metadata_including_entries(array);
gpr_free(array);
}
/*
* Creates an empty metadata array with given capacity.
* Array can later be destroyed by grpc_metadata_array_destroy_full.
*/
void grpcsharp_metadata_array_destroy_recursive(grpc_metadata_array *array) {
if (!array->metadata) {
GPR_EXPORT grpc_metadata_array *GPR_CALLTYPE
grpcsharp_metadata_array_create(size_t capacity) {
grpc_metadata_array *array =
(grpc_metadata_array *)gpr_malloc(sizeof(grpc_metadata_array));
grpc_metadata_array_init(array);
array->capacity = capacity;
array->count = 0;
if (capacity > 0) {
array->metadata =
(grpc_metadata *)gpr_malloc(sizeof(grpc_metadata) * capacity);
memset(array->metadata, 0, sizeof(grpc_metadata) * capacity);
} else {
array->metadata = NULL;
}
return array;
}
GPR_EXPORT void GPR_CALLTYPE
grpcsharp_metadata_array_add(grpc_metadata_array *array, const char *key,
const char *value, size_t value_length) {
size_t i = array->count;
GPR_ASSERT(array->count < array->capacity);
array->metadata[i].key = gpr_strdup(key);
array->metadata[i].value = (char *)gpr_malloc(value_length);
memcpy((void *)array->metadata[i].value, value, value_length);
array->metadata[i].value_length = value_length;
array->count++;
}
/* Move contents of metadata array */
void grpcsharp_metadata_array_move(grpc_metadata_array *dest,
grpc_metadata_array *src) {
if (!src) {
dest->capacity = 0;
dest->count = 0;
dest->metadata = NULL;
return;
}
/* TODO: destroy also keys and values */
grpc_metadata_array_destroy(array);
dest->capacity = src->capacity;
dest->count = src->count;
dest->metadata = src->metadata;
src->capacity = 0;
src->count = 0;
src->metadata = NULL;
}
void grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) {
if (!ctx) {
return;
}
grpcsharp_metadata_array_destroy_recursive(&(ctx->send_initial_metadata));
grpcsharp_metadata_array_destroy_metadata_including_entries(
&(ctx->send_initial_metadata));
grpc_byte_buffer_destroy(ctx->send_message);
grpcsharp_metadata_array_destroy_recursive(
grpcsharp_metadata_array_destroy_metadata_including_entries(
&(ctx->send_status_from_server.trailing_metadata));
gpr_free(ctx->send_status_from_server.status_details);
grpc_metadata_array_destroy(&(ctx->recv_initial_metadata));
grpcsharp_metadata_array_destroy_metadata_only(&(ctx->recv_initial_metadata));
grpc_byte_buffer_destroy(ctx->recv_message);
grpc_metadata_array_destroy(&(ctx->recv_status_on_client.trailing_metadata));
grpcsharp_metadata_array_destroy_metadata_only(
&(ctx->recv_status_on_client.trailing_metadata));
gpr_free((void *)ctx->recv_status_on_client.status_details);
/* NOTE: ctx->server_rpc_new.call is not destroyed because callback handler is
@ -137,7 +217,8 @@ void grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) {
to take its ownership. */
grpc_call_details_destroy(&(ctx->server_rpc_new.call_details));
grpc_metadata_array_destroy(&(ctx->server_rpc_new.request_metadata));
grpcsharp_metadata_array_destroy_metadata_only(
&(ctx->server_rpc_new.request_metadata));
gpr_free(ctx);
}
@ -346,17 +427,19 @@ grpcsharp_call_start_write_from_copied_buffer(grpc_call *call,
GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_unary(grpc_call *call, callback_funcptr callback,
const char *send_buffer, size_t send_buffer_len) {
const char *send_buffer, size_t send_buffer_len,
grpc_metadata_array *initial_metadata) {
/* TODO: don't use magic number */
grpc_op ops[6];
grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
ctx->callback = callback;
/* TODO: implement sending the metadata... */
ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
/* ctx->send_initial_metadata is already zeroed out. */
ops[0].data.send_initial_metadata.count = 0;
ops[0].data.send_initial_metadata.metadata = NULL;
grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
initial_metadata);
ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
ops[0].data.send_initial_metadata.metadata =
ctx->send_initial_metadata.metadata;
ops[1].op = GRPC_OP_SEND_MESSAGE;
ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
@ -389,9 +472,11 @@ GPR_EXPORT void GPR_CALLTYPE
grpcsharp_call_blocking_unary(grpc_call *call,
grpc_completion_queue *dedicated_cq,
callback_funcptr callback,
const char *send_buffer, size_t send_buffer_len) {
const char *send_buffer, size_t send_buffer_len,
grpc_metadata_array *initial_metadata) {
GPR_ASSERT(grpcsharp_call_start_unary(call, callback, send_buffer,
send_buffer_len) == GRPC_CALL_OK);
send_buffer_len,
initial_metadata) == GRPC_CALL_OK);
/* TODO: we would like to use pluck, but we don't know the tag */
GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) ==
@ -403,17 +488,19 @@ grpcsharp_call_blocking_unary(grpc_call *call,
GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_client_streaming(grpc_call *call,
callback_funcptr callback) {
callback_funcptr callback,
grpc_metadata_array *initial_metadata) {
/* TODO: don't use magic number */
grpc_op ops[4];
grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
ctx->callback = callback;
/* TODO: implement sending the metadata... */
ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
/* ctx->send_initial_metadata is already zeroed out. */
ops[0].data.send_initial_metadata.count = 0;
ops[0].data.send_initial_metadata.metadata = NULL;
grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
initial_metadata);
ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
ops[0].data.send_initial_metadata.metadata =
ctx->send_initial_metadata.metadata;
ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
ops[1].data.recv_initial_metadata = &(ctx->recv_initial_metadata);
@ -435,21 +522,20 @@ grpcsharp_call_start_client_streaming(grpc_call *call,
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_server_streaming(grpc_call *call,
callback_funcptr callback,
const char *send_buffer,
size_t send_buffer_len) {
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
grpc_call *call, callback_funcptr callback, const char *send_buffer,
size_t send_buffer_len, grpc_metadata_array *initial_metadata) {
/* TODO: don't use magic number */
grpc_op ops[5];
grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
ctx->callback = callback;
/* TODO: implement sending the metadata... */
ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
/* ctx->send_initial_metadata is already zeroed out. */
ops[0].data.send_initial_metadata.count = 0;
ops[0].data.send_initial_metadata.metadata = NULL;
grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
initial_metadata);
ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
ops[0].data.send_initial_metadata.metadata =
ctx->send_initial_metadata.metadata;
ops[1].op = GRPC_OP_SEND_MESSAGE;
ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
@ -476,17 +562,19 @@ grpcsharp_call_start_server_streaming(grpc_call *call,
GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_duplex_streaming(grpc_call *call,
callback_funcptr callback) {
callback_funcptr callback,
grpc_metadata_array *initial_metadata) {
/* TODO: don't use magic number */
grpc_op ops[3];
grpcsharp_batch_context *ctx = grpcsharp_batch_context_create();
ctx->callback = callback;
/* TODO: implement sending the metadata... */
ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
/* ctx->send_initial_metadata is already zeroed out. */
ops[0].data.send_initial_metadata.count = 0;
ops[0].data.send_initial_metadata.metadata = NULL;
grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
initial_metadata);
ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
ops[0].data.send_initial_metadata.metadata =
ctx->send_initial_metadata.metadata;
ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
ops[1].data.recv_initial_metadata = &(ctx->recv_initial_metadata);

@ -75,6 +75,9 @@ using v8::Value;
NanCallback *Call::constructor;
Persistent<FunctionTemplate> Call::fun_tpl;
bool EndsWith(const char *str, const char *substr) {
return strcmp(str+strlen(str)-strlen(substr), substr) == 0;
}
bool CreateMetadataArray(Handle<Object> metadata, grpc_metadata_array *array,
shared_ptr<Resources> resources) {
@ -99,14 +102,19 @@ bool CreateMetadataArray(Handle<Object> metadata, grpc_metadata_array *array,
Handle<Value> value = values->Get(j);
grpc_metadata *current = &array->metadata[array->count];
current->key = **utf8_key;
if (::node::Buffer::HasInstance(value)) {
current->value = ::node::Buffer::Data(value);
current->value_length = ::node::Buffer::Length(value);
Persistent<Value> *handle = new Persistent<Value>();
NanAssignPersistent(*handle, value);
resources->handles.push_back(unique_ptr<PersistentHolder>(
new PersistentHolder(handle)));
} else if (value->IsString()) {
// Only allow binary headers for "-bin" keys
if (EndsWith(current->key, "-bin")) {
if (::node::Buffer::HasInstance(value)) {
current->value = ::node::Buffer::Data(value);
current->value_length = ::node::Buffer::Length(value);
Persistent<Value> *handle = new Persistent<Value>();
NanAssignPersistent(*handle, value);
resources->handles.push_back(unique_ptr<PersistentHolder>(
new PersistentHolder(handle)));
continue;
}
}
if (value->IsString()) {
Handle<String> string_value = value->ToString();
NanUtf8String *utf8_value = new NanUtf8String(string_value);
resources->strings.push_back(unique_ptr<NanUtf8String>(utf8_value));
@ -146,9 +154,13 @@ Handle<Value> ParseMetadata(const grpc_metadata_array *metadata_array) {
array = NanNew<Array>(size_map[elem->key]);
metadata_object->Set(key_string, array);
}
array->Set(index_map[elem->key],
MakeFastBuffer(
NanNewBufferHandle(elem->value, elem->value_length)));
if (EndsWith(elem->key, "-bin")) {
array->Set(index_map[elem->key],
MakeFastBuffer(
NanNewBufferHandle(elem->value, elem->value_length)));
} else {
array->Set(index_map[elem->key], NanNew(elem->value));
}
index_map[elem->key] += 1;
}
return NanEscapeScope(metadata_object);

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

@ -142,8 +142,8 @@ describe('call', function() {
assert.doesNotThrow(function() {
var batch = {};
batch[grpc.opType.SEND_INITIAL_METADATA] = {
'key1': [new Buffer('value1')],
'key2': [new Buffer('value2')]
'key1-bin': [new Buffer('value1')],
'key2-bin': [new Buffer('value2')]
};
call.startBatch(batch, function(err, resp) {
assert.ifError(err);

@ -138,21 +138,21 @@ describe('end-to-end', function() {
client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
call.startBatch(client_batch, function(err, response) {
assert.ifError(err);
assert(response['send metadata']);
assert(response['client close']);
assert(response.hasOwnProperty('metadata'));
assert.strictEqual(response.metadata.server_key[0].toString(),
'server_value');
assert.deepEqual(response.status, {'code': grpc.status.OK,
'details': status_text,
'metadata': {}});
assert.deepEqual(response,{
'send metadata': true,
'client close': true,
metadata: {server_key: ['server_value']},
status: {'code': grpc.status.OK,
'details': status_text,
'metadata': {}}
});
done();
});
server.requestCall(function(err, call_details) {
var new_call = call_details['new call'];
assert.notEqual(new_call, null);
assert.strictEqual(new_call.metadata.client_key[0].toString(),
assert.strictEqual(new_call.metadata.client_key[0],
'client_value');
var server_call = new_call.call;
assert.notEqual(server_call, null);

@ -42,11 +42,12 @@ class InsecureInteropTest(
unittest.TestCase):
def setUp(self):
self.server = implementations.insecure_server(methods.SERVER_METHODS, 0)
self.server = implementations.insecure_server(
methods.SERVICE_NAME, methods.SERVER_METHODS, 0)
self.server.start()
port = self.server.port()
self.stub = implementations.insecure_stub(
methods.CLIENT_METHODS, 'localhost', port)
methods.SERVICE_NAME, methods.CLIENT_METHODS, 'localhost', port)
def tearDown(self):
self.server.stop()

@ -46,12 +46,12 @@ class SecureInteropTest(
def setUp(self):
self.server = implementations.secure_server(
methods.SERVER_METHODS, 0, resources.private_key(),
resources.certificate_chain())
methods.SERVICE_NAME, methods.SERVER_METHODS, 0,
resources.private_key(), resources.certificate_chain())
self.server.start()
port = self.server.port()
self.stub = implementations.secure_stub(
methods.CLIENT_METHODS, 'localhost', port,
methods.SERVICE_NAME, methods.CLIENT_METHODS, 'localhost', port,
resources.test_root_certificates(), None, None,
server_host_override=_SERVER_HOST_OVERRIDE)

@ -67,12 +67,13 @@ def _stub(args):
root_certificates = resources.prod_root_certificates()
stub = implementations.secure_stub(
methods.CLIENT_METHODS, args.server_host, args.server_port,
root_certificates, None, None,
methods.SERVICE_NAME, methods.CLIENT_METHODS, args.server_host,
args.server_port, root_certificates, None, None,
server_host_override=args.server_host_override)
else:
stub = implementations.insecure_stub(
methods.CLIENT_METHODS, args.server_host, args.server_port)
methods.SERVICE_NAME, methods.CLIENT_METHODS, args.server_host,
args.server_port)
return stub

@ -32,7 +32,7 @@
import enum
import threading
from grpc.early_adopter import utilities
from grpc.framework.alpha import utilities
from interop import empty_pb2
from interop import messages_pb2
@ -122,31 +122,31 @@ _SERVER_HALF_DUPLEX_CALL = utilities.stream_stream_service_description(
messages_pb2.StreamingOutputCallResponse.SerializeToString)
_SERVICE_NAME = '/grpc.testing.TestService'
SERVICE_NAME = 'grpc.testing.TestService'
EMPTY_CALL_METHOD_NAME = _SERVICE_NAME + '/EmptyCall'
UNARY_CALL_METHOD_NAME = _SERVICE_NAME + '/UnaryCall'
STREAMING_OUTPUT_CALL_METHOD_NAME = _SERVICE_NAME + '/StreamingOutputCall'
STREAMING_INPUT_CALL_METHOD_NAME = _SERVICE_NAME + '/StreamingInputCall'
FULL_DUPLEX_CALL_METHOD_NAME = _SERVICE_NAME + '/FullDuplexCall'
HALF_DUPLEX_CALL_METHOD_NAME = _SERVICE_NAME + '/HalfDuplexCall'
_EMPTY_CALL_METHOD_NAME = 'EmptyCall'
_UNARY_CALL_METHOD_NAME = 'UnaryCall'
_STREAMING_OUTPUT_CALL_METHOD_NAME = 'StreamingOutputCall'
_STREAMING_INPUT_CALL_METHOD_NAME = 'StreamingInputCall'
_FULL_DUPLEX_CALL_METHOD_NAME = 'FullDuplexCall'
_HALF_DUPLEX_CALL_METHOD_NAME = 'HalfDuplexCall'
CLIENT_METHODS = {
EMPTY_CALL_METHOD_NAME: _CLIENT_EMPTY_CALL,
UNARY_CALL_METHOD_NAME: _CLIENT_UNARY_CALL,
STREAMING_OUTPUT_CALL_METHOD_NAME: _CLIENT_STREAMING_OUTPUT_CALL,
STREAMING_INPUT_CALL_METHOD_NAME: _CLIENT_STREAMING_INPUT_CALL,
FULL_DUPLEX_CALL_METHOD_NAME: _CLIENT_FULL_DUPLEX_CALL,
HALF_DUPLEX_CALL_METHOD_NAME: _CLIENT_HALF_DUPLEX_CALL,
_EMPTY_CALL_METHOD_NAME: _CLIENT_EMPTY_CALL,
_UNARY_CALL_METHOD_NAME: _CLIENT_UNARY_CALL,
_STREAMING_OUTPUT_CALL_METHOD_NAME: _CLIENT_STREAMING_OUTPUT_CALL,
_STREAMING_INPUT_CALL_METHOD_NAME: _CLIENT_STREAMING_INPUT_CALL,
_FULL_DUPLEX_CALL_METHOD_NAME: _CLIENT_FULL_DUPLEX_CALL,
_HALF_DUPLEX_CALL_METHOD_NAME: _CLIENT_HALF_DUPLEX_CALL,
}
SERVER_METHODS = {
EMPTY_CALL_METHOD_NAME: _SERVER_EMPTY_CALL,
UNARY_CALL_METHOD_NAME: _SERVER_UNARY_CALL,
STREAMING_OUTPUT_CALL_METHOD_NAME: _SERVER_STREAMING_OUTPUT_CALL,
STREAMING_INPUT_CALL_METHOD_NAME: _SERVER_STREAMING_INPUT_CALL,
FULL_DUPLEX_CALL_METHOD_NAME: _SERVER_FULL_DUPLEX_CALL,
HALF_DUPLEX_CALL_METHOD_NAME: _SERVER_HALF_DUPLEX_CALL,
_EMPTY_CALL_METHOD_NAME: _SERVER_EMPTY_CALL,
_UNARY_CALL_METHOD_NAME: _SERVER_UNARY_CALL,
_STREAMING_OUTPUT_CALL_METHOD_NAME: _SERVER_STREAMING_OUTPUT_CALL,
_STREAMING_INPUT_CALL_METHOD_NAME: _SERVER_STREAMING_INPUT_CALL,
_FULL_DUPLEX_CALL_METHOD_NAME: _SERVER_FULL_DUPLEX_CALL,
_HALF_DUPLEX_CALL_METHOD_NAME: _SERVER_HALF_DUPLEX_CALL,
}

@ -54,10 +54,11 @@ def serve():
private_key = resources.private_key()
certificate_chain = resources.certificate_chain()
server = implementations.secure_server(
methods.SERVER_METHODS, args.port, private_key, certificate_chain)
methods.SERVICE_NAME, methods.SERVER_METHODS, args.port, private_key,
certificate_chain)
else:
server = implementations.insecure_server(
methods.SERVER_METHODS, args.port)
methods.SERVICE_NAME, methods.SERVER_METHODS, args.port)
server.start()
logging.info('Server serving.')

@ -34,7 +34,7 @@ import unittest
from grpc._adapter import fore
from grpc._adapter import rear
from grpc.framework.base import util
from grpc.framework.base.packets import implementations as tickets_implementations
from grpc.framework.base import implementations as base_implementations
from grpc.framework.face import implementations as face_implementations
from grpc.framework.face.testing import coverage
from grpc.framework.face.testing import serial
@ -69,8 +69,8 @@ class FaceTestCase(test_case.FaceTestCase, coverage.BlockingCoverage):
serialization.request_serializers,
serialization.response_deserializers, False, None, None, None)
rear_link.start()
front = tickets_implementations.front(pool, pool, pool)
back = tickets_implementations.back(
front = base_implementations.front_link(pool, pool, pool)
back = base_implementations.back_link(
servicer, pool, pool, pool, _TIMEOUT, _MAXIMUM_TIMEOUT)
fore_link.join_rear_link(back)
back.join_fore_link(fore_link)

@ -37,7 +37,6 @@ from grpc._adapter import _test_links
from grpc._adapter import fore
from grpc._adapter import rear
from grpc.framework.base import interfaces
from grpc.framework.base.packets import packets as tickets
from grpc.framework.foundation import logging_pool
_IDENTITY = lambda x: x
@ -60,9 +59,11 @@ class RoundTripTest(unittest.TestCase):
test_fore_link = _test_links.ForeLink(None, None)
def rear_action(front_to_back_ticket, fore_link):
if front_to_back_ticket.kind in (
tickets.Kind.COMPLETION, tickets.Kind.ENTIRE):
back_to_front_ticket = tickets.BackToFrontPacket(
front_to_back_ticket.operation_id, 0, tickets.Kind.COMPLETION, None)
interfaces.FrontToBackTicket.Kind.COMPLETION,
interfaces.FrontToBackTicket.Kind.ENTIRE):
back_to_front_ticket = interfaces.BackToFrontTicket(
front_to_back_ticket.operation_id, 0,
interfaces.BackToFrontTicket.Kind.COMPLETION, None)
fore_link.accept_back_to_front_ticket(back_to_front_ticket)
test_rear_link = _test_links.RearLink(rear_action, None)
@ -80,21 +81,25 @@ class RoundTripTest(unittest.TestCase):
test_fore_link.join_rear_link(rear_link)
rear_link.start()
front_to_back_ticket = tickets.FrontToBackPacket(
test_operation_id, 0, tickets.Kind.ENTIRE, test_method,
interfaces.ServicedSubscription.Kind.FULL, None, None, _TIMEOUT)
front_to_back_ticket = interfaces.FrontToBackTicket(
test_operation_id, 0, interfaces.FrontToBackTicket.Kind.ENTIRE,
test_method, interfaces.ServicedSubscription.Kind.FULL, None, None,
_TIMEOUT)
rear_link.accept_front_to_back_ticket(front_to_back_ticket)
with test_fore_link.condition:
while (not test_fore_link.tickets or
test_fore_link.tickets[-1].kind is tickets.Kind.CONTINUATION):
test_fore_link.tickets[-1].kind is
interfaces.BackToFrontTicket.Kind.CONTINUATION):
test_fore_link.condition.wait()
rear_link.stop()
fore_link.stop()
with test_fore_link.condition:
self.assertIs(test_fore_link.tickets[-1].kind, tickets.Kind.COMPLETION)
self.assertIs(
test_fore_link.tickets[-1].kind,
interfaces.BackToFrontTicket.Kind.COMPLETION)
def testEntireRoundTrip(self):
test_operation_id = object()
@ -109,11 +114,15 @@ class RoundTripTest(unittest.TestCase):
else:
payload = test_back_to_front_datum
terminal = front_to_back_ticket.kind in (
tickets.Kind.COMPLETION, tickets.Kind.ENTIRE)
interfaces.FrontToBackTicket.Kind.COMPLETION,
interfaces.FrontToBackTicket.Kind.ENTIRE)
if payload is not None or terminal:
back_to_front_ticket = tickets.BackToFrontPacket(
front_to_back_ticket.operation_id, rear_sequence_number[0],
tickets.Kind.COMPLETION if terminal else tickets.Kind.CONTINUATION,
if terminal:
kind = interfaces.BackToFrontTicket.Kind.COMPLETION
else:
kind = interfaces.BackToFrontTicket.Kind.CONTINUATION
back_to_front_ticket = interfaces.BackToFrontTicket(
front_to_back_ticket.operation_id, rear_sequence_number[0], kind,
payload)
rear_sequence_number[0] += 1
fore_link.accept_back_to_front_ticket(back_to_front_ticket)
@ -134,15 +143,16 @@ class RoundTripTest(unittest.TestCase):
test_fore_link.join_rear_link(rear_link)
rear_link.start()
front_to_back_ticket = tickets.FrontToBackPacket(
test_operation_id, 0, tickets.Kind.ENTIRE, test_method,
interfaces.ServicedSubscription.Kind.FULL, None,
front_to_back_ticket = interfaces.FrontToBackTicket(
test_operation_id, 0, interfaces.FrontToBackTicket.Kind.ENTIRE,
test_method, interfaces.ServicedSubscription.Kind.FULL, None,
test_front_to_back_datum, _TIMEOUT)
rear_link.accept_front_to_back_ticket(front_to_back_ticket)
with test_fore_link.condition:
while (not test_fore_link.tickets or
test_fore_link.tickets[-1].kind is not tickets.Kind.COMPLETION):
test_fore_link.tickets[-1].kind is not
interfaces.BackToFrontTicket.Kind.COMPLETION):
test_fore_link.condition.wait()
rear_link.stop()
@ -172,11 +182,15 @@ class RoundTripTest(unittest.TestCase):
else:
response = None
terminal = front_to_back_ticket.kind in (
tickets.Kind.COMPLETION, tickets.Kind.ENTIRE)
interfaces.FrontToBackTicket.Kind.COMPLETION,
interfaces.FrontToBackTicket.Kind.ENTIRE)
if response is not None or terminal:
back_to_front_ticket = tickets.BackToFrontPacket(
front_to_back_ticket.operation_id, rear_sequence_number[0],
tickets.Kind.COMPLETION if terminal else tickets.Kind.CONTINUATION,
if terminal:
kind = interfaces.BackToFrontTicket.Kind.COMPLETION
else:
kind = interfaces.BackToFrontTicket.Kind.CONTINUATION
back_to_front_ticket = interfaces.BackToFrontTicket(
front_to_back_ticket.operation_id, rear_sequence_number[0], kind,
response)
rear_sequence_number[0] += 1
fore_link.accept_back_to_front_ticket(back_to_front_ticket)
@ -198,26 +212,31 @@ class RoundTripTest(unittest.TestCase):
test_fore_link.join_rear_link(rear_link)
rear_link.start()
commencement_ticket = tickets.FrontToBackPacket(
test_operation_id, 0, tickets.Kind.COMMENCEMENT, test_method,
interfaces.ServicedSubscription.Kind.FULL, None, None, _TIMEOUT)
commencement_ticket = interfaces.FrontToBackTicket(
test_operation_id, 0,
interfaces.FrontToBackTicket.Kind.COMMENCEMENT, test_method,
interfaces.ServicedSubscription.Kind.FULL, None, None,
_TIMEOUT)
fore_sequence_number = 1
rear_link.accept_front_to_back_ticket(commencement_ticket)
for request in scenario.requests():
continuation_ticket = tickets.FrontToBackPacket(
test_operation_id, fore_sequence_number, tickets.Kind.CONTINUATION,
None, None, None, request, None)
continuation_ticket = interfaces.FrontToBackTicket(
test_operation_id, fore_sequence_number,
interfaces.FrontToBackTicket.Kind.CONTINUATION, None, None, None,
request, None)
fore_sequence_number += 1
rear_link.accept_front_to_back_ticket(continuation_ticket)
completion_ticket = tickets.FrontToBackPacket(
test_operation_id, fore_sequence_number, tickets.Kind.COMPLETION, None,
None, None, None, None)
completion_ticket = interfaces.FrontToBackTicket(
test_operation_id, fore_sequence_number,
interfaces.FrontToBackTicket.Kind.COMPLETION, None, None, None, None,
None)
fore_sequence_number += 1
rear_link.accept_front_to_back_ticket(completion_ticket)
with test_fore_link.condition:
while (not test_fore_link.tickets or
test_fore_link.tickets[-1].kind is not tickets.Kind.COMPLETION):
test_fore_link.tickets[-1].kind is not
interfaces.BackToFrontTicket.Kind.COMPLETION):
test_fore_link.condition.wait()
rear_link.stop()

@ -34,7 +34,6 @@ import unittest
from grpc._adapter import _test_links
from grpc._adapter import rear
from grpc.framework.base import interfaces
from grpc.framework.base.packets import packets
from grpc.framework.foundation import logging_pool
_IDENTITY = lambda x: x
@ -68,7 +67,7 @@ class LonelyRearLinkTest(unittest.TestCase):
rear_link.join_fore_link(fore_link)
rear_link.start()
front_to_back_ticket = packets.FrontToBackPacket(
front_to_back_ticket = interfaces.FrontToBackTicket(
test_operation_id, 0, front_to_back_ticket_kind, test_method,
interfaces.ServicedSubscription.Kind.FULL, None, None, _TIMEOUT)
rear_link.accept_front_to_back_ticket(front_to_back_ticket)
@ -76,22 +75,25 @@ class LonelyRearLinkTest(unittest.TestCase):
with fore_link.condition:
while True:
if (fore_link.tickets and
fore_link.tickets[-1].kind is not packets.Kind.CONTINUATION):
fore_link.tickets[-1].kind is not
interfaces.BackToFrontTicket.Kind.CONTINUATION):
break
fore_link.condition.wait()
rear_link.stop()
with fore_link.condition:
self.assertIsNot(fore_link.tickets[-1].kind, packets.Kind.COMPLETION)
self.assertIsNot(
fore_link.tickets[-1].kind,
interfaces.BackToFrontTicket.Kind.COMPLETION)
@unittest.skip('TODO(nathaniel): This seems to have broken in the last few weeks; fix it.')
def testLonelyClientCommencementPacket(self):
def testLonelyClientCommencementTicket(self):
self._perform_lonely_client_test_with_ticket_kind(
packets.Kind.COMMENCEMENT)
interfaces.FrontToBackTicket.Kind.COMMENCEMENT)
def testLonelyClientEntirePacket(self):
self._perform_lonely_client_test_with_ticket_kind(packets.Kind.ENTIRE)
def testLonelyClientEntireTicket(self):
self._perform_lonely_client_test_with_ticket_kind(
interfaces.FrontToBackTicket.Kind.ENTIRE)
if __name__ == '__main__':

@ -31,7 +31,7 @@
import threading
from grpc.framework.base.packets import interfaces
from grpc.framework.base import interfaces
class ForeLink(interfaces.ForeLink):

@ -36,10 +36,8 @@ import time
from grpc._adapter import _common
from grpc._adapter import _low
from grpc.framework.base import interfaces
from grpc.framework.base.packets import interfaces as ticket_interfaces
from grpc.framework.base.packets import null
from grpc.framework.base.packets import packets as tickets
from grpc.framework.base import interfaces as base_interfaces
from grpc.framework.base import null
from grpc.framework.foundation import activated
from grpc.framework.foundation import logging_pool
@ -69,7 +67,7 @@ def _status(call, rpc_state):
rpc_state.write.low = _LowWrite.CLOSED
class ForeLink(ticket_interfaces.ForeLink, activated.Activated):
class ForeLink(base_interfaces.ForeLink, activated.Activated):
"""A service-side bridge between RPC Framework and the C-ish _low code."""
def __init__(
@ -127,9 +125,9 @@ class ForeLink(ticket_interfaces.ForeLink, activated.Activated):
self._request_deserializers[method],
self._response_serializers[method])
ticket = tickets.FrontToBackPacket(
call, 0, tickets.Kind.COMMENCEMENT, method,
interfaces.ServicedSubscription.Kind.FULL, None, None,
ticket = base_interfaces.FrontToBackTicket(
call, 0, base_interfaces.FrontToBackTicket.Kind.COMMENCEMENT, method,
base_interfaces.ServicedSubscription.Kind.FULL, None, None,
service_acceptance.deadline - time.time())
self._rear_link.accept_front_to_back_ticket(ticket)
@ -145,14 +143,16 @@ class ForeLink(ticket_interfaces.ForeLink, activated.Activated):
sequence_number = rpc_state.sequence_number
rpc_state.sequence_number += 1
if event.bytes is None:
ticket = tickets.FrontToBackPacket(
call, sequence_number, tickets.Kind.COMPLETION, None, None, None,
ticket = base_interfaces.FrontToBackTicket(
call, sequence_number,
base_interfaces.FrontToBackTicket.Kind.COMPLETION, None, None, None,
None, None)
else:
call.read(call)
ticket = tickets.FrontToBackPacket(
call, sequence_number, tickets.Kind.CONTINUATION, None, None, None,
rpc_state.deserializer(event.bytes), None)
ticket = base_interfaces.FrontToBackTicket(
call, sequence_number,
base_interfaces.FrontToBackTicket.Kind.CONTINUATION, None, None,
None, rpc_state.deserializer(event.bytes), None)
self._rear_link.accept_front_to_back_ticket(ticket)
@ -180,9 +180,10 @@ class ForeLink(ticket_interfaces.ForeLink, activated.Activated):
sequence_number = rpc_state.sequence_number
rpc_state.sequence_number += 1
ticket = tickets.FrontToBackPacket(
call, sequence_number, tickets.Kind.TRANSMISSION_FAILURE, None, None,
None, None, None)
ticket = base_interfaces.FrontToBackTicket(
call, sequence_number,
base_interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE, None,
None, None, None, None)
self._rear_link.accept_front_to_back_ticket(ticket)
def _on_finish_event(self, event):
@ -199,18 +200,21 @@ class ForeLink(ticket_interfaces.ForeLink, activated.Activated):
sequence_number = rpc_state.sequence_number
rpc_state.sequence_number += 1
if code is _low.Code.CANCELLED:
ticket = tickets.FrontToBackPacket(
call, sequence_number, tickets.Kind.CANCELLATION, None, None, None,
None, None)
ticket = base_interfaces.FrontToBackTicket(
call, sequence_number,
base_interfaces.FrontToBackTicket.Kind.CANCELLATION, None, None,
None, None, None)
elif code is _low.Code.EXPIRED:
ticket = tickets.FrontToBackPacket(
call, sequence_number, tickets.Kind.EXPIRATION, None, None, None,
ticket = base_interfaces.FrontToBackTicket(
call, sequence_number,
base_interfaces.FrontToBackTicket.Kind.EXPIRATION, None, None, None,
None, None)
else:
# TODO(nathaniel): Better mapping of codes to ticket-categories
ticket = tickets.FrontToBackPacket(
call, sequence_number, tickets.Kind.TRANSMISSION_FAILURE, None, None,
None, None, None)
ticket = base_interfaces.FrontToBackTicket(
call, sequence_number,
base_interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE, None,
None, None, None, None)
self._rear_link.accept_front_to_back_ticket(ticket)
def _spin(self, completion_queue, server):
@ -266,7 +270,7 @@ class ForeLink(ticket_interfaces.ForeLink, activated.Activated):
self._rpc_states.pop(call, None)
def join_rear_link(self, rear_link):
"""See ticket_interfaces.ForeLink.join_rear_link for specification."""
"""See base_interfaces.ForeLink.join_rear_link for specification."""
self._rear_link = null.NULL_REAR_LINK if rear_link is None else rear_link
def _start(self):
@ -346,14 +350,14 @@ class ForeLink(ticket_interfaces.ForeLink, activated.Activated):
return self._port
def accept_back_to_front_ticket(self, ticket):
"""See ticket_interfaces.ForeLink.accept_back_to_front_ticket for spec."""
"""See base_interfaces.ForeLink.accept_back_to_front_ticket for spec."""
with self._condition:
if self._server is None:
return
if ticket.kind is tickets.Kind.CONTINUATION:
if ticket.kind is base_interfaces.BackToFrontTicket.Kind.CONTINUATION:
self._continue(ticket.operation_id, ticket.payload)
elif ticket.kind is tickets.Kind.COMPLETION:
elif ticket.kind is base_interfaces.BackToFrontTicket.Kind.COMPLETION:
self._complete(ticket.operation_id, ticket.payload)
else:
self._cancel(ticket.operation_id)

@ -36,9 +36,8 @@ import time
from grpc._adapter import _common
from grpc._adapter import _low
from grpc.framework.base.packets import interfaces as ticket_interfaces
from grpc.framework.base.packets import null
from grpc.framework.base.packets import packets as tickets
from grpc.framework.base import interfaces as base_interfaces
from grpc.framework.base import null
from grpc.framework.foundation import activated
from grpc.framework.foundation import logging_pool
@ -88,7 +87,7 @@ def _write(operation_id, call, outstanding, write_state, serialized_payload):
raise ValueError('Write attempted after writes completed!')
class RearLink(ticket_interfaces.RearLink, activated.Activated):
class RearLink(base_interfaces.RearLink, activated.Activated):
"""An invocation-side bridge between RPC Framework and the C-ish _low code."""
def __init__(
@ -152,9 +151,9 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated):
else:
logging.error('RPC write not accepted! Event: %s', (event,))
rpc_state.active = False
ticket = tickets.BackToFrontPacket(
ticket = base_interfaces.BackToFrontTicket(
operation_id, rpc_state.common.sequence_number,
tickets.Kind.TRANSMISSION_FAILURE, None)
base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE, None)
rpc_state.common.sequence_number += 1
self._fore_link.accept_back_to_front_ticket(ticket)
@ -163,9 +162,10 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated):
rpc_state.call.read(operation_id)
rpc_state.outstanding.add(_low.Event.Kind.READ_ACCEPTED)
ticket = tickets.BackToFrontPacket(
ticket = base_interfaces.BackToFrontTicket(
operation_id, rpc_state.common.sequence_number,
tickets.Kind.CONTINUATION, rpc_state.common.deserializer(event.bytes))
base_interfaces.BackToFrontTicket.Kind.CONTINUATION,
rpc_state.common.deserializer(event.bytes))
rpc_state.common.sequence_number += 1
self._fore_link.accept_back_to_front_ticket(ticket)
@ -173,9 +173,9 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated):
if not event.complete_accepted:
logging.error('RPC complete not accepted! Event: %s', (event,))
rpc_state.active = False
ticket = tickets.BackToFrontPacket(
ticket = base_interfaces.BackToFrontTicket(
operation_id, rpc_state.common.sequence_number,
tickets.Kind.TRANSMISSION_FAILURE, None)
base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE, None)
rpc_state.common.sequence_number += 1
self._fore_link.accept_back_to_front_ticket(ticket)
@ -188,17 +188,15 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated):
"""Handle termination of an RPC."""
# TODO(nathaniel): Cover all statuses.
if event.status.code is _low.Code.OK:
category = tickets.Kind.COMPLETION
kind = base_interfaces.BackToFrontTicket.Kind.COMPLETION
elif event.status.code is _low.Code.CANCELLED:
# TODO(issue 752): Use a CANCELLATION ticket kind here.
category = tickets.Kind.SERVICER_FAILURE
kind = base_interfaces.BackToFrontTicket.Kind.CANCELLATION
elif event.status.code is _low.Code.EXPIRED:
category = tickets.Kind.EXPIRATION
kind = base_interfaces.BackToFrontTicket.Kind.EXPIRATION
else:
category = tickets.Kind.TRANSMISSION_FAILURE
ticket = tickets.BackToFrontPacket(
operation_id, rpc_state.common.sequence_number, category,
None)
kind = base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE
ticket = base_interfaces.BackToFrontTicket(
operation_id, rpc_state.common.sequence_number, kind, None)
rpc_state.common.sequence_number += 1
self._fore_link.accept_back_to_front_ticket(ticket)
@ -318,7 +316,7 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated):
rpc_state.active = False
def join_fore_link(self, fore_link):
"""See ticket_interfaces.RearLink.join_fore_link for specification."""
"""See base_interfaces.RearLink.join_fore_link for specification."""
with self._condition:
self._fore_link = null.NULL_FORE_LINK if fore_link is None else fore_link
@ -367,22 +365,22 @@ class RearLink(ticket_interfaces.RearLink, activated.Activated):
self._stop()
def accept_front_to_back_ticket(self, ticket):
"""See ticket_interfaces.RearLink.accept_front_to_back_ticket for spec."""
"""See base_interfaces.RearLink.accept_front_to_back_ticket for spec."""
with self._condition:
if self._completion_queue is None:
return
if ticket.kind is tickets.Kind.COMMENCEMENT:
if ticket.kind is base_interfaces.FrontToBackTicket.Kind.COMMENCEMENT:
self._commence(
ticket.operation_id, ticket.name, ticket.payload, ticket.timeout)
elif ticket.kind is tickets.Kind.CONTINUATION:
elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.CONTINUATION:
self._continue(ticket.operation_id, ticket.payload)
elif ticket.kind is tickets.Kind.COMPLETION:
elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.COMPLETION:
self._complete(ticket.operation_id, ticket.payload)
elif ticket.kind is tickets.Kind.ENTIRE:
elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.ENTIRE:
self._entire(
ticket.operation_id, ticket.name, ticket.payload, ticket.timeout)
elif ticket.kind is tickets.Kind.CANCELLATION:
elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.CANCELLATION:
self._cancel(ticket.operation_id)
else:
# NOTE(nathaniel): All other categories are treated as cancellation.

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

Loading…
Cancel
Save