// 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/client/client_mlme.h>

#include <wlan/common/bitfield.h>
#include <wlan/common/channel.h>
#include <wlan/common/logging.h>
#include <wlan/mlme/client/client_factory.h>
#include <wlan/mlme/client/scanner.h>
#include <wlan/mlme/client/station.h>
#include <wlan/mlme/debug.h>
#include <wlan/mlme/mac_frame.h>
#include <wlan/mlme/packet.h>
#include <wlan/mlme/service.h>
#include <wlan/mlme/timer.h>
#include <wlan/mlme/timer_manager.h>
#include <wlan/mlme/wlan.h>

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

#include <lib/zx/time.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>

#include <cinttypes>
#include <cstring>
#include <sstream>

namespace wlan {

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

ClientMlme::ClientMlme(DeviceInterface* device) : device_(device), on_channel_handler_(this) {
    debugfn();
}

ClientMlme::~ClientMlme() = default;

zx_status_t ClientMlme::Init() {
    debugfn();

    fbl::unique_ptr<Timer> timer;
    ObjectId timer_id;
    timer_id.set_subtype(to_enum_type(ObjectSubtype::kTimer));
    timer_id.set_target(to_enum_type(ObjectTarget::kChannelScheduler));
    zx_status_t status = device_->GetTimer(ToPortKey(PortKeyType::kMlme, timer_id.val()), &timer);
    if (status != ZX_OK) {
        errorf("could not create channel scheduler timer: %d\n", status);
        return status;
    }
    chan_sched_.reset(new ChannelScheduler(&on_channel_handler_, device_, std::move(timer)));

    scanner_.reset(new Scanner(device_, chan_sched_.get()));
    return status;
}

zx_status_t ClientMlme::HandleTimeout(const ObjectId id) {
    switch (id.target()) {
    case to_enum_type(ObjectTarget::kChannelScheduler):
        chan_sched_->HandleTimeout();
        break;
    case to_enum_type(ObjectTarget::kStation):
        if (sta_ != nullptr) {
            sta_->HandleTimeout();
        } else {
            warnf("timeout for unknown STA: %zu\n", id.mac());
        }
        break;
    default:
        ZX_DEBUG_ASSERT(0);
        return ZX_ERR_NOT_SUPPORTED;
    }
    return ZX_OK;
}

void ClientMlme::HwScanComplete(uint8_t result_code) {
    if (result_code == WLAN_HW_SCAN_SUCCESS) {
        scanner_->HandleHwScanComplete();
    } else {
        scanner_->HandleHwScanAborted();
    }
}

zx_status_t ClientMlme::HandleMlmeMsg(const BaseMlmeMsg& msg) {
    if (auto scan_req = msg.As<wlan_mlme::ScanRequest>()) {
        // Let the Scanner handle all MLME-SCAN.requests.
        return scanner_->HandleMlmeScanReq(*scan_req);
    } else if (auto join_req = msg.As<wlan_mlme::JoinRequest>()) {
        // An MLME-JOIN-request will synchronize the MLME with the request's BSS.
        // Synchronization is mandatory for spawning a client and starting its association flow.

        Unjoin();
        return HandleMlmeJoinReq(*join_req);
    } else if (!join_ctx_.has_value()) {
        warnf("rx'ed MLME message (ordinal: %u) before synchronizing with a BSS\n", msg.ordinal());
        return ZX_ERR_BAD_STATE;
    }

    // TODO(hahnr): Keys should not be handled in the STA and instead in the MLME.
    // For now, shortcut into the STA and leave this change as a follow-up.
    if (auto setkeys_req = msg.As<wlan_mlme::SetKeysRequest>()) {
        if (sta_ != nullptr) {
            return sta_->SetKeys(setkeys_req->body()->keylist);
        } else {
            warnf("rx'ed MLME message (ordinal: %u) before authenticating with a BSS\n",
                  msg.ordinal());
            return ZX_ERR_BAD_STATE;
        }
    }

    // All remaining message must use the same BSS this MLME synchronized to before.
    auto peer_addr = service::GetPeerAddr(msg);
    if (!peer_addr.has_value()) {
        warnf("rx'ed unsupported MLME msg (ordinal: %u)\n", msg.ordinal());
        return ZX_ERR_INVALID_ARGS;
    } else if (peer_addr.value() != join_ctx_->bssid()) {
        warnf("rx'ed MLME msg (ordinal: %u) with unexpected peer addr; expected: %s ; actual: %s\n",
              msg.ordinal(), join_ctx_->bssid().ToString().c_str(), peer_addr->ToString().c_str());
        return ZX_ERR_INVALID_ARGS;
    }

    // This will spawn a new client instance and start association flow.
    if (auto auth_req = msg.As<wlan_mlme::AuthenticateRequest>()) {
        auto status = SpawnStation();
        if (status != ZX_OK) {
            errorf("error spawning STA: %d\n", status);
            return service::SendAuthConfirm(device_, join_ctx_->bssid(),
                                            wlan_mlme::AuthenticateResultCodes::REFUSED);
        }

        // Let station handle the request itself.
        return sta_->Authenticate(auth_req->body()->auth_type,
                                  auth_req->body()->auth_failure_timeout);
    }

    // If the STA exists, forward all incoming MLME messages.
    if (sta_ == nullptr) {
        warnf("rx'ed MLME message (ordinal: %u) before authenticating with a BSS\n", msg.ordinal());
        return ZX_ERR_BAD_STATE;
    }

    if (auto deauth_req = msg.As<wlan_mlme::DeauthenticateRequest>()) {
        return sta_->Deauthenticate(deauth_req->body()->reason_code);
    } else if (auto assoc_req = msg.As<wlan_mlme::AssociateRequest>()) {
        return sta_->Associate(*assoc_req->body()->rsn);
    } else if (auto eapol_req = msg.As<wlan_mlme::EapolRequest>()) {
        auto body = eapol_req->body();
        return sta_->SendEapolFrame(body->data, common::MacAddr(body->src_addr),
                                    common::MacAddr(body->dst_addr));
    } else if (auto setctrlport_req = msg.As<wlan_mlme::SetControlledPortRequest>()) {
        sta_->UpdateControlledPort(setctrlport_req->body()->state);
        return ZX_OK;
    } else {
        warnf("rx'ed unsupported MLME message for client; ordinal: %u\n", msg.ordinal());
        return ZX_ERR_BAD_STATE;
    }
}

zx_status_t ClientMlme::HandleFramePacket(fbl::unique_ptr<Packet> pkt) {
    switch (pkt->peer()) {
    case Packet::Peer::kEthernet: {
        // For outbound frame (Ethernet frame), hand to station directly so
        // station sends frame to device when on channel, or buffers it when
        // off channel.
        if (sta_ != nullptr) {
            if (auto eth_frame = EthFrameView::CheckType(pkt.get()).CheckLength()) {
                sta_->HandleEthFrame(eth_frame.IntoOwned(std::move(pkt)));
            }
        }
        break;
    }
    case Packet::Peer::kWlan: {
        chan_sched_->HandleIncomingFrame(std::move(pkt));
        break;
    }
    default:
        errorf("unknown Packet peer: %u\n", pkt->peer());
        break;
    }
    return ZX_OK;
}

zx_status_t ClientMlme::HandleMlmeJoinReq(const MlmeMsg<wlan_mlme::JoinRequest>& req) {
    debugfn();

    wlan_mlme::BSSDescription bss;
    auto status = req.body()->selected_bss.Clone(&bss);
    if (status != ZX_OK) {
        errorf("error cloning MLME-JOIN.request: %d\n", status);
        return status;
    }
    JoinContext join_ctx(std::move(bss), req.body()->phy, req.body()->cbw);

    auto join_chan = join_ctx.channel();
    debugjoin("setting channel to %s\n", common::ChanStrLong(join_chan).c_str());
    status = chan_sched_->SetChannel(join_chan);
    if (status != ZX_OK) {
        errorf("could not set WLAN channel to %s: %d\n", common::ChanStrLong(join_chan).c_str(),
               status);
        service::SendJoinConfirm(device_, wlan_mlme::JoinResultCodes::JOIN_FAILURE_TIMEOUT);
        return status;
    }

    // Notify driver about BSS.
    wlan_bss_config_t cfg{
        .bss_type = WLAN_BSS_TYPE_INFRASTRUCTURE,
        .remote = true,
    };
    join_ctx.bssid().CopyTo(cfg.bssid);
    status = device_->ConfigureBss(&cfg);
    if (status != ZX_OK) {
        errorf("error configuring BSS in driver; aborting: %d\n", status);
        // TODO(hahnr): JoinResultCodes needs to define better result codes.
        return service::SendJoinConfirm(device_, wlan_mlme::JoinResultCodes::JOIN_FAILURE_TIMEOUT);
    }

    join_ctx_ = std::move(join_ctx);

    // Send confirmation for successful synchronization to SME.
    return service::SendJoinConfirm(device_, wlan_mlme::JoinResultCodes::SUCCESS);
}

zx_status_t ClientMlme::SpawnStation() {
    if (!join_ctx_.has_value()) { return ZX_ERR_BAD_STATE; }

    auto client = CreateDefaultClient(device_, &join_ctx_.value(), chan_sched_.get());
    if (!client) { return ZX_ERR_INTERNAL; }
    sta_ = std::move(client);
    return ZX_OK;
}

void ClientMlme::OnChannelHandlerImpl::PreSwitchOffChannel() {
    debugfn();
    if (mlme_->sta_ != nullptr) { mlme_->sta_->PreSwitchOffChannel(); }
}

void ClientMlme::OnChannelHandlerImpl::HandleOnChannelFrame(fbl::unique_ptr<Packet> packet) {
    debugfn();
    // Only WLAN frame is handed to channel handler since all Ethernet frames are handed
    // over to station directly.
    ZX_DEBUG_ASSERT(packet->peer() == Packet::Peer::kWlan);

    if (auto mgmt_frame = MgmtFrameView<>::CheckType(packet.get()).CheckLength()) {
        if (auto bcn_frame = mgmt_frame.CheckBodyType<Beacon>().CheckLength()) {
            mlme_->scanner_->HandleBeacon(bcn_frame);
        }
    }

    if (mlme_->sta_ != nullptr) { mlme_->sta_->HandleWlanFrame(std::move(packet)); }
}

void ClientMlme::OnChannelHandlerImpl::ReturnedOnChannel() {
    debugfn();
    if (mlme_->sta_ != nullptr) { mlme_->sta_->BackToMainChannel(); }
}

wlan_stats::MlmeStats ClientMlme::GetMlmeStats() const {
    wlan_stats::MlmeStats mlme_stats{};
    if (sta_ != nullptr) { mlme_stats.set_client_mlme_stats(sta_->stats()); }
    return mlme_stats;
}

void ClientMlme::ResetMlmeStats() {
    if (sta_ != nullptr) { sta_->ResetStats(); }
}

bool ClientMlme::OnChannel() {
    if (chan_sched_ != nullptr) { return chan_sched_->OnChannel(); }
    return false;
}

void ClientMlme::Unjoin() {
    join_ctx_.reset();
    sta_.reset();
}

}  // namespace wlan
