/*
 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * 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.
 *    * Neither the name of The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
 */
#ifndef DBG
    #define DBG true
#endif /* DBG */
#define LOG_TAG "IPAHALService"

/* HIDL Includes */
#include <hwbinder/IPCThreadState.h>
#include <hwbinder/ProcessState.h>

/* Kernel Includes */
#include <linux/netfilter/nfnetlink_compat.h>

/* External Includes */
#include <cutils/log.h>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <vector>

/* Internal Includes */
#include "HAL.h"
#include "LocalLogBuffer.h"
#include "PrefixParser.h"

/* Namespace pollution avoidance */
using ::android::hardware::Void;
using ::android::status_t;

using RET = ::IOffloadManager::RET;
using Prefix = ::IOffloadManager::Prefix;

using ::std::map;
using ::std::vector;


/* ------------------------------ PUBLIC ------------------------------------ */
HAL* HAL::makeIPAHAL(int version, IOffloadManager* mgr) {
    if (DBG)
        ALOGI("makeIPAHAL(%d, %s)", version,
                (mgr != nullptr) ? "provided" : "null");
    if (nullptr == mgr) return NULL;
    else if (version != 1) return NULL;
    HAL* ret = new HAL(mgr);
    if (nullptr == ret) return NULL;
    configureRpcThreadpool(1, false);
    ret->registerAsSystemService();
    return ret;
} /* makeIPAHAL */


/* ------------------------------ PRIVATE ----------------------------------- */
HAL::HAL(IOffloadManager* mgr) : mLogs("HAL Function Calls", 100) {
    mIPA = mgr;
    mCb.clear();
    mCbIpa = nullptr;
    mCbCt = nullptr;
} /* HAL */

void HAL::registerAsSystemService() {
    status_t ret = 0;

    ret = IOffloadControl::registerAsService();
    if (ret != 0) ALOGE("Failed to register IOffloadControl (%d)", ret);
    else if (DBG) {
        ALOGI("Successfully registered IOffloadControl");
    }

    IOffloadConfig::registerAsService();
    if (ret != 0) ALOGE("Failed to register IOffloadConfig (%d)", ret);
    else if (DBG) {
        ALOGI("Successfully registered IOffloadConfig");
    }
} /* registerAsSystemService */

void HAL::doLogcatDump() {
    ALOGD("mHandles");
    ALOGD("========");
    /* @TODO This will segfault if they aren't initialized and I don't currently
     * care to check for initialization in a function that isn't used anyways
     * ALOGD("fd1->%d", mHandle1->data[0]);
     * ALOGD("fd2->%d", mHandle2->data[0]);
     */
    ALOGD("========");
} /* doLogcatDump */

HAL::BoolResult HAL::makeInputCheckFailure(string customErr) {
    BoolResult ret;
    ret.success = false;
    ret.errMsg = "Failed Input Checks: " + customErr;
    return ret;
} /* makeInputCheckFailure */

HAL::BoolResult HAL::ipaResultToBoolResult(RET in) {
    BoolResult ret;
    ret.success = (in >= RET::SUCCESS);
    switch (in) {
        case RET::FAIL_TOO_MANY_PREFIXES:
            ret.errMsg = "Too Many Prefixes Provided";
            break;
        case RET::FAIL_UNSUPPORTED:
            ret.errMsg = "Unsupported by Hardware";
            break;
        case RET::FAIL_INPUT_CHECK:
            ret.errMsg = "Failed Input Checks";
            break;
        case RET::FAIL_HARDWARE:
            ret.errMsg = "Hardware did not accept";
            break;
        case RET::FAIL_TRY_AGAIN:
            ret.errMsg = "Try Again";
            break;
        case RET::SUCCESS:
            ret.errMsg = "Successful";
            break;
        case RET::SUCCESS_DUPLICATE_CONFIG:
            ret.errMsg = "Successful: Was a duplicate configuration";
            break;
        case RET::SUCCESS_NO_OP:
            ret.errMsg = "Successful: No action needed";
            break;
        case RET::SUCCESS_OPTIMIZED:
            ret.errMsg = "Successful: Performed optimized version of action";
            break;
        default:
            ret.errMsg = "Unknown Error";
            break;
    }
    return ret;
} /* ipaResultToBoolResult */

/* This will likely always result in doubling the number of loops the execution
 * goes through.  Obviously that is suboptimal.  But if we first translate
 * away from all HIDL specific code, then we can avoid sprinkling HIDL
 * dependencies everywhere.
 */
vector<string> HAL::convertHidlStrToStdStr(hidl_vec<hidl_string> in) {
    vector<string> ret;
    for (size_t i = 0; i < in.size(); i++) {
        string add = in[i];
        ret.push_back(add);
    }
    return ret;
} /* convertHidlStrToStdStr */

void HAL::registerEventListeners() {
    registerIpaCb();
    registerCtCb();
} /* registerEventListeners */

void HAL::registerIpaCb() {
    if (isInitialized() && mCbIpa == nullptr) {
        LocalLogBuffer::FunctionLog fl("registerEventListener");
        mCbIpa = new IpaEventRelay(mCb);
        mIPA->registerEventListener(mCbIpa);
        mLogs.addLog(fl);
    } else {
        ALOGE("Failed to registerIpaCb (isInitialized()=%s, (mCbIpa == nullptr)=%s)",
                isInitialized() ? "true" : "false",
                (mCbIpa == nullptr) ? "true" : "false");
    }
} /* registerIpaCb */

void HAL::registerCtCb() {
    if (isInitialized() && mCbCt == nullptr) {
        LocalLogBuffer::FunctionLog fl("registerCtTimeoutUpdater");
        mCbCt = new CtUpdateAmbassador(mCb);
        mIPA->registerCtTimeoutUpdater(mCbCt);
        mLogs.addLog(fl);
    } else {
        ALOGE("Failed to registerCtCb (isInitialized()=%s, (mCbCt == nullptr)=%s)",
                isInitialized() ? "true" : "false",
                (mCbCt == nullptr) ? "true" : "false");
    }
} /* registerCtCb */

void HAL::unregisterEventListeners() {
    unregisterIpaCb();
    unregisterCtCb();
} /* unregisterEventListeners */

void HAL::unregisterIpaCb() {
    if (mCbIpa != nullptr) {
        LocalLogBuffer::FunctionLog fl("unregisterEventListener");
        mIPA->unregisterEventListener(mCbIpa);
        mCbIpa = nullptr;
        mLogs.addLog(fl);
    } else {
        ALOGE("Failed to unregisterIpaCb");
    }
} /* unregisterIpaCb */

void HAL::unregisterCtCb() {
    if (mCbCt != nullptr) {
        LocalLogBuffer::FunctionLog fl("unregisterCtTimeoutUpdater");
        mIPA->unregisterCtTimeoutUpdater(mCbCt);
        mCbCt = nullptr;
        mLogs.addLog(fl);
    } else {
        ALOGE("Failed to unregisterCtCb");
    }
} /* unregisterCtCb */

void HAL::clearHandles() {
    ALOGI("clearHandles()");
    /* @TODO handle this more gracefully... also remove the log
     *
     * Things that would be nice, but I can't do:
     * [1] Destroy the object (it's on the stack)
     * [2] Call freeHandle (it's private)
     *
     * Things I can do but are hacks:
     * [1] Look at code and notice that setTo immediately calls freeHandle
     */
    mHandle1.setTo(nullptr, true);
    mHandle2.setTo(nullptr, true);
} /* clearHandles */

bool HAL::isInitialized() {
    return mCb.get() != nullptr;
} /* isInitialized */


/* -------------------------- IOffloadConfig -------------------------------- */
Return<void> HAL::setHandles(
    const hidl_handle &fd1,
    const hidl_handle &fd2,
    setHandles_cb hidl_cb
) {
    LocalLogBuffer::FunctionLog fl(__func__);

    if (fd1->numFds != 1) {
        BoolResult res = makeInputCheckFailure("Must provide exactly one FD per handle (fd1)");
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);

        mLogs.addLog(fl);
        return Void();
    }

    if (fd2->numFds != 1) {
        BoolResult res = makeInputCheckFailure("Must provide exactly one FD per handle (fd2)");
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);

        mLogs.addLog(fl);
        return Void();
    }

    /* The = operator calls freeHandle internally.  Therefore, if we were using
     * these handles previously, they're now gone... forever.  But hopefully the
     * new ones kick in very quickly.
     *
     * After freeing anything previously held, it will dup the FD so we have our
     * own copy.
     */
    mHandle1 = fd1;
    mHandle2 = fd2;

    /* Log the DUPed FD instead of the actual input FD so that we can lookup
     * this value in ls -l /proc/<pid>/<fd>
     */
    fl.addArg("fd1", mHandle1->data[0]);
    fl.addArg("fd2", mHandle2->data[0]);

    /* Try to provide each handle to IPACM.  Destroy our DUPed hidl_handles if
     * IPACM does not like either input.  This keeps us from leaking FDs or
     * providing half solutions.
     *
     * @TODO unfortunately, this does not cover duplicate configs where IPACM
     * thinks it is still holding on to a handle that we would have freed above.
     * It also probably means that IPACM would not know about the first FD being
     * freed if it rejects the second FD.
     */
    RET ipaReturn = mIPA->provideFd(mHandle1->data[0], UDP_SUBSCRIPTIONS);
    if (ipaReturn == RET::SUCCESS) {
        ipaReturn = mIPA->provideFd(mHandle2->data[0], TCP_SUBSCRIPTIONS);
    }

    if (ipaReturn != RET::SUCCESS) {
        ALOGE("IPACM failed to accept the FDs (%d %d)", mHandle1->data[0],
                mHandle2->data[0]);
        clearHandles();
    } else {
        /* @TODO remove logs after stabilization */
        ALOGI("IPACM was provided two FDs (%d, %d)", mHandle1->data[0],
                mHandle2->data[0]);
    }

    BoolResult res = ipaResultToBoolResult(ipaReturn);
    hidl_cb(res.success, res.errMsg);

    fl.setResult(res.success, res.errMsg);
    mLogs.addLog(fl);
    return Void();
} /* setHandles */


/* -------------------------- IOffloadControl ------------------------------- */
Return<void> HAL::initOffload
(
    const ::android::sp<ITetheringOffloadCallback>& cb,
    initOffload_cb hidl_cb
) {
    LocalLogBuffer::FunctionLog fl(__func__);

    if (isInitialized()) {
        BoolResult res = makeInputCheckFailure("Already initialized");
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
        mLogs.addLog(fl);
    } else {
        /* Should storing the CB be a function? */
        mCb = cb;
        registerEventListeners();
        BoolResult res = ipaResultToBoolResult(RET::SUCCESS);
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
        mLogs.addLog(fl);
    }

    return Void();
} /* initOffload */

Return<void> HAL::stopOffload
(
    stopOffload_cb hidl_cb
) {
    LocalLogBuffer::FunctionLog fl(__func__);

    if (!isInitialized()) {
        BoolResult res = makeInputCheckFailure("Was never initialized");
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
        mLogs.addLog(fl);
    } else {
        /* Should removing the CB be a function? */
        mCb.clear();
        unregisterEventListeners();

        RET ipaReturn = mIPA->stopAllOffload();
        if (ipaReturn != RET::SUCCESS) {
            /* Ignore IPAs return value here and provide why stopAllOffload
             * failed.  However, if IPA failed to clearAllFds, then we can't
             * clear our map because they may still be in use.
             */
            RET ret = mIPA->clearAllFds();
            if (ret == RET::SUCCESS) {
                clearHandles();
            }
        } else {
            ipaReturn = mIPA->clearAllFds();
            /* If IPA fails, they may still be using these for some reason. */
            if (ipaReturn == RET::SUCCESS) {
                clearHandles();
            } else {
                ALOGE("IPACM failed to return success for clearAllFds so they will not be released...");
            }
        }

        BoolResult res = ipaResultToBoolResult(ipaReturn);
        hidl_cb(res.success, res.errMsg);

        fl.setResult(res.success, res.errMsg);
        mLogs.addLog(fl);
    }

    return Void();
} /* stopOffload */

Return<void> HAL::setLocalPrefixes
(
    const hidl_vec<hidl_string>& prefixes,
    setLocalPrefixes_cb hidl_cb
) {
    BoolResult res;
    PrefixParser parser;
    vector<string> prefixesStr = convertHidlStrToStdStr(prefixes);

    LocalLogBuffer::FunctionLog fl(__func__);
    fl.addArg("prefixes", prefixesStr);

    if (!isInitialized()) {
        res = makeInputCheckFailure("Not initialized");
    } else if(prefixesStr.size() < 1) {
        res = ipaResultToBoolResult(RET::FAIL_INPUT_CHECK);
    } else if (!parser.add(prefixesStr)) {
        res = makeInputCheckFailure(parser.getLastErrAsStr());
    } else {
        res = ipaResultToBoolResult(RET::SUCCESS);
    }

    hidl_cb(res.success, res.errMsg);
    fl.setResult(res.success, res.errMsg);
    mLogs.addLog(fl);
    return Void();
} /* setLocalPrefixes */

Return<void> HAL::getForwardedStats
(
    const hidl_string& upstream,
    getForwardedStats_cb hidl_cb
) {
    LocalLogBuffer::FunctionLog fl(__func__);
    fl.addArg("upstream", upstream);

    OffloadStatistics ret;
    RET ipaReturn = mIPA->getStats(upstream.c_str(), true, ret);
    if (ipaReturn == RET::SUCCESS) {
        hidl_cb(ret.getTotalRxBytes(), ret.getTotalTxBytes());
        fl.setResult(ret.getTotalRxBytes(), ret.getTotalTxBytes());
    } else {
        /* @TODO Ensure the output is zeroed, but this is probably not enough to
         * tell Framework that an error has occurred.  If, for example, they had
         * not yet polled for statistics previously, they may incorrectly assume
         * that simply no statistics have transpired on hardware path.
         *
         * Maybe ITetheringOffloadCallback:onEvent(OFFLOAD_STOPPED_ERROR) is
         * enough to handle this case, time will tell.
         */
        hidl_cb(0, 0);
        fl.setResult(0, 0);
    }

    mLogs.addLog(fl);
    return Void();
} /* getForwardedStats */

Return<void> HAL::setDataLimit
(
    const hidl_string& upstream,
    uint64_t limit,
    setDataLimit_cb hidl_cb
) {
    LocalLogBuffer::FunctionLog fl(__func__);
    fl.addArg("upstream", upstream);
    fl.addArg("limit", limit);

    if (!isInitialized()) {
        BoolResult res = makeInputCheckFailure("Not initialized (setDataLimit)");
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    } else {
        RET ipaReturn = mIPA->setQuota(upstream.c_str(), limit);
        BoolResult res = ipaResultToBoolResult(ipaReturn);
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    }

    mLogs.addLog(fl);
    return Void();
} /* setDataLimit */

Return<void> HAL::setUpstreamParameters
(
    const hidl_string& iface,
    const hidl_string& v4Addr,
    const hidl_string& v4Gw,
    const hidl_vec<hidl_string>& v6Gws,
    setUpstreamParameters_cb hidl_cb
) {
    vector<string> v6GwStrs = convertHidlStrToStdStr(v6Gws);

    LocalLogBuffer::FunctionLog fl(__func__);
    fl.addArg("iface", iface);
    fl.addArg("v4Addr", v4Addr);
    fl.addArg("v4Gw", v4Gw);
    fl.addArg("v6Gws", v6GwStrs);

    PrefixParser v4AddrParser;
    PrefixParser v4GwParser;
    PrefixParser v6GwParser;

    /* @TODO maybe we should enforce that these addresses and gateways are fully
     * qualified here.  But then, how do we allow them to be empty/null as well
     * while still preserving a sane API on PrefixParser?
     */
    if (!isInitialized()) {
        BoolResult res = makeInputCheckFailure("Not initialized (setUpstreamParameters)");
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    } else if (!v4AddrParser.addV4(v4Addr) && !v4Addr.empty()) {
        BoolResult res = makeInputCheckFailure(v4AddrParser.getLastErrAsStr());
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    } else if (!v4GwParser.addV4(v4Gw) && !v4Gw.empty()) {
        BoolResult res = makeInputCheckFailure(v4GwParser.getLastErrAsStr());
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    } else if (v6GwStrs.size() >= 1 && !v6GwParser.addV6(v6GwStrs)) {
        BoolResult res = makeInputCheckFailure(v6GwParser.getLastErrAsStr());
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    } else if (iface.size()>= 1) {
        RET ipaReturn = mIPA->setUpstream(
                iface.c_str(),
                v4GwParser.getFirstPrefix(),
                v6GwParser.getFirstPrefix());
        BoolResult res = ipaResultToBoolResult(ipaReturn);
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    } else {
	/* send NULL iface string when upstream down */
        RET ipaReturn = mIPA->setUpstream(
                NULL,
                v4GwParser.getFirstPrefix(),
                v6GwParser.getFirstPrefix());
        BoolResult res = ipaResultToBoolResult(ipaReturn);
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    }

    mLogs.addLog(fl);
    return Void();
} /* setUpstreamParameters */

Return<void> HAL::addDownstream
(
    const hidl_string& iface,
    const hidl_string& prefix,
    addDownstream_cb hidl_cb
) {
    LocalLogBuffer::FunctionLog fl(__func__);
    fl.addArg("iface", iface);
    fl.addArg("prefix", prefix);

    PrefixParser prefixParser;

    if (!isInitialized()) {
        BoolResult res = makeInputCheckFailure("Not initialized (setUpstreamParameters)");
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    }
    else if (!prefixParser.add(prefix)) {
        BoolResult res = makeInputCheckFailure(prefixParser.getLastErrAsStr());
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    } else {
        RET ipaReturn = mIPA->addDownstream(
                iface.c_str(),
                prefixParser.getFirstPrefix());
        BoolResult res = ipaResultToBoolResult(ipaReturn);
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    }

    mLogs.addLog(fl);
    return Void();
} /* addDownstream */

Return<void> HAL::removeDownstream
(
    const hidl_string& iface,
    const hidl_string& prefix,
    removeDownstream_cb hidl_cb
) {
    LocalLogBuffer::FunctionLog fl(__func__);
    fl.addArg("iface", iface);
    fl.addArg("prefix", prefix);

    PrefixParser prefixParser;

    if (!isInitialized()) {
        BoolResult res = makeInputCheckFailure("Not initialized (setUpstreamParameters)");
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    }
    else if (!prefixParser.add(prefix)) {
        BoolResult res = makeInputCheckFailure(prefixParser.getLastErrAsStr());
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    } else {
        RET ipaReturn = mIPA->removeDownstream(
                iface.c_str(),
                prefixParser.getFirstPrefix());
        BoolResult res = ipaResultToBoolResult(ipaReturn);
        hidl_cb(res.success, res.errMsg);
        fl.setResult(res.success, res.errMsg);
    }

    mLogs.addLog(fl);
    return Void();
} /* removeDownstream */

Return<void> HAL::debug
(
    const hidl_handle& handle,
    const hidl_vec<hidl_string>& /* options */
) {
    if (handle != nullptr && handle->numFds >= 1) {
        mLogs.toFd(handle->data[0]);
    }
    return Void();
} /* debug */
