nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 1 | /* |
| 2 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | * Copyright 2015 gRPC authors. |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 4 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 8 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 10 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 16 | * |
| 17 | */ |
| 18 | |
Nicolas "Pixel" Noble | d51d121 | 2016-01-31 11:33:19 +0100 | [diff] [blame] | 19 | #include <ruby/ruby.h> |
Nicolas "Pixel" Noble | 9fcdc87 | 2016-05-05 06:15:34 +0200 | [diff] [blame] | 20 | |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 21 | #include "rb_grpc.h" |
Craig Tiller | 5b1c5f2 | 2017-04-19 09:52:18 -0700 | [diff] [blame] | 22 | #include "rb_grpc_imports.generated.h" |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 23 | |
| 24 | #include <math.h> |
Yuki Yugui Sonoda | 2288791 | 2015-04-16 20:57:17 +0900 | [diff] [blame] | 25 | #include <ruby/vm.h> |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 26 | #include <sys/time.h> |
| 27 | |
| 28 | #include <grpc/grpc.h> |
| 29 | #include <grpc/support/time.h> |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 30 | #include "rb_call.h" |
murgatroid99 | 9946f2b | 2015-12-04 14:36:27 -0800 | [diff] [blame] | 31 | #include "rb_call_credentials.h" |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 32 | #include "rb_channel.h" |
Tim Emiola | 9332ea6 | 2015-10-27 23:48:29 -0700 | [diff] [blame] | 33 | #include "rb_channel_credentials.h" |
Craig Tiller | 5b1c5f2 | 2017-04-19 09:52:18 -0700 | [diff] [blame] | 34 | #include "rb_compression_options.h" |
murgatroid99 | ce67bff | 2017-04-19 15:54:27 -0700 | [diff] [blame] | 35 | #include "rb_event_thread.h" |
Nicolas "Pixel" Noble | d51d121 | 2016-01-31 11:33:19 +0100 | [diff] [blame] | 36 | #include "rb_loader.h" |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 37 | #include "rb_server.h" |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame] | 38 | #include "rb_server_credentials.h" |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 39 | |
Yuki Yugui Sonoda | 3c88e5d | 2015-04-16 20:09:00 +0900 | [diff] [blame] | 40 | static VALUE grpc_rb_cTimeVal = Qnil; |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 41 | |
Yuki Yugui Sonoda | d441c2e | 2015-04-11 15:33:58 +0900 | [diff] [blame] | 42 | static rb_data_type_t grpc_rb_timespec_data_type = { |
| 43 | "gpr_timespec", |
Craig Tiller | 5b1c5f2 | 2017-04-19 09:52:18 -0700 | [diff] [blame] | 44 | {GRPC_RB_GC_NOT_MARKED, |
| 45 | GRPC_RB_GC_DONT_FREE, |
| 46 | GRPC_RB_MEMSIZE_UNAVAILABLE, |
murgatroid99 | 87afb5d | 2015-07-16 16:01:02 -0700 | [diff] [blame] | 47 | {NULL, NULL}}, |
Yuki Yugui Sonoda | d441c2e | 2015-04-11 15:33:58 +0900 | [diff] [blame] | 48 | NULL, |
| 49 | NULL, |
Tim Emiola | 9161a82 | 2015-11-11 15:58:44 -0800 | [diff] [blame] | 50 | #ifdef RUBY_TYPED_FREE_IMMEDIATELY |
| 51 | RUBY_TYPED_FREE_IMMEDIATELY |
| 52 | #endif |
| 53 | }; |
Yuki Yugui Sonoda | d441c2e | 2015-04-11 15:33:58 +0900 | [diff] [blame] | 54 | |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 55 | /* Alloc func that blocks allocation of a given object by raising an |
| 56 | * exception. */ |
| 57 | VALUE grpc_rb_cannot_alloc(VALUE cls) { |
| 58 | rb_raise(rb_eTypeError, |
| 59 | "allocation of %s only allowed from the gRPC native layer", |
| 60 | rb_class2name(cls)); |
| 61 | return Qnil; |
| 62 | } |
| 63 | |
| 64 | /* Init func that fails by raising an exception. */ |
| 65 | VALUE grpc_rb_cannot_init(VALUE self) { |
| 66 | rb_raise(rb_eTypeError, |
| 67 | "initialization of %s only allowed from the gRPC native layer", |
| 68 | rb_obj_classname(self)); |
| 69 | return Qnil; |
| 70 | } |
| 71 | |
| 72 | /* Init/Clone func that fails by raising an exception. */ |
| 73 | VALUE grpc_rb_cannot_init_copy(VALUE copy, VALUE self) { |
murgatroid99 | 87afb5d | 2015-07-16 16:01:02 -0700 | [diff] [blame] | 74 | (void)self; |
Craig Tiller | 5b1c5f2 | 2017-04-19 09:52:18 -0700 | [diff] [blame] | 75 | rb_raise(rb_eTypeError, "Copy initialization of %s is not supported", |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 76 | rb_obj_classname(copy)); |
| 77 | return Qnil; |
| 78 | } |
| 79 | |
| 80 | /* id_tv_{,u}sec are accessor methods on Ruby Time instances. */ |
| 81 | static ID id_tv_sec; |
| 82 | static ID id_tv_nsec; |
| 83 | |
| 84 | /** |
Jan Tattermusch | 8808637 | 2015-12-10 10:54:12 -0800 | [diff] [blame] | 85 | * grpc_rb_time_timeval creates a timeval from a ruby time object. |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 86 | * |
| 87 | * This func is copied from ruby source, MRI/source/time.c, which is published |
| 88 | * under the same license as the ruby.h, on which the entire extensions is |
| 89 | * based. |
| 90 | */ |
| 91 | gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) { |
| 92 | gpr_timespec t; |
| 93 | gpr_timespec *time_const; |
| 94 | const char *tstr = interval ? "time interval" : "time"; |
| 95 | const char *want = " want <secs from epoch>|<Time>|<GRPC::TimeConst.*>"; |
| 96 | |
Craig Tiller | 5a1e7fd | 2015-07-14 07:14:47 -0700 | [diff] [blame] | 97 | t.clock_type = GPR_CLOCK_REALTIME; |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 98 | switch (TYPE(time)) { |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 99 | case T_DATA: |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 100 | if (CLASS_OF(time) == grpc_rb_cTimeVal) { |
Yuki Yugui Sonoda | d441c2e | 2015-04-11 15:33:58 +0900 | [diff] [blame] | 101 | TypedData_Get_Struct(time, gpr_timespec, &grpc_rb_timespec_data_type, |
| 102 | time_const); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 103 | t = *time_const; |
| 104 | } else if (CLASS_OF(time) == rb_cTime) { |
Craig Tiller | b5dcec5 | 2015-01-13 11:13:42 -0800 | [diff] [blame] | 105 | t.tv_sec = NUM2INT(rb_funcall(time, id_tv_sec, 0)); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 106 | t.tv_nsec = NUM2INT(rb_funcall(time, id_tv_nsec, 0)); |
| 107 | } else { |
Craig Tiller | b5dcec5 | 2015-01-13 11:13:42 -0800 | [diff] [blame] | 108 | rb_raise(rb_eTypeError, "bad input: (%s)->c_timeval, got <%s>,%s", tstr, |
| 109 | rb_obj_classname(time), want); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 110 | } |
| 111 | break; |
| 112 | |
| 113 | case T_FIXNUM: |
| 114 | t.tv_sec = FIX2LONG(time); |
| 115 | if (interval && t.tv_sec < 0) |
| 116 | rb_raise(rb_eArgError, "%s must be positive", tstr); |
| 117 | t.tv_nsec = 0; |
| 118 | break; |
| 119 | |
| 120 | case T_FLOAT: |
mattn | b9e1563 | 2015-02-28 23:45:58 +0900 | [diff] [blame] | 121 | if (interval && RFLOAT_VALUE(time) < 0.0) |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 122 | rb_raise(rb_eArgError, "%s must be positive", tstr); |
| 123 | else { |
| 124 | double f, d; |
| 125 | |
mattn | b9e1563 | 2015-02-28 23:45:58 +0900 | [diff] [blame] | 126 | d = modf(RFLOAT_VALUE(time), &f); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 127 | if (d < 0) { |
| 128 | d += 1; |
| 129 | f -= 1; |
| 130 | } |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 131 | t.tv_sec = (int64_t)f; |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 132 | if (f != t.tv_sec) { |
Craig Tiller | 5b1c5f2 | 2017-04-19 09:52:18 -0700 | [diff] [blame] | 133 | rb_raise(rb_eRangeError, "%f out of Time range", RFLOAT_VALUE(time)); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 134 | } |
Marcin Wyszynski | 1a2ac33 | 2015-07-23 20:12:33 +0200 | [diff] [blame] | 135 | t.tv_nsec = (int)(d * 1e9 + 0.5); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 136 | } |
| 137 | break; |
| 138 | |
| 139 | case T_BIGNUM: |
| 140 | t.tv_sec = NUM2LONG(time); |
| 141 | if (interval && t.tv_sec < 0) |
| 142 | rb_raise(rb_eArgError, "%s must be positive", tstr); |
| 143 | t.tv_nsec = 0; |
| 144 | break; |
| 145 | |
| 146 | default: |
Craig Tiller | b5dcec5 | 2015-01-13 11:13:42 -0800 | [diff] [blame] | 147 | rb_raise(rb_eTypeError, "bad input: (%s)->c_timeval, got <%s>,%s", tstr, |
| 148 | rb_obj_classname(time), want); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 149 | break; |
| 150 | } |
| 151 | return t; |
| 152 | } |
| 153 | |
Yuki Yugui Sonoda | f0eee5f | 2015-04-16 20:25:28 +0900 | [diff] [blame] | 154 | static void Init_grpc_status_codes() { |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 155 | /* Constants representing the status codes or grpc_status_code in status.h */ |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 156 | VALUE grpc_rb_mStatusCodes = |
| 157 | rb_define_module_under(grpc_rb_mGrpcCore, "StatusCodes"); |
| 158 | rb_define_const(grpc_rb_mStatusCodes, "OK", INT2NUM(GRPC_STATUS_OK)); |
| 159 | rb_define_const(grpc_rb_mStatusCodes, "CANCELLED", |
| 160 | INT2NUM(GRPC_STATUS_CANCELLED)); |
| 161 | rb_define_const(grpc_rb_mStatusCodes, "UNKNOWN", |
| 162 | INT2NUM(GRPC_STATUS_UNKNOWN)); |
| 163 | rb_define_const(grpc_rb_mStatusCodes, "INVALID_ARGUMENT", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 164 | INT2NUM(GRPC_STATUS_INVALID_ARGUMENT)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 165 | rb_define_const(grpc_rb_mStatusCodes, "DEADLINE_EXCEEDED", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 166 | INT2NUM(GRPC_STATUS_DEADLINE_EXCEEDED)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 167 | rb_define_const(grpc_rb_mStatusCodes, "NOT_FOUND", |
| 168 | INT2NUM(GRPC_STATUS_NOT_FOUND)); |
| 169 | rb_define_const(grpc_rb_mStatusCodes, "ALREADY_EXISTS", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 170 | INT2NUM(GRPC_STATUS_ALREADY_EXISTS)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 171 | rb_define_const(grpc_rb_mStatusCodes, "PERMISSION_DENIED", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 172 | INT2NUM(GRPC_STATUS_PERMISSION_DENIED)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 173 | rb_define_const(grpc_rb_mStatusCodes, "UNAUTHENTICATED", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 174 | INT2NUM(GRPC_STATUS_UNAUTHENTICATED)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 175 | rb_define_const(grpc_rb_mStatusCodes, "RESOURCE_EXHAUSTED", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 176 | INT2NUM(GRPC_STATUS_RESOURCE_EXHAUSTED)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 177 | rb_define_const(grpc_rb_mStatusCodes, "FAILED_PRECONDITION", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 178 | INT2NUM(GRPC_STATUS_FAILED_PRECONDITION)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 179 | rb_define_const(grpc_rb_mStatusCodes, "ABORTED", |
| 180 | INT2NUM(GRPC_STATUS_ABORTED)); |
| 181 | rb_define_const(grpc_rb_mStatusCodes, "OUT_OF_RANGE", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 182 | INT2NUM(GRPC_STATUS_OUT_OF_RANGE)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 183 | rb_define_const(grpc_rb_mStatusCodes, "UNIMPLEMENTED", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 184 | INT2NUM(GRPC_STATUS_UNIMPLEMENTED)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 185 | rb_define_const(grpc_rb_mStatusCodes, "INTERNAL", |
| 186 | INT2NUM(GRPC_STATUS_INTERNAL)); |
| 187 | rb_define_const(grpc_rb_mStatusCodes, "UNAVAILABLE", |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 188 | INT2NUM(GRPC_STATUS_UNAVAILABLE)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 189 | rb_define_const(grpc_rb_mStatusCodes, "DATA_LOSS", |
| 190 | INT2NUM(GRPC_STATUS_DATA_LOSS)); |
temiola | 5832791 | 2014-12-15 17:51:16 -0800 | [diff] [blame] | 191 | } |
| 192 | |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 193 | /* id_at is the constructor method of the ruby standard Time class. */ |
| 194 | static ID id_at; |
| 195 | |
| 196 | /* id_inspect is the inspect method found on various ruby objects. */ |
| 197 | static ID id_inspect; |
| 198 | |
| 199 | /* id_to_s is the to_s method found on various ruby objects. */ |
| 200 | static ID id_to_s; |
| 201 | |
Tim Emiola | 98a32d3 | 2015-03-28 01:48:44 -0700 | [diff] [blame] | 202 | /* Converts a wrapped time constant to a standard time. */ |
Yuki Yugui Sonoda | f0eee5f | 2015-04-16 20:25:28 +0900 | [diff] [blame] | 203 | static VALUE grpc_rb_time_val_to_time(VALUE self) { |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 204 | gpr_timespec *time_const = NULL; |
Craig Tiller | 94329d0 | 2015-07-23 09:52:11 -0700 | [diff] [blame] | 205 | gpr_timespec real_time; |
Yuki Yugui Sonoda | d441c2e | 2015-04-11 15:33:58 +0900 | [diff] [blame] | 206 | TypedData_Get_Struct(self, gpr_timespec, &grpc_rb_timespec_data_type, |
| 207 | time_const); |
Craig Tiller | 94329d0 | 2015-07-23 09:52:11 -0700 | [diff] [blame] | 208 | real_time = gpr_convert_clock_type(*time_const, GPR_CLOCK_REALTIME); |
| 209 | return rb_funcall(rb_cTime, id_at, 2, INT2NUM(real_time.tv_sec), |
Eric Richardson | 8e769fd | 2016-07-08 12:36:54 -0400 | [diff] [blame] | 210 | INT2NUM(real_time.tv_nsec / 1000)); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 211 | } |
| 212 | |
| 213 | /* Invokes inspect on the ctime version of the time val. */ |
Yuki Yugui Sonoda | f0eee5f | 2015-04-16 20:25:28 +0900 | [diff] [blame] | 214 | static VALUE grpc_rb_time_val_inspect(VALUE self) { |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 215 | return rb_funcall(grpc_rb_time_val_to_time(self), id_inspect, 0); |
| 216 | } |
| 217 | |
| 218 | /* Invokes to_s on the ctime version of the time val. */ |
Yuki Yugui Sonoda | f0eee5f | 2015-04-16 20:25:28 +0900 | [diff] [blame] | 219 | static VALUE grpc_rb_time_val_to_s(VALUE self) { |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 220 | return rb_funcall(grpc_rb_time_val_to_time(self), id_to_s, 0); |
| 221 | } |
| 222 | |
Craig Tiller | 354398f | 2015-07-13 09:16:03 -0700 | [diff] [blame] | 223 | static gpr_timespec zero_realtime; |
| 224 | static gpr_timespec inf_future_realtime; |
| 225 | static gpr_timespec inf_past_realtime; |
| 226 | |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 227 | /* Adds a module with constants that map to gpr's static timeval structs. */ |
Yuki Yugui Sonoda | f0eee5f | 2015-04-16 20:25:28 +0900 | [diff] [blame] | 228 | static void Init_grpc_time_consts() { |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 229 | VALUE grpc_rb_mTimeConsts = |
| 230 | rb_define_module_under(grpc_rb_mGrpcCore, "TimeConsts"); |
| 231 | grpc_rb_cTimeVal = |
| 232 | rb_define_class_under(grpc_rb_mGrpcCore, "TimeSpec", rb_cObject); |
Craig Tiller | 354398f | 2015-07-13 09:16:03 -0700 | [diff] [blame] | 233 | zero_realtime = gpr_time_0(GPR_CLOCK_REALTIME); |
| 234 | inf_future_realtime = gpr_inf_future(GPR_CLOCK_REALTIME); |
| 235 | inf_past_realtime = gpr_inf_past(GPR_CLOCK_REALTIME); |
Yuki Yugui Sonoda | d441c2e | 2015-04-11 15:33:58 +0900 | [diff] [blame] | 236 | rb_define_const( |
| 237 | grpc_rb_mTimeConsts, "ZERO", |
| 238 | TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type, |
Craig Tiller | 354398f | 2015-07-13 09:16:03 -0700 | [diff] [blame] | 239 | (void *)&zero_realtime)); |
Yuki Yugui Sonoda | d441c2e | 2015-04-11 15:33:58 +0900 | [diff] [blame] | 240 | rb_define_const( |
| 241 | grpc_rb_mTimeConsts, "INFINITE_FUTURE", |
| 242 | TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type, |
Craig Tiller | 354398f | 2015-07-13 09:16:03 -0700 | [diff] [blame] | 243 | (void *)&inf_future_realtime)); |
Yuki Yugui Sonoda | d441c2e | 2015-04-11 15:33:58 +0900 | [diff] [blame] | 244 | rb_define_const( |
| 245 | grpc_rb_mTimeConsts, "INFINITE_PAST", |
| 246 | TypedData_Wrap_Struct(grpc_rb_cTimeVal, &grpc_rb_timespec_data_type, |
Craig Tiller | 354398f | 2015-07-13 09:16:03 -0700 | [diff] [blame] | 247 | (void *)&inf_past_realtime)); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 248 | rb_define_method(grpc_rb_cTimeVal, "to_time", grpc_rb_time_val_to_time, 0); |
| 249 | rb_define_method(grpc_rb_cTimeVal, "inspect", grpc_rb_time_val_inspect, 0); |
| 250 | rb_define_method(grpc_rb_cTimeVal, "to_s", grpc_rb_time_val_to_s, 0); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 251 | id_at = rb_intern("at"); |
| 252 | id_inspect = rb_intern("inspect"); |
| 253 | id_to_s = rb_intern("to_s"); |
| 254 | id_tv_sec = rb_intern("tv_sec"); |
| 255 | id_tv_nsec = rb_intern("tv_nsec"); |
| 256 | } |
| 257 | |
Craig Tiller | 5b1c5f2 | 2017-04-19 09:52:18 -0700 | [diff] [blame] | 258 | static void grpc_rb_shutdown(void) { grpc_shutdown(); } |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 259 | |
Tim Emiola | 409e6c8 | 2015-02-17 17:46:35 -0800 | [diff] [blame] | 260 | /* Initialize the GRPC module structs */ |
temiola | 21bb60c | 2014-12-18 10:58:22 -0800 | [diff] [blame] | 261 | |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 262 | /* grpc_rb_sNewServerRpc is the struct that holds new server rpc details. */ |
| 263 | VALUE grpc_rb_sNewServerRpc = Qnil; |
| 264 | /* grpc_rb_sStatus is the struct that holds status details. */ |
| 265 | VALUE grpc_rb_sStatus = Qnil; |
temiola | 21bb60c | 2014-12-18 10:58:22 -0800 | [diff] [blame] | 266 | |
Tim Emiola | 409e6c8 | 2015-02-17 17:46:35 -0800 | [diff] [blame] | 267 | /* Initialize the GRPC module. */ |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 268 | VALUE grpc_rb_mGRPC = Qnil; |
| 269 | VALUE grpc_rb_mGrpcCore = Qnil; |
temiola | 21bb60c | 2014-12-18 10:58:22 -0800 | [diff] [blame] | 270 | |
Yuki Yugui Sonoda | 99eb9f9 | 2015-04-16 20:09:55 +0900 | [diff] [blame] | 271 | /* cached Symbols for members in Status struct */ |
| 272 | VALUE sym_code = Qundef; |
| 273 | VALUE sym_details = Qundef; |
| 274 | VALUE sym_metadata = Qundef; |
| 275 | |
Nicolas "Pixel" Noble | cb90397 | 2016-02-21 22:58:26 +0100 | [diff] [blame] | 276 | static gpr_once g_once_init = GPR_ONCE_INIT; |
| 277 | |
Alexander Polcyn | 2a9b5d7 | 2017-04-14 12:10:55 -0700 | [diff] [blame] | 278 | static void grpc_ruby_once_init_internal() { |
Nicolas "Pixel" Noble | cb90397 | 2016-02-21 22:58:26 +0100 | [diff] [blame] | 279 | grpc_init(); |
| 280 | atexit(grpc_rb_shutdown); |
| 281 | } |
| 282 | |
Alexander Polcyn | 5c6dda8 | 2017-05-17 13:08:34 -0700 | [diff] [blame] | 283 | static VALUE bg_thread_init_rb_mu = Qundef; |
| 284 | static int bg_thread_init_done = 0; |
| 285 | |
Alexander Polcyn | 2a9b5d7 | 2017-04-14 12:10:55 -0700 | [diff] [blame] | 286 | void grpc_ruby_once_init() { |
Nicolas "Pixel" Noble | 88dc3c5 | 2016-02-22 03:21:08 +0100 | [diff] [blame] | 287 | /* ruby_vm_at_exit doesn't seem to be working. It would crash once every |
| 288 | * blue moon, and some users are getting it repeatedly. See the discussions |
| 289 | * - https://github.com/grpc/grpc/pull/5337 |
| 290 | * - https://bugs.ruby-lang.org/issues/12095 |
| 291 | * |
| 292 | * In order to still be able to handle the (unlikely) situation where the |
| 293 | * extension is loaded by a first Ruby VM that is subsequently destroyed, |
| 294 | * then loaded again by another VM within the same process, we need to |
| 295 | * schedule our initialization and destruction only once. |
| 296 | */ |
Alexander Polcyn | 2a9b5d7 | 2017-04-14 12:10:55 -0700 | [diff] [blame] | 297 | gpr_once_init(&g_once_init, grpc_ruby_once_init_internal); |
Alexander Polcyn | 5c6dda8 | 2017-05-17 13:08:34 -0700 | [diff] [blame] | 298 | |
| 299 | // Avoid calling calling into ruby library (when creating threads here) |
| 300 | // in gpr_once_init. In general, it appears to be unsafe to call |
| 301 | // into the ruby library while holding a non-ruby mutex, because a gil yield |
| 302 | // could end up trying to lock onto that same mutex and deadlocking. |
| 303 | rb_mutex_lock(bg_thread_init_rb_mu); |
| 304 | if (!bg_thread_init_done) { |
| 305 | grpc_rb_event_queue_thread_start(); |
| 306 | grpc_rb_channel_polling_thread_start(); |
| 307 | bg_thread_init_done = 1; |
| 308 | } |
| 309 | rb_mutex_unlock(bg_thread_init_rb_mu); |
Alexander Polcyn | 2a9b5d7 | 2017-04-14 12:10:55 -0700 | [diff] [blame] | 310 | } |
| 311 | |
| 312 | void Init_grpc_c() { |
| 313 | if (!grpc_rb_load_core()) { |
| 314 | rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core"); |
| 315 | return; |
| 316 | } |
Tim Emiola | 9161a82 | 2015-11-11 15:58:44 -0800 | [diff] [blame] | 317 | |
Alexander Polcyn | 5c6dda8 | 2017-05-17 13:08:34 -0700 | [diff] [blame] | 318 | rb_global_variable(&bg_thread_init_rb_mu); |
Alexander Polcyn | 8c12d9e | 2017-10-05 08:47:39 -0700 | [diff] [blame^] | 319 | bg_thread_init_rb_mu = rb_mutex_new(); |
Alexander Polcyn | 5c6dda8 | 2017-05-17 13:08:34 -0700 | [diff] [blame] | 320 | |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 321 | grpc_rb_mGRPC = rb_define_module("GRPC"); |
| 322 | grpc_rb_mGrpcCore = rb_define_module_under(grpc_rb_mGRPC, "Core"); |
Craig Tiller | 5b1c5f2 | 2017-04-19 09:52:18 -0700 | [diff] [blame] | 323 | grpc_rb_sNewServerRpc = rb_struct_define( |
| 324 | "NewServerRpc", "method", "host", "deadline", "metadata", "call", NULL); |
Yuki Yugui Sonoda | a7d369e | 2015-04-11 11:48:36 +0900 | [diff] [blame] | 325 | grpc_rb_sStatus = |
| 326 | rb_struct_define("Status", "code", "details", "metadata", NULL); |
Tim Emiola | 98a32d3 | 2015-03-28 01:48:44 -0700 | [diff] [blame] | 327 | sym_code = ID2SYM(rb_intern("code")); |
| 328 | sym_details = ID2SYM(rb_intern("details")); |
| 329 | sym_metadata = ID2SYM(rb_intern("metadata")); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 330 | |
Tim Emiola | 409e6c8 | 2015-02-17 17:46:35 -0800 | [diff] [blame] | 331 | Init_grpc_channel(); |
Tim Emiola | 409e6c8 | 2015-02-17 17:46:35 -0800 | [diff] [blame] | 332 | Init_grpc_call(); |
murgatroid99 | 9946f2b | 2015-12-04 14:36:27 -0800 | [diff] [blame] | 333 | Init_grpc_call_credentials(); |
Tim Emiola | 9332ea6 | 2015-10-27 23:48:29 -0700 | [diff] [blame] | 334 | Init_grpc_channel_credentials(); |
Tim Emiola | 409e6c8 | 2015-02-17 17:46:35 -0800 | [diff] [blame] | 335 | Init_grpc_server(); |
| 336 | Init_grpc_server_credentials(); |
| 337 | Init_grpc_status_codes(); |
| 338 | Init_grpc_time_consts(); |
Alexander Polcyn | 0dccf10 | 2016-06-27 13:11:07 -0700 | [diff] [blame] | 339 | Init_grpc_compression_options(); |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 340 | } |