// Copyright 2018 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 "src/connectivity/bluetooth/core/bt-host/l2cap/bredr_signaling_channel.h"

#include <zircon/compiler.h>

#include "src/connectivity/bluetooth/core/bt-host/common/log.h"

namespace bt {
namespace l2cap {
namespace internal {

BrEdrSignalingChannel::BrEdrSignalingChannel(fbl::RefPtr<Channel> chan, hci::Connection::Role role)
    : SignalingChannel(std::move(chan), role) {
  set_mtu(kDefaultMTU);

  // Add default handler for incoming Echo Request commands.
  ServeRequest(kEchoRequest, [](const ByteBuffer& req_payload, Responder* responder) {
    responder->Send(req_payload);
  });
}

bool BrEdrSignalingChannel::TestLink(const ByteBuffer& data, DataCallback cb) {
  return SendRequest(kEchoRequest, data,
                     [cb = std::move(cb)](Status status, const ByteBuffer& rsp_payload) {
                       if (status == Status::kSuccess) {
                         cb(rsp_payload);
                       } else {
                         cb(BufferView());
                       }
                       return ResponseHandlerAction::kCompleteOutboundTransaction;
                     });
}

void BrEdrSignalingChannel::DecodeRxUnit(ByteBufferPtr sdu, const SignalingPacketHandler& cb) {
  // "Multiple commands may be sent in a single C-frame over Fixed Channel CID
  // 0x0001 (ACL-U) (v5.0, Vol 3, Part A, Section 4)"
  ZX_DEBUG_ASSERT(sdu);
  if (sdu->size() < sizeof(CommandHeader)) {
    bt_log(TRACE, "l2cap-bredr", "sig: dropped malformed ACL signaling packet");
    return;
  }

  size_t sdu_offset = 0;
  while (sdu_offset + sizeof(CommandHeader) <= sdu->size()) {
    auto& header_data = sdu->view(sdu_offset, sizeof(CommandHeader));
    SignalingPacket packet(&header_data);

    uint16_t expected_payload_length = le16toh(packet.header().length);
    size_t remaining_sdu_length = sdu->size() - sdu_offset - sizeof(CommandHeader);
    if (remaining_sdu_length < expected_payload_length) {
      bt_log(TRACE, "l2cap-bredr", "sig: expected more bytes (%zu < %u); drop",
             remaining_sdu_length, expected_payload_length);
      SendCommandReject(packet.header().id, RejectReason::kNotUnderstood, BufferView());
      return;
    }

    auto& packet_data = sdu->view(sdu_offset, sizeof(CommandHeader) + expected_payload_length);
    cb(SignalingPacket(&packet_data, expected_payload_length));

    sdu_offset += packet_data.size();
  }

  if (sdu_offset != sdu->size()) {
    bt_log(TRACE, "l2cap-bredr",
           "sig: incomplete packet header "
           "(expected: %zu, left: %zu)",
           sizeof(CommandHeader), sdu->size() - sdu_offset);
  }
}

bool BrEdrSignalingChannel::IsSupportedResponse(CommandCode code) const {
  switch (code) {
    case kCommandRejectCode:
    case kConnectionResponse:
    case kConfigurationResponse:
    case kDisconnectionResponse:
    case kEchoResponse:
    case kInformationResponse:
      return true;
  }

  // Other response-type commands are for AMP/LE and are not supported.
  return false;
}

}  // namespace internal
}  // namespace l2cap
}  // namespace bt
