// Copyright 2020 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 <fuzzer/FuzzedDataProvider.h>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/controller_test.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/controller_test_double_base.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/test_packets.h"

namespace bt::testing {

// ACL Buffer Info
constexpr size_t kMaxDataPacketLength = 64;
// Ensure outbound ACL packets aren't queued.
constexpr size_t kMaxPacketCount = 1000;

// If the packet size is too large, we consume too much of the fuzzer data per packet without much
// benefit.
constexpr uint16_t kMaxAclPacketSize = 100;

constexpr hci_spec::ConnectionHandle kHandle = 0x0001;

// Don't toggle connection too often or else l2cap won't get very far.
constexpr float kToggleConnectionChance = 0.04;

class FuzzerController : public ControllerTestDoubleBase {
 public:
  FuzzerController() {}
  ~FuzzerController() override = default;

 private:
  void OnCommandPacketReceived(const PacketView<hci_spec::CommandHeader>& command_packet) override {
  }
  void OnACLDataPacketReceived(const ByteBuffer& acl_data_packet) override {}
  void OnScoDataPacketReceived(const ByteBuffer& acl_data_packet) override {}
};

// Reuse ControllerTest test fixture code even though we're not using gtest.
using TestingBase = ControllerTest<FuzzerController>;
class DataFuzzTest : public TestingBase {
 public:
  DataFuzzTest(const uint8_t* data, size_t size) : data_(data, size), connection_(false) {
    TestingBase::SetUp();
    const auto bredr_buffer_info = hci::DataBufferInfo(kMaxDataPacketLength, kMaxPacketCount);
    InitializeACLDataChannel(bredr_buffer_info);

    domain_ = AdoptRef(
        new l2cap::ChannelManager(transport()->acl_data_channel(), /*random_channel_ids=*/true));

    StartTestDevice();
  }

  ~DataFuzzTest() override {
    domain_ = nullptr;
    TestingBase::TearDown();
  }

  void TestBody() override {
    RegisterService();

    while (data_.remaining_bytes() > 0) {
      bool run_loop = data_.ConsumeBool();
      if (run_loop) {
        RunLoopUntilIdle();
      }

      if (!SendAclPacket()) {
        break;
      }

      if (data_.ConsumeProbability<float>() < kToggleConnectionChance) {
        ToggleConnection();
      }
    }

    RunLoopUntilIdle();
  }

  bool SendAclPacket() {
    if (data_.remaining_bytes() < sizeof(uint64_t)) {
      return false;
    }
    // Consumes 8 bytes.
    auto packet_size = data_.ConsumeIntegralInRange<uint16_t>(
        sizeof(hci_spec::ACLDataHeader),
        std::min(static_cast<size_t>(kMaxAclPacketSize), data_.remaining_bytes()));

    auto packet_data = data_.ConsumeBytes<uint8_t>(packet_size);
    if (packet_data.size() < packet_size) {
      // Check if we ran out of fuzzer data.
      return false;
    }

    MutableBufferView packet_view(packet_data.data(), packet_data.size());

    // Use correct length so packets aren't rejected for invalid length.
    packet_view.AsMutable<hci_spec::ACLDataHeader>().data_total_length =
        htole16(packet_view.size() - sizeof(hci_spec::ACLDataHeader));

    // Use correct connection handle so packets aren't rejected/queued for invalid handle.
    uint16_t handle_and_flags =
        packet_view.ReadMember<&hci_spec::ACLDataHeader::handle_and_flags>();
    handle_and_flags &= 0xF000;  // Keep flags, clear handle.
    handle_and_flags |= kHandle;
    packet_view.AsMutable<hci_spec::ACLDataHeader>().handle_and_flags = handle_and_flags;

    auto status = test_device()->SendACLDataChannelPacket(packet_view);
    ZX_ASSERT(status == ZX_OK);
    return true;
  }

  void RegisterService() {
    domain_->RegisterService(l2cap::kAVDTP, l2cap::ChannelParameters(),
                             [this](fbl::RefPtr<l2cap::Channel> chan) {
                               if (!chan) {
                                 return;
                               }
                               chan->Activate(/*rx_callback=*/[](auto) {}, /*closed_callback=*/
                                              [this, id = chan->id()] { channels_.erase(id); });
                               channels_.emplace(chan->id(), std::move(chan));
                             });
  }

  void ToggleConnection() {
    if (connection_) {
      acl_data_channel()->UnregisterLink(kHandle);
      domain_->RemoveConnection(kHandle);
      connection_ = false;
      return;
    }

    acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kACL);
    domain_->AddACLConnection(
        kHandle, hci_spec::ConnectionRole::kCentral, /*link_error_callback=*/[] {},
        /*security_callback=*/[](auto, auto, auto) {});
    connection_ = true;
  }

 private:
  FuzzedDataProvider data_;
  fbl::RefPtr<l2cap::L2cap> domain_;
  bool connection_;
  std::unordered_map<l2cap::ChannelId, fbl::RefPtr<l2cap::Channel>> channels_;
};

}  // namespace bt::testing

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  bt::testing::DataFuzzTest fuzz(data, size);
  fuzz.TestBody();
  return 0;
}
