/*
 *  Copyright (c) 2016-2017, 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 includes definitions for maintaining Thread network topologies.
 */

#include "topology.hpp"

#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"

namespace ot {

bool Neighbor::AddressMatcher::Matches(const Neighbor &aNeighbor) const
{
    bool matches = false;

    VerifyOrExit(aNeighbor.MatchesFilter(mStateFilter));

    if (mShortAddress != Mac::kShortAddrInvalid)
    {
        VerifyOrExit(mShortAddress == aNeighbor.GetRloc16());
    }

    if (mExtAddress != nullptr)
    {
        VerifyOrExit(*mExtAddress == aNeighbor.GetExtAddress());
    }

    matches = true;

exit:
    return matches;
}

void Neighbor::Info::SetFrom(const Neighbor &aNeighbor)
{
    Clear();

    mExtAddress       = aNeighbor.GetExtAddress();
    mAge              = Time::MsecToSec(TimerMilli::GetNow() - aNeighbor.GetLastHeard());
    mRloc16           = aNeighbor.GetRloc16();
    mLinkFrameCounter = aNeighbor.GetLinkFrameCounters().GetMaximum();
    mMleFrameCounter  = aNeighbor.GetMleFrameCounter();
    mLinkQualityIn    = aNeighbor.GetLinkInfo().GetLinkQuality();
    mAverageRssi      = aNeighbor.GetLinkInfo().GetAverageRss();
    mLastRssi         = aNeighbor.GetLinkInfo().GetLastRss();
    mFrameErrorRate   = aNeighbor.GetLinkInfo().GetFrameErrorRate();
    mMessageErrorRate = aNeighbor.GetLinkInfo().GetMessageErrorRate();
    mRxOnWhenIdle     = aNeighbor.IsRxOnWhenIdle();
    mFullThreadDevice = aNeighbor.IsFullThreadDevice();
    mFullNetworkData  = (aNeighbor.GetNetworkDataType() == NetworkData::kFullSet);
}

void Neighbor::Init(Instance &aInstance)
{
    InstanceLocatorInit::Init(aInstance);
    mLinkInfo.Init(aInstance);
    SetState(kStateInvalid);
}

bool Neighbor::IsStateValidOrAttaching(void) const
{
    bool rval = false;

    switch (GetState())
    {
    case kStateInvalid:
    case kStateParentRequest:
    case kStateParentResponse:
        break;

    case kStateRestored:
    case kStateChildIdRequest:
    case kStateLinkRequest:
    case kStateChildUpdateRequest:
    case kStateValid:
        rval = true;
        break;
    }

    return rval;
}

bool Neighbor::MatchesFilter(StateFilter aFilter) const
{
    bool matches = false;

    switch (aFilter)
    {
    case kInStateValid:
        matches = IsStateValid();
        break;

    case kInStateValidOrRestoring:
        matches = IsStateValidOrRestoring();
        break;

    case kInStateChildIdRequest:
        matches = IsStateChildIdRequest();
        break;

    case kInStateValidOrAttaching:
        matches = IsStateValidOrAttaching();
        break;

    case kInStateInvalid:
        matches = IsStateInvalid();
        break;

    case kInStateAnyExceptInvalid:
        matches = !IsStateInvalid();
        break;

    case kInStateAnyExceptValidOrRestoring:
        matches = !IsStateValidOrRestoring();
        break;

    case kInStateAny:
        matches = true;
        break;
    }

    return matches;
}

#if OPENTHREAD_CONFIG_MULTI_RADIO
void Neighbor::SetLastRxFragmentTag(uint16_t aTag)
{
    mLastRxFragmentTag     = (aTag == 0) ? 0xffff : aTag;
    mLastRxFragmentTagTime = TimerMilli::GetNow();
}

bool Neighbor::IsLastRxFragmentTagSet(void) const
{
    return (mLastRxFragmentTag != 0) && (TimerMilli::GetNow() <= mLastRxFragmentTagTime + kLastRxFragmentTagTimeout);
}
#endif

void Neighbor::GenerateChallenge(void)
{
    IgnoreError(
        Random::Crypto::FillBuffer(mValidPending.mPending.mChallenge, sizeof(mValidPending.mPending.mChallenge)));
}

#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
void Neighbor::AggregateLinkMetrics(uint8_t aSeriesId, uint8_t aFrameType, uint8_t aLqi, int8_t aRss)
{
    for (LinkMetrics::SeriesInfo &entry : mLinkMetricsSeriesInfoList)
    {
        if (aSeriesId == 0 || aSeriesId == entry.GetSeriesId())
        {
            entry.AggregateLinkMetrics(aFrameType, aLqi, aRss);
        }
    }
}

LinkMetrics::SeriesInfo *Neighbor::GetForwardTrackingSeriesInfo(const uint8_t &aSeriesId)
{
    return mLinkMetricsSeriesInfoList.FindMatching(aSeriesId);
}

void Neighbor::AddForwardTrackingSeriesInfo(LinkMetrics::SeriesInfo &aSeriesInfo)
{
    mLinkMetricsSeriesInfoList.Push(aSeriesInfo);
}

LinkMetrics::SeriesInfo *Neighbor::RemoveForwardTrackingSeriesInfo(const uint8_t &aSeriesId)
{
    return mLinkMetricsSeriesInfoList.RemoveMatching(aSeriesId);
}

void Neighbor::RemoveAllForwardTrackingSeriesInfo(void)
{
    while (!mLinkMetricsSeriesInfoList.IsEmpty())
    {
        LinkMetrics::SeriesInfo *seriesInfo = mLinkMetricsSeriesInfoList.Pop();
        Get<LinkMetrics::LinkMetrics>().mSeriesInfoPool.Free(*seriesInfo);
    }
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE

const char *Neighbor::StateToString(State aState)
{
    static const char *const kStateStrings[] = {
        "Invalid",        // (0) kStateInvalid
        "Restored",       // (1) kStateRestored
        "ParentReq",      // (2) kStateParentRequest
        "ParentRes",      // (3) kStateParentResponse
        "ChildIdReq",     // (4) kStateChildIdRequest
        "LinkReq",        // (5) kStateLinkRequest
        "ChildUpdateReq", // (6) kStateChildUpdateRequest
        "Valid",          // (7) kStateValid
    };

    static_assert(0 == kStateInvalid, "kStateInvalid value is incorrect");
    static_assert(1 == kStateRestored, "kStateRestored value is incorrect");
    static_assert(2 == kStateParentRequest, "kStateParentRequest value is incorrect");
    static_assert(3 == kStateParentResponse, "kStateParentResponse value is incorrect");
    static_assert(4 == kStateChildIdRequest, "kStateChildIdRequest value is incorrect");
    static_assert(5 == kStateLinkRequest, "kStateLinkRequest value is incorrect");
    static_assert(6 == kStateChildUpdateRequest, "kStateChildUpdateRequest value is incorrect");
    static_assert(7 == kStateValid, "kStateValid value is incorrect");

    return kStateStrings[aState];
}

#if OPENTHREAD_FTD

void Child::Info::SetFrom(const Child &aChild)
{
    Clear();
    mExtAddress         = aChild.GetExtAddress();
    mTimeout            = aChild.GetTimeout();
    mRloc16             = aChild.GetRloc16();
    mChildId            = Mle::Mle::ChildIdFromRloc16(aChild.GetRloc16());
    mNetworkDataVersion = aChild.GetNetworkDataVersion();
    mAge                = Time::MsecToSec(TimerMilli::GetNow() - aChild.GetLastHeard());
    mLinkQualityIn      = aChild.GetLinkInfo().GetLinkQuality();
    mAverageRssi        = aChild.GetLinkInfo().GetAverageRss();
    mLastRssi           = aChild.GetLinkInfo().GetLastRss();
    mFrameErrorRate     = aChild.GetLinkInfo().GetFrameErrorRate();
    mMessageErrorRate   = aChild.GetLinkInfo().GetMessageErrorRate();
    mQueuedMessageCnt   = aChild.GetIndirectMessageCount();
    mVersion            = aChild.GetVersion();
    mRxOnWhenIdle       = aChild.IsRxOnWhenIdle();
    mFullThreadDevice   = aChild.IsFullThreadDevice();
    mFullNetworkData    = (aChild.GetNetworkDataType() == NetworkData::kFullSet);
    mIsStateRestoring   = aChild.IsStateRestoring();
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
    mIsCslSynced = aChild.IsCslSynchronized();
#else
    mIsCslSynced = false;
#endif
}

const Ip6::Address *Child::AddressIterator::GetAddress(void) const
{
    // `mIndex` value of zero indicates mesh-local IPv6 address.
    // Non-zero value specifies the index into address array starting
    // from one for first element (i.e, `mIndex - 1` gives the array
    // index).

    return (mIndex == 0) ? &mMeshLocalAddress : ((mIndex < kMaxIndex) ? &mChild.mIp6Address[mIndex - 1] : nullptr);
}

void Child::AddressIterator::Update(void)
{
    const Ip6::Address *address;

    if ((mIndex == 0) && (mChild.GetMeshLocalIp6Address(mMeshLocalAddress) != kErrorNone))
    {
        mIndex++;
    }

    while (true)
    {
        address = GetAddress();

        VerifyOrExit((address != nullptr) && !address->IsUnspecified(), mIndex = kMaxIndex);

        VerifyOrExit(!address->MatchesFilter(mFilter));
        mIndex++;
    }

exit:
    return;
}

void Child::Clear(void)
{
    Instance &instance = GetInstance();

    memset(reinterpret_cast<void *>(this), 0, sizeof(Child));
    Init(instance);
}

void Child::ClearIp6Addresses(void)
{
    mMeshLocalIid.Clear();
    memset(mIp6Address, 0, sizeof(mIp6Address));
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
    mMlrToRegisterMask.Clear();
    mMlrRegisteredMask.Clear();
#endif
}

void Child::SetDeviceMode(Mle::DeviceMode aMode)
{
    VerifyOrExit(aMode != GetDeviceMode());

    Neighbor::SetDeviceMode(aMode);

    VerifyOrExit(IsStateValid());
    Get<NeighborTable>().Signal(NeighborTable::kChildModeChanged, *this);

exit:
    return;
}

Error Child::GetMeshLocalIp6Address(Ip6::Address &aAddress) const
{
    Error error = kErrorNone;

    VerifyOrExit(!mMeshLocalIid.IsUnspecified(), error = kErrorNotFound);

    aAddress.SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
    aAddress.SetIid(mMeshLocalIid);

exit:
    return error;
}

Error Child::AddIp6Address(const Ip6::Address &aAddress)
{
    Error error = kErrorNone;

    VerifyOrExit(!aAddress.IsUnspecified(), error = kErrorInvalidArgs);

    if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
    {
        VerifyOrExit(mMeshLocalIid.IsUnspecified(), error = kErrorAlready);
        mMeshLocalIid = aAddress.GetIid();
        ExitNow();
    }

    for (Ip6::Address &ip6Address : mIp6Address)
    {
        if (ip6Address.IsUnspecified())
        {
            ip6Address = aAddress;
            ExitNow();
        }

        VerifyOrExit(ip6Address != aAddress, error = kErrorAlready);
    }

    error = kErrorNoBufs;

exit:
    return error;
}

Error Child::RemoveIp6Address(const Ip6::Address &aAddress)
{
    Error    error = kErrorNotFound;
    uint16_t index;

    VerifyOrExit(!aAddress.IsUnspecified(), error = kErrorInvalidArgs);

    if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
    {
        if (aAddress.GetIid() == mMeshLocalIid)
        {
            mMeshLocalIid.Clear();
            error = kErrorNone;
        }

        ExitNow();
    }

    for (index = 0; index < kNumIp6Addresses; index++)
    {
        VerifyOrExit(!mIp6Address[index].IsUnspecified());

        if (mIp6Address[index] == aAddress)
        {
            error = kErrorNone;
            break;
        }
    }

    SuccessOrExit(error);

    for (; index < kNumIp6Addresses - 1; index++)
    {
        mIp6Address[index] = mIp6Address[index + 1];
    }

    mIp6Address[kNumIp6Addresses - 1].Clear();

exit:
    return error;
}

bool Child::HasIp6Address(const Ip6::Address &aAddress) const
{
    bool retval = false;

    VerifyOrExit(!aAddress.IsUnspecified());

    if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
    {
        retval = (aAddress.GetIid() == mMeshLocalIid);
        ExitNow();
    }

    for (const Ip6::Address &ip6Address : mIp6Address)
    {
        VerifyOrExit(!ip6Address.IsUnspecified());

        if (ip6Address == aAddress)
        {
            ExitNow(retval = true);
        }
    }

exit:
    return retval;
}

#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
const Ip6::Address *Child::GetDomainUnicastAddress(void) const
{
    const Ip6::Address *addr = nullptr;

    for (const Ip6::Address &ip6Address : mIp6Address)
    {
        VerifyOrExit(!ip6Address.IsUnspecified());

        if (Get<BackboneRouter::Leader>().IsDomainUnicast(ip6Address))
        {
            ExitNow(addr = &ip6Address);
        }
    }

exit:
    return addr;
}
#endif

void Child::GenerateChallenge(void)
{
    IgnoreError(Random::Crypto::FillBuffer(mAttachChallenge, sizeof(mAttachChallenge)));
}

#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
bool Child::HasMlrRegisteredAddress(const Ip6::Address &aAddress) const
{
    bool has = false;

    VerifyOrExit(mMlrRegisteredMask.HasAny());

    for (const Ip6::Address &address : IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
    {
        if (GetAddressMlrState(address) == kMlrStateRegistered && address == aAddress)
        {
            ExitNow(has = true);
        }
    }

exit:
    return has;
}

MlrState Child::GetAddressMlrState(const Ip6::Address &aAddress) const
{
    uint16_t addressIndex;

    OT_ASSERT(&mIp6Address[0] <= &aAddress && &aAddress < GetArrayEnd(mIp6Address));

    addressIndex = static_cast<uint16_t>(&aAddress - mIp6Address);

    return mMlrToRegisterMask.Get(addressIndex)
               ? kMlrStateToRegister
               : (mMlrRegisteredMask.Get(addressIndex) ? kMlrStateRegistered : kMlrStateRegistering);
}

void Child::SetAddressMlrState(const Ip6::Address &aAddress, MlrState aState)
{
    uint16_t addressIndex;

    OT_ASSERT(&mIp6Address[0] <= &aAddress && &aAddress < GetArrayEnd(mIp6Address));

    addressIndex = static_cast<uint16_t>(&aAddress - mIp6Address);

    mMlrToRegisterMask.Set(addressIndex, aState == kMlrStateToRegister);
    mMlrRegisteredMask.Set(addressIndex, aState == kMlrStateRegistered);
}
#endif // OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE

#endif // OPENTHREAD_FTD

void Router::Info::SetFrom(const Router &aRouter)
{
    Clear();
    mRloc16          = aRouter.GetRloc16();
    mRouterId        = Mle::Mle::RouterIdFromRloc16(mRloc16);
    mExtAddress      = aRouter.GetExtAddress();
    mAllocated       = true;
    mNextHop         = aRouter.GetNextHop();
    mLinkEstablished = aRouter.IsStateValid();
    mPathCost        = aRouter.GetCost();
    mLinkQualityIn   = aRouter.GetLinkInfo().GetLinkQuality();
    mLinkQualityOut  = aRouter.GetLinkQualityOut();
    mAge             = static_cast<uint8_t>(Time::MsecToSec(TimerMilli::GetNow() - aRouter.GetLastHeard()));
}

void Router::Clear(void)
{
    Instance &instance = GetInstance();

    memset(reinterpret_cast<void *>(this), 0, sizeof(Router));
    Init(instance);
}

} // namespace ot
