// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "bearer.h"

#include <lib/async/default.h>

#include "garnet/drivers/bluetooth/lib/common/slab_allocator.h"
#include "garnet/drivers/bluetooth/lib/l2cap/channel.h"

#include "lib/fxl/strings/string_printf.h"

namespace btlib {
namespace att {

// static
constexpr Bearer::HandlerId Bearer::kInvalidHandlerId;
constexpr Bearer::TransactionId Bearer::kInvalidTransactionId;

namespace {

MethodType GetMethodType(OpCode opcode) {
  // We treat all packets as a command if the command bit was set. An
  // unrecognized command will always be ignored (so it is OK to return kCommand
  // here if, for example, |opcode| is a response with the command-bit set).
  if (opcode & kCommandFlag)
    return MethodType::kCommand;

  switch (opcode) {
    case kInvalidOpCode:
      return MethodType::kInvalid;

    case kExchangeMTURequest:
    case kFindInformationRequest:
    case kFindByTypeValueRequest:
    case kReadByTypeRequest:
    case kReadRequest:
    case kReadBlobRequest:
    case kReadMultipleRequest:
    case kReadByGroupTypeRequest:
    case kWriteRequest:
    case kPrepareWriteRequest:
    case kExecuteWriteRequest:
      return MethodType::kRequest;

    case kErrorResponse:
    case kExchangeMTUResponse:
    case kFindInformationResponse:
    case kFindByTypeValueResponse:
    case kReadByTypeResponse:
    case kReadResponse:
    case kReadBlobResponse:
    case kReadMultipleResponse:
    case kReadByGroupTypeResponse:
    case kWriteResponse:
    case kPrepareWriteResponse:
    case kExecuteWriteResponse:
      return MethodType::kResponse;

    case kNotification:
      return MethodType::kNotification;
    case kIndication:
      return MethodType::kIndication;
    case kConfirmation:
      return MethodType::kConfirmation;

    // These are redundant with the check above but are included for
    // completeness.
    case kWriteCommand:
    case kSignedWriteCommand:
      return MethodType::kCommand;

    default:
      break;
  }

  // Everything else will be treated as an incoming request.
  return MethodType::kRequest;
}

// Returns the corresponding originating transaction opcode for
// |transaction_end_code|, where the latter must correspond to a response or
// confirmation.
OpCode MatchingTransactionCode(OpCode transaction_end_code) {
  switch (transaction_end_code) {
    case kExchangeMTUResponse:
      return kExchangeMTURequest;
    case kFindInformationResponse:
      return kFindInformationRequest;
    case kFindByTypeValueResponse:
      return kFindByTypeValueRequest;
    case kReadByTypeResponse:
      return kReadByTypeRequest;
    case kReadResponse:
      return kReadRequest;
    case kReadBlobResponse:
      return kReadBlobRequest;
    case kReadMultipleResponse:
      return kReadMultipleRequest;
    case kReadByGroupTypeResponse:
      return kReadByGroupTypeRequest;
    case kWriteResponse:
      return kWriteRequest;
    case kPrepareWriteResponse:
      return kPrepareWriteRequest;
    case kExecuteWriteResponse:
      return kExecuteWriteRequest;
    case kConfirmation:
      return kIndication;
    default:
      break;
  }

  return kInvalidOpCode;
}

}  // namespace

// static
fxl::RefPtr<Bearer> Bearer::Create(fbl::RefPtr<l2cap::Channel> chan) {
  auto bearer = fxl::AdoptRef(new Bearer(std::move(chan)));
  return bearer->Activate() ? bearer : nullptr;
}

Bearer::PendingTransaction::PendingTransaction(OpCode opcode,
                                               TransactionCallback callback,
                                               ErrorCallback error_callback,
                                               common::ByteBufferPtr pdu)
    : opcode(opcode),
      callback(std::move(callback)),
      error_callback(std::move(error_callback)),
      pdu(std::move(pdu)) {
  FXL_DCHECK(this->callback);
  FXL_DCHECK(this->error_callback);
  FXL_DCHECK(this->pdu);
}

Bearer::PendingRemoteTransaction::PendingRemoteTransaction(TransactionId id,
                                                           OpCode opcode)
    : id(id), opcode(opcode) {}

Bearer::TransactionQueue::TransactionQueue(TransactionQueue&& other)
    : queue_(std::move(other.queue_)), current_(std::move(other.current_)) {
  // The move constructor is only used during shut down below. So we simply
  // cancel the task and not worry about moving it.
  other.timeout_task_.Cancel();
}

Bearer::PendingTransactionPtr Bearer::TransactionQueue::ClearCurrent() {
  FXL_DCHECK(current_);
  FXL_DCHECK(timeout_task_.is_pending());

  timeout_task_.Cancel();

  return std::move(current_);
}

void Bearer::TransactionQueue::Enqueue(PendingTransactionPtr transaction) {
  queue_.push_back(std::move(transaction));
}

void Bearer::TransactionQueue::TrySendNext(l2cap::Channel* chan,
                                           async::Task::Handler timeout_cb,
                                           uint32_t timeout_ms) {
  FXL_DCHECK(chan);

  // Abort if a transaction is currently pending.
  if (current())
    return;

  // Advance to the next transaction.
  current_ = queue_.pop_front();
  if (current()) {
    FXL_DCHECK(!timeout_task_.is_pending());
    timeout_task_.set_handler(std::move(timeout_cb));
    timeout_task_.PostDelayed(async_get_default_dispatcher(), zx::msec(timeout_ms));
    chan->Send(std::move(current()->pdu));
  }
}

void Bearer::TransactionQueue::Reset() {
  timeout_task_.Cancel();
  queue_.clear();
  current_ = nullptr;
}

void Bearer::TransactionQueue::InvokeErrorAll(Status status) {
  if (current_) {
    current_->error_callback(status, kInvalidHandle);
  }

  for (const auto& t : queue_) {
    if (t.error_callback)
      t.error_callback(status, kInvalidHandle);
  }
}

Bearer::Bearer(fbl::RefPtr<l2cap::Channel> chan)
    : chan_(std::move(chan)),
      next_remote_transaction_id_(1u),
      next_handler_id_(1u) {
  FXL_DCHECK(chan_);

  if (chan_->link_type() == hci::Connection::LinkType::kLE) {
    min_mtu_ = kLEMinMTU;
  } else {
    min_mtu_ = kBREDRMinMTU;
  }

  mtu_ = min_mtu();
  preferred_mtu_ =
      std::max(min_mtu(), std::min(chan_->tx_mtu(), chan_->rx_mtu()));
}

Bearer::~Bearer() {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());

  rx_task_.Cancel();
  chan_ = nullptr;

  request_queue_.Reset();
  indication_queue_.Reset();
}

bool Bearer::Activate() {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());

  rx_task_.Reset(fit::bind_member(this, &Bearer::OnRxBFrame));
  chan_closed_cb_.Reset(fit::bind_member(this, &Bearer::OnChannelClosed));

  return chan_->Activate(rx_task_.callback(), chan_closed_cb_.callback(),
                         async_get_default_dispatcher());
}

void Bearer::ShutDown() {
  if (is_open())
    ShutDownInternal(false /* due_to_timeout */);
}

void Bearer::ShutDownInternal(bool due_to_timeout) {
  FXL_DCHECK(is_open());
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());

  FXL_VLOG(1) << "att: Bearer shutting down";

  rx_task_.Cancel();
  chan_closed_cb_.Cancel();

  // This will have no effect if the channel is already closed (e.g. if
  // ShutDown() was called by OnChannelClosed()).
  chan_->SignalLinkError();
  chan_ = nullptr;

  // Move the contents to temporaries. This prevents a potential memory
  // corruption in InvokeErrorAll if the Bearer gets deleted by one of the
  // invoked error callbacks.
  TransactionQueue req_queue(std::move(request_queue_));
  TransactionQueue ind_queue(std::move(indication_queue_));

  if (closed_cb_)
    closed_cb_();

  // Terminate all remaining procedures with an error. This is safe even if
  // the bearer got deleted by |closed_cb_|.
  Status status(due_to_timeout ? common::HostError::kTimedOut
                               : common::HostError::kFailed);
  req_queue.InvokeErrorAll(status);
  ind_queue.InvokeErrorAll(status);
}

bool Bearer::StartTransaction(common::ByteBufferPtr pdu,
                              TransactionCallback callback,
                              ErrorCallback error_callback) {
  FXL_DCHECK(pdu);
  FXL_DCHECK(callback);
  FXL_DCHECK(error_callback);

  return SendInternal(std::move(pdu), std::move(callback), std::move(error_callback));
}

bool Bearer::SendWithoutResponse(common::ByteBufferPtr pdu) {
  FXL_DCHECK(pdu);
  return SendInternal(std::move(pdu), {}, {});
}

bool Bearer::SendInternal(common::ByteBufferPtr pdu,
                          TransactionCallback callback,
                          ErrorCallback error_callback) {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
  if (!is_open()) {
    FXL_VLOG(2) << "att: Bearer closed";
    return false;
  }

  if (!IsPacketValid(*pdu)) {
    FXL_VLOG(1) << "att: Packet has bad length!";
    return false;
  }

  PacketReader reader(pdu.get());
  MethodType type = GetMethodType(reader.opcode());

  TransactionQueue* tq = nullptr;

  switch (type) {
    case MethodType::kCommand:
    case MethodType::kNotification:
      if (callback || error_callback) {
        FXL_VLOG(1) << "att: Method not a transaction";
        return false;
      }

      // Send the command. No flow control is necessary.
      chan_->Send(std::move(pdu));
      return true;

    case MethodType::kRequest:
      tq = &request_queue_;
      break;
    case MethodType::kIndication:
      tq = &indication_queue_;
      break;
    default:
      FXL_VLOG(1) << "att: invalid opcode: "
                  << static_cast<unsigned>(reader.opcode());
      return false;
  }

  if (!callback || !error_callback) {
    FXL_VLOG(1) << "att: Transaction requires callbacks";
    return false;
  }

  tq->Enqueue(std::make_unique<PendingTransaction>(
      reader.opcode(), std::move(callback), std::move(error_callback), std::move(pdu)));
  TryStartNextTransaction(tq);

  return true;
}

Bearer::HandlerId Bearer::RegisterHandler(OpCode opcode,
                                          Handler handler) {
  FXL_DCHECK(handler);

  if (!is_open())
    return kInvalidHandlerId;

  if (handlers_.find(opcode) != handlers_.end()) {
    FXL_VLOG(1) << fxl::StringPrintf(
        "att: Can only register one Handler per opcode (0x%02x)", opcode);
    return kInvalidHandlerId;
  }

  HandlerId id = NextHandlerId();
  if (id == kInvalidHandlerId)
    return kInvalidHandlerId;

  auto res = handler_id_map_.emplace(id, opcode);
  FXL_CHECK(res.second) << "att: Handler ID got reused (id: " << id << ")";

  handlers_[opcode] = std::move(handler);

  return id;
}

void Bearer::UnregisterHandler(HandlerId id) {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
  FXL_DCHECK(id != kInvalidHandlerId);

  auto iter = handler_id_map_.find(id);
  if (iter == handler_id_map_.end()) {
    FXL_VLOG(1) << "att: Cannot unregister unknown handler id: " << id;
    return;
  }

  OpCode opcode = iter->second;
  handlers_.erase(opcode);
}

bool Bearer::Reply(TransactionId tid, common::ByteBufferPtr pdu) {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
  FXL_DCHECK(pdu);

  if (tid == kInvalidTransactionId)
    return false;

  if (!is_open()) {
    FXL_VLOG(2) << "att: Bearer closed";
    return false;
  }

  if (!IsPacketValid(*pdu)) {
    FXL_VLOG(1) << "att: Invalid response PDU";
    return false;
  }

  RemoteTransaction* pending = FindRemoteTransaction(tid);
  if (!pending)
    return false;

  PacketReader reader(pdu.get());

  // Use ReplyWithError() instead.
  if (reader.opcode() == kErrorResponse)
    return false;

  OpCode pending_opcode = (*pending)->opcode;
  if (pending_opcode != MatchingTransactionCode(reader.opcode())) {
    FXL_VLOG(1) << fxl::StringPrintf(
        "att: opcode does not match pending (pending: 0x%02x, given: 0x%02x)",
        pending_opcode, reader.opcode());
    return false;
  }

  pending->Reset();
  chan_->Send(std::move(pdu));

  return true;
}

bool Bearer::ReplyWithError(TransactionId id,
                            Handle handle,
                            ErrorCode error_code) {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());

  RemoteTransaction* pending = FindRemoteTransaction(id);
  if (!pending)
    return false;

  OpCode pending_opcode = (*pending)->opcode;
  if (pending_opcode == kIndication) {
    FXL_VLOG(1) << "att: Cannot respond to an indication with error!";
    return false;
  }

  pending->Reset();
  SendErrorResponse(pending_opcode, handle, error_code);

  return true;
}

bool Bearer::IsPacketValid(const common::ByteBuffer& packet) {
  return packet.size() != 0u && packet.size() <= mtu_;
}

void Bearer::TryStartNextTransaction(TransactionQueue* tq) {
  FXL_DCHECK(is_open());
  FXL_DCHECK(tq);

  tq->TrySendNext(chan_.get(),
                  [this](async_dispatcher_t*, async::Task*, zx_status_t status) {
                    if (status == ZX_OK)
                      ShutDownInternal(true /* due_to_timeout */);
                  },
                  kTransactionTimeoutMs);
}

void Bearer::SendErrorResponse(OpCode request_opcode,
                               Handle attribute_handle,
                               ErrorCode error_code) {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());

  auto buffer =
      common::NewSlabBuffer(sizeof(Header) + sizeof(ErrorResponseParams));
  FXL_CHECK(buffer);

  PacketWriter packet(kErrorResponse, buffer.get());
  auto* payload = packet.mutable_payload<ErrorResponseParams>();
  payload->request_opcode = request_opcode;
  payload->attribute_handle = htole16(attribute_handle);
  payload->error_code = error_code;

  chan_->Send(std::move(buffer));
}

void Bearer::HandleEndTransaction(TransactionQueue* tq,
                                  const PacketReader& packet) {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
  FXL_DCHECK(is_open());
  FXL_DCHECK(tq);

  if (!tq->current()) {
    FXL_VLOG(1) << fxl::StringPrintf(
        "att: received unexpected transaction PDU (opcode: 0x%02x)",
        packet.opcode());
    ShutDown();
    return;
  }

  bool report_error = false;
  OpCode target_opcode;
  ErrorCode error_code = ErrorCode::kNoError;
  Handle attr_in_error = kInvalidHandle;

  if (packet.opcode() == kErrorResponse) {
    // We should never hit this branch for indications.
    FXL_DCHECK(tq->current()->opcode != kIndication);

    if (packet.payload_size() == sizeof(ErrorResponseParams)) {
      report_error = true;

      const auto& payload = packet.payload<ErrorResponseParams>();
      target_opcode = payload.request_opcode;
      error_code = payload.error_code;
      attr_in_error = le16toh(payload.attribute_handle);
    } else {
      FXL_VLOG(2) << "att: Received malformed error response";

      // Invalid opcode will fail the opcode comparison below.
      target_opcode = kInvalidOpCode;
    }
  } else {
    target_opcode = MatchingTransactionCode(packet.opcode());
  }

  FXL_DCHECK(tq->current()->opcode != kInvalidOpCode);

  if (tq->current()->opcode != target_opcode) {
    FXL_VLOG(1) << fxl::StringPrintf(
        "att: Received bad transaction PDU (opcode: 0x%02x)", packet.opcode());
    ShutDown();
    return;
  }

  // The transaction is complete. Send out the next queued transaction and
  // notify the callback.
  auto transaction = tq->ClearCurrent();
  FXL_DCHECK(transaction);

  TryStartNextTransaction(tq);

  if (!report_error)
    transaction->callback(packet);
  else if (transaction->error_callback)
    transaction->error_callback(Status(error_code), attr_in_error);
}

Bearer::HandlerId Bearer::NextHandlerId() {
  auto id = next_handler_id_;

  // This will stop incrementing if this were overflows and always return
  // kInvalidHandlerId.
  if (next_handler_id_ != kInvalidHandlerId)
    next_handler_id_++;
  return id;
}

Bearer::TransactionId Bearer::NextRemoteTransactionId() {
  auto id = next_remote_transaction_id_;

  next_remote_transaction_id_++;

  // Increment extra in the case of overflow.
  if (next_remote_transaction_id_ == kInvalidTransactionId)
    next_remote_transaction_id_++;

  return id;
}

void Bearer::HandleBeginTransaction(RemoteTransaction* currently_pending,
                                    const PacketReader& packet) {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
  FXL_DCHECK(currently_pending);

  if (currently_pending->HasValue()) {
    FXL_VLOG(1) << fxl::StringPrintf(
        "att: A transaction is already pending! (opcode: 0x%02x)",
        packet.opcode());
    ShutDown();
    return;
  }

  auto iter = handlers_.find(packet.opcode());
  if (iter == handlers_.end()) {
    FXL_VLOG(1) << fxl::StringPrintf(
        "att: No handler registered for opcode 0x%02x", packet.opcode());
    SendErrorResponse(packet.opcode(), 0, ErrorCode::kRequestNotSupported);
    return;
  }

  auto id = NextRemoteTransactionId();
  *currently_pending = PendingRemoteTransaction(id, packet.opcode());

  iter->second(id, packet);
}

Bearer::RemoteTransaction* Bearer::FindRemoteTransaction(TransactionId id) {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());

  if (remote_request_ && remote_request_->id == id) {
    return &remote_request_;
  }

  if (remote_indication_ && remote_indication_->id == id) {
    return &remote_indication_;
  }

  FXL_VLOG(1) << "att: id " << id << " does not match any transaction";
  return nullptr;
}

void Bearer::HandlePDUWithoutResponse(const PacketReader& packet) {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());

  auto iter = handlers_.find(packet.opcode());
  if (iter == handlers_.end()) {
    FXL_VLOG(1) << fxl::StringPrintf(
        "att: Dropping unhandled packet (opcode: 0x%02x)", packet.opcode());
    return;
  }

  iter->second(kInvalidTransactionId, packet);
}

void Bearer::OnChannelClosed() {
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());

  // This will deactivate the channel and notify |closed_cb_|.
  ShutDown();
}

void Bearer::OnRxBFrame(const l2cap::SDU& sdu) {
  FXL_DCHECK(is_open());
  FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());

  uint16_t length = sdu.length();

  // An ATT PDU should at least contain the opcode.
  if (length < sizeof(OpCode)) {
    FXL_VLOG(1) << "att: PDU too short!";
    ShutDown();
    return;
  }

  if (length > mtu_) {
    FXL_VLOG(1) << "att: PDU exceeds MTU!";
    ShutDown();
    return;
  }

  // The following will read the entire ATT PDU in a single call.
  l2cap::SDU::Reader reader(&sdu);
  reader.ReadNext(length, [this, length](const common::ByteBuffer& att_pdu) {
    FXL_CHECK(att_pdu.size() == length);
    PacketReader packet(&att_pdu);

    MethodType type = GetMethodType(packet.opcode());

    switch (type) {
      case MethodType::kResponse:
        HandleEndTransaction(&request_queue_, packet);
        break;
      case MethodType::kConfirmation:
        HandleEndTransaction(&indication_queue_, packet);
        break;
      case MethodType::kRequest:
        HandleBeginTransaction(&remote_request_, packet);
        break;
      case MethodType::kIndication:
        HandleBeginTransaction(&remote_indication_, packet);
        break;
      case MethodType::kNotification:
      case MethodType::kCommand:
        HandlePDUWithoutResponse(packet);
        break;
      default:
        FXL_VLOG(2) << fxl::StringPrintf("att: Unsupported opcode: 0x%02x",
                                         packet.opcode());
        SendErrorResponse(packet.opcode(), 0, ErrorCode::kRequestNotSupported);
        break;
    }
  });
}

}  // namespace att
}  // namespace btlib
