// 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 <fuchsia/wlan/minstrel/cpp/fidl.h>
#include <fuchsia/wlan/mlme/cpp/fidl.h>
#include <zircon/fidl.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <atomic>
#include <cinttypes>
#include <cstring>
#include <memory>
#include <sstream>

#include <ddk/hw/wlan/wlaninfo.h>
#include <wlan/common/band.h>
#include <wlan/common/channel.h>
#include <wlan/common/mac_frame.h>
#include <wlan/common/stats.h>
#include <wlan/mlme/ap/ap_mlme.h>
#include <wlan/mlme/client/client_mlme.h>
#include <wlan/mlme/device_interface.h>
#include <wlan/mlme/dispatcher.h>
#include <wlan/mlme/mac_frame.h>
#include <wlan/mlme/packet.h>
#include <wlan/mlme/service.h>
#include <wlan/protocol/mac.h>

namespace wlan {

namespace wlan_common = ::fuchsia::wlan::common;
namespace wlan_mlme = ::fuchsia::wlan::mlme;
namespace wlan_minstrel = ::fuchsia::wlan::minstrel;
namespace wlan_stats = ::fuchsia::wlan::stats;

Dispatcher::Dispatcher(DeviceInterface* device, std::unique_ptr<Mlme> mlme)
    : device_(device), mlme_(std::move(mlme)) {
  debugfn();
  ZX_ASSERT(mlme_ != nullptr);
}

Dispatcher::~Dispatcher() {}

zx_status_t Dispatcher::HandlePacket(std::unique_ptr<Packet> packet) {
  debugfn();

  ZX_DEBUG_ASSERT(packet != nullptr);
  ZX_DEBUG_ASSERT(packet->peer() != Packet::Peer::kUnknown);

  WLAN_STATS_INC(any_packet.in);

  // If there is no active MLME, block all packets but service ones.
  // MLME-JOIN.request and MLME-START.request implicitly select a mode and
  // initialize the MLME. DEVICE_QUERY.request is used to obtain device
  // capabilities.

  auto service_msg = (packet->peer() == Packet::Peer::kService);
  if (mlme_ == nullptr && !service_msg) {
    WLAN_STATS_INC(any_packet.drop);
    return ZX_OK;
  }

  WLAN_STATS_INC(any_packet.out);

  zx_status_t status = ZX_OK;
  switch (packet->peer()) {
    case Packet::Peer::kEthernet:
      status = mlme_->HandleFramePacket(std::move(packet));
      break;
    case Packet::Peer::kWlan:
      if (auto fc = packet->field<FrameControl>(0)) {
        switch (fc->type()) {
          case FrameType::kManagement:
            WLAN_STATS_INC(mgmt_frame.in);
            break;
          case FrameType::kControl:
            WLAN_STATS_INC(ctrl_frame.in);
            break;
          case FrameType::kData:
            WLAN_STATS_INC(data_frame.in);
            break;
          default:
            break;
        }

        status = mlme_->HandleFramePacket(std::move(packet));
      }
      break;
    default:
      break;
  }

  return status;
}

zx_status_t Dispatcher::HandlePortPacket(uint64_t key) {
  debugfn();
  ZX_DEBUG_ASSERT(ToPortKeyType(key) == PortKeyType::kMlme);

  ObjectId id(ToPortKeyId(key));
  switch (id.subtype()) {
    case to_enum_type(ObjectSubtype::kTimer): {
      auto status = mlme_->HandleTimeout(id);
      if (status == ZX_ERR_NOT_SUPPORTED) {
        warnf("unknown MLME timer target: %u\n", id.target());
      }
      break;
    }
    default:
      warnf("unknown MLME event subtype: %u\n", id.subtype());
  }
  return ZX_OK;
}

zx_status_t Dispatcher::HandleAnyMlmeMessage(fbl::Span<uint8_t> span) {
  debugfn();
  // Attempt to process encoded message in MLME.
  auto hdr = FromBytes<fidl_message_header_t>(span);
  if (hdr == nullptr) {
    errorf("short mlme message, len=%zu\n", span.size());
    return ZX_OK;
  }
  uint64_t ordinal = hdr->ordinal;
  debughdr("service packet txid=%u ordinal=%lu\n", hdr->txid, ordinal);

  // TODO(fxbug.dev/44480): Rust MLME message handler does not support transaction ID.
  switch (ordinal) {
    case fuchsia::wlan::mlme::internal::kMLME_QueryDeviceInfo_Ordinal:
      return HandleQueryDeviceInfo(hdr->txid);
    case fuchsia::wlan::mlme::internal::kMLME_ListMinstrelPeers_Ordinal:
      return HandleMinstrelPeerList(ordinal, hdr->txid);
    case fuchsia::wlan::mlme::internal::kMLME_GetMinstrelStats_Ordinal:
      return HandleMinstrelTxStats(span, ordinal, hdr->txid);
    // TODO(fxbug.dev/44485): Rust MLME does not support Mesh.
    case fuchsia::wlan::mlme::internal::kMLME_SendMpOpenAction_Ordinal:
      return HandleMlmeMessage<wlan_mlme::MeshPeeringOpenAction>(span, ordinal);
    case fuchsia::wlan::mlme::internal::kMLME_SendMpConfirmAction_Ordinal:
      return HandleMlmeMessage<wlan_mlme::MeshPeeringConfirmAction>(span, ordinal);
    case fuchsia::wlan::mlme::internal::kMLME_MeshPeeringEstablished_Ordinal:
      return HandleMlmeMessage<wlan_mlme::MeshPeeringParams>(span, ordinal);
    case fuchsia::wlan::mlme::internal::kMLME_GetMeshPathTableReq_Ordinal:
      return HandleMlmeMessage<wlan_mlme::GetMeshPathTableRequest>(span, ordinal);
    default:
      return mlme_->HandleEncodedMlmeMsg(span);
  }
}

template <typename Message>
zx_status_t Dispatcher::HandleMlmeMessage(fbl::Span<uint8_t> span, uint64_t ordinal) {
  // If the encoded message was not handled, manually decode and dispatch message.
  auto msg = MlmeMsg<Message>::Decode(span, ordinal);
  if (!msg.has_value()) {
    errorf("could not deserialize MLME primitive %lu: \n", ordinal);
    return ZX_ERR_INVALID_ARGS;
  }
  return mlme_->HandleMlmeMsg(*msg);
}

zx_status_t Dispatcher::HandleQueryDeviceInfo(zx_txid_t txid) {
  debugfn();

  wlan_mlme::DeviceInfo resp;
  const wlan_info_t& info = device_->GetWlanInfo().ifc_info;

  memcpy(resp.mac_addr.data(), info.mac_addr, ETH_MAC_SIZE);

  // mac_role is a bitfield, but only a single value is supported for an
  // interface
  switch (info.mac_role) {
    case WLAN_INFO_MAC_ROLE_CLIENT:
      resp.role = wlan_mlme::MacRole::CLIENT;
      break;
    case WLAN_INFO_MAC_ROLE_AP:
      resp.role = wlan_mlme::MacRole::AP;
      break;
    case WLAN_INFO_MAC_ROLE_MESH:
      resp.role = wlan_mlme::MacRole::MESH;
      break;
    default:
      // TODO(fxbug.dev/28723): return an error!
      break;
  }

  auto wlanmac_info = device_->GetWlanInfo().ifc_info;

  resp.bands.resize(0);
  for (uint8_t band_idx = 0; band_idx < info.bands_count; band_idx++) {
    const wlan_info_band_info_t& band_info = info.bands[band_idx];
    wlan_mlme::BandCapabilities band;
    band.band_id = wlan::common::BandToFidl(band_info.band);
    band.rates.resize(0);
    for (size_t rate_idx = 0; rate_idx < sizeof(band_info.rates); rate_idx++) {
      if (band_info.rates[rate_idx] != 0) {
        band.rates.push_back(band_info.rates[rate_idx]);
      }
    }
    const wlan_info_channel_list_t& chan_list = band_info.supported_channels;
    band.base_frequency = chan_list.base_freq;
    band.channels.resize(0);
    for (size_t chan_idx = 0; chan_idx < sizeof(chan_list.channels); chan_idx++) {
      if (chan_list.channels[chan_idx] != 0) {
        band.channels.push_back(chan_list.channels[chan_idx]);
      }
    }

    band.cap = CapabilityInfo::FromDdk(wlanmac_info.caps).val();

    if (band_info.ht_supported) {
      auto ht_cap = HtCapabilities::FromDdk(band_info.ht_caps);
      band.ht_cap = wlan_mlme::HtCapabilities::New();
      static_assert(sizeof(band.ht_cap->bytes) == sizeof(ht_cap));
      memcpy(band.ht_cap->bytes.data(), &ht_cap, sizeof(ht_cap));
    }
    if (band_info.vht_supported) {
      auto vht_cap = VhtCapabilities::FromDdk(band_info.vht_caps);
      band.vht_cap = wlan_mlme::VhtCapabilities::New();
      static_assert(sizeof(band.vht_cap->bytes) == sizeof(vht_cap));
      memcpy(band.vht_cap->bytes.data(), &vht_cap, sizeof(vht_cap));
    }

    resp.bands.push_back(std::move(band));
  }

  resp.driver_features.resize(0);
  if (info.driver_features & WLAN_INFO_DRIVER_FEATURE_SCAN_OFFLOAD) {
    resp.driver_features.push_back(wlan_common::DriverFeature::SCAN_OFFLOAD);
  }
  if (info.driver_features & WLAN_INFO_DRIVER_FEATURE_RATE_SELECTION) {
    resp.driver_features.push_back(wlan_common::DriverFeature::RATE_SELECTION);
  }
  if (info.driver_features & WLAN_INFO_DRIVER_FEATURE_SYNTH) {
    resp.driver_features.push_back(wlan_common::DriverFeature::SYNTH);
  }
  if (info.driver_features & WLAN_INFO_DRIVER_FEATURE_TX_STATUS_REPORT) {
    resp.driver_features.push_back(wlan_common::DriverFeature::TX_STATUS_REPORT);
  }
  if (info.driver_features & WLAN_INFO_DRIVER_FEATURE_DFS) {
    resp.driver_features.push_back(wlan_common::DriverFeature::DFS);
  }
  if (info.driver_features & WLAN_INFO_DRIVER_FEATURE_PROBE_RESP_OFFLOAD) {
    resp.driver_features.push_back(wlan_common::DriverFeature::PROBE_RESP_OFFLOAD);
  }
  resp.driver_features.push_back(wlan_common::DriverFeature::SAE_SME_AUTH);
  // TODO(fxbug.dev/41640): Remove this flag once FullMAC drivers no longer needs SME.
  // This flag tells SME that SoftMAC drivers need SME to derive association capabilities.
  resp.driver_features.push_back(wlan_common::DriverFeature::TEMP_SOFTMAC);

  return SendServiceMsg(device_, &resp,
                        fuchsia::wlan::mlme::internal::kMLME_QueryDeviceInfo_Ordinal, txid);
}

zx_status_t Dispatcher::HandleMlmeStats(uint64_t ordinal) const {
  debugfn();
  wlan_mlme::StatsQueryResponse resp = GetStatsToFidl();
  return SendServiceMsg(device_, &resp,
                        fuchsia::wlan::mlme::internal::kMLME_StatsQueryResp_Ordinal);
}

zx_status_t Dispatcher::HandleMinstrelPeerList(uint64_t ordinal, zx_txid_t txid) const {
  debugfn();
  wlan_mlme::MinstrelListResponse resp{};
  zx_status_t status = device_->GetMinstrelPeers(&resp.peers);
  if (status != ZX_OK) {
    errorf("cannot get minstrel peer list: %s\n", zx_status_get_string(status));
    resp.peers.peers.resize(0);
  }
  return SendServiceMsg(device_, &resp,
                        fuchsia::wlan::mlme::internal::kMLME_ListMinstrelPeers_Ordinal, txid);
}

zx_status_t Dispatcher::HandleMinstrelTxStats(fbl::Span<uint8_t> span, uint64_t ordinal,
                                              zx_txid_t txid) const {
  debugfn();
  wlan_mlme::MinstrelStatsResponse resp{};
  auto req = MlmeMsg<wlan_mlme::MinstrelStatsRequest>::Decode(
      span, fuchsia::wlan::mlme::internal::kMLME_GetMinstrelStats_Ordinal);
  if (!req.has_value()) {
    errorf("could not deserialize MLME primitive %lu\n", ordinal);
    return ZX_ERR_INVALID_ARGS;
  }
  common::MacAddr addr(req->body()->mac_addr);

  wlan_minstrel::Peer peer;
  auto status = device_->GetMinstrelStats(addr, &peer);
  if (status == ZX_OK) {
    resp.peer = std::make_unique<wlan_minstrel::Peer>(std::move(peer));
  } else {
    errorf("could not get peer stats: %s\n", zx_status_get_string(status));
  }
  return SendServiceMsg(device_, &resp,
                        fuchsia::wlan::mlme::internal::kMLME_GetMinstrelStats_Ordinal, txid);
}

void Dispatcher::HwIndication(uint32_t ind) {
  debugfn();
  mlme_->HwIndication(ind);
}

void Dispatcher::HwScanComplete(uint8_t result_code) {
  debugfn();
  mlme_->HwScanComplete(result_code);
}

void Dispatcher::ResetStats() {
  stats_.Reset();
  if (mlme_) {
    mlme_->ResetMlmeStats();
  }
}

wlan_mlme::StatsQueryResponse Dispatcher::GetStatsToFidl() const {
  wlan_mlme::StatsQueryResponse stats_response;
  stats_response.stats.dispatcher_stats = stats_.ToFidl();
  auto mlme_stats = mlme_->GetMlmeStats();
  if (!mlme_stats.has_invalid_tag()) {
    stats_response.stats.mlme_stats =
        std::make_unique<wlan_stats::MlmeStats>(mlme_->GetMlmeStats());
  }
  return stats_response;
}

}  // namespace wlan
