/* 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;
}
Exemple #2
0
/*
 * 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));
}
Exemple #3
0
// 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;
}
Exemple #4
0
// 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;
}
Exemple #6
0
/*
  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);
}
Exemple #7
0
/*
  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;
}
Exemple #8
0
/* 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;
}
Exemple #9
0
/*
 * 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;
}
Exemple #10
0
/*
 * @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);
  }
}
Exemple #11
0
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;
}
Exemple #12
0
/*
 * @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);
}
Exemple #13
0
/* 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);
}
Exemple #14
0
/* 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);
}
Exemple #15
0
/* 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;
}
Exemple #16
0
// 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;
}
Exemple #17
0
/* 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;
}
Exemple #18
0
/*
 * 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;
}
Exemple #19
0
/*
 * @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;
}
Exemple #20
0
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;
}
Exemple #22
0
/* 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;
}
Exemple #23
0
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;
}
Exemple #24
0
/*
  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;
}
Exemple #25
0
static rb_tp_t *
tpptr(VALUE tpval)
{
    rb_tp_t *tp;
    TypedData_Get_Struct(tpval, rb_tp_t, &tp_data_type, tp);
    return tp;
}
Exemple #26
0
/*
  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;
}
Exemple #27
0
/*
  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;
}
Exemple #28
0
/* 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;
}
Exemple #30
0
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;
}