/*
 *
 * Copyright 2018 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h"

#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h"

const size_t kInitialIovecBufferSize = 8;

/* Makes sure iovec_buf in alts_grpc_record_protocol is large enough.  */
static void ensure_iovec_buf_size(alts_grpc_record_protocol* rp,
                                  const grpc_slice_buffer* sb) {
  GPR_ASSERT(rp != nullptr && sb != nullptr);
  if (sb->count <= rp->iovec_buf_length) {
    return;
  }
  /* At least double the iovec buffer size.  */
  rp->iovec_buf_length = GPR_MAX(sb->count, 2 * rp->iovec_buf_length);
  rp->iovec_buf = static_cast<iovec_t*>(
      gpr_realloc(rp->iovec_buf, rp->iovec_buf_length * sizeof(iovec_t)));
}

/* --- Implementation of methods defined in tsi_grpc_record_protocol_common.h.
 * --- */

void alts_grpc_record_protocol_convert_slice_buffer_to_iovec(
    alts_grpc_record_protocol* rp, const grpc_slice_buffer* sb) {
  GPR_ASSERT(rp != nullptr && sb != nullptr);
  ensure_iovec_buf_size(rp, sb);
  for (size_t i = 0; i < sb->count; i++) {
    rp->iovec_buf[i].iov_base = GRPC_SLICE_START_PTR(sb->slices[i]);
    rp->iovec_buf[i].iov_len = GRPC_SLICE_LENGTH(sb->slices[i]);
  }
}

void alts_grpc_record_protocol_copy_slice_buffer(const grpc_slice_buffer* src,
                                                 unsigned char* dst) {
  GPR_ASSERT(src != nullptr && dst != nullptr);
  for (size_t i = 0; i < src->count; i++) {
    size_t slice_length = GRPC_SLICE_LENGTH(src->slices[i]);
    memcpy(dst, GRPC_SLICE_START_PTR(src->slices[i]), slice_length);
    dst += slice_length;
  }
}

iovec_t alts_grpc_record_protocol_get_header_iovec(
    alts_grpc_record_protocol* rp) {
  iovec_t header_iovec = {nullptr, 0};
  if (rp == nullptr) {
    return header_iovec;
  }
  header_iovec.iov_len = rp->header_length;
  if (rp->header_sb.count == 1) {
    header_iovec.iov_base = GRPC_SLICE_START_PTR(rp->header_sb.slices[0]);
  } else {
    /* Frame header is in multiple slices, copies the header bytes from slice
     * buffer to a single flat buffer.  */
    alts_grpc_record_protocol_copy_slice_buffer(&rp->header_sb, rp->header_buf);
    header_iovec.iov_base = rp->header_buf;
  }
  return header_iovec;
}

tsi_result alts_grpc_record_protocol_init(alts_grpc_record_protocol* rp,
                                          gsec_aead_crypter* crypter,
                                          size_t overflow_size, bool is_client,
                                          bool is_integrity_only,
                                          bool is_protect) {
  if (rp == nullptr || crypter == nullptr) {
    gpr_log(GPR_ERROR,
            "Invalid nullptr arguments to alts_grpc_record_protocol init.");
    return TSI_INVALID_ARGUMENT;
  }
  /* Creates alts_iovec_record_protocol.  */
  char* error_details = nullptr;
  grpc_status_code status = alts_iovec_record_protocol_create(
      crypter, overflow_size, is_client, is_integrity_only, is_protect,
      &rp->iovec_rp, &error_details);
  if (status != GRPC_STATUS_OK) {
    gpr_log(GPR_ERROR, "Failed to create alts_iovec_record_protocol, %s.",
            error_details);
    gpr_free(error_details);
    return TSI_INTERNAL_ERROR;
  }
  /* Allocates header slice buffer.  */
  grpc_slice_buffer_init(&rp->header_sb);
  /* Allocates header buffer.  */
  rp->header_length = alts_iovec_record_protocol_get_header_length();
  rp->header_buf = static_cast<unsigned char*>(gpr_malloc(rp->header_length));
  rp->tag_length = alts_iovec_record_protocol_get_tag_length(rp->iovec_rp);
  /* Allocates iovec buffer.  */
  rp->iovec_buf_length = kInitialIovecBufferSize;
  rp->iovec_buf =
      static_cast<iovec_t*>(gpr_malloc(rp->iovec_buf_length * sizeof(iovec_t)));
  return TSI_OK;
}

/* --- Implementation of methods defined in tsi_grpc_record_protocol.h. --- */
tsi_result alts_grpc_record_protocol_protect(
    alts_grpc_record_protocol* self, grpc_slice_buffer* unprotected_slices,
    grpc_slice_buffer* protected_slices) {
  if (grpc_core::ExecCtx::Get() == nullptr || self == nullptr ||
      self->vtable == nullptr || unprotected_slices == nullptr ||
      protected_slices == nullptr) {
    return TSI_INVALID_ARGUMENT;
  }
  if (self->vtable->protect == nullptr) {
    return TSI_UNIMPLEMENTED;
  }
  return self->vtable->protect(self, unprotected_slices, protected_slices);
}

tsi_result alts_grpc_record_protocol_unprotect(
    alts_grpc_record_protocol* self, grpc_slice_buffer* protected_slices,
    grpc_slice_buffer* unprotected_slices) {
  if (grpc_core::ExecCtx::Get() == nullptr || self == nullptr ||
      self->vtable == nullptr || protected_slices == nullptr ||
      unprotected_slices == nullptr) {
    return TSI_INVALID_ARGUMENT;
  }
  if (self->vtable->unprotect == nullptr) {
    return TSI_UNIMPLEMENTED;
  }
  return self->vtable->unprotect(self, protected_slices, unprotected_slices);
}

void alts_grpc_record_protocol_destroy(alts_grpc_record_protocol* self) {
  if (self == nullptr) {
    return;
  }
  if (self->vtable->destruct != nullptr) {
    self->vtable->destruct(self);
  }
  alts_iovec_record_protocol_destroy(self->iovec_rp);
  grpc_slice_buffer_destroy_internal(&self->header_sb);
  gpr_free(self->header_buf);
  gpr_free(self->iovec_buf);
  gpr_free(self);
}

/* Integrity-only and privacy-integrity share the same implementation. No need
 * to call vtable.  */
size_t alts_grpc_record_protocol_max_unprotected_data_size(
    const alts_grpc_record_protocol* self, size_t max_protected_frame_size) {
  if (self == nullptr) {
    return 0;
  }
  return alts_iovec_record_protocol_max_unprotected_data_size(
      self->iovec_rp, max_protected_frame_size);
}
