grpc 1.4.1 → 1.4.5

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e39080ec605040289bb2b93e27ed1797c99d4bf1
4
- data.tar.gz: 2c93d45be2c465e705deacf118ebbb9bce2f8aa9
3
+ metadata.gz: 41d777c781a715c7193857593c53732018a49b3d
4
+ data.tar.gz: abcce4df9529daef3bd697bfa860a8247512e0f4
5
5
  SHA512:
6
- metadata.gz: 4b24f13ba6a723ec29cfbc25e44c8d1114878f369c0c6738794afe4b5e8309a2ba3ead24df133d8b2f9cfca32990d8f2b47886323ea7b38c499fc83eca85fdd7
7
- data.tar.gz: 020c079ec978700bd7a3931b88b87e58c16117bf11faf4ea813c666a9f7a36892d9c7fca4ee3e18da88bac4ec6f8c69284c22175a6c9380c6f09d9ec7d3c8b8a
6
+ metadata.gz: ec200f702fe2c9f8b169eec5df70a5e44aa6f8714fc2ab90a4d0d3ad92ff261859bbd1a535a49f556581710262b4201724762fad8f6172a7869bf63045e9d2fb
7
+ data.tar.gz: a0244c322356e3d54084347ea6bcceabd041065cbcab6d584b1dc93550b89aff2afb7d8462e11d65455adcf2de3ca4f74501ee0ddc010783e44cdb8f3819d0fa
data/Makefile CHANGED
@@ -423,8 +423,8 @@ Q = @
423
423
  endif
424
424
 
425
425
  CORE_VERSION = 4.0.0
426
- CPP_VERSION = 1.4.1
427
- CSHARP_VERSION = 1.4.1
426
+ CPP_VERSION = 1.4.5
427
+ CSHARP_VERSION = 1.4.5
428
428
 
429
429
  CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
430
430
  CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -39,6 +39,8 @@
39
39
  #include <grpc/grpc.h>
40
40
  #include <grpc/impl/codegen/compression_types.h>
41
41
  #include <grpc/support/alloc.h>
42
+ #include <grpc/support/alloc.h>
43
+ #include <grpc/support/log.h>
42
44
 
43
45
  #include "rb_byte_buffer.h"
44
46
  #include "rb_call_credentials.h"
@@ -383,7 +385,7 @@ static VALUE grpc_rb_call_set_credentials(VALUE self, VALUE credentials) {
383
385
  to fill grpc_metadata_array.
384
386
 
385
387
  it's capacity should have been computed via a prior call to
386
- grpc_rb_md_ary_fill_hash_cb
388
+ grpc_rb_md_ary_capacity_hash_cb
387
389
  */
388
390
  static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
389
391
  grpc_metadata_array *md_ary = NULL;
@@ -391,7 +393,7 @@ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
391
393
  long i;
392
394
  grpc_slice key_slice;
393
395
  grpc_slice value_slice;
394
- char *tmp_str;
396
+ char *tmp_str = NULL;
395
397
 
396
398
  if (TYPE(key) == T_SYMBOL) {
397
399
  key_slice = grpc_slice_from_static_string(rb_id2name(SYM2ID(key)));
@@ -401,6 +403,7 @@ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
401
403
  } else {
402
404
  rb_raise(rb_eTypeError,
403
405
  "grpc_rb_md_ary_fill_hash_cb: bad type for key parameter");
406
+ return ST_STOP;
404
407
  }
405
408
 
406
409
  if (!grpc_header_key_is_legal(key_slice)) {
@@ -428,6 +431,7 @@ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
428
431
  tmp_str);
429
432
  return ST_STOP;
430
433
  }
434
+ GPR_ASSERT(md_ary->count < md_ary->capacity);
431
435
  md_ary->metadata[md_ary->count].key = key_slice;
432
436
  md_ary->metadata[md_ary->count].value = value_slice;
433
437
  md_ary->count += 1;
@@ -443,6 +447,7 @@ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
443
447
  tmp_str);
444
448
  return ST_STOP;
445
449
  }
450
+ GPR_ASSERT(md_ary->count < md_ary->capacity);
446
451
  md_ary->metadata[md_ary->count].key = key_slice;
447
452
  md_ary->metadata[md_ary->count].value = value_slice;
448
453
  md_ary->count += 1;
@@ -450,7 +455,6 @@ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
450
455
  rb_raise(rb_eArgError, "Header values must be of type string or array");
451
456
  return ST_STOP;
452
457
  }
453
-
454
458
  return ST_CONTINUE;
455
459
  }
456
460
 
@@ -473,6 +477,7 @@ static int grpc_rb_md_ary_capacity_hash_cb(VALUE key, VALUE val,
473
477
  } else {
474
478
  md_ary->capacity += 1;
475
479
  }
480
+
476
481
  return ST_CONTINUE;
477
482
  }
478
483
 
@@ -495,7 +500,7 @@ void grpc_rb_md_ary_convert(VALUE md_ary_hash, grpc_metadata_array *md_ary) {
495
500
  md_ary_obj =
496
501
  TypedData_Wrap_Struct(grpc_rb_cMdAry, &grpc_rb_md_ary_data_type, md_ary);
497
502
  rb_hash_foreach(md_ary_hash, grpc_rb_md_ary_capacity_hash_cb, md_ary_obj);
498
- md_ary->metadata = gpr_malloc(md_ary->capacity * sizeof(grpc_metadata));
503
+ md_ary->metadata = gpr_zalloc(md_ary->capacity * sizeof(grpc_metadata));
499
504
  rb_hash_foreach(md_ary_hash, grpc_rb_md_ary_fill_hash_cb, md_ary_obj);
500
505
  }
501
506
 
@@ -626,13 +631,25 @@ static void grpc_run_batch_stack_init(run_batch_stack *st,
626
631
  st->write_flag = write_flag;
627
632
  }
628
633
 
634
+ void grpc_rb_metadata_array_destroy_including_entries(
635
+ grpc_metadata_array *array) {
636
+ size_t i;
637
+ if (array->metadata) {
638
+ for (i = 0; i < array->count; i++) {
639
+ grpc_slice_unref(array->metadata[i].key);
640
+ grpc_slice_unref(array->metadata[i].value);
641
+ }
642
+ }
643
+ grpc_metadata_array_destroy(array);
644
+ }
645
+
629
646
  /* grpc_run_batch_stack_cleanup ensures the run_batch_stack is properly
630
647
  * cleaned up */
631
648
  static void grpc_run_batch_stack_cleanup(run_batch_stack *st) {
632
649
  size_t i = 0;
633
650
 
634
- grpc_metadata_array_destroy(&st->send_metadata);
635
- grpc_metadata_array_destroy(&st->send_trailing_metadata);
651
+ grpc_rb_metadata_array_destroy_including_entries(&st->send_metadata);
652
+ grpc_rb_metadata_array_destroy_including_entries(&st->send_trailing_metadata);
636
653
  grpc_metadata_array_destroy(&st->recv_metadata);
637
654
  grpc_metadata_array_destroy(&st->recv_trailing_metadata);
638
655
 
@@ -673,8 +690,6 @@ static void grpc_run_batch_stack_fill_ops(run_batch_stack *st, VALUE ops_hash) {
673
690
  st->ops[st->op_num].flags = 0;
674
691
  switch (NUM2INT(this_op)) {
675
692
  case GRPC_OP_SEND_INITIAL_METADATA:
676
- /* N.B. later there is no need to explicitly delete the metadata keys
677
- * and values, they are references to data in ruby objects. */
678
693
  grpc_rb_md_ary_convert(this_value, &st->send_metadata);
679
694
  st->ops[st->op_num].data.send_initial_metadata.count =
680
695
  st->send_metadata.count;
@@ -690,8 +705,6 @@ static void grpc_run_batch_stack_fill_ops(run_batch_stack *st, VALUE ops_hash) {
690
705
  case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
691
706
  break;
692
707
  case GRPC_OP_SEND_STATUS_FROM_SERVER:
693
- /* N.B. later there is no need to explicitly delete the metadata keys
694
- * and values, they are references to data in ruby objects. */
695
708
  grpc_rb_op_update_status_from_server(
696
709
  &st->ops[st->op_num], &st->send_trailing_metadata,
697
710
  &st->send_status_details, this_value);
@@ -55,6 +55,9 @@ VALUE grpc_rb_md_ary_to_h(grpc_metadata_array *md_ary);
55
55
  */
56
56
  void grpc_rb_md_ary_convert(VALUE md_ary_hash, grpc_metadata_array *md_ary);
57
57
 
58
+ void grpc_rb_metadata_array_destroy_including_entries(
59
+ grpc_metadata_array *md_ary);
60
+
58
61
  /* grpc_rb_eCallError is the ruby class of the exception thrown during call
59
62
  operations. */
60
63
  extern VALUE grpc_rb_eCallError;
@@ -123,7 +123,7 @@ static void grpc_rb_call_credentials_callback_with_gil(void *param) {
123
123
  error_details = StringValueCStr(details);
124
124
  params->callback(params->user_data, md_ary.metadata, md_ary.count, status,
125
125
  error_details);
126
- grpc_metadata_array_destroy(&md_ary);
126
+ grpc_rb_metadata_array_destroy_including_entries(&md_ary);
127
127
  gpr_free(params);
128
128
  }
129
129
 
@@ -254,6 +254,7 @@ static VALUE grpc_rb_call_credentials_compose(int argc, VALUE *argv,
254
254
  VALUE self) {
255
255
  grpc_call_credentials *creds;
256
256
  grpc_call_credentials *other;
257
+ grpc_call_credentials *prev = NULL;
257
258
  VALUE mark;
258
259
  if (argc == 0) {
259
260
  return self;
@@ -264,6 +265,10 @@ static VALUE grpc_rb_call_credentials_compose(int argc, VALUE *argv,
264
265
  rb_ary_push(mark, argv[i]);
265
266
  other = grpc_rb_get_wrapped_call_credentials(argv[i]);
266
267
  creds = grpc_composite_call_credentials_create(creds, other, NULL);
268
+ if (prev != NULL) {
269
+ grpc_call_credentials_release(prev);
270
+ }
271
+ prev = creds;
267
272
  }
268
273
  return grpc_rb_wrap_call_credentials(creds, mark);
269
274
  }
@@ -199,6 +199,7 @@ static VALUE grpc_rb_channel_credentials_compose(int argc, VALUE *argv,
199
199
  VALUE self) {
200
200
  grpc_channel_credentials *creds;
201
201
  grpc_call_credentials *other;
202
+ grpc_channel_credentials *prev = NULL;
202
203
  VALUE mark;
203
204
  if (argc == 0) {
204
205
  return self;
@@ -210,6 +211,11 @@ static VALUE grpc_rb_channel_credentials_compose(int argc, VALUE *argv,
210
211
  rb_ary_push(mark, argv[i]);
211
212
  other = grpc_rb_get_wrapped_call_credentials(argv[i]);
212
213
  creds = grpc_composite_channel_credentials_create(creds, other, NULL);
214
+ if (prev != NULL) {
215
+ grpc_channel_credentials_release(prev);
216
+ }
217
+ prev = creds;
218
+
213
219
  if (creds == NULL) {
214
220
  rb_raise(rb_eRuntimeError,
215
221
  "Failed to compose channel and call credentials");
@@ -55,13 +55,13 @@ end
55
55
  module GRPC
56
56
  # The ActiveCall class provides simple methods for sending marshallable
57
57
  # data to a call
58
- class ActiveCall
58
+ class ActiveCall # rubocop:disable Metrics/ClassLength
59
59
  include Core::TimeConsts
60
60
  include Core::CallOps
61
61
  extend Forwardable
62
- attr_reader :deadline, :metadata_sent, :metadata_to_send
62
+ attr_reader :deadline, :metadata_sent, :metadata_to_send, :peer, :peer_cert
63
63
  def_delegators :@call, :cancel, :metadata, :write_flag, :write_flag=,
64
- :peer, :peer_cert, :trailing_metadata
64
+ :trailing_metadata, :status
65
65
 
66
66
  # client_invoke begins a client invocation.
67
67
  #
@@ -115,6 +115,18 @@ module GRPC
115
115
  fail(ArgumentError, 'Already sent md') if started && metadata_to_send
116
116
  @metadata_to_send = metadata_to_send || {} unless started
117
117
  @send_initial_md_mutex = Mutex.new
118
+
119
+ @output_stream_done = false
120
+ @input_stream_done = false
121
+ @call_finished = false
122
+ @call_finished_mu = Mutex.new
123
+
124
+ @client_call_executed = false
125
+ @client_call_executed_mu = Mutex.new
126
+
127
+ # set the peer now so that the accessor can still function
128
+ # after the server closes the call
129
+ @peer = call.peer
118
130
  end
119
131
 
120
132
  # Sends the initial metadata that has yet to be sent.
@@ -157,11 +169,9 @@ module GRPC
157
169
  Operation.new(self)
158
170
  end
159
171
 
160
- # finished waits until a client call is completed.
161
- #
162
- # It blocks until the remote endpoint acknowledges by sending a status.
163
- def finished
172
+ def receive_and_check_status
164
173
  batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
174
+ set_input_stream_done
165
175
  attach_status_results_and_complete_call(batch_result)
166
176
  end
167
177
 
@@ -170,8 +180,6 @@ module GRPC
170
180
  @call.trailing_metadata = recv_status_batch_result.status.metadata
171
181
  end
172
182
  @call.status = recv_status_batch_result.status
173
- @call.close
174
- op_is_done
175
183
 
176
184
  # The RECV_STATUS in run_batch always succeeds
177
185
  # Check the status for a bad status or failed run batch
@@ -208,9 +216,19 @@ module GRPC
208
216
  }
209
217
  ops[RECV_CLOSE_ON_SERVER] = nil if assert_finished
210
218
  @call.run_batch(ops)
219
+ set_output_stream_done
220
+
211
221
  nil
212
222
  end
213
223
 
224
+ # Intended for use on server-side calls when a single request from
225
+ # the client is expected (i.e., unary and server-streaming RPC types).
226
+ def read_unary_request
227
+ req = remote_read
228
+ set_input_stream_done
229
+ req
230
+ end
231
+
214
232
  def server_unary_response(req, trailing_metadata: {},
215
233
  code: Core::StatusCodes::OK, details: 'OK')
216
234
  ops = {}
@@ -226,6 +244,7 @@ module GRPC
226
244
  ops[RECV_CLOSE_ON_SERVER] = nil
227
245
 
228
246
  @call.run_batch(ops)
247
+ set_output_stream_done
229
248
  end
230
249
 
231
250
  # remote_read reads a response from the remote endpoint.
@@ -256,6 +275,8 @@ module GRPC
256
275
 
257
276
  # each_remote_read passes each response to the given block or returns an
258
277
  # enumerator the responses if no block is given.
278
+ # Used to generate the request enumerable for
279
+ # server-side client-streaming RPC's.
259
280
  #
260
281
  # == Enumerator ==
261
282
  #
@@ -273,10 +294,14 @@ module GRPC
273
294
  # @return [Enumerator] if no block was given
274
295
  def each_remote_read
275
296
  return enum_for(:each_remote_read) unless block_given?
276
- loop do
277
- resp = remote_read
278
- break if resp.nil? # the last response was received
279
- yield resp
297
+ begin
298
+ loop do
299
+ resp = remote_read
300
+ break if resp.nil? # the last response was received
301
+ yield resp
302
+ end
303
+ ensure
304
+ set_input_stream_done
280
305
  end
281
306
  end
282
307
 
@@ -302,13 +327,17 @@ module GRPC
302
327
  # @return [Enumerator] if no block was given
303
328
  def each_remote_read_then_finish
304
329
  return enum_for(:each_remote_read_then_finish) unless block_given?
305
- loop do
306
- resp = remote_read
307
- if resp.nil? # the last response was received, but not finished yet
308
- finished
309
- break
330
+ begin
331
+ loop do
332
+ resp = remote_read
333
+ if resp.nil? # the last response was received
334
+ receive_and_check_status
335
+ break
336
+ end
337
+ yield resp
310
338
  end
311
- yield resp
339
+ ensure
340
+ set_input_stream_done
312
341
  end
313
342
  end
314
343
 
@@ -320,6 +349,7 @@ module GRPC
320
349
  # a list, multiple metadata for its key are sent
321
350
  # @return [Object] the response received from the server
322
351
  def request_response(req, metadata: {})
352
+ raise_error_if_already_executed
323
353
  ops = {
324
354
  SEND_MESSAGE => @marshal.call(req),
325
355
  SEND_CLOSE_FROM_CLIENT => nil,
@@ -334,7 +364,15 @@ module GRPC
334
364
  end
335
365
  @metadata_sent = true
336
366
  end
337
- batch_result = @call.run_batch(ops)
367
+
368
+ begin
369
+ batch_result = @call.run_batch(ops)
370
+ # no need to check for cancellation after a CallError because this
371
+ # batch contains a RECV_STATUS op
372
+ ensure
373
+ set_input_stream_done
374
+ set_output_stream_done
375
+ end
338
376
 
339
377
  @call.metadata = batch_result.metadata
340
378
  attach_status_results_and_complete_call(batch_result)
@@ -354,10 +392,20 @@ module GRPC
354
392
  # a list, multiple metadata for its key are sent
355
393
  # @return [Object] the response received from the server
356
394
  def client_streamer(requests, metadata: {})
357
- # Metadata might have already been sent if this is an operation view
358
- merge_metadata_and_send_if_not_already_sent(metadata)
395
+ raise_error_if_already_executed
396
+ begin
397
+ merge_metadata_and_send_if_not_already_sent(metadata)
398
+ requests.each { |r| @call.run_batch(SEND_MESSAGE => @marshal.call(r)) }
399
+ rescue GRPC::Core::CallError => e
400
+ receive_and_check_status # check for Cancelled
401
+ raise e
402
+ rescue => e
403
+ set_input_stream_done
404
+ raise e
405
+ ensure
406
+ set_output_stream_done
407
+ end
359
408
 
360
- requests.each { |r| @call.run_batch(SEND_MESSAGE => @marshal.call(r)) }
361
409
  batch_result = @call.run_batch(
362
410
  SEND_CLOSE_FROM_CLIENT => nil,
363
411
  RECV_INITIAL_METADATA => nil,
@@ -365,12 +413,11 @@ module GRPC
365
413
  RECV_STATUS_ON_CLIENT => nil
366
414
  )
367
415
 
416
+ set_input_stream_done
417
+
368
418
  @call.metadata = batch_result.metadata
369
419
  attach_status_results_and_complete_call(batch_result)
370
420
  get_message_from_batch_result(batch_result)
371
- rescue GRPC::Core::CallError => e
372
- finished # checks for Cancelled
373
- raise e
374
421
  end
375
422
 
376
423
  # server_streamer sends one request to the GRPC server, which yields a
@@ -388,6 +435,7 @@ module GRPC
388
435
  # a list, multiple metadata for its key are sent
389
436
  # @return [Enumerator|nil] a response Enumerator
390
437
  def server_streamer(req, metadata: {})
438
+ raise_error_if_already_executed
391
439
  ops = {
392
440
  SEND_MESSAGE => @marshal.call(req),
393
441
  SEND_CLOSE_FROM_CLIENT => nil
@@ -399,13 +447,22 @@ module GRPC
399
447
  end
400
448
  @metadata_sent = true
401
449
  end
402
- @call.run_batch(ops)
450
+
451
+ begin
452
+ @call.run_batch(ops)
453
+ rescue GRPC::Core::CallError => e
454
+ receive_and_check_status # checks for Cancelled
455
+ raise e
456
+ rescue => e
457
+ set_input_stream_done
458
+ raise e
459
+ ensure
460
+ set_output_stream_done
461
+ end
462
+
403
463
  replies = enum_for(:each_remote_read_then_finish)
404
464
  return replies unless block_given?
405
465
  replies.each { |r| yield r }
406
- rescue GRPC::Core::CallError => e
407
- finished # checks for Cancelled
408
- raise e
409
466
  end
410
467
 
411
468
  # bidi_streamer sends a stream of requests to the GRPC server, and yields
@@ -436,6 +493,7 @@ module GRPC
436
493
  # a list, multiple metadata for its key are sent
437
494
  # @return [Enumerator, nil] a response Enumerator
438
495
  def bidi_streamer(requests, metadata: {}, &blk)
496
+ raise_error_if_already_executed
439
497
  # Metadata might have already been sent if this is an operation view
440
498
  merge_metadata_and_send_if_not_already_sent(metadata)
441
499
  bd = BidiCall.new(@call,
@@ -443,7 +501,10 @@ module GRPC
443
501
  @unmarshal,
444
502
  metadata_received: @metadata_received)
445
503
 
446
- bd.run_on_client(requests, @op_notifier, &blk)
504
+ bd.run_on_client(requests,
505
+ proc { set_input_stream_done },
506
+ proc { set_output_stream_done },
507
+ &blk)
447
508
  end
448
509
 
449
510
  # run_server_bidi orchestrates a BiDi stream processing on a server.
@@ -464,7 +525,7 @@ module GRPC
464
525
  metadata_received: @metadata_received,
465
526
  req_view: MultiReqView.new(self))
466
527
 
467
- bd.run_on_server(gen_each_reply)
528
+ bd.run_on_server(gen_each_reply, proc { set_input_stream_done })
468
529
  end
469
530
 
470
531
  # Waits till an operation completes
@@ -474,7 +535,8 @@ module GRPC
474
535
  @op_notifier.wait
475
536
  end
476
537
 
477
- # Signals that an operation is done
538
+ # Signals that an operation is done.
539
+ # Only relevant on the client-side (this is a no-op on the server-side)
478
540
  def op_is_done
479
541
  return if @op_notifier.nil?
480
542
  @op_notifier.notify(self)
@@ -499,8 +561,40 @@ module GRPC
499
561
  end
500
562
  end
501
563
 
564
+ def attach_peer_cert(peer_cert)
565
+ @peer_cert = peer_cert
566
+ end
567
+
502
568
  private
503
569
 
570
+ # To be called once the "input stream" has been completelly
571
+ # read through (i.e, done reading from client or received status)
572
+ # note this is idempotent
573
+ def set_input_stream_done
574
+ @call_finished_mu.synchronize do
575
+ @input_stream_done = true
576
+ maybe_finish_and_close_call_locked
577
+ end
578
+ end
579
+
580
+ # To be called once the "output stream" has been completelly
581
+ # sent through (i.e, done sending from client or sent status)
582
+ # note this is idempotent
583
+ def set_output_stream_done
584
+ @call_finished_mu.synchronize do
585
+ @output_stream_done = true
586
+ maybe_finish_and_close_call_locked
587
+ end
588
+ end
589
+
590
+ def maybe_finish_and_close_call_locked
591
+ return unless @output_stream_done && @input_stream_done
592
+ return if @call_finished
593
+ @call_finished = true
594
+ op_is_done
595
+ @call.close
596
+ end
597
+
504
598
  # Starts the call if not already started
505
599
  # @param metadata [Hash] metadata to be sent to the server. If a value is
506
600
  # a list, multiple metadata for its key are sent
@@ -508,6 +602,15 @@ module GRPC
508
602
  merge_metadata_to_send(metadata) && send_initial_metadata
509
603
  end
510
604
 
605
+ def raise_error_if_already_executed
606
+ @client_call_executed_mu.synchronize do
607
+ if @client_call_executed
608
+ fail GRPC::Core::CallError, 'attempting to re-run a call'
609
+ end
610
+ @client_call_executed = true
611
+ end
612
+ end
613
+
511
614
  def self.view_class(*visible_methods)
512
615
  Class.new do
513
616
  extend ::Forwardable
@@ -533,6 +636,7 @@ module GRPC
533
636
  # server client_streamer handlers.
534
637
  MultiReqView = view_class(:cancelled?, :deadline, :each_queued_msg,
535
638
  :each_remote_read, :metadata, :output_metadata,
639
+ :peer, :peer_cert,
536
640
  :send_initial_metadata,
537
641
  :metadata_to_send,
538
642
  :merge_metadata_to_send,