Exemple #1
0
static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
                              grpc_mdelem *md) {
  grpc_chttp2_transport *t = tp;
  grpc_chttp2_stream *s = t->incoming_stream;

  GPR_TIMER_BEGIN("on_initial_header", 0);

  GPR_ASSERT(s != NULL);

  GRPC_CHTTP2_IF_TRACING(gpr_log(
      GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR",
      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));

  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
    /* TODO(ctiller): check for a status like " 0" */
    s->seen_error = true;
  }

  if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
    gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
    if (!cached_timeout) {
      /* not already parsed: parse it now, and store the result away */
      cached_timeout = gpr_malloc(sizeof(gpr_timespec));
      if (!grpc_http2_decode_timeout(grpc_mdstr_as_c_string(md->value),
                                     cached_timeout)) {
        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
                grpc_mdstr_as_c_string(md->value));
        *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
      }
      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
    }
    grpc_chttp2_incoming_metadata_buffer_set_deadline(
        &s->metadata_buffer[0],
        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
    GRPC_MDELEM_UNREF(md);
  } else {
    const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
    const size_t metadata_size_limit =
        t->settings[GRPC_ACKED_SETTINGS]
                   [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
    if (new_size > metadata_size_limit) {
      gpr_log(GPR_DEBUG,
              "received initial metadata size exceeds limit (%" PRIuPTR
              " vs. %" PRIuPTR ")",
              new_size, metadata_size_limit);
      grpc_chttp2_cancel_stream(
          exec_ctx, t, s,
          grpc_error_set_int(
              GRPC_ERROR_CREATE("received initial metadata size exceeds limit"),
              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
      grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
      s->seen_error = true;
      GRPC_MDELEM_UNREF(md);
    } else {
      grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md);
    }
  }

  GPR_TIMER_END("on_initial_header", 0);
}
Exemple #2
0
static void test_user_data_works(void) {
  int *ud1;
  int *ud2;
  grpc_mdelem *md;
  LOG_TEST("test_user_data_works");

  grpc_init();
  ud1 = gpr_malloc(sizeof(int));
  *ud1 = 1;
  ud2 = gpr_malloc(sizeof(int));
  *ud2 = 2;
  md = grpc_mdelem_from_strings("abc", "123");
  grpc_mdelem_set_user_data(md, gpr_free, ud1);
  grpc_mdelem_set_user_data(md, gpr_free, ud2);
  GPR_ASSERT(grpc_mdelem_get_user_data(md, gpr_free) == ud1);
  GRPC_MDELEM_UNREF(md);
  grpc_shutdown();
}
Exemple #3
0
static gpr_uint32 decode_status(grpc_mdelem *md) {
  gpr_uint32 status;
  void *user_data = grpc_mdelem_get_user_data(md, destroy_status);
  if (user_data) {
    status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET;
  } else {
    if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value),
                                   GPR_SLICE_LENGTH(md->value->slice),
                                   &status)) {
      status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
    }
    grpc_mdelem_set_user_data(md, destroy_status,
                              (void *)(gpr_intptr)(status + STATUS_OFFSET));
  }
  return status;
}
Exemple #4
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 #5
0
static void on_initial_header(void *tp, grpc_mdelem *md) {
  grpc_chttp2_transport_parsing *transport_parsing = tp;
  grpc_chttp2_stream_parsing *stream_parsing =
      transport_parsing->incoming_stream;

  GPR_TIMER_BEGIN("on_initial_header", 0);

  GPR_ASSERT(stream_parsing);

  GRPC_CHTTP2_IF_TRACING(gpr_log(
      GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
      transport_parsing->is_client ? "CLI" : "SVR",
      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));

  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
    /* TODO(ctiller): check for a status like " 0" */
    stream_parsing->seen_error = 1;
  }

  if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
    gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
    if (!cached_timeout) {
      /* not already parsed: parse it now, and store the result away */
      cached_timeout = gpr_malloc(sizeof(gpr_timespec));
      if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
                                      cached_timeout)) {
        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
                grpc_mdstr_as_c_string(md->value));
        *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
      }
      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
    }
    grpc_chttp2_incoming_metadata_buffer_set_deadline(
        &stream_parsing->metadata_buffer[0],
        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
    GRPC_MDELEM_UNREF(md);
  } else {
    grpc_chttp2_incoming_metadata_buffer_add(
        &stream_parsing->metadata_buffer[0], md);
  }

  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);

  GPR_TIMER_END("on_initial_header", 0);
}
Exemple #6
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 #7
0
static void on_header(void *tp, grpc_mdelem *md) {
    grpc_chttp2_transport_parsing *transport_parsing = tp;
    grpc_chttp2_stream_parsing *stream_parsing =
        transport_parsing->incoming_stream;

    GPR_ASSERT(stream_parsing);

    GRPC_CHTTP2_IF_TRACING(gpr_log(
                               GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
                               transport_parsing->is_client ? "CLI" : "SVR",
                               grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));

    if (md->key == transport_parsing->str_grpc_timeout) {
        gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
        if (!cached_timeout) {
            /* not already parsed: parse it now, and store the result away */
            cached_timeout = gpr_malloc(sizeof(gpr_timespec));
            if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
                                            cached_timeout)) {
                gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
                        grpc_mdstr_as_c_string(md->value));
                *cached_timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
            }
            grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
        }
        grpc_chttp2_incoming_metadata_buffer_set_deadline(
            &stream_parsing->incoming_metadata,
            gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), *cached_timeout));
        GRPC_MDELEM_UNREF(md);
    } else {
        grpc_chttp2_incoming_metadata_buffer_add(&stream_parsing->incoming_metadata,
                md);
    }

    grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);
}
Exemple #8
0
static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
                              grpc_mdelem md) {
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
  grpc_chttp2_stream *s = t->incoming_stream;

  GPR_TIMER_BEGIN("on_initial_header", 0);

  GPR_ASSERT(s != NULL);

  if (GRPC_TRACER_ON(grpc_http_trace)) {
    char *key = grpc_slice_to_c_string(GRPC_MDKEY(md));
    char *value =
        grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
    gpr_log(GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id,
            t->is_client ? "CLI" : "SVR", key, value);
    gpr_free(key);
    gpr_free(value);
  }

  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) &&
      !grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) {
    /* TODO(ctiller): check for a status like " 0" */
    s->seen_error = true;
  }

  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
    gpr_timespec *cached_timeout =
        (gpr_timespec *)grpc_mdelem_get_user_data(md, free_timeout);
    gpr_timespec timeout;
    if (cached_timeout == NULL) {
      /* not already parsed: parse it now, and store the result away */
      cached_timeout = (gpr_timespec *)gpr_malloc(sizeof(gpr_timespec));
      if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), cached_timeout)) {
        char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
        gpr_free(val);
        *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
      }
      timeout = *cached_timeout;
      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
    } else {
      timeout = *cached_timeout;
    }
    grpc_chttp2_incoming_metadata_buffer_set_deadline(
        &s->metadata_buffer[0],
        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), timeout));
    GRPC_MDELEM_UNREF(exec_ctx, md);
  } else {
    const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
    const size_t metadata_size_limit =
        t->settings[GRPC_ACKED_SETTINGS]
                   [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
    if (new_size > metadata_size_limit) {
      gpr_log(GPR_DEBUG,
              "received initial metadata size exceeds limit (%" PRIuPTR
              " vs. %" PRIuPTR ")",
              new_size, metadata_size_limit);
      grpc_chttp2_cancel_stream(
          exec_ctx, t, s,
          grpc_error_set_int(
              GRPC_ERROR_CREATE_FROM_STATIC_STRING(
                  "received initial metadata size exceeds limit"),
              GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
      grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
      s->seen_error = true;
      GRPC_MDELEM_UNREF(exec_ctx, md);
    } else {
      grpc_error *error = grpc_chttp2_incoming_metadata_buffer_add(
          exec_ctx, &s->metadata_buffer[0], md);
      if (error != GRPC_ERROR_NONE) {
        grpc_chttp2_cancel_stream(exec_ctx, t, s, error);
        grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
        s->seen_error = true;
        GRPC_MDELEM_UNREF(exec_ctx, md);
      }
    }
  }

  GPR_TIMER_END("on_initial_header", 0);
}
static void on_initial_header(void *tp, grpc_mdelem *md) {
  grpc_chttp2_transport_parsing *transport_parsing = tp;
  grpc_chttp2_stream_parsing *stream_parsing =
      transport_parsing->incoming_stream;

  GPR_TIMER_BEGIN("on_initial_header", 0);

  GPR_ASSERT(stream_parsing);

  GRPC_CHTTP2_IF_TRACING(gpr_log(
      GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", stream_parsing->id,
      transport_parsing->is_client ? "CLI" : "SVR",
      grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)));

  if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) {
    /* TODO(ctiller): check for a status like " 0" */
    stream_parsing->seen_error = true;
  }

  if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) {
    gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
    if (!cached_timeout) {
      /* not already parsed: parse it now, and store the result away */
      cached_timeout = gpr_malloc(sizeof(gpr_timespec));
      if (!grpc_chttp2_decode_timeout(grpc_mdstr_as_c_string(md->value),
                                      cached_timeout)) {
        gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'",
                grpc_mdstr_as_c_string(md->value));
        *cached_timeout = gpr_inf_future(GPR_TIMESPAN);
      }
      grpc_mdelem_set_user_data(md, free_timeout, cached_timeout);
    }
    grpc_chttp2_incoming_metadata_buffer_set_deadline(
        &stream_parsing->metadata_buffer[0],
        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout));
    GRPC_MDELEM_UNREF(md);
  } else {
    const size_t new_size =
        stream_parsing->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md);
    grpc_chttp2_transport_global *transport_global =
        &TRANSPORT_FROM_PARSING(transport_parsing)->global;
    const size_t metadata_size_limit =
        transport_global->settings[GRPC_LOCAL_SETTINGS]
                                  [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
    if (new_size > metadata_size_limit) {
      if (!stream_parsing->exceeded_metadata_size) {
        gpr_log(GPR_DEBUG,
                "received initial metadata size exceeds limit (%" PRIuPTR
                " vs. %" PRIuPTR ")",
                new_size, metadata_size_limit);
        stream_parsing->seen_error = true;
        stream_parsing->exceeded_metadata_size = true;
      }
      GRPC_MDELEM_UNREF(md);
    } else {
      grpc_chttp2_incoming_metadata_buffer_add(
          &stream_parsing->metadata_buffer[0], md);
    }
  }

  grpc_chttp2_list_add_parsing_seen_stream(transport_parsing, stream_parsing);

  GPR_TIMER_END("on_initial_header", 0);
}