static void plugin_md_request_metadata_ready(void *request, const grpc_metadata *md, size_t num_md, grpc_status_code status, const char *error_details) { /* called from application code */ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request; if (status != GRPC_STATUS_OK) { if (error_details != NULL) { gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s", error_details); } r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, error_details); } else { size_t i; bool seen_illegal_header = false; grpc_credentials_md *md_array = NULL; for (i = 0; i < num_md; i++) { if (!grpc_header_key_is_legal(md[i].key, strlen(md[i].key))) { gpr_log(GPR_ERROR, "Plugin added invalid metadata key: %s", md[i].key); seen_illegal_header = true; break; } else if (!grpc_is_binary_header(md[i].key, strlen(md[i].key)) && !grpc_header_nonbin_value_is_legal(md[i].value, md[i].value_length)) { gpr_log(GPR_ERROR, "Plugin added invalid metadata value."); seen_illegal_header = true; break; } } if (seen_illegal_header) { r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR, "Illegal metadata"); } else if (num_md > 0) { md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md)); for (i = 0; i < num_md; i++) { md_array[i].key = gpr_slice_from_copied_string(md[i].key); md_array[i].value = gpr_slice_from_copied_buffer(md[i].value, md[i].value_length); } r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK, NULL); for (i = 0; i < num_md; i++) { gpr_slice_unref(md_array[i].key); gpr_slice_unref(md_array[i].value); } gpr_free(md_array); } } gpr_free(r); grpc_exec_ctx_finish(&exec_ctx); }
/* grpc_rb_md_ary_fill_hash_cb is the hash iteration callback used to fill grpc_metadata_array. it's capacity should have been computed via a prior call to grpc_rb_md_ary_fill_hash_cb */ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) { grpc_metadata_array *md_ary = NULL; long array_length; long i; grpc_slice key_slice; grpc_slice value_slice; char *tmp_str; if (TYPE(key) == T_SYMBOL) { key_slice = grpc_slice_from_static_string(rb_id2name(SYM2ID(key))); } else if (TYPE(key) == T_STRING) { key_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(key), RSTRING_LEN(key)); } else { rb_raise(rb_eTypeError, "grpc_rb_md_ary_fill_hash_cb: bad type for key parameter"); } if (!grpc_header_key_is_legal(key_slice)) { tmp_str = grpc_slice_to_c_string(key_slice); rb_raise(rb_eArgError, "'%s' is an invalid header key, must match [a-z0-9-_.]+", tmp_str); return ST_STOP; } /* Construct a metadata object from key and value and add it */ TypedData_Get_Struct(md_ary_obj, grpc_metadata_array, &grpc_rb_md_ary_data_type, md_ary); if (TYPE(val) == T_ARRAY) { array_length = RARRAY_LEN(val); /* If the value is an array, add capacity for each value in the array */ for (i = 0; i < array_length; i++) { value_slice = grpc_slice_from_copied_buffer( RSTRING_PTR(rb_ary_entry(val, i)), RSTRING_LEN(rb_ary_entry(val, i))); if (!grpc_is_binary_header(key_slice) && !grpc_header_nonbin_value_is_legal(value_slice)) { // The value has invalid characters tmp_str = grpc_slice_to_c_string(value_slice); rb_raise(rb_eArgError, "Header value '%s' has invalid characters", tmp_str); return ST_STOP; } md_ary->metadata[md_ary->count].key = key_slice; md_ary->metadata[md_ary->count].value = value_slice; md_ary->count += 1; } } else if (TYPE(val) == T_STRING) { value_slice = grpc_slice_from_copied_buffer(RSTRING_PTR(val), RSTRING_LEN(val)); if (!grpc_is_binary_header(key_slice) && !grpc_header_nonbin_value_is_legal(value_slice)) { // The value has invalid characters tmp_str = grpc_slice_to_c_string(value_slice); rb_raise(rb_eArgError, "Header value '%s' has invalid characters", tmp_str); return ST_STOP; } md_ary->metadata[md_ary->count].key = key_slice; md_ary->metadata[md_ary->count].value = value_slice; md_ary->count += 1; } else { rb_raise(rb_eArgError, "Header values must be of type string or array"); return ST_STOP; } return ST_CONTINUE; }
/* grpc_rb_md_ary_fill_hash_cb is the hash iteration callback used to fill grpc_metadata_array. it's capacity should have been computed via a prior call to grpc_rb_md_ary_fill_hash_cb */ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) { grpc_metadata_array *md_ary = NULL; long array_length; long i; char *key_str; size_t key_len; char *value_str; size_t value_len; if (TYPE(key) == T_SYMBOL) { key_str = (char *)rb_id2name(SYM2ID(key)); key_len = strlen(key_str); } else { /* StringValueCStr does all other type exclusions for us */ key_str = StringValueCStr(key); key_len = RSTRING_LEN(key); } if (!grpc_header_key_is_legal(key_str, key_len)) { rb_raise(rb_eArgError, "'%s' is an invalid header key, must match [a-z0-9-_.]+", key_str); return ST_STOP; } /* Construct a metadata object from key and value and add it */ TypedData_Get_Struct(md_ary_obj, grpc_metadata_array, &grpc_rb_md_ary_data_type, md_ary); if (TYPE(val) == T_ARRAY) { array_length = RARRAY_LEN(val); /* If the value is an array, add capacity for each value in the array */ for (i = 0; i < array_length; i++) { value_str = RSTRING_PTR(rb_ary_entry(val, i)); value_len = RSTRING_LEN(rb_ary_entry(val, i)); if (!grpc_is_binary_header(key_str, key_len) && !grpc_header_nonbin_value_is_legal(value_str, value_len)) { // The value has invalid characters rb_raise(rb_eArgError, "Header value '%s' has invalid characters", value_str); return ST_STOP; } md_ary->metadata[md_ary->count].key = key_str; md_ary->metadata[md_ary->count].value = value_str; md_ary->metadata[md_ary->count].value_length = value_len; md_ary->count += 1; } } else { value_str = RSTRING_PTR(val); value_len = RSTRING_LEN(val); if (!grpc_is_binary_header(key_str, key_len) && !grpc_header_nonbin_value_is_legal(value_str, value_len)) { // The value has invalid characters rb_raise(rb_eArgError, "Header value '%s' has invalid characters", value_str); return ST_STOP; } md_ary->metadata[md_ary->count].key = key_str; md_ary->metadata[md_ary->count].value = value_str; md_ary->metadata[md_ary->count].value_length = value_len; md_ary->count += 1; } return ST_CONTINUE; }