grpc 0.5.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 (86) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +10 -0
  5. data/.rubocop_todo.yml +52 -0
  6. data/Gemfile +4 -0
  7. data/README.md +82 -0
  8. data/Rakefile +54 -0
  9. data/bin/apis/google/protobuf/empty.rb +44 -0
  10. data/bin/apis/pubsub_demo.rb +267 -0
  11. data/bin/apis/tech/pubsub/proto/pubsub.rb +174 -0
  12. data/bin/apis/tech/pubsub/proto/pubsub_services.rb +103 -0
  13. data/bin/interop/README.md +8 -0
  14. data/bin/interop/interop_client.rb +334 -0
  15. data/bin/interop/interop_server.rb +192 -0
  16. data/bin/interop/test/cpp/interop/empty.rb +44 -0
  17. data/bin/interop/test/cpp/interop/messages.rb +89 -0
  18. data/bin/interop/test/cpp/interop/test.rb +43 -0
  19. data/bin/interop/test/cpp/interop/test_services.rb +60 -0
  20. data/bin/math.proto +80 -0
  21. data/bin/math.rb +61 -0
  22. data/bin/math_client.rb +147 -0
  23. data/bin/math_server.rb +190 -0
  24. data/bin/math_services.rb +56 -0
  25. data/bin/noproto_client.rb +108 -0
  26. data/bin/noproto_server.rb +112 -0
  27. data/ext/grpc/extconf.rb +76 -0
  28. data/ext/grpc/rb_byte_buffer.c +241 -0
  29. data/ext/grpc/rb_byte_buffer.h +54 -0
  30. data/ext/grpc/rb_call.c +569 -0
  31. data/ext/grpc/rb_call.h +59 -0
  32. data/ext/grpc/rb_channel.c +264 -0
  33. data/ext/grpc/rb_channel.h +49 -0
  34. data/ext/grpc/rb_channel_args.c +154 -0
  35. data/ext/grpc/rb_channel_args.h +52 -0
  36. data/ext/grpc/rb_completion_queue.c +185 -0
  37. data/ext/grpc/rb_completion_queue.h +50 -0
  38. data/ext/grpc/rb_credentials.c +281 -0
  39. data/ext/grpc/rb_credentials.h +50 -0
  40. data/ext/grpc/rb_event.c +361 -0
  41. data/ext/grpc/rb_event.h +53 -0
  42. data/ext/grpc/rb_grpc.c +274 -0
  43. data/ext/grpc/rb_grpc.h +74 -0
  44. data/ext/grpc/rb_metadata.c +215 -0
  45. data/ext/grpc/rb_metadata.h +53 -0
  46. data/ext/grpc/rb_server.c +278 -0
  47. data/ext/grpc/rb_server.h +50 -0
  48. data/ext/grpc/rb_server_credentials.c +210 -0
  49. data/ext/grpc/rb_server_credentials.h +50 -0
  50. data/grpc.gemspec +41 -0
  51. data/lib/grpc.rb +39 -0
  52. data/lib/grpc/core/event.rb +44 -0
  53. data/lib/grpc/core/time_consts.rb +71 -0
  54. data/lib/grpc/errors.rb +61 -0
  55. data/lib/grpc/generic/active_call.rb +536 -0
  56. data/lib/grpc/generic/bidi_call.rb +221 -0
  57. data/lib/grpc/generic/client_stub.rb +413 -0
  58. data/lib/grpc/generic/rpc_desc.rb +150 -0
  59. data/lib/grpc/generic/rpc_server.rb +404 -0
  60. data/lib/grpc/generic/service.rb +235 -0
  61. data/lib/grpc/logconfig.rb +40 -0
  62. data/lib/grpc/version.rb +33 -0
  63. data/spec/alloc_spec.rb +44 -0
  64. data/spec/byte_buffer_spec.rb +67 -0
  65. data/spec/call_spec.rb +163 -0
  66. data/spec/channel_spec.rb +181 -0
  67. data/spec/client_server_spec.rb +372 -0
  68. data/spec/completion_queue_spec.rb +74 -0
  69. data/spec/credentials_spec.rb +71 -0
  70. data/spec/event_spec.rb +53 -0
  71. data/spec/generic/active_call_spec.rb +373 -0
  72. data/spec/generic/client_stub_spec.rb +519 -0
  73. data/spec/generic/rpc_desc_spec.rb +357 -0
  74. data/spec/generic/rpc_server_pool_spec.rb +139 -0
  75. data/spec/generic/rpc_server_spec.rb +404 -0
  76. data/spec/generic/service_spec.rb +342 -0
  77. data/spec/metadata_spec.rb +64 -0
  78. data/spec/server_credentials_spec.rb +69 -0
  79. data/spec/server_spec.rb +212 -0
  80. data/spec/spec_helper.rb +51 -0
  81. data/spec/testdata/README +1 -0
  82. data/spec/testdata/ca.pem +15 -0
  83. data/spec/testdata/server1.key +16 -0
  84. data/spec/testdata/server1.pem +16 -0
  85. data/spec/time_consts_spec.rb +89 -0
  86. metadata +353 -0
@@ -0,0 +1,54 @@
1
+ /*
2
+ *
3
+ * Copyright 2015, Google Inc.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are
8
+ * met:
9
+ *
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above
13
+ * copyright notice, this list of conditions and the following disclaimer
14
+ * in the documentation and/or other materials provided with the
15
+ * distribution.
16
+ * * Neither the name of Google Inc. nor the names of its
17
+ * contributors may be used to endorse or promote products derived from
18
+ * this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ *
32
+ */
33
+
34
+ #ifndef GRPC_RB_BYTE_BUFFER_H_
35
+ #define GRPC_RB_BYTE_BUFFER_H_
36
+
37
+ #include <grpc/grpc.h>
38
+ #include <ruby.h>
39
+
40
+ /* rb_cByteBuffer is the ByteBuffer class whose instances proxy
41
+ grpc_byte_buffer. */
42
+ extern VALUE rb_cByteBuffer;
43
+
44
+ /* Initializes the ByteBuffer class. */
45
+ void Init_grpc_byte_buffer();
46
+
47
+ /* grpc_rb_byte_buffer_create_with_mark creates a grpc_rb_byte_buffer with a
48
+ * ruby mark object that will be kept alive while the byte_buffer is alive. */
49
+ VALUE grpc_rb_byte_buffer_create_with_mark(VALUE mark, grpc_byte_buffer* bb);
50
+
51
+ /* Gets the wrapped byte_buffer from its ruby object. */
52
+ grpc_byte_buffer* grpc_rb_get_wrapped_byte_buffer(VALUE v);
53
+
54
+ #endif /* GRPC_RB_BYTE_BUFFER_H_ */
@@ -0,0 +1,569 @@
1
+ /*
2
+ *
3
+ * Copyright 2015, Google Inc.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are
8
+ * met:
9
+ *
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above
13
+ * copyright notice, this list of conditions and the following disclaimer
14
+ * in the documentation and/or other materials provided with the
15
+ * distribution.
16
+ * * Neither the name of Google Inc. nor the names of its
17
+ * contributors may be used to endorse or promote products derived from
18
+ * this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ *
32
+ */
33
+
34
+ #include "rb_call.h"
35
+
36
+ #include <ruby.h>
37
+
38
+ #include <grpc/grpc.h>
39
+ #include "rb_byte_buffer.h"
40
+ #include "rb_completion_queue.h"
41
+ #include "rb_metadata.h"
42
+ #include "rb_grpc.h"
43
+
44
+ /* id_cq is the name of the hidden ivar that preserves a reference to a
45
+ * completion queue */
46
+ static ID id_cq;
47
+
48
+ /* id_flags is the name of the hidden ivar that preserves the value of
49
+ * the flags used to create metadata from a Hash */
50
+ static ID id_flags;
51
+
52
+ /* id_input_md is the name of the hidden ivar that preserves the hash used to
53
+ * create metadata, so that references to the strings it contains last as long
54
+ * as the call the metadata is added to. */
55
+ static ID id_input_md;
56
+
57
+ /* id_metadata is name of the attribute used to access the metadata hash
58
+ * received by the call and subsequently saved on it. */
59
+ static ID id_metadata;
60
+
61
+ /* id_status is name of the attribute used to access the status object
62
+ * received by the call and subsequently saved on it. */
63
+ static ID id_status;
64
+
65
+ /* hash_all_calls is a hash of Call address -> reference count that is used to
66
+ * track the creation and destruction of rb_call instances.
67
+ */
68
+ static VALUE hash_all_calls;
69
+
70
+ /* Destroys a Call. */
71
+ void grpc_rb_call_destroy(void *p) {
72
+ grpc_call *call = NULL;
73
+ VALUE ref_count = Qnil;
74
+ if (p == NULL) {
75
+ return;
76
+ };
77
+ call = (grpc_call *)p;
78
+
79
+ ref_count = rb_hash_aref(hash_all_calls, OFFT2NUM((VALUE)call));
80
+ if (ref_count == Qnil) {
81
+ return; /* No longer in the hash, so already deleted */
82
+ } else if (NUM2UINT(ref_count) == 1) {
83
+ rb_hash_delete(hash_all_calls, OFFT2NUM((VALUE)call));
84
+ grpc_call_destroy(call);
85
+ } else {
86
+ rb_hash_aset(hash_all_calls, OFFT2NUM((VALUE)call),
87
+ UINT2NUM(NUM2UINT(ref_count) - 1));
88
+ }
89
+ }
90
+
91
+ /* Error code details is a hash containing text strings describing errors */
92
+ VALUE rb_error_code_details;
93
+
94
+ /* Obtains the error detail string for given error code */
95
+ const char *grpc_call_error_detail_of(grpc_call_error err) {
96
+ VALUE detail_ref = rb_hash_aref(rb_error_code_details, UINT2NUM(err));
97
+ const char *detail = "unknown error code!";
98
+ if (detail_ref != Qnil) {
99
+ detail = StringValueCStr(detail_ref);
100
+ }
101
+ return detail;
102
+ }
103
+
104
+ /* grpc_rb_call_add_metadata_hash_cb is the hash iteration callback used by
105
+ grpc_rb_call_add_metadata.
106
+ */
107
+ int grpc_rb_call_add_metadata_hash_cb(VALUE key, VALUE val, VALUE call_obj) {
108
+ grpc_call *call = NULL;
109
+ grpc_metadata *md = NULL;
110
+ VALUE md_obj = Qnil;
111
+ VALUE md_obj_args[2];
112
+ VALUE flags = rb_ivar_get(call_obj, id_flags);
113
+ grpc_call_error err;
114
+ int array_length;
115
+ int i;
116
+
117
+ /* Construct a metadata object from key and value and add it */
118
+ Data_Get_Struct(call_obj, grpc_call, call);
119
+ md_obj_args[0] = key;
120
+
121
+ if (TYPE(val) == T_ARRAY) {
122
+ /* If the value is an array, add each value in the array separately */
123
+ array_length = RARRAY_LEN(val);
124
+ for (i = 0; i < array_length; i++) {
125
+ md_obj_args[1] = rb_ary_entry(val, i);
126
+ md_obj = rb_class_new_instance(2, md_obj_args, rb_cMetadata);
127
+ md = grpc_rb_get_wrapped_metadata(md_obj);
128
+ err = grpc_call_add_metadata_old(call, md, NUM2UINT(flags));
129
+ if (err != GRPC_CALL_OK) {
130
+ rb_raise(rb_eCallError, "add metadata failed: %s (code=%d)",
131
+ grpc_call_error_detail_of(err), err);
132
+ return ST_STOP;
133
+ }
134
+ }
135
+ } else {
136
+ md_obj_args[1] = val;
137
+ md_obj = rb_class_new_instance(2, md_obj_args, rb_cMetadata);
138
+ md = grpc_rb_get_wrapped_metadata(md_obj);
139
+ err = grpc_call_add_metadata_old(call, md, NUM2UINT(flags));
140
+ if (err != GRPC_CALL_OK) {
141
+ rb_raise(rb_eCallError, "add metadata failed: %s (code=%d)",
142
+ grpc_call_error_detail_of(err), err);
143
+ return ST_STOP;
144
+ }
145
+ }
146
+
147
+ return ST_CONTINUE;
148
+ }
149
+
150
+ /*
151
+ call-seq:
152
+ call.add_metadata(completion_queue, hash_elements, flags=nil)
153
+
154
+ Add metadata elements to the call from a ruby hash, to be sent upon
155
+ invocation. flags is a bit-field combination of the write flags defined
156
+ above. REQUIRES: grpc_call_invoke/grpc_call_accept have not been
157
+ called on this call. Produces no events. */
158
+
159
+ static VALUE grpc_rb_call_add_metadata(int argc, VALUE *argv, VALUE self) {
160
+ VALUE metadata;
161
+ VALUE flags = Qnil;
162
+ ID id_size = rb_intern("size");
163
+
164
+ /* "11" == 1 mandatory args, 1 (flags) is optional */
165
+ rb_scan_args(argc, argv, "11", &metadata, &flags);
166
+ if (NIL_P(flags)) {
167
+ flags = UINT2NUM(0); /* Default to no flags */
168
+ }
169
+ if (TYPE(metadata) != T_HASH) {
170
+ rb_raise(rb_eTypeError, "add metadata failed: metadata should be a hash");
171
+ return Qnil;
172
+ }
173
+ if (NUM2UINT(rb_funcall(metadata, id_size, 0)) == 0) {
174
+ return Qnil;
175
+ }
176
+ rb_ivar_set(self, id_flags, flags);
177
+ rb_ivar_set(self, id_input_md, metadata);
178
+ rb_hash_foreach(metadata, grpc_rb_call_add_metadata_hash_cb, self);
179
+ return Qnil;
180
+ }
181
+
182
+ /* Called by clients to cancel an RPC on the server.
183
+ Can be called multiple times, from any thread. */
184
+ static VALUE grpc_rb_call_cancel(VALUE self) {
185
+ grpc_call *call = NULL;
186
+ grpc_call_error err;
187
+ Data_Get_Struct(self, grpc_call, call);
188
+ err = grpc_call_cancel(call);
189
+ if (err != GRPC_CALL_OK) {
190
+ rb_raise(rb_eCallError, "cancel failed: %s (code=%d)",
191
+ grpc_call_error_detail_of(err), err);
192
+ }
193
+
194
+ return Qnil;
195
+ }
196
+
197
+ /*
198
+ call-seq:
199
+ call.invoke(completion_queue, tag, flags=nil)
200
+
201
+ Invoke the RPC. Starts sending metadata and request headers on the wire.
202
+ flags is a bit-field combination of the write flags defined above.
203
+ REQUIRES: Can be called at most once per call.
204
+ Can only be called on the client.
205
+ Produces a GRPC_INVOKE_ACCEPTED event on completion. */
206
+ static VALUE grpc_rb_call_invoke(int argc, VALUE *argv, VALUE self) {
207
+ VALUE cqueue = Qnil;
208
+ VALUE metadata_read_tag = Qnil;
209
+ VALUE finished_tag = Qnil;
210
+ VALUE flags = Qnil;
211
+ grpc_call *call = NULL;
212
+ grpc_completion_queue *cq = NULL;
213
+ grpc_call_error err;
214
+
215
+ /* "31" == 3 mandatory args, 1 (flags) is optional */
216
+ rb_scan_args(argc, argv, "31", &cqueue, &metadata_read_tag, &finished_tag,
217
+ &flags);
218
+ if (NIL_P(flags)) {
219
+ flags = UINT2NUM(0); /* Default to no flags */
220
+ }
221
+ cq = grpc_rb_get_wrapped_completion_queue(cqueue);
222
+ Data_Get_Struct(self, grpc_call, call);
223
+ err = grpc_call_invoke_old(call, cq, ROBJECT(metadata_read_tag),
224
+ ROBJECT(finished_tag), NUM2UINT(flags));
225
+ if (err != GRPC_CALL_OK) {
226
+ rb_raise(rb_eCallError, "invoke failed: %s (code=%d)",
227
+ grpc_call_error_detail_of(err), err);
228
+ }
229
+
230
+ /* Add the completion queue as an instance attribute, prevents it from being
231
+ * GCed until this call object is GCed */
232
+ rb_ivar_set(self, id_cq, cqueue);
233
+
234
+ return Qnil;
235
+ }
236
+
237
+ /* Initiate a read on a call. Output event contains a byte buffer with the
238
+ result of the read.
239
+ REQUIRES: No other reads are pending on the call. It is only safe to start
240
+ the next read after the corresponding read event is received. */
241
+ static VALUE grpc_rb_call_start_read(VALUE self, VALUE tag) {
242
+ grpc_call *call = NULL;
243
+ grpc_call_error err;
244
+ Data_Get_Struct(self, grpc_call, call);
245
+ err = grpc_call_start_read_old(call, ROBJECT(tag));
246
+ if (err != GRPC_CALL_OK) {
247
+ rb_raise(rb_eCallError, "start read failed: %s (code=%d)",
248
+ grpc_call_error_detail_of(err), err);
249
+ }
250
+
251
+ return Qnil;
252
+ }
253
+
254
+ /*
255
+ call-seq:
256
+ status = call.status
257
+
258
+ Gets the status object saved the call. */
259
+ static VALUE grpc_rb_call_get_status(VALUE self) {
260
+ return rb_ivar_get(self, id_status);
261
+ }
262
+
263
+ /*
264
+ call-seq:
265
+ call.status = status
266
+
267
+ Saves a status object on the call. */
268
+ static VALUE grpc_rb_call_set_status(VALUE self, VALUE status) {
269
+ if (!NIL_P(status) && rb_obj_class(status) != rb_sStatus) {
270
+ rb_raise(rb_eTypeError, "bad status: got:<%s> want: <Struct::Status>",
271
+ rb_obj_classname(status));
272
+ return Qnil;
273
+ }
274
+
275
+ return rb_ivar_set(self, id_status, status);
276
+ }
277
+
278
+ /*
279
+ call-seq:
280
+ metadata = call.metadata
281
+
282
+ Gets the metadata object saved the call. */
283
+ static VALUE grpc_rb_call_get_metadata(VALUE self) {
284
+ return rb_ivar_get(self, id_metadata);
285
+ }
286
+
287
+ /*
288
+ call-seq:
289
+ call.metadata = metadata
290
+
291
+ Saves the metadata hash on the call. */
292
+ static VALUE grpc_rb_call_set_metadata(VALUE self, VALUE metadata) {
293
+ if (!NIL_P(metadata) && TYPE(metadata) != T_HASH) {
294
+ rb_raise(rb_eTypeError, "bad metadata: got:<%s> want: <Hash>",
295
+ rb_obj_classname(metadata));
296
+ return Qnil;
297
+ }
298
+
299
+ return rb_ivar_set(self, id_metadata, metadata);
300
+ }
301
+
302
+ /*
303
+ call-seq:
304
+ call.start_write(byte_buffer, tag, flags=nil)
305
+
306
+ Queue a byte buffer for writing.
307
+ flags is a bit-field combination of the write flags defined above.
308
+ A write with byte_buffer null is allowed, and will not send any bytes on the
309
+ wire. If this is performed without GRPC_WRITE_BUFFER_HINT flag it provides
310
+ a mechanism to flush any previously buffered writes to outgoing flow control.
311
+ REQUIRES: No other writes are pending on the call. It is only safe to
312
+ start the next write after the corresponding write_accepted event
313
+ is received.
314
+ GRPC_INVOKE_ACCEPTED must have been received by the application
315
+ prior to calling this on the client. On the server,
316
+ grpc_call_accept must have been called successfully.
317
+ Produces a GRPC_WRITE_ACCEPTED event. */
318
+ static VALUE grpc_rb_call_start_write(int argc, VALUE *argv, VALUE self) {
319
+ VALUE byte_buffer = Qnil;
320
+ VALUE tag = Qnil;
321
+ VALUE flags = Qnil;
322
+ grpc_call *call = NULL;
323
+ grpc_byte_buffer *bfr = NULL;
324
+ grpc_call_error err;
325
+
326
+ /* "21" == 2 mandatory args, 1 (flags) is optional */
327
+ rb_scan_args(argc, argv, "21", &byte_buffer, &tag, &flags);
328
+ if (NIL_P(flags)) {
329
+ flags = UINT2NUM(0); /* Default to no flags */
330
+ }
331
+ bfr = grpc_rb_get_wrapped_byte_buffer(byte_buffer);
332
+ Data_Get_Struct(self, grpc_call, call);
333
+ err = grpc_call_start_write_old(call, bfr, ROBJECT(tag), NUM2UINT(flags));
334
+ if (err != GRPC_CALL_OK) {
335
+ rb_raise(rb_eCallError, "start write failed: %s (code=%d)",
336
+ grpc_call_error_detail_of(err), err);
337
+ }
338
+
339
+ return Qnil;
340
+ }
341
+
342
+ /* Queue a status for writing.
343
+
344
+ call-seq:
345
+ tag = Object.new
346
+ call.write_status(200, "OK", tag)
347
+
348
+ REQUIRES: No other writes are pending on the call. It is only safe to
349
+ start the next write after the corresponding write_accepted event
350
+ is received.
351
+ GRPC_INVOKE_ACCEPTED must have been received by the application
352
+ prior to calling this.
353
+ Only callable on the server.
354
+ Produces a GRPC_FINISHED event when the status is sent and the stream is
355
+ fully closed */
356
+ static VALUE grpc_rb_call_start_write_status(VALUE self, VALUE code,
357
+ VALUE status, VALUE tag) {
358
+ grpc_call *call = NULL;
359
+ grpc_call_error err;
360
+ Data_Get_Struct(self, grpc_call, call);
361
+ err = grpc_call_start_write_status_old(call, NUM2UINT(code),
362
+ StringValueCStr(status), ROBJECT(tag));
363
+ if (err != GRPC_CALL_OK) {
364
+ rb_raise(rb_eCallError, "start write status: %s (code=%d)",
365
+ grpc_call_error_detail_of(err), err);
366
+ }
367
+
368
+ return Qnil;
369
+ }
370
+
371
+ /* No more messages to send.
372
+ REQUIRES: No other writes are pending on the call. */
373
+ static VALUE grpc_rb_call_writes_done(VALUE self, VALUE tag) {
374
+ grpc_call *call = NULL;
375
+ grpc_call_error err;
376
+ Data_Get_Struct(self, grpc_call, call);
377
+ err = grpc_call_writes_done_old(call, ROBJECT(tag));
378
+ if (err != GRPC_CALL_OK) {
379
+ rb_raise(rb_eCallError, "writes done: %s (code=%d)",
380
+ grpc_call_error_detail_of(err), err);
381
+ }
382
+
383
+ return Qnil;
384
+ }
385
+
386
+ /* call-seq:
387
+ call.server_end_initial_metadata(flag)
388
+
389
+ Only to be called on servers, before sending messages.
390
+ flags is a bit-field combination of the write flags defined above.
391
+
392
+ REQUIRES: Can be called at most once per call.
393
+ Can only be called on the server, must be called after
394
+ grpc_call_server_accept
395
+ Produces no events */
396
+ static VALUE grpc_rb_call_server_end_initial_metadata(int argc, VALUE *argv,
397
+ VALUE self) {
398
+ VALUE flags = Qnil;
399
+ grpc_call *call = NULL;
400
+ grpc_call_error err;
401
+
402
+ /* "01" == 1 (flags) is optional */
403
+ rb_scan_args(argc, argv, "01", &flags);
404
+ if (NIL_P(flags)) {
405
+ flags = UINT2NUM(0); /* Default to no flags */
406
+ }
407
+ Data_Get_Struct(self, grpc_call, call);
408
+ err = grpc_call_server_end_initial_metadata_old(call, NUM2UINT(flags));
409
+ if (err != GRPC_CALL_OK) {
410
+ rb_raise(rb_eCallError, "end_initial_metadata failed: %s (code=%d)",
411
+ grpc_call_error_detail_of(err), err);
412
+ }
413
+ return Qnil;
414
+ }
415
+
416
+ /* call-seq:
417
+ call.server_accept(completion_queue, finished_tag)
418
+
419
+ Accept an incoming RPC, binding a completion queue to it.
420
+ To be called before sending or receiving messages.
421
+
422
+ REQUIRES: Can be called at most once per call.
423
+ Can only be called on the server.
424
+ Produces a GRPC_FINISHED event with finished_tag when the call has been
425
+ completed (there may be other events for the call pending at this
426
+ time) */
427
+ static VALUE grpc_rb_call_server_accept(VALUE self, VALUE cqueue,
428
+ VALUE finished_tag) {
429
+ grpc_call *call = NULL;
430
+ grpc_completion_queue *cq = grpc_rb_get_wrapped_completion_queue(cqueue);
431
+ grpc_call_error err;
432
+ Data_Get_Struct(self, grpc_call, call);
433
+ err = grpc_call_server_accept_old(call, cq, ROBJECT(finished_tag));
434
+ if (err != GRPC_CALL_OK) {
435
+ rb_raise(rb_eCallError, "server_accept failed: %s (code=%d)",
436
+ grpc_call_error_detail_of(err), err);
437
+ }
438
+
439
+ /* Add the completion queue as an instance attribute, prevents it from being
440
+ * GCed until this call object is GCed */
441
+ rb_ivar_set(self, id_cq, cqueue);
442
+ return Qnil;
443
+ }
444
+
445
+ /* rb_cCall is the ruby class that proxies grpc_call. */
446
+ VALUE rb_cCall = Qnil;
447
+
448
+ /* rb_eCallError is the ruby class of the exception thrown during call
449
+ operations; */
450
+ VALUE rb_eCallError = Qnil;
451
+
452
+ void Init_grpc_error_codes() {
453
+ /* Constants representing the error codes of grpc_call_error in grpc.h */
454
+ VALUE rb_RpcErrors = rb_define_module_under(rb_mGrpcCore, "RpcErrors");
455
+ rb_define_const(rb_RpcErrors, "OK", UINT2NUM(GRPC_CALL_OK));
456
+ rb_define_const(rb_RpcErrors, "ERROR", UINT2NUM(GRPC_CALL_ERROR));
457
+ rb_define_const(rb_RpcErrors, "NOT_ON_SERVER",
458
+ UINT2NUM(GRPC_CALL_ERROR_NOT_ON_SERVER));
459
+ rb_define_const(rb_RpcErrors, "NOT_ON_CLIENT",
460
+ UINT2NUM(GRPC_CALL_ERROR_NOT_ON_CLIENT));
461
+ rb_define_const(rb_RpcErrors, "ALREADY_ACCEPTED",
462
+ UINT2NUM(GRPC_CALL_ERROR_ALREADY_ACCEPTED));
463
+ rb_define_const(rb_RpcErrors, "ALREADY_INVOKED",
464
+ UINT2NUM(GRPC_CALL_ERROR_ALREADY_INVOKED));
465
+ rb_define_const(rb_RpcErrors, "NOT_INVOKED",
466
+ UINT2NUM(GRPC_CALL_ERROR_NOT_INVOKED));
467
+ rb_define_const(rb_RpcErrors, "ALREADY_FINISHED",
468
+ UINT2NUM(GRPC_CALL_ERROR_ALREADY_FINISHED));
469
+ rb_define_const(rb_RpcErrors, "TOO_MANY_OPERATIONS",
470
+ UINT2NUM(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS));
471
+ rb_define_const(rb_RpcErrors, "INVALID_FLAGS",
472
+ UINT2NUM(GRPC_CALL_ERROR_INVALID_FLAGS));
473
+
474
+ /* Add the detail strings to a Hash */
475
+ rb_error_code_details = rb_hash_new();
476
+ rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_OK),
477
+ rb_str_new2("ok"));
478
+ rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR),
479
+ rb_str_new2("unknown error"));
480
+ rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_NOT_ON_SERVER),
481
+ rb_str_new2("not available on a server"));
482
+ rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_NOT_ON_CLIENT),
483
+ rb_str_new2("not available on a client"));
484
+ rb_hash_aset(rb_error_code_details,
485
+ UINT2NUM(GRPC_CALL_ERROR_ALREADY_ACCEPTED),
486
+ rb_str_new2("call is already accepted"));
487
+ rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_ALREADY_INVOKED),
488
+ rb_str_new2("call is already invoked"));
489
+ rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_NOT_INVOKED),
490
+ rb_str_new2("call is not yet invoked"));
491
+ rb_hash_aset(rb_error_code_details,
492
+ UINT2NUM(GRPC_CALL_ERROR_ALREADY_FINISHED),
493
+ rb_str_new2("call is already finished"));
494
+ rb_hash_aset(rb_error_code_details,
495
+ UINT2NUM(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS),
496
+ rb_str_new2("outstanding read or write present"));
497
+ rb_hash_aset(rb_error_code_details, UINT2NUM(GRPC_CALL_ERROR_INVALID_FLAGS),
498
+ rb_str_new2("a bad flag was given"));
499
+ rb_define_const(rb_RpcErrors, "ErrorMessages", rb_error_code_details);
500
+ rb_obj_freeze(rb_error_code_details);
501
+ }
502
+
503
+ void Init_grpc_call() {
504
+ /* CallError inherits from Exception to signal that it is non-recoverable */
505
+ rb_eCallError =
506
+ rb_define_class_under(rb_mGrpcCore, "CallError", rb_eException);
507
+ rb_cCall = rb_define_class_under(rb_mGrpcCore, "Call", rb_cObject);
508
+
509
+ /* Prevent allocation or inialization of the Call class */
510
+ rb_define_alloc_func(rb_cCall, grpc_rb_cannot_alloc);
511
+ rb_define_method(rb_cCall, "initialize", grpc_rb_cannot_init, 0);
512
+ rb_define_method(rb_cCall, "initialize_copy", grpc_rb_cannot_init_copy, 1);
513
+
514
+ /* Add ruby analogues of the Call methods. */
515
+ rb_define_method(rb_cCall, "server_accept", grpc_rb_call_server_accept, 2);
516
+ rb_define_method(rb_cCall, "server_end_initial_metadata",
517
+ grpc_rb_call_server_end_initial_metadata, -1);
518
+ rb_define_method(rb_cCall, "add_metadata", grpc_rb_call_add_metadata, -1);
519
+ rb_define_method(rb_cCall, "cancel", grpc_rb_call_cancel, 0);
520
+ rb_define_method(rb_cCall, "invoke", grpc_rb_call_invoke, -1);
521
+ rb_define_method(rb_cCall, "start_read", grpc_rb_call_start_read, 1);
522
+ rb_define_method(rb_cCall, "start_write", grpc_rb_call_start_write, -1);
523
+ rb_define_method(rb_cCall, "start_write_status",
524
+ grpc_rb_call_start_write_status, 3);
525
+ rb_define_method(rb_cCall, "writes_done", grpc_rb_call_writes_done, 1);
526
+ rb_define_method(rb_cCall, "status", grpc_rb_call_get_status, 0);
527
+ rb_define_method(rb_cCall, "status=", grpc_rb_call_set_status, 1);
528
+ rb_define_method(rb_cCall, "metadata", grpc_rb_call_get_metadata, 0);
529
+ rb_define_method(rb_cCall, "metadata=", grpc_rb_call_set_metadata, 1);
530
+
531
+ /* Ids used to support call attributes */
532
+ id_metadata = rb_intern("metadata");
533
+ id_status = rb_intern("status");
534
+
535
+ /* Ids used by the c wrapping internals. */
536
+ id_cq = rb_intern("__cq");
537
+ id_flags = rb_intern("__flags");
538
+ id_input_md = rb_intern("__input_md");
539
+
540
+ /* The hash for reference counting calls, to ensure they can't be destroyed
541
+ * more than once */
542
+ hash_all_calls = rb_hash_new();
543
+ rb_define_const(rb_cCall, "INTERNAL_ALL_CALLs", hash_all_calls);
544
+
545
+ Init_grpc_error_codes();
546
+ }
547
+
548
+ /* Gets the call from the ruby object */
549
+ grpc_call *grpc_rb_get_wrapped_call(VALUE v) {
550
+ grpc_call *c = NULL;
551
+ Data_Get_Struct(v, grpc_call, c);
552
+ return c;
553
+ }
554
+
555
+ /* Obtains the wrapped object for a given call */
556
+ VALUE grpc_rb_wrap_call(grpc_call *c) {
557
+ VALUE obj = Qnil;
558
+ if (c == NULL) {
559
+ return Qnil;
560
+ }
561
+ obj = rb_hash_aref(hash_all_calls, OFFT2NUM((VALUE)c));
562
+ if (obj == Qnil) { /* Not in the hash add it */
563
+ rb_hash_aset(hash_all_calls, OFFT2NUM((VALUE)c), UINT2NUM(1));
564
+ } else {
565
+ rb_hash_aset(hash_all_calls, OFFT2NUM((VALUE)c),
566
+ UINT2NUM(NUM2UINT(obj) + 1));
567
+ }
568
+ return Data_Wrap_Struct(rb_cCall, GC_NOT_MARKED, grpc_rb_call_destroy, c);
569
+ }