Exemplo n.º 1
0
void grpc_slice_split(grpc_slice str, const char *sep, grpc_slice_buffer *dst) {
  const size_t sep_len = strlen(sep);
  size_t begin, end;

  GPR_ASSERT(sep_len > 0);

  if (slice_find_separator_offset(str, sep, 0, &begin, &end) != 0) {
    do {
      grpc_slice_buffer_add_indexed(dst, grpc_slice_sub(str, begin, end));
    } while (slice_find_separator_offset(str, sep, end + sep_len, &begin,
                                         &end) != 0);
    grpc_slice_buffer_add_indexed(
        dst, grpc_slice_sub(str, end + sep_len, GRPC_SLICE_LENGTH(str)));
  } else { /* no sep found, add whole input */
    grpc_slice_buffer_add_indexed(dst, grpc_slice_ref(str));
  }
}
Exemplo n.º 2
0
void grpc_split_slices(grpc_slice_split_mode mode, grpc_slice *src_slices,
                       size_t src_slice_count, grpc_slice **dst_slices,
                       size_t *dst_slice_count) {
  size_t i, j;
  size_t length;

  switch (mode) {
    case GRPC_SLICE_SPLIT_IDENTITY:
      *dst_slice_count = src_slice_count;
      *dst_slices = gpr_malloc(sizeof(grpc_slice) * src_slice_count);
      for (i = 0; i < src_slice_count; i++) {
        (*dst_slices)[i] = src_slices[i];
        grpc_slice_ref((*dst_slices)[i]);
      }
      break;
    case GRPC_SLICE_SPLIT_MERGE_ALL:
      *dst_slice_count = 1;
      length = 0;
      for (i = 0; i < src_slice_count; i++) {
        length += GRPC_SLICE_LENGTH(src_slices[i]);
      }
      *dst_slices = gpr_malloc(sizeof(grpc_slice));
      **dst_slices = grpc_slice_malloc(length);
      length = 0;
      for (i = 0; i < src_slice_count; i++) {
        memcpy(GRPC_SLICE_START_PTR(**dst_slices) + length,
               GRPC_SLICE_START_PTR(src_slices[i]),
               GRPC_SLICE_LENGTH(src_slices[i]));
        length += GRPC_SLICE_LENGTH(src_slices[i]);
      }
      break;
    case GRPC_SLICE_SPLIT_ONE_BYTE:
      length = 0;
      for (i = 0; i < src_slice_count; i++) {
        length += GRPC_SLICE_LENGTH(src_slices[i]);
      }
      *dst_slice_count = length;
      *dst_slices = gpr_malloc(sizeof(grpc_slice) * length);
      length = 0;
      for (i = 0; i < src_slice_count; i++) {
        for (j = 0; j < GRPC_SLICE_LENGTH(src_slices[i]); j++) {
          (*dst_slices)[length] = grpc_slice_sub(src_slices[i], j, j + 1);
          length++;
        }
      }
      break;
  }
}
Exemplo n.º 3
0
static grpc_error *parse_inner(grpc_exec_ctx *exec_ctx,
                               grpc_chttp2_data_parser *p,
                               grpc_chttp2_transport *t, grpc_chttp2_stream *s,
                               grpc_slice slice) {
  uint8_t *const beg = GRPC_SLICE_START_PTR(slice);
  uint8_t *const end = GRPC_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 = grpc_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,
            grpc_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,
            grpc_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,
            grpc_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"));
}
Exemplo n.º 4
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;
}