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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.rubocop_todo.yml +12 -20
- data/CHANGELOG.md +11 -0
- data/Rakefile +1 -0
- data/bin/apis/pubsub_demo.rb +3 -6
- data/bin/interop/interop_client.rb +43 -3
- data/bin/interop/interop_server.rb +1 -1
- data/bin/math_server.rb +1 -1
- data/bin/noproto_server.rb +1 -1
- data/ext/grpc/rb_byte_buffer.c +15 -189
- data/ext/grpc/rb_byte_buffer.h +4 -12
- data/ext/grpc/rb_call.c +514 -307
- data/ext/grpc/rb_call.h +4 -4
- data/ext/grpc/rb_channel.c +58 -34
- data/ext/grpc/rb_channel.h +0 -3
- data/ext/grpc/rb_channel_args.c +13 -4
- data/ext/grpc/rb_completion_queue.c +50 -23
- data/ext/grpc/rb_completion_queue.h +7 -3
- data/ext/grpc/rb_credentials.c +40 -28
- data/ext/grpc/rb_credentials.h +0 -4
- data/ext/grpc/rb_grpc.c +86 -67
- data/ext/grpc/rb_grpc.h +20 -10
- data/ext/grpc/rb_server.c +119 -26
- data/ext/grpc/rb_server.h +0 -4
- data/ext/grpc/rb_server_credentials.c +29 -16
- data/ext/grpc/rb_server_credentials.h +0 -4
- data/grpc.gemspec +11 -8
- data/lib/grpc.rb +1 -1
- data/lib/grpc/errors.rb +8 -7
- data/lib/grpc/generic/active_call.rb +104 -171
- data/lib/grpc/generic/bidi_call.rb +32 -60
- data/lib/grpc/generic/client_stub.rb +42 -31
- data/lib/grpc/generic/rpc_desc.rb +7 -12
- data/lib/grpc/generic/rpc_server.rb +253 -170
- data/lib/grpc/{core/event.rb → notifier.rb} +25 -9
- data/lib/grpc/version.rb +1 -1
- data/spec/call_spec.rb +23 -40
- data/spec/channel_spec.rb +11 -20
- data/spec/client_server_spec.rb +193 -175
- data/spec/credentials_spec.rb +2 -2
- data/spec/generic/active_call_spec.rb +59 -85
- data/spec/generic/client_stub_spec.rb +46 -64
- data/spec/generic/rpc_desc_spec.rb +50 -80
- data/spec/generic/rpc_server_pool_spec.rb +2 -3
- data/spec/generic/rpc_server_spec.rb +158 -29
- data/spec/server_spec.rb +1 -1
- data/spec/spec_helper.rb +8 -4
- metadata +27 -37
- data/ext/grpc/rb_event.c +0 -361
- data/ext/grpc/rb_event.h +0 -53
- data/ext/grpc/rb_metadata.c +0 -215
- data/ext/grpc/rb_metadata.h +0 -53
- data/spec/alloc_spec.rb +0 -44
- data/spec/byte_buffer_spec.rb +0 -67
- data/spec/event_spec.rb +0 -53
- data/spec/metadata_spec.rb +0 -64
data/ext/grpc/rb_credentials.h
CHANGED
@@ -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
|
|
data/ext/grpc/rb_grpc.c
CHANGED
@@ -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
|
-
|
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
|
-
|
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) ==
|
103
|
-
|
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
|
159
|
-
rb_define_module_under(
|
160
|
-
rb_define_const(
|
161
|
-
rb_define_const(
|
162
|
-
|
163
|
-
rb_define_const(
|
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(
|
169
|
+
rb_define_const(grpc_rb_mStatusCodes, "DEADLINE_EXCEEDED",
|
166
170
|
INT2NUM(GRPC_STATUS_DEADLINE_EXCEEDED));
|
167
|
-
rb_define_const(
|
168
|
-
|
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(
|
175
|
+
rb_define_const(grpc_rb_mStatusCodes, "PERMISSION_DENIED",
|
171
176
|
INT2NUM(GRPC_STATUS_PERMISSION_DENIED));
|
172
|
-
rb_define_const(
|
177
|
+
rb_define_const(grpc_rb_mStatusCodes, "UNAUTHENTICATED",
|
173
178
|
INT2NUM(GRPC_STATUS_UNAUTHENTICATED));
|
174
|
-
rb_define_const(
|
179
|
+
rb_define_const(grpc_rb_mStatusCodes, "RESOURCE_EXHAUSTED",
|
175
180
|
INT2NUM(GRPC_STATUS_RESOURCE_EXHAUSTED));
|
176
|
-
rb_define_const(
|
181
|
+
rb_define_const(grpc_rb_mStatusCodes, "FAILED_PRECONDITION",
|
177
182
|
INT2NUM(GRPC_STATUS_FAILED_PRECONDITION));
|
178
|
-
rb_define_const(
|
179
|
-
|
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(
|
187
|
+
rb_define_const(grpc_rb_mStatusCodes, "UNIMPLEMENTED",
|
182
188
|
INT2NUM(GRPC_STATUS_UNIMPLEMENTED));
|
183
|
-
rb_define_const(
|
184
|
-
|
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(
|
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
|
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
|
-
|
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
|
219
|
-
rb_define_module_under(
|
220
|
-
|
221
|
-
rb_define_class_under(
|
222
|
-
rb_define_const(
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
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(
|
253
|
+
static void grpc_rb_shutdown(ruby_vm_t *vm) { grpc_shutdown(); }
|
242
254
|
|
243
255
|
/* Initialize the GRPC module structs */
|
244
256
|
|
245
|
-
/*
|
246
|
-
VALUE
|
247
|
-
/*
|
248
|
-
VALUE
|
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
|
252
|
-
VALUE
|
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
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
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();
|
data/ext/grpc/rb_grpc.h
CHANGED
@@ -38,26 +38,36 @@
|
|
38
38
|
#include <ruby.h>
|
39
39
|
#include <grpc/support/time.h>
|
40
40
|
|
41
|
-
/*
|
42
|
-
extern VALUE
|
41
|
+
/* grpc_rb_mGrpcCore is the module containing the ruby wrapper GRPC classes. */
|
42
|
+
extern VALUE grpc_rb_mGrpcCore;
|
43
43
|
|
44
|
-
/*
|
45
|
-
extern VALUE
|
44
|
+
/* grpc_rb_sNewServerRpc is the struct that holds new server rpc details. */
|
45
|
+
extern VALUE grpc_rb_sNewServerRpc;
|
46
46
|
|
47
|
-
/*
|
48
|
-
extern VALUE
|
47
|
+
/* grpc_rb_sStruct is the struct that holds status details. */
|
48
|
+
extern VALUE grpc_rb_sStatus;
|
49
49
|
|
50
|
-
/*
|
51
|
-
extern VALUE
|
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
|
-
|
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
|
-
|
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);
|
data/ext/grpc/rb_server.c
CHANGED
@@ -43,8 +43,11 @@
|
|
43
43
|
#include "rb_server_credentials.h"
|
44
44
|
#include "rb_grpc.h"
|
45
45
|
|
46
|
-
/*
|
47
|
-
VALUE
|
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
|
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
|
-
|
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(
|
157
|
+
rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(grpc_rb_cServer));
|
144
158
|
}
|
145
159
|
|
146
|
-
|
147
|
-
|
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
|
-
|
156
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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(
|
249
|
-
rb_define_method(
|
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(
|
253
|
-
|
254
|
-
rb_define_method(
|
255
|
-
|
256
|
-
|
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
|
-
|
356
|
+
TypedData_Get_Struct(v, grpc_rb_server, &grpc_rb_server_data_type, wrapper);
|
264
357
|
return wrapper->wrapped;
|
265
358
|
}
|