示例#1
0
void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
                                     grpc_chttp2_data_parser *parser) {
  if (parser->parsing_frame != NULL) {
    grpc_chttp2_incoming_byte_stream_finished(
        exec_ctx, parser->parsing_frame, GRPC_ERROR_CREATE("Parser destroyed"));
  }
  GRPC_ERROR_UNREF(parser->error);
}
示例#2
0
void grpc_chttp2_data_parser_destroy(grpc_exec_ctx *exec_ctx,
                                     grpc_chttp2_data_parser *parser) {
  grpc_byte_stream *bs;
  if (parser->parsing_frame) {
    grpc_chttp2_incoming_byte_stream_finished(exec_ctx, parser->parsing_frame);
  }
  while (
      (bs = grpc_chttp2_incoming_frame_queue_pop(&parser->incoming_frames))) {
    grpc_byte_stream_destroy(bs);
  }
}
示例#3
0
grpc_chttp2_parse_error grpc_chttp2_data_parser_parse(
    grpc_exec_ctx *exec_ctx, void *parser,
    grpc_chttp2_transport_parsing *transport_parsing,
    grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last) {
  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
  uint8_t *const end = GPR_SLICE_END_PTR(slice);
  uint8_t *cur = beg;
  grpc_chttp2_data_parser *p = parser;
  uint32_t message_flags;
  grpc_chttp2_incoming_byte_stream *incoming_byte_stream;

  if (is_last && p->is_last_frame) {
    stream_parsing->received_close = 1;
  }

  if (cur == end) {
    return GRPC_CHTTP2_PARSE_OK;
  }

  switch (p->state) {
  fh_0:
    case GRPC_CHTTP2_DATA_FH_0:
      p->frame_type = *cur;
      switch (p->frame_type) {
        case 0:
          p->is_frame_compressed = 0; /* GPR_FALSE */
          break;
        case 1:
          p->is_frame_compressed = 1; /* GPR_TRUE */
          break;
        default:
          gpr_log(GPR_ERROR, "Bad GRPC frame type 0x%02x", p->frame_type);
          return GRPC_CHTTP2_STREAM_ERROR;
      }
      if (++cur == end) {
        p->state = GRPC_CHTTP2_DATA_FH_1;
        return GRPC_CHTTP2_PARSE_OK;
      }
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FH_1:
      p->frame_size = ((uint32_t)*cur) << 24;
      if (++cur == end) {
        p->state = GRPC_CHTTP2_DATA_FH_2;
        return GRPC_CHTTP2_PARSE_OK;
      }
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FH_2:
      p->frame_size |= ((uint32_t)*cur) << 16;
      if (++cur == end) {
        p->state = GRPC_CHTTP2_DATA_FH_3;
        return GRPC_CHTTP2_PARSE_OK;
      }
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FH_3:
      p->frame_size |= ((uint32_t)*cur) << 8;
      if (++cur == end) {
        p->state = GRPC_CHTTP2_DATA_FH_4;
        return GRPC_CHTTP2_PARSE_OK;
      }
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FH_4:
      p->frame_size |= ((uint32_t)*cur);
      p->state = GRPC_CHTTP2_DATA_FRAME;
      ++cur;
      message_flags = 0;
      if (p->is_frame_compressed) {
        message_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
      }
      p->parsing_frame = incoming_byte_stream =
          grpc_chttp2_incoming_byte_stream_create(
              exec_ctx, transport_parsing, stream_parsing, p->frame_size,
              message_flags, &p->incoming_frames);
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FRAME:
      if (cur == end) {
        grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
                                                 stream_parsing);
        return GRPC_CHTTP2_PARSE_OK;
      }
      grpc_chttp2_list_add_parsing_seen_stream(transport_parsing,
                                               stream_parsing);
      if ((uint32_t)(end - cur) == p->frame_size) {
        grpc_chttp2_incoming_byte_stream_push(
            exec_ctx, p->parsing_frame,
            gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
                                                  1);
        p->parsing_frame = NULL;
        p->state = GRPC_CHTTP2_DATA_FH_0;
        return GRPC_CHTTP2_PARSE_OK;
      } else if ((uint32_t)(end - cur) > p->frame_size) {
        grpc_chttp2_incoming_byte_stream_push(
            exec_ctx, p->parsing_frame,
            gpr_slice_sub(slice, (size_t)(cur - beg),
                          (size_t)(cur + p->frame_size - beg)));
        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame, 1,
                                                  1);
        p->parsing_frame = NULL;
        cur += p->frame_size;
        goto fh_0; /* loop */
      } else {
        grpc_chttp2_incoming_byte_stream_push(
            exec_ctx, p->parsing_frame,
            gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
        GPR_ASSERT((size_t)(end - cur) <= p->frame_size);
        p->frame_size -= (uint32_t)(end - cur);
        return GRPC_CHTTP2_PARSE_OK;
      }
  }

  GPR_UNREACHABLE_CODE(return GRPC_CHTTP2_CONNECTION_ERROR);
}
示例#4
0
static grpc_error *parse_inner(grpc_exec_ctx *exec_ctx,
                               grpc_chttp2_data_parser *p,
                               grpc_chttp2_transport *t, grpc_chttp2_stream *s,
                               gpr_slice slice) {
  uint8_t *const beg = GPR_SLICE_START_PTR(slice);
  uint8_t *const end = GPR_SLICE_END_PTR(slice);
  uint8_t *cur = beg;
  uint32_t message_flags;
  grpc_chttp2_incoming_byte_stream *incoming_byte_stream;
  char *msg;

  if (cur == end) {
    return GRPC_ERROR_NONE;
  }

  switch (p->state) {
    case GRPC_CHTTP2_DATA_ERROR:
      p->state = GRPC_CHTTP2_DATA_ERROR;
      return GRPC_ERROR_REF(p->error);
    fh_0:
    case GRPC_CHTTP2_DATA_FH_0:
      s->stats.incoming.framing_bytes++;
      p->frame_type = *cur;
      switch (p->frame_type) {
        case 0:
          p->is_frame_compressed = 0; /* GPR_FALSE */
          break;
        case 1:
          p->is_frame_compressed = 1; /* GPR_TRUE */
          break;
        default:
          gpr_asprintf(&msg, "Bad GRPC frame type 0x%02x", p->frame_type);
          p->error = GRPC_ERROR_CREATE(msg);
          p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID,
                                        (intptr_t)s->id);
          gpr_free(msg);
          msg = gpr_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
          p->error =
              grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES, msg);
          gpr_free(msg);
          p->error =
              grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg);
          p->state = GRPC_CHTTP2_DATA_ERROR;
          return GRPC_ERROR_REF(p->error);
      }
      if (++cur == end) {
        p->state = GRPC_CHTTP2_DATA_FH_1;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FH_1:
      s->stats.incoming.framing_bytes++;
      p->frame_size = ((uint32_t)*cur) << 24;
      if (++cur == end) {
        p->state = GRPC_CHTTP2_DATA_FH_2;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FH_2:
      s->stats.incoming.framing_bytes++;
      p->frame_size |= ((uint32_t)*cur) << 16;
      if (++cur == end) {
        p->state = GRPC_CHTTP2_DATA_FH_3;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FH_3:
      s->stats.incoming.framing_bytes++;
      p->frame_size |= ((uint32_t)*cur) << 8;
      if (++cur == end) {
        p->state = GRPC_CHTTP2_DATA_FH_4;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FH_4:
      s->stats.incoming.framing_bytes++;
      p->frame_size |= ((uint32_t)*cur);
      p->state = GRPC_CHTTP2_DATA_FRAME;
      ++cur;
      message_flags = 0;
      if (p->is_frame_compressed) {
        message_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
      }
      p->parsing_frame = incoming_byte_stream =
          grpc_chttp2_incoming_byte_stream_create(exec_ctx, t, s, p->frame_size,
                                                  message_flags);
    /* fallthrough */
    case GRPC_CHTTP2_DATA_FRAME:
      if (cur == end) {
        return GRPC_ERROR_NONE;
      }
      uint32_t remaining = (uint32_t)(end - cur);
      if (remaining == p->frame_size) {
        s->stats.incoming.data_bytes += p->frame_size;
        grpc_chttp2_incoming_byte_stream_push(
            exec_ctx, p->parsing_frame,
            gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame,
                                                  GRPC_ERROR_NONE);
        p->parsing_frame = NULL;
        p->state = GRPC_CHTTP2_DATA_FH_0;
        return GRPC_ERROR_NONE;
      } else if (remaining > p->frame_size) {
        s->stats.incoming.data_bytes += p->frame_size;
        grpc_chttp2_incoming_byte_stream_push(
            exec_ctx, p->parsing_frame,
            gpr_slice_sub(slice, (size_t)(cur - beg),
                          (size_t)(cur + p->frame_size - beg)));
        grpc_chttp2_incoming_byte_stream_finished(exec_ctx, p->parsing_frame,
                                                  GRPC_ERROR_NONE);
        p->parsing_frame = NULL;
        cur += p->frame_size;
        goto fh_0; /* loop */
      } else {
        GPR_ASSERT(remaining <= p->frame_size);
        grpc_chttp2_incoming_byte_stream_push(
            exec_ctx, p->parsing_frame,
            gpr_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
        p->frame_size -= remaining;
        s->stats.incoming.data_bytes += remaining;
        return GRPC_ERROR_NONE;
      }
  }

  GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
示例#5
0
grpc_error *grpc_deframe_unprocessed_incoming_frames(
    grpc_exec_ctx *exec_ctx, grpc_chttp2_data_parser *p, grpc_chttp2_stream *s,
    grpc_slice_buffer *slices, grpc_slice *slice_out,
    grpc_byte_stream **stream_out) {
  grpc_error *error = GRPC_ERROR_NONE;
  grpc_chttp2_transport *t = s->t;

  while (slices->count > 0) {
    uint8_t *beg = NULL;
    uint8_t *end = NULL;
    uint8_t *cur = NULL;

    grpc_slice slice = grpc_slice_buffer_take_first(slices);

    beg = GRPC_SLICE_START_PTR(slice);
    end = GRPC_SLICE_END_PTR(slice);
    cur = beg;
    uint32_t message_flags;
    char *msg;

    if (cur == end) {
      grpc_slice_unref_internal(exec_ctx, slice);
      continue;
    }

    switch (p->state) {
      case GRPC_CHTTP2_DATA_ERROR:
        p->state = GRPC_CHTTP2_DATA_ERROR;
        grpc_slice_unref_internal(exec_ctx, slice);
        return GRPC_ERROR_REF(p->error);
      case GRPC_CHTTP2_DATA_FH_0:
        p->frame_type = *cur;
        switch (p->frame_type) {
          case 0:
            p->is_frame_compressed = false; /* GPR_FALSE */
            break;
          case 1:
            p->is_frame_compressed = true; /* GPR_TRUE */
            break;
          default:
            gpr_asprintf(&msg, "Bad GRPC frame type 0x%02x", p->frame_type);
            p->error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
            p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID,
                                          (intptr_t)s->id);
            gpr_free(msg);
            msg = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
            p->error = grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES,
                                          grpc_slice_from_copied_string(msg));
            gpr_free(msg);
            p->error =
                grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg);
            p->state = GRPC_CHTTP2_DATA_ERROR;
            grpc_slice_unref_internal(exec_ctx, slice);
            return GRPC_ERROR_REF(p->error);
        }
        if (++cur == end) {
          p->state = GRPC_CHTTP2_DATA_FH_1;
          grpc_slice_unref_internal(exec_ctx, slice);
          continue;
        }
      /* fallthrough */
      case GRPC_CHTTP2_DATA_FH_1:
        p->frame_size = ((uint32_t)*cur) << 24;
        if (++cur == end) {
          p->state = GRPC_CHTTP2_DATA_FH_2;
          grpc_slice_unref_internal(exec_ctx, slice);
          continue;
        }
      /* fallthrough */
      case GRPC_CHTTP2_DATA_FH_2:
        p->frame_size |= ((uint32_t)*cur) << 16;
        if (++cur == end) {
          p->state = GRPC_CHTTP2_DATA_FH_3;
          grpc_slice_unref_internal(exec_ctx, slice);
          continue;
        }
      /* fallthrough */
      case GRPC_CHTTP2_DATA_FH_3:
        p->frame_size |= ((uint32_t)*cur) << 8;
        if (++cur == end) {
          p->state = GRPC_CHTTP2_DATA_FH_4;
          grpc_slice_unref_internal(exec_ctx, slice);
          continue;
        }
      /* fallthrough */
      case GRPC_CHTTP2_DATA_FH_4:
        GPR_ASSERT(stream_out != NULL);
        GPR_ASSERT(p->parsing_frame == NULL);
        p->frame_size |= ((uint32_t)*cur);
        p->state = GRPC_CHTTP2_DATA_FRAME;
        ++cur;
        message_flags = 0;
        if (p->is_frame_compressed) {
          message_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
        }
        p->parsing_frame = grpc_chttp2_incoming_byte_stream_create(
            exec_ctx, t, s, p->frame_size, message_flags);
        *stream_out = &p->parsing_frame->base;
        if (p->parsing_frame->remaining_bytes == 0) {
          GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished(
              exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true));
          p->parsing_frame = NULL;
          p->state = GRPC_CHTTP2_DATA_FH_0;
        }
        s->pending_byte_stream = true;

        if (cur != end) {
          grpc_slice_buffer_undo_take_first(
              &s->unprocessed_incoming_frames_buffer,
              grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
        }
        grpc_slice_unref_internal(exec_ctx, slice);
        return GRPC_ERROR_NONE;
      case GRPC_CHTTP2_DATA_FRAME: {
        GPR_ASSERT(p->parsing_frame != NULL);
        GPR_ASSERT(slice_out != NULL);
        if (cur == end) {
          grpc_slice_unref_internal(exec_ctx, slice);
          continue;
        }
        uint32_t remaining = (uint32_t)(end - cur);
        if (remaining == p->frame_size) {
          if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push(
                                      exec_ctx, p->parsing_frame,
                                      grpc_slice_sub(slice, (size_t)(cur - beg),
                                                     (size_t)(end - beg)),
                                      slice_out))) {
            grpc_slice_unref_internal(exec_ctx, slice);
            return error;
          }
          if (GRPC_ERROR_NONE !=
              (error = grpc_chttp2_incoming_byte_stream_finished(
                   exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) {
            grpc_slice_unref_internal(exec_ctx, slice);
            return error;
          }
          p->parsing_frame = NULL;
          p->state = GRPC_CHTTP2_DATA_FH_0;
          grpc_slice_unref_internal(exec_ctx, slice);
          return GRPC_ERROR_NONE;
        } else if (remaining < p->frame_size) {
          if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push(
                                      exec_ctx, p->parsing_frame,
                                      grpc_slice_sub(slice, (size_t)(cur - beg),
                                                     (size_t)(end - beg)),
                                      slice_out))) {
            return error;
          }
          p->frame_size -= remaining;
          grpc_slice_unref_internal(exec_ctx, slice);
          return GRPC_ERROR_NONE;
        } else {
          GPR_ASSERT(remaining > p->frame_size);
          if (GRPC_ERROR_NONE !=
              (grpc_chttp2_incoming_byte_stream_push(
                  exec_ctx, p->parsing_frame,
                  grpc_slice_sub(slice, (size_t)(cur - beg),
                                 (size_t)(cur + p->frame_size - beg)),
                  slice_out))) {
            grpc_slice_unref_internal(exec_ctx, slice);
            return error;
          }
          if (GRPC_ERROR_NONE !=
              (error = grpc_chttp2_incoming_byte_stream_finished(
                   exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) {
            grpc_slice_unref_internal(exec_ctx, slice);
            return error;
          }
          p->parsing_frame = NULL;
          p->state = GRPC_CHTTP2_DATA_FH_0;
          cur += p->frame_size;
          grpc_slice_buffer_undo_take_first(
              &s->unprocessed_incoming_frames_buffer,
              grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)));
          grpc_slice_unref_internal(exec_ctx, slice);
          return GRPC_ERROR_NONE;
        }
      }
    }
  }

  return GRPC_ERROR_NONE;
}