grpc 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -2
  3. data/bin/{interop/test/cpp/interop/test.rb → grpc_ruby_interop_client} +4 -14
  4. data/bin/{interop/test/cpp/interop/empty.rb → grpc_ruby_interop_server} +4 -15
  5. data/bin/interop/interop_client.rb +9 -335
  6. data/bin/interop/interop_server.rb +9 -153
  7. data/bin/math_client.rb +3 -3
  8. data/bin/math_server.rb +18 -1
  9. data/bin/noproto_server.rb +2 -1
  10. data/ext/grpc/rb_call.c +82 -15
  11. data/ext/grpc/rb_channel.c +141 -11
  12. data/ext/grpc/rb_channel_args.c +2 -1
  13. data/ext/grpc/rb_completion_queue.c +8 -7
  14. data/ext/grpc/rb_credentials.c +7 -6
  15. data/ext/grpc/rb_grpc.c +23 -8
  16. data/ext/grpc/rb_server.c +31 -45
  17. data/ext/grpc/rb_server_credentials.c +91 -34
  18. data/lib/grpc/generic/active_call.rb +7 -7
  19. data/lib/grpc/generic/bidi_call.rb +17 -12
  20. data/lib/grpc/generic/client_stub.rb +88 -22
  21. data/lib/grpc/generic/rpc_server.rb +19 -18
  22. data/lib/grpc/generic/service.rb +8 -10
  23. data/lib/grpc/grpc.so +0 -0
  24. data/lib/grpc/logconfig.rb +26 -10
  25. data/lib/grpc/version.rb +1 -1
  26. data/spec/call_spec.rb +9 -1
  27. data/spec/channel_spec.rb +2 -2
  28. data/spec/client_server_spec.rb +28 -11
  29. data/spec/credentials_spec.rb +7 -7
  30. data/spec/generic/active_call_spec.rb +43 -18
  31. data/spec/generic/client_stub_spec.rb +21 -1
  32. data/spec/generic/rpc_server_spec.rb +20 -9
  33. data/spec/pb/health/checker_spec.rb +232 -0
  34. data/spec/server_credentials_spec.rb +32 -7
  35. data/spec/server_spec.rb +8 -4
  36. data/spec/spec_helper.rb +13 -1
  37. metadata +31 -51
  38. data/.gitignore +0 -15
  39. data/.rspec +0 -4
  40. data/.rubocop.yml +0 -10
  41. data/.rubocop_todo.yml +0 -44
  42. data/CHANGELOG.md +0 -11
  43. data/Gemfile +0 -4
  44. data/README.md +0 -84
  45. data/bin/interop/README.md +0 -8
  46. data/bin/interop/test/cpp/interop/messages.rb +0 -89
  47. data/bin/interop/test/cpp/interop/test_services.rb +0 -60
  48. data/grpc.gemspec +0 -40
@@ -50,7 +50,7 @@ def do_div(stub)
50
50
  GRPC.logger.info('----------------')
51
51
  req = Math::DivArgs.new(dividend: 7, divisor: 3)
52
52
  GRPC.logger.info("div(7/3): req=#{req.inspect}")
53
- resp = stub.div(req, INFINITE_FUTURE)
53
+ resp = stub.div(req, timeout: INFINITE_FUTURE)
54
54
  GRPC.logger.info("Answer: #{resp.inspect}")
55
55
  GRPC.logger.info('----------------')
56
56
  end
@@ -71,7 +71,7 @@ def do_fib(stub)
71
71
  GRPC.logger.info('----------------')
72
72
  req = Math::FibArgs.new(limit: 11)
73
73
  GRPC.logger.info("fib(11): req=#{req.inspect}")
74
- resp = stub.fib(req, INFINITE_FUTURE)
74
+ resp = stub.fib(req, timeout: INFINITE_FUTURE)
75
75
  resp.each do |r|
76
76
  GRPC.logger.info("Answer: #{r.inspect}")
77
77
  end
@@ -86,7 +86,7 @@ def do_div_many(stub)
86
86
  reqs << Math::DivArgs.new(dividend: 5, divisor: 2)
87
87
  reqs << Math::DivArgs.new(dividend: 7, divisor: 2)
88
88
  GRPC.logger.info("div(7/3), div(5/2), div(7/2): reqs=#{reqs.inspect}")
89
- resp = stub.div_many(reqs, 10)
89
+ resp = stub.div_many(reqs, timeout: INFINITE_FUTURE)
90
90
  resp.each do |r|
91
91
  GRPC.logger.info("Answer: #{r.inspect}")
92
92
  end
@@ -41,9 +41,25 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
41
41
 
42
42
  require 'forwardable'
43
43
  require 'grpc'
44
+ require 'logger'
44
45
  require 'math_services'
45
46
  require 'optparse'
46
47
 
48
+ # RubyLogger defines a logger for gRPC based on the standard ruby logger.
49
+ module RubyLogger
50
+ def logger
51
+ LOGGER
52
+ end
53
+
54
+ LOGGER = Logger.new(STDOUT)
55
+ end
56
+
57
+ # GRPC is the general RPC module
58
+ module GRPC
59
+ # Inject the noop #logger if no module-level logger method has been injected.
60
+ extend RubyLogger
61
+ end
62
+
47
63
  # Holds state for a fibonacci series
48
64
  class Fibber
49
65
  def initialize(limit)
@@ -155,7 +171,8 @@ end
155
171
 
156
172
  def test_server_creds
157
173
  certs = load_test_certs
158
- GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
174
+ GRPC::Core::ServerCredentials.new(
175
+ nil, [{ private_key: certs[1], cert_chain: certs[2] }], false)
159
176
  end
160
177
 
161
178
  def main
@@ -77,7 +77,8 @@ end
77
77
 
78
78
  def test_server_creds
79
79
  certs = load_test_certs
80
- GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
80
+ GRPC::Core::ServerCredentials.new(
81
+ nil, [{ private_key: certs[1], cert_chain: certs[2] }], false)
81
82
  end
82
83
 
83
84
  def main
@@ -82,6 +82,10 @@ static ID id_metadata;
82
82
  * received by the call and subsequently saved on it. */
83
83
  static ID id_status;
84
84
 
85
+ /* id_write_flag is name of the attribute used to access the write_flag
86
+ * saved on the call. */
87
+ static ID id_write_flag;
88
+
85
89
  /* sym_* are the symbol for attributes of grpc_rb_sBatchResult. */
86
90
  static VALUE sym_send_message;
87
91
  static VALUE sym_send_metadata;
@@ -131,7 +135,8 @@ static size_t md_ary_datasize(const void *p) {
131
135
 
132
136
  static const rb_data_type_t grpc_rb_md_ary_data_type = {
133
137
  "grpc_metadata_array",
134
- {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, md_ary_datasize},
138
+ {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, md_ary_datasize,
139
+ {NULL, NULL}},
135
140
  NULL,
136
141
  NULL,
137
142
  0};
@@ -139,7 +144,8 @@ static const rb_data_type_t grpc_rb_md_ary_data_type = {
139
144
  /* Describes grpc_call struct for RTypedData */
140
145
  static const rb_data_type_t grpc_call_data_type = {
141
146
  "grpc_call",
142
- {GRPC_RB_GC_NOT_MARKED, grpc_rb_call_destroy, GRPC_RB_MEMSIZE_UNAVAILABLE},
147
+ {GRPC_RB_GC_NOT_MARKED, grpc_rb_call_destroy, GRPC_RB_MEMSIZE_UNAVAILABLE,
148
+ {NULL, NULL}},
143
149
  NULL,
144
150
  NULL,
145
151
  /* it is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because
@@ -168,7 +174,7 @@ static VALUE grpc_rb_call_cancel(VALUE self) {
168
174
  grpc_call *call = NULL;
169
175
  grpc_call_error err;
170
176
  TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
171
- err = grpc_call_cancel(call);
177
+ err = grpc_call_cancel(call, NULL);
172
178
  if (err != GRPC_CALL_OK) {
173
179
  rb_raise(grpc_rb_eCallError, "cancel failed: %s (code=%d)",
174
180
  grpc_call_error_detail_of(err), err);
@@ -177,6 +183,19 @@ static VALUE grpc_rb_call_cancel(VALUE self) {
177
183
  return Qnil;
178
184
  }
179
185
 
186
+ /* Called to obtain the peer that this call is connected to. */
187
+ static VALUE grpc_rb_call_get_peer(VALUE self) {
188
+ VALUE res = Qnil;
189
+ grpc_call *call = NULL;
190
+ char *peer = NULL;
191
+ TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
192
+ peer = grpc_call_get_peer(call);
193
+ res = rb_str_new2(peer);
194
+ gpr_free(peer);
195
+
196
+ return res;
197
+ }
198
+
180
199
  /*
181
200
  call-seq:
182
201
  status = call.status
@@ -225,6 +244,30 @@ static VALUE grpc_rb_call_set_metadata(VALUE self, VALUE metadata) {
225
244
  return rb_ivar_set(self, id_metadata, metadata);
226
245
  }
227
246
 
247
+ /*
248
+ call-seq:
249
+ write_flag = call.write_flag
250
+
251
+ Gets the write_flag value saved the call. */
252
+ static VALUE grpc_rb_call_get_write_flag(VALUE self) {
253
+ return rb_ivar_get(self, id_write_flag);
254
+ }
255
+
256
+ /*
257
+ call-seq:
258
+ call.write_flag = write_flag
259
+
260
+ Saves the write_flag on the call. */
261
+ static VALUE grpc_rb_call_set_write_flag(VALUE self, VALUE write_flag) {
262
+ if (!NIL_P(write_flag) && TYPE(write_flag) != T_FIXNUM) {
263
+ rb_raise(rb_eTypeError, "bad write_flag: got:<%s> want: <Fixnum>",
264
+ rb_obj_classname(write_flag));
265
+ return Qnil;
266
+ }
267
+
268
+ return rb_ivar_set(self, id_write_flag, write_flag);
269
+ }
270
+
228
271
  /* grpc_rb_md_ary_fill_hash_cb is the hash iteration callback used
229
272
  to fill grpc_metadata_array.
230
273
 
@@ -233,8 +276,8 @@ static VALUE grpc_rb_call_set_metadata(VALUE self, VALUE metadata) {
233
276
  */
234
277
  static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
235
278
  grpc_metadata_array *md_ary = NULL;
236
- int array_length;
237
- int i;
279
+ long array_length;
280
+ long i;
238
281
 
239
282
  /* Construct a metadata object from key and value and add it */
240
283
  TypedData_Get_Struct(md_ary_obj, grpc_metadata_array,
@@ -275,6 +318,8 @@ static int grpc_rb_md_ary_capacity_hash_cb(VALUE key, VALUE val,
275
318
  VALUE md_ary_obj) {
276
319
  grpc_metadata_array *md_ary = NULL;
277
320
 
321
+ (void)key;
322
+
278
323
  /* Construct a metadata object from key and value and add it */
279
324
  TypedData_Get_Struct(md_ary_obj, grpc_metadata_array,
280
325
  &grpc_rb_md_ary_data_type, md_ary);
@@ -348,6 +393,7 @@ VALUE grpc_rb_md_ary_to_h(grpc_metadata_array *md_ary) {
348
393
  */
349
394
  static int grpc_rb_call_check_op_keys_hash_cb(VALUE key, VALUE val,
350
395
  VALUE ops_ary) {
396
+ (void)val;
351
397
  /* Update the capacity; the value is an array, add capacity for each value in
352
398
  * the array */
353
399
  if (TYPE(key) != T_FIXNUM) {
@@ -419,17 +465,19 @@ typedef struct run_batch_stack {
419
465
  grpc_status_code recv_status;
420
466
  char *recv_status_details;
421
467
  size_t recv_status_details_capacity;
468
+ uint write_flag;
422
469
  } run_batch_stack;
423
470
 
424
471
  /* grpc_run_batch_stack_init ensures the run_batch_stack is properly
425
472
  * initialized */
426
- static void grpc_run_batch_stack_init(run_batch_stack *st) {
473
+ static void grpc_run_batch_stack_init(run_batch_stack *st, uint write_flag) {
427
474
  MEMZERO(st, run_batch_stack, 1);
428
475
  grpc_metadata_array_init(&st->send_metadata);
429
476
  grpc_metadata_array_init(&st->send_trailing_metadata);
430
477
  grpc_metadata_array_init(&st->recv_metadata);
431
478
  grpc_metadata_array_init(&st->recv_trailing_metadata);
432
479
  st->op_num = 0;
480
+ st->write_flag = write_flag;
433
481
  }
434
482
 
435
483
  /* grpc_run_batch_stack_cleanup ensures the run_batch_stack is properly
@@ -459,6 +507,7 @@ static void grpc_run_batch_stack_fill_ops(run_batch_stack *st, VALUE ops_hash) {
459
507
  for (i = 0; i < (size_t)RARRAY_LEN(ops_ary); i++) {
460
508
  this_op = rb_ary_entry(ops_ary, i);
461
509
  this_value = rb_hash_aref(ops_hash, this_op);
510
+ st->ops[st->op_num].flags = 0;
462
511
  switch (NUM2INT(this_op)) {
463
512
  case GRPC_OP_SEND_INITIAL_METADATA:
464
513
  /* N.B. later there is no need to explicitly delete the metadata keys
@@ -472,6 +521,7 @@ static void grpc_run_batch_stack_fill_ops(run_batch_stack *st, VALUE ops_hash) {
472
521
  case GRPC_OP_SEND_MESSAGE:
473
522
  st->ops[st->op_num].data.send_message = grpc_rb_s_to_byte_buffer(
474
523
  RSTRING_PTR(this_value), RSTRING_LEN(this_value));
524
+ st->ops[st->op_num].flags = st->write_flag;
475
525
  break;
476
526
  case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
477
527
  break;
@@ -507,7 +557,7 @@ static void grpc_run_batch_stack_fill_ops(run_batch_stack *st, VALUE ops_hash) {
507
557
  NUM2INT(this_op));
508
558
  };
509
559
  st->ops[st->op_num].op = (grpc_op_type)NUM2INT(this_op);
510
- st->ops[st->op_num].flags = 0;
560
+ st->ops[st->op_num].reserved = NULL;
511
561
  st->op_num++;
512
562
  }
513
563
  }
@@ -585,6 +635,8 @@ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE cqueue, VALUE tag,
585
635
  grpc_event ev;
586
636
  grpc_call_error err;
587
637
  VALUE result = Qnil;
638
+ VALUE rb_write_flag = rb_ivar_get(self, id_write_flag);
639
+ uint write_flag = 0;
588
640
  TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
589
641
 
590
642
  /* Validate the ops args, adding them to a ruby array */
@@ -592,12 +644,15 @@ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE cqueue, VALUE tag,
592
644
  rb_raise(rb_eTypeError, "call#run_batch: ops hash should be a hash");
593
645
  return Qnil;
594
646
  }
595
- grpc_run_batch_stack_init(&st);
647
+ if (rb_write_flag != Qnil) {
648
+ write_flag = NUM2UINT(rb_write_flag);
649
+ }
650
+ grpc_run_batch_stack_init(&st, write_flag);
596
651
  grpc_run_batch_stack_fill_ops(&st, ops_hash);
597
652
 
598
653
  /* call grpc_call_start_batch, then wait for it to complete using
599
654
  * pluck_event */
600
- err = grpc_call_start_batch(call, st.ops, st.op_num, ROBJECT(tag));
655
+ err = grpc_call_start_batch(call, st.ops, st.op_num, ROBJECT(tag), NULL);
601
656
  if (err != GRPC_CALL_OK) {
602
657
  grpc_run_batch_stack_cleanup(&st);
603
658
  rb_raise(grpc_rb_eCallError,
@@ -611,18 +666,24 @@ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE cqueue, VALUE tag,
611
666
  rb_raise(grpc_rb_eOutOfTime, "grpc_call_start_batch timed out");
612
667
  return Qnil;
613
668
  }
614
- if (!ev.success) {
615
- grpc_run_batch_stack_cleanup(&st);
616
- rb_raise(grpc_rb_eCallError, "start_batch completion failed");
617
- return Qnil;
618
- }
619
669
 
620
- /* Build and return the BatchResult struct result */
670
+ /* Build and return the BatchResult struct result,
671
+ if there is an error, it's reflected in the status */
621
672
  result = grpc_run_batch_stack_build_result(&st);
622
673
  grpc_run_batch_stack_cleanup(&st);
623
674
  return result;
624
675
  }
625
676
 
677
+ static void Init_grpc_write_flags() {
678
+ /* Constants representing the write flags in grpc.h */
679
+ VALUE grpc_rb_mWriteFlags =
680
+ rb_define_module_under(grpc_rb_mGrpcCore, "WriteFlags");
681
+ rb_define_const(grpc_rb_mWriteFlags, "BUFFER_HINT",
682
+ UINT2NUM(GRPC_WRITE_BUFFER_HINT));
683
+ rb_define_const(grpc_rb_mWriteFlags, "NO_COMPRESS",
684
+ UINT2NUM(GRPC_WRITE_NO_COMPRESS));
685
+ }
686
+
626
687
  static void Init_grpc_error_codes() {
627
688
  /* Constants representing the error codes of grpc_call_error in grpc.h */
628
689
  VALUE grpc_rb_mRpcErrors =
@@ -715,14 +776,19 @@ void Init_grpc_call() {
715
776
  /* Add ruby analogues of the Call methods. */
716
777
  rb_define_method(grpc_rb_cCall, "run_batch", grpc_rb_call_run_batch, 4);
717
778
  rb_define_method(grpc_rb_cCall, "cancel", grpc_rb_call_cancel, 0);
779
+ rb_define_method(grpc_rb_cCall, "peer", grpc_rb_call_get_peer, 0);
718
780
  rb_define_method(grpc_rb_cCall, "status", grpc_rb_call_get_status, 0);
719
781
  rb_define_method(grpc_rb_cCall, "status=", grpc_rb_call_set_status, 1);
720
782
  rb_define_method(grpc_rb_cCall, "metadata", grpc_rb_call_get_metadata, 0);
721
783
  rb_define_method(grpc_rb_cCall, "metadata=", grpc_rb_call_set_metadata, 1);
784
+ rb_define_method(grpc_rb_cCall, "write_flag", grpc_rb_call_get_write_flag, 0);
785
+ rb_define_method(grpc_rb_cCall, "write_flag=", grpc_rb_call_set_write_flag,
786
+ 1);
722
787
 
723
788
  /* Ids used to support call attributes */
724
789
  id_metadata = rb_intern("metadata");
725
790
  id_status = rb_intern("status");
791
+ id_write_flag = rb_intern("write_flag");
726
792
 
727
793
  /* Ids used by the c wrapping internals. */
728
794
  id_cq = rb_intern("__cq");
@@ -750,6 +816,7 @@ void Init_grpc_call() {
750
816
 
751
817
  Init_grpc_error_codes();
752
818
  Init_grpc_op_codes();
819
+ Init_grpc_write_flags();
753
820
  }
754
821
 
755
822
  /* Gets the call from the ruby object */
@@ -37,6 +37,7 @@
37
37
 
38
38
  #include <grpc/grpc.h>
39
39
  #include <grpc/grpc_security.h>
40
+ #include <grpc/support/alloc.h>
40
41
  #include "rb_grpc.h"
41
42
  #include "rb_call.h"
42
43
  #include "rb_channel_args.h"
@@ -107,7 +108,8 @@ static void grpc_rb_channel_mark(void *p) {
107
108
 
108
109
  static rb_data_type_t grpc_channel_data_type = {
109
110
  "grpc_channel",
110
- {grpc_rb_channel_mark, grpc_rb_channel_free, GRPC_RB_MEMSIZE_UNAVAILABLE},
111
+ {grpc_rb_channel_mark, grpc_rb_channel_free, GRPC_RB_MEMSIZE_UNAVAILABLE,
112
+ {NULL, NULL}},
111
113
  NULL, NULL,
112
114
  RUBY_TYPED_FREE_IMMEDIATELY
113
115
  };
@@ -145,10 +147,10 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
145
147
  target_chars = StringValueCStr(target);
146
148
  grpc_rb_hash_convert_to_channel_args(channel_args, &args);
147
149
  if (credentials == Qnil) {
148
- ch = grpc_channel_create(target_chars, &args);
150
+ ch = grpc_insecure_channel_create(target_chars, &args, NULL);
149
151
  } else {
150
152
  creds = grpc_rb_get_wrapped_credentials(credentials);
151
- ch = grpc_secure_channel_create(creds, target_chars, &args);
153
+ ch = grpc_secure_channel_create(creds, target_chars, &args, NULL);
152
154
  }
153
155
  if (args.args != NULL) {
154
156
  xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */
@@ -163,6 +165,65 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) {
163
165
  return self;
164
166
  }
165
167
 
168
+ /*
169
+ call-seq:
170
+ insecure_channel = Channel:new("myhost:8080", {'arg1': 'value1'})
171
+ creds = ...
172
+ secure_channel = Channel:new("myhost:443", {'arg1': 'value1'}, creds)
173
+
174
+ Creates channel instances. */
175
+ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv,
176
+ VALUE self) {
177
+ VALUE try_to_connect = Qfalse;
178
+ grpc_rb_channel *wrapper = NULL;
179
+ grpc_channel *ch = NULL;
180
+
181
+ /* "01" == 0 mandatory args, 1 (try_to_connect) is optional */
182
+ rb_scan_args(argc, argv, "01", try_to_connect);
183
+
184
+ TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
185
+ ch = wrapper->wrapped;
186
+ if (ch == NULL) {
187
+ rb_raise(rb_eRuntimeError, "closed!");
188
+ return Qnil;
189
+ }
190
+ return NUM2LONG(
191
+ grpc_channel_check_connectivity_state(ch, (int)try_to_connect));
192
+ }
193
+
194
+ /* Watch for a change in connectivity state.
195
+
196
+ Once the channel connectivity state is different from the last observed
197
+ state, tag will be enqueued on cq with success=1
198
+
199
+ If deadline expires BEFORE the state is changed, tag will be enqueued on
200
+ the completion queue with success=0 */
201
+ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self,
202
+ VALUE last_state,
203
+ VALUE cqueue,
204
+ VALUE deadline,
205
+ VALUE tag) {
206
+ grpc_rb_channel *wrapper = NULL;
207
+ grpc_channel *ch = NULL;
208
+ grpc_completion_queue *cq = NULL;
209
+
210
+ cq = grpc_rb_get_wrapped_completion_queue(cqueue);
211
+ TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
212
+ ch = wrapper->wrapped;
213
+ if (ch == NULL) {
214
+ rb_raise(rb_eRuntimeError, "closed!");
215
+ return Qnil;
216
+ }
217
+ grpc_channel_watch_connectivity_state(
218
+ ch,
219
+ NUM2LONG(last_state),
220
+ grpc_rb_time_timeval(deadline, /* absolute time */ 0),
221
+ cq,
222
+ ROBJECT(tag));
223
+
224
+ return Qnil;
225
+ }
226
+
166
227
  /* Clones Channel instances.
167
228
 
168
229
  Gives Channel a consistent implementation of Ruby's object copy/dup
@@ -193,15 +254,28 @@ static VALUE grpc_rb_channel_init_copy(VALUE copy, VALUE orig) {
193
254
 
194
255
  /* Create a call given a grpc_channel, in order to call method. The request
195
256
  is not sent until grpc_call_invoke is called. */
196
- static VALUE grpc_rb_channel_create_call(VALUE self, VALUE cqueue, VALUE method,
197
- VALUE host, VALUE deadline) {
257
+ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE cqueue,
258
+ VALUE parent, VALUE mask,
259
+ VALUE method, VALUE host,
260
+ VALUE deadline) {
198
261
  VALUE res = Qnil;
199
262
  grpc_rb_channel *wrapper = NULL;
200
263
  grpc_call *call = NULL;
264
+ grpc_call *parent_call = NULL;
201
265
  grpc_channel *ch = NULL;
202
266
  grpc_completion_queue *cq = NULL;
267
+ int flags = GRPC_PROPAGATE_DEFAULTS;
203
268
  char *method_chars = StringValueCStr(method);
204
- char *host_chars = StringValueCStr(host);
269
+ char *host_chars = NULL;
270
+ if (host != Qnil) {
271
+ host_chars = StringValueCStr(host);
272
+ }
273
+ if (mask != Qnil) {
274
+ flags = NUM2UINT(mask);
275
+ }
276
+ if (parent != Qnil) {
277
+ parent_call = grpc_rb_get_wrapped_call(parent);
278
+ }
205
279
 
206
280
  cq = grpc_rb_get_wrapped_completion_queue(cqueue);
207
281
  TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
@@ -211,10 +285,10 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE cqueue, VALUE method,
211
285
  return Qnil;
212
286
  }
213
287
 
214
- call =
215
- grpc_channel_create_call(ch, cq, method_chars, host_chars,
216
- grpc_rb_time_timeval(deadline,
217
- /* absolute time */ 0));
288
+ call = grpc_channel_create_call(ch, parent_call, flags, cq, method_chars,
289
+ host_chars, grpc_rb_time_timeval(
290
+ deadline,
291
+ /* absolute time */ 0), NULL);
218
292
  if (call == NULL) {
219
293
  rb_raise(rb_eRuntimeError, "cannot create call with method %s",
220
294
  method_chars);
@@ -232,6 +306,7 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE cqueue, VALUE method,
232
306
  return res;
233
307
  }
234
308
 
309
+
235
310
  /* Closes the channel, calling it's destroy method */
236
311
  static VALUE grpc_rb_channel_destroy(VALUE self) {
237
312
  grpc_rb_channel *wrapper = NULL;
@@ -248,6 +323,53 @@ static VALUE grpc_rb_channel_destroy(VALUE self) {
248
323
  return Qnil;
249
324
  }
250
325
 
326
+
327
+ /* Called to obtain the target that this channel accesses. */
328
+ static VALUE grpc_rb_channel_get_target(VALUE self) {
329
+ grpc_rb_channel *wrapper = NULL;
330
+ VALUE res = Qnil;
331
+ char* target = NULL;
332
+
333
+ TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper);
334
+ target = grpc_channel_get_target(wrapper->wrapped);
335
+ res = rb_str_new2(target);
336
+ gpr_free(target);
337
+
338
+ return res;
339
+ }
340
+
341
+ static void Init_grpc_propagate_masks() {
342
+ /* Constants representing call propagation masks in grpc.h */
343
+ VALUE grpc_rb_mPropagateMasks = rb_define_module_under(
344
+ grpc_rb_mGrpcCore, "PropagateMasks");
345
+ rb_define_const(grpc_rb_mPropagateMasks, "DEADLINE",
346
+ UINT2NUM(GRPC_PROPAGATE_DEADLINE));
347
+ rb_define_const(grpc_rb_mPropagateMasks, "CENSUS_STATS_CONTEXT",
348
+ UINT2NUM(GRPC_PROPAGATE_CENSUS_STATS_CONTEXT));
349
+ rb_define_const(grpc_rb_mPropagateMasks, "CENSUS_TRACING_CONTEXT",
350
+ UINT2NUM(GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT));
351
+ rb_define_const(grpc_rb_mPropagateMasks, "CANCELLATION",
352
+ UINT2NUM(GRPC_PROPAGATE_CANCELLATION));
353
+ rb_define_const(grpc_rb_mPropagateMasks, "DEFAULTS",
354
+ UINT2NUM(GRPC_PROPAGATE_DEFAULTS));
355
+ }
356
+
357
+ static void Init_grpc_connectivity_states() {
358
+ /* Constants representing call propagation masks in grpc.h */
359
+ VALUE grpc_rb_mConnectivityStates = rb_define_module_under(
360
+ grpc_rb_mGrpcCore, "ConnectivityStates");
361
+ rb_define_const(grpc_rb_mConnectivityStates, "IDLE",
362
+ LONG2NUM(GRPC_CHANNEL_IDLE));
363
+ rb_define_const(grpc_rb_mConnectivityStates, "CONNECTING",
364
+ LONG2NUM(GRPC_CHANNEL_CONNECTING));
365
+ rb_define_const(grpc_rb_mConnectivityStates, "READY",
366
+ LONG2NUM(GRPC_CHANNEL_READY));
367
+ rb_define_const(grpc_rb_mConnectivityStates, "TRANSIENT_FAILURE",
368
+ LONG2NUM(GRPC_CHANNEL_TRANSIENT_FAILURE));
369
+ rb_define_const(grpc_rb_mConnectivityStates, "FATAL_FAILURE",
370
+ LONG2NUM(GRPC_CHANNEL_FATAL_FAILURE));
371
+ }
372
+
251
373
  void Init_grpc_channel() {
252
374
  grpc_rb_cChannelArgs = rb_define_class("TmpChannelArgs", rb_cObject);
253
375
  grpc_rb_cChannel =
@@ -262,8 +384,14 @@ void Init_grpc_channel() {
262
384
  grpc_rb_channel_init_copy, 1);
263
385
 
264
386
  /* Add ruby analogues of the Channel methods. */
387
+ rb_define_method(grpc_rb_cChannel, "connectivity_state",
388
+ grpc_rb_channel_get_connectivity_state,
389
+ -1);
390
+ rb_define_method(grpc_rb_cChannel, "watch_connectivity_state",
391
+ grpc_rb_channel_watch_connectivity_state, 4);
265
392
  rb_define_method(grpc_rb_cChannel, "create_call",
266
- grpc_rb_channel_create_call, 4);
393
+ grpc_rb_channel_create_call, 6);
394
+ rb_define_method(grpc_rb_cChannel, "target", grpc_rb_channel_get_target, 0);
267
395
  rb_define_method(grpc_rb_cChannel, "destroy", grpc_rb_channel_destroy, 0);
268
396
  rb_define_alias(grpc_rb_cChannel, "close", "destroy");
269
397
 
@@ -278,6 +406,8 @@ void Init_grpc_channel() {
278
406
  ID2SYM(rb_intern(GRPC_ARG_MAX_CONCURRENT_STREAMS)));
279
407
  rb_define_const(grpc_rb_cChannel, "MAX_MESSAGE_LENGTH",
280
408
  ID2SYM(rb_intern(GRPC_ARG_MAX_MESSAGE_LENGTH)));
409
+ Init_grpc_propagate_masks();
410
+ Init_grpc_connectivity_states();
281
411
  }
282
412
 
283
413
  /* Gets the wrapped channel from the ruby wrapper */