コード例 #1
0
ファイル: parsing.c プロジェクト: endobson/grpc
static void on_trailing_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_trailing_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:TRL:%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;
  }

  const size_t new_size = s->metadata_buffer[1].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 trailing 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 trailing 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[1], 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_trailing_header", 0);
}
コード例 #2
0
ファイル: chttp2_transport.c プロジェクト: rootusr/grpc
static void remove_stream(grpc_chttp2_transport *t, gpr_uint32 id) {
  size_t new_stream_count;
  grpc_chttp2_stream *s =
      grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
  if (!s) {
    s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
  }
  grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
  GPR_ASSERT(s);
  s->global.in_stream_map = 0;
  if (t->parsing.incoming_stream == &s->parsing) {
    t->parsing.incoming_stream = NULL;
    grpc_chttp2_parsing_become_skip_parser(&t->parsing);
  }
  if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
    close_transport_locked(t);
  }

  new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
                     grpc_chttp2_stream_map_size(&t->new_stream_map);
  if (new_stream_count != t->global.concurrent_stream_count) {
    t->global.concurrent_stream_count = new_stream_count;
    maybe_start_some_streams(&t->global);
  }
}
コード例 #3
0
ファイル: parsing.c プロジェクト: endobson/grpc
static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx,
                                     grpc_chttp2_transport *t, grpc_slice slice,
                                     int is_last) {
  grpc_chttp2_stream *s = t->incoming_stream;
  grpc_error *err = t->parser(exec_ctx, t->parser_data, t, s, slice, is_last);
  if (err == GRPC_ERROR_NONE) {
    return err;
  } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
    if (GRPC_TRACER_ON(grpc_http_trace)) {
      const char *msg = grpc_error_string(err);
      gpr_log(GPR_ERROR, "%s", msg);
    }
    grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
    if (s) {
      s->forced_close_error = err;
      grpc_slice_buffer_add(
          &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
                                                  GRPC_HTTP2_PROTOCOL_ERROR,
                                                  &s->stats.outgoing));
    } else {
      GRPC_ERROR_UNREF(err);
    }
  }
  return err;
}
コード例 #4
0
static grpc_error *parse_frame_slice(
    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
    gpr_slice slice, int is_last) {
  grpc_chttp2_stream_parsing *stream_parsing =
      transport_parsing->incoming_stream;
  grpc_error *err = transport_parsing->parser(
      exec_ctx, transport_parsing->parser_data, transport_parsing,
      stream_parsing, slice, is_last);
  if (err == GRPC_ERROR_NONE) {
    if (stream_parsing) {
      grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
                                               stream_parsing);
    }
    return GRPC_ERROR_NONE;
  } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
    if (grpc_http_trace) {
      const char *msg = grpc_error_string(err);
      gpr_log(GPR_ERROR, "%s", msg);
      grpc_error_free_string(msg);
    }
    grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
    if (stream_parsing) {
      stream_parsing->forced_close_error = err;
      gpr_slice_buffer_add(
          &transport_parsing->qbuf,
          grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
                                        GRPC_CHTTP2_PROTOCOL_ERROR,
                                        &stream_parsing->stats.outgoing));
    } else {
      GRPC_ERROR_UNREF(err);
    }
  }
  return err;
}
コード例 #5
0
ファイル: parsing.c プロジェクト: xincun/grpc
static int parse_frame_slice(grpc_chttp2_transport_parsing *transport_parsing,
                             gpr_slice slice, int is_last) {
    grpc_chttp2_stream_parsing *stream_parsing =
        transport_parsing->incoming_stream;
    switch (transport_parsing->parser(transport_parsing->parser_data,
                                      transport_parsing, stream_parsing, slice,
                                      is_last)) {
    case GRPC_CHTTP2_PARSE_OK:
        if (stream_parsing) {
            grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
                    stream_parsing);
        }
        return 1;
    case GRPC_CHTTP2_STREAM_ERROR:
        grpc_chttp2_parsing_become_skip_parser(transport_parsing);
        if (stream_parsing) {
            stream_parsing->saw_rst_stream = 1;
            stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
            gpr_slice_buffer_add(
                &transport_parsing->qbuf,
                grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
                                              GRPC_CHTTP2_PROTOCOL_ERROR));
        }
        return 1;
    case GRPC_CHTTP2_CONNECTION_ERROR:
        return 0;
    }
    gpr_log(GPR_ERROR, "should never reach here");
    abort();
    return 0;
}
コード例 #6
0
ファイル: parsing.c プロジェクト: andrewpollock/grpc
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);
}
コード例 #7
0
ファイル: parsing.c プロジェクト: github188/grpc
static int parse_frame_slice(grpc_exec_ctx *exec_ctx,
                             grpc_chttp2_transport_parsing *transport_parsing,
                             gpr_slice slice, int is_last) {
  grpc_chttp2_stream_parsing *stream_parsing =
      transport_parsing->incoming_stream;
  switch (transport_parsing->parser(exec_ctx, transport_parsing->parser_data,
                                    transport_parsing, stream_parsing, slice,
                                    is_last)) {
    case GRPC_CHTTP2_PARSE_OK:
      if (stream_parsing) {
        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
                                                 stream_parsing);
      }
      return 1;
    case GRPC_CHTTP2_STREAM_ERROR:
      grpc_chttp2_parsing_become_skip_parser(exec_ctx, transport_parsing);
      if (stream_parsing) {
        stream_parsing->saw_rst_stream = 1;
        stream_parsing->rst_stream_reason = GRPC_CHTTP2_PROTOCOL_ERROR;
        gpr_slice_buffer_add(
            &transport_parsing->qbuf,
            grpc_chttp2_rst_stream_create(transport_parsing->incoming_stream_id,
                                          GRPC_CHTTP2_PROTOCOL_ERROR));
      }
      return 1;
    case GRPC_CHTTP2_CONNECTION_ERROR:
      return 0;
  }
  GPR_UNREACHABLE_CODE(return 0);
}
コード例 #8
0
ファイル: parsing.c プロジェクト: andrewpollock/grpc
static void on_trailing_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_trailing_header", 0);

  GPR_ASSERT(s != NULL);

  GRPC_CHTTP2_IF_TRACING(gpr_log(
      GPR_INFO, "HTTP:%d:TRL:%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;
  }

  const size_t new_size = s->metadata_buffer[1].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 trailing 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 trailing 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[1], md);
  }

  GPR_TIMER_END("on_trailing_header", 0);
}
コード例 #9
0
ファイル: chttp2_transport.c プロジェクト: lokicui/grpc
static void remove_stream(grpc_chttp2_transport *t, gpr_uint32 id) {
  size_t new_stream_count;
  grpc_chttp2_stream *s =
      grpc_chttp2_stream_map_delete(&t->parsing_stream_map, id);
  if (!s) {
    s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
  }
  GPR_ASSERT(s);
  s->global.in_stream_map = 0;
  if (t->parsing.incoming_stream == &s->parsing) {
    t->parsing.incoming_stream = NULL;
    grpc_chttp2_parsing_become_skip_parser(&t->parsing);
  }

  new_stream_count =
      grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
      grpc_chttp2_stream_map_size(&t->new_stream_map);
  if (new_stream_count != t->global.concurrent_stream_count) {
    t->global.concurrent_stream_count = new_stream_count;
    maybe_start_some_streams(&t->global);
  }
}
コード例 #10
0
ファイル: parsing.c プロジェクト: endobson/grpc
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);
}