Grpc-XS

 view release on metacpan or  search on metacpan

util.c  view on Meta::CPAN

  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 )