// 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 "discovery_filter.h"

#include <endian.h>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/advertising_data.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/low_energy_scanner.h"

namespace bt {
namespace gap {
namespace {

bool MatchUuids(const std::vector<UUID>& uuids, const BufferView& data,
                size_t uuid_size) {
  if (data.size() % uuid_size) {
    bt_log(WARN, "gap", "malformed service UUIDs list");
    return false;
  }

  size_t uuid_count = data.size() / uuid_size;
  for (size_t i = 0; i < uuid_count; i++) {
    const BufferView uuid_bytes(data.data() + i * uuid_size, uuid_size);
    for (const auto& uuid : uuids) {
      if (uuid.CompareBytes(uuid_bytes))
        return true;
    }
  }

  return false;
}

}  // namespace

void DiscoveryFilter::SetGeneralDiscoveryFlags() {
  set_flags(static_cast<uint8_t>(AdvFlag::kLEGeneralDiscoverableMode) |
            static_cast<uint8_t>(AdvFlag::kLELimitedDiscoverableMode));
}

bool DiscoveryFilter::MatchLowEnergyResult(const ByteBuffer& advertising_data,
                                           bool connectable,
                                           int8_t rssi) const {
  // No need to iterate over |advertising_data| for the |connectable_| filter.
  if (connectable_ && *connectable_ != connectable)
    return false;

  // If a pathloss filter is not set then apply the RSSI filter before iterating
  // over |advertising_data|. (An RSSI value of kRSSIInvalid means that RSSI is
  // not available, which we check for here).
  bool rssi_ok = !rssi_ || (rssi != hci::kRSSIInvalid && rssi >= *rssi_);
  if (!pathloss_ && !rssi_ok)
    return false;

  // Filters that require iterating over advertising data.
  bool flags_ok = !flags_;
  bool service_uuids_ok = service_uuids_.empty();
  bool name_ok = name_substring_.empty();
  bool manufacturer_ok = !manufacturer_code_;
  bool pathloss_ok = !pathloss_;
  bool tx_power_found = false;

  AdvertisingDataReader reader(advertising_data);
  if (advertising_data.size() && !reader.is_valid())
    return false;

  DataType type;
  BufferView data;
  while (reader.GetNextField(&type, &data)) {
    switch (type) {
      case DataType::kFlags: {
        if (flags_ok)
          break;

        // The Flags field may be zero or more octets long for potential future
        // extension. We only care about the first octet.
        if (data.size() < kFlagsSizeMin) {
          bt_log(WARN, "gap", "malformed flags field");
          break;
        }

        // We check if all bits in |flags_| are present in the data.
        uint8_t masked_flags = data[0] & *flags_;
        flags_ok =
            all_flags_required_ ? (masked_flags == *flags_) : !!masked_flags;

        break;
      }
      case DataType::kTxPowerLevel: {
        if (pathloss_ok)
          break;

        if (data.size() != kTxPowerLevelSize) {
          bt_log(WARN, "gap", "malformed tx-power level");
          break;
        }

        tx_power_found = true;

        // An RSSI value of kRSSIInvalid means that RSSI is not available.
        if (rssi == hci::kRSSIInvalid)
          break;

        int8_t tx_power_lvl = static_cast<int8_t>(*data.data());
        if (tx_power_lvl < rssi) {
          bt_log(WARN, "gap", "reported tx-power level is less than the RSSI");
          break;
        }

        int8_t pathloss = tx_power_lvl - rssi;
        pathloss_ok = (pathloss <= *pathloss_);
        break;
      }
      case DataType::kCompleteLocalName:
      case DataType::kShortenedLocalName: {
        if (name_ok)
          break;

        auto name = data.AsString();
        name_ok = (name.find(name_substring_) != fxl::StringView::npos);
        break;
      }
      case DataType::kManufacturerSpecificData:
        if (manufacturer_ok)
          break;

        // The first two octets of the manufacturer specific data field contains
        // the Company Identifier Code.
        if (data.size() < kManufacturerSpecificDataSizeMin) {
          bt_log(WARN, "gap", "malformed manufacturer-specific data");
          break;
        }

        manufacturer_ok =
            (le16toh(*reinterpret_cast<const uint16_t*>(data.data())) ==
             *manufacturer_code_);
        break;
      case DataType::kIncomplete16BitServiceUuids:
      case DataType::kComplete16BitServiceUuids:
        if (!service_uuids_ok) {
          service_uuids_ok =
              MatchUuids(service_uuids_, data, k16BitUuidElemSize);
        }
        break;
      case DataType::kIncomplete32BitServiceUuids:
      case DataType::kComplete32BitServiceUuids:
        if (!service_uuids_ok) {
          service_uuids_ok =
              MatchUuids(service_uuids_, data, k32BitUuidElemSize);
        }
        break;
      case DataType::kIncomplete128BitServiceUuids:
      case DataType::kComplete128BitServiceUuids:
        if (!service_uuids_ok) {
          service_uuids_ok =
              MatchUuids(service_uuids_, data, k128BitUuidElemSize);
        }
        break;
      default:
        break;
    }
  }

  // If the pathloss filter failed, then fall back to RSSI if requested.
  if (!pathloss_ok) {
    // No match if the Tx Power Level was provided and the computed pathloss
    // value was not within the threshold.
    if (tx_power_found)
      return false;

    // If no RSSI filter was set OR if one was set but it didn't match the scan
    // result, we fail.
    if (!rssi_ || !rssi_ok)
      return false;
  }

  return flags_ok && service_uuids_ok && name_ok && manufacturer_ok;
}

void DiscoveryFilter::Reset() {
  service_uuids_.clear();
  name_substring_.clear();
  connectable_.reset();
  manufacturer_code_.reset();
  pathloss_.reset();
  rssi_.reset();
}

}  // namespace gap
}  // namespace bt
