Пример #1
0
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;
}
Пример #2
0
static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) {
    grpc_chttp2_stream_writing *stream_writing;

    while (
        grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) {
        if (stream_writing->sopb.nops > 0 || stream_writing->send_closed != GRPC_DONT_SEND_CLOSED) {
            grpc_chttp2_encode(stream_writing->sopb.ops, stream_writing->sopb.nops,
                               stream_writing->send_closed != GRPC_DONT_SEND_CLOSED,
                               stream_writing->id, &transport_writing->hpack_compressor,
                               &transport_writing->outbuf);
            stream_writing->sopb.nops = 0;
        }
        if (stream_writing->announce_window > 0) {
            gpr_slice_buffer_add(
                &transport_writing->outbuf,
                grpc_chttp2_window_update_create(
                    stream_writing->id, stream_writing->announce_window));
            stream_writing->announce_window = 0;
        }
        if (stream_writing->send_closed == GRPC_SEND_CLOSED_WITH_RST_STREAM) {
            gpr_slice_buffer_add(&transport_writing->outbuf,
                                 grpc_chttp2_rst_stream_create(stream_writing->id,
                                         GRPC_CHTTP2_NO_ERROR));
        }
        grpc_chttp2_list_add_written_stream(transport_writing, stream_writing);
    }
}
Пример #3
0
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;
}
Пример #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
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);
}
Пример #6
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);
}
Пример #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 = 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;
  }
}
Пример #8
0
static void cancel_from_api(grpc_chttp2_transport_global *transport_global,
                            grpc_chttp2_stream_global *stream_global,
                            grpc_status_code status) {
  stream_global->cancelled = 1;
  stream_global->cancelled_status = status;
  if (stream_global->id != 0) {
    gpr_slice_buffer_add(&transport_global->qbuf,
                         grpc_chttp2_rst_stream_create(
                             stream_global->id,
                             grpc_chttp2_grpc_status_to_http2_error(status)));
  }
  grpc_chttp2_list_add_read_write_state_changed(transport_global,
                                                stream_global);
}
Пример #9
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;
  }
}
Пример #10
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;
  }
}
Пример #11
0
static void close_from_api(grpc_chttp2_transport_global *transport_global,
                           grpc_chttp2_stream_global *stream_global,
                           grpc_status_code status,
                           gpr_slice *optional_message) {
  gpr_slice hdr;
  gpr_slice status_hdr;
  gpr_slice message_pfx;
  gpr_uint8 *p;
  gpr_uint32 len = 0;

  GPR_ASSERT(status >= 0 && (int)status < 100);

  stream_global->cancelled = 1;
  stream_global->cancelled_status = status;
  GPR_ASSERT(stream_global->id != 0);
  GPR_ASSERT(!stream_global->written_anything);

  /* Hand roll a header block.
     This is unnecessarily ugly - at some point we should find a more elegant
     solution.
     It's complicated by the fact that our send machinery would be dead by the
     time we got around to sending this, so instead we ignore HPACK compression
     and just write the uncompressed bytes onto the wire. */
  status_hdr = gpr_slice_malloc(15 + (status >= 10));
  p = GPR_SLICE_START_PTR(status_hdr);
  *p++ = 0x40; /* literal header */
  *p++ = 11;   /* len(grpc-status) */
  *p++ = 'g';
  *p++ = 'r';
  *p++ = 'p';
  *p++ = 'c';
  *p++ = '-';
  *p++ = 's';
  *p++ = 't';
  *p++ = 'a';
  *p++ = 't';
  *p++ = 'u';
  *p++ = 's';
  if (status < 10) {
    *p++ = 1;
    *p++ = (gpr_uint8)('0' + status);
  } else {
    *p++ = 2;
    *p++ = (gpr_uint8)('0' + (status / 10));
    *p++ = (gpr_uint8)('0' + (status % 10));
  }
  GPR_ASSERT(p == GPR_SLICE_END_PTR(status_hdr));
  len += (gpr_uint32)GPR_SLICE_LENGTH(status_hdr);

  if (optional_message) {
    GPR_ASSERT(GPR_SLICE_LENGTH(*optional_message) < 127);
    message_pfx = gpr_slice_malloc(15);
    p = GPR_SLICE_START_PTR(message_pfx);
    *p++ = 0x40;
    *p++ = 12; /* len(grpc-message) */
    *p++ = 'g';
    *p++ = 'r';
    *p++ = 'p';
    *p++ = 'c';
    *p++ = '-';
    *p++ = 'm';
    *p++ = 'e';
    *p++ = 's';
    *p++ = 's';
    *p++ = 'a';
    *p++ = 'g';
    *p++ = 'e';
    *p++ = (gpr_uint8)GPR_SLICE_LENGTH(*optional_message);
    GPR_ASSERT(p == GPR_SLICE_END_PTR(message_pfx));
    len += (gpr_uint32)GPR_SLICE_LENGTH(message_pfx);
    len += (gpr_uint32)GPR_SLICE_LENGTH(*optional_message);
  }

  hdr = gpr_slice_malloc(9);
  p = GPR_SLICE_START_PTR(hdr);
  *p++ = (gpr_uint8)(len >> 16);
  *p++ = (gpr_uint8)(len >> 8);
  *p++ = (gpr_uint8)(len);
  *p++ = GRPC_CHTTP2_FRAME_HEADER;
  *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
  *p++ = (gpr_uint8)(stream_global->id >> 24);
  *p++ = (gpr_uint8)(stream_global->id >> 16);
  *p++ = (gpr_uint8)(stream_global->id >> 8);
  *p++ = (gpr_uint8)(stream_global->id);
  GPR_ASSERT(p == GPR_SLICE_END_PTR(hdr));

  gpr_slice_buffer_add(&transport_global->qbuf, hdr);
  gpr_slice_buffer_add(&transport_global->qbuf, status_hdr);
  if (optional_message) {
    gpr_slice_buffer_add(&transport_global->qbuf, message_pfx);
    gpr_slice_buffer_add(&transport_global->qbuf,
                         gpr_slice_ref(*optional_message));
  }

  gpr_slice_buffer_add(
      &transport_global->qbuf,
      grpc_chttp2_rst_stream_create(stream_global->id, GRPC_CHTTP2_NO_ERROR));

  grpc_chttp2_list_add_read_write_state_changed(transport_global,
                                                stream_global);
}