grpc 0.6.0 → 0.6.1

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.rubocop_todo.yml +12 -20
  4. data/CHANGELOG.md +11 -0
  5. data/Rakefile +1 -0
  6. data/bin/apis/pubsub_demo.rb +3 -6
  7. data/bin/interop/interop_client.rb +43 -3
  8. data/bin/interop/interop_server.rb +1 -1
  9. data/bin/math_server.rb +1 -1
  10. data/bin/noproto_server.rb +1 -1
  11. data/ext/grpc/rb_byte_buffer.c +15 -189
  12. data/ext/grpc/rb_byte_buffer.h +4 -12
  13. data/ext/grpc/rb_call.c +514 -307
  14. data/ext/grpc/rb_call.h +4 -4
  15. data/ext/grpc/rb_channel.c +58 -34
  16. data/ext/grpc/rb_channel.h +0 -3
  17. data/ext/grpc/rb_channel_args.c +13 -4
  18. data/ext/grpc/rb_completion_queue.c +50 -23
  19. data/ext/grpc/rb_completion_queue.h +7 -3
  20. data/ext/grpc/rb_credentials.c +40 -28
  21. data/ext/grpc/rb_credentials.h +0 -4
  22. data/ext/grpc/rb_grpc.c +86 -67
  23. data/ext/grpc/rb_grpc.h +20 -10
  24. data/ext/grpc/rb_server.c +119 -26
  25. data/ext/grpc/rb_server.h +0 -4
  26. data/ext/grpc/rb_server_credentials.c +29 -16
  27. data/ext/grpc/rb_server_credentials.h +0 -4
  28. data/grpc.gemspec +11 -8
  29. data/lib/grpc.rb +1 -1
  30. data/lib/grpc/errors.rb +8 -7
  31. data/lib/grpc/generic/active_call.rb +104 -171
  32. data/lib/grpc/generic/bidi_call.rb +32 -60
  33. data/lib/grpc/generic/client_stub.rb +42 -31
  34. data/lib/grpc/generic/rpc_desc.rb +7 -12
  35. data/lib/grpc/generic/rpc_server.rb +253 -170
  36. data/lib/grpc/{core/event.rb → notifier.rb} +25 -9
  37. data/lib/grpc/version.rb +1 -1
  38. data/spec/call_spec.rb +23 -40
  39. data/spec/channel_spec.rb +11 -20
  40. data/spec/client_server_spec.rb +193 -175
  41. data/spec/credentials_spec.rb +2 -2
  42. data/spec/generic/active_call_spec.rb +59 -85
  43. data/spec/generic/client_stub_spec.rb +46 -64
  44. data/spec/generic/rpc_desc_spec.rb +50 -80
  45. data/spec/generic/rpc_server_pool_spec.rb +2 -3
  46. data/spec/generic/rpc_server_spec.rb +158 -29
  47. data/spec/server_spec.rb +1 -1
  48. data/spec/spec_helper.rb +8 -4
  49. metadata +27 -37
  50. data/ext/grpc/rb_event.c +0 -361
  51. data/ext/grpc/rb_event.h +0 -53
  52. data/ext/grpc/rb_metadata.c +0 -215
  53. data/ext/grpc/rb_metadata.h +0 -53
  54. data/spec/alloc_spec.rb +0 -44
  55. data/spec/byte_buffer_spec.rb +0 -67
  56. data/spec/event_spec.rb +0 -53
  57. data/spec/metadata_spec.rb +0 -64
@@ -37,10 +37,6 @@
37
37
  #include <ruby.h>
38
38
  #include <grpc/grpc_security.h>
39
39
 
40
- /* rb_cCredentials is the ruby class whose instances proxy
41
- grpc_credentials. */
42
- extern VALUE rb_cCredentials;
43
-
44
40
  /* Initializes the ruby Credentials class. */
45
41
  void Init_grpc_credentials();
46
42
 
@@ -34,26 +34,27 @@
34
34
  #include "rb_grpc.h"
35
35
 
36
36
  #include <math.h>
37
- #include <ruby.h>
37
+ #include <ruby/ruby.h>
38
+ #include <ruby/vm.h>
38
39
  #include <sys/time.h>
39
40
 
40
41
  #include <grpc/grpc.h>
41
42
  #include <grpc/support/time.h>
42
- #include "rb_byte_buffer.h"
43
43
  #include "rb_call.h"
44
44
  #include "rb_channel.h"
45
45
  #include "rb_completion_queue.h"
46
- #include "rb_event.h"
47
- #include "rb_metadata.h"
48
46
  #include "rb_server.h"
49
47
  #include "rb_credentials.h"
50
48
  #include "rb_server_credentials.h"
51
49
 
52
- /* Define common vars and funcs declared in rb.h */
53
- const RUBY_DATA_FUNC GC_NOT_MARKED = NULL;
54
- const RUBY_DATA_FUNC GC_DONT_FREE = NULL;
50
+ static VALUE grpc_rb_cTimeVal = Qnil;
55
51
 
56
- VALUE rb_cTimeVal = Qnil;
52
+ static rb_data_type_t grpc_rb_timespec_data_type = {
53
+ "gpr_timespec",
54
+ {GRPC_RB_GC_NOT_MARKED, GRPC_RB_GC_DONT_FREE, GRPC_RB_MEMSIZE_UNAVAILABLE},
55
+ NULL,
56
+ NULL,
57
+ RUBY_TYPED_FREE_IMMEDIATELY};
57
58
 
58
59
  /* Alloc func that blocks allocation of a given object by raising an
59
60
  * exception. */
@@ -99,8 +100,9 @@ gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) {
99
100
 
100
101
  switch (TYPE(time)) {
101
102
  case T_DATA:
102
- if (CLASS_OF(time) == rb_cTimeVal) {
103
- Data_Get_Struct(time, gpr_timespec, time_const);
103
+ if (CLASS_OF(time) == grpc_rb_cTimeVal) {
104
+ TypedData_Get_Struct(time, gpr_timespec, &grpc_rb_timespec_data_type,
105
+ time_const);
104
106
  t = *time_const;
105
107
  } else if (CLASS_OF(time) == rb_cTime) {
106
108
  t.tv_sec = NUM2INT(rb_funcall(time, id_tv_sec, 0));
@@ -153,37 +155,43 @@ gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) {
153
155
  return t;
154
156
  }
155
157
 
156
- void Init_grpc_status_codes() {
158
+ static void Init_grpc_status_codes() {
157
159
  /* Constants representing the status codes or grpc_status_code in status.h */
158
- VALUE rb_mStatusCodes =
159
- rb_define_module_under(rb_mGrpcCore, "StatusCodes");
160
- rb_define_const(rb_mStatusCodes, "OK", INT2NUM(GRPC_STATUS_OK));
161
- rb_define_const(rb_mStatusCodes, "CANCELLED", INT2NUM(GRPC_STATUS_CANCELLED));
162
- rb_define_const(rb_mStatusCodes, "UNKNOWN", INT2NUM(GRPC_STATUS_UNKNOWN));
163
- rb_define_const(rb_mStatusCodes, "INVALID_ARGUMENT",
160
+ VALUE grpc_rb_mStatusCodes =
161
+ rb_define_module_under(grpc_rb_mGrpcCore, "StatusCodes");
162
+ rb_define_const(grpc_rb_mStatusCodes, "OK", INT2NUM(GRPC_STATUS_OK));
163
+ rb_define_const(grpc_rb_mStatusCodes, "CANCELLED",
164
+ INT2NUM(GRPC_STATUS_CANCELLED));
165
+ rb_define_const(grpc_rb_mStatusCodes, "UNKNOWN",
166
+ INT2NUM(GRPC_STATUS_UNKNOWN));
167
+ rb_define_const(grpc_rb_mStatusCodes, "INVALID_ARGUMENT",
164
168
  INT2NUM(GRPC_STATUS_INVALID_ARGUMENT));
165
- rb_define_const(rb_mStatusCodes, "DEADLINE_EXCEEDED",
169
+ rb_define_const(grpc_rb_mStatusCodes, "DEADLINE_EXCEEDED",
166
170
  INT2NUM(GRPC_STATUS_DEADLINE_EXCEEDED));
167
- rb_define_const(rb_mStatusCodes, "NOT_FOUND", INT2NUM(GRPC_STATUS_NOT_FOUND));
168
- rb_define_const(rb_mStatusCodes, "ALREADY_EXISTS",
171
+ rb_define_const(grpc_rb_mStatusCodes, "NOT_FOUND",
172
+ INT2NUM(GRPC_STATUS_NOT_FOUND));
173
+ rb_define_const(grpc_rb_mStatusCodes, "ALREADY_EXISTS",
169
174
  INT2NUM(GRPC_STATUS_ALREADY_EXISTS));
170
- rb_define_const(rb_mStatusCodes, "PERMISSION_DENIED",
175
+ rb_define_const(grpc_rb_mStatusCodes, "PERMISSION_DENIED",
171
176
  INT2NUM(GRPC_STATUS_PERMISSION_DENIED));
172
- rb_define_const(rb_mStatusCodes, "UNAUTHENTICATED",
177
+ rb_define_const(grpc_rb_mStatusCodes, "UNAUTHENTICATED",
173
178
  INT2NUM(GRPC_STATUS_UNAUTHENTICATED));
174
- rb_define_const(rb_mStatusCodes, "RESOURCE_EXHAUSTED",
179
+ rb_define_const(grpc_rb_mStatusCodes, "RESOURCE_EXHAUSTED",
175
180
  INT2NUM(GRPC_STATUS_RESOURCE_EXHAUSTED));
176
- rb_define_const(rb_mStatusCodes, "FAILED_PRECONDITION",
181
+ rb_define_const(grpc_rb_mStatusCodes, "FAILED_PRECONDITION",
177
182
  INT2NUM(GRPC_STATUS_FAILED_PRECONDITION));
178
- rb_define_const(rb_mStatusCodes, "ABORTED", INT2NUM(GRPC_STATUS_ABORTED));
179
- rb_define_const(rb_mStatusCodes, "OUT_OF_RANGE",
183
+ rb_define_const(grpc_rb_mStatusCodes, "ABORTED",
184
+ INT2NUM(GRPC_STATUS_ABORTED));
185
+ rb_define_const(grpc_rb_mStatusCodes, "OUT_OF_RANGE",
180
186
  INT2NUM(GRPC_STATUS_OUT_OF_RANGE));
181
- rb_define_const(rb_mStatusCodes, "UNIMPLEMENTED",
187
+ rb_define_const(grpc_rb_mStatusCodes, "UNIMPLEMENTED",
182
188
  INT2NUM(GRPC_STATUS_UNIMPLEMENTED));
183
- rb_define_const(rb_mStatusCodes, "INTERNAL", INT2NUM(GRPC_STATUS_INTERNAL));
184
- rb_define_const(rb_mStatusCodes, "UNAVAILABLE",
189
+ rb_define_const(grpc_rb_mStatusCodes, "INTERNAL",
190
+ INT2NUM(GRPC_STATUS_INTERNAL));
191
+ rb_define_const(grpc_rb_mStatusCodes, "UNAVAILABLE",
185
192
  INT2NUM(GRPC_STATUS_UNAVAILABLE));
186
- rb_define_const(rb_mStatusCodes, "DATA_LOSS", INT2NUM(GRPC_STATUS_DATA_LOSS));
193
+ rb_define_const(grpc_rb_mStatusCodes, "DATA_LOSS",
194
+ INT2NUM(GRPC_STATUS_DATA_LOSS));
187
195
  }
188
196
 
189
197
  /* id_at is the constructor method of the ruby standard Time class. */
@@ -195,42 +203,46 @@ static ID id_inspect;
195
203
  /* id_to_s is the to_s method found on various ruby objects. */
196
204
  static ID id_to_s;
197
205
 
198
- /* Converts `a wrapped time constant to a standard time. */
199
- VALUE grpc_rb_time_val_to_time(VALUE self) {
206
+ /* Converts a wrapped time constant to a standard time. */
207
+ static VALUE grpc_rb_time_val_to_time(VALUE self) {
200
208
  gpr_timespec *time_const = NULL;
201
- Data_Get_Struct(self, gpr_timespec, time_const);
209
+ TypedData_Get_Struct(self, gpr_timespec, &grpc_rb_timespec_data_type,
210
+ time_const);
202
211
  return rb_funcall(rb_cTime, id_at, 2, INT2NUM(time_const->tv_sec),
203
212
  INT2NUM(time_const->tv_nsec));
204
213
  }
205
214
 
206
215
  /* Invokes inspect on the ctime version of the time val. */
207
- VALUE grpc_rb_time_val_inspect(VALUE self) {
216
+ static VALUE grpc_rb_time_val_inspect(VALUE self) {
208
217
  return rb_funcall(grpc_rb_time_val_to_time(self), id_inspect, 0);
209
218
  }
210
219
 
211
220
  /* Invokes to_s on the ctime version of the time val. */
212
- VALUE grpc_rb_time_val_to_s(VALUE self) {
221
+ static VALUE grpc_rb_time_val_to_s(VALUE self) {
213
222
  return rb_funcall(grpc_rb_time_val_to_time(self), id_to_s, 0);
214
223
  }
215
224
 
216
225
  /* Adds a module with constants that map to gpr's static timeval structs. */
217
- void Init_grpc_time_consts() {
218
- VALUE rb_mTimeConsts =
219
- rb_define_module_under(rb_mGrpcCore, "TimeConsts");
220
- rb_cTimeVal =
221
- rb_define_class_under(rb_mGrpcCore, "TimeSpec", rb_cObject);
222
- rb_define_const(rb_mTimeConsts, "ZERO",
223
- Data_Wrap_Struct(rb_cTimeVal, GC_NOT_MARKED, GC_DONT_FREE,
224
- (void *)&gpr_time_0));
225
- rb_define_const(rb_mTimeConsts, "INFINITE_FUTURE",
226
- Data_Wrap_Struct(rb_cTimeVal, GC_NOT_MARKED, GC_DONT_FREE,
227
- (void *)&gpr_inf_future));
228
- rb_define_const(rb_mTimeConsts, "INFINITE_PAST",
229
- Data_Wrap_Struct(rb_cTimeVal, GC_NOT_MARKED, GC_DONT_FREE,
230
- (void *)&gpr_inf_past));
231
- rb_define_method(rb_cTimeVal, "to_time", grpc_rb_time_val_to_time, 0);
232
- rb_define_method(rb_cTimeVal, "inspect", grpc_rb_time_val_inspect, 0);
233
- rb_define_method(rb_cTimeVal, "to_s", grpc_rb_time_val_to_s, 0);
226
+ static void Init_grpc_time_consts() {
227
+ VALUE grpc_rb_mTimeConsts =
228
+ rb_define_module_under(grpc_rb_mGrpcCore, "TimeConsts");
229
+ grpc_rb_cTimeVal =
230
+ rb_define_class_under(grpc_rb_mGrpcCore, "TimeSpec", rb_cObject);
231
+ rb_define_const(
232
+ grpc_rb_mTimeConsts, "ZERO",
233
+ TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
234
+ (void *)&gpr_time_0));
235
+ rb_define_const(
236
+ grpc_rb_mTimeConsts, "INFINITE_FUTURE",
237
+ TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
238
+ (void *)&gpr_inf_future));
239
+ rb_define_const(
240
+ grpc_rb_mTimeConsts, "INFINITE_PAST",
241
+ TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type,
242
+ (void *)&gpr_inf_past));
243
+ rb_define_method(grpc_rb_cTimeVal, "to_time", grpc_rb_time_val_to_time, 0);
244
+ rb_define_method(grpc_rb_cTimeVal, "inspect", grpc_rb_time_val_inspect, 0);
245
+ rb_define_method(grpc_rb_cTimeVal, "to_s", grpc_rb_time_val_to_s, 0);
234
246
  id_at = rb_intern("at");
235
247
  id_inspect = rb_intern("inspect");
236
248
  id_to_s = rb_intern("to_s");
@@ -238,35 +250,42 @@ void Init_grpc_time_consts() {
238
250
  id_tv_nsec = rb_intern("tv_nsec");
239
251
  }
240
252
 
241
- void grpc_rb_shutdown(void *vm) { grpc_shutdown(); }
253
+ static void grpc_rb_shutdown(ruby_vm_t *vm) { grpc_shutdown(); }
242
254
 
243
255
  /* Initialize the GRPC module structs */
244
256
 
245
- /* rb_sNewServerRpc is the struct that holds new server rpc details. */
246
- VALUE rb_sNewServerRpc = Qnil;
247
- /* rb_sStatus is the struct that holds status details. */
248
- VALUE rb_sStatus = Qnil;
257
+ /* grpc_rb_sNewServerRpc is the struct that holds new server rpc details. */
258
+ VALUE grpc_rb_sNewServerRpc = Qnil;
259
+ /* grpc_rb_sStatus is the struct that holds status details. */
260
+ VALUE grpc_rb_sStatus = Qnil;
249
261
 
250
262
  /* Initialize the GRPC module. */
251
- VALUE rb_mGRPC = Qnil;
252
- VALUE rb_mGrpcCore = Qnil;
263
+ VALUE grpc_rb_mGRPC = Qnil;
264
+ VALUE grpc_rb_mGrpcCore = Qnil;
265
+
266
+ /* cached Symbols for members in Status struct */
267
+ VALUE sym_code = Qundef;
268
+ VALUE sym_details = Qundef;
269
+ VALUE sym_metadata = Qundef;
253
270
 
254
271
  void Init_grpc() {
255
272
  grpc_init();
256
273
  ruby_vm_at_exit(grpc_rb_shutdown);
257
- rb_mGRPC = rb_define_module("GRPC");
258
- rb_mGrpcCore = rb_define_module_under(rb_mGRPC, "Core");
259
- rb_sNewServerRpc = rb_struct_define("NewServerRpc", "method", "host",
260
- "deadline", "metadata", NULL);
261
- rb_sStatus = rb_struct_define("Status", "code", "details", "metadata", NULL);
274
+ grpc_rb_mGRPC = rb_define_module("GRPC");
275
+ grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core");
276
+ grpc_rb_sNewServerRpc =
277
+ rb_struct_define("NewServerRpc", "method", "host",
278
+ "deadline", "metadata", "call", NULL);
279
+ grpc_rb_sStatus =
280
+ rb_struct_define("Status", "code", "details", "metadata", NULL);
281
+ sym_code = ID2SYM(rb_intern("code"));
282
+ sym_details = ID2SYM(rb_intern("details"));
283
+ sym_metadata = ID2SYM(rb_intern("metadata"));
262
284
 
263
- Init_grpc_byte_buffer();
264
- Init_grpc_event();
265
285
  Init_grpc_channel();
266
286
  Init_grpc_completion_queue();
267
287
  Init_grpc_call();
268
288
  Init_grpc_credentials();
269
- Init_grpc_metadata();
270
289
  Init_grpc_server();
271
290
  Init_grpc_server_credentials();
272
291
  Init_grpc_status_codes();
@@ -38,26 +38,36 @@
38
38
  #include <ruby.h>
39
39
  #include <grpc/support/time.h>
40
40
 
41
- /* rb_mGrpcCore is the module containing the ruby wrapper GRPC classes. */
42
- extern VALUE rb_mGrpcCore;
41
+ /* grpc_rb_mGrpcCore is the module containing the ruby wrapper GRPC classes. */
42
+ extern VALUE grpc_rb_mGrpcCore;
43
43
 
44
- /* Class used to wrap timeval structs. */
45
- extern VALUE rb_cTimeVal;
44
+ /* grpc_rb_sNewServerRpc is the struct that holds new server rpc details. */
45
+ extern VALUE grpc_rb_sNewServerRpc;
46
46
 
47
- /* rb_sNewServerRpc is the struct that holds new server rpc details. */
48
- extern VALUE rb_sNewServerRpc;
47
+ /* grpc_rb_sStruct is the struct that holds status details. */
48
+ extern VALUE grpc_rb_sStatus;
49
49
 
50
- /* rb_sStruct is the struct that holds status details. */
51
- extern VALUE rb_sStatus;
50
+ /* sym_code is the symbol for the code attribute of grpc_rb_sStatus. */
51
+ extern VALUE sym_code;
52
+
53
+ /* sym_details is the symbol for the details attribute of grpc_rb_sStatus. */
54
+ extern VALUE sym_details;
55
+
56
+ /* sym_metadata is the symbol for the metadata attribute of grpc_rb_sStatus. */
57
+ extern VALUE sym_metadata;
52
58
 
53
59
  /* GC_NOT_MARKED is used in calls to Data_Wrap_Struct to indicate that the
54
60
  wrapped struct does not need to participate in ruby gc. */
55
- extern const RUBY_DATA_FUNC GC_NOT_MARKED;
61
+ #define GRPC_RB_GC_NOT_MARKED (RUBY_DATA_FUNC)(NULL)
56
62
 
57
63
  /* GC_DONT_FREED is used in calls to Data_Wrap_Struct to indicate that the
58
64
  wrapped struct should not be freed the wrapped ruby object is released by
59
65
  the garbage collector. */
60
- extern const RUBY_DATA_FUNC GC_DONT_FREE;
66
+ #define GRPC_RB_GC_DONT_FREE (RUBY_DATA_FUNC)(NULL)
67
+
68
+ /* GRPC_RB_MEMSIZE_UNAVAILABLE is used in rb_data_type_t to indicate that the
69
+ * number of bytes used by the wrapped struct is not available. */
70
+ #define GRPC_RB_MEMSIZE_UNAVAILABLE (size_t (*)(const void*))(NULL)
61
71
 
62
72
  /* A ruby object alloc func that fails by raising an exception. */
63
73
  VALUE grpc_rb_cannot_alloc(VALUE cls);
@@ -43,8 +43,11 @@
43
43
  #include "rb_server_credentials.h"
44
44
  #include "rb_grpc.h"
45
45
 
46
- /* rb_cServer is the ruby class that proxies grpc_server. */
47
- VALUE rb_cServer = Qnil;
46
+ /* grpc_rb_cServer is the ruby class that proxies grpc_server. */
47
+ static VALUE grpc_rb_cServer = Qnil;
48
+
49
+ /* id_at is the constructor method of the ruby standard Time class. */
50
+ static ID id_at;
48
51
 
49
52
  /* grpc_rb_server wraps a grpc_server. It provides a peer ruby object,
50
53
  'mark' to minimize copying when a server is created from ruby. */
@@ -85,13 +88,23 @@ static void grpc_rb_server_mark(void *p) {
85
88
  }
86
89
  }
87
90
 
91
+ static const rb_data_type_t grpc_rb_server_data_type = {
92
+ "grpc_server",
93
+ {grpc_rb_server_mark, grpc_rb_server_free, GRPC_RB_MEMSIZE_UNAVAILABLE},
94
+ NULL,
95
+ NULL,
96
+ /* It is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because the free function would block
97
+ * and we might want to unlock GVL
98
+ * TODO(yugui) Unlock GVL?
99
+ */
100
+ 0};
101
+
88
102
  /* Allocates grpc_rb_server instances. */
89
103
  static VALUE grpc_rb_server_alloc(VALUE cls) {
90
104
  grpc_rb_server *wrapper = ALLOC(grpc_rb_server);
91
105
  wrapper->wrapped = NULL;
92
106
  wrapper->mark = Qnil;
93
- return Data_Wrap_Struct(cls, grpc_rb_server_mark, grpc_rb_server_free,
94
- wrapper);
107
+ return TypedData_Wrap_Struct(cls, &grpc_rb_server_data_type, wrapper);
95
108
  }
96
109
 
97
110
  /*
@@ -107,7 +120,8 @@ static VALUE grpc_rb_server_init(VALUE self, VALUE cqueue, VALUE channel_args) {
107
120
  grpc_channel_args args;
108
121
  MEMZERO(&args, grpc_channel_args, 1);
109
122
  cq = grpc_rb_get_wrapped_completion_queue(cqueue);
110
- Data_Get_Struct(self, grpc_rb_server, wrapper);
123
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type,
124
+ wrapper);
111
125
  grpc_rb_hash_convert_to_channel_args(channel_args, &args);
112
126
  srv = grpc_server_create(cq, &args);
113
127
 
@@ -140,11 +154,13 @@ static VALUE grpc_rb_server_init_copy(VALUE copy, VALUE orig) {
140
154
  /* Raise an error if orig is not a server object or a subclass. */
141
155
  if (TYPE(orig) != T_DATA ||
142
156
  RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_server_free) {
143
- rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(rb_cServer));
157
+ rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(grpc_rb_cServer));
144
158
  }
145
159
 
146
- Data_Get_Struct(orig, grpc_rb_server, orig_srv);
147
- Data_Get_Struct(copy, grpc_rb_server, copy_srv);
160
+ TypedData_Get_Struct(orig, grpc_rb_server, &grpc_rb_server_data_type,
161
+ orig_srv);
162
+ TypedData_Get_Struct(copy, grpc_rb_server, &grpc_rb_server_data_type,
163
+ copy_srv);
148
164
 
149
165
  /* use ruby's MEMCPY to make a byte-for-byte copy of the server wrapper
150
166
  object. */
@@ -152,25 +168,97 @@ static VALUE grpc_rb_server_init_copy(VALUE copy, VALUE orig) {
152
168
  return copy;
153
169
  }
154
170
 
155
- static VALUE grpc_rb_server_request_call(VALUE self, VALUE tag_new) {
156
- grpc_call_error err;
171
+ /* request_call_stack holds various values used by the
172
+ * grpc_rb_server_request_call function */
173
+ typedef struct request_call_stack {
174
+ grpc_call_details details;
175
+ grpc_metadata_array md_ary;
176
+ } request_call_stack;
177
+
178
+ /* grpc_request_call_stack_init ensures the request_call_stack is properly
179
+ * initialized */
180
+ static void grpc_request_call_stack_init(request_call_stack* st) {
181
+ MEMZERO(st, request_call_stack, 1);
182
+ grpc_metadata_array_init(&st->md_ary);
183
+ grpc_call_details_init(&st->details);
184
+ st->details.method = NULL;
185
+ st->details.host = NULL;
186
+ }
187
+
188
+ /* grpc_request_call_stack_cleanup ensures the request_call_stack is properly
189
+ * cleaned up */
190
+ static void grpc_request_call_stack_cleanup(request_call_stack* st) {
191
+ grpc_metadata_array_destroy(&st->md_ary);
192
+ grpc_call_details_destroy(&st->details);
193
+ }
194
+
195
+ /* call-seq:
196
+ cq = CompletionQueue.new
197
+ tag = Object.new
198
+ timeout = 10
199
+ server.request_call(cqueue, tag, timeout)
200
+
201
+ Requests notification of a new call on a server. */
202
+ static VALUE grpc_rb_server_request_call(VALUE self, VALUE cqueue,
203
+ VALUE tag_new, VALUE timeout) {
157
204
  grpc_rb_server *s = NULL;
158
- Data_Get_Struct(self, grpc_rb_server, s);
205
+ grpc_call *call = NULL;
206
+ grpc_event *ev = NULL;
207
+ grpc_call_error err;
208
+ request_call_stack st;
209
+ VALUE result;
210
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
159
211
  if (s->wrapped == NULL) {
160
212
  rb_raise(rb_eRuntimeError, "closed!");
213
+ return Qnil;
161
214
  } else {
162
- err = grpc_server_request_call_old(s->wrapped, ROBJECT(tag_new));
215
+ grpc_request_call_stack_init(&st);
216
+ /* call grpc_server_request_call, then wait for it to complete using
217
+ * pluck_event */
218
+ err = grpc_server_request_call(
219
+ s->wrapped, &call, &st.details, &st.md_ary,
220
+ grpc_rb_get_wrapped_completion_queue(cqueue),
221
+ ROBJECT(tag_new));
163
222
  if (err != GRPC_CALL_OK) {
164
- rb_raise(rb_eCallError, "server request failed: %s (code=%d)",
223
+ grpc_request_call_stack_cleanup(&st);
224
+ rb_raise(grpc_rb_eCallError,
225
+ "grpc_server_request_call failed: %s (code=%d)",
165
226
  grpc_call_error_detail_of(err), err);
227
+ return Qnil;
166
228
  }
229
+ ev = grpc_rb_completion_queue_pluck_event(cqueue, tag_new, timeout);
230
+ if (ev == NULL) {
231
+ grpc_request_call_stack_cleanup(&st);
232
+ return Qnil;
233
+ }
234
+ if (ev->data.op_complete != GRPC_OP_OK) {
235
+ grpc_request_call_stack_cleanup(&st);
236
+ grpc_event_finish(ev);
237
+ rb_raise(grpc_rb_eCallError, "request_call completion failed: (code=%d)",
238
+ ev->data.op_complete);
239
+ return Qnil;
240
+ }
241
+
242
+ /* build the NewServerRpc struct result */
243
+ result = rb_struct_new(
244
+ grpc_rb_sNewServerRpc,
245
+ rb_str_new2(st.details.method),
246
+ rb_str_new2(st.details.host),
247
+ rb_funcall(rb_cTime, id_at, 2, INT2NUM(st.details.deadline.tv_sec),
248
+ INT2NUM(st.details.deadline.tv_nsec)),
249
+ grpc_rb_md_ary_to_h(&st.md_ary),
250
+ grpc_rb_wrap_call(call),
251
+ NULL);
252
+ grpc_event_finish(ev);
253
+ grpc_request_call_stack_cleanup(&st);
254
+ return result;
167
255
  }
168
256
  return Qnil;
169
257
  }
170
258
 
171
259
  static VALUE grpc_rb_server_start(VALUE self) {
172
260
  grpc_rb_server *s = NULL;
173
- Data_Get_Struct(self, grpc_rb_server, s);
261
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
174
262
  if (s->wrapped == NULL) {
175
263
  rb_raise(rb_eRuntimeError, "closed!");
176
264
  } else {
@@ -181,7 +269,7 @@ static VALUE grpc_rb_server_start(VALUE self) {
181
269
 
182
270
  static VALUE grpc_rb_server_destroy(VALUE self) {
183
271
  grpc_rb_server *s = NULL;
184
- Data_Get_Struct(self, grpc_rb_server, s);
272
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
185
273
  if (s->wrapped != NULL) {
186
274
  grpc_server_shutdown(s->wrapped);
187
275
  grpc_server_destroy(s->wrapped);
@@ -213,7 +301,7 @@ static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) {
213
301
  /* "11" == 1 mandatory args, 1 (rb_creds) is optional */
214
302
  rb_scan_args(argc, argv, "11", &port, &rb_creds);
215
303
 
216
- Data_Get_Struct(self, grpc_rb_server, s);
304
+ TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
217
305
  if (s->wrapped == NULL) {
218
306
  rb_raise(rb_eRuntimeError, "closed!");
219
307
  return Qnil;
@@ -239,27 +327,32 @@ static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) {
239
327
  }
240
328
 
241
329
  void Init_grpc_server() {
242
- rb_cServer = rb_define_class_under(rb_mGrpcCore, "Server", rb_cObject);
330
+ grpc_rb_cServer =
331
+ rb_define_class_under(grpc_rb_mGrpcCore, "Server", rb_cObject);
243
332
 
244
333
  /* Allocates an object managed by the ruby runtime */
245
- rb_define_alloc_func(rb_cServer, grpc_rb_server_alloc);
334
+ rb_define_alloc_func(grpc_rb_cServer, grpc_rb_server_alloc);
246
335
 
247
336
  /* Provides a ruby constructor and support for dup/clone. */
248
- rb_define_method(rb_cServer, "initialize", grpc_rb_server_init, 2);
249
- rb_define_method(rb_cServer, "initialize_copy", grpc_rb_server_init_copy, 1);
337
+ rb_define_method(grpc_rb_cServer, "initialize", grpc_rb_server_init, 2);
338
+ rb_define_method(grpc_rb_cServer, "initialize_copy",
339
+ grpc_rb_server_init_copy, 1);
250
340
 
251
341
  /* Add the server methods. */
252
- rb_define_method(rb_cServer, "request_call", grpc_rb_server_request_call, 1);
253
- rb_define_method(rb_cServer, "start", grpc_rb_server_start, 0);
254
- rb_define_method(rb_cServer, "destroy", grpc_rb_server_destroy, 0);
255
- rb_define_alias(rb_cServer, "close", "destroy");
256
- rb_define_method(rb_cServer, "add_http2_port", grpc_rb_server_add_http2_port,
342
+ rb_define_method(grpc_rb_cServer, "request_call",
343
+ grpc_rb_server_request_call, 3);
344
+ rb_define_method(grpc_rb_cServer, "start", grpc_rb_server_start, 0);
345
+ rb_define_method(grpc_rb_cServer, "destroy", grpc_rb_server_destroy, 0);
346
+ rb_define_alias(grpc_rb_cServer, "close", "destroy");
347
+ rb_define_method(grpc_rb_cServer, "add_http2_port",
348
+ grpc_rb_server_add_http2_port,
257
349
  -1);
350
+ id_at = rb_intern("at");
258
351
  }
259
352
 
260
353
  /* Gets the wrapped server from the ruby wrapper */
261
354
  grpc_server *grpc_rb_get_wrapped_server(VALUE v) {
262
355
  grpc_rb_server *wrapper = NULL;
263
- Data_Get_Struct(v, grpc_rb_server, wrapper);
356
+ TypedData_Get_Struct(v, grpc_rb_server, &grpc_rb_server_data_type, wrapper);
264
357
  return wrapper->wrapped;
265
358
  }