diff options
Diffstat (limited to 'src/ruby')
24 files changed, 249 insertions, 195 deletions
diff --git a/src/ruby/bin/apis/pubsub_demo.rb b/src/ruby/bin/apis/pubsub_demo.rb index a039d036ac..003e91a6b3 100755 --- a/src/ruby/bin/apis/pubsub_demo.rb +++ b/src/ruby/bin/apis/pubsub_demo.rb @@ -66,7 +66,7 @@ end # creates a SSL Credentials from the production certificates. def ssl_creds - GRPC::Core::Credentials.new(load_prod_cert) + GRPC::Core::ChannelCredentials.new(load_prod_cert) end # Builds the metadata authentication update proc. diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb index 0ebd26f780..d7e00e4293 100755 --- a/src/ruby/bin/math_client.rb +++ b/src/ruby/bin/math_client.rb @@ -102,7 +102,7 @@ end def test_creds certs = load_test_certs - GRPC::Core::Credentials.new(certs[0]) + GRPC::Core::ChannelCredentials.new(certs[0]) end def main diff --git a/src/ruby/bin/noproto_client.rb b/src/ruby/bin/noproto_client.rb index 390a9c59c3..3aa11870c0 100755 --- a/src/ruby/bin/noproto_client.rb +++ b/src/ruby/bin/noproto_client.rb @@ -68,7 +68,7 @@ end def test_creds certs = load_test_certs - GRPC::Core::Credentials.new(certs[0]) + GRPC::Core::ChannelCredentials.new(certs[0]) end def main diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c index 6b5beb6f5d..40364328ee 100644 --- a/src/ruby/ext/grpc/rb_call.c +++ b/src/ruby/ext/grpc/rb_call.c @@ -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; diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 90afdc3fe1..d5d82421f5 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -41,8 +41,8 @@ #include "rb_grpc.h" #include "rb_call.h" #include "rb_channel_args.h" +#include "rb_channel_credentials.h" #include "rb_completion_queue.h" -#include "rb_credentials.h" #include "rb_server.h" /* id_channel is the name of the hidden ivar that preserves a reference to the @@ -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. */ @@ -134,8 +136,8 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { VALUE credentials = Qnil; VALUE target = Qnil; grpc_rb_channel *wrapper = NULL; - grpc_credentials *creds = NULL; grpc_channel *ch = NULL; + grpc_channel_credentials *creds = NULL; char *target_chars = NULL; grpc_channel_args args; MEMZERO(&args, grpc_channel_args, 1); @@ -149,7 +151,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { if (credentials == Qnil) { ch = grpc_insecure_channel_create(target_chars, &args, NULL); } else { - creds = grpc_rb_get_wrapped_credentials(credentials); + creds = grpc_rb_get_wrapped_channel_credentials(credentials); ch = grpc_secure_channel_create(creds, target_chars, &args, NULL); } if (args.args != NULL) { diff --git a/src/ruby/ext/grpc/rb_channel_args.c b/src/ruby/ext/grpc/rb_channel_args.c index 1ba30b69aa..37dd981925 100644 --- a/src/ruby/ext/grpc/rb_channel_args.c +++ b/src/ruby/ext/grpc/rb_channel_args.c @@ -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 */ diff --git a/src/ruby/ext/grpc/rb_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c index ae757f6986..072a6f54ab 100644 --- a/src/ruby/ext/grpc/rb_credentials.c +++ b/src/ruby/ext/grpc/rb_channel_credentials.c @@ -31,7 +31,7 @@ * */ -#include "rb_credentials.h" +#include "rb_channel_credentials.h" #include <ruby/ruby.h> @@ -40,32 +40,33 @@ #include "rb_grpc.h" -/* grpc_rb_cCredentials is the ruby class that proxies grpc_credentials. */ -static VALUE grpc_rb_cCredentials = Qnil; +/* grpc_rb_cChannelCredentials is the ruby class that proxies + grpc_channel_credentials. */ +static VALUE grpc_rb_cChannelCredentials = Qnil; -/* grpc_rb_credentials wraps a grpc_credentials. It provides a +/* grpc_rb_channel_credentials wraps a grpc_channel_credentials. It provides a * peer ruby object, 'mark' to minimize copying when a credential is * created from ruby. */ -typedef struct grpc_rb_credentials { +typedef struct grpc_rb_channel_credentials { /* Holder of ruby objects involved in constructing the credentials */ VALUE mark; /* The actual credentials */ - grpc_credentials *wrapped; -} grpc_rb_credentials; + grpc_channel_credentials *wrapped; +} grpc_rb_channel_credentials; /* Destroys the credentials instances. */ -static void grpc_rb_credentials_free(void *p) { - grpc_rb_credentials *wrapper = NULL; +static void grpc_rb_channel_credentials_free(void *p) { + grpc_rb_channel_credentials *wrapper = NULL; if (p == NULL) { return; }; - wrapper = (grpc_rb_credentials *)p; + wrapper = (grpc_rb_channel_credentials *)p; /* Delete the wrapped object if the mark object is Qnil, which indicates that * no other object is the actual owner. */ if (wrapper->wrapped != NULL && wrapper->mark == Qnil) { - grpc_credentials_release(wrapper->wrapped); + grpc_channel_credentials_release(wrapper->wrapped); wrapper->wrapped = NULL; } @@ -73,12 +74,12 @@ static void grpc_rb_credentials_free(void *p) { } /* Protects the mark object from GC */ -static void grpc_rb_credentials_mark(void *p) { - grpc_rb_credentials *wrapper = NULL; +static void grpc_rb_channel_credentials_mark(void *p) { + grpc_rb_channel_credentials *wrapper = NULL; if (p == NULL) { return; } - wrapper = (grpc_rb_credentials *)p; + wrapper = (grpc_rb_channel_credentials *)p; /* If it's not already cleaned up, mark the mark object */ if (wrapper->mark != Qnil) { @@ -86,29 +87,32 @@ static void grpc_rb_credentials_mark(void *p) { } } -static rb_data_type_t grpc_rb_credentials_data_type = { - "grpc_credentials", - {grpc_rb_credentials_mark, grpc_rb_credentials_free, +static rb_data_type_t grpc_rb_channel_credentials_data_type = { + "grpc_channel_credentials", + {grpc_rb_channel_credentials_mark, grpc_rb_channel_credentials_free, 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. +/* Allocates ChannelCredential instances. Provides safe initial defaults for the instance fields. */ -static VALUE grpc_rb_credentials_alloc(VALUE cls) { - grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials); +static VALUE grpc_rb_channel_credentials_alloc(VALUE cls) { + grpc_rb_channel_credentials *wrapper = ALLOC(grpc_rb_channel_credentials); wrapper->wrapped = NULL; wrapper->mark = Qnil; - return TypedData_Wrap_Struct(cls, &grpc_rb_credentials_data_type, wrapper); + return TypedData_Wrap_Struct(cls, &grpc_rb_channel_credentials_data_type, wrapper); } -/* Clones Credentials instances. - Gives Credentials a consistent implementation of Ruby's object copy/dup +/* Clones ChannelCredentials instances. + Gives ChannelCredentials a consistent implementation of Ruby's object copy/dup protocol. */ -static VALUE grpc_rb_credentials_init_copy(VALUE copy, VALUE orig) { - grpc_rb_credentials *orig_cred = NULL; - grpc_rb_credentials *copy_cred = NULL; +static VALUE grpc_rb_channel_credentials_init_copy(VALUE copy, VALUE orig) { + grpc_rb_channel_credentials *orig_cred = NULL; + grpc_rb_channel_credentials *copy_cred = NULL; if (copy == orig) { return copy; @@ -116,83 +120,22 @@ static VALUE grpc_rb_credentials_init_copy(VALUE copy, VALUE orig) { /* Raise an error if orig is not a credentials object or a subclass. */ if (TYPE(orig) != T_DATA || - RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_credentials_free) { - rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(grpc_rb_cCredentials)); + RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_channel_credentials_free) { + rb_raise(rb_eTypeError, "not a %s", + rb_obj_classname(grpc_rb_cChannelCredentials)); } - TypedData_Get_Struct(orig, grpc_rb_credentials, - &grpc_rb_credentials_data_type, orig_cred); - TypedData_Get_Struct(copy, grpc_rb_credentials, - &grpc_rb_credentials_data_type, copy_cred); + TypedData_Get_Struct(orig, grpc_rb_channel_credentials, + &grpc_rb_channel_credentials_data_type, orig_cred); + TypedData_Get_Struct(copy, grpc_rb_channel_credentials, + &grpc_rb_channel_credentials_data_type, copy_cred); /* use ruby's MEMCPY to make a byte-for-byte copy of the credentials * wrapper object. */ - MEMCPY(copy_cred, orig_cred, grpc_rb_credentials, 1); + MEMCPY(copy_cred, orig_cred, grpc_rb_channel_credentials, 1); return copy; } -/* - call-seq: - creds = Credentials.default() - Creates the default credential instances. */ -static VALUE grpc_rb_default_credentials_create(VALUE cls) { - grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials); - wrapper->wrapped = grpc_google_default_credentials_create(); - if (wrapper->wrapped == NULL) { - rb_raise(rb_eRuntimeError, - "could not create default credentials, not sure why"); - return Qnil; - } - - wrapper->mark = Qnil; - return TypedData_Wrap_Struct(cls, &grpc_rb_credentials_data_type, wrapper); -} - -/* - call-seq: - creds = Credentials.compute_engine() - Creates the default credential instances. */ -static VALUE grpc_rb_compute_engine_credentials_create(VALUE cls) { - grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials); - wrapper->wrapped = grpc_google_compute_engine_credentials_create(NULL); - if (wrapper->wrapped == NULL) { - rb_raise(rb_eRuntimeError, - "could not create composite engine credentials, not sure why"); - return Qnil; - } - - wrapper->mark = Qnil; - return TypedData_Wrap_Struct(cls, &grpc_rb_credentials_data_type, wrapper); -} - -/* - call-seq: - creds1 = ... - creds2 = ... - creds3 = creds1.add(creds2) - Creates the default credential instances. */ -static VALUE grpc_rb_composite_credentials_create(VALUE self, VALUE other) { - grpc_rb_credentials *self_wrapper = NULL; - grpc_rb_credentials *other_wrapper = NULL; - grpc_rb_credentials *wrapper = NULL; - - TypedData_Get_Struct(self, grpc_rb_credentials, - &grpc_rb_credentials_data_type, self_wrapper); - TypedData_Get_Struct(other, grpc_rb_credentials, - &grpc_rb_credentials_data_type, other_wrapper); - wrapper = ALLOC(grpc_rb_credentials); - wrapper->wrapped = grpc_composite_credentials_create( - self_wrapper->wrapped, other_wrapper->wrapped, NULL); - if (wrapper->wrapped == NULL) { - rb_raise(rb_eRuntimeError, - "could not create composite credentials, not sure why"); - return Qnil; - } - - wrapper->mark = Qnil; - return TypedData_Wrap_Struct(grpc_rb_cCredentials, - &grpc_rb_credentials_data_type, wrapper); -} /* The attribute used on the mark object to hold the pem_root_certs. */ static ID id_pem_root_certs; @@ -213,12 +156,12 @@ static ID id_pem_cert_chain; pem_private_key: (optional) PEM encoding of the client's private key pem_cert_chain: (optional) PEM encoding of the client's cert chain Initializes Credential instances. */ -static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) { +static VALUE grpc_rb_channel_credentials_init(int argc, VALUE *argv, VALUE self) { VALUE pem_root_certs = Qnil; VALUE pem_private_key = Qnil; VALUE pem_cert_chain = Qnil; - grpc_rb_credentials *wrapper = NULL; - grpc_credentials *creds = NULL; + grpc_rb_channel_credentials *wrapper = NULL; + grpc_channel_credentials *creds = NULL; grpc_ssl_pem_key_cert_pair key_cert_pair; MEMZERO(&key_cert_pair, grpc_ssl_pem_key_cert_pair, 1); /* TODO: Remove mandatory arg when we support default roots. */ @@ -226,8 +169,8 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) { rb_scan_args(argc, argv, "12", &pem_root_certs, &pem_private_key, &pem_cert_chain); - TypedData_Get_Struct(self, grpc_rb_credentials, - &grpc_rb_credentials_data_type, wrapper); + TypedData_Get_Struct(self, grpc_rb_channel_credentials, + &grpc_rb_channel_credentials_data_type, wrapper); if (pem_root_certs == Qnil) { rb_raise(rb_eRuntimeError, "could not create a credential: nil pem_root_certs"); @@ -256,39 +199,30 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) { return self; } -void Init_grpc_credentials() { - grpc_rb_cCredentials = - rb_define_class_under(grpc_rb_mGrpcCore, "Credentials", rb_cObject); +void Init_grpc_channel_credentials() { + grpc_rb_cChannelCredentials = + rb_define_class_under(grpc_rb_mGrpcCore, "ChannelCredentials", rb_cObject); /* Allocates an object managed by the ruby runtime */ - rb_define_alloc_func(grpc_rb_cCredentials, grpc_rb_credentials_alloc); + rb_define_alloc_func(grpc_rb_cChannelCredentials, + grpc_rb_channel_credentials_alloc); /* Provides a ruby constructor and support for dup/clone. */ - rb_define_method(grpc_rb_cCredentials, "initialize", grpc_rb_credentials_init, - -1); - rb_define_method(grpc_rb_cCredentials, "initialize_copy", - grpc_rb_credentials_init_copy, 1); - - /* Provide static funcs that create new special instances. */ - rb_define_singleton_method(grpc_rb_cCredentials, "default", - grpc_rb_default_credentials_create, 0); - - rb_define_singleton_method(grpc_rb_cCredentials, "compute_engine", - grpc_rb_compute_engine_credentials_create, 0); - - /* Provide other methods. */ - rb_define_method(grpc_rb_cCredentials, "compose", - grpc_rb_composite_credentials_create, 1); + rb_define_method(grpc_rb_cChannelCredentials, "initialize", + grpc_rb_channel_credentials_init, -1); + rb_define_method(grpc_rb_cChannelCredentials, "initialize_copy", + grpc_rb_channel_credentials_init_copy, 1); id_pem_cert_chain = rb_intern("__pem_cert_chain"); id_pem_private_key = rb_intern("__pem_private_key"); id_pem_root_certs = rb_intern("__pem_root_certs"); } -/* Gets the wrapped grpc_credentials from the ruby wrapper */ -grpc_credentials *grpc_rb_get_wrapped_credentials(VALUE v) { - grpc_rb_credentials *wrapper = NULL; - TypedData_Get_Struct(v, grpc_rb_credentials, &grpc_rb_credentials_data_type, +/* Gets the wrapped grpc_channel_credentials from the ruby wrapper */ +grpc_channel_credentials *grpc_rb_get_wrapped_channel_credentials(VALUE v) { + grpc_rb_channel_credentials *wrapper = NULL; + TypedData_Get_Struct(v, grpc_rb_channel_credentials, + &grpc_rb_channel_credentials_data_type, wrapper); return wrapper->wrapped; } diff --git a/src/ruby/ext/grpc/rb_credentials.h b/src/ruby/ext/grpc/rb_channel_credentials.h index 840f7d5f9c..15229de932 100644 --- a/src/ruby/ext/grpc/rb_credentials.h +++ b/src/ruby/ext/grpc/rb_channel_credentials.h @@ -38,10 +38,10 @@ #include <grpc/grpc_security.h> -/* Initializes the ruby Credentials class. */ -void Init_grpc_credentials(); +/* Initializes the ruby ChannelCredentials class. */ +void Init_grpc_channel_credentials(); /* Gets the wrapped credentials from the ruby wrapper */ -grpc_credentials* grpc_rb_get_wrapped_credentials(VALUE v); +grpc_channel_credentials* grpc_rb_get_wrapped_channel_credentials(VALUE v); #endif /* GRPC_RB_CREDENTIALS_H_ */ diff --git a/src/ruby/ext/grpc/rb_completion_queue.c b/src/ruby/ext/grpc/rb_completion_queue.c index 0bc9eb2a97..a7de96d718 100644 --- a/src/ruby/ext/grpc/rb_completion_queue.c +++ b/src/ruby/ext/grpc/rb_completion_queue.c @@ -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. */ diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c index 327fd1a4fc..7c7c2d3440 100644 --- a/src/ruby/ext/grpc/rb_grpc.c +++ b/src/ruby/ext/grpc/rb_grpc.c @@ -42,9 +42,9 @@ #include <grpc/support/time.h> #include "rb_call.h" #include "rb_channel.h" +#include "rb_channel_credentials.h" #include "rb_completion_queue.h" #include "rb_server.h" -#include "rb_credentials.h" #include "rb_server_credentials.h" static VALUE grpc_rb_cTimeVal = Qnil; @@ -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 = @@ -300,7 +318,7 @@ void Init_grpc() { Init_grpc_channel(); Init_grpc_completion_queue(); Init_grpc_call(); - Init_grpc_credentials(); + Init_grpc_channel_credentials(); Init_grpc_server(); Init_grpc_server_credentials(); Init_grpc_status_codes(); diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 4469658869..ebdd7e1a34 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -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) { diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c index ea4d0d864e..de57585e0b 100644 --- a/src/ruby/ext/grpc/rb_server_credentials.c +++ b/src/ruby/ext/grpc/rb_server_credentials.c @@ -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. diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb index d9cb924735..e80d24edc9 100644 --- a/src/ruby/lib/grpc/generic/active_call.rb +++ b/src/ruby/lib/grpc/generic/active_call.rb @@ -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 diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb index 9dbbb74caf..6b9b785693 100644 --- a/src/ruby/lib/grpc/generic/bidi_call.rb +++ b/src/ruby/lib/grpc/generic/bidi_call.rb @@ -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? diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb index b8e33ad295..90aaa026ec 100644 --- a/src/ruby/lib/grpc/generic/client_stub.rb +++ b/src/ruby/lib/grpc/generic/client_stub.rb @@ -51,7 +51,9 @@ module GRPC end kw['grpc.primary_user_agent'] = "grpc-ruby/#{VERSION}" return Core::Channel.new(host, kw) if creds.nil? - fail(TypeError, '!Credentials') unless creds.is_a?(Core::Credentials) + unless creds.is_a?(Core::ChannelCredentials) + fail(TypeError, '!ChannelCredentials') + end Core::Channel.new(host, kw, creds) end @@ -106,7 +108,7 @@ module GRPC # @param q [Core::CompletionQueue] used to wait for events # @param channel_override [Core::Channel] a pre-created channel # @param timeout [Number] the default timeout to use in requests - # @param creds [Core::Credentials] the channel + # @param creds [Core::ChannelCredentials] the channel credentials # @param update_metadata a func that updates metadata as described above # @param kw [KeywordArgs]the channel arguments def initialize(host, q, diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 228c500672..0e318bd53b 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -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 diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb index 1388685734..30550d6cc0 100755 --- a/src/ruby/pb/test/client.rb +++ b/src/ruby/pb/test/client.rb @@ -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 @@ -86,13 +103,13 @@ end # creates SSL Credentials from the test certificates. def test_creds certs = load_test_certs - GRPC::Core::Credentials.new(certs[0]) + GRPC::Core::ChannelCredentials.new(certs[0]) end # creates SSL Credentials from the production certificates. def prod_creds cert_text = load_prod_cert - GRPC::Core::Credentials.new(cert_text) + GRPC::Core::ChannelCredentials.new(cert_text) end # creates the SSL Credentials. diff --git a/src/ruby/pb/test/server.rb b/src/ruby/pb/test/server.rb index 25c1b1e9e6..67877a191f 100755 --- a/src/ruby/pb/test/server.rb +++ b/src/ruby/pb/test/server.rb @@ -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 diff --git a/src/ruby/spec/credentials_spec.rb b/src/ruby/spec/channel_credentials_spec.rb index b02219dfdb..b2bdf7032e 100644 --- a/src/ruby/spec/credentials_spec.rb +++ b/src/ruby/spec/channel_credentials_spec.rb @@ -29,8 +29,8 @@ require 'grpc' -describe GRPC::Core::Credentials do - Credentials = GRPC::Core::Credentials +describe GRPC::Core::ChannelCredentials do + ChannelCredentials = GRPC::Core::ChannelCredentials def load_test_certs test_root = File.join(File.dirname(__FILE__), 'testdata') @@ -40,32 +40,24 @@ describe GRPC::Core::Credentials do describe '#new' do it 'can be constructed with fake inputs' do - expect { Credentials.new('root_certs', 'key', 'cert') }.not_to raise_error + blk = proc { ChannelCredentials.new('root_certs', 'key', 'cert') } + expect(&blk).not_to raise_error end it 'it can be constructed using specific test certificates' do certs = load_test_certs - expect { Credentials.new(*certs) }.not_to raise_error + expect { ChannelCredentials.new(*certs) }.not_to raise_error end it 'can be constructed with server roots certs only' do root_cert, _, _ = load_test_certs - expect { Credentials.new(root_cert) }.not_to raise_error + expect { ChannelCredentials.new(root_cert) }.not_to raise_error end it 'cannot be constructed with a nil server roots' do _, client_key, client_chain = load_test_certs - blk = proc { Credentials.new(nil, client_key, client_chain) } + blk = proc { ChannelCredentials.new(nil, client_key, client_chain) } expect(&blk).to raise_error end end - - describe '#compose' do - it 'cannot be completed OK with 2 SSL creds' do - certs = load_test_certs - cred1 = Credentials.new(*certs) - cred2 = Credentials.new(*certs) - expect { cred1.compose(cred2) }.to raise_error - end - end end diff --git a/src/ruby/spec/channel_spec.rb b/src/ruby/spec/channel_spec.rb index 25cefcdfb7..b4d2b94a81 100644 --- a/src/ruby/spec/channel_spec.rb +++ b/src/ruby/spec/channel_spec.rb @@ -40,7 +40,7 @@ describe GRPC::Core::Channel do let(:cq) { GRPC::Core::CompletionQueue.new } def create_test_cert - GRPC::Core::Credentials.new(load_test_certs[0]) + GRPC::Core::ChannelCredentials.new(load_test_certs[0]) end shared_examples '#new' do diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb index ad0fb26896..734f176e94 100644 --- a/src/ruby/spec/client_server_spec.rb +++ b/src/ruby/spec/client_server_spec.rb @@ -431,7 +431,7 @@ describe 'the secure http client/server' do @server.start args = { Channel::SSL_TARGET => 'foo.test.google.fr' } @ch = Channel.new("0.0.0.0:#{server_port}", args, - GRPC::Core::Credentials.new(certs[0], nil, nil)) + GRPC::Core::ChannelCredentials.new(certs[0], nil, nil)) end after(:example) do diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb index c5173aee1d..da5bc6c9e5 100644 --- a/src/ruby/spec/generic/client_stub_spec.rb +++ b/src/ruby/spec/generic/client_stub_spec.rb @@ -113,7 +113,7 @@ describe 'ClientStub' do opts = { GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr', a_channel_arg: 'an_arg', - creds: GRPC::Core::Credentials.new(certs[0], nil, nil) + creds: GRPC::Core::ChannelCredentials.new(certs[0], nil, nil) } GRPC::ClientStub.new(fake_host, @cq, **opts) end diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb index 9bc82638c7..322566b784 100644 --- a/src/ruby/spec/pb/health/checker_spec.rb +++ b/src/ruby/spec/pb/health/checker_spec.rb @@ -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') diff --git a/src/ruby/spec/testdata/server1.pem b/src/ruby/spec/testdata/server1.pem index 8e582e571f..f3d43fcc5b 100755 --- a/src/ruby/spec/testdata/server1.pem +++ b/src/ruby/spec/testdata/server1.pem @@ -1,16 +1,16 @@ -----BEGIN CERTIFICATE----- -MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET -MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ -dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5 -MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV -BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl -c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs -JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO -RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30 -3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL -BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6 -b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ -KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS -wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e -aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s= +MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx +MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50 +ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco +LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg +zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd +9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw +CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy +em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G +CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6 +hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh +y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8 -----END CERTIFICATE----- |