/*
 *  Copyright (c) 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 implements the child supervision feature.
 */

#include <openthread/config.h>

#include "child_supervision.hpp"

#include <openthread/openthread.h>

#include "openthread-core-config.h"
#include "openthread-instance.h"
#include "common/code_utils.hpp"
#include "common/logging.hpp"
#include "thread/thread_netif.hpp"

namespace ot {
namespace Utils {

#if OPENTHREAD_ENABLE_CHILD_SUPERVISION

#if OPENTHREAD_FTD

ChildSupervisor::ChildSupervisor(ThreadNetif &aThreadNetif) :
    ThreadNetifLocator(aThreadNetif),
    mTimer(aThreadNetif.GetIp6().mTimerScheduler, &ChildSupervisor::HandleTimer, this),
    mSupervisionInterval(kDefaultSupervisionInterval)
{
}

void ChildSupervisor::Start(void)
{
    VerifyOrExit(mSupervisionInterval != 0);
    VerifyOrExit(!mTimer.IsRunning());
    mTimer.Start(kOneSecond);

exit:
    return;
}

void ChildSupervisor::Stop(void)
{
    mTimer.Stop();
}

void ChildSupervisor::SetSupervisionInterval(uint16_t aInterval)
{
    mSupervisionInterval = aInterval;
    Start();
}

Child *ChildSupervisor::GetDestination(const Message &aMessage) const
{
    Child *child = NULL;
    uint8_t childIndex;
    uint8_t numChildren;

    VerifyOrExit(aMessage.GetType() == Message::kTypeSupervision);

    aMessage.Read(0, sizeof(childIndex), &childIndex);
    child = GetNetif().GetMle().GetChildren(&numChildren);
    VerifyOrExit(childIndex < numChildren, child = NULL);
    child += childIndex;

exit:
    return child;
}

void ChildSupervisor::SendMessage(Child &aChild)
{
    ThreadNetif &netif = GetNetif();
    Message *message = NULL;
    otError error = OT_ERROR_NONE;
    uint8_t childIndex;

    VerifyOrExit(aChild.GetIndirectMessageCount() == 0);

    message = netif.GetIp6().mMessagePool.New(Message::kTypeSupervision, sizeof(uint8_t));
    VerifyOrExit(message != NULL);

    // Supervision message is an empty payload 15.4 data frame.
    // The child index is stored here in the message content to allow
    // the destination of the message to be later retrieved using
    // `ChildSupervisor::GetDestination(message)`.

    childIndex = netif.GetMle().GetChildIndex(aChild);
    SuccessOrExit(error = message->Append(&childIndex, sizeof(childIndex)));

    SuccessOrExit(error = netif.SendMessage(*message));
    message = NULL;

    otLogInfoMle(GetInstance(), "Sending supervision message to child 0x%04x", aChild.GetRloc16());

exit:

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

void ChildSupervisor::UpdateOnSend(Child &aChild)
{
    aChild.ResetSecondsSinceLastSupervision();
}

void ChildSupervisor::HandleTimer(Timer &aTimer)
{
    GetOwner(aTimer).HandleTimer();
}

void ChildSupervisor::HandleTimer(void)
{
    Child *child;
    uint8_t numChildren;

    VerifyOrExit(mSupervisionInterval != 0);

    child = GetNetif().GetMle().GetChildren(&numChildren);

    for (uint8_t i = 0; i < numChildren; i++, child++)
    {
        if (!child->IsStateValidOrRestoring())
        {
            continue;
        }

        child->IncrementSecondsSinceLastSupervision();

        if ((child->GetSecondsSinceLastSupervision() >= mSupervisionInterval) && (child->IsRxOnWhenIdle() == false))
        {
            SendMessage(*child);
        }
    }

    mTimer.Start(kOneSecond);

exit:
    return;
}

ChildSupervisor &ChildSupervisor::GetOwner(const Context &aContext)
{
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
    ChildSupervisor &supervisor = *static_cast<ChildSupervisor *>(aContext.GetContext());
#else
    ChildSupervisor &supervisor = otGetThreadNetif().GetChildSupervisor();
    OT_UNUSED_VARIABLE(aContext);
#endif
    return supervisor;
}

#endif // #if OPENTHREAD_FTD

SupervisionListener::SupervisionListener(ThreadNetif &aThreadNetif) :
    ThreadNetifLocator(aThreadNetif),
    mTimer(aThreadNetif.GetIp6().mTimerScheduler, &SupervisionListener::HandleTimer, this),
    mTimeout(0)
{
    SetTimeout(kDefaultTimeout);
}

void SupervisionListener::Start(void)
{
    RestartTimer();
}

void SupervisionListener::Stop(void)
{
    mTimer.Stop();
}

void SupervisionListener::SetTimeout(uint16_t aTimeout)
{
    if (mTimeout != aTimeout)
    {
        mTimeout = aTimeout;
        RestartTimer();
    }
}

void SupervisionListener::UpdateOnReceive(const Mac::Address &aSourceAddress, bool aIsSecure)
{
    ThreadNetif &netif = GetNetif();

    // If listener is enabled and device is a child and it received a secure frame from its parent, restart the timer.

    VerifyOrExit(mTimer.IsRunning() && aIsSecure  && (netif.GetMle().GetRole() == OT_DEVICE_ROLE_CHILD) &&
                 (netif.GetMle().GetNeighbor(aSourceAddress) == netif.GetMle().GetParent()));

    RestartTimer();

exit:
    return;
}

void SupervisionListener::RestartTimer(void)
{
    ThreadNetif &netif = GetNetif();

    // Restart the timer, if the timeout value is non-zero and the device is a sleepy child.

    if ((mTimeout != 0) && (netif.GetMle().GetRole() == OT_DEVICE_ROLE_CHILD) &&
        (netif.GetMeshForwarder().GetRxOnWhenIdle() == false))
    {
        mTimer.Start(Timer::SecToMsec(mTimeout));
    }
    else
    {
        mTimer.Stop();
    }
}

void SupervisionListener::HandleTimer(Timer &aTimer)
{
    GetOwner(aTimer).HandleTimer();
}

void SupervisionListener::HandleTimer(void)
{
    ThreadNetif &netif = GetNetif();

    VerifyOrExit((netif.GetMle().GetRole() == OT_DEVICE_ROLE_CHILD) &&
                 (netif.GetMeshForwarder().GetRxOnWhenIdle() == false));

    otLogWarnMle(netif.GetInstance(), "Supervision timeout. No frame from parent in %d sec", mTimeout);

    netif.GetMle().SendChildUpdateRequest();

exit:
    RestartTimer();
}

SupervisionListener &SupervisionListener::GetOwner(const Context &aContext)
{
#if OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
    SupervisionListener &listener = *static_cast<SupervisionListener *>(aContext.GetContext());
#else
    SupervisionListener &listener = otGetThreadNetif().GetSupervisionListener();
    OT_UNUSED_VARIABLE(aContext);
#endif
    return listener;
}

#endif // #if OPENTHREAD_ENABLE_CHILD_SUPERVISION

} // namespace Utils
} // namespace ot
