/*
 * Copyright 2020 The Android Open Source Project
 *
 * 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 "hci/fuzz/fuzz_hci_layer.h"
#include "fuzz/helpers.h"

namespace bluetooth {
namespace hci {
namespace fuzz {

using bluetooth::common::ContextualCallback;
using bluetooth::fuzz::GetArbitraryBytes;
using bluetooth::fuzz::InvokeIfValid;

hci::SecurityInterface* FuzzHciLayer::GetSecurityInterface(ContextualCallback<void(hci::EventView)> event_handler) {
  return &security_interface_;
}

hci::LeSecurityInterface* FuzzHciLayer::GetLeSecurityInterface(
    ContextualCallback<void(hci::LeMetaEventView)> event_handler) {
  return &le_security_interface_;
}

hci::AclConnectionInterface* FuzzHciLayer::GetAclConnectionInterface(
    ContextualCallback<void(hci::EventView)> event_handler,
    ContextualCallback<void(uint16_t, hci::ErrorCode)> on_disconnect,
    ContextualCallback<
        void(hci::ErrorCode, uint16_t, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version)>
        on_read_remote_version) {
  return &acl_connection_interface_;
}

hci::LeAclConnectionInterface* FuzzHciLayer::GetLeAclConnectionInterface(
    ContextualCallback<void(hci::LeMetaEventView)> event_handler,
    ContextualCallback<void(uint16_t, hci::ErrorCode)> on_disconnect,
    ContextualCallback<
        void(hci::ErrorCode, uint16_t, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version)>
        on_read_remote_version) {
  return &le_acl_connection_interface_;
}

hci::LeAdvertisingInterface* FuzzHciLayer::GetLeAdvertisingInterface(
    ContextualCallback<void(hci::LeMetaEventView)> event_handler) {
  return &le_advertising_interface_;
}

hci::LeScanningInterface* FuzzHciLayer::GetLeScanningInterface(
    ContextualCallback<void(hci::LeMetaEventView)> event_handler) {
  return &le_scanning_interface_;
}

hci::LeIsoInterface* FuzzHciLayer::GetLeIsoInterface(ContextualCallback<void(hci::LeMetaEventView)> event_handler) {
  return &le_iso_interface_;
}

void FuzzHciLayer::Start() {
  acl_dev_null_ = new os::fuzz::DevNullQueue<AclBuilder>(acl_queue_.GetDownEnd(), GetHandler());
  acl_dev_null_->Start();
  acl_inject_ = new os::fuzz::FuzzInjectQueue<AclView>(acl_queue_.GetDownEnd(), GetHandler());
}

void FuzzHciLayer::Stop() {
  acl_dev_null_->Stop();
  delete acl_dev_null_;
  delete acl_inject_;
}

void FuzzHciLayer::injectArbitrary(FuzzedDataProvider& fdp) {
  const uint8_t action = fdp.ConsumeIntegralInRange(0, 13);
  switch (action) {
    case 1:
      injectAclData(GetArbitraryBytes(&fdp));
      break;
    case 2:
      injectCommandComplete(GetArbitraryBytes(&fdp));
      break;
    case 3:
      injectCommandStatus(GetArbitraryBytes(&fdp));
      break;
    case 4:
      injectEvent(fdp);
      break;
    case 5:
      injectLeEvent(fdp);
      break;
    case 6:
      injectSecurityEvent(GetArbitraryBytes(&fdp));
      break;
    case 7:
      injectLeSecurityEvent(GetArbitraryBytes(&fdp));
      break;
    case 8:
      injectAclEvent(GetArbitraryBytes(&fdp));
      break;
    case 9:
      injectAclDisconnect(fdp);
      break;
    case 10:
      injectLeAclEvent(GetArbitraryBytes(&fdp));
      break;
    case 11:
      injectLeAclDisconnect(fdp);
      break;
    case 12:
      injectLeAdvertisingEvent(GetArbitraryBytes(&fdp));
      break;
    case 13:
      injectLeScanningEvent(GetArbitraryBytes(&fdp));
      break;
  }
}

void FuzzHciLayer::injectAclData(std::vector<uint8_t> data) {
  CONSTRUCT_VALID_UNIQUE_OTHERWISE_BAIL(hci::AclView, packet, data);
  acl_inject_->Inject(std::move(packet));
}

void FuzzHciLayer::injectCommandComplete(std::vector<uint8_t> data) {
  InvokeIfValid<hci::CommandCompleteView>(std::move(on_command_complete_), data);
}

void FuzzHciLayer::injectCommandStatus(std::vector<uint8_t> data) {
  InvokeIfValid<hci::CommandStatusView>(std::move(on_command_status_), data);
}

void FuzzHciLayer::injectEvent(FuzzedDataProvider& fdp) {
  auto handler_pair = event_handlers_.find(static_cast<EventCode>(fdp.ConsumeIntegral<uint8_t>()));
  if (handler_pair != event_handlers_.end()) {
    InvokeIfValid<EventView>(handler_pair->second, GetArbitraryBytes(&fdp));
  }
}

void FuzzHciLayer::injectLeEvent(FuzzedDataProvider& fdp) {
  auto handler_pair = le_event_handlers_.find(static_cast<SubeventCode>(fdp.ConsumeIntegral<uint8_t>()));
  if (handler_pair != le_event_handlers_.end()) {
    InvokeIfValid<LeMetaEventView>(handler_pair->second, GetArbitraryBytes(&fdp));
  }
}

void FuzzHciLayer::injectSecurityEvent(std::vector<uint8_t> data) {
  InvokeIfValid<EventView>(security_event_handler_, data);
}

void FuzzHciLayer::injectLeSecurityEvent(std::vector<uint8_t> data) {
  InvokeIfValid<LeMetaEventView>(le_security_event_handler_, data);
}

void FuzzHciLayer::injectAclEvent(std::vector<uint8_t> data) {
  InvokeIfValid<EventView>(acl_event_handler_, data);
}

void FuzzHciLayer::injectAclDisconnect(FuzzedDataProvider& fdp) {
  acl_on_disconnect_.InvokeIfNotEmpty(fdp.ConsumeIntegral<uint16_t>(),
                                      static_cast<hci::ErrorCode>(fdp.ConsumeIntegral<uint8_t>()));
}

void FuzzHciLayer::injectLeAclEvent(std::vector<uint8_t> data) {
  InvokeIfValid<LeMetaEventView>(le_acl_event_handler_, data);
}

void FuzzHciLayer::injectLeAclDisconnect(FuzzedDataProvider& fdp) {
  le_acl_on_disconnect_.InvokeIfNotEmpty(fdp.ConsumeIntegral<uint16_t>(),
                                         static_cast<hci::ErrorCode>(fdp.ConsumeIntegral<uint8_t>()));
}

void FuzzHciLayer::injectLeAdvertisingEvent(std::vector<uint8_t> data) {
  InvokeIfValid<LeMetaEventView>(le_advertising_event_handler_, data);
}

void FuzzHciLayer::injectLeScanningEvent(std::vector<uint8_t> data) {
  InvokeIfValid<LeMetaEventView>(le_scanning_event_handler_, data);
}

void FuzzHciLayer::injectLeIsoEvent(std::vector<uint8_t> data) {
  InvokeIfValid<LeMetaEventView>(le_iso_event_handler_, data);
}

const ModuleFactory FuzzHciLayer::Factory = ModuleFactory([]() { return new FuzzHciLayer(); });

}  // namespace fuzz
}  // namespace hci
}  // namespace bluetooth
