/* Clones CallCredentials instances. Gives CallCredentials a consistent implementation of Ruby's object copy/dup protocol. */ static VALUE grpc_rb_call_credentials_init_copy(VALUE copy, VALUE orig) { grpc_rb_call_credentials *orig_cred = NULL; grpc_rb_call_credentials *copy_cred = NULL; if (copy == orig) { return copy; } /* Raise an error if orig is not a credentials object or a subclass. */ if (TYPE(orig) != T_DATA || RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_call_credentials_free) { rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(grpc_rb_cCallCredentials)); } TypedData_Get_Struct(orig, grpc_rb_call_credentials, &grpc_rb_call_credentials_data_type, orig_cred); TypedData_Get_Struct(copy, grpc_rb_call_credentials, &grpc_rb_call_credentials_data_type, copy_cred); /* use ruby's MEMCPY to make a byte-for-byte copy of the credentials * wrapper object. */ MEMCPY(copy_cred, orig_cred, grpc_rb_call_credentials, 1); return copy; }
/* * call-seq: * Message.==(other) => boolean * * Performs a deep comparison of this message with another. Messages are equal * if they have the same type and if each field is equal according to the :== * method's semantics (a more efficient comparison may actually be done if the * field is of a primitive type). */ VALUE Message_eq(VALUE _self, VALUE _other) { MessageHeader* self; MessageHeader* other; TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); TypedData_Get_Struct(_other, MessageHeader, &Message_type, other); if (self->descriptor != other->descriptor) { return Qfalse; } return layout_eq(self->descriptor->layout, Message_data(self), Message_data(other)); }
// Internal only; used by Google::Protobuf.deep_copy. VALUE Message_deep_copy(VALUE _self) { MessageHeader* self; TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self)); MessageHeader* new_msg_self; TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self); layout_deep_copy(self->descriptor->layout, Message_data(new_msg_self), Message_data(self)); return new_msg; }
// default behavior of async (doesn't accept Symbol) // call-seq: // async { } // async Proc.new static VALUE kern_async(int argc, VALUE *argv, VALUE self) { VALUE obj; rb_proc_t *proc; rb_iseq_t *niseq; rb_scan_args(argc, argv, "01", &obj); if (!NIL_P(obj)) { if (!rb_obj_is_proc(obj)) { VALUE thread = rb_thread_current(); rb_thread_t * th; TypedData_Get_Struct(thread, rb_thread_t, RTYPEDDATA_TYPE(thread), th); if (self == th->vm->top_self) { return mod_async(CLASS_OF(self), obj); } else { rb_raise(rb_eTypeError, "wrong argument type (expected Proc)"); } } } else if (rb_block_given_p()) { obj = rb_block_proc(); } else { rb_raise(rb_eArgError, "Proc or block is required"); } proc = (rb_proc_t *)DATA_PTR(obj); // うーーー niseq = transform(obj); proc->block.iseq = niseq; return obj; }
/* Provides a ruby hash of GRPC core channel argument key-values that * correspond to the compression settings on this instance. */ VALUE grpc_rb_compression_options_to_hash(VALUE self) { grpc_rb_compression_options* wrapper = NULL; grpc_compression_options* compression_options = NULL; VALUE channel_arg_hash = rb_hash_new(); VALUE key = Qnil; VALUE value = Qnil; TypedData_Get_Struct(self, grpc_rb_compression_options, &grpc_rb_compression_options_data_type, wrapper); compression_options = wrapper->wrapped; /* Add key-value pairs to the new Ruby hash. It can be used * as GRPC core channel arguments. */ if (compression_options->default_level.is_set) { key = rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL); value = INT2NUM((int)compression_options->default_level.level); rb_hash_aset(channel_arg_hash, key, value); } if (compression_options->default_algorithm.is_set) { key = rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM); value = INT2NUM((int)compression_options->default_algorithm.algorithm); rb_hash_aset(channel_arg_hash, key, value); } key = rb_str_new2(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET); value = INT2NUM((int)compression_options->enabled_algorithms_bitset); rb_hash_aset(channel_arg_hash, key, value); return channel_arg_hash; }
/* call-seq: // insecure port insecure_server = Server.new(cq, {'arg1': 'value1'}) insecure_server.add_http2_port('mydomain:50051', :this_port_is_insecure) // secure port server_creds = ... secure_server = Server.new(cq, {'arg1': 'value1'}) secure_server.add_http_port('mydomain:50051', server_creds) Adds a http2 port to server */ static VALUE grpc_rb_server_add_http2_port(VALUE self, VALUE port, VALUE rb_creds) { grpc_rb_server* s = NULL; grpc_server_credentials* creds = NULL; int recvd_port = 0; TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s); if (s->wrapped == NULL) { rb_raise(rb_eRuntimeError, "destroyed!"); return Qnil; } else if (TYPE(rb_creds) == T_SYMBOL) { if (id_insecure_server != SYM2ID(rb_creds)) { rb_raise(rb_eTypeError, "bad creds symbol, want :this_port_is_insecure"); return Qnil; } recvd_port = grpc_server_add_insecure_http2_port(s->wrapped, StringValueCStr(port)); if (recvd_port == 0) { rb_raise(rb_eRuntimeError, "could not add port %s to server, not sure why", StringValueCStr(port)); } } else { creds = grpc_rb_get_wrapped_server_credentials(rb_creds); recvd_port = grpc_server_add_secure_http2_port( s->wrapped, StringValueCStr(port), creds); if (recvd_port == 0) { rb_raise(rb_eRuntimeError, "could not add secure port %s to server, not sure why", StringValueCStr(port)); } } return INT2NUM(recvd_port); }
/* call-seq: server = Server.new({'arg1': 'value1'}) Initializes server instances. */ static VALUE grpc_rb_server_init(VALUE self, VALUE channel_args) { grpc_completion_queue* cq = NULL; grpc_rb_server* wrapper = NULL; grpc_server* srv = NULL; grpc_channel_args args; MEMZERO(&args, grpc_channel_args, 1); grpc_ruby_once_init(); cq = grpc_completion_queue_create_for_pluck(NULL); TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, wrapper); grpc_rb_hash_convert_to_channel_args(channel_args, &args); srv = grpc_server_create(&args, NULL); if (args.args != NULL) { xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */ } if (srv == NULL) { rb_raise(rb_eRuntimeError, "could not create a gRPC server, not sure why"); } grpc_server_register_completion_queue(srv, cq, NULL); wrapper->wrapped = srv; wrapper->queue = cq; return self; }
/* Create a call given a grpc_channel, in order to call method. The request is not sent until grpc_call_invoke is called. */ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE parent, VALUE mask, VALUE method, VALUE host, VALUE deadline) { VALUE res = Qnil; grpc_rb_channel *wrapper = NULL; grpc_call *call = NULL; grpc_call *parent_call = NULL; grpc_completion_queue *cq = NULL; int flags = GRPC_PROPAGATE_DEFAULTS; grpc_slice method_slice; grpc_slice host_slice; grpc_slice *host_slice_ptr = NULL; char *tmp_str = NULL; if (host != Qnil) { host_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(host), RSTRING_LEN(host)); host_slice_ptr = &host_slice; } if (mask != Qnil) { flags = NUM2UINT(mask); } if (parent != Qnil) { parent_call = grpc_rb_get_wrapped_call(parent); } cq = grpc_completion_queue_create_for_pluck(NULL); TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); if (wrapper->bg_wrapped == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } method_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(method), RSTRING_LEN(method)); call = grpc_channel_create_call(wrapper->bg_wrapped->channel, parent_call, flags, cq, method_slice, host_slice_ptr, grpc_rb_time_timeval(deadline, /* absolute time */ 0), NULL); if (call == NULL) { tmp_str = grpc_slice_to_c_string(method_slice); rb_raise(rb_eRuntimeError, "cannot create call with method %s", tmp_str); return Qnil; } grpc_slice_unref(method_slice); if (host_slice_ptr != NULL) { grpc_slice_unref(host_slice); } res = grpc_rb_wrap_call(call, cq); /* Make this channel an instance attribute of the call so that it is not GCed * before the call. */ rb_ivar_set(res, id_channel, self); return res; }
/* * call-seq: * MessageClass.decode_json(data) => message * * Decodes the given data (as a string containing bytes in protocol buffers wire * format) under the interpretration given by this message class's definition * and returns a message object with the corresponding field values. */ VALUE Message_decode_json(VALUE klass, VALUE data) { VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); Descriptor* desc = ruby_to_Descriptor(descriptor); VALUE msgklass = Descriptor_msgclass(descriptor); VALUE msg_rb; MessageHeader* msg; if (TYPE(data) != T_STRING) { rb_raise(rb_eArgError, "Expected string for JSON data."); } // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to // convert, because string handlers pass data directly to message string // fields. msg_rb = rb_class_new_instance(0, NULL, msgklass); TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); { stackenv se; upb_sink sink; upb_json_parser* parser; stackenv_init(&se, "Error occurred during parsing: %s"); upb_sink_reset(&sink, get_fill_handlers(desc), msg); parser = upb_json_parser_create(&se.env, &sink); upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), upb_json_parser_input(parser)); stackenv_uninit(&se); } return msg_rb; }
/* * @overload poll(is_stderr: false, timeout: -1) * Poll a channel for data to read. * @since 0.1.0 * @param [Boolean] is_stderr A boolean to select the stderr stream. * @param [Fixnum] timeout A timeout in milliseconds. A negative value means an * infinite timeout. * @return [Fixnum, nil] The number of bytes available for reading. +nil+ if * timed out. * @see http://api.libssh.org/stable/group__libssh__channel.html * ssh_channel_poll_timeout */ static VALUE m_poll(int argc, VALUE *argv, VALUE self) { ChannelHolder *holder; VALUE opts; const ID table[] = {id_stderr, id_timeout}; VALUE kwvals[sizeof(table) / sizeof(*table)]; struct nogvl_poll_args args; TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder); rb_scan_args(argc, argv, "00:", &opts); rb_get_kwargs(opts, table, 0, 2, kwvals); if (kwvals[0] == Qundef) { args.is_stderr = 0; } else { args.is_stderr = RTEST(kwvals[0]) ? 1 : 0; } if (kwvals[1] == Qundef) { args.timeout = -1; } else { Check_Type(kwvals[1], T_FIXNUM); args.timeout = FIX2INT(kwvals[1]); } args.channel = holder->channel; rb_thread_call_without_gvl(nogvl_poll, &args, RUBY_UBF_IO, NULL); RAISE_IF_ERROR(args.rc); if (args.rc == SSH_EOF) { return Qnil; } else { return INT2FIX(args.rc); } }
imf_jpeg_src_mgr_t * get_imf_jpeg_src_mgr(VALUE obj) { imf_jpeg_src_mgr_t *srcmgr; TypedData_Get_Struct(obj, imf_jpeg_src_mgr_t, &imf_jpeg_src_mgr_data_type, srcmgr); return srcmgr; }
/* * @overload [](id) * @param id [Integer, Groonga::Record] The record ID for the * column value. * * @return [Object] The value for the record ID. */ static VALUE rb_grn_column_cache_array_reference (VALUE self, VALUE rb_id) { RbGrnColumnCache *rb_grn_column_cache; grn_id id; void *value; size_t value_size = 0; TypedData_Get_Struct(self, RbGrnColumnCache, &data_type, rb_grn_column_cache); if (!rb_grn_column_cache->column_cache) { return Qnil; } id = rb_grn_id_from_ruby_object(rb_id, rb_grn_column_cache->context, rb_grn_column_cache->table, self); value = grn_column_cache_ref(rb_grn_column_cache->context, rb_grn_column_cache->column_cache, id, &value_size); rb_grn_context_check(rb_grn_column_cache->context, self); GRN_TEXT_SET_REF(&(rb_grn_column_cache->buffer), value, value_size); return GRNBULK2RVAL(rb_grn_column_cache->context, &(rb_grn_column_cache->buffer), rb_grn_column_cache->range, self); }
/* call-seq: emitter.line_width * * Get the preferred line width. */ static VALUE line_width(VALUE self) { yaml_emitter_t * emitter; TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); return INT2NUM(emitter->best_width); }
/* call-seq: emitter.indentation * * Get the indentation level. */ static VALUE indentation(VALUE self) { yaml_emitter_t * emitter; TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); return INT2NUM(emitter->best_indent); }
/* call-seq: emitter.canonical * * Get the output style, canonical or not. */ static VALUE canonical(VALUE self) { yaml_emitter_t * emitter; TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); return (emitter->canonical == 0) ? Qfalse : Qtrue; }
// Handler for a submessage field in a oneof. static void *oneofsubmsg_handler(void *closure, const void *hd) { MessageHeader* msg = closure; const oneof_handlerdata_t *oneofdata = hd; uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t); VALUE subdesc = get_def_obj((void*)oneofdata->md); VALUE subklass = Descriptor_msgclass(subdesc); VALUE submsg_rb; MessageHeader* submsg; if (oldcase != oneofdata->oneof_case_num || DEREF(msg, oneofdata->ofs, VALUE) == Qnil) { DEREF(msg, oneofdata->ofs, VALUE) = rb_class_new_instance(0, NULL, subklass); } // Set the oneof case *after* allocating the new class instance -- otherwise, // if the Ruby GC is invoked as part of a call into the VM, it might invoke // our mark routines, and our mark routines might see the case value // indicating a VALUE is present and expect a valid VALUE. See comment in // layout_set() for more detail: basically, the change to the value and the // case must be atomic w.r.t. the Ruby VM. DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num; submsg_rb = DEREF(msg, oneofdata->ofs, VALUE); TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); return submsg; }
/* Called to obtain the x509 cert of an authenticated peer. */ static VALUE grpc_rb_call_get_peer_cert(VALUE self) { grpc_rb_call *call = NULL; VALUE res = Qnil; grpc_auth_context *ctx = NULL; if (RTYPEDDATA_DATA(self) == NULL) { rb_raise(grpc_rb_eCallError, "Cannot get peer cert on closed call"); return Qnil; } TypedData_Get_Struct(self, grpc_rb_call, &grpc_call_data_type, call); ctx = grpc_call_auth_context(call->wrapped); if (!ctx || !grpc_auth_context_peer_is_authenticated(ctx)) { return Qnil; } { grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME); const grpc_auth_property *prop = grpc_auth_property_iterator_next(&it); if (prop == NULL) { return Qnil; } res = rb_str_new2(prop->value); } grpc_auth_context_release(ctx); return res; }
/* * call-seq: * MessageClass.decode(data) => message * * Decodes the given data (as a string containing bytes in protocol buffers wire * format) under the interpretration given by this message class's definition * and returns a message object with the corresponding field values. */ VALUE Message_decode(VALUE klass, VALUE data) { VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); Descriptor* desc = ruby_to_Descriptor(descriptor); VALUE msgklass = Descriptor_msgclass(descriptor); VALUE msg_rb; MessageHeader* msg; if (TYPE(data) != T_STRING) { rb_raise(rb_eArgError, "Expected string for binary protobuf data."); } msg_rb = rb_class_new_instance(0, NULL, msgklass); TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); { const upb_pbdecodermethod* method = msgdef_decodermethod(desc); const upb_handlers* h = upb_pbdecodermethod_desthandlers(method); stackenv se; upb_sink sink; upb_pbdecoder* decoder; stackenv_init(&se, "Error occurred during parsing: %s"); upb_sink_reset(&sink, h, msg); decoder = upb_pbdecoder_create(&se.env, method, &sink); upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), upb_pbdecoder_input(decoder)); stackenv_uninit(&se); } return msg_rb; }
/* * @overload read(count, is_stderr: false, timeout: -1) * Read data from a channel. * @since 0.1.0 * @param [Fixnum] count The count of bytes to be read. * @param [Boolean] is_stderr Read from the stderr flow or not. * @param [Fixnum] timeout A timeout in seconds. +-1+ means infinite timeout. * @return [String] Data read from the channel. * @see http://api.libssh.org/stable/group__libssh__channel.html * ssh_channel_read_timeout */ static VALUE m_read(int argc, VALUE *argv, VALUE self) { ChannelHolder *holder; VALUE count, opts; const ID table[] = {id_stderr, id_timeout}; VALUE kwvals[sizeof(table) / sizeof(*table)]; struct nogvl_read_args args; VALUE ret; TypedData_Get_Struct(self, ChannelHolder, &channel_type, holder); rb_scan_args(argc, argv, "10:", &count, &opts); Check_Type(count, T_FIXNUM); rb_get_kwargs(opts, table, 0, 2, kwvals); if (kwvals[0] == Qundef) { args.is_stderr = 0; } else { args.is_stderr = RTEST(kwvals[0]) ? 1 : 0; } if (kwvals[1] == Qundef) { args.timeout = -1; } else { Check_Type(kwvals[1], T_FIXNUM); args.timeout = FIX2INT(kwvals[1]); } args.channel = holder->channel; args.count = FIX2UINT(count); args.buf = ALLOC_N(char, args.count); rb_thread_call_without_gvl(nogvl_read, &args, RUBY_UBF_IO, NULL); ret = rb_utf8_str_new(args.buf, args.rc); ruby_xfree(args.buf); return ret; }
static VALUE component_initialize(VALUE self) { component_t *data; TypedData_Get_Struct(self, component_t, &data_type, data); data->component = qmlbind_component_new(rbqml_get_engine(rbqml_engine)); return self; }
/* Gets the wrapped grpc_call_credentials from the ruby wrapper */ grpc_call_credentials *grpc_rb_get_wrapped_call_credentials(VALUE v) { grpc_rb_call_credentials *wrapper = NULL; TypedData_Get_Struct(v, grpc_rb_call_credentials, &grpc_rb_call_credentials_data_type, wrapper); return wrapper->wrapped; }
/* Watch for a change in connectivity state. Once the channel connectivity state is different from the last observed state, tag will be enqueued on cq with success=1 If deadline expires BEFORE the state is changed, tag will be enqueued on the completion queue with success=0 */ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, VALUE last_state, VALUE cqueue, VALUE deadline, VALUE tag) { grpc_rb_channel *wrapper = NULL; grpc_channel *ch = NULL; grpc_completion_queue *cq = NULL; cq = grpc_rb_get_wrapped_completion_queue(cqueue); TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); ch = wrapper->wrapped; if (ch == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } grpc_channel_watch_connectivity_state( ch, (grpc_connectivity_state)NUM2LONG(last_state), grpc_rb_time_timeval(deadline, /* absolute time */ 0), cq, ROBJECT(tag)); return Qnil; }
static VALUE application_initialize(VALUE self, VALUE args) { if (rb_thread_main() != rb_thread_current()) { rb_raise(rb_eThreadError, "Initializing QML::Application outside the main thread"); } application_t *data; TypedData_Get_Struct(self, application_t, &data_type, data); if (rb_type(args) != T_ARRAY) { rb_raise(rb_eTypeError, "Expected Array"); } args = rb_ary_concat(rb_ary_new_from_args(1, rb_argv0), args); int argc = RARRAY_LEN(args); char **argv = malloc(argc * sizeof(char *)); for (int i = 0; i < argc; ++i) { VALUE arg = RARRAY_AREF(args, i); argv[i] = rb_string_value_cstr(&arg); } data->application = qmlbind_application_new(argc, argv); return self; }
/* call-seq: cq = CompletionQueue.new server = Server.new(cq, {'arg1': 'value1'}) ... // do stuff with server ... ... // to shutdown the server server.destroy(cq) ... // to shutdown the server with a timeout server.destroy(cq, timeout) Destroys server instances. */ static VALUE grpc_rb_server_destroy(int argc, VALUE *argv, VALUE self) { VALUE cqueue = Qnil; VALUE timeout = Qnil; grpc_completion_queue *cq = NULL; grpc_event ev; grpc_rb_server *s = NULL; /* "11" == 1 mandatory args, 1 (timeout) is optional */ rb_scan_args(argc, argv, "11", &cqueue, &timeout); cq = grpc_rb_get_wrapped_completion_queue(cqueue); TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s); if (s->wrapped != NULL) { grpc_server_shutdown_and_notify(s->wrapped, cq, NULL); ev = grpc_rb_completion_queue_pluck_event(cqueue, Qnil, timeout); if (!ev.success) { rb_warn("server shutdown failed, cancelling the calls, objects may leak"); grpc_server_cancel_all_calls(s->wrapped); return Qfalse; } grpc_server_destroy(s->wrapped); s->wrapped = NULL; } return Qtrue; }
static rb_tp_t * tpptr(VALUE tpval) { rb_tp_t *tp; TypedData_Get_Struct(tpval, rb_tp_t, &tp_data_type, tp); return tp; }
/* call-seq: cq = CompletionQueue.new server = Server.new(cq, {'arg1': 'value1'}) Initializes server instances. */ static VALUE grpc_rb_server_init(VALUE self, VALUE cqueue, VALUE channel_args) { grpc_completion_queue *cq = NULL; grpc_rb_server *wrapper = NULL; grpc_server *srv = NULL; grpc_channel_args args; MEMZERO(&args, grpc_channel_args, 1); cq = grpc_rb_get_wrapped_completion_queue(cqueue); TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, wrapper); grpc_rb_hash_convert_to_channel_args(channel_args, &args); srv = grpc_server_create(&args, NULL); if (args.args != NULL) { xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */ } if (srv == NULL) { rb_raise(rb_eRuntimeError, "could not create a gRPC server, not sure why"); } grpc_server_register_completion_queue(srv, cq, NULL); wrapper->wrapped = srv; /* Add the cq as the server's mark object. This ensures the ruby cq can't be GCed before the server */ wrapper->mark = cqueue; return self; }
/* call-seq: insecure_channel = Channel:new("myhost:8080", {'arg1': 'value1'}) creds = ... secure_channel = Channel:new("myhost:443", {'arg1': 'value1'}, creds) Creates channel instances. */ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { VALUE channel_args = Qnil; VALUE credentials = Qnil; VALUE target = Qnil; grpc_rb_channel *wrapper = NULL; grpc_credentials *creds = NULL; grpc_channel *ch = NULL; char *target_chars = NULL; grpc_channel_args args; MEMZERO(&args, grpc_channel_args, 1); /* "21" == 2 mandatory args, 1 (credentials) is optional */ rb_scan_args(argc, argv, "21", &target, &channel_args, &credentials); TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); target_chars = StringValueCStr(target); grpc_rb_hash_convert_to_channel_args(channel_args, &args); if (credentials == Qnil) { ch = grpc_insecure_channel_create(target_chars, &args); } else { creds = grpc_rb_get_wrapped_credentials(credentials); ch = grpc_secure_channel_create(creds, target_chars, &args); } if (args.args != NULL) { xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */ } if (ch == NULL) { rb_raise(rb_eRuntimeError, "could not create an rpc channel to target:%s", target_chars); return Qnil; } rb_ivar_set(self, id_target, target); wrapper->wrapped = ch; return self; }
/* Wait until the channel's connectivity state becomes different from * "last_state", or "deadline" expires. * Returns true if the channel's connectivity state becomes different * from "last_state" within "deadline". * Returns false if "deadline" expires before the channel's connectivity * state changes from "last_state". * */ static VALUE grpc_rb_channel_watch_connectivity_state(VALUE self, VALUE last_state, VALUE deadline) { grpc_rb_channel* wrapper = NULL; watch_state_stack stack; void* op_success = 0; TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); if (wrapper->bg_wrapped == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } if (!FIXNUM_P(last_state)) { rb_raise( rb_eTypeError, "bad type for last_state. want a GRPC::Core::ChannelState constant"); return Qnil; } stack.bg_wrapped = wrapper->bg_wrapped; stack.deadline = grpc_rb_time_timeval(deadline, 0), stack.last_state = NUM2LONG(last_state); op_success = rb_thread_call_without_gvl( wait_for_watch_state_op_complete_without_gvl, &stack, wait_for_watch_state_op_complete_unblocking_func, wrapper->bg_wrapped); return op_success ? Qtrue : Qfalse; }
/* call-seq: creds = Credentials.new auth_proc proc: (required) Proc that generates auth metadata Initializes CallCredential instances. */ static VALUE grpc_rb_call_credentials_init(VALUE self, VALUE proc) { grpc_rb_call_credentials* wrapper = NULL; grpc_call_credentials* creds = NULL; grpc_metadata_credentials_plugin plugin; grpc_ruby_once_init(); TypedData_Get_Struct(self, grpc_rb_call_credentials, &grpc_rb_call_credentials_data_type, wrapper); plugin.get_metadata = grpc_rb_call_credentials_plugin_get_metadata; plugin.destroy = grpc_rb_call_credentials_plugin_destroy; if (!rb_obj_is_proc(proc)) { rb_raise(rb_eTypeError, "Argument to CallCredentials#new must be a proc"); return Qnil; } plugin.state = (void*)proc; plugin.type = ""; creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL); if (creds == NULL) { rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why"); return Qnil; } wrapper->mark = proc; wrapper->wrapped = creds; rb_ivar_set(self, id_callback, proc); return self; }
int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) { MessageHeader* self; char *name; const upb_fielddef* f; TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); if (TYPE(key) == T_STRING) { name = RSTRING_PTR(key); } else if (TYPE(key) == T_SYMBOL) { name = RSTRING_PTR(rb_id2str(SYM2ID(key))); } else { rb_raise(rb_eArgError, "Expected string or symbols as hash keys when initializing proto from hash."); } f = upb_msgdef_ntofz(self->descriptor->msgdef, name); if (f == NULL) { rb_raise(rb_eArgError, "Unknown field name '%s' in initialization map entry.", name); } if (TYPE(val) == T_NIL) { return 0; } if (is_map_field(f)) { VALUE map; if (TYPE(val) != T_HASH) { rb_raise(rb_eArgError, "Expected Hash object as initializer value for map field '%s'.", name); } map = layout_get(self->descriptor->layout, Message_data(self), f); Map_merge_into_self(map, val); } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) { VALUE ary; if (TYPE(val) != T_ARRAY) { rb_raise(rb_eArgError, "Expected array as initializer value for repeated field '%s'.", name); } ary = layout_get(self->descriptor->layout, Message_data(self), f); for (int i = 0; i < RARRAY_LEN(val); i++) { VALUE entry = rb_ary_entry(val, i); if (TYPE(entry) == T_HASH && upb_fielddef_issubmsg(f)) { entry = create_submsg_from_hash(f, entry); } RepeatedField_push(ary, entry); } } else { if (TYPE(val) == T_HASH && upb_fielddef_issubmsg(f)) { val = create_submsg_from_hash(f, val); } layout_set(self->descriptor->layout, Message_data(self), f, val); } return 0; }