Пример #1
0
void gpr_slice_buffer_move_first(gpr_slice_buffer *src, size_t n,
                                 gpr_slice_buffer *dst) {
  size_t src_idx;
  size_t output_len = dst->length + n;
  size_t new_input_len = src->length - n;
  GPR_ASSERT(src->length >= n);
  if (src->length == n) {
    gpr_slice_buffer_move_into(src, dst);
    return;
  }
  src_idx = 0;
  while (src_idx < src->capacity) {
    gpr_slice slice = src->slices[src_idx];
    size_t slice_len = GPR_SLICE_LENGTH(slice);
    if (n > slice_len) {
      gpr_slice_buffer_add(dst, slice);
      n -= slice_len;
      src_idx++;
    } else if (n == slice_len) {
      gpr_slice_buffer_add(dst, slice);
      src_idx++;
      break;
    } else { /* n < slice_len */
      src->slices[src_idx] = gpr_slice_split_tail(&slice, n);
      GPR_ASSERT(GPR_SLICE_LENGTH(slice) == n);
      GPR_ASSERT(GPR_SLICE_LENGTH(src->slices[src_idx]) == slice_len - n);
      gpr_slice_buffer_add(dst, slice);
      break;
    }
  }
  GPR_ASSERT(dst->length == output_len);
  memmove(src->slices, src->slices + src_idx,
          sizeof(gpr_slice) * (src->count - src_idx));
  src->count -= src_idx;
  src->length = new_input_len;
  GPR_ASSERT(src->count > 0);
}
Пример #2
0
static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
        void *handshake,
        grpc_error *error) {
    grpc_security_handshake *h = handshake;
    size_t consumed_slice_size = 0;
    tsi_result result = TSI_OK;
    size_t i;
    size_t num_left_overs;
    int has_left_overs_in_current_slice = 0;

    if (error != GRPC_ERROR_NONE) {
        security_handshake_done(
            exec_ctx, h,
            GRPC_ERROR_CREATE_REFERENCING("Handshake read failed", &error, 1));
        return;
    }

    for (i = 0; i < h->incoming.count; i++) {
        consumed_slice_size = GPR_SLICE_LENGTH(h->incoming.slices[i]);
        result = tsi_handshaker_process_bytes_from_peer(
                     h->handshaker, GPR_SLICE_START_PTR(h->incoming.slices[i]),
                     &consumed_slice_size);
        if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
    }

    if (tsi_handshaker_is_in_progress(h->handshaker)) {
        /* We may need more data. */
        if (result == TSI_INCOMPLETE_DATA) {
            grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
                               &h->on_handshake_data_received_from_peer);
            return;
        } else {
            send_handshake_bytes_to_peer(exec_ctx, h);
            return;
        }
    }

    if (result != TSI_OK) {
        security_handshake_done(exec_ctx, h,
                                grpc_set_tsi_error_result(
                                    GRPC_ERROR_CREATE("Handshake failed"), result));
        return;
    }

    /* Handshake is done and successful this point. */
    has_left_overs_in_current_slice =
        (consumed_slice_size < GPR_SLICE_LENGTH(h->incoming.slices[i]));
    num_left_overs =
        (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1;
    if (num_left_overs == 0) {
        check_peer(exec_ctx, h);
        return;
    }

    /* Put the leftovers in our buffer (ownership transfered). */
    if (has_left_overs_in_current_slice) {
        gpr_slice_buffer_add(
            &h->left_overs,
            gpr_slice_split_tail(&h->incoming.slices[i], consumed_slice_size));
        gpr_slice_unref(
            h->incoming.slices[i]); /* split_tail above increments refcount. */
    }
    gpr_slice_buffer_addn(
        &h->left_overs, &h->incoming.slices[i + 1],
        num_left_overs - (size_t)has_left_overs_in_current_slice);
    check_peer(exec_ctx, h);
}
Пример #3
0
static void on_handshake_data_received_from_peer(
    void *setup, gpr_slice *slices, size_t nslices,
    grpc_endpoint_cb_status error) {
  grpc_secure_transport_setup *s = setup;
  size_t consumed_slice_size = 0;
  tsi_result result = TSI_OK;
  size_t i;
  size_t num_left_overs;
  int has_left_overs_in_current_slice = 0;

  if (error != GRPC_ENDPOINT_CB_OK) {
    gpr_log(GPR_ERROR, "Read failed.");
    cleanup_slices(slices, nslices);
    secure_transport_setup_done(s, 0);
    return;
  }

  for (i = 0; i < nslices; i++) {
    consumed_slice_size = GPR_SLICE_LENGTH(slices[i]);
    result = tsi_handshaker_process_bytes_from_peer(
        s->handshaker, GPR_SLICE_START_PTR(slices[i]), &consumed_slice_size);
    if (!tsi_handshaker_is_in_progress(s->handshaker)) break;
  }

  if (tsi_handshaker_is_in_progress(s->handshaker)) {
    /* We may need more data. */
    if (result == TSI_INCOMPLETE_DATA) {
      /* TODO(klempner,jboeuf): This should probably use the client setup
         deadline */
      grpc_endpoint_notify_on_read(s->endpoint,
                                   on_handshake_data_received_from_peer, setup);
      cleanup_slices(slices, nslices);
      return;
    } else {
      send_handshake_bytes_to_peer(s);
      cleanup_slices(slices, nslices);
      return;
    }
  }

  if (result != TSI_OK) {
    gpr_log(GPR_ERROR, "Handshake failed with error %s",
            tsi_result_to_string(result));
    cleanup_slices(slices, nslices);
    secure_transport_setup_done(s, 0);
    return;
  }

  /* Handshake is done and successful this point. */
  has_left_overs_in_current_slice =
      (consumed_slice_size < GPR_SLICE_LENGTH(slices[i]));
  num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) + nslices - i - 1;
  if (num_left_overs == 0) {
    cleanup_slices(slices, nslices);
    check_peer(s);
    return;
  }
  cleanup_slices(slices, nslices - num_left_overs);

  /* Put the leftovers in our buffer (ownership transfered). */
  if (has_left_overs_in_current_slice) {
    gpr_slice_buffer_add(&s->left_overs,
                         gpr_slice_split_tail(&slices[i], consumed_slice_size));
    gpr_slice_unref(slices[i]); /* split_tail above increments refcount. */
  }
  gpr_slice_buffer_addn(&s->left_overs, &slices[i + 1],
                        num_left_overs - has_left_overs_in_current_slice);
  check_peer(s);
}