/*
 *  Copyright (c) 2016, 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 the Thread Network Data managed by the Thread Leader.
 */

#if OPENTHREAD_FTD

#include "network_data_leader.hpp"

#include "coap/coap_message.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
#include "common/logging.hpp"
#include "common/message.hpp"
#include "common/timer.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/meshcop.hpp"
#include "thread/lowpan.hpp"
#include "thread/mle_router.hpp"
#include "thread/thread_netif.hpp"
#include "thread/thread_tlvs.hpp"
#include "thread/thread_uri_paths.hpp"

using ot::Encoding::BigEndian::HostSwap16;

namespace ot {
namespace NetworkData {

Leader::Leader(Instance &aInstance)
    : LeaderBase(aInstance)
    , mTimer(aInstance, &Leader::HandleTimer, this)
    , mServerData(OT_URI_PATH_SERVER_DATA, &Leader::HandleServerData, this)
    , mCommissioningDataGet(OT_URI_PATH_COMMISSIONER_GET, &Leader::HandleCommissioningGet, this)
    , mCommissioningDataSet(OT_URI_PATH_COMMISSIONER_SET, &Leader::HandleCommissioningSet, this)
{
    Reset();
}

void Leader::Reset(void)
{
    LeaderBase::Reset();

    memset(mContextLastUsed, 0, sizeof(mContextLastUsed));
    mContextUsed         = 0;
    mContextIdReuseDelay = kContextIdReuseDelay;
}

void Leader::Start(void)
{
    Get<Coap::Coap>().AddResource(mServerData);
    Get<Coap::Coap>().AddResource(mCommissioningDataGet);
    Get<Coap::Coap>().AddResource(mCommissioningDataSet);
}

void Leader::Stop(void)
{
    Get<Coap::Coap>().RemoveResource(mServerData);
    Get<Coap::Coap>().RemoveResource(mCommissioningDataGet);
    Get<Coap::Coap>().RemoveResource(mCommissioningDataSet);
}

void Leader::IncrementVersion(void)
{
    if (Get<Mle::MleRouter>().GetRole() == OT_DEVICE_ROLE_LEADER)
    {
        mVersion++;
        Get<Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);
    }
}

void Leader::IncrementStableVersion(void)
{
    if (Get<Mle::MleRouter>().GetRole() == OT_DEVICE_ROLE_LEADER)
    {
        mStableVersion++;
    }
}

uint32_t Leader::GetContextIdReuseDelay(void) const
{
    return mContextIdReuseDelay;
}

void Leader::SetContextIdReuseDelay(uint32_t aDelay)
{
    mContextIdReuseDelay = aDelay;
}

void Leader::RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode)
{
    bool rlocIn     = false;
    bool rlocStable = false;

    RlocLookup(aRloc16, rlocIn, rlocStable, mTlvs, mLength, aMatchMode);
    VerifyOrExit(rlocIn);
    RemoveRloc(aRloc16, aMatchMode);

    mVersion++;

    if (rlocStable)
    {
        mStableVersion++;
    }

    Get<Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);

exit:
    return;
}

void Leader::HandleServerData(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
    static_cast<Leader *>(aContext)->HandleServerData(*static_cast<Coap::Message *>(aMessage),
                                                      *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

void Leader::HandleServerData(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    ThreadNetworkDataTlv networkData;
    ThreadRloc16Tlv      rloc16;

    otLogInfoNetData("Received network data registration");

    if (ThreadTlv::GetTlv(aMessage, ThreadTlv::kRloc16, sizeof(rloc16), rloc16) == OT_ERROR_NONE)
    {
        VerifyOrExit(rloc16.IsValid());
        RemoveBorderRouter(rloc16.GetRloc16(), kMatchModeRloc16);
    }

    if (ThreadTlv::GetTlv(aMessage, ThreadTlv::kThreadNetworkData, sizeof(networkData), networkData) == OT_ERROR_NONE)
    {
        VerifyOrExit(networkData.IsValid());
        RegisterNetworkData(HostSwap16(aMessageInfo.mPeerAddr.mFields.m16[7]), networkData.GetTlvs(),
                            networkData.GetLength());
    }

    SuccessOrExit(Get<Coap::Coap>().SendEmptyAck(aMessage, aMessageInfo));

    otLogInfoNetData("Sent network data registration acknowledgment");

exit:
    return;
}

void Leader::HandleCommissioningSet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
    static_cast<Leader *>(aContext)->HandleCommissioningSet(*static_cast<Coap::Message *>(aMessage),
                                                            *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

void Leader::HandleCommissioningSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    uint16_t                 offset = aMessage.GetOffset();
    uint16_t                 length = aMessage.GetLength() - aMessage.GetOffset();
    uint8_t                  tlvs[NetworkData::kMaxSize];
    MeshCoP::StateTlv::State state        = MeshCoP::StateTlv::kReject;
    bool                     hasSessionId = false;
    bool                     hasValidTlv  = false;
    uint16_t                 sessionId    = 0;

    MeshCoP::Tlv *cur;
    MeshCoP::Tlv *end;

    VerifyOrExit(length <= sizeof(tlvs));
    VerifyOrExit(Get<Mle::MleRouter>().GetRole() == OT_DEVICE_ROLE_LEADER);

    aMessage.Read(offset, length, tlvs);

    // Session Id and Border Router Locator MUST NOT be set, but accept including unexpected or
    // unknown TLV as long as there is at least one valid TLV.
    cur = reinterpret_cast<MeshCoP::Tlv *>(tlvs);
    end = reinterpret_cast<MeshCoP::Tlv *>(tlvs + length);

    while (cur < end)
    {
        MeshCoP::Tlv::Type type;

        VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end);

        type = cur->GetType();

        if (type == MeshCoP::Tlv::kJoinerUdpPort || type == MeshCoP::Tlv::kSteeringData)
        {
            hasValidTlv = true;
        }
        else if (type == MeshCoP::Tlv::kBorderAgentLocator)
        {
            ExitNow();
        }
        else if (type == MeshCoP::Tlv::kCommissionerSessionId)
        {
            MeshCoP::CommissionerSessionIdTlv *tlv = static_cast<MeshCoP::CommissionerSessionIdTlv *>(cur);

            VerifyOrExit(tlv->IsValid());
            sessionId    = tlv->GetCommissionerSessionId();
            hasSessionId = true;
        }
        else
        {
            // do nothing for unexpected or unknown TLV
        }

        cur = cur->GetNext();
    }

    // verify whether or not commissioner session id TLV is included
    VerifyOrExit(hasSessionId);

    // verify whether or not MGMT_COMM_SET.req includes at least one valid TLV
    VerifyOrExit(hasValidTlv);

    // Find Commissioning Data TLV
    for (NetworkDataTlv *netDataTlv = reinterpret_cast<NetworkDataTlv *>(mTlvs);
         netDataTlv < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); netDataTlv = netDataTlv->GetNext())
    {
        if (netDataTlv->GetType() == NetworkDataTlv::kTypeCommissioningData)
        {
            // Iterate over MeshCoP TLVs and extract desired data
            for (cur = reinterpret_cast<MeshCoP::Tlv *>(netDataTlv->GetValue());
                 cur < reinterpret_cast<MeshCoP::Tlv *>(netDataTlv->GetValue() + netDataTlv->GetLength());
                 cur = cur->GetNext())
            {
                if (cur->GetType() == MeshCoP::Tlv::kCommissionerSessionId)
                {
                    VerifyOrExit(sessionId ==
                                 static_cast<MeshCoP::CommissionerSessionIdTlv *>(cur)->GetCommissionerSessionId());
                }
                else if (cur->GetType() == MeshCoP::Tlv::kBorderAgentLocator)
                {
                    VerifyOrExit(length + cur->GetSize() <= sizeof(tlvs));
                    memcpy(tlvs + length, reinterpret_cast<uint8_t *>(cur), cur->GetSize());
                    length += cur->GetSize();
                }
            }
        }
    }

    SetCommissioningData(tlvs, static_cast<uint8_t>(length));

    state = MeshCoP::StateTlv::kAccept;

exit:

    if (Get<Mle::MleRouter>().GetRole() == OT_DEVICE_ROLE_LEADER)
    {
        SendCommissioningSetResponse(aMessage, aMessageInfo, state);
    }
}

void Leader::HandleCommissioningGet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
    static_cast<Leader *>(aContext)->HandleCommissioningGet(*static_cast<Coap::Message *>(aMessage),
                                                            *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}

void Leader::HandleCommissioningGet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    uint16_t length = 0;
    uint16_t offset;

    SuccessOrExit(Tlv::GetValueOffset(aMessage, MeshCoP::Tlv::kGet, offset, length));
    aMessage.SetOffset(offset);

exit:
    SendCommissioningGetResponse(aMessage, length, aMessageInfo);
}

void Leader::SendCommissioningGetResponse(const Coap::Message &   aRequest,
                                          uint16_t                aLength,
                                          const Ip6::MessageInfo &aMessageInfo)
{
    otError        error = OT_ERROR_NONE;
    Coap::Message *message;
    uint8_t        index;
    uint8_t *      data   = NULL;
    uint8_t        length = 0;

    VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Coap::Coap>())) != NULL, error = OT_ERROR_NO_BUFS);

    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
    SuccessOrExit(error = message->SetPayloadMarker());

    for (NetworkDataTlv *cur                                            = reinterpret_cast<NetworkDataTlv *>(mTlvs);
         cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
    {
        if (cur->GetType() == NetworkDataTlv::kTypeCommissioningData)
        {
            data   = cur->GetValue();
            length = cur->GetLength();
            break;
        }
    }

    VerifyOrExit(data && length, error = OT_ERROR_DROP);

    if (aLength == 0)
    {
        SuccessOrExit(error = message->Append(data, length));
    }
    else
    {
        for (index = 0; index < aLength; index++)
        {
            uint8_t type;

            aRequest.Read(aRequest.GetOffset() + index, sizeof(type), &type);

            for (MeshCoP::Tlv *cur                                          = reinterpret_cast<MeshCoP::Tlv *>(data);
                 cur < reinterpret_cast<MeshCoP::Tlv *>(data + length); cur = cur->GetNext())
            {
                if (cur->GetType() == type)
                {
                    SuccessOrExit(error = cur->AppendTo(*message));
                    break;
                }
            }
        }
    }

    if (message->GetLength() == message->GetOffset())
    {
        // no payload, remove coap payload marker
        message->SetLength(message->GetLength() - 1);
    }

    SuccessOrExit(error = Get<Coap::Coap>().SendMessage(*message, aMessageInfo));

    otLogInfoMeshCoP("sent commissioning dataset get response");

exit:

    if (error != OT_ERROR_NONE && message != NULL)
    {
        message->Free();
    }
}

void Leader::SendCommissioningSetResponse(const Coap::Message &    aRequest,
                                          const Ip6::MessageInfo & aMessageInfo,
                                          MeshCoP::StateTlv::State aState)
{
    otError           error = OT_ERROR_NONE;
    Coap::Message *   message;
    MeshCoP::StateTlv state;

    VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Coap::Coap>())) != NULL, error = OT_ERROR_NO_BUFS);

    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
    SuccessOrExit(error = message->SetPayloadMarker());

    state.Init();
    state.SetState(aState);
    SuccessOrExit(error = state.AppendTo(*message));

    SuccessOrExit(error = Get<Coap::Coap>().SendMessage(*message, aMessageInfo));

    otLogInfoMeshCoP("sent commissioning dataset set response");

exit:

    if (error != OT_ERROR_NONE && message != NULL)
    {
        message->Free();
    }
}

bool Leader::RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode)
{
    bool matched = false;

    switch (aMatchMode)
    {
    case kMatchModeRloc16:
        matched = (aFirstRloc16 == aSecondRloc16);
        break;

    case kMatchModeRouterId:
        matched = Mle::Mle::RouterIdMatch(aFirstRloc16, aSecondRloc16);
        break;
    }

    return matched;
}

otError Leader::RlocLookup(uint16_t  aRloc16,
                           bool &    aIn,
                           bool &    aStable,
                           uint8_t * aTlvs,
                           uint8_t   aTlvsLength,
                           MatchMode aMatchMode,
                           bool      aAllowOtherEntries)
{
    otError            error = OT_ERROR_NONE;
    NetworkDataTlv *   cur   = reinterpret_cast<NetworkDataTlv *>(aTlvs);
    NetworkDataTlv *   end   = reinterpret_cast<NetworkDataTlv *>(aTlvs + aTlvsLength);
    NetworkDataTlv *   subCur;
    NetworkDataTlv *   subEnd;
    PrefixTlv *        prefix;
    BorderRouterTlv *  borderRouter;
    HasRouteTlv *      hasRoute;
    BorderRouterEntry *borderRouterEntry;
    HasRouteEntry *    hasRouteEntry;
    ServiceTlv *       service;
    ServerTlv *        server;

    while (cur < end)
    {
        VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end, error = OT_ERROR_PARSE);

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypePrefix:
        {
            prefix = static_cast<PrefixTlv *>(cur);
            VerifyOrExit(prefix->IsValid(), error = OT_ERROR_PARSE);

            subCur = prefix->GetSubTlvs();
            subEnd = prefix->GetNext();

            VerifyOrExit(subEnd <= end, error = OT_ERROR_PARSE);

            while (subCur < subEnd)
            {
                VerifyOrExit((subCur + 1) <= subEnd && subCur->GetNext() <= subEnd, error = OT_ERROR_PARSE);

                switch (subCur->GetType())
                {
                case NetworkDataTlv::kTypeBorderRouter:
                    borderRouter = static_cast<BorderRouterTlv *>(subCur);

                    for (uint8_t i = 0; i < borderRouter->GetNumEntries(); i++)
                    {
                        borderRouterEntry = borderRouter->GetEntry(i);

                        if (RlocMatch(borderRouterEntry->GetRloc(), aRloc16, aMatchMode))
                        {
                            aIn = true;

                            if (borderRouter->IsStable())
                            {
                                aStable = true;
                            }
                        }
                        else
                        {
                            VerifyOrExit(aAllowOtherEntries, error = OT_ERROR_FAILED);
                        }
                    }

                    break;

                case NetworkDataTlv::kTypeHasRoute:
                    hasRoute = static_cast<HasRouteTlv *>(subCur);

                    for (uint8_t i = 0; i < hasRoute->GetNumEntries(); i++)
                    {
                        hasRouteEntry = hasRoute->GetEntry(i);

                        if (RlocMatch(hasRouteEntry->GetRloc(), aRloc16, aMatchMode))
                        {
                            aIn = true;

                            if (hasRoute->IsStable())
                            {
                                aStable = true;
                            }
                        }
                        else
                        {
                            VerifyOrExit(aAllowOtherEntries, error = OT_ERROR_FAILED);
                        }
                    }

                    break;

                default:
                    break;
                }

                if (aIn && aStable && aAllowOtherEntries)
                {
                    ExitNow();
                }

                subCur = subCur->GetNext();
            }
        }
        break;

        case NetworkDataTlv::kTypeService:
        {
            service = static_cast<ServiceTlv *>(cur);
            VerifyOrExit(service->IsValid(), error = OT_ERROR_PARSE);

            subCur = service->GetSubTlvs();
            subEnd = service->GetNext();

            VerifyOrExit(subEnd <= end, error = OT_ERROR_PARSE);

            while (subCur < subEnd)
            {
                VerifyOrExit((subCur + 1) <= subEnd && subCur->GetNext() <= subEnd, error = OT_ERROR_PARSE);

                switch (subCur->GetType())
                {
                case NetworkDataTlv::kTypeServer:
                    server = static_cast<ServerTlv *>(subCur);
                    VerifyOrExit(server->IsValid(), error = OT_ERROR_PARSE);

                    if (RlocMatch(server->GetServer16(), aRloc16, aMatchMode))
                    {
                        aIn = true;

                        if (server->IsStable())
                        {
                            aStable = true;
                        }
                    }
                    else
                    {
                        VerifyOrExit(aAllowOtherEntries, error = OT_ERROR_FAILED);
                    }

                    break;

                default:
                    break;
                }

                if (aIn && aStable && aAllowOtherEntries)
                {
                    ExitNow();
                }

                subCur = subCur->GetNext();
            }

            break;
        }

        default:
            break;
        }

        cur = cur->GetNext();
    }

exit:
    return error;
}

bool Leader::IsStableUpdated(uint8_t *aTlvs, uint8_t aTlvsLength, uint8_t *aTlvsBase, uint8_t aTlvsBaseLength)
{
    bool            rval = false;
    NetworkDataTlv *cur  = reinterpret_cast<NetworkDataTlv *>(aTlvs);
    NetworkDataTlv *end  = reinterpret_cast<NetworkDataTlv *>(aTlvs + aTlvsLength);
    ServiceTlv *    service;

    while (cur < end)
    {
        VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end);

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypePrefix:
        {
            PrefixTlv *      prefix       = static_cast<PrefixTlv *>(cur);
            ContextTlv *     context      = FindContext(*prefix);
            BorderRouterTlv *borderRouter = FindBorderRouter(*prefix, true);
            HasRouteTlv *    hasRoute     = FindHasRoute(*prefix, true);

            if (cur->IsStable() && (!context || borderRouter))
            {
                PrefixTlv *prefixBase =
                    FindPrefix(prefix->GetPrefix(), prefix->GetPrefixLength(), aTlvsBase, aTlvsBaseLength);

                if (!prefixBase)
                {
                    ExitNow(rval = true);
                }

                if (borderRouter)
                {
                    BorderRouterTlv *borderRouterBase = FindBorderRouter(*prefixBase, true);

                    if (!borderRouterBase || (borderRouter->GetLength() != borderRouterBase->GetLength()) ||
                        (memcmp(borderRouter, borderRouterBase, borderRouter->GetLength()) != 0))
                    {
                        ExitNow(rval = true);
                    }
                }

                if (hasRoute)
                {
                    HasRouteTlv *hasRouteBase = FindHasRoute(*prefixBase, true);

                    if (!hasRouteBase || (hasRoute->GetLength() != hasRouteBase->GetLength()) ||
                        (memcmp(hasRoute, hasRouteBase, hasRoute->GetLength()) != 0))
                    {
                        ExitNow(rval = true);
                    }
                }
            }

            break;
        }

        case NetworkDataTlv::kTypeService:
            service = static_cast<ServiceTlv *>(cur);

            if (cur->IsStable())
            {
                NetworkDataTlv *curInner;
                NetworkDataTlv *endInner;

                ServiceTlv *serviceBase = FindService(service->GetEnterpriseNumber(), service->GetServiceData(),
                                                      service->GetServiceDataLength(), aTlvsBase, aTlvsBaseLength);

                if (!serviceBase || !serviceBase->IsStable())
                {
                    ExitNow(rval = true);
                }

                curInner = service->GetSubTlvs();
                endInner = service->GetNext();

                while (curInner < endInner)
                {
                    if (curInner->IsStable())
                    {
                        switch (curInner->GetType())
                        {
                        case NetworkDataTlv::kTypeServer:
                        {
                            bool       foundInBase = false;
                            ServerTlv *server      = static_cast<ServerTlv *>(curInner);

                            NetworkDataTlv *curServerBase = serviceBase->GetSubTlvs();
                            NetworkDataTlv *endServerBase = serviceBase->GetNext();

                            while (curServerBase <= endServerBase)
                            {
                                ServerTlv *serverBase = static_cast<ServerTlv *>(curServerBase);

                                VerifyOrExit((curServerBase + 1) <= endServerBase && curServerBase->GetNext() <= end);

                                if (curServerBase->IsStable() && (server->GetServer16() == serverBase->GetServer16()) &&
                                    (server->GetServerDataLength() == serverBase->GetServerDataLength()) &&
                                    (memcmp(server->GetServerData(), serverBase->GetServerData(),
                                            server->GetServerDataLength()) == 0))
                                {
                                    foundInBase = true;
                                    break;
                                }

                                curServerBase = curServerBase->GetNext();
                            }

                            if (!foundInBase)
                            {
                                ExitNow(rval = true);
                            }

                            break;
                        }

                        default:
                            break;
                        }
                    }

                    curInner = curInner->GetNext();
                }
            }

            break;

        default:
            break;
        }

        cur = cur->GetNext();
    }

exit:
    return rval;
}

otError Leader::RegisterNetworkData(uint16_t aRloc16, uint8_t *aTlvs, uint8_t aTlvsLength)
{
    otError error         = OT_ERROR_NONE;
    bool    rlocIn        = false;
    bool    rlocStable    = false;
    bool    stableUpdated = false;
    bool    unused;
    uint8_t oldTlvs[NetworkData::kMaxSize];
    uint8_t oldTlvsLength = NetworkData::kMaxSize;

    // Verify that `aTlvs` only contains entries matching `aRloc16`.
    SuccessOrExit(error = RlocLookup(aRloc16, rlocIn, rlocStable, aTlvs, aTlvsLength, kMatchModeRloc16,
                                     /* aAllowOtherEntries */ false));

    RlocLookup(aRloc16, rlocIn, unused, mTlvs, mLength, kMatchModeRloc16);

    if (rlocIn)
    {
        if (IsStableUpdated(aTlvs, aTlvsLength, mTlvs, mLength) || IsStableUpdated(mTlvs, mLength, aTlvs, aTlvsLength))
        {
            stableUpdated = true;
        }

        // Store old Service IDs for given rloc16, so updates to server will reuse the same Service ID
        SuccessOrExit(error = GetNetworkData(false, oldTlvs, oldTlvsLength));

        RemoveRloc(aRloc16, kMatchModeRloc16);
        SuccessOrExit(error = AddNetworkData(aTlvs, aTlvsLength, oldTlvs, oldTlvsLength));

        mVersion++;

        if (stableUpdated)
        {
            mStableVersion++;
        }
    }
    else
    {
        // No old data to be preserved, lets avoid memcpy() & FindService calls.
        SuccessOrExit(error = AddNetworkData(aTlvs, aTlvsLength, oldTlvs, 0));

        mVersion++;

        if (rlocStable)
        {
            mStableVersion++;
        }
    }

    Get<Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);

exit:
    return error;
}

otError Leader::AddNetworkData(uint8_t *aTlvs, uint8_t aTlvsLength, uint8_t *aOldTlvs, uint8_t aOldTlvsLength)
{
    otError         error = OT_ERROR_NONE;
    NetworkDataTlv *cur   = reinterpret_cast<NetworkDataTlv *>(aTlvs);
    NetworkDataTlv *end   = reinterpret_cast<NetworkDataTlv *>(aTlvs + aTlvsLength);

    while (cur < end)
    {
        VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end, error = OT_ERROR_PARSE);

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypePrefix:
            SuccessOrExit(error = AddPrefix(*static_cast<PrefixTlv *>(cur)));
            otDumpDebgNetData("add prefix done", mTlvs, mLength);
            break;

        case NetworkDataTlv::kTypeService:
            SuccessOrExit(error = AddService(*static_cast<ServiceTlv *>(cur), aOldTlvs, aOldTlvsLength));
            otDumpDebgNetData("add service done", mTlvs, mLength);
            break;

        default:
            break;
        }

        cur = cur->GetNext();
    }

    otDumpDebgNetData("add done", mTlvs, mLength);

exit:
    return error;
}

otError Leader::AddPrefix(PrefixTlv &aPrefix)
{
    otError         error = OT_ERROR_NONE;
    NetworkDataTlv *cur;
    NetworkDataTlv *end;

    VerifyOrExit(aPrefix.IsValid(), error = OT_ERROR_PARSE);
    cur = aPrefix.GetSubTlvs();
    end = aPrefix.GetNext();

    while (cur < end)
    {
        VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end, error = OT_ERROR_PARSE);

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypeHasRoute:
            SuccessOrExit(error = AddHasRoute(aPrefix, *static_cast<HasRouteTlv *>(cur)));
            break;

        case NetworkDataTlv::kTypeBorderRouter:
            SuccessOrExit(error = AddBorderRouter(aPrefix, *static_cast<BorderRouterTlv *>(cur)));
            break;

        default:
            break;
        }

        cur = cur->GetNext();
    }

exit:
    return error;
}

otError Leader::AddService(ServiceTlv &aService, uint8_t *aOldTlvs, uint8_t aOldTlvsLength)
{
    otError         error = OT_ERROR_NONE;
    NetworkDataTlv *cur;
    NetworkDataTlv *end;

    VerifyOrExit(aService.IsValid(), error = OT_ERROR_PARSE);
    cur = aService.GetSubTlvs();
    end = aService.GetNext();

    while (cur < end)
    {
        VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end, error = OT_ERROR_PARSE);

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypeServer:
            SuccessOrExit(error = AddServer(aService, *static_cast<ServerTlv *>(cur), aOldTlvs, aOldTlvsLength));
            break;

        default:
            break;
        }

        cur = cur->GetNext();
    }

exit:
    return error;
}

otError Leader::AddHasRoute(PrefixTlv &aPrefix, HasRouteTlv &aHasRoute)
{
    otError      error        = OT_ERROR_NONE;
    PrefixTlv *  dstPrefix    = NULL;
    HasRouteTlv *dstHasRoute  = NULL;
    uint16_t     appendLength = 0;

    VerifyOrExit(aHasRoute.GetNumEntries() > 0, error = OT_ERROR_PARSE);

    if ((dstPrefix = FindPrefix(aPrefix.GetPrefix(), aPrefix.GetPrefixLength())) != NULL)
    {
        dstHasRoute = FindHasRoute(*dstPrefix, aHasRoute.IsStable());
    }

    if (dstPrefix == NULL)
    {
        appendLength += sizeof(PrefixTlv) + BitVectorBytes(aPrefix.GetPrefixLength());
    }

    if (dstHasRoute == NULL)
    {
        appendLength += sizeof(HasRouteTlv);
    }

    appendLength += sizeof(HasRouteEntry);

    VerifyOrExit(mLength + appendLength <= sizeof(mTlvs), error = OT_ERROR_NO_BUFS);

    if (dstPrefix == NULL)
    {
        dstPrefix = reinterpret_cast<PrefixTlv *>(mTlvs + mLength);
        Insert(reinterpret_cast<uint8_t *>(dstPrefix), sizeof(PrefixTlv) + BitVectorBytes(aPrefix.GetPrefixLength()));
        dstPrefix->Init(aPrefix.GetDomainId(), aPrefix.GetPrefixLength(), aPrefix.GetPrefix());
    }

    if (aHasRoute.IsStable())
    {
        dstPrefix->SetStable();
    }

    if (dstHasRoute == NULL)
    {
        dstHasRoute = static_cast<HasRouteTlv *>(dstPrefix->GetNext());
        Insert(reinterpret_cast<uint8_t *>(dstHasRoute), sizeof(HasRouteTlv));
        dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(HasRouteTlv));
        dstHasRoute->Init();

        if (aHasRoute.IsStable())
        {
            dstHasRoute->SetStable();
        }
    }

    Insert(reinterpret_cast<uint8_t *>(dstHasRoute->GetNext()), sizeof(HasRouteEntry));
    dstHasRoute->SetLength(dstHasRoute->GetLength() + sizeof(HasRouteEntry));
    dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(HasRouteEntry));
    memcpy(dstHasRoute->GetEntry(dstHasRoute->GetNumEntries() - 1), aHasRoute.GetEntry(0), sizeof(HasRouteEntry));

exit:
    return error;
}

otError Leader::AddServer(ServiceTlv &aService, ServerTlv &aServer, uint8_t *aOldTlvs, uint8_t aOldTlvsLength)
{
    otError     error               = OT_ERROR_NONE;
    ServiceTlv *dstService          = NULL;
    ServiceTlv *oldService          = NULL;
    ServerTlv * dstServer           = NULL;
    uint16_t    appendLength        = 0;
    uint8_t     serviceID           = 0;
    uint8_t     serviceInsertLength = sizeof(ServiceTlv) + sizeof(uint8_t) /*mServiceDataLength*/ +
                                  ServiceTlv::GetEnterpriseNumberFieldLength(aService.GetEnterpriseNumber()) +
                                  aService.GetServiceDataLength();

    dstService =
        FindService(aService.GetEnterpriseNumber(), aService.GetServiceData(), aService.GetServiceDataLength());

    if (dstService == NULL)
    {
        appendLength += serviceInsertLength;
    }

    appendLength += sizeof(ServerTlv) + aServer.GetServerDataLength();

    VerifyOrExit(mLength + appendLength <= sizeof(mTlvs), error = OT_ERROR_NO_BUFS);

    if (dstService == NULL)
    {
        // Try to preserve old Service ID, if existing
        oldService = FindService(aService.GetEnterpriseNumber(), aService.GetServiceData(),
                                 aService.GetServiceDataLength(), aOldTlvs, aOldTlvsLength);

        if (oldService != NULL)
        {
            // The same service is not found in current data, but was in old data. So, it had to be just removed by
            // RemoveRloc() Lets use the same ServiceID
            serviceID = oldService->GetServiceID();
        }
        else
        {
            uint8_t i;

            // This seems like completely new service. Lets try to find new ServiceID for it. If all are taken, error
            // out. Since we call FindServiceById() on mTlv, we need to execute this before Insert() call, otherwise
            // we'll find uninitialized service as well.
            for (i = Mle::kServiceMinId; i <= Mle::kServiceMaxId; i++)
            {
                if (FindServiceById(i) == NULL)
                {
                    serviceID = i;
                    break;
                }
            }

            otLogInfoNetData("Allocated Service ID = %d", i);

            VerifyOrExit(i <= Mle::kServiceMaxId, error = OT_ERROR_NO_BUFS);
        }

        dstService = reinterpret_cast<ServiceTlv *>(mTlvs + mLength);
        Insert(reinterpret_cast<uint8_t *>(dstService), serviceInsertLength);
        dstService->Init();
        dstService->SetServiceID(serviceID);
        dstService->SetEnterpriseNumber(aService.GetEnterpriseNumber());
        dstService->SetServiceData(aService.GetServiceData(), aService.GetServiceDataLength());
        dstService->SetLength(serviceInsertLength - sizeof(NetworkDataTlv));
    }

    dstServer = static_cast<ServerTlv *>(dstService->GetNext());

    Insert(reinterpret_cast<uint8_t *>(dstServer), sizeof(ServerTlv) + aServer.GetServerDataLength());
    dstServer->Init();
    dstServer->SetServer16(aServer.GetServer16());
    dstServer->SetServerData(aServer.GetServerData(), aServer.GetServerDataLength());

    if (aServer.IsStable())
    {
        dstService->SetStable();
        dstServer->SetStable();
    }

    dstService->SetLength(dstService->GetLength() + sizeof(ServerTlv) + aServer.GetServerDataLength());

exit:
    return error;
}

ServiceTlv *Leader::FindServiceById(uint8_t aServiceId)
{
    NetworkDataTlv *cur     = reinterpret_cast<NetworkDataTlv *>(mTlvs);
    NetworkDataTlv *end     = reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
    ServiceTlv *    compare = NULL;

    while (cur < end)
    {
        VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end);

        if (cur->GetType() == NetworkDataTlv::kTypeService)
        {
            compare = static_cast<ServiceTlv *>(cur);

            if (compare->GetServiceID() == aServiceId)
            {
                ExitNow();
            }
        }

        cur = cur->GetNext();
    }

    compare = NULL;

exit:
    return compare;
}

otError Leader::AddBorderRouter(PrefixTlv &aPrefix, BorderRouterTlv &aBorderRouter)
{
    otError          error           = OT_ERROR_NONE;
    PrefixTlv *      dstPrefix       = NULL;
    ContextTlv *     dstContext      = NULL;
    BorderRouterTlv *dstBorderRouter = NULL;
    int              contextId       = -1;
    uint16_t         appendLength    = 0;

    VerifyOrExit(aBorderRouter.GetNumEntries() > 0, error = OT_ERROR_PARSE);

    if ((dstPrefix = FindPrefix(aPrefix.GetPrefix(), aPrefix.GetPrefixLength())) != NULL)
    {
        dstContext      = FindContext(*dstPrefix);
        dstBorderRouter = FindBorderRouter(*dstPrefix, aBorderRouter.IsStable());
    }

    if (dstPrefix == NULL)
    {
        appendLength += sizeof(PrefixTlv) + BitVectorBytes(aPrefix.GetPrefixLength());
    }

    if (dstContext == NULL)
    {
        appendLength += sizeof(ContextTlv);
    }

    if (dstBorderRouter == NULL)
    {
        appendLength += sizeof(BorderRouterTlv);
    }

    appendLength += sizeof(BorderRouterEntry);

    VerifyOrExit(mLength + appendLength <= sizeof(mTlvs), error = OT_ERROR_NO_BUFS);

    if (dstContext == NULL)
    {
        contextId = AllocateContext();
        VerifyOrExit(contextId >= 0, error = OT_ERROR_NO_BUFS);
    }

    if (dstPrefix == NULL)
    {
        dstPrefix = reinterpret_cast<PrefixTlv *>(mTlvs + mLength);
        Insert(reinterpret_cast<uint8_t *>(dstPrefix), sizeof(PrefixTlv) + BitVectorBytes(aPrefix.GetPrefixLength()));
        dstPrefix->Init(aPrefix.GetDomainId(), aPrefix.GetPrefixLength(), aPrefix.GetPrefix());
    }

    if (dstContext == NULL)
    {
        dstContext = static_cast<ContextTlv *>(dstPrefix->GetNext());
        Insert(reinterpret_cast<uint8_t *>(dstContext), sizeof(ContextTlv));
        dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(ContextTlv));
        dstContext->Init();
        dstContext->SetCompress();
        dstContext->SetContextId(static_cast<uint8_t>(contextId));
        dstContext->SetContextLength(aPrefix.GetPrefixLength());
    }

    dstContext->SetCompress();
    StopContextReuseTimer(dstContext->GetContextId());

    if (dstBorderRouter == NULL)
    {
        dstBorderRouter = static_cast<BorderRouterTlv *>(dstPrefix->GetNext());
        Insert(reinterpret_cast<uint8_t *>(dstBorderRouter), sizeof(BorderRouterTlv));
        dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(BorderRouterTlv));
        dstBorderRouter->Init();
    }

    Insert(reinterpret_cast<uint8_t *>(dstBorderRouter->GetNext()), sizeof(BorderRouterEntry));
    dstBorderRouter->SetLength(dstBorderRouter->GetLength() + sizeof(BorderRouterEntry));
    dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(BorderRouterEntry));
    memcpy(dstBorderRouter->GetEntry(dstBorderRouter->GetNumEntries() - 1), aBorderRouter.GetEntry(0),
           sizeof(BorderRouterEntry));

    if (aBorderRouter.IsStable())
    {
        dstPrefix->SetStable();
        dstContext->SetStable();
        dstBorderRouter->SetStable();
    }

exit:
    return error;
}

int Leader::AllocateContext(void)
{
    int rval = -1;

    for (int i = kMinContextId; i < kMinContextId + kNumContextIds; i++)
    {
        if ((mContextUsed & (1 << i)) == 0)
        {
            mContextUsed |= 1 << i;
            rval = i;
            otLogInfoNetData("Allocated Context ID = %d", rval);
            ExitNow();
        }
    }

exit:
    return rval;
}

void Leader::FreeContext(uint8_t aContextId)
{
    otLogInfoNetData("Free Context Id = %d", aContextId);
    RemoveContext(aContextId);
    mContextUsed &= ~(1 << aContextId);
    mVersion++;
    mStableVersion++;
    Get<Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);
}

void Leader::StartContextReuseTimer(uint8_t aContextId)
{
    mContextLastUsed[aContextId - kMinContextId] = TimerMilli::GetNow();

    if (mContextLastUsed[aContextId - kMinContextId].GetValue() == 0)
    {
        mContextLastUsed[aContextId - kMinContextId].SetValue(1);
    }

    mTimer.Start(kStateUpdatePeriod);
}

void Leader::StopContextReuseTimer(uint8_t aContextId)
{
    mContextLastUsed[aContextId - kMinContextId].SetValue(0);
}

otError Leader::SendServerDataNotification(uint16_t aRloc16)
{
    otError error      = OT_ERROR_NONE;
    bool    rlocIn     = false;
    bool    rlocStable = false;

    RlocLookup(aRloc16, rlocIn, rlocStable, mTlvs, mLength, kMatchModeRloc16);

    VerifyOrExit(rlocIn, error = OT_ERROR_NOT_FOUND);

    SuccessOrExit(error = NetworkData::SendServerDataNotification(aRloc16));

exit:
    return error;
}

void Leader::RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode)
{
    NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
    NetworkDataTlv *end;
    PrefixTlv *     prefix;
    ServiceTlv *    service;

    while (1)
    {
        end = reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);

        if (cur >= end)
        {
            break;
        }

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypePrefix:
        {
            prefix = static_cast<PrefixTlv *>(cur);
            RemoveRloc(*prefix, aRloc16, aMatchMode);

            if (prefix->GetSubTlvsLength() == 0)
            {
                Remove(reinterpret_cast<uint8_t *>(prefix), sizeof(NetworkDataTlv) + prefix->GetLength());
                continue;
            }

            otDumpDebgNetData("remove prefix done", mTlvs, mLength);
            break;
        }

        case NetworkDataTlv::kTypeService:
        {
            service = static_cast<ServiceTlv *>(cur);
            RemoveRloc(*service, aRloc16, aMatchMode);

            if (service->GetSubTlvsLength() == 0)
            {
                Remove(reinterpret_cast<uint8_t *>(service), sizeof(NetworkDataTlv) + service->GetLength());
                continue;
            }

            otDumpDebgNetData("remove service done", mTlvs, mLength);

            break;
        }

        default:
            break;
        }

        cur = cur->GetNext();
    }

    otDumpDebgNetData("remove done", mTlvs, mLength);
}

void Leader::RemoveRloc(PrefixTlv &aPrefix, uint16_t aRloc16, MatchMode aMatchMode)
{
    NetworkDataTlv *cur = aPrefix.GetSubTlvs();
    NetworkDataTlv *end;
    ContextTlv *    context;

    while (1)
    {
        end = aPrefix.GetNext();

        if (cur >= end)
        {
            break;
        }

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypeHasRoute:
            RemoveRloc(aPrefix, *static_cast<HasRouteTlv *>(cur), aRloc16, aMatchMode);

            // remove has route tlv if empty
            if (cur->GetLength() == 0)
            {
                aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - sizeof(HasRouteTlv));
                Remove(reinterpret_cast<uint8_t *>(cur), sizeof(HasRouteTlv));
                continue;
            }

            break;

        case NetworkDataTlv::kTypeBorderRouter:
            RemoveRloc(aPrefix, *static_cast<BorderRouterTlv *>(cur), aRloc16, aMatchMode);

            // remove border router tlv if empty
            if (cur->GetLength() == 0)
            {
                aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - sizeof(BorderRouterTlv));
                Remove(reinterpret_cast<uint8_t *>(cur), sizeof(BorderRouterTlv));
                continue;
            }

            break;

        default:
            break;
        }

        cur = cur->GetNext();
    }

    if ((context = FindContext(aPrefix)) != NULL)
    {
        if (aPrefix.GetSubTlvsLength() == sizeof(ContextTlv))
        {
            context->ClearCompress();
            StartContextReuseTimer(context->GetContextId());
        }
        else
        {
            context->SetCompress();
            StopContextReuseTimer(context->GetContextId());
        }
    }
}

void Leader::RemoveRloc(ServiceTlv &aService, uint16_t aRloc16, MatchMode aMatchMode)
{
    NetworkDataTlv *cur = aService.GetSubTlvs();
    NetworkDataTlv *end;
    ServerTlv *     server;
    uint8_t         removeLength;

    while (1)
    {
        end = aService.GetNext();

        if (cur >= end)
        {
            break;
        }

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypeServer:
            server = static_cast<ServerTlv *>(cur);

            if (RlocMatch(server->GetServer16(), aRloc16, aMatchMode))
            {
                removeLength = sizeof(ServerTlv) + server->GetServerDataLength();
                aService.SetSubTlvsLength(aService.GetSubTlvsLength() - removeLength);
                Remove(reinterpret_cast<uint8_t *>(cur), removeLength);
                continue;
            }

            break;

        default:
            break;
        }

        cur = cur->GetNext();
    }
}

void Leader::RemoveRloc(PrefixTlv &aPrefix, HasRouteTlv &aHasRoute, uint16_t aRloc16, MatchMode aMatchMode)
{
    HasRouteEntry *entry = aHasRoute.GetFirstEntry();

    while (entry <= aHasRoute.GetLastEntry())
    {
        if (RlocMatch(entry->GetRloc(), aRloc16, aMatchMode))
        {
            aHasRoute.SetLength(aHasRoute.GetLength() - sizeof(HasRouteEntry));
            aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - sizeof(HasRouteEntry));
            Remove(reinterpret_cast<uint8_t *>(entry), sizeof(HasRouteEntry));
            continue;
        }

        entry = entry->GetNext();
    }
}

void Leader::RemoveRloc(PrefixTlv &aPrefix, BorderRouterTlv &aBorderRouter, uint16_t aRloc16, MatchMode aMatchMode)
{
    BorderRouterEntry *entry = aBorderRouter.GetFirstEntry();

    while (entry <= aBorderRouter.GetLastEntry())
    {
        if (RlocMatch(entry->GetRloc(), aRloc16, aMatchMode))
        {
            aBorderRouter.SetLength(aBorderRouter.GetLength() - sizeof(BorderRouterEntry));
            aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - sizeof(BorderRouterEntry));
            Remove(reinterpret_cast<uint8_t *>(entry), sizeof(*entry));
            continue;
        }

        entry = entry->GetNext();
    }
}

void Leader::RemoveContext(uint8_t aContextId)
{
    NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
    NetworkDataTlv *end;
    PrefixTlv *     prefix;

    while (1)
    {
        end = reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);

        if (cur >= end)
        {
            break;
        }

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypePrefix:
        {
            prefix = static_cast<PrefixTlv *>(cur);
            RemoveContext(*prefix, aContextId);

            if (prefix->GetSubTlvsLength() == 0)
            {
                Remove(reinterpret_cast<uint8_t *>(prefix), sizeof(NetworkDataTlv) + prefix->GetLength());
                continue;
            }

            otDumpDebgNetData("remove prefix done", mTlvs, mLength);
            break;
        }

        default:
            break;
        }

        cur = cur->GetNext();
    }

    otDumpDebgNetData("remove done", mTlvs, mLength);
}

void Leader::RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId)
{
    NetworkDataTlv *cur = aPrefix.GetSubTlvs();
    NetworkDataTlv *end;
    ContextTlv *    context;
    uint8_t         length;

    while (1)
    {
        end = aPrefix.GetNext();

        if (cur >= end)
        {
            break;
        }

        switch (cur->GetType())
        {
        case NetworkDataTlv::kTypeContext:
        {
            // remove context tlv
            context = static_cast<ContextTlv *>(cur);

            if (context->GetContextId() == aContextId)
            {
                length = sizeof(NetworkDataTlv) + context->GetLength();
                aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - length);
                Remove(reinterpret_cast<uint8_t *>(context), length);
                continue;
            }

            break;
        }

        default:
            break;
        }

        cur = cur->GetNext();
    }
}

void Leader::UpdateContextsAfterReset(void)
{
    PrefixTlv * prefix;
    ContextTlv *contextTlv;

    // Iterate through Network Data and synchronize missing contexts.
    for (NetworkDataTlv *cur                                            = reinterpret_cast<NetworkDataTlv *>(mTlvs);
         cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
    {
        if (cur->GetType() != NetworkDataTlv::kTypePrefix)
        {
            continue;
        }

        prefix     = static_cast<PrefixTlv *>(cur);
        contextTlv = FindContext(*prefix);

        if (contextTlv == NULL)
        {
            continue;
        }

        mContextUsed |= 1 << contextTlv->GetContextId();

        if (contextTlv->IsCompress())
        {
            StopContextReuseTimer(contextTlv->GetContextId());
        }
        else
        {
            StartContextReuseTimer(contextTlv->GetContextId());
        }
    }
}

void Leader::HandleTimer(Timer &aTimer)
{
    aTimer.GetOwner<Leader>().HandleTimer();
}

void Leader::HandleTimer(void)
{
    bool contextsWaiting = false;

    for (uint8_t i = 0; i < kNumContextIds; i++)
    {
        if (mContextLastUsed[i].GetValue() == 0)
        {
            continue;
        }

        if (TimerMilli::GetNow() - mContextLastUsed[i] >= Time::SecToMsec(mContextIdReuseDelay))
        {
            FreeContext(kMinContextId + i);
        }
        else
        {
            contextsWaiting = true;
        }
    }

    if (contextsWaiting)
    {
        mTimer.Start(kStateUpdatePeriod);
    }
}

} // namespace NetworkData
} // namespace ot

#endif // OPENTHREAD_FTD
