/*
 *  Copyright (C) 2004-2023 Savoir-faire Linux Inc.
 *
 *  Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
 *  Author: Eden Abitbol <eden.abitbol@savoirfairelinux.com>
 *  Author: Mohamed Chibani <mohamed.chibani@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */

#include "upnp_context.h"

namespace jami {
namespace upnp {

constexpr static auto MAP_UPDATE_INTERVAL = std::chrono::seconds(30);
constexpr static int MAX_REQUEST_RETRIES = 20;
constexpr static int MAX_REQUEST_REMOVE_COUNT = 5;

constexpr static uint16_t UPNP_TCP_PORT_MIN {10000};
constexpr static uint16_t UPNP_TCP_PORT_MAX {UPNP_TCP_PORT_MIN + 5000};
constexpr static uint16_t UPNP_UDP_PORT_MIN {20000};
constexpr static uint16_t UPNP_UDP_PORT_MAX {UPNP_UDP_PORT_MIN + 5000};

UPnPContext::UPnPContext()
{
    JAMI_DBG("Creating UPnPContext instance [%p]", this);

    // Set port ranges
    portRange_.emplace(PortType::TCP, std::make_pair(UPNP_TCP_PORT_MIN, UPNP_TCP_PORT_MAX));
    portRange_.emplace(PortType::UDP, std::make_pair(UPNP_UDP_PORT_MIN, UPNP_UDP_PORT_MAX));

    if (not isValidThread()) {
        runOnUpnpContextQueue([this] { init(); });
        return;
    }
}

std::shared_ptr<UPnPContext>
UPnPContext::getUPnPContext()
{
    // This is the unique shared instance (singleton) of UPnPContext class.
    static auto context = std::make_shared<UPnPContext>();
    return context;
}

void
UPnPContext::shutdown(std::condition_variable& cv)
{
    JAMI_DBG("Shutdown UPnPContext instance [%p]", this);

    stopUpnp(true);

    for (auto const& [_, proto] : protocolList_) {
        proto->terminate();
    }

    {
        std::lock_guard<std::mutex> lock(mappingMutex_);
        mappingList_->clear();
        if (mappingListUpdateTimer_)
            mappingListUpdateTimer_->cancel();
        controllerList_.clear();
        protocolList_.clear();
        shutdownComplete_ = true;
        cv.notify_one();
    }
}

void
UPnPContext::shutdown()
{
    std::unique_lock<std::mutex> lk(mappingMutex_);
    std::condition_variable cv;

    runOnUpnpContextQueue([&, this] { shutdown(cv); });

    JAMI_DBG("Waiting for shutdown ...");

    if (cv.wait_for(lk, std::chrono::seconds(30), [this] { return shutdownComplete_; })) {
        JAMI_DBG("Shutdown completed");
    } else {
        JAMI_ERR("Shutdown timed-out");
    }
}

UPnPContext::~UPnPContext()
{
    JAMI_DBG("UPnPContext instance [%p] destroyed", this);
}

void
UPnPContext::init()
{
    threadId_ = getCurrentThread();
    CHECK_VALID_THREAD();

#if HAVE_LIBNATPMP
    auto natPmp = std::make_shared<NatPmp>();
    natPmp->setObserver(this);
    protocolList_.emplace(NatProtocolType::NAT_PMP, std::move(natPmp));
#endif

#if HAVE_LIBUPNP
    auto pupnp = std::make_shared<PUPnP>();
    pupnp->setObserver(this);
    protocolList_.emplace(NatProtocolType::PUPNP, std::move(pupnp));
#endif
}

void
UPnPContext::startUpnp()
{
    assert(not controllerList_.empty());

    CHECK_VALID_THREAD();

    JAMI_DBG("Starting UPNP context");

    // Request a new IGD search.
    for (auto const& [_, protocol] : protocolList_) {
        protocol->searchForIgd();
    }

    started_ = true;
}

void
UPnPContext::stopUpnp(bool forceRelease)
{
    if (not isValidThread()) {
        runOnUpnpContextQueue([this, forceRelease] { stopUpnp(forceRelease); });
        return;
    }

    JAMI_DBG("Stopping UPNP context");

    // Clear all current mappings if any.

    // Use a temporary list to avoid processing the mapping
    // list while holding the lock.
    std::list<Mapping::sharedPtr_t> toRemoveList;
    {
        std::lock_guard<std::mutex> lock(mappingMutex_);

        PortType types[2] {PortType::TCP, PortType::UDP};
        for (auto& type : types) {
            auto& mappingList = getMappingList(type);
            for (auto const& [_, map] : mappingList) {
                toRemoveList.emplace_back(map);
            }
        }
        // Invalidate the current IGDs.
        preferredIgd_.reset();
        validIgdList_.clear();
    }
    for (auto const& map : toRemoveList) {
        requestRemoveMapping(map);

        // Notify is not needed in updateMappingState when
        // shutting down (hence set it to false). NotifyCallback
        // would trigger a new SIP registration and create a
        // false registered state upon program close.
        // It's handled by upper layers.

        updateMappingState(map, MappingState::FAILED, false);
        // We dont remove mappings with auto-update enabled,
        // unless forceRelease is true.
        if (not map->getAutoUpdate() or forceRelease) {
            map->enableAutoUpdate(false);
            unregisterMapping(map);
        }
    }

    // Clear all current IGDs.
    for (auto const& [_, protocol] : protocolList_) {
        protocol->clearIgds();
    }

    started_ = false;
}

uint16_t
UPnPContext::generateRandomPort(PortType type, bool mustBeEven)
{
    auto minPort = type == PortType::TCP ? UPNP_TCP_PORT_MIN : UPNP_UDP_PORT_MIN;
    auto maxPort = type == PortType::TCP ? UPNP_TCP_PORT_MAX : UPNP_UDP_PORT_MAX;

    if (minPort >= maxPort) {
        JAMI_ERR("Max port number (%i) must be greater than min port number (%i)", maxPort, minPort);
        // Must be called with valid range.
        assert(false);
    }

    int fact = mustBeEven ? 2 : 1;
    if (mustBeEven) {
        minPort /= fact;
        maxPort /= fact;
    }

    // Seed the generator.
    static std::mt19937 gen(dht::crypto::getSeededRandomEngine());
    // Define the range.
    std::uniform_int_distribution<uint16_t> dist(minPort, maxPort);
    return dist(gen) * fact;
}

void
UPnPContext::connectivityChanged()
{
    if (not isValidThread()) {
        runOnUpnpContextQueue([this] { connectivityChanged(); });
        return;
    }

    auto hostAddr = ip_utils::getLocalAddr(AF_INET);

    JAMI_DBG("Connectivity change check: host address %s", hostAddr.toString().c_str());

    auto restartUpnp = false;

    // On reception of "connectivity change" notification, the UPNP search
    // will be restarted if either there is no valid IGD, or the IGD address
    // changed.

    if (not isReady()) {
        restartUpnp = true;
    } else {
        // Check if the host address changed.
        for (auto const& [_, protocol] : protocolList_) {
            if (protocol->isReady() and hostAddr != protocol->getHostAddress()) {
                JAMI_WARN("Host address changed from %s to %s",
                          protocol->getHostAddress().toString().c_str(),
                          hostAddr.toString().c_str());
                protocol->clearIgds();
                restartUpnp = true;
                break;
            }
        }
    }

    // We have at least one valid IGD and the host address did
    // not change, so no need to restart.
    if (not restartUpnp) {
        return;
    }

    // No registered controller. A new search will be performed when
    // a controller is registered.
    if (controllerList_.empty())
        return;

    JAMI_DBG("Connectivity changed. Clear the IGDs and restart");

    stopUpnp();
    startUpnp();

    // Mapping with auto update enabled must be processed first.
    processMappingWithAutoUpdate();
}

void
UPnPContext::setPublicAddress(const IpAddr& addr)
{
    if (not addr)
        return;

    std::lock_guard<std::mutex> lock(mappingMutex_);
    if (knownPublicAddress_ != addr) {
        knownPublicAddress_ = std::move(addr);
        JAMI_DBG("Setting the known public address to %s", addr.toString().c_str());
    }
}

bool
UPnPContext::isReady() const
{
    std::lock_guard<std::mutex> lock(mappingMutex_);
    return not validIgdList_.empty();
}

IpAddr
UPnPContext::getExternalIP() const
{
    std::lock_guard<std::mutex> lock(mappingMutex_);
    // Return the first IGD Ip available.
    if (not validIgdList_.empty()) {
        return (*validIgdList_.begin())->getPublicIp();
    }
    return {};
}

Mapping::sharedPtr_t
UPnPContext::reserveMapping(Mapping& requestedMap)
{
    auto desiredPort = requestedMap.getExternalPort();

    if (desiredPort == 0) {
        JAMI_DBG("Desired port is not set, will provide the first available port for [%s]",
                 requestedMap.getTypeStr());
    } else {
        JAMI_DBG("Try to find mapping for port %i [%s]", desiredPort, requestedMap.getTypeStr());
    }

    Mapping::sharedPtr_t mapRes;

    {
        std::lock_guard<std::mutex> lock(mappingMutex_);
        auto& mappingList = getMappingList(requestedMap.getType());

        // We try to provide a mapping in "OPEN" state. If not found,
        // we provide any available mapping. In this case, it's up to
        // the caller to use it or not.
        for (auto const& [_, map] : mappingList) {
            // If the desired port is null, we pick the first available port.
            if (map->isValid() and (desiredPort == 0 or map->getExternalPort() == desiredPort)
                and map->isAvailable()) {
                // Considere the first available mapping regardless of its
                // state. A mapping with OPEN state will be used if found.
                if (not mapRes)
                    mapRes = map;

                if (map->getState() == MappingState::OPEN) {
                    // Found an "OPEN" mapping. We are done.
                    mapRes = map;
                    break;
                }
            }
        }
    }

    // Create a mapping if none was available.
    if (not mapRes) {
        JAMI_WARN("Did not find any available mapping. Will request one now");
        mapRes = registerMapping(requestedMap);
    }

    if (mapRes) {
        // Make the mapping unavailable
        mapRes->setAvailable(false);
        // Copy attributes.
        mapRes->setNotifyCallback(requestedMap.getNotifyCallback());
        mapRes->enableAutoUpdate(requestedMap.getAutoUpdate());
        // Notify the listener.
        if (auto cb = mapRes->getNotifyCallback())
            cb(mapRes);
    }

    updateMappingList(true);

    return mapRes;
}

void
UPnPContext::releaseMapping(const Mapping& map)
{
    if (not isValidThread()) {
        runOnUpnpContextQueue([this, map] { releaseMapping(map); });
        return;
    }

    auto mapPtr = getMappingWithKey(map.getMapKey());

    if (not mapPtr) {
        // Might happen if the mapping failed or was never granted.
        JAMI_DBG("Mapping %s does not exist or was already removed", map.toString().c_str());
        return;
    }

    if (mapPtr->isAvailable()) {
        JAMI_WARN("Trying to release an unused mapping %s", mapPtr->toString().c_str());
        return;
    }

    // Remove it.
    requestRemoveMapping(mapPtr);
    unregisterMapping(mapPtr);
}

void
UPnPContext::registerController(void* controller)
{
    {
        std::lock_guard<std::mutex> lock(mappingMutex_);
        if (shutdownComplete_) {
            JAMI_WARN("UPnPContext already shut down");
            return;
        }
    }

    if (not isValidThread()) {
        runOnUpnpContextQueue([this, controller] { registerController(controller); });
        return;
    }

    auto ret = controllerList_.emplace(controller);
    if (not ret.second) {
        JAMI_WARN("Controller %p is already registered", controller);
        return;
    }

    JAMI_DBG("Successfully registered controller %p", controller);
    if (not started_)
        startUpnp();
}

void
UPnPContext::unregisterController(void* controller)
{
    if (not isValidThread()) {
        runOnUpnpContextQueue([this, controller] { unregisterController(controller); });
        return;
    }

    if (controllerList_.erase(controller) == 1) {
        JAMI_DBG("Successfully unregistered controller %p", controller);
    } else {
        JAMI_DBG("Controller %p was already removed", controller);
    }

    if (controllerList_.empty()) {
        stopUpnp();
    }
}

uint16_t
UPnPContext::getAvailablePortNumber(PortType type)
{
    // Only return an availalable random port. No actual
    // reservation is made here.

    std::lock_guard<std::mutex> lock(mappingMutex_);
    auto& mappingList = getMappingList(type);
    int tryCount = 0;
    while (tryCount++ < MAX_REQUEST_RETRIES) {
        uint16_t port = generateRandomPort(type);
        Mapping map(type, port, port);
        if (mappingList.find(map.getMapKey()) == mappingList.end())
            return port;
    }

    // Very unlikely to get here.
    JAMI_ERR("Could not find an available port after %i trials", MAX_REQUEST_RETRIES);
    return 0;
}

void
UPnPContext::requestMapping(const Mapping::sharedPtr_t& map)
{
    assert(map);

    if (not isValidThread()) {
        runOnUpnpContextQueue([this, map] { requestMapping(map); });
        return;
    }

    auto const& igd = getPreferredIgd();
    // We must have at least a valid IGD pointer if we get here.
    // Not this method is called only if there were a valid IGD, however,
    // because the processing is asynchronous, it's possible that the IGD
    // was invalidated when the this code executed.
    if (not igd) {
        JAMI_DBG("No valid IGDs available");
        return;
    }

    map->setIgd(igd);

    JAMI_DBG("Request mapping %s using protocol [%s] IGD [%s]",
             map->toString().c_str(),
             igd->getProtocolName(),
             igd->toString().c_str());

    if (map->getState() != MappingState::IN_PROGRESS)
        updateMappingState(map, MappingState::IN_PROGRESS);

    auto const& protocol = protocolList_.at(igd->getProtocol());
    protocol->requestMappingAdd(*map);
}

bool
UPnPContext::provisionNewMappings(PortType type, int portCount)
{
    JAMI_DBG("Provision %i new mappings of type [%s]", portCount, Mapping::getTypeStr(type));

    assert(portCount > 0);

    while (portCount > 0) {
        auto port = getAvailablePortNumber(type);
        if (port > 0) {
            // Found an available port number
            portCount--;
            Mapping map(type, port, port, true);
            registerMapping(map);
        } else {
            // Very unlikely to get here!
            JAMI_ERR("Can not find any available port to provision!");
            return false;
        }
    }

    return true;
}

bool
UPnPContext::deleteUnneededMappings(PortType type, int portCount)
{
    JAMI_DBG("Remove %i unneeded mapping of type [%s]", portCount, Mapping::getTypeStr(type));

    assert(portCount > 0);

    CHECK_VALID_THREAD();

    std::lock_guard<std::mutex> lock(mappingMutex_);
    auto& mappingList = getMappingList(type);

    for (auto it = mappingList.begin(); it != mappingList.end();) {
        auto map = it->second;
        assert(map);

        if (not map->isAvailable()) {
            it++;
            continue;
        }

        if (map->getState() == MappingState::OPEN and portCount > 0) {
            // Close portCount mappings in "OPEN" state.
            requestRemoveMapping(map);
            it = unregisterMapping(it);
            portCount--;
        } else if (map->getState() != MappingState::OPEN) {
            // If this methods is called, it means there are more open
            // mappings than required. So, all mappings in a state other
            // than "OPEN" state (typically in in-progress state) will
            // be deleted as well.
            it = unregisterMapping(it);
        } else {
            it++;
        }
    }

    return true;
}

void
UPnPContext::updatePreferredIgd()
{
    CHECK_VALID_THREAD();

    if (preferredIgd_ and preferredIgd_->isValid())
        return;

    // Reset and search for the best IGD.
    preferredIgd_.reset();

    for (auto const& [_, protocol] : protocolList_) {
        if (protocol->isReady()) {
            auto igdList = protocol->getIgdList();
            assert(not igdList.empty());
            auto const& igd = igdList.front();
            if (not igd->isValid())
                continue;

            // Prefer NAT-PMP over PUPNP.
            if (preferredIgd_ and igd->getProtocol() != NatProtocolType::NAT_PMP)
                continue;

            // Update.
            preferredIgd_ = igd;
        }
    }

    if (preferredIgd_ and preferredIgd_->isValid()) {
        JAMI_DBG("Preferred IGD updated to [%s] IGD [%s %s] ",
                 preferredIgd_->getProtocolName(),
                 preferredIgd_->getUID().c_str(),
                 preferredIgd_->toString().c_str());
    }
}

std::shared_ptr<IGD>
UPnPContext::getPreferredIgd() const
{
    CHECK_VALID_THREAD();

    return preferredIgd_;
}

void
UPnPContext::updateMappingList(bool async)
{
    // Run async if requested.
    if (async) {
        runOnUpnpContextQueue([this] { updateMappingList(false); });
        return;
    }

    CHECK_VALID_THREAD();

    // Update the preferred IGD.
    updatePreferredIgd();

    if (mappingListUpdateTimer_) {
        mappingListUpdateTimer_->cancel();
        mappingListUpdateTimer_ = {};
    }

    // Skip if no controller registered.
    if (controllerList_.empty())
        return;

    // Cancel the current timer (if any) and re-schedule.
    std::shared_ptr<IGD> prefIgd = getPreferredIgd();
    if (not prefIgd) {
        JAMI_DBG("UPNP/NAT-PMP enabled, but no valid IGDs available");
        // No valid IGD. Nothing to do.
        return;
    }

    mappingListUpdateTimer_ = getScheduler()->scheduleIn([this] { updateMappingList(false); },
                                                         MAP_UPDATE_INTERVAL);

    // Process pending requests if any.
    processPendingRequests(prefIgd);

    // Make new requests for mappings that failed and have
    // the auto-update option enabled.
    processMappingWithAutoUpdate();

    PortType typeArray[2] = {PortType::TCP, PortType::UDP};

    for (auto idx : {0, 1}) {
        auto type = typeArray[idx];

        MappingStatus status;
        getMappingStatus(type, status);

        JAMI_DBG("Mapping status [%s] - overall %i: %i open (%i ready + %i in use), %i pending, %i "
                 "in-progress, %i failed",
                 Mapping::getTypeStr(type),
                 status.sum(),
                 status.openCount_,
                 status.readyCount_,
                 status.openCount_ - status.readyCount_,
                 status.pendingCount_,
                 status.inProgressCount_,
                 status.failedCount_);

        if (status.failedCount_ > 0) {
            std::lock_guard<std::mutex> lock(mappingMutex_);
            auto const& mappingList = getMappingList(type);
            for (auto const& [_, map] : mappingList) {
                if (map->getState() == MappingState::FAILED) {
                    JAMI_DBG("Mapping status [%s] - Available [%s]",
                             map->toString(true).c_str(),
                             map->isAvailable() ? "YES" : "NO");
                }
            }
        }

        int toRequestCount = (int) minOpenPortLimit_[idx]
                             - (int) (status.readyCount_ + status.inProgressCount_
                                      + status.pendingCount_);

        // Provision/release mappings accordingly.
        if (toRequestCount > 0) {
            // Take into account the request in-progress when making
            // requests for new mappings.
            provisionNewMappings(type, toRequestCount);
        } else if (status.readyCount_ > maxOpenPortLimit_[idx]) {
            deleteUnneededMappings(type, status.readyCount_ - maxOpenPortLimit_[idx]);
        }
    }

    // Prune the mapping list if needed
    if (protocolList_.at(NatProtocolType::PUPNP)->isReady()) {
#if HAVE_LIBNATPMP
        // Dont perform if NAT-PMP is valid.
        if (not protocolList_.at(NatProtocolType::NAT_PMP)->isReady())
#endif
        {
            pruneMappingList();
        }
    }

#if HAVE_LIBNATPMP
    // Renew nat-pmp allocations
    if (protocolList_.at(NatProtocolType::NAT_PMP)->isReady())
        renewAllocations();
#endif
}

void
UPnPContext::pruneMappingList()
{
    CHECK_VALID_THREAD();

    MappingStatus status;
    getMappingStatus(status);

    // Do not prune the list if there are pending/in-progress requests.
    if (status.inProgressCount_ != 0 or status.pendingCount_ != 0) {
        return;
    }

    auto const& igd = getPreferredIgd();
    if (not igd or igd->getProtocol() != NatProtocolType::PUPNP) {
        return;
    }
    auto protocol = protocolList_.at(NatProtocolType::PUPNP);

    auto remoteMapList = protocol->getMappingsListByDescr(igd,
                                                          Mapping::UPNP_MAPPING_DESCRIPTION_PREFIX);
    if (remoteMapList.empty()) {
        std::lock_guard<std::mutex> lock(mappingMutex_);
        if (not getMappingList(PortType::TCP).empty() or getMappingList(PortType::TCP).empty()) {
            JAMI_WARN("We have provisionned mappings but the PUPNP IGD returned an empty list!");
        }
    }

    pruneUnMatchedMappings(igd, remoteMapList);
    pruneUnTrackedMappings(igd, remoteMapList);
}

void
UPnPContext::pruneUnMatchedMappings(const std::shared_ptr<IGD>& igd,
                                    const std::map<Mapping::key_t, Mapping>& remoteMapList)
{
    // Check/synchronize local mapping list with the list
    // returned by the IGD.

    PortType types[2] {PortType::TCP, PortType::UDP};

    for (auto& type : types) {
        // Use a temporary list to avoid processing mappings while holding the lock.
        std::list<Mapping::sharedPtr_t> toRemoveList;
        {
            std::lock_guard<std::mutex> lock(mappingMutex_);
            auto& mappingList = getMappingList(type);
            for (auto const& [_, map] : mappingList) {
                // Only check mappings allocated by UPNP protocol.
                if (map->getProtocol() != NatProtocolType::PUPNP) {
                    continue;
                }
                // Set mapping as failed if not found in the list
                // returned by the IGD.
                if (map->getState() == MappingState::OPEN
                    and remoteMapList.find(map->getMapKey()) == remoteMapList.end()) {
                    toRemoveList.emplace_back(map);

                    JAMI_WARN("Mapping %s (IGD %s) marked as \"OPEN\" but not found in the "
                              "remote list. Mark as failed!",
                              map->toString().c_str(),
                              igd->toString().c_str());
                }
            }
        }

        for (auto const& map : toRemoveList) {
            updateMappingState(map, MappingState::FAILED);
            unregisterMapping(map);
        }
    }
}

void
UPnPContext::pruneUnTrackedMappings(const std::shared_ptr<IGD>& igd,
                                    const std::map<Mapping::key_t, Mapping>& remoteMapList)
{
    // Use a temporary list to avoid processing mappings while holding the lock.
    std::list<Mapping> toRemoveList;
    {
        std::lock_guard<std::mutex> lock(mappingMutex_);

        for (auto const& [_, map] : remoteMapList) {
            // Must has valid IGD pointer and use UPNP protocol.
            assert(map.getIgd());
            assert(map.getIgd()->getProtocol() == NatProtocolType::PUPNP);
            auto& mappingList = getMappingList(map.getType());
            auto it = mappingList.find(map.getMapKey());
            if (it == mappingList.end()) {
                // Not present, request mapping remove.
                toRemoveList.emplace_back(std::move(map));
                // Make only few remove requests at once.
                if (toRemoveList.size() >= MAX_REQUEST_REMOVE_COUNT)
                    break;
            }
        }
    }

    // Remove un-tracked mappings.
    auto protocol = protocolList_.at(NatProtocolType::PUPNP);
    for (auto const& map : toRemoveList) {
        protocol->requestMappingRemove(map);
    }
}

void
UPnPContext::pruneMappingsWithInvalidIgds(const std::shared_ptr<IGD>& igd)
{
    CHECK_VALID_THREAD();

    // Use temporary list to avoid holding the lock while
    // processing the mapping list.
    std::list<Mapping::sharedPtr_t> toRemoveList;
    {
        std::lock_guard<std::mutex> lock(mappingMutex_);

        PortType types[2] {PortType::TCP, PortType::UDP};
        for (auto& type : types) {
            auto& mappingList = getMappingList(type);
            for (auto const& [_, map] : mappingList) {
                if (map->getIgd() == igd)
                    toRemoveList.emplace_back(map);
            }
        }
    }

    for (auto const& map : toRemoveList) {
        JAMI_DBG("Remove mapping %s (has an invalid IGD %s [%s])",
                 map->toString().c_str(),
                 igd->toString().c_str(),
                 igd->getProtocolName());
        updateMappingState(map, MappingState::FAILED);
        unregisterMapping(map);
    }
}

void
UPnPContext::processPendingRequests(const std::shared_ptr<IGD>& igd)
{
    // This list holds the mappings to be requested. This is
    // needed to avoid performing the requests while holding
    // the lock.
    std::list<Mapping::sharedPtr_t> requestsList;

    // Populate the list of requests to perform.
    {
        std::lock_guard<std::mutex> lock(mappingMutex_);
        PortType typeArray[2] {PortType::TCP, PortType::UDP};

        for (auto type : typeArray) {
            auto& mappingList = getMappingList(type);
            for (auto& [_, map] : mappingList) {
                if (map->getState() == MappingState::PENDING) {
                    JAMI_DBG("Send pending request for mapping %s to IGD %s",
                             map->toString().c_str(),
                             igd->toString().c_str());
                    requestsList.emplace_back(map);
                }
            }
        }
    }

    // Process the pending requests.
    for (auto const& map : requestsList) {
        requestMapping(map);
    }
}

void
UPnPContext::processMappingWithAutoUpdate()
{
    // This list holds the mappings to be requested. This is
    // needed to avoid performing the requests while holding
    // the lock.
    std::list<Mapping::sharedPtr_t> requestsList;

    // Populate the list of requests for mappings with auto-update enabled.
    {
        std::lock_guard<std::mutex> lock(mappingMutex_);
        PortType typeArray[2] {PortType::TCP, PortType::UDP};

        for (auto type : typeArray) {
            auto& mappingList = getMappingList(type);
            for (auto const& [_, map] : mappingList) {
                if (map->getState() == MappingState::FAILED and map->getAutoUpdate()) {
                    requestsList.emplace_back(map);
                }
            }
        }
    }

    for (auto const& oldMap : requestsList) {
        // Request a new mapping if auto-update is enabled.
        JAMI_DBG("Mapping %s has auto-update enabled, a new mapping will be requested",
                 oldMap->toString().c_str());

        // Reserve a new mapping.
        Mapping newMapping(oldMap->getType());
        newMapping.enableAutoUpdate(true);
        newMapping.setNotifyCallback(oldMap->getNotifyCallback());

        auto const& mapPtr = reserveMapping(newMapping);
        assert(mapPtr);

        // Release the old one.
        oldMap->setAvailable(true);
        oldMap->enableAutoUpdate(false);
        oldMap->setNotifyCallback(nullptr);
        unregisterMapping(oldMap);
    }
}

void
UPnPContext::onIgdUpdated(const std::shared_ptr<IGD>& igd, UpnpIgdEvent event)
{
    assert(igd);

    if (not isValidThread()) {
        runOnUpnpContextQueue([this, igd, event] { onIgdUpdated(igd, event); });
        return;
    }

    // Reset to start search for a new best IGD.
    preferredIgd_.reset();

    char const* IgdState = event == UpnpIgdEvent::ADDED     ? "ADDED"
                           : event == UpnpIgdEvent::REMOVED ? "REMOVED"
                                                            : "INVALID";

    auto const& igdLocalAddr = igd->getLocalIp();
    auto protocolName = igd->getProtocolName();

    JAMI_DBG("New event for IGD [%s %s] [%s]: [%s]",
             igd->getUID().c_str(),
             igd->toString().c_str(),
             protocolName,
             IgdState);

    // Check if the IGD has valid addresses.
    if (not igdLocalAddr) {
        JAMI_WARN("[%s] IGD has an invalid local address", protocolName);
        return;
    }

    if (not igd->getPublicIp()) {
        JAMI_WARN("[%s] IGD has an invalid public address", protocolName);
        return;
    }

    if (knownPublicAddress_ and igd->getPublicIp() != knownPublicAddress_) {
        JAMI_WARN("[%s] IGD external address [%s] does not match known public address [%s]."
                  " The mapped addresses might not be reachable",
                  protocolName,
                  igd->getPublicIp().toString().c_str(),
                  knownPublicAddress_.toString().c_str());
    }

    // The IGD was removed or is invalid.
    if (event == UpnpIgdEvent::REMOVED or event == UpnpIgdEvent::INVALID_STATE) {
        JAMI_WARN("State of IGD [%s %s] [%s] changed to [%s]. Pruning the mapping list",
                  igd->getUID().c_str(),
                  igd->toString().c_str(),
                  protocolName,
                  IgdState);

        pruneMappingsWithInvalidIgds(igd);

        std::lock_guard<std::mutex> lock(mappingMutex_);
        validIgdList_.erase(igd);
        return;
    }

    // Update the IGD list.
    {
        std::lock_guard<std::mutex> lock(mappingMutex_);
        auto ret = validIgdList_.emplace(igd);
        if (ret.second) {
            JAMI_DBG("IGD [%s] on address %s was added. Will process any pending requests",
                     protocolName,
                     igdLocalAddr.toString(true, true).c_str());
        } else {
            // Already in the list.
            JAMI_ERR("IGD [%s] on address %s already in the list",
                     protocolName,
                     igdLocalAddr.toString(true, true).c_str());
            return;
        }
    }

    // Update the provisionned mappings.
    updateMappingList(false);
}

void
UPnPContext::onMappingAdded(const std::shared_ptr<IGD>& igd, const Mapping& mapRes)
{
    CHECK_VALID_THREAD();

    // Check if we have a pending request for this response.
    auto map = getMappingWithKey(mapRes.getMapKey());
    if (not map) {
        // We may receive a response for a canceled request. Just ignore it.
        JAMI_DBG("Response for mapping %s [IGD %s] [%s] does not have a local match",
                 mapRes.toString().c_str(),
                 igd->toString().c_str(),
                 mapRes.getProtocolName());
        return;
    }

    // The mapping request is new and successful. Update.
    map->setIgd(igd);
    map->setInternalAddress(mapRes.getInternalAddress());
    map->setExternalPort(mapRes.getExternalPort());

    // Update the state and report to the owner.
    updateMappingState(map, MappingState::OPEN);

    JAMI_DBG("Mapping %s (on IGD %s [%s]) successfully performed",
             map->toString().c_str(),
             igd->toString().c_str(),
             map->getProtocolName());

    // Call setValid() to reset the errors counter. We need
    // to reset the counter on each successful response.
    igd->setValid(true);
}

#if HAVE_LIBNATPMP
void
UPnPContext::onMappingRenewed(const std::shared_ptr<IGD>& igd, const Mapping& map)
{
    auto mapPtr = getMappingWithKey(map.getMapKey());

    if (not mapPtr) {
        // We may receive a notification for a canceled request. Ignore it.
        JAMI_WARN("Renewed mapping %s from IGD  %s [%s] does not have a match in local list",
                  map.toString().c_str(),
                  igd->toString().c_str(),
                  map.getProtocolName());
        return;
    }
    if (mapPtr->getProtocol() != NatProtocolType::NAT_PMP or not mapPtr->isValid()
        or mapPtr->getState() != MappingState::OPEN) {
        JAMI_WARN("Renewed mapping %s from IGD %s [%s] is in unexpected state",
                  mapPtr->toString().c_str(),
                  igd->toString().c_str(),
                  mapPtr->getProtocolName());
        return;
    }

    mapPtr->setRenewalTime(map.getRenewalTime());
}
#endif

void
UPnPContext::requestRemoveMapping(const Mapping::sharedPtr_t& map)
{
    CHECK_VALID_THREAD();

    if (not map) {
        JAMI_ERR("Mapping shared pointer is null!");
        return;
    }

    if (not map->isValid()) {
        // Silently ignore if the mapping is invalid
        return;
    }

    auto protocol = protocolList_.at(map->getIgd()->getProtocol());
    protocol->requestMappingRemove(*map);
}

void
UPnPContext::deleteAllMappings(PortType type)
{
    if (not isValidThread()) {
        runOnUpnpContextQueue([this, type] { deleteAllMappings(type); });
        return;
    }

    std::lock_guard<std::mutex> lock(mappingMutex_);
    auto& mappingList = getMappingList(type);

    for (auto const& [_, map] : mappingList) {
        requestRemoveMapping(map);
    }
}

void
UPnPContext::onMappingRemoved(const std::shared_ptr<IGD>& igd, const Mapping& mapRes)
{
    if (not mapRes.isValid())
        return;

    if (not isValidThread()) {
        runOnUpnpContextQueue([this, igd, mapRes] { onMappingRemoved(igd, mapRes); });
        return;
    }

    auto map = getMappingWithKey(mapRes.getMapKey());
    // Notify the listener.
    if (map and map->getNotifyCallback())
        map->getNotifyCallback()(map);
}

Mapping::sharedPtr_t
UPnPContext::registerMapping(Mapping& map)
{
    if (map.getExternalPort() == 0) {
        JAMI_DBG("Port number not set. Will set a random port number");
        auto port = getAvailablePortNumber(map.getType());
        map.setExternalPort(port);
        map.setInternalPort(port);
    }

    // Newly added mapping must be in pending state by default.
    map.setState(MappingState::PENDING);

    Mapping::sharedPtr_t mapPtr;

    {
        std::lock_guard<std::mutex> lock(mappingMutex_);
        auto& mappingList = getMappingList(map.getType());

        auto ret = mappingList.emplace(map.getMapKey(), std::make_shared<Mapping>(map));
        if (not ret.second) {
            JAMI_WARN("Mapping request for %s already added!", map.toString().c_str());
            return {};
        }
        mapPtr = ret.first->second;
        assert(mapPtr);
    }

    // No available IGD. The pending mapping requests will be processed
    // when a IGD becomes available (in onIgdAdded() method).
    if (not isReady()) {
        JAMI_WARN("No IGD available. Mapping will be requested when an IGD becomes available");
    } else {
        requestMapping(mapPtr);
    }

    return mapPtr;
}

std::map<Mapping::key_t, Mapping::sharedPtr_t>::iterator
UPnPContext::unregisterMapping(std::map<Mapping::key_t, Mapping::sharedPtr_t>::iterator it)
{
    assert(it->second);

    CHECK_VALID_THREAD();
    auto descr = it->second->toString();
    auto& mappingList = getMappingList(it->second->getType());
    auto ret = mappingList.erase(it);

    return ret;
}

void
UPnPContext::unregisterMapping(const Mapping::sharedPtr_t& map)
{
    CHECK_VALID_THREAD();

    if (not map) {
        JAMI_ERR("Mapping pointer is null");
        return;
    }

    if (map->getAutoUpdate()) {
        // Dont unregister mappings with auto-update enabled.
        return;
    }
    auto& mappingList = getMappingList(map->getType());

    if (mappingList.erase(map->getMapKey()) == 1) {
        JAMI_DBG("Unregistered mapping %s", map->toString().c_str());
    } else {
        // The mapping may already be un-registered. Just ignore it.
        JAMI_DBG("Mapping %s [%s] does not have a local match",
                 map->toString().c_str(),
                 map->getProtocolName());
    }
}

std::map<Mapping::key_t, Mapping::sharedPtr_t>&
UPnPContext::getMappingList(PortType type)
{
    unsigned typeIdx = type == PortType::TCP ? 0 : 1;
    return mappingList_[typeIdx];
}

Mapping::sharedPtr_t
UPnPContext::getMappingWithKey(Mapping::key_t key)
{
    std::lock_guard<std::mutex> lock(mappingMutex_);
    auto const& mappingList = getMappingList(Mapping::getTypeFromMapKey(key));
    auto it = mappingList.find(key);
    if (it == mappingList.end())
        return nullptr;
    return it->second;
}

void
UPnPContext::getMappingStatus(PortType type, MappingStatus& status)
{
    std::lock_guard<std::mutex> lock(mappingMutex_);
    auto& mappingList = getMappingList(type);

    for (auto const& [_, map] : mappingList) {
        switch (map->getState()) {
        case MappingState::PENDING: {
            status.pendingCount_++;
            break;
        }
        case MappingState::IN_PROGRESS: {
            status.inProgressCount_++;
            break;
        }
        case MappingState::FAILED: {
            status.failedCount_++;
            break;
        }
        case MappingState::OPEN: {
            status.openCount_++;
            if (map->isAvailable())
                status.readyCount_++;
            break;
        }

        default:
            // Must not get here.
            assert(false);
            break;
        }
    }
}

void
UPnPContext::getMappingStatus(MappingStatus& status)
{
    getMappingStatus(PortType::TCP, status);
    getMappingStatus(PortType::UDP, status);
}

void
UPnPContext::onMappingRequestFailed(const Mapping& mapRes)
{
    CHECK_VALID_THREAD();

    auto const& map = getMappingWithKey(mapRes.getMapKey());
    if (not map) {
        // We may receive a response for a removed request. Just ignore it.
        JAMI_DBG("Mapping %s [IGD %s] does not have a local match",
                 mapRes.toString().c_str(),
                 mapRes.getProtocolName());
        return;
    }

    auto igd = map->getIgd();
    if (not igd) {
        JAMI_ERR("IGD pointer is null");
        return;
    }

    updateMappingState(map, MappingState::FAILED);
    unregisterMapping(map);

    JAMI_WARN("Mapping request for %s failed on IGD %s [%s]",
              map->toString().c_str(),
              igd->toString().c_str(),
              igd->getProtocolName());
}

void
UPnPContext::updateMappingState(const Mapping::sharedPtr_t& map, MappingState newState, bool notify)
{
    CHECK_VALID_THREAD();

    assert(map);

    // Ignore if the state did not change.
    if (newState == map->getState()) {
        JAMI_DBG("Mapping %s already in state %s", map->toString().c_str(), map->getStateStr());
        return;
    }

    // Update the state.
    map->setState(newState);

    // Notify the listener if set.
    if (notify and map->getNotifyCallback())
        map->getNotifyCallback()(map);
}

#if HAVE_LIBNATPMP
void
UPnPContext::renewAllocations()
{
    CHECK_VALID_THREAD();

    // Check if the we have valid PMP IGD.
    auto pmpProto = protocolList_.at(NatProtocolType::NAT_PMP);

    auto now = sys_clock::now();
    std::vector<Mapping::sharedPtr_t> toRenew;

    for (auto type : {PortType::TCP, PortType::UDP}) {
        std::lock_guard<std::mutex> lock(mappingMutex_);
        auto mappingList = getMappingList(type);
        for (auto const& [_, map] : mappingList) {
            if (not map->isValid())
                continue;
            if (map->getProtocol() != NatProtocolType::NAT_PMP)
                continue;
            if (map->getState() != MappingState::OPEN)
                continue;
            if (now < map->getRenewalTime())
                continue;

            toRenew.emplace_back(map);
        }
    }

    // Quit if there are no mapping to renew
    if (toRenew.empty())
        return;

    for (auto const& map : toRenew) {
        pmpProto->requestMappingRenew(*map);
    }
}
#endif

} // namespace upnp
} // namespace jami
