// 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::l2cap::internal {

BrEdrSignalingChannel::BrEdrSignalingChannel(fbl::RefPtr<Channel> chan,
                                             hci_spec::ConnectionRole 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(DEBUG, "l2cap-bredr", "sig: dropped malformed ACL signaling packet");
    return;
  }

  size_t sdu_offset = 0;
  while (sdu_offset + sizeof(CommandHeader) <= sdu->size()) {
    const 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(DEBUG, "l2cap-bredr", "sig: expected more bytes (%zu < %u); drop",
             remaining_sdu_length, expected_payload_length);
      SendCommandReject(packet.header().id, RejectReason::kNotUnderstood, BufferView());
      return;
    }

    const 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(DEBUG, "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 bt::l2cap::internal
