// 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 <wlan/mlme/dispatcher.h>

#include <fbl/unique_ptr.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/debug.h>
#include <wlan/mlme/device_interface.h>
#include <wlan/mlme/mac_frame.h>
#include <wlan/mlme/packet.h>
#include <wlan/mlme/service.h>
#include <wlan/protocol/mac.h>
#include <zircon/fidl.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <fuchsia/wlan/minstrel/cpp/fidl.h>
#include <fuchsia/wlan/mlme/c/fidl.h>
#include <fuchsia/wlan/mlme/cpp/fidl.h>

#include <zircon/fidl.h>
#include <atomic>
#include <cinttypes>
#include <cstring>
#include <sstream>

#include "lib/svc/cpp/services.h"

namespace wlan {

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

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

Dispatcher::~Dispatcher() {}

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

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

    finspect("Packet: %s\n", debug::Describe(*packet).c_str());

    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(Span<uint8_t> span) {
    debugfn();

    auto hdr = FromBytes<fidl_message_header_t>(span);
    if (hdr == nullptr) {
        errorf("short mlme message, len=%zu\n", span.size());
        return ZX_OK;
    }
    debughdr("service packet txid=%u flags=%u ordinal=%u\n", hdr->txid, hdr->flags, hdr->ordinal);

    // Messages in wlan_mlme_ext.fidl does not involve MLME.
    switch (hdr->ordinal) {
    case fuchsia_wlan_mlme_MLMEQueryDeviceInfoOrdinal:
        return HandleQueryDeviceInfo(hdr->txid);
    case fuchsia_wlan_mlme_MLMEStatsQueryReqOrdinal:
        return HandleMlmeStats(hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEListMinstrelPeersOrdinal:
        return HandleMinstrelPeerList(hdr->ordinal, hdr->txid);
    case fuchsia_wlan_mlme_MLMEGetMinstrelStatsOrdinal:
        return HandleMinstrelTxStats(span, hdr->ordinal, hdr->txid);
    }

    switch (hdr->ordinal) {
    case fuchsia_wlan_mlme_MLMEResetReqOrdinal:
        infof("resetting MLME\n");
        HandleMlmeMessage<wlan_mlme::ResetRequest>(span, hdr->ordinal);
        return ZX_OK;
    case fuchsia_wlan_mlme_MLMEStartReqOrdinal:
        return HandleMlmeMessage<wlan_mlme::StartRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEStopReqOrdinal:
        return HandleMlmeMessage<wlan_mlme::StopRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEStartScanOrdinal:
        return HandleMlmeMessage<wlan_mlme::ScanRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEJoinReqOrdinal:
        return HandleMlmeMessage<wlan_mlme::JoinRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEAuthenticateReqOrdinal:
        return HandleMlmeMessage<wlan_mlme::AuthenticateRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEAuthenticateRespOrdinal:
        return HandleMlmeMessage<wlan_mlme::AuthenticateResponse>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEDeauthenticateReqOrdinal:
        return HandleMlmeMessage<wlan_mlme::DeauthenticateRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEAssociateReqOrdinal:
        return HandleMlmeMessage<wlan_mlme::AssociateRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEAssociateRespOrdinal:
        return HandleMlmeMessage<wlan_mlme::AssociateResponse>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEEapolReqOrdinal:
        return HandleMlmeMessage<wlan_mlme::EapolRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMESetKeysReqOrdinal:
        return HandleMlmeMessage<wlan_mlme::SetKeysRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMESetControlledPortOrdinal:
        return HandleMlmeMessage<wlan_mlme::SetControlledPortRequest>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMESendMpOpenActionOrdinal:
        return HandleMlmeMessage<wlan_mlme::MeshPeeringOpenAction>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMESendMpConfirmActionOrdinal:
        return HandleMlmeMessage<wlan_mlme::MeshPeeringConfirmAction>(span, hdr->ordinal);
    case fuchsia_wlan_mlme_MLMEMeshPeeringEstablishedOrdinal:
        return HandleMlmeMessage<wlan_mlme::MeshPeeringParams>(span, hdr->ordinal);
    default:
        warnf("unknown MLME method %u\n", hdr->ordinal);
        return ZX_ERR_NOT_SUPPORTED;
    }
}

template <typename Message>
zx_status_t Dispatcher::HandleMlmeMessage(Span<uint8_t> span, uint32_t ordinal) {
    auto msg = MlmeMsg<Message>::Decode(span, ordinal);
    if (!msg.has_value()) {
        errorf("could not deserialize MLME primitive %d: \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.mutable_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_MAC_ROLE_CLIENT:
        resp.role = wlan_mlme::MacRole::CLIENT;
        break;
    case WLAN_MAC_ROLE_AP:
        resp.role = wlan_mlme::MacRole::AP;
        break;
    case WLAN_MAC_ROLE_MESH:
        resp.role = wlan_mlme::MacRole::MESH;
        break;
    default:
        // TODO(NET-1116): return an error!
        break;
    }

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

    resp.bands.resize(0);
    for (uint8_t band_idx = 0; band_idx < info.num_bands; band_idx++) {
        const wlan_band_info_t& band_info = info.bands[band_idx];
        wlan_mlme::BandCapabilities band;
        band.band_id = wlan::common::BandToFidl(band_info.band_id);
        band.basic_rates.resize(0);
        for (size_t rate_idx = 0; rate_idx < sizeof(band_info.basic_rates); rate_idx++) {
            if (band_info.basic_rates[rate_idx] != 0) {
                band.basic_rates.push_back(band_info.basic_rates[rate_idx]);
            }
        }
        const wlan_chan_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).ToFidl();

        if (band_info.ht_supported) {
            auto ht_cap = HtCapabilities::FromDdk(band_info.ht_caps);
            band.ht_cap = std::make_unique<wlan_mlme::HtCapabilities>(ht_cap.ToFidl());
        }
        if (band_info.vht_supported) {
            auto vht_cap = VhtCapabilities::FromDdk(band_info.vht_caps);
            band.vht_cap = std::make_unique<wlan_mlme::VhtCapabilities>(vht_cap.ToFidl());
        }

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

    return SendServiceMsg(device_, &resp, fuchsia_wlan_mlme_MLMEQueryDeviceInfoOrdinal, txid);
}

zx_status_t Dispatcher::HandleMlmeStats(uint32_t ordinal) const {
    debugfn();
    wlan_mlme::StatsQueryResponse resp = GetStatsToFidl();
    return SendServiceMsg(device_, &resp, fuchsia_wlan_mlme_MLMEStatsQueryRespOrdinal);
}

zx_status_t Dispatcher::HandleMinstrelPeerList(uint32_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_MLMEListMinstrelPeersOrdinal, txid);
}

zx_status_t Dispatcher::HandleMinstrelTxStats(Span<uint8_t> span, uint32_t ordinal,
                                              zx_txid_t txid) const {
    debugfn();
    wlan_mlme::MinstrelStatsResponse resp{};
    auto req = MlmeMsg<wlan_mlme::MinstrelStatsRequest>::Decode(
        span, fuchsia_wlan_mlme_MLMEGetMinstrelStatsOrdinal);
    if (!req.has_value()) {
        errorf("could not deserialize MLME primitive %d\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_MLMEGetMinstrelStatsOrdinal, 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
