/*
 *  Copyright (C) 2004-2023 Savoir-faire Linux Inc.
 *
 *  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, see <https://www.gnu.org/licenses/>.
 */
#include "nat_pmp.h"

#if HAVE_LIBNATPMP

namespace dhtnet {
namespace upnp {

NatPmp::NatPmp()
{
    // JAMI_DBG("NAT-PMP: Instance [%p] created", this);
    runOnNatPmpQueue([this] {
        threadId_ = getCurrentThread();
        igd_ = std::make_shared<PMPIGD>();
    });
}

NatPmp::~NatPmp()
{
    // JAMI_DBG("NAT-PMP: Instance [%p] destroyed", this);
}

void
NatPmp::initNatPmp()
{
    if (not isValidThread()) {
        runOnNatPmpQueue([w = weak()] {
            if (auto pmpThis = w.lock()) {
                pmpThis->initNatPmp();
            }
        });
        return;
    }

    initialized_ = false;

    {
        std::lock_guard<std::mutex> lock(natpmpMutex_);
        hostAddress_ = ip_utils::getLocalAddr(AF_INET);
    }

    // Local address must be valid.
    if (not getHostAddress() or getHostAddress().isLoopback()) {
        // JAMI_WARN("NAT-PMP: Does not have a valid local address!");
        return;
    }

    assert(igd_);
    if (igd_->isValid()) {
        igd_->setValid(false);
        processIgdUpdate(UpnpIgdEvent::REMOVED);
    }

    igd_->setLocalIp(IpAddr());
    igd_->setPublicIp(IpAddr());
    igd_->setUID("");

    // JAMI_DBG("NAT-PMP: Trying to initialize IGD");

    int err = initnatpmp(&natpmpHdl_, 0, 0);

    if (err < 0) {
        // JAMI_WARN("NAT-PMP: Initializing IGD using default gateway failed!");
        const auto& localGw = ip_utils::getLocalGateway();
        if (not localGw) {
            // JAMI_WARN("NAT-PMP: Couldn't find valid gateway on local host");
            err = NATPMP_ERR_CANNOTGETGATEWAY;
        } else {
            // JAMI_WARN("NAT-PMP: Trying to initialize using detected gateway %s",
                      localGw.toString().c_str());

            struct in_addr inaddr;
            inet_pton(AF_INET, localGw.toString().c_str(), &inaddr);
            err = initnatpmp(&natpmpHdl_, 1, inaddr.s_addr);
        }
    }

    if (err < 0) {
        // JAMI_ERR("NAT-PMP: Can't initialize libnatpmp -> %s", getNatPmpErrorStr(err));
        return;
    }

    char addrbuf[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &natpmpHdl_.gateway, addrbuf, sizeof(addrbuf));
    IpAddr igdAddr(addrbuf);
    // JAMI_DBG("NAT-PMP: Initialized on gateway %s", igdAddr.toString().c_str());

    // Set the local (gateway) address.
    igd_->setLocalIp(igdAddr);
    // NAT-PMP protocol does not have UID, but we will set generic
    // one debugging purposes.
    igd_->setUID("NAT-PMP Gateway");

    // Search and set the public address.
    getIgdPublicAddress();

    // Update and notify.
    if (igd_->isValid()) {
        initialized_ = true;
        processIgdUpdate(UpnpIgdEvent::ADDED);
    };
}

void
NatPmp::setObserver(UpnpMappingObserver* obs)
{
    if (not isValidThread()) {
        runOnNatPmpQueue([w = weak(), obs] {
            if (auto pmpThis = w.lock()) {
                pmpThis->setObserver(obs);
            }
        });
        return;
    }

    // JAMI_DBG("NAT-PMP: Setting observer to %p", obs);

    observer_ = obs;
}

void
NatPmp::terminate(std::condition_variable& cv)
{
    initialized_ = false;
    observer_ = nullptr;

    {
        std::lock_guard<std::mutex> lock(natpmpMutex_);
        shutdownComplete_ = true;
        cv.notify_one();
    }
}

void
NatPmp::terminate()
{
    std::unique_lock<std::mutex> lk(natpmpMutex_);
    std::condition_variable cv {};

    runOnNatPmpQueue([w = weak(), &cv = cv] {
        if (auto pmpThis = w.lock()) {
            pmpThis->terminate(cv);
        }
    });

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

const IpAddr
NatPmp::getHostAddress() const
{
    std::lock_guard<std::mutex> lock(natpmpMutex_);
    return hostAddress_;
}

void
NatPmp::clearIgds()
{
    if (not isValidThread()) {
        runOnNatPmpQueue([w = weak()] {
            if (auto pmpThis = w.lock()) {
                pmpThis->clearIgds();
            }
        });
        return;
    }

    bool do_close = false;

    if (igd_) {
        if (igd_->isValid()) {
            do_close = true;
        }
        igd_->setValid(false);
    }

    initialized_ = false;
    if (searchForIgdTimer_)
        searchForIgdTimer_->cancel();

    igdSearchCounter_ = 0;

    if (do_close) {
        closenatpmp(&natpmpHdl_);
        memset(&natpmpHdl_, 0, sizeof(natpmpHdl_));
    }
}

void
NatPmp::searchForIgd()
{
    if (not isValidThread()) {
        runOnNatPmpQueue([w = weak()] {
            if (auto pmpThis = w.lock()) {
                pmpThis->searchForIgd();
            }
        });
        return;
    }

    if (not initialized_) {
        initNatPmp();
    }

    // Schedule a retry in case init failed.
    if (not initialized_) {
        if (igdSearchCounter_++ < MAX_RESTART_SEARCH_RETRIES) {
            // JAMI_DBG("NAT-PMP: Start search for IGDs. Attempt %i", igdSearchCounter_);

            // Cancel the current timer (if any) and re-schedule.
            if (searchForIgdTimer_)
                searchForIgdTimer_->cancel();

            searchForIgdTimer_ = getNatpmpScheduler()->scheduleIn([this] { searchForIgd(); },
                                                                  NATPMP_SEARCH_RETRY_UNIT
                                                                      * igdSearchCounter_);
        } else {
            // JAMI_WARN("NAT-PMP: Setup failed after %u trials. NAT-PMP will be disabled!",
            //           MAX_RESTART_SEARCH_RETRIES);
        }
    }
}

std::list<std::shared_ptr<IGD>>
NatPmp::getIgdList() const
{
    std::lock_guard<std::mutex> lock(natpmpMutex_);
    std::list<std::shared_ptr<IGD>> igdList;
    if (igd_->isValid())
        igdList.emplace_back(igd_);
    return igdList;
}

bool
NatPmp::isReady() const
{
    if (observer_ == nullptr) {
        // JAMI_ERR("NAT-PMP: the observer is not set!");
        return false;
    }

    // Must at least have a valid local address.
    if (not getHostAddress() or getHostAddress().isLoopback())
        return false;

    return igd_ and igd_->isValid();
}

void
NatPmp::incrementErrorsCounter(const std::shared_ptr<IGD>& igdIn)
{
    if (not validIgdInstance(igdIn)) {
        return;
    }

    if (not igd_->isValid()) {
        // Already invalid. Nothing to do.
        return;
    }

    if (not igd_->incrementErrorsCounter()) {
        // Disable this IGD.
        igd_->setValid(false);
        // Notify the listener.
        // JAMI_WARN("NAT-PMP: No more valid IGD!");

        processIgdUpdate(UpnpIgdEvent::INVALID_STATE);
    }
}

void
NatPmp::requestMappingAdd(const Mapping& mapping)
{
    // Process on nat-pmp thread.
    if (not isValidThread()) {
        runOnNatPmpQueue([w = weak(), mapping] {
            if (auto pmpThis = w.lock()) {
                pmpThis->requestMappingAdd(mapping);
            }
        });
        return;
    }

    Mapping map(mapping);
    assert(map.getIgd());
    auto err = addPortMapping(map);
    if (err < 0) {
        // JAMI_WARN("NAT-PMP: Request for mapping %s on %s failed with error %i: %s",
        //           map.toString().c_str(),
        //           igd_->toString().c_str(),
        //           err,
        //           getNatPmpErrorStr(err));

        if (isErrorFatal(err)) {
            // Fatal error, increment the counter.
            incrementErrorsCounter(igd_);
        }
        // Notify the listener.
        processMappingRequestFailed(std::move(map));
    } else {
        // JAMI_DBG("NAT-PMP: Request for mapping %s on %s succeeded",
        //          map.toString().c_str(),
        //          igd_->toString().c_str());
        // Notify the listener.
        processMappingAdded(std::move(map));
    }
}

void
NatPmp::requestMappingRenew(const Mapping& mapping)
{
    // Process on nat-pmp thread.
    if (not isValidThread()) {
        runOnNatPmpQueue([w = weak(), mapping] {
            if (auto pmpThis = w.lock()) {
                pmpThis->requestMappingRenew(mapping);
            }
        });
        return;
    }

    Mapping map(mapping);
    auto err = addPortMapping(map);
    if (err < 0) {
        // JAMI_WARN("NAT-PMP: Renewal request for mapping %s on %s failed with error %i: %s",
        //           map.toString().c_str(),
        //           igd_->toString().c_str(),
        //           err,
        //           getNatPmpErrorStr(err));
        // Notify the listener.
        processMappingRequestFailed(std::move(map));

        if (isErrorFatal(err)) {
            // Fatal error, increment the counter.
            incrementErrorsCounter(igd_);
        }
    } else {
        // JAMI_DBG("NAT-PMP: Renewal request for mapping %s on %s succeeded",
        //          map.toString().c_str(),
        //          igd_->toString().c_str());
        // Notify the listener.
        processMappingRenewed(map);
    }
}

int
NatPmp::readResponse(natpmp_t& handle, natpmpresp_t& response)
{
    int err = 0;
    unsigned readRetriesCounter = 0;

    while (true) {
        if (readRetriesCounter++ > MAX_READ_RETRIES) {
            err = NATPMP_ERR_SOCKETERROR;
            break;
        }

        fd_set fds;
        struct timeval timeout;
        FD_ZERO(&fds);
        FD_SET(handle.s, &fds);
        getnatpmprequesttimeout(&handle, &timeout);
        // Wait for data.
        if (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == -1) {
            err = NATPMP_ERR_SOCKETERROR;
            break;
        }

        // Read the data.
        err = readnatpmpresponseorretry(&handle, &response);

        if (err == NATPMP_TRYAGAIN) {
            std::this_thread::sleep_for(std::chrono::milliseconds(TIMEOUT_BEFORE_READ_RETRY));
        } else {
            break;
        }
    }

    return err;
}

int
NatPmp::sendMappingRequest(const Mapping& mapping, uint32_t& lifetime)
{
    CHECK_VALID_THREAD();

    int err = sendnewportmappingrequest(&natpmpHdl_,
                                        mapping.getType() == PortType::UDP ? NATPMP_PROTOCOL_UDP
                                                                           : NATPMP_PROTOCOL_TCP,
                                        mapping.getInternalPort(),
                                        mapping.getExternalPort(),
                                        lifetime);

    if (err < 0) {
        // JAMI_ERR("NAT-PMP: Send mapping request failed with error %s %i",
                //  getNatPmpErrorStr(err),
                //  errno);
        return err;
    }

    unsigned readRetriesCounter = 0;

    while (readRetriesCounter++ < MAX_READ_RETRIES) {
        // Read the response
        natpmpresp_t response;
        err = readResponse(natpmpHdl_, response);

        if (err < 0) {
            // JAMI_WARN("NAT-PMP: Read response on IGD %s failed with error %s",
            //           igd_->toString().c_str(),
            //           getNatPmpErrorStr(err));
        } else if (response.type != NATPMP_RESPTYPE_TCPPORTMAPPING
                   and response.type != NATPMP_RESPTYPE_UDPPORTMAPPING) {
            // JAMI_ERR("NAT-PMP: Unexpected response type (%i) for mapping %s from IGD %s.",
            //          response.type,
            //          mapping.toString().c_str(),
            //          igd_->toString().c_str());
            // Try to read again.
            continue;
        }

        lifetime = response.pnu.newportmapping.lifetime;
        // Done.
        break;
    }

    return err;
}

int
NatPmp::addPortMapping(Mapping& mapping)
{
    auto const& igdIn = mapping.getIgd();
    assert(igdIn);
    assert(igdIn->getProtocol() == NatProtocolType::NAT_PMP);

    if (not igdIn->isValid() or not validIgdInstance(igdIn)) {
        mapping.setState(MappingState::FAILED);
        return NATPMP_ERR_INVALIDARGS;
    }

    mapping.setInternalAddress(getHostAddress().toString());

    uint32_t lifetime = MAPPING_ALLOCATION_LIFETIME;
    int err = sendMappingRequest(mapping, lifetime);

    if (err < 0) {
        mapping.setState(MappingState::FAILED);
        return err;
    }

    // Set the renewal time and update.
    mapping.setRenewalTime(sys_clock::now() + std::chrono::seconds(lifetime * 4 / 5));
    mapping.setState(MappingState::OPEN);

    return 0;
}

void
NatPmp::requestMappingRemove(const Mapping& mapping)
{
    // Process on nat-pmp thread.
    if (not isValidThread()) {
        runOnNatPmpQueue([w = weak(), mapping] {
            if (auto pmpThis = w.lock()) {
                Mapping map {mapping};
                pmpThis->removePortMapping(map);
            }
        });
        return;
    }
}

void
NatPmp::removePortMapping(Mapping& mapping)
{
    auto igdIn = mapping.getIgd();
    assert(igdIn);
    if (not igdIn->isValid()) {
        return;
    }

    if (not validIgdInstance(igdIn)) {
        return;
    }

    Mapping mapToRemove(mapping);

    uint32_t lifetime = 0;
    int err = sendMappingRequest(mapping, lifetime);

    if (err < 0) {
        // Nothing to do if the request fails, just log the error.
        // JAMI_WARN("NAT-PMP: Send remove request failed with error %s. Ignoring",
        //           getNatPmpErrorStr(err));
    }

    // Update and notify the listener.
    mapToRemove.setState(MappingState::FAILED);
    processMappingRemoved(std::move(mapToRemove));
}

void
NatPmp::getIgdPublicAddress()
{
    CHECK_VALID_THREAD();

    // Set the public address for this IGD if it does not
    // have one already.
    if (igd_->getPublicIp()) {
        // JAMI_WARN("NAT-PMP: IGD %s already have a public address (%s)",
        //           igd_->toString().c_str(),
        //           igd_->getPublicIp().toString().c_str());
        return;
    }
    assert(igd_->getProtocol() == NatProtocolType::NAT_PMP);

    int err = sendpublicaddressrequest(&natpmpHdl_);

    if (err < 0) {
        // JAMI_ERR("NAT-PMP: send public address request on IGD %s failed with error: %s",
        //          igd_->toString().c_str(),
        //          getNatPmpErrorStr(err));

        if (isErrorFatal(err)) {
            // Fatal error, increment the counter.
            incrementErrorsCounter(igd_);
        }
        return;
    }

    natpmpresp_t response;
    err = readResponse(natpmpHdl_, response);

    if (err < 0) {
        // JAMI_WARN("NAT-PMP: Read response on IGD %s failed - %s",
        //           igd_->toString().c_str(),
        //           getNatPmpErrorStr(err));
        return;
    }

    if (response.type != NATPMP_RESPTYPE_PUBLICADDRESS) {
        // JAMI_ERR("NAT-PMP: Unexpected response type (%i) for public address request from IGD %s.",
        //          response.type,
        //          igd_->toString().c_str());
        return;
    }

    IpAddr publicAddr(response.pnu.publicaddress.addr);

    if (not publicAddr) {
        // JAMI_ERR("NAT-PMP: IGD %s returned an invalid public address %s",
        //          igd_->toString().c_str(),
        //          publicAddr.toString().c_str());
    }

    // Update.
    igd_->setPublicIp(publicAddr);
    igd_->setValid(true);

    // JAMI_DBG("NAT-PMP: Setting IGD %s public address to %s",
    //          igd_->toString().c_str(),
    //          igd_->getPublicIp().toString().c_str());
}

void
NatPmp::removeAllMappings()
{
    CHECK_VALID_THREAD();

    // JAMI_WARN("NAT-PMP: Send request to close all existing mappings to IGD %s",
    //           igd_->toString().c_str());

    int err = sendnewportmappingrequest(&natpmpHdl_, NATPMP_PROTOCOL_TCP, 0, 0, 0);
    if (err < 0) {
        // JAMI_WARN("NAT-PMP: Send close all TCP mappings request failed with error %s",
        //           getNatPmpErrorStr(err));
    }
    err = sendnewportmappingrequest(&natpmpHdl_, NATPMP_PROTOCOL_UDP, 0, 0, 0);
    if (err < 0) {
        // JAMI_WARN("NAT-PMP: Send close all UDP mappings request failed with error %s",
        //           getNatPmpErrorStr(err));
    }
}

const char*
NatPmp::getNatPmpErrorStr(int errorCode) const
{
#ifdef ENABLE_STRNATPMPERR
    return strnatpmperr(errorCode);
#else
    switch (errorCode) {
    case NATPMP_ERR_INVALIDARGS:
        return "INVALIDARGS";
        break;
    case NATPMP_ERR_SOCKETERROR:
        return "SOCKETERROR";
        break;
    case NATPMP_ERR_CANNOTGETGATEWAY:
        return "CANNOTGETGATEWAY";
        break;
    case NATPMP_ERR_CLOSEERR:
        return "CLOSEERR";
        break;
    case NATPMP_ERR_RECVFROM:
        return "RECVFROM";
        break;
    case NATPMP_ERR_NOPENDINGREQ:
        return "NOPENDINGREQ";
        break;
    case NATPMP_ERR_NOGATEWAYSUPPORT:
        return "NOGATEWAYSUPPORT";
        break;
    case NATPMP_ERR_CONNECTERR:
        return "CONNECTERR";
        break;
    case NATPMP_ERR_WRONGPACKETSOURCE:
        return "WRONGPACKETSOURCE";
        break;
    case NATPMP_ERR_SENDERR:
        return "SENDERR";
        break;
    case NATPMP_ERR_FCNTLERROR:
        return "FCNTLERROR";
        break;
    case NATPMP_ERR_GETTIMEOFDAYERR:
        return "GETTIMEOFDAYERR";
        break;
    case NATPMP_ERR_UNSUPPORTEDVERSION:
        return "UNSUPPORTEDVERSION";
        break;
    case NATPMP_ERR_UNSUPPORTEDOPCODE:
        return "UNSUPPORTEDOPCODE";
        break;
    case NATPMP_ERR_UNDEFINEDERROR:
        return "UNDEFINEDERROR";
        break;
    case NATPMP_ERR_NOTAUTHORIZED:
        return "NOTAUTHORIZED";
        break;
    case NATPMP_ERR_NETWORKFAILURE:
        return "NETWORKFAILURE";
        break;
    case NATPMP_ERR_OUTOFRESOURCES:
        return "OUTOFRESOURCES";
        break;
    case NATPMP_TRYAGAIN:
        return "TRYAGAIN";
        break;
    default:
        return "UNKNOWNERR";
        break;
    }
#endif
}

bool
NatPmp::isErrorFatal(int error)
{
    switch (error) {
    case NATPMP_ERR_INVALIDARGS:
    case NATPMP_ERR_SOCKETERROR:
    case NATPMP_ERR_CANNOTGETGATEWAY:
    case NATPMP_ERR_CLOSEERR:
    case NATPMP_ERR_RECVFROM:
    case NATPMP_ERR_NOGATEWAYSUPPORT:
    case NATPMP_ERR_CONNECTERR:
    case NATPMP_ERR_SENDERR:
    case NATPMP_ERR_UNDEFINEDERROR:
    case NATPMP_ERR_UNSUPPORTEDVERSION:
    case NATPMP_ERR_UNSUPPORTEDOPCODE:
    case NATPMP_ERR_NOTAUTHORIZED:
    case NATPMP_ERR_NETWORKFAILURE:
    case NATPMP_ERR_OUTOFRESOURCES:
        return true;
    default:
        return false;
    }
}

bool
NatPmp::validIgdInstance(const std::shared_ptr<IGD>& igdIn)
{
    if (igd_.get() != igdIn.get()) {
        // JAMI_ERR("NAT-PMP: IGD (%s) does not match local instance (%s)",
        //          igdIn->toString().c_str(),
        //          igd_->toString().c_str());
        return false;
    }

    return true;
}

void
NatPmp::processIgdUpdate(UpnpIgdEvent event)
{
    if (igd_->isValid()) {
        // Remove all current mappings if any.
        removeAllMappings();
    }

    if (observer_ == nullptr)
        return;
    // Process the response on the context thread.
    runOnUpnpContextQueue([obs = observer_, igd = igd_, event] { obs->onIgdUpdated(igd, event); });
}

void
NatPmp::processMappingAdded(const Mapping& map)
{
    if (observer_ == nullptr)
        return;

    // Process the response on the context thread.
    runOnUpnpContextQueue([obs = observer_, igd = igd_, map] { obs->onMappingAdded(igd, map); });
}

void
NatPmp::processMappingRequestFailed(const Mapping& map)
{
    if (observer_ == nullptr)
        return;

    // Process the response on the context thread.
    runOnUpnpContextQueue([obs = observer_, igd = igd_, map] { obs->onMappingRequestFailed(map); });
}

void
NatPmp::processMappingRenewed(const Mapping& map)
{
    if (observer_ == nullptr)
        return;

    // Process the response on the context thread.
    runOnUpnpContextQueue([obs = observer_, igd = igd_, map] { obs->onMappingRenewed(igd, map); });
}

void
NatPmp::processMappingRemoved(const Mapping& map)
{
    if (observer_ == nullptr)
        return;

    // Process the response on the context thread.
    runOnUpnpContextQueue([obs = observer_, igd = igd_, map] { obs->onMappingRemoved(igd, map); });
}

} // namespace upnp
} // namespace dhtnet

#endif //-- #if HAVE_LIBNATPMP
