Merge branch 'master' of https://github.com/grpc/grpc into update_ssl_cert

pull/4096/head
Julien Boeuf 9 years ago
commit 802f6b6724
  1. 7
      binding.gyp
  2. 16
      build.yaml
  3. 6
      doc/PROTOCOL-HTTP2.md
  4. 2
      doc/interop-test-descriptions.md
  5. 2
      examples/node/README.md
  6. 2
      examples/python/helloworld/greeter_server.py
  7. 11
      include/grpc++/client_context.h
  8. 3
      include/grpc++/support/channel_arguments.h
  9. 1
      include/grpc++/support/time.h
  10. 8
      src/cpp/client/client_context.cc
  11. 2
      src/node/ext/channel.cc
  12. 3
      src/objective-c/examples/Sample/Podfile
  13. 12
      src/objective-c/examples/Sample/Sample/ViewController.m
  14. 31
      src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.podspec
  15. 120
      src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto
  16. 3
      src/objective-c/tests/Podfile
  17. 0
      src/objective-c/tests/RemoteTestClient/RemoteTest.podspec
  18. 0
      src/objective-c/tests/RemoteTestClient/empty.proto
  19. 0
      src/objective-c/tests/RemoteTestClient/messages.proto
  20. 0
      src/objective-c/tests/RemoteTestClient/test.proto
  21. 8
      src/php/lib/Grpc/BaseStub.php
  22. 4
      src/python/grpcio/grpc/framework/interfaces/face/face.py
  23. 15
      src/ruby/ext/grpc/rb_call.c
  24. 2
      src/ruby/ext/grpc/rb_channel.c
  25. 2
      src/ruby/ext/grpc/rb_channel_args.c
  26. 4
      src/ruby/ext/grpc/rb_completion_queue.c
  27. 5
      src/ruby/ext/grpc/rb_credentials.c
  28. 20
      src/ruby/ext/grpc/rb_grpc.c
  29. 5
      src/ruby/ext/grpc/rb_server.c
  30. 2
      src/ruby/ext/grpc/rb_server_credentials.c
  31. 10
      src/ruby/lib/grpc/generic/active_call.rb
  32. 20
      src/ruby/lib/grpc/generic/bidi_call.rb
  33. 19
      src/ruby/lib/grpc/generic/rpc_server.rb
  34. 17
      src/ruby/pb/test/client.rb
  35. 57
      src/ruby/pb/test/server.rb
  36. 1
      src/ruby/spec/pb/health/checker_spec.rb
  37. 25
      templates/binding.gyp.template
  38. 12
      test/cpp/end2end/end2end_test.cc
  39. 6
      test/cpp/interop/stress_test.cc
  40. 63
      tools/buildgen/plugins/transitive_dependencies.py

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

@ -2232,3 +2232,19 @@ vspackages:
props: false
redist: false
version: 1.7.0.1
node_modules:
- deps:
- grpc
- gpr
name: grpc_node
src:
- src/node/ext/byte_buffer.cc
- src/node/ext/call.cc
- src/node/ext/call_credentials.cc
- src/node/ext/channel.cc
- src/node/ext/channel_credentials.cc
- src/node/ext/completion_queue_async_worker.cc
- src/node/ext/node_grpc.cc
- src/node/ext/server.cc
- src/node/ext/server_credentials.cc
- src/node/ext/timeval.cc

@ -66,9 +66,9 @@ Base64-encoded values.
**ASCII-Value** should not have leading or trailing whitespace. If it contains
leading or trailing whitespace, it may be stripped. The **ASCII-Value**
character range defined is more strict than HTTP. Implementations must not error
due to receiving an invalid **ASCII-Value** but value valid in HTTP, but the
precise behavior is not strictly defined: they may throw the value away or
accept the value. If accepted, care must be taken to make sure that the
due to receiving an invalid **ASCII-Value** that's a valid **field-value** in
HTTP, but the precise behavior is not strictly defined: they may throw the value
away or accept the value. If accepted, care must be taken to make sure that the
application is permitted to echo the value back as metadata. For example, if the
metadata is provided to the application as a list in a request, the application
should not trigger an error by providing that same list as the metadata in the

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

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

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

@ -53,15 +53,16 @@
#include <memory>
#include <string>
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc++/impl/sync.h>
#include <grpc++/security/auth_context.h>
#include <grpc++/support/config.h>
#include <grpc++/support/status.h>
#include <grpc++/support/string_ref.h>
#include <grpc++/support/time.h>
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
struct census_context;
@ -315,7 +316,9 @@ class ClientContext {
bool initial_metadata_received_;
std::shared_ptr<Channel> channel_;
grpc::mutex mu_;
grpc_call* call_;
bool call_canceled_;
gpr_timespec deadline_;
grpc::string authority_;
std::shared_ptr<Credentials> creds_;

@ -70,7 +70,8 @@ class ChannelArguments {
void SetChannelArgs(grpc_channel_args* channel_args) const;
// gRPC specific channel argument setters
/// Set target name override for SSL host name checking.
/// Set target name override for SSL host name checking. This option is for
/// testing only and should never be used in production.
void SetSslTargetNameOverride(const grpc::string& name);
// TODO(yangg) add flow control options
/// Set the compression algorithm for the channel.

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

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

@ -82,7 +82,7 @@ bool ParseChannelArgs(Local<Value> args_val,
return false;
}
grpc_channel_args *channel_args = reinterpret_cast<grpc_channel_args*>(
malloc(sizeof(channel_args)));
malloc(sizeof(grpc_channel_args)));
*channel_args_ptr = channel_args;
Local<Object> args_hash = Nan::To<Object>(args_val).ToLocalChecked();
Local<Array> keys = Nan::GetOwnPropertyNames(args_hash).ToLocalChecked();

@ -1,8 +1,9 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'Protobuf', :path => "../../../../third_party/protobuf"
pod 'gRPC', :path => "../../../.."
pod 'RemoteTest', :path => "../../generated_libraries/RemoteTestClient"
pod 'RemoteTest', :path => "../RemoteTestClient"
target 'Sample' do
end

@ -34,7 +34,7 @@
#import "ViewController.h"
#import <GRPCClient/GRPCCall.h>
#import <GRPCClient/GRPCMethodName.h>
#import <ProtoRPC/ProtoMethod.h>
#import <RemoteTest/Messages.pbobjc.h>
#import <RemoteTest/Test.pbrpc.h>
#import <RxLibrary/GRXWriter+Immediate.h>
@ -66,14 +66,14 @@
// Same example call using the generic gRPC client library:
GRPCMethodName *method = [[GRPCMethodName alloc] initWithPackage:@"grpc.testing"
interface:@"TestService"
method:@"UnaryCall"];
ProtoMethod *method = [[ProtoMethod alloc] initWithPackage:@"grpc.testing"
service:@"TestService"
method:@"UnaryCall"];
id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[request data]];
GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kRemoteHost
method:method
path:method.HTTPPath
requestsWriter:requestsWriter];
id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {

@ -1,31 +0,0 @@
Pod::Spec.new do |s|
s.name = "RouteGuide"
s.version = "0.0.1"
s.license = "New BSD"
s.ios.deployment_target = "6.0"
s.osx.deployment_target = "10.8"
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.prepare_command = <<-CMD
BINDIR=../../../../bins/$CONFIG
PROTOC=$BINDIR/protobuf/protoc
PLUGIN=$BINDIR/grpc_objective_c_plugin
$PROTOC --plugin=protoc-gen-grpc=$PLUGIN --objc_out=. --grpc_out=. *.proto
CMD
s.subspec "Messages" do |ms|
ms.source_files = "*.pbobjc.{h,m}"
ms.header_mappings_dir = "."
ms.requires_arc = false
ms.dependency "Protobuf", "~> 3.0.0-alpha-3"
end
s.subspec "Services" do |ss|
ss.source_files = "*.pbrpc.{h,m}"
ss.header_mappings_dir = "."
ss.requires_arc = true
ss.dependency "gRPC", "~> 0.5"
ss.dependency "#{s.name}/Messages"
end
end

@ -1,120 +0,0 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package routeguide;
option objc_class_prefix = "RGD";
// Interface exported by the server.
service RouteGuide {
// A simple RPC.
//
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
Point lo = 1;
// The other corner of the rectangle.
Point hi = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
string name = 1;
// The point where the feature is detected.
Point location = 2;
}
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
Point location = 1;
// The message to be sent.
string message = 2;
}
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
int32 point_count = 1;
// The number of known features passed while traversing the route.
int32 feature_count = 2;
// The distance covered in metres.
int32 distance = 3;
// The duration of the traversal in seconds.
int32 elapsed_time = 4;
}

@ -3,8 +3,7 @@ platform :ios, '8.0'
pod 'Protobuf', :path => "../../../third_party/protobuf"
pod 'gRPC', :path => "../../.."
pod 'RemoteTest', :path => "../generated_libraries/RemoteTestClient"
pod 'RouteGuide', :path => "../generated_libraries/RouteGuideClient"
pod 'RemoteTest', :path => "RemoteTestClient"
link_with 'AllTests',
'RxLibraryUnitTests',

@ -51,6 +51,7 @@ class BaseStub
* @param $opts array
* - 'update_metadata': (optional) a callback function which takes in a
* metadata array, and returns an updated metadata array
* - 'grpc.primary_user_agent': (optional) a user-agent string
*/
public function __construct($hostname, $opts)
{
@ -64,7 +65,12 @@ class BaseStub
}
$package_config = json_decode(
file_get_contents(dirname(__FILE__).'/../../composer.json'), true);
$opts['grpc.primary_user_agent'] =
if (!empty($opts['grpc.primary_user_agent'])) {
$opts['grpc.primary_user_agent'] .= ' ';
} else {
$opts['grpc.primary_user_agent'] = '';
}
$opts['grpc.primary_user_agent'] .=
'grpc-php/'.$package_config['version'];
$this->channel = new Channel($hostname, $opts);
}

@ -117,6 +117,10 @@ class AbortionError(Exception):
self.code = code
self.details = details
def __str__(self):
return '%s(code=%s, details="%s")' % (
self.__class__.__name__, self.code, self.details)
class CancellationError(AbortionError):
"""Indicates that an RPC has been cancelled."""

@ -139,7 +139,15 @@ static const rb_data_type_t grpc_rb_md_ary_data_type = {
{NULL, NULL}},
NULL,
NULL,
0};
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
/* it is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because
* grpc_rb_call_destroy
* touches a hash object.
* TODO(yugui) Directly use st_table and call the free function earlier?
*/
0,
#endif
};
/* Describes grpc_call struct for RTypedData */
static const rb_data_type_t grpc_call_data_type = {
@ -148,12 +156,15 @@ static const rb_data_type_t grpc_call_data_type = {
{NULL, NULL}},
NULL,
NULL,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
/* it is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because
* grpc_rb_call_destroy
* touches a hash object.
* TODO(yugui) Directly use st_table and call the free function earlier?
*/
0};
0,
#endif
};
/* Error code details is a hash containing text strings describing errors */
VALUE rb_error_code_details;

@ -111,7 +111,9 @@ static rb_data_type_t grpc_channel_data_type = {
{grpc_rb_channel_mark, grpc_rb_channel_free, GRPC_RB_MEMSIZE_UNAVAILABLE,
{NULL, NULL}},
NULL, NULL,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
RUBY_TYPED_FREE_IMMEDIATELY
#endif
};
/* Allocates grpc_rb_channel instances. */

@ -44,7 +44,9 @@ static rb_data_type_t grpc_rb_channel_args_data_type = {
{GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, GRPC_RB_MEMSIZE_UNAVAILABLE,
{NULL, NULL}},
NULL, NULL,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
RUBY_TYPED_FREE_IMMEDIATELY
#endif
};
/* A callback the processes the hash key values in channel_args hash */

@ -121,9 +121,11 @@ static rb_data_type_t grpc_rb_completion_queue_data_type = {
{GRPC_RB_GC_NOT_MARKED, grpc_rb_completion_queue_destroy,
GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
NULL, NULL,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
/* cannot immediately free because grpc_rb_completion_queue_shutdown_drain
* calls rb_thread_call_without_gvl. */
0
0,
#endif
};
/* Allocates a completion queue. */

@ -92,7 +92,10 @@ static rb_data_type_t grpc_rb_credentials_data_type = {
GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
NULL,
NULL,
RUBY_TYPED_FREE_IMMEDIATELY};
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
RUBY_TYPED_FREE_IMMEDIATELY
#endif
};
/* Allocates Credential instances.
Provides safe initial defaults for the instance fields. */

@ -55,7 +55,10 @@ static rb_data_type_t grpc_rb_timespec_data_type = {
{NULL, NULL}},
NULL,
NULL,
RUBY_TYPED_FREE_IMMEDIATELY};
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
RUBY_TYPED_FREE_IMMEDIATELY
#endif
};
/* Alloc func that blocks allocation of a given object by raising an
* exception. */
@ -262,10 +265,20 @@ static void Init_grpc_time_consts() {
id_tv_nsec = rb_intern("tv_nsec");
}
/*
TODO: find an alternative to ruby_vm_at_exit that is ok in Ruby 2.0 where
RUBY_TYPED_FREE_IMMEDIATELY is not defined.
At the moment, registering a function using ruby_vm_at_exit segfaults in Ruby
2.0. This is not an issue with the gRPC handler. More likely, this was an
in issue with 2.0 that got resolved in 2.1 and has not been backported.
*/
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
static void grpc_rb_shutdown(ruby_vm_t *vm) {
(void)vm;
grpc_shutdown();
}
#endif
/* Initialize the GRPC module structs */
@ -285,7 +298,12 @@ VALUE sym_metadata = Qundef;
void Init_grpc() {
grpc_init();
/* TODO: find alternative to ruby_vm_at_exit that is ok in Ruby 2.0 */
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
ruby_vm_at_exit(grpc_rb_shutdown);
#endif
grpc_rb_mGRPC = rb_define_module("GRPC");
grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");
grpc_rb_sNewServerRpc =

@ -101,11 +101,14 @@ static const rb_data_type_t grpc_rb_server_data_type = {
{NULL, NULL}},
NULL,
NULL,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
/* It is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because the free function would block
* and we might want to unlock GVL
* TODO(yugui) Unlock GVL?
*/
0};
0,
#endif
};
/* Allocates grpc_rb_server instances. */
static VALUE grpc_rb_server_alloc(VALUE cls) {

@ -91,7 +91,9 @@ static const rb_data_type_t grpc_rb_server_credentials_data_type = {
{grpc_rb_server_credentials_mark, grpc_rb_server_credentials_free,
GRPC_RB_MEMSIZE_UNAVAILABLE, {NULL, NULL}},
NULL, NULL,
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
RUBY_TYPED_FREE_IMMEDIATELY
#endif
};
/* Allocates ServerCredential instances.

@ -199,11 +199,7 @@ module GRPC
# marshalled.
def remote_send(req, marshalled = false)
GRPC.logger.debug("sending #{req}, marshalled? #{marshalled}")
if marshalled
payload = req
else
payload = @marshal.call(req)
end
payload = marshalled ? req : @marshal.call(req)
@call.run_batch(@cq, self, INFINITE_FUTURE, SEND_MESSAGE => payload)
end
@ -417,7 +413,9 @@ module GRPC
# @return [Enumerator, nil] a response Enumerator
def bidi_streamer(requests, **kw, &blk)
start_call(**kw) unless @started
bd = BidiCall.new(@call, @cq, @marshal, @unmarshal)
bd = BidiCall.new(@call, @cq, @marshal, @unmarshal,
metadata_tag: @metadata_tag)
@metadata_tag = nil # run_on_client ensures metadata is read
bd.run_on_client(requests, @op_notifier, &blk)
end

@ -56,7 +56,8 @@ module GRPC
# the call
# @param marshal [Function] f(obj)->string that marshal requests
# @param unmarshal [Function] f(string)->obj that unmarshals responses
def initialize(call, q, marshal, unmarshal)
# @param metadata_tag [Object] tag object used to collect metadata
def initialize(call, q, marshal, unmarshal, metadata_tag: nil)
fail(ArgumentError, 'not a call') unless call.is_a? Core::Call
unless q.is_a? Core::CompletionQueue
fail(ArgumentError, 'not a CompletionQueue')
@ -67,6 +68,7 @@ module GRPC
@op_notifier = nil # signals completion on clients
@readq = Queue.new
@unmarshal = unmarshal
@metadata_tag = metadata_tag
end
# Begins orchestration of the Bidi stream for a client sending requests.
@ -113,6 +115,18 @@ module GRPC
@op_notifier.notify(self)
end
# performs a read using @call.run_batch, ensures metadata is set up
def read_using_run_batch
ops = { RECV_MESSAGE => nil }
ops[RECV_INITIAL_METADATA] = nil unless @metadata_tag.nil?
batch_result = @call.run_batch(@cq, self, INFINITE_FUTURE, ops)
unless @metadata_tag.nil?
@call.metadata = batch_result.metadata
@metadata_tag = nil
end
batch_result
end
# each_queued_msg yields each message on this instances readq
#
# - messages are added to the readq by #read_loop
@ -169,9 +183,7 @@ module GRPC
loop do
GRPC.logger.debug("bidi-read-loop: #{count}")
count += 1
# TODO: ensure metadata is read if available, currently it's not
batch_result = @call.run_batch(@cq, read_tag, INFINITE_FUTURE,
RECV_MESSAGE => nil)
batch_result = read_using_run_batch
# handle the next message
if batch_result.message.nil?

@ -418,11 +418,11 @@ module GRPC
an_rpc = @server.request_call(@cq, loop_tag, INFINITE_FUTURE)
break if (!an_rpc.nil?) && an_rpc.call.nil?
c = new_active_server_call(an_rpc)
unless c.nil?
mth = an_rpc.method.to_sym
@pool.schedule(c) do |call|
rpc_descs[mth].run_server_method(call, rpc_handlers[mth])
active_call = new_active_server_call(an_rpc)
unless active_call.nil?
@pool.schedule(active_call) do |ac|
c, mth = ac
rpc_descs[mth].run_server_method(c, rpc_handlers[mth])
end
end
rescue Core::CallError, RuntimeError => e
@ -442,6 +442,7 @@ module GRPC
# allow the metadata to be accessed from the call
handle_call_tag = Object.new
an_rpc.call.metadata = an_rpc.metadata # attaches md to call for handlers
GRPC.logger.debug("call md is #{an_rpc.metadata}")
connect_md = nil
unless @connect_md_proc.nil?
connect_md = @connect_md_proc.call(an_rpc.method, an_rpc.metadata)
@ -454,9 +455,11 @@ module GRPC
# Create the ActiveCall
GRPC.logger.info("deadline is #{an_rpc.deadline}; (now=#{Time.now})")
rpc_desc = rpc_descs[an_rpc.method.to_sym]
ActiveCall.new(an_rpc.call, @cq,
rpc_desc.marshal_proc, rpc_desc.unmarshal_proc(:input),
an_rpc.deadline)
c = ActiveCall.new(an_rpc.call, @cq,
rpc_desc.marshal_proc, rpc_desc.unmarshal_proc(:input),
an_rpc.deadline)
mth = an_rpc.method.to_sym
[c, mth]
end
protected

@ -46,6 +46,7 @@ $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'optparse'
require 'logger'
require 'grpc'
require 'googleauth'
@ -59,6 +60,22 @@ require 'signet/ssl_config'
AUTH_ENV = Google::Auth::CredentialsLoader::ENV_VAR
# RubyLogger defines a logger for gRPC based on the standard ruby logger.
module RubyLogger
def logger
LOGGER
end
LOGGER = Logger.new(STDOUT)
LOGGER.level = Logger::INFO
end
# GRPC is the general RPC module
module GRPC
# Inject the noop #logger if no module-level logger method has been injected.
extend RubyLogger
end
# AssertionError is use to indicate interop test failures.
class AssertionError < RuntimeError; end

@ -45,6 +45,7 @@ $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'forwardable'
require 'logger'
require 'optparse'
require 'grpc'
@ -53,6 +54,60 @@ require 'test/proto/empty'
require 'test/proto/messages'
require 'test/proto/test_services'
# DebugIsTruncated extends the default Logger to truncate debug messages
class DebugIsTruncated < Logger
def debug(s)
super(truncate(s, 1024))
end
# Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
#
# 'Once upon a time in a world far far away'.truncate(27)
# # => "Once upon a time in a wo..."
#
# Pass a string or regexp <tt>:separator</tt> to truncate +text+ at a natural break:
#
# 'Once upon a time in a world far far away'.truncate(27, separator: ' ')
# # => "Once upon a time in a..."
#
# 'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
# # => "Once upon a time in a..."
#
# The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
# for a total length not exceeding <tt>length</tt>:
#
# 'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
# # => "And they f... (continued)"
def truncate(s, truncate_at, options = {})
return s unless s.length > truncate_at
omission = options[:omission] || '...'
with_extra_room = truncate_at - omission.length
stop = \
if options[:separator]
rindex(options[:separator], with_extra_room) || with_extra_room
else
with_extra_room
end
"#{s[0, stop]}#{omission}"
end
end
# RubyLogger defines a logger for gRPC based on the standard ruby logger.
module RubyLogger
def logger
LOGGER
end
LOGGER = DebugIsTruncated.new(STDOUT)
LOGGER.level = Logger::WARN
end
# GRPC is the general RPC module
module GRPC
# Inject the noop #logger if no module-level logger method has been injected.
extend RubyLogger
end
# loads the certificates by the test server.
def load_test_certs
this_dir = File.expand_path(File.dirname(__FILE__))
@ -113,7 +168,7 @@ class TestTarget < Grpc::Testing::TestService::Service
def streaming_input_call(call)
sizes = call.each_remote_read.map { |x| x.payload.body.length }
sum = sizes.inject { |s, x| s + x }
sum = sizes.inject(0) { |s, x| s + x }
StreamingInputCallResponse.new(aggregated_payload_size: sum)
end

@ -31,6 +31,7 @@ require 'grpc'
require 'grpc/health/v1alpha/health'
require 'grpc/health/checker'
require 'open3'
require 'tmpdir'
def can_run_codegen_check
system('which grpc_ruby_plugin') && system('which protoc')

@ -89,8 +89,9 @@
]
},
'targets': [
% for module in node_modules:
% for lib in libs:
% if lib.name == 'gpr' or lib.name == 'grpc':
% if lib.name in module.transitive_deps:
{
'target_name': '${lib.name}',
'product_prefix': 'lib',
@ -142,22 +143,18 @@
}
}]
],
"target_name": "grpc_node",
"target_name": "${module.name}",
"sources": [
"src/node/ext/byte_buffer.cc",
"src/node/ext/call.cc",
"src/node/ext/call_credentials.cc",
"src/node/ext/channel.cc",
"src/node/ext/channel_credentials.cc",
"src/node/ext/completion_queue_async_worker.cc",
"src/node/ext/node_grpc.cc",
"src/node/ext/server.cc",
"src/node/ext/server_credentials.cc",
"src/node/ext/timeval.cc"
% for source in module.src:
"${source}",
% endfor
],
"dependencies": [
"grpc"
% for dep in getattr(module, 'deps', []):
"${dep}",
% endfor
]
}
},
% endfor
]
}

@ -575,6 +575,18 @@ void CancelRpc(ClientContext* context, int delay_us, TestServiceImpl* service) {
context->TryCancel();
}
TEST_P(End2endTest, CancelRpcBeforeStart) {
ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
request.set_message("hello");
context.TryCancel();
Status s = stub_->Echo(&context, request, &response);
EXPECT_EQ("", response.message());
EXPECT_EQ(grpc::StatusCode::CANCELLED, s.error_code());
}
// Client cancels request stream after sending two messages
TEST_P(End2endTest, ClientCancelsRequestStream) {
ResetStub();

@ -41,6 +41,7 @@
#include <grpc/support/time.h>
#include <grpc++/create_channel.h>
#include <grpc++/grpc++.h>
#include <grpc++/impl/thd.h>
#include "test/cpp/interop/interop_client.h"
#include "test/cpp/interop/stress_interop_client.h"
@ -80,7 +81,6 @@ DEFINE_string(test_cases, "",
using std::make_pair;
using std::pair;
using std::thread;
using std::vector;
using grpc::testing::kTestCaseList;
@ -202,7 +202,7 @@ int main(int argc, char** argv) {
gpr_log(GPR_INFO, "Starting test(s)..");
vector<thread> test_threads;
vector<grpc::thread> test_threads;
int thread_idx = 0;
for (auto it = server_addresses.begin(); it != server_addresses.end(); it++) {
StressTestInteropClient* client = new StressTestInteropClient(
@ -210,7 +210,7 @@ int main(int argc, char** argv) {
FLAGS_sleep_duration_ms);
test_threads.emplace_back(
thread(&StressTestInteropClient::MainLoop, client));
grpc::thread(&StressTestInteropClient::MainLoop, client));
}
for (auto it = test_threads.begin(); it != test_threads.end(); it++) {

@ -0,0 +1,63 @@
# 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.
"""Buildgen transitive dependencies
This takes the list of libs, node_modules, and targets from our
yaml dictionary, and adds to each the transitive closure
of the list of dependencies.
"""
def get_lib(libs, name):
return next(lib for lib in libs if lib['name']==name)
def transitive_deps(lib, libs):
if 'deps' in lib:
# Recursively call transitive_deps on each dependency, and take the union
return set.union(set(lib['deps']),
*[set(transitive_deps(get_lib(libs, dep), libs))
for dep in lib['deps']])
else:
return set()
def mako_plugin(dictionary):
"""The exported plugin code for transitive_dependencies.
Each item in libs, node_modules, and targets can have a deps list.
We add a transitive_deps property to each with the transitive closure
of those dependency lists.
"""
libs = dictionary.get('libs')
node_modules = dictionary.get('node_modules')
targets = dictionary.get('targets')
for target_list in (libs, node_modules, targets):
for target in target_list:
target['transitive_deps'] = transitive_deps(target, libs)
Loading…
Cancel
Save