Пример #1
0
static int init_data_frame_parser(
    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
  grpc_chttp2_stream_parsing *stream_parsing =
      grpc_chttp2_parsing_lookup_stream(transport_parsing,
                                        transport_parsing->incoming_stream_id);
  grpc_chttp2_parse_error err = GRPC_CHTTP2_PARSE_OK;
  if (!stream_parsing || stream_parsing->received_close)
    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
  if (err == GRPC_CHTTP2_PARSE_OK) {
    err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
  }
  if (err == GRPC_CHTTP2_PARSE_OK) {
    err = grpc_chttp2_data_parser_begin_frame(
        &stream_parsing->data_parser, transport_parsing->incoming_frame_flags);
  }
  switch (err) {
    case GRPC_CHTTP2_PARSE_OK:
      transport_parsing->incoming_stream = stream_parsing;
      transport_parsing->parser = grpc_chttp2_data_parser_parse;
      transport_parsing->parser_data = &stream_parsing->data_parser;
      return 1;
    case GRPC_CHTTP2_STREAM_ERROR:
      stream_parsing->received_close = 1;
      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 init_skip_frame_parser(exec_ctx, transport_parsing, 0);
    case GRPC_CHTTP2_CONNECTION_ERROR:
      return 0;
  }
  GPR_UNREACHABLE_CODE(return 0);
}
Пример #2
0
static grpc_error *init_data_frame_parser(grpc_exec_ctx *exec_ctx,
                                          grpc_chttp2_transport *t) {
  grpc_chttp2_stream *s =
      grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
  grpc_error *err = GRPC_ERROR_NONE;
  err = grpc_chttp2_flowctl_recv_data(&t->flow_control,
                                      s == NULL ? NULL : &s->flow_control,
                                      t->incoming_frame_size);
  grpc_chttp2_act_on_flowctl_action(
      exec_ctx, grpc_chttp2_flowctl_get_action(
                    &t->flow_control, s == NULL ? NULL : &s->flow_control),
      t, s);
  if (err != GRPC_ERROR_NONE) {
    goto error_handler;
  }
  if (s == NULL) {
    return init_skip_frame_parser(exec_ctx, t, 0);
  }
  s->received_bytes += t->incoming_frame_size;
  s->stats.incoming.framing_bytes += 9;
  if (err == GRPC_ERROR_NONE && s->read_closed) {
    return init_skip_frame_parser(exec_ctx, t, 0);
  }
  if (err == GRPC_ERROR_NONE) {
    err = grpc_chttp2_data_parser_begin_frame(
        &s->data_parser, t->incoming_frame_flags, s->id, s);
  }
error_handler:
  if (err == GRPC_ERROR_NONE) {
    t->incoming_stream = s;
    /* t->parser = grpc_chttp2_data_parser_parse;*/
    t->parser = grpc_chttp2_data_parser_parse;
    t->parser_data = &s->data_parser;
    t->ping_state.pings_before_data_required =
        t->ping_policy.max_pings_without_data;
    t->ping_state.last_ping_sent_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);
    return GRPC_ERROR_NONE;
  } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
    /* handle stream errors by closing the stream */
    if (s != NULL) {
      grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, false, err);
    }
    grpc_slice_buffer_add(
        &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
                                                GRPC_HTTP2_PROTOCOL_ERROR,
                                                &s->stats.outgoing));
    return init_skip_frame_parser(exec_ctx, t, 0);
  } else {
    return err;
  }
}
Пример #3
0
static int init_window_update_frame_parser(
    grpc_chttp2_transport_parsing *transport_parsing) {
    int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_window_update_parser_begin_frame(
                 &transport_parsing->simple.window_update,
                 transport_parsing->incoming_frame_size,
                 transport_parsing->incoming_frame_flags);
    if (transport_parsing->incoming_stream_id) {
        transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
                transport_parsing, transport_parsing->incoming_stream_id);
    }
    transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
    transport_parsing->parser_data = &transport_parsing->simple.window_update;
    return ok;
}
Пример #4
0
static grpc_error *init_rst_stream_parser(grpc_exec_ctx *exec_ctx,
                                          grpc_chttp2_transport *t) {
  grpc_error *err = grpc_chttp2_rst_stream_parser_begin_frame(
      &t->simple.rst_stream, t->incoming_frame_size, t->incoming_frame_flags);
  if (err != GRPC_ERROR_NONE) return err;
  grpc_chttp2_stream *s = t->incoming_stream =
      grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
  if (!t->incoming_stream) {
    return init_skip_frame_parser(exec_ctx, t, 0);
  }
  s->stats.incoming.framing_bytes += 9;
  t->parser = grpc_chttp2_rst_stream_parser_parse;
  t->parser_data = &t->simple.rst_stream;
  return GRPC_ERROR_NONE;
}
Пример #5
0
static int init_rst_stream_parser(
    grpc_chttp2_transport_parsing *transport_parsing) {
    int ok = GRPC_CHTTP2_PARSE_OK == grpc_chttp2_rst_stream_parser_begin_frame(
                 &transport_parsing->simple.rst_stream,
                 transport_parsing->incoming_frame_size,
                 transport_parsing->incoming_frame_flags);
    transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
            transport_parsing, transport_parsing->incoming_stream_id);
    if (!transport_parsing->incoming_stream) {
        return init_skip_frame_parser(transport_parsing, 0);
    }
    transport_parsing->parser = grpc_chttp2_rst_stream_parser_parse;
    transport_parsing->parser_data = &transport_parsing->simple.rst_stream;
    return ok;
}
Пример #6
0
static grpc_error *init_window_update_frame_parser(
    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
  grpc_error *err = grpc_chttp2_window_update_parser_begin_frame(
      &transport_parsing->simple.window_update,
      transport_parsing->incoming_frame_size,
      transport_parsing->incoming_frame_flags);
  if (err != GRPC_ERROR_NONE) return err;
  if (transport_parsing->incoming_stream_id != 0) {
    grpc_chttp2_stream_parsing *stream_parsing =
        transport_parsing->incoming_stream = grpc_chttp2_parsing_lookup_stream(
            transport_parsing, transport_parsing->incoming_stream_id);
    if (stream_parsing == NULL) {
      return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
    }
    stream_parsing->stats.incoming.framing_bytes += 9;
  }
  transport_parsing->parser = grpc_chttp2_window_update_parser_parse;
  transport_parsing->parser_data = &transport_parsing->simple.window_update;
  return GRPC_ERROR_NONE;
}
Пример #7
0
static grpc_error *init_data_frame_parser(grpc_exec_ctx *exec_ctx,
                                          grpc_chttp2_transport *t) {
  grpc_chttp2_stream *s =
      grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
  grpc_error *err = GRPC_ERROR_NONE;
  err = update_incoming_window(exec_ctx, t, s);
  if (err != GRPC_ERROR_NONE) {
    goto error_handler;
  }
  if (s == NULL) {
    return init_skip_frame_parser(exec_ctx, t, 0);
  }
  s->stats.incoming.framing_bytes += 9;
  if (err == GRPC_ERROR_NONE && s->read_closed) {
    return init_skip_frame_parser(exec_ctx, t, 0);
  }
  if (err == GRPC_ERROR_NONE) {
    err = grpc_chttp2_data_parser_begin_frame(
        &s->data_parser, t->incoming_frame_flags, s->id, s);
  }
error_handler:
  if (err == GRPC_ERROR_NONE) {
    t->incoming_stream = s;
    /* t->parser = grpc_chttp2_data_parser_parse;*/
    t->parser = grpc_chttp2_data_parser_parse;
    t->parser_data = &s->data_parser;
    return GRPC_ERROR_NONE;
  } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
    /* handle stream errors by closing the stream */
    if (s != NULL) {
      grpc_chttp2_mark_stream_closed(exec_ctx, t, s, true, false, err);
    }
    grpc_slice_buffer_add(
        &t->qbuf, grpc_chttp2_rst_stream_create(t->incoming_stream_id,
                                                GRPC_HTTP2_PROTOCOL_ERROR,
                                                &s->stats.outgoing));
    return init_skip_frame_parser(exec_ctx, t, 0);
  } else {
    return err;
  }
}
Пример #8
0
static grpc_error *init_data_frame_parser(
    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing) {
  grpc_chttp2_stream_parsing *stream_parsing =
      grpc_chttp2_parsing_lookup_stream(transport_parsing,
                                        transport_parsing->incoming_stream_id);
  grpc_error *err = GRPC_ERROR_NONE;
  if (stream_parsing == NULL) {
    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
  }
  stream_parsing->stats.incoming.framing_bytes += 9;
  if (stream_parsing->received_close) {
    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
  }
  if (err == GRPC_ERROR_NONE) {
    err = update_incoming_window(exec_ctx, transport_parsing, stream_parsing);
  }
  if (err == GRPC_ERROR_NONE) {
    err = grpc_chttp2_data_parser_begin_frame(
        &stream_parsing->data_parser, transport_parsing->incoming_frame_flags,
        stream_parsing->id);
  }
  if (err == GRPC_ERROR_NONE) {
    transport_parsing->incoming_stream = stream_parsing;
    transport_parsing->parser = grpc_chttp2_data_parser_parse;
    transport_parsing->parser_data = &stream_parsing->data_parser;
    return GRPC_ERROR_NONE;
  } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
    /* handle stream errors by closing the stream */
    stream_parsing->received_close = 1;
    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));
    return init_skip_frame_parser(exec_ctx, transport_parsing, 0);
  } else {
    return err;
  }
}
Пример #9
0
static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx,
                                            grpc_chttp2_transport *t,
                                            int is_continuation) {
  uint8_t is_eoh =
      (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
  grpc_chttp2_stream *s;

  /* TODO(ctiller): when to increment header_frames_received? */

  if (is_eoh) {
    t->expect_continuation_stream_id = 0;
  } else {
    t->expect_continuation_stream_id = t->incoming_stream_id;
  }

  if (!is_continuation) {
    t->header_eof =
        (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
  }

  t->ping_state.pings_before_data_required =
      t->ping_policy.max_pings_without_data;
  t->ping_state.last_ping_sent_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);

  /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
  s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
  if (s == NULL) {
    if (is_continuation) {
      GRPC_CHTTP2_IF_TRACING(
          gpr_log(GPR_ERROR,
                  "grpc_chttp2_stream disbanded before CONTINUATION received"));
      return init_skip_frame_parser(exec_ctx, t, 1);
    }
    if (t->is_client) {
      if ((t->incoming_stream_id & 1) &&
          t->incoming_stream_id < t->next_stream_id) {
        /* this is an old (probably cancelled) grpc_chttp2_stream */
      } else {
        GRPC_CHTTP2_IF_TRACING(gpr_log(
            GPR_ERROR, "ignoring new grpc_chttp2_stream creation on client"));
      }
      return init_skip_frame_parser(exec_ctx, t, 1);
    } else if (t->last_new_stream_id >= t->incoming_stream_id) {
      GRPC_CHTTP2_IF_TRACING(gpr_log(
          GPR_ERROR,
          "ignoring out of order new grpc_chttp2_stream request on server; "
          "last grpc_chttp2_stream "
          "id=%d, new grpc_chttp2_stream id=%d",
          t->last_new_stream_id, t->incoming_stream_id));
      return init_skip_frame_parser(exec_ctx, t, 1);
    } else if ((t->incoming_stream_id & 1) == 0) {
      GRPC_CHTTP2_IF_TRACING(gpr_log(
          GPR_ERROR,
          "ignoring grpc_chttp2_stream with non-client generated index %d",
          t->incoming_stream_id));
      return init_skip_frame_parser(exec_ctx, t, 1);
    } else if (grpc_chttp2_stream_map_size(&t->stream_map) >=
               t->settings[GRPC_ACKED_SETTINGS]
                          [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]) {
      return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Max stream count exceeded");
    }
    t->last_new_stream_id = t->incoming_stream_id;
    s = t->incoming_stream =
        grpc_chttp2_parsing_accept_stream(exec_ctx, t, t->incoming_stream_id);
    if (s == NULL) {
      GRPC_CHTTP2_IF_TRACING(
          gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted"));
      return init_skip_frame_parser(exec_ctx, t, 1);
    }
  } else {
    t->incoming_stream = s;
  }
  GPR_ASSERT(s != NULL);
  s->stats.incoming.framing_bytes += 9;
  if (s->read_closed) {
    GRPC_CHTTP2_IF_TRACING(gpr_log(
        GPR_ERROR, "skipping already closed grpc_chttp2_stream header"));
    t->incoming_stream = NULL;
    return init_skip_frame_parser(exec_ctx, t, 1);
  }
  t->parser = grpc_chttp2_header_parser_parse;
  t->parser_data = &t->hpack_parser;
  switch (s->header_frames_received) {
    case 0:
      if (t->is_client && t->header_eof) {
        GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing Trailers-Only"));
        if (s->trailing_metadata_available != NULL) {
          *s->trailing_metadata_available = true;
        }
        t->hpack_parser.on_header = on_trailing_header;
        s->received_trailing_metadata = true;
      } else {
        GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing initial_metadata"));
        t->hpack_parser.on_header = on_initial_header;
      }
      break;
    case 1:
      GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing trailing_metadata"));
      t->hpack_parser.on_header = on_trailing_header;
      s->received_trailing_metadata = true;
      break;
    case 2:
      gpr_log(GPR_ERROR, "too many header frames received");
      return init_skip_frame_parser(exec_ctx, t, 1);
  }
  t->hpack_parser.on_header_user_data = t;
  t->hpack_parser.is_boundary = is_eoh;
  t->hpack_parser.is_eof = (uint8_t)(is_eoh ? t->header_eof : 0);
  if (!is_continuation &&
      (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
    grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser);
  }
  return GRPC_ERROR_NONE;
}
Пример #10
0
static grpc_error *init_header_frame_parser(
    grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_parsing *transport_parsing,
    int is_continuation) {
  uint8_t is_eoh = (transport_parsing->incoming_frame_flags &
                    GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0;
  int via_accept = 0;
  grpc_chttp2_stream_parsing *stream_parsing;

  /* TODO(ctiller): when to increment header_frames_received? */

  if (is_eoh) {
    transport_parsing->expect_continuation_stream_id = 0;
  } else {
    transport_parsing->expect_continuation_stream_id =
        transport_parsing->incoming_stream_id;
  }

  if (!is_continuation) {
    transport_parsing->header_eof = (transport_parsing->incoming_frame_flags &
                                     GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
  }

  /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
  stream_parsing = grpc_chttp2_parsing_lookup_stream(
      transport_parsing, transport_parsing->incoming_stream_id);
  if (stream_parsing == NULL) {
    if (is_continuation) {
      gpr_log(GPR_ERROR,
              "grpc_chttp2_stream disbanded before CONTINUATION received");
      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
    }
    if (transport_parsing->is_client) {
      if ((transport_parsing->incoming_stream_id & 1) &&
          transport_parsing->incoming_stream_id <
              transport_parsing->next_stream_id) {
        /* this is an old (probably cancelled) grpc_chttp2_stream */
      } else {
        gpr_log(GPR_ERROR,
                "ignoring new grpc_chttp2_stream creation on client");
      }
      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
    } else if (transport_parsing->last_incoming_stream_id >
               transport_parsing->incoming_stream_id) {
      gpr_log(GPR_ERROR,
              "ignoring out of order new grpc_chttp2_stream request on server; "
              "last grpc_chttp2_stream "
              "id=%d, new grpc_chttp2_stream id=%d",
              transport_parsing->last_incoming_stream_id,
              transport_parsing->incoming_stream_id);
      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
    } else if ((transport_parsing->incoming_stream_id & 1) == 0) {
      gpr_log(GPR_ERROR,
              "ignoring grpc_chttp2_stream with non-client generated index %d",
              transport_parsing->incoming_stream_id);
      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
    }
    stream_parsing = transport_parsing->incoming_stream =
        grpc_chttp2_parsing_accept_stream(
            exec_ctx, transport_parsing, transport_parsing->incoming_stream_id);
    if (stream_parsing == NULL) {
      gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted");
      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
    }
    via_accept = 1;
  } else {
    transport_parsing->incoming_stream = stream_parsing;
  }
  GPR_ASSERT(stream_parsing != NULL && (via_accept == 0 || via_accept == 1));
  stream_parsing->stats.incoming.framing_bytes += 9;
  if (stream_parsing->received_close) {
    gpr_log(GPR_ERROR, "skipping already closed grpc_chttp2_stream header");
    transport_parsing->incoming_stream = NULL;
    return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
  }
  transport_parsing->parser = grpc_chttp2_header_parser_parse;
  transport_parsing->parser_data = &transport_parsing->hpack_parser;
  switch (stream_parsing->header_frames_received) {
    case 0:
      transport_parsing->hpack_parser.on_header = on_initial_header;
      break;
    case 1:
      transport_parsing->hpack_parser.on_header = on_trailing_header;
      break;
    case 2:
      gpr_log(GPR_ERROR, "too many header frames received");
      return init_skip_frame_parser(exec_ctx, transport_parsing, 1);
  }
  transport_parsing->hpack_parser.on_header_user_data = transport_parsing;
  transport_parsing->hpack_parser.is_boundary = is_eoh;
  transport_parsing->hpack_parser.is_eof =
      (uint8_t)(is_eoh ? transport_parsing->header_eof : 0);
  if (!is_continuation && (transport_parsing->incoming_frame_flags &
                           GRPC_CHTTP2_FLAG_HAS_PRIORITY)) {
    grpc_chttp2_hpack_parser_set_has_priority(&transport_parsing->hpack_parser);
  }
  return GRPC_ERROR_NONE;
}