Grpc-XS
view release on metacpan or search on metacpan
metadata->capacity = 0;
hv_iterinit(hash);
while((value = hv_iternextsv(hash,&key,&keylen))!=NULL) {
if (!SvROK(value)) {
warn("expected array ref in metadata value %s, ignoring...",key);
continue;
}
value = SvRV(value);
if (SvTYPE(value)!=SVt_PVAV) {
warn("expected array ref in metadata value %s, ignoring...",key);
continue;
}
metadata->capacity += av_len((AV*)value)+1;
}
if(metadata->capacity > 0) {
metadata->metadata = gpr_malloc(metadata->capacity * sizeof(grpc_metadata));
} else {
metadata->metadata = NULL;
return TRUE;
}
metadata->count = 0;
hv_iterinit(hash);
while((value = hv_iternextsv(hash,&key,&keylen))!=NULL) {
if (!SvROK(value)) {
//warn("expected array ref in metadata value %s, ignoring...",key);
continue;
}
value = SvRV(value);
if (SvTYPE(value)!=SVt_PVAV) {
//warn("expected array ref in metadata value %s, ignoring...",key);
continue;
}
for(i=0;i<av_len((AV*)value)+1;i++) {
SV** inner_value = av_fetch((AV*)value,i,1);
if (SvOK(*inner_value)) {
#if defined(GRPC_VERSION_1_2)
metadata->metadata[metadata->count].key = grpc_slice_from_copied_string(key);
metadata->metadata[metadata->count].value =
grpc_slice_from_sv(*inner_value);
#else
metadata->metadata[metadata->count].key = key;
metadata->metadata[metadata->count].value =
strdup(SvPV(*inner_value,metadata->metadata[metadata->count].value_length));
#endif
metadata->count += 1;
} else {
warn("args values must be int or string");
return FALSE;
}
}
}
return TRUE;
}
/* Callback function for plugin creds API */
#if defined(GRPC_VERSION_1_7)
int plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data,
grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
size_t *num_creds_md, grpc_status_code *status,
const char **error_details) {
#else
void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb,
void *user_data) {
#endif
static char error_details_buf[1024];
SV* callback = (SV*)ptr;
SV* err_tmp;
int has_error = FALSE;
char *error_details_out = NULL;
grpc_metadata_array metadata;
dSP;
ENTER;
HV* hash = newHV();
hv_stores(hash,"service_url", newSVpv(context.service_url,0));
hv_stores(hash,"method_name", newSVpv(context.method_name,0));
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal((SV*)newRV_noinc((SV*)hash)));
PUTBACK;
int count = perl_call_sv(callback, G_SCALAR|G_EVAL);
SPAGAIN;
err_tmp = ERRSV;
if (SvTRUE(err_tmp)) {
has_error = TRUE;
my_strlcpy(error_details_buf, SvPV_nolen(err_tmp), sizeof(error_details_buf));
error_details_out = error_details_buf;
POPs;
} else if (count!=1) {
has_error = TRUE;
error_details_out = "callback returned more/less than 1 value";
POPs;
} else {
SV* retval = POPs;
if (SvROK(retval)) { // create_metadata_array() segfaults without this check
if (!create_metadata_array((HV*)SvRV(retval), &metadata)) {
has_error = TRUE;
error_details_out = "callback returned invalid metadata";
grpc_metadata_array_destroy(&metadata);
}
} else {
has_error = TRUE;
error_details_out = "calback returned non-reference";
}
}
PUTBACK;
FREETMPS;
LEAVE;
// TODO Documentation says that for GRPC_VERSION_1_7-style API a
// callback MUST be called from a different thread. This doesn't
// crash right now, but definitely should be fixed.
// GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX is 4, so we can return
// up to that amount of metadata items synchronously.
if ( has_error ) {
grpc_status_code code = GRPC_STATUS_INVALID_ARGUMENT;
( run in 1.012 second using v1.01-cache-2.11-cpan-5837b0d9d2c )