/*
 *  Copyright (c) 2016-2020, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements MLE Discover Scan process.
 */

#include "discover_scanner.hpp"

#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "thread/mesh_forwarder.hpp"
#include "thread/mle.hpp"
#include "thread/mle_router.hpp"

namespace ot {
namespace Mle {

DiscoverScanner::DiscoverScanner(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mHandler(nullptr)
    , mHandlerContext(nullptr)
    , mTimer(aInstance, DiscoverScanner::HandleTimer)
    , mFilterIndexes()
    , mState(kStateIdle)
    , mScanChannel(0)
    , mAdvDataLength(0)
    , mEnableFiltering(false)
    , mShouldRestorePanId(false)
{
}

Error DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
                                uint16_t                aPanId,
                                bool                    aJoiner,
                                bool                    aEnableFiltering,
                                const FilterIndexes *   aFilterIndexes,
                                Handler                 aCallback,
                                void *                  aContext)
{
    Error                           error   = kErrorNone;
    Message *                       message = nullptr;
    Tlv                             tlv;
    Ip6::Address                    destination;
    MeshCoP::DiscoveryRequestTlv    discoveryRequest;
    MeshCoP::JoinerAdvertisementTlv joinerAdvertisement;

    VerifyOrExit(Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);

    VerifyOrExit(mState == kStateIdle, error = kErrorBusy);

    mEnableFiltering = aEnableFiltering;

    if (mEnableFiltering)
    {
        if (aFilterIndexes == nullptr)
        {
            Mac::ExtAddress extAddress;

            Get<Radio>().GetIeeeEui64(extAddress);
            MeshCoP::ComputeJoinerId(extAddress, extAddress);
            MeshCoP::SteeringData::CalculateHashBitIndexes(extAddress, mFilterIndexes);
        }
        else
        {
            mFilterIndexes = *aFilterIndexes;
        }
    }

    mHandler            = aCallback;
    mHandlerContext     = aContext;
    mShouldRestorePanId = false;
    mScanChannels       = Get<Mac::Mac>().GetSupportedChannelMask();

    if (!aScanChannels.IsEmpty())
    {
        mScanChannels.Intersect(aScanChannels);
    }

    VerifyOrExit((message = Get<Mle>().NewMleMessage(Mle::kCommandDiscoveryRequest)) != nullptr, error = kErrorNoBufs);
    message->SetPanId(aPanId);

    // Prepare sub-TLV MeshCoP Discovery Request.
    discoveryRequest.Init();
    discoveryRequest.SetVersion(kThreadVersion);
    discoveryRequest.SetJoiner(aJoiner);

    if (mAdvDataLength != 0)
    {
        // Prepare sub-TLV MeshCoP Joiner Advertisement.
        joinerAdvertisement.Init();
        joinerAdvertisement.SetOui(mOui);
        joinerAdvertisement.SetAdvData(mAdvData, mAdvDataLength);
    }

    // Append Discovery TLV with one or two sub-TLVs.
    tlv.SetType(Tlv::kDiscovery);
    tlv.SetLength(
        static_cast<uint8_t>(discoveryRequest.GetSize() + ((mAdvDataLength != 0) ? joinerAdvertisement.GetSize() : 0)));

    SuccessOrExit(error = message->Append(tlv));
    SuccessOrExit(error = discoveryRequest.AppendTo(*message));

    if (mAdvDataLength != 0)
    {
        SuccessOrExit(error = joinerAdvertisement.AppendTo(*message));
    }

    destination.SetToLinkLocalAllRoutersMulticast();

    SuccessOrExit(error = Get<Mle>().SendMessage(*message, destination));

    if ((aPanId == Mac::kPanIdBroadcast) && (Get<Mac::Mac>().GetPanId() == Mac::kPanIdBroadcast))
    {
        // In case a specific PAN ID of a Thread Network to be
        // discovered is not known, Discovery Request messages MUST
        // have the Destination PAN ID in the IEEE 802.15.4 MAC
        // header set to be the Broadcast PAN ID (0xffff) and the
        // Source PAN ID set to a randomly generated value.

        Get<Mac::Mac>().SetPanId(Mac::GenerateRandomPanId());
        mShouldRestorePanId = true;
    }

    mScanChannel = Mac::ChannelMask::kChannelIteratorFirst;
    mState       = (mScanChannels.GetNextChannel(mScanChannel) == kErrorNone) ? kStateScanning : kStateScanDone;

    Mle::Log(Mle::kMessageSend, Mle::kTypeDiscoveryRequest, destination);

exit:
    FreeMessageOnError(message, error);
    return error;
}

Error DiscoverScanner::SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength)
{
    Error error = kErrorNone;

    VerifyOrExit((aAdvData != nullptr) && (aAdvDataLength != 0) &&
                     (aAdvDataLength <= MeshCoP::JoinerAdvertisementTlv::kAdvDataMaxLength) && (aOui <= kMaxOui),
                 error = kErrorInvalidArgs);

    mOui           = aOui;
    mAdvDataLength = aAdvDataLength;

    memcpy(mAdvData, aAdvData, aAdvDataLength);

exit:
    return error;
}

Mac::TxFrame *DiscoverScanner::PrepareDiscoveryRequestFrame(Mac::TxFrame &aFrame)
{
    Mac::TxFrame *frame = &aFrame;

    switch (mState)
    {
    case kStateIdle:
    case kStateScanDone:
        // If scan is finished (no more channels to scan), abort the
        // Discovery Request frame tx. The handler callback is invoked &
        // state is cleared from `HandleDiscoveryRequestFrameTxDone()`.
        frame = nullptr;
        break;

    case kStateScanning:
        frame->SetChannel(mScanChannel);
        IgnoreError(Get<Mac::Mac>().SetTemporaryChannel(mScanChannel));
        break;
    }

    return frame;
}

void DiscoverScanner::HandleDiscoveryRequestFrameTxDone(Message &aMessage)
{
    switch (mState)
    {
    case kStateIdle:
        break;

    case kStateScanning:
        // Mark the Discovery Request message for direct tx to ensure it
        // is not dequeued and freed by `MeshForwarder` and is ready for
        // the next scan channel. Also pause message tx on `MeshForwarder`
        // while listening to receive Discovery Responses.
        aMessage.SetDirectTransmission();
        Get<MeshForwarder>().PauseMessageTransmissions();
        mTimer.Start(kDefaultScanDuration);
        break;

    case kStateScanDone:
        HandleDiscoverComplete();
        break;
    }
}

void DiscoverScanner::HandleDiscoverComplete(void)
{
    switch (mState)
    {
    case kStateIdle:
        break;

    case kStateScanning:
        mTimer.Stop();
        Get<MeshForwarder>().ResumeMessageTransmissions();

        OT_FALL_THROUGH;

    case kStateScanDone:
        Get<Mac::Mac>().ClearTemporaryChannel();

        if (mShouldRestorePanId)
        {
            Get<Mac::Mac>().SetPanId(Mac::kPanIdBroadcast);
            mShouldRestorePanId = false;
        }

        mState = kStateIdle;

        if (mHandler)
        {
            mHandler(nullptr, mHandlerContext);
        }

        break;
    }
}

void DiscoverScanner::HandleTimer(Timer &aTimer)
{
    aTimer.Get<DiscoverScanner>().HandleTimer();
}

void DiscoverScanner::HandleTimer(void)
{
    VerifyOrExit(mState == kStateScanning);

    // Move to next scan channel and resume message transmissions on
    // `MeshForwarder` so that the queued MLE Discovery Request message
    // is prepared again for the next scan channel. If no more channel
    // to scan, change the state to `kStateScanDone` which ensures the
    // frame tx is aborted  from `PrepareDiscoveryRequestFrame()` and
    // then wraps up the scan (invoking handler callback).

    if (mScanChannels.GetNextChannel(mScanChannel) != kErrorNone)
    {
        mState = kStateScanDone;
    }

    Get<MeshForwarder>().ResumeMessageTransmissions();

exit:
    return;
}

void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
{
    Error                         error    = kErrorNone;
    const ThreadLinkInfo *        linkInfo = aRxInfo.mMessageInfo.GetThreadLinkInfo();
    Tlv                           tlv;
    MeshCoP::Tlv                  meshcopTlv;
    MeshCoP::DiscoveryResponseTlv discoveryResponse;
    MeshCoP::NetworkNameTlv       networkName;
    ScanResult                    result;
    uint16_t                      offset;
    uint16_t                      end;
    bool                          didCheckSteeringData = false;

    Mle::Log(Mle::kMessageReceive, Mle::kTypeDiscoveryResponse, aRxInfo.mMessageInfo.GetPeerAddr());

    VerifyOrExit(mState == kStateScanning, error = kErrorDrop);

    // Find MLE Discovery TLV
    VerifyOrExit(Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kDiscovery, offset) == kErrorNone, error = kErrorParse);
    IgnoreError(aRxInfo.mMessage.Read(offset, tlv));

    offset += sizeof(tlv);
    end = offset + tlv.GetLength();

    memset(&result, 0, sizeof(result));
    result.mDiscover = true;
    result.mPanId    = linkInfo->mPanId;
    result.mChannel  = linkInfo->mChannel;
    result.mRssi     = linkInfo->mRss;
    result.mLqi      = linkInfo->mLqi;

    aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(AsCoreType(&result.mExtAddress));

    // Process MeshCoP TLVs
    while (offset < end)
    {
        IgnoreError(aRxInfo.mMessage.Read(offset, meshcopTlv));

        switch (meshcopTlv.GetType())
        {
        case MeshCoP::Tlv::kDiscoveryResponse:
            IgnoreError(aRxInfo.mMessage.Read(offset, discoveryResponse));
            VerifyOrExit(discoveryResponse.IsValid(), error = kErrorParse);
            result.mVersion  = discoveryResponse.GetVersion();
            result.mIsNative = discoveryResponse.IsNativeCommissioner();
            break;

        case MeshCoP::Tlv::kExtendedPanId:
            SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offset,
                                                                       AsCoreType(&result.mExtendedPanId)));
            break;

        case MeshCoP::Tlv::kNetworkName:
            IgnoreError(aRxInfo.mMessage.Read(offset, networkName));
            if (networkName.IsValid())
            {
                IgnoreError(AsCoreType(&result.mNetworkName).Set(networkName.GetNetworkName()));
            }
            break;

        case MeshCoP::Tlv::kSteeringData:
            if (meshcopTlv.GetLength() > 0)
            {
                MeshCoP::SteeringData &steeringData = AsCoreType(&result.mSteeringData);
                uint8_t                dataLength   = MeshCoP::SteeringData::kMaxLength;

                if (meshcopTlv.GetLength() < dataLength)
                {
                    dataLength = meshcopTlv.GetLength();
                }

                steeringData.Init(dataLength);

                SuccessOrExit(error = Tlv::ReadTlv(aRxInfo.mMessage, offset, steeringData.GetData(), dataLength));

                if (mEnableFiltering)
                {
                    VerifyOrExit(steeringData.Contains(mFilterIndexes));
                }

                didCheckSteeringData = true;
            }
            break;

        case MeshCoP::Tlv::kJoinerUdpPort:
            SuccessOrExit(error =
                              Tlv::Read<MeshCoP::JoinerUdpPortTlv>(aRxInfo.mMessage, offset, result.mJoinerUdpPort));
            break;

        default:
            break;
        }

        offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
    }

    VerifyOrExit(!mEnableFiltering || didCheckSteeringData);

    if (mHandler)
    {
        mHandler(&result, mHandlerContext);
    }

exit:
    Mle::LogProcessError(Mle::kTypeDiscoveryResponse, error);
}

} // namespace Mle
} // namespace ot
