Ejemplo n.º 1
0
grpc_error *grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
                                     grpc_chttp2_transport *t,
                                     grpc_slice slice) {
  uint8_t *beg = GRPC_SLICE_START_PTR(slice);
  uint8_t *end = GRPC_SLICE_END_PTR(slice);
  uint8_t *cur = beg;
  grpc_error *err;

  if (cur == end) return GRPC_ERROR_NONE;

  switch (t->deframe_state) {
    case GRPC_DTS_CLIENT_PREFIX_0:
    case GRPC_DTS_CLIENT_PREFIX_1:
    case GRPC_DTS_CLIENT_PREFIX_2:
    case GRPC_DTS_CLIENT_PREFIX_3:
    case GRPC_DTS_CLIENT_PREFIX_4:
    case GRPC_DTS_CLIENT_PREFIX_5:
    case GRPC_DTS_CLIENT_PREFIX_6:
    case GRPC_DTS_CLIENT_PREFIX_7:
    case GRPC_DTS_CLIENT_PREFIX_8:
    case GRPC_DTS_CLIENT_PREFIX_9:
    case GRPC_DTS_CLIENT_PREFIX_10:
    case GRPC_DTS_CLIENT_PREFIX_11:
    case GRPC_DTS_CLIENT_PREFIX_12:
    case GRPC_DTS_CLIENT_PREFIX_13:
    case GRPC_DTS_CLIENT_PREFIX_14:
    case GRPC_DTS_CLIENT_PREFIX_15:
    case GRPC_DTS_CLIENT_PREFIX_16:
    case GRPC_DTS_CLIENT_PREFIX_17:
    case GRPC_DTS_CLIENT_PREFIX_18:
    case GRPC_DTS_CLIENT_PREFIX_19:
    case GRPC_DTS_CLIENT_PREFIX_20:
    case GRPC_DTS_CLIENT_PREFIX_21:
    case GRPC_DTS_CLIENT_PREFIX_22:
    case GRPC_DTS_CLIENT_PREFIX_23:
      while (cur != end && t->deframe_state != GRPC_DTS_FH_0) {
        if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state]) {
          char *msg;
          gpr_asprintf(
              &msg,
              "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
              "at byte %d",
              GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state],
              (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state],
              *cur, (int)*cur, t->deframe_state);
          err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
          gpr_free(msg);
          return err;
        }
        ++cur;
        t->deframe_state =
            (grpc_chttp2_deframe_transport_state)(1 + (int)t->deframe_state);
      }
      if (cur == end) {
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    dts_fh_0:
    case GRPC_DTS_FH_0:
      GPR_ASSERT(cur < end);
      t->incoming_frame_size = ((uint32_t)*cur) << 16;
      if (++cur == end) {
        t->deframe_state = GRPC_DTS_FH_1;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_1:
      GPR_ASSERT(cur < end);
      t->incoming_frame_size |= ((uint32_t)*cur) << 8;
      if (++cur == end) {
        t->deframe_state = GRPC_DTS_FH_2;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_2:
      GPR_ASSERT(cur < end);
      t->incoming_frame_size |= *cur;
      if (++cur == end) {
        t->deframe_state = GRPC_DTS_FH_3;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_3:
      GPR_ASSERT(cur < end);
      t->incoming_frame_type = *cur;
      if (++cur == end) {
        t->deframe_state = GRPC_DTS_FH_4;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_4:
      GPR_ASSERT(cur < end);
      t->incoming_frame_flags = *cur;
      if (++cur == end) {
        t->deframe_state = GRPC_DTS_FH_5;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_5:
      GPR_ASSERT(cur < end);
      t->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24;
      if (++cur == end) {
        t->deframe_state = GRPC_DTS_FH_6;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_6:
      GPR_ASSERT(cur < end);
      t->incoming_stream_id |= ((uint32_t)*cur) << 16;
      if (++cur == end) {
        t->deframe_state = GRPC_DTS_FH_7;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_7:
      GPR_ASSERT(cur < end);
      t->incoming_stream_id |= ((uint32_t)*cur) << 8;
      if (++cur == end) {
        t->deframe_state = GRPC_DTS_FH_8;
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FH_8:
      GPR_ASSERT(cur < end);
      t->incoming_stream_id |= ((uint32_t)*cur);
      t->deframe_state = GRPC_DTS_FRAME;
      err = init_frame_parser(exec_ctx, t);
      if (err != GRPC_ERROR_NONE) {
        return err;
      }
      if (t->incoming_frame_size == 0) {
        err = parse_frame_slice(exec_ctx, t, grpc_empty_slice(), 1);
        if (err != GRPC_ERROR_NONE) {
          return err;
        }
        t->incoming_stream = NULL;
        if (++cur == end) {
          t->deframe_state = GRPC_DTS_FH_0;
          return GRPC_ERROR_NONE;
        }
        goto dts_fh_0; /* loop */
      } else if (t->incoming_frame_size >
                 t->settings[GRPC_ACKED_SETTINGS]
                            [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]) {
        char *msg;
        gpr_asprintf(&msg, "Frame size %d is larger than max frame size %d",
                     t->incoming_frame_size,
                     t->settings[GRPC_ACKED_SETTINGS]
                                [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]);
        err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
        gpr_free(msg);
        return err;
      }
      if (++cur == end) {
        return GRPC_ERROR_NONE;
      }
    /* fallthrough */
    case GRPC_DTS_FRAME:
      GPR_ASSERT(cur < end);
      if ((uint32_t)(end - cur) == t->incoming_frame_size) {
        err = parse_frame_slice(
            exec_ctx, t, grpc_slice_sub_no_ref(slice, (size_t)(cur - beg),
                                               (size_t)(end - beg)),
            1);
        if (err != GRPC_ERROR_NONE) {
          return err;
        }
        t->deframe_state = GRPC_DTS_FH_0;
        t->incoming_stream = NULL;
        return GRPC_ERROR_NONE;
      } else if ((uint32_t)(end - cur) > t->incoming_frame_size) {
        size_t cur_offset = (size_t)(cur - beg);
        err = parse_frame_slice(
            exec_ctx, t,
            grpc_slice_sub_no_ref(slice, cur_offset,
                                  cur_offset + t->incoming_frame_size),
            1);
        if (err != GRPC_ERROR_NONE) {
          return err;
        }
        cur += t->incoming_frame_size;
        t->incoming_stream = NULL;
        goto dts_fh_0; /* loop */
      } else {
        err = parse_frame_slice(
            exec_ctx, t, grpc_slice_sub_no_ref(slice, (size_t)(cur - beg),
                                               (size_t)(end - beg)),
            0);
        if (err != GRPC_ERROR_NONE) {
          return err;
        }
        t->incoming_frame_size -= (uint32_t)(end - cur);
        return GRPC_ERROR_NONE;
      }
      GPR_UNREACHABLE_CODE(return 0);
  }

  GPR_UNREACHABLE_CODE(return 0);
}
Ejemplo n.º 2
0
int grpc_chttp2_perform_read(grpc_chttp2_transport_parsing *transport_parsing,
                             gpr_slice slice) {
    gpr_uint8 *beg = GPR_SLICE_START_PTR(slice);
    gpr_uint8 *end = GPR_SLICE_END_PTR(slice);
    gpr_uint8 *cur = beg;

    if (cur == end) return 1;

    switch (transport_parsing->deframe_state) {
    case GRPC_DTS_CLIENT_PREFIX_0:
    case GRPC_DTS_CLIENT_PREFIX_1:
    case GRPC_DTS_CLIENT_PREFIX_2:
    case GRPC_DTS_CLIENT_PREFIX_3:
    case GRPC_DTS_CLIENT_PREFIX_4:
    case GRPC_DTS_CLIENT_PREFIX_5:
    case GRPC_DTS_CLIENT_PREFIX_6:
    case GRPC_DTS_CLIENT_PREFIX_7:
    case GRPC_DTS_CLIENT_PREFIX_8:
    case GRPC_DTS_CLIENT_PREFIX_9:
    case GRPC_DTS_CLIENT_PREFIX_10:
    case GRPC_DTS_CLIENT_PREFIX_11:
    case GRPC_DTS_CLIENT_PREFIX_12:
    case GRPC_DTS_CLIENT_PREFIX_13:
    case GRPC_DTS_CLIENT_PREFIX_14:
    case GRPC_DTS_CLIENT_PREFIX_15:
    case GRPC_DTS_CLIENT_PREFIX_16:
    case GRPC_DTS_CLIENT_PREFIX_17:
    case GRPC_DTS_CLIENT_PREFIX_18:
    case GRPC_DTS_CLIENT_PREFIX_19:
    case GRPC_DTS_CLIENT_PREFIX_20:
    case GRPC_DTS_CLIENT_PREFIX_21:
    case GRPC_DTS_CLIENT_PREFIX_22:
    case GRPC_DTS_CLIENT_PREFIX_23:
        while (cur != end && transport_parsing->deframe_state != GRPC_DTS_FH_0) {
            if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
                    ->deframe_state]) {
                gpr_log(GPR_INFO,
                        "Connect string mismatch: expected '%c' (%d) got '%c' (%d) "
                        "at byte %d",
                        GRPC_CHTTP2_CLIENT_CONNECT_STRING[transport_parsing
                                ->deframe_state],
                        (int)(gpr_uint8)GRPC_CHTTP2_CLIENT_CONNECT_STRING
                        [transport_parsing->deframe_state],
                        *cur, (int)*cur, transport_parsing->deframe_state);
                return 0;
            }
            ++cur;
            ++transport_parsing->deframe_state;
        }
        if (cur == end) {
            return 1;
        }
        /* fallthrough */
dts_fh_0:
    case GRPC_DTS_FH_0:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_size = ((gpr_uint32)*cur) << 16;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_1;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_1:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_size |= ((gpr_uint32)*cur) << 8;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_2;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_2:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_size |= *cur;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_3;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_3:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_type = *cur;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_4;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_4:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_frame_flags = *cur;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_5;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_5:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_stream_id = (((gpr_uint32)*cur) & 0x7f) << 24;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_6;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_6:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 16;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_7;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_7:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur) << 8;
        if (++cur == end) {
            transport_parsing->deframe_state = GRPC_DTS_FH_8;
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FH_8:
        GPR_ASSERT(cur < end);
        transport_parsing->incoming_stream_id |= ((gpr_uint32)*cur);
        transport_parsing->deframe_state = GRPC_DTS_FRAME;
        if (!init_frame_parser(transport_parsing)) {
            return 0;
        }
        if (transport_parsing->incoming_stream_id) {
            transport_parsing->last_incoming_stream_id =
                transport_parsing->incoming_stream_id;
        }
        if (transport_parsing->incoming_frame_size == 0) {
            if (!parse_frame_slice(transport_parsing, gpr_empty_slice(), 1)) {
                return 0;
            }
            transport_parsing->incoming_stream = NULL;
            if (++cur == end) {
                transport_parsing->deframe_state = GRPC_DTS_FH_0;
                return 1;
            }
            goto dts_fh_0; /* loop */
        }
        if (++cur == end) {
            return 1;
        }
    /* fallthrough */
    case GRPC_DTS_FRAME:
        GPR_ASSERT(cur < end);
        if ((gpr_uint32)(end - cur) == transport_parsing->incoming_frame_size) {
            if (!parse_frame_slice(
                        transport_parsing,
                        gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 1)) {
                return 0;
            }
            transport_parsing->deframe_state = GRPC_DTS_FH_0;
            transport_parsing->incoming_stream = NULL;
            return 1;
        } else if ((gpr_uint32)(end - cur) >
                   transport_parsing->incoming_frame_size) {
            if (!parse_frame_slice(
                        transport_parsing,
                        gpr_slice_sub_no_ref(
                            slice, cur - beg,
                            cur + transport_parsing->incoming_frame_size - beg),
                        1)) {
                return 0;
            }
            cur += transport_parsing->incoming_frame_size;
            transport_parsing->incoming_stream = NULL;
            goto dts_fh_0; /* loop */
        } else {
            if (!parse_frame_slice(
                        transport_parsing,
                        gpr_slice_sub_no_ref(slice, cur - beg, end - beg), 0)) {
                return 0;
            }
            transport_parsing->incoming_frame_size -= (end - cur);
            return 1;
        }
        gpr_log(GPR_ERROR, "should never reach here");
        abort();
    }

    gpr_log(GPR_ERROR, "should never reach here");
    abort();

    return 0;
}