static void test_compression_algorithm_parse(void) {
  size_t i;
  const char *valid_names[] = {"identity", "gzip", "deflate"};
  const grpc_compression_algorithm valid_algorithms[] = {
      GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_DEFLATE};
  const char *invalid_names[] = {"gzip2", "foo", "", "2gzip"};

  gpr_log(GPR_DEBUG, "test_compression_algorithm_parse");

  for (i = 0; i < GPR_ARRAY_SIZE(valid_names); i++) {
    const char *valid_name = valid_names[i];
    grpc_compression_algorithm algorithm;
    const int success = grpc_compression_algorithm_parse(
        valid_name, strlen(valid_name), &algorithm);
    GPR_ASSERT(success != 0);
    GPR_ASSERT(algorithm == valid_algorithms[i]);
  }

  for (i = 0; i < GPR_ARRAY_SIZE(invalid_names); i++) {
    const char *invalid_name = invalid_names[i];
    grpc_compression_algorithm algorithm;
    int success;
    success = grpc_compression_algorithm_parse(
        invalid_name, strlen(invalid_name), &algorithm);
    GPR_ASSERT(success == 0);
    /* the value of "algorithm" is undefined upon failure */
  }
}
Exemple #2
0
/** For each \a md element from the incoming metadata, filter out the entry for
 * "grpc-encoding", using its value to populate the call data's
 * compression_algorithm field. */
static grpc_mdelem *compression_md_filter(void *user_data, grpc_mdelem *md) {
    grpc_call_element *elem = user_data;
    call_data *calld = elem->call_data;
    channel_data *channeld = elem->channel_data;

    if (md->key == GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST) {
        const char *md_c_str = grpc_mdstr_as_c_string(md->value);
        if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
                                              &calld->compression_algorithm)) {
            gpr_log(GPR_ERROR,
                    "Invalid compression algorithm: '%s' (unknown). Ignoring.",
                    md_c_str);
            calld->compression_algorithm = GRPC_COMPRESS_NONE;
        }
        if (grpc_compression_options_is_algorithm_enabled(
                    &channeld->compression_options, calld->compression_algorithm) ==
                0) {
            gpr_log(GPR_ERROR,
                    "Invalid compression algorithm: '%s' (previously disabled). "
                    "Ignoring.",
                    md_c_str);
            calld->compression_algorithm = GRPC_COMPRESS_NONE;
        }
        calld->has_compression_algorithm = 1;
        return NULL;
    }

    return md;
}
Exemple #3
0
static void test_algorithm_mesh(void) {
  int i;

  gpr_log(GPR_DEBUG, "test_algorithm_mesh");

  for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) {
    const char *name;
    grpc_compression_algorithm parsed;
    grpc_slice mdstr;
    grpc_mdelem mdelem;
    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
    GPR_ASSERT(
        grpc_compression_algorithm_name((grpc_compression_algorithm)i, &name));
    GPR_ASSERT(grpc_compression_algorithm_parse(
        grpc_slice_from_static_string(name), &parsed));
    GPR_ASSERT((int)parsed == i);
    mdstr = grpc_slice_from_copied_string(name);
    GPR_ASSERT(grpc_slice_eq(mdstr, grpc_compression_algorithm_slice(parsed)));
    GPR_ASSERT(parsed == grpc_compression_algorithm_from_slice(mdstr));
    mdelem = grpc_compression_encoding_mdelem(parsed);
    GPR_ASSERT(grpc_slice_eq(GRPC_MDVALUE(mdelem), mdstr));
    GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_GRPC_ENCODING));
    grpc_slice_unref_internal(&exec_ctx, mdstr);
    GRPC_MDELEM_UNREF(&exec_ctx, mdelem);
    grpc_exec_ctx_finish(&exec_ctx);
  }

  /* test failure */
  GPR_ASSERT(GRPC_MDISNULL(
      grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT)));
}
/* Gets the internal value of a compression algorithm suitable as the value
 * in a GRPC core channel arguments hash.
 * algorithm_value is an out parameter.
 * Raises an error if the name of the algorithm passed in is invalid. */
void grpc_rb_compression_options_algorithm_name_to_value_internal(
    grpc_compression_algorithm* algorithm_value, VALUE algorithm_name) {
  grpc_slice name_slice;
  VALUE algorithm_name_as_string = Qnil;

  Check_Type(algorithm_name, T_SYMBOL);

  /* Convert the algorithm symbol to a ruby string, so that we can get the
   * correct C string out of it. */
  algorithm_name_as_string = rb_funcall(algorithm_name, rb_intern("to_s"), 0);

  name_slice =
      grpc_slice_from_copied_buffer(RSTRING_PTR(algorithm_name_as_string),
                                    RSTRING_LEN(algorithm_name_as_string));

  /* Raise an error if the name isn't recognized as a compression algorithm by
   * the algorithm parse function
   * in GRPC core. */
  if (!grpc_compression_algorithm_parse(name_slice, algorithm_value)) {
    char* name_slice_str = grpc_slice_to_c_string(name_slice);
    char* error_message_str = NULL;
    VALUE error_message_ruby_str = Qnil;
    GPR_ASSERT(gpr_asprintf(&error_message_str,
                            "Invalid compression algorithm name: %s",
                            name_slice_str) != -1);
    gpr_free(name_slice_str);
    error_message_ruby_str =
        rb_str_new(error_message_str, strlen(error_message_str));
    gpr_free(error_message_str);
    rb_raise(rb_eNameError, "%s", StringValueCStr(error_message_ruby_str));
  }

  grpc_slice_unref(name_slice);
}
static grpc_error *process_send_initial_metadata(
    grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
    grpc_metadata_batch *initial_metadata, bool *has_compression_algorithm) {
  call_data *calld = elem->call_data;
  channel_data *channeld = elem->channel_data;
  *has_compression_algorithm = false;
  /* Parse incoming request for compression. If any, it'll be available
   * at calld->compression_algorithm */
  if (initial_metadata->idx.named.grpc_internal_encoding_request != NULL) {
    grpc_mdelem md =
        initial_metadata->idx.named.grpc_internal_encoding_request->md;
    if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md),
                                          &calld->compression_algorithm)) {
      char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
      gpr_log(GPR_ERROR,
              "Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
      gpr_free(val);
      calld->compression_algorithm = GRPC_COMPRESS_NONE;
    }
    if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
                    calld->compression_algorithm)) {
      char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
      gpr_log(GPR_ERROR,
              "Invalid compression algorithm: '%s' (previously disabled). "
              "Ignoring.",
              val);
      gpr_free(val);
      calld->compression_algorithm = GRPC_COMPRESS_NONE;
    }
    *has_compression_algorithm = true;

    grpc_metadata_batch_remove(
        exec_ctx, initial_metadata,
        initial_metadata->idx.named.grpc_internal_encoding_request);
  } else {
    /* If no algorithm was found in the metadata and we aren't
     * exceptionally skipping compression, fall back to the channel
     * default */
    calld->compression_algorithm = channeld->default_compression_algorithm;
    *has_compression_algorithm = true;
  }

  grpc_error *error = GRPC_ERROR_NONE;
  /* hint compression algorithm */
  if (calld->compression_algorithm != GRPC_COMPRESS_NONE) {
    error = grpc_metadata_batch_add_tail(
        exec_ctx, initial_metadata, &calld->compression_algorithm_storage,
        grpc_compression_encoding_mdelem(calld->compression_algorithm));
  }

  if (error != GRPC_ERROR_NONE) return error;

  /* convey supported compression algorithms */
  error = grpc_metadata_batch_add_tail(
      exec_ctx, initial_metadata, &calld->accept_encoding_storage,
      GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
          channeld->supported_compression_algorithms));

  return error;
}
Exemple #6
0
static void set_encodings_accepted_by_peer(grpc_call *call, grpc_mdelem *mdel) {
  size_t i;
  grpc_compression_algorithm algorithm;
  gpr_slice_buffer accept_encoding_parts;
  gpr_slice accept_encoding_slice;
  void *accepted_user_data;

  accepted_user_data =
      grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
  if (accepted_user_data != NULL) {
    call->encodings_accepted_by_peer =
        (gpr_uint32)(((gpr_uintptr)accepted_user_data) - 1);
    return;
  }

  accept_encoding_slice = mdel->value->slice;
  gpr_slice_buffer_init(&accept_encoding_parts);
  gpr_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);

  /* No need to zero call->encodings_accepted_by_peer: grpc_call_create already
   * zeroes the whole grpc_call */
  /* Always support no compression */
  GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
  for (i = 0; i < accept_encoding_parts.count; i++) {
    const gpr_slice *accept_encoding_entry_slice =
        &accept_encoding_parts.slices[i];
    if (grpc_compression_algorithm_parse(
            (const char *)GPR_SLICE_START_PTR(*accept_encoding_entry_slice),
            GPR_SLICE_LENGTH(*accept_encoding_entry_slice), &algorithm)) {
      GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
    } else {
      char *accept_encoding_entry_str =
          gpr_dump_slice(*accept_encoding_entry_slice, GPR_DUMP_ASCII);
      gpr_log(GPR_ERROR,
              "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
              accept_encoding_entry_str);
      gpr_free(accept_encoding_entry_str);
    }
  }

  gpr_slice_buffer_destroy(&accept_encoding_parts);

  grpc_mdelem_set_user_data(
      mdel, destroy_encodings_accepted_by_peer,
      (void *)(((gpr_uintptr)call->encodings_accepted_by_peer) + 1));
}
Exemple #7
0
static gpr_uint32 decode_compression(grpc_mdelem *md) {
  grpc_compression_algorithm algorithm;
  void *user_data = grpc_mdelem_get_user_data(md, destroy_compression);
  if (user_data) {
    algorithm =
        ((grpc_compression_algorithm)(gpr_intptr)user_data) - COMPRESS_OFFSET;
  } else {
    const char *md_c_str = grpc_mdstr_as_c_string(md->value);
    if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
                                          &algorithm)) {
      gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'", md_c_str);
      assert(0);
    }
    grpc_mdelem_set_user_data(
        md, destroy_compression,
        (void *)(gpr_intptr)(algorithm + COMPRESS_OFFSET));
  }
  return algorithm;
}
Exemple #8
0
/** For each \a md element from the incoming metadata, filter out the entry for
 * "grpc-encoding", using its value to populate the call data's
 * compression_algorithm field. */
static grpc_mdelem *compression_md_filter(void *user_data, grpc_mdelem *md) {
    grpc_call_element *elem = user_data;
    call_data *calld = elem->call_data;
    channel_data *channeld = elem->channel_data;

    if (md->key == channeld->mdstr_request_compression_algorithm_key) {
        const char *md_c_str = grpc_mdstr_as_c_string(md->value);
        if (!grpc_compression_algorithm_parse(md_c_str, strlen(md_c_str),
                                              &calld->compression_algorithm)) {
            gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'. Ignoring.",
                    md_c_str);
            calld->compression_algorithm = GRPC_COMPRESS_NONE;
        }
        calld->has_compression_algorithm = 1;
        return NULL;
    }

    return md;
}