/*
 *    Copyright (c) 2021 Project CHIP Authors
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include <access/AuthMode.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ScopedMemoryBuffer.h>
#include <transport/SecureSession.h>
#include <transport/SecureSessionTable.h>

namespace chip {
namespace Transport {

Optional<SessionHandle> SecureSessionTable::CreateNewSecureSessionForTest(SecureSession::Type secureSessionType,
                                                                          uint16_t localSessionId, NodeId localNodeId,
                                                                          NodeId peerNodeId, CATValues peerCATs,
                                                                          uint16_t peerSessionId, FabricIndex fabricIndex,
                                                                          const ReliableMessageProtocolConfig & config)
{
    if (secureSessionType == SecureSession::Type::kCASE)
    {
        if ((fabricIndex == kUndefinedFabricIndex) || (localNodeId == kUndefinedNodeId) || (peerNodeId == kUndefinedNodeId))
        {
            return Optional<SessionHandle>::Missing();
        }
    }
    else if (secureSessionType == SecureSession::Type::kPASE)
    {
        if ((fabricIndex != kUndefinedFabricIndex) || (localNodeId != kUndefinedNodeId) || (peerNodeId != kUndefinedNodeId))
        {
            // TODO: This secure session type is infeasible! We must fix the tests
            if (false)
            {
                return Optional<SessionHandle>::Missing();
            }

            (void) fabricIndex;
        }
    }

    SecureSession * result = mEntries.CreateObject(*this, secureSessionType, localSessionId, localNodeId, peerNodeId, peerCATs,
                                                   peerSessionId, fabricIndex, config);
    return result != nullptr ? MakeOptional<SessionHandle>(*result) : Optional<SessionHandle>::Missing();
}

Optional<SessionHandle> SecureSessionTable::CreateNewSecureSession(SecureSession::Type secureSessionType,
                                                                   ScopedNodeId sessionEvictionHint)
{
    Optional<SessionHandle> rv = Optional<SessionHandle>::Missing();
    SecureSession * allocated  = nullptr;

    auto sessionId = FindUnusedSessionId();
    VerifyOrReturnValue(sessionId.HasValue(), Optional<SessionHandle>::Missing());

    //
    // We allocate a new session out of the pool if we have space in it. If we don't, we need
    // to run the eviction algorithm to get a free slot. We shall ALWAYS be guaranteed to evict
    // an existing session in the table in normal operating circumstances.
    //
    if (mEntries.Allocated() < GetMaxSessionTableSize())
    {
        allocated = mEntries.CreateObject(*this, secureSessionType, sessionId.Value());
    }
    else
    {
        allocated = EvictAndAllocate(sessionId.Value(), secureSessionType, sessionEvictionHint);
    }

    VerifyOrReturnValue(allocated != nullptr, Optional<SessionHandle>::Missing());

    rv             = MakeOptional<SessionHandle>(*allocated);
    mNextSessionId = sessionId.Value() == kMaxSessionID ? static_cast<uint16_t>(kUnsecuredSessionId + 1)
                                                        : static_cast<uint16_t>(sessionId.Value() + 1);

    return rv;
}

SecureSession * SecureSessionTable::EvictAndAllocate(uint16_t localSessionId, SecureSession::Type secureSessionType,
                                                     const ScopedNodeId & sessionEvictionHint)
{
    VerifyOrDieWithMsg(!mRunningEvictionLogic, SecureChannel,
                       "EvictAndAllocate isn't re-entrant, yet someone called us while we're already running");

    mRunningEvictionLogic = true;

    auto cleanup = ScopeExit([this]() { mRunningEvictionLogic = false; });

    ChipLogProgress(SecureChannel, "Evicting a slot for session with LSID: %d, type: %u", localSessionId,
                    (uint8_t) secureSessionType);

    VerifyOrDie(mEntries.Allocated() <= GetMaxSessionTableSize());

    //
    // Create a temporary list of objects each of which points to a session in the existing
    // session table, but are swappable. This allows them to then be used with a sorting algorithm
    // without affecting the sessions in the table itself.
    //
    // The size of this shouldn't place significant demands on the stack if using the default
    // configuration for CHIP_CONFIG_SECURE_SESSION_POOL_SIZE (17). Each item is
    // 8 bytes in size (on a 32-bit platform), and 16 bytes in size (on a 64-bit platform,
    // including padding).
    //
    // Total size of this stack variable = 17 * 8 = 136bytes (32-bit platform), 272 bytes (64-bit platform).
    //
    // Even if the define is set to a large value, it's likely not so bad on the sort of platform setup
    // that would have that sort of pool size.
    //
    // We need to sort (as opposed to just a linear search for the smallest/largest item)
    // since it is possible that the candidate selected for eviction may not actually be
    // released once marked for expiration (see comments below for more details).
    //
    // Consequently, we may need to walk the candidate list till we find one that is.
    // Sorting provides a better overall performance model in this scheme.
    //
    // (#19967): Investigate doing linear search instead.
    //
    //
    SortableSession sortableSessions[CHIP_CONFIG_SECURE_SESSION_POOL_SIZE];

    unsigned int index = 0;

    //
    // Compute two key stats for each session - the number of other sessions that
    // match its fabric, as well as the number of other sessions that match its peer.
    //
    // This will be used by the session eviction algorithm later.
    //
    ForEachSession([&index, &sortableSessions, this](auto * session) {
        sortableSessions[index].mSession             = session;
        sortableSessions[index].mNumMatchingOnFabric = 0;
        sortableSessions[index].mNumMatchingOnPeer   = 0;

        ForEachSession([session, index, &sortableSessions](auto * otherSession) {
            if (session != otherSession)
            {
                if (session->GetFabricIndex() == otherSession->GetFabricIndex())
                {
                    sortableSessions[index].mNumMatchingOnFabric++;

                    if (session->GetPeerNodeId() == otherSession->GetPeerNodeId())
                    {
                        sortableSessions[index].mNumMatchingOnPeer++;
                    }
                }
            }

            return Loop::Continue;
        });

        index++;
        return Loop::Continue;
    });

    auto sortableSessionSpan = Span<SortableSession>(sortableSessions, mEntries.Allocated());
    EvictionPolicyContext policyContext(sortableSessionSpan, sessionEvictionHint);

    DefaultEvictionPolicy(policyContext);
    ChipLogProgress(SecureChannel, "Sorted sessions for eviction...");

    const auto numSessions = mEntries.Allocated();

#if CHIP_DETAIL_LOGGING
    ChipLogDetail(SecureChannel, "Sorted Eviction Candidates (ranked from best candidate to worst):");
    for (auto * session = sortableSessions; session != (sortableSessions + numSessions); session++)
    {
        ChipLogDetail(SecureChannel,
                      "\t%ld: [%p] -- Peer: [%u:" ChipLogFormatX64
                      "] State: '%s', NumMatchingOnFabric: %d NumMatchingOnPeer: %d ActivityTime: %lu",
                      static_cast<long int>(session - sortableSessions), session->mSession,
                      session->mSession->GetPeer().GetFabricIndex(), ChipLogValueX64(session->mSession->GetPeer().GetNodeId()),
                      session->mSession->GetStateStr(), session->mNumMatchingOnFabric, session->mNumMatchingOnPeer,
                      static_cast<unsigned long>(session->mSession->GetLastActivityTime().count()));
    }
#endif

    for (auto * session = sortableSessions; session != (sortableSessions + numSessions); session++)
    {
        if (session->mSession->IsPendingEviction())
        {
            continue;
        }

        ChipLogProgress(SecureChannel, "Candidate Session[%p] - Attempting to evict...", session->mSession);

        auto prevCount = mEntries.Allocated();

        //
        // SessionHolders act like weak-refs on a session, but since they do still add to the ref-count of a SecureSession, we
        // cannot actually tell whether there are truly any strong-refs (SessionHandles) on this session because if we did, we'd
        // avoid evicting it since it's pointless to do so.
        //
        // However, we don't actually have SessionHolders implemented correctly as weak-refs, requiring us to go ahead and 'try' to
        // evict it, and see if it still remains in the table. If it does, we have to try the next one. If it doesn't, we know we've
        // earned a free spot.
        //
        // See #19495.
        //
        session->mSession->MarkForEviction();

        auto newCount = mEntries.Allocated();

        if (newCount < prevCount)
        {
            ChipLogProgress(SecureChannel, "Successfully evicted a session!");
            auto * retSession = mEntries.CreateObject(*this, secureSessionType, localSessionId);
            VerifyOrDie(session != nullptr);
            return retSession;
        }
    }

    VerifyOrDieWithMsg(false, SecureChannel, "We couldn't find any session to evict at all, something's wrong!");
    return nullptr;
}

void SecureSessionTable::DefaultEvictionPolicy(EvictionPolicyContext & evictionContext)
{
    //
    // This implements a spec-compliant sorting policy that ensures both guarantees for sessions per-fabric as
    // mandated by the spec as well as fairness in terms of selecting the most appropriate session to evict
    // based on multiple criteria.
    //
    // See the description of this function in the header for more details on each sorting key below.
    //
    evictionContext.Sort([&evictionContext](const SortableSession & a, const SortableSession & b) -> bool {
        //
        // Sorting on Key1
        //
        if (a.mNumMatchingOnFabric != b.mNumMatchingOnFabric)
        {
            return a.mNumMatchingOnFabric > b.mNumMatchingOnFabric;
        }

        bool doesAMatchSessionHintFabric =
            a.mSession->GetPeer().GetFabricIndex() == evictionContext.GetSessionEvictionHint().GetFabricIndex();
        bool doesBMatchSessionHintFabric =
            b.mSession->GetPeer().GetFabricIndex() == evictionContext.GetSessionEvictionHint().GetFabricIndex();

        //
        // Sorting on Key2
        //
        if (doesAMatchSessionHintFabric != doesBMatchSessionHintFabric)
        {
            return doesAMatchSessionHintFabric > doesBMatchSessionHintFabric;
        }

        //
        // Sorting on Key3
        //
        if (a.mNumMatchingOnPeer != b.mNumMatchingOnPeer)
        {
            return a.mNumMatchingOnPeer > b.mNumMatchingOnPeer;
        }

        // We have an evicton hint in two cases:
        //
        // 1) When we just established CASE as a responder, the hint is the node
        //    we just established CASE to.
        // 2) When starting to establish CASE as an initiator, the hint is the
        //    node we are going to establish CASE to.
        //
        // In case 2, we should not end up here if there is an active session to
        // the peer at all (because that session should have been used instead
        // of establishing a new one).
        //
        // In case 1, we know we have a session matching the hint, but we don't
        // want to pick that one for eviction, because we just established it.
        // So we should not consider a session as matching a hint if it's active
        // and is the only session to our peer.
        //
        // Checking for the "active" state in addition to the "only session to
        // peer" state allows us to prioritize evicting defuct sessions that
        // match the hint against other defunct sessions.
        auto sessionMatchesEvictionHint = [&evictionContext](const SortableSession & session) -> int {
            if (session.mSession->GetPeer() != evictionContext.GetSessionEvictionHint())
            {
                return false;
            }
            bool isOnlyActiveSessionToPeer = session.mSession->IsActiveSession() && session.mNumMatchingOnPeer == 0;
            return !isOnlyActiveSessionToPeer;
        };
        int doesAMatchSessionHint = sessionMatchesEvictionHint(a);
        int doesBMatchSessionHint = sessionMatchesEvictionHint(b);

        //
        // Sorting on Key4
        //
        if (doesAMatchSessionHint != doesBMatchSessionHint)
        {
            return doesAMatchSessionHint > doesBMatchSessionHint;
        }

        int aStateScore = 0, bStateScore = 0;
        auto assignStateScore = [](auto & score, const auto & session) {
            if (session.IsDefunct())
            {
                score = 2;
            }
            else if (session.IsActiveSession())
            {
                score = 1;
            }
            else
            {
                score = 0;
            }
        };

        assignStateScore(aStateScore, *a.mSession);
        assignStateScore(bStateScore, *b.mSession);

        //
        // Sorting on Key5
        //
        if (aStateScore != bStateScore)
        {
            return (aStateScore > bStateScore);
        }

        //
        // Sorting on Key6
        //
        return (a->GetLastActivityTime() < b->GetLastActivityTime());
    });
}

Optional<SessionHandle> SecureSessionTable::FindSecureSessionByLocalKey(uint16_t localSessionId)
{
    SecureSession * result = nullptr;
    mEntries.ForEachActiveObject([&](auto session) {
        if (session->GetLocalSessionId() == localSessionId)
        {
            result = session;
            return Loop::Break;
        }
        return Loop::Continue;
    });
    return result != nullptr ? MakeOptional<SessionHandle>(*result) : Optional<SessionHandle>::Missing();
}

Optional<uint16_t> SecureSessionTable::FindUnusedSessionId()
{
    uint16_t candidate_base = 0;
    uint64_t candidate_mask = 0;
    for (uint32_t i = 0; i <= kMaxSessionID; i += 64)
    {
        // candidate_base is the base session ID we are searching from.
        // We have a 64-bit mask anchored at this ID and iterate over the
        // whole session table, setting bits in the mask for in-use IDs.
        // If we can iterate through the entire session table and have
        // any bits clear in the mask, we have available session IDs.
        candidate_base = static_cast<uint16_t>(i + mNextSessionId);
        candidate_mask = 0;
        {
            uint16_t shift = static_cast<uint16_t>(kUnsecuredSessionId - candidate_base);
            if (shift <= 63)
            {
                candidate_mask |= (1ULL << shift); // kUnsecuredSessionId is never available
            }
        }
        mEntries.ForEachActiveObject([&](auto session) {
            uint16_t shift = static_cast<uint16_t>(session->GetLocalSessionId() - candidate_base);
            if (shift <= 63)
            {
                candidate_mask |= (1ULL << shift);
            }
            if (candidate_mask == UINT64_MAX)
            {
                return Loop::Break; // No bits clear means this bucket is full.
            }
            return Loop::Continue;
        });
        if (candidate_mask != UINT64_MAX)
        {
            break; // Any bit clear means we have an available ID in this bucket.
        }
    }
    if (candidate_mask != UINT64_MAX)
    {
        uint16_t offset = 0;
        while (candidate_mask & 1)
        {
            candidate_mask >>= 1;
            ++offset;
        }
        uint16_t available = static_cast<uint16_t>(candidate_base + offset);
        return MakeOptional<uint16_t>(available);
    }

    return NullOptional;
}

} // namespace Transport
} // namespace chip
