static void grpc_rb_call_credentials_callback_with_gil(void* param) { callback_params* const params = (callback_params*)param; VALUE auth_uri = rb_str_new_cstr(params->context.service_url); /* Pass the arguments to the proc in a hash, which currently only has they key 'auth_uri' */ VALUE callback_args = rb_ary_new(); VALUE args = rb_hash_new(); VALUE result; grpc_metadata_array md_ary; grpc_status_code status; VALUE details; char* error_details; grpc_metadata_array_init(&md_ary); rb_hash_aset(args, ID2SYM(rb_intern("jwt_aud_uri")), auth_uri); rb_ary_push(callback_args, params->get_metadata); rb_ary_push(callback_args, args); result = rb_rescue(grpc_rb_call_credentials_callback, callback_args, grpc_rb_call_credentials_callback_rescue, Qnil); // Both callbacks return a hash, so result should be a hash grpc_rb_md_ary_convert(rb_hash_aref(result, rb_str_new2("metadata")), &md_ary); status = NUM2INT(rb_hash_aref(result, rb_str_new2("status"))); details = rb_hash_aref(result, rb_str_new2("details")); error_details = StringValueCStr(details); params->callback(params->user_data, md_ary.metadata, md_ary.count, status, error_details); grpc_rb_metadata_array_destroy_including_entries(&md_ary); gpr_free(params); }
/* grpc_rb_op_update_status_from_server adds the values in a ruby status struct to the 'send_status_from_server' portion of an op. */ static void grpc_rb_op_update_status_from_server( grpc_op *op, grpc_metadata_array *md_ary, grpc_slice *send_status_details, VALUE status) { VALUE code = rb_struct_aref(status, sym_code); VALUE details = rb_struct_aref(status, sym_details); VALUE metadata_hash = rb_struct_aref(status, sym_metadata); /* TODO: add check to ensure status is the correct struct type */ if (TYPE(code) != T_FIXNUM) { rb_raise(rb_eTypeError, "invalid code : got <%s>, want <Fixnum>", rb_obj_classname(code)); return; } if (TYPE(details) != T_STRING) { rb_raise(rb_eTypeError, "invalid details : got <%s>, want <String>", rb_obj_classname(code)); return; } *send_status_details = grpc_slice_from_copied_buffer(RSTRING_PTR(details), RSTRING_LEN(details)); op->data.send_status_from_server.status = NUM2INT(code); op->data.send_status_from_server.status_details = send_status_details; grpc_rb_md_ary_convert(metadata_hash, md_ary); op->data.send_status_from_server.trailing_metadata_count = md_ary->count; op->data.send_status_from_server.trailing_metadata = md_ary->metadata; }
/* grpc_run_batch_stack_fill_ops fills the run_batch_stack ops array from * ops_hash */ static void grpc_run_batch_stack_fill_ops(run_batch_stack *st, VALUE ops_hash) { VALUE this_op = Qnil; VALUE this_value = Qnil; VALUE ops_ary = rb_ary_new(); size_t i = 0; /* Create a ruby array with just the operation keys */ rb_hash_foreach(ops_hash, grpc_rb_call_check_op_keys_hash_cb, ops_ary); /* Fill the ops array */ for (i = 0; i < (size_t)RARRAY_LEN(ops_ary); i++) { this_op = rb_ary_entry(ops_ary, i); this_value = rb_hash_aref(ops_hash, this_op); switch (NUM2INT(this_op)) { case GRPC_OP_SEND_INITIAL_METADATA: /* N.B. later there is no need to explicitly delete the metadata keys * and values, they are references to data in ruby objects. */ grpc_rb_md_ary_convert(this_value, &st->send_metadata); st->ops[st->op_num].data.send_initial_metadata.count = st->send_metadata.count; st->ops[st->op_num].data.send_initial_metadata.metadata = st->send_metadata.metadata; break; case GRPC_OP_SEND_MESSAGE: st->ops[st->op_num].data.send_message = grpc_rb_s_to_byte_buffer( RSTRING_PTR(this_value), RSTRING_LEN(this_value)); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: break; case GRPC_OP_SEND_STATUS_FROM_SERVER: /* N.B. later there is no need to explicitly delete the metadata keys * and values, they are references to data in ruby objects. */ grpc_rb_op_update_status_from_server( &st->ops[st->op_num], &st->send_trailing_metadata, this_value); break; case GRPC_OP_RECV_INITIAL_METADATA: st->ops[st->op_num].data.recv_initial_metadata = &st->recv_metadata; break; case GRPC_OP_RECV_MESSAGE: st->ops[st->op_num].data.recv_message = &st->recv_message; break; case GRPC_OP_RECV_STATUS_ON_CLIENT: st->ops[st->op_num].data.recv_status_on_client.trailing_metadata = &st->recv_trailing_metadata; st->ops[st->op_num].data.recv_status_on_client.status = &st->recv_status; st->ops[st->op_num].data.recv_status_on_client.status_details = &st->recv_status_details; st->ops[st->op_num].data.recv_status_on_client.status_details_capacity = &st->recv_status_details_capacity; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: st->ops[st->op_num].data.recv_close_on_server.cancelled = &st->recv_cancelled; break; default: grpc_run_batch_stack_cleanup(st); rb_raise(rb_eTypeError, "invalid operation : bad value %d", NUM2INT(this_op)); }; st->ops[st->op_num].op = (grpc_op_type)NUM2INT(this_op); st->ops[st->op_num].flags = 0; st->op_num++; } }