/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * 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.
 */

/*
 * Implementation of the user-space ashmem API for devices, which have our
 * ashmem-enabled kernel. See ashmem-sim.c for the "fake" tmp-based version,
 * used by the simulator.
 */

#include "IPCCommunicator.h"
#include "Buffering/IPCBuffer.h"
#include "IPCArguments.h"
#include "IPCByteArray.h"
#include "IPCCheck.h"
#include "IPCException.h"
#include "IPCFutexPageQueue.h"
#include "IPCLog.h"
#include "IPCResult.h"
#include "IPCString.h"
#include "Serializing/IPCSerializer.h"
#include "futex.h"
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <vector>

namespace {
class BufferAssembler
    : public IPCResult,
      public IPCArguments {
public:
    void readFromBuffer(const char*);
    void readTypes(const char*&);
    void readData(const char*&);
    // IPCResult
    const void* getData() override;
    IPCType getType() override;
    const uint16_t* getStringContent() override;
    size_t getStringLength() override;
    const char* getByteArrayContent() override;
    size_t getByteArrayLength() override;

    // IPCArguments
    const void* getData(int index) override;
    IPCType getType(int index) override;
    size_t getCount() override;

private:
    std::vector<uint32_t> m_types;
    std::vector<std::unique_ptr<char[]>> m_datas;
};

void BufferAssembler::readFromBuffer(const char* blob)
{
    readTypes(blob);
    readData(blob);
}

void BufferAssembler::readTypes(const char*& blob)
{
    while (true) {
        uint32_t type;
        type = *reinterpret_cast<const uint32_t*>(blob);
        blob += sizeof(uint32_t);
        if (type == static_cast<uint32_t>(IPCType::END))
            break;
        m_types.emplace_back(type);
    }
}

void BufferAssembler::readData(const char*& blob)
{
    for (uint32_t type : m_types) {
        switch (static_cast<IPCType>(type)) {
        case IPCType::INT32: {
            int32_t n;
            memcpy(&n, blob, sizeof(n));
            blob += sizeof(n);
            std::unique_ptr<char[]> data(new char[sizeof(n)]);
            *reinterpret_cast<int32_t*>(data.get()) = n;
            m_datas.emplace_back(std::move(data));
        } break;
        case IPCType::INT64: {
            int64_t n;
            memcpy(&n, blob, sizeof(n));
            blob += sizeof(n);
            std::unique_ptr<char[]> data(new char[sizeof(n)]);
            *reinterpret_cast<int64_t*>(data.get()) = n;
            m_datas.emplace_back(std::move(data));
        } break;
        case IPCType::FLOAT: {
            float n;
            memcpy(&n, blob, sizeof(n));
            blob += sizeof(n);
            std::unique_ptr<char[]> data(new char[sizeof(n)]);
            *reinterpret_cast<float*>(data.get()) = n;
            m_datas.emplace_back(std::move(data));
        } break;
        case IPCType::DOUBLE: {
            double n;
            memcpy(&n, blob, sizeof(n));
            blob += sizeof(n);
            std::unique_ptr<char[]> data(new char[sizeof(n)]);
            *reinterpret_cast<double*>(data.get()) = n;
            m_datas.emplace_back(std::move(data));
        } break;
        case IPCType::JSONSTRING:
        case IPCType::STRING: {
            uint32_t n;
            memcpy(&n, blob, sizeof(n));
            blob += sizeof(n);
            size_t byteLength = n * sizeof(uint16_t);
            std::unique_ptr<char[]> data(new char[byteLength + sizeof(IPCString)]);
            IPCString* s = reinterpret_cast<IPCString*>(data.get());
            s->length = n;
            memcpy(s->content, blob, byteLength);
            blob += byteLength;
            m_datas.emplace_back(std::move(data));
        } break;
        case IPCType::BYTEARRAY: {
            uint32_t n;
            memcpy(&n, blob, sizeof(n));
            blob += sizeof(n);
            size_t byteLength = n;
            std::unique_ptr<char[]> data(new char[byteLength + sizeof(IPCByteArray)]);
            IPCByteArray* s = reinterpret_cast<IPCByteArray*>(data.get());
            s->length = n;
            memcpy(s->content, blob, byteLength);
            blob += byteLength;
            s->content[byteLength] = '\0';
            m_datas.emplace_back(std::move(data));
        } break;
        case IPCType::JSUNDEFINED:
        case IPCType::VOID:
            m_datas.emplace_back();
            break;
        case IPCType::END:
        default:
            IPC_UNREACHABLE();
        }
    }
}

// IPCResult
const void* BufferAssembler::getData()
{
    return getData(0);
}

IPCType BufferAssembler::getType()
{
    return getType(0);
}

const uint16_t* BufferAssembler::getStringContent()
{
    IPC_DCHECK((getType(0) == IPCType::STRING) || (getType(0) == IPCType::JSONSTRING));
    const IPCString* s = reinterpret_cast<const IPCString*>(getData(0));
    return s->content;
}

size_t BufferAssembler::getStringLength()
{
    IPC_DCHECK((getType(0) == IPCType::STRING) || (getType(0) == IPCType::JSONSTRING));
    const IPCString* s = reinterpret_cast<const IPCString*>(getData(0));
    return s->length;
}

const char* BufferAssembler::getByteArrayContent()
{
    IPC_DCHECK(getType(0) == IPCType::BYTEARRAY);
    const IPCByteArray* s = reinterpret_cast<const IPCByteArray*>(getData(0));
    return s->content;
}

size_t BufferAssembler::getByteArrayLength()
{
    IPC_DCHECK(getType(0) == IPCType::BYTEARRAY);
    const IPCByteArray* s = reinterpret_cast<const IPCByteArray*>(getData(0));
    return s->length;
}

// IPCArguments
const void* BufferAssembler::getData(int index)
{
    return m_datas.at(index).get();
}

IPCType BufferAssembler::getType(int index)
{
    return static_cast<IPCType>(m_types.at(index));
}

size_t BufferAssembler::getCount()
{
    return m_types.size();
}
}

IPCCommunicator::IPCCommunicator(IPCFutexPageQueue* futexPageQueue)
    : m_futexPageQueue(futexPageQueue)
{
}

IPCCommunicator::~IPCCommunicator()
{
}

std::unique_ptr<IPCResult> IPCCommunicator::assembleResult()
{
    std::unique_ptr<BufferAssembler> bufferAssembler(new BufferAssembler());
    bufferAssembler->readFromBuffer(getBlob());
    return std::unique_ptr<IPCResult>(bufferAssembler.release());
}

std::unique_ptr<IPCArguments> IPCCommunicator::assembleArguments()
{
    std::unique_ptr<BufferAssembler> bufferAssembler(new BufferAssembler());
    bufferAssembler->readFromBuffer(getBlob());
    return std::unique_ptr<IPCArguments>(bufferAssembler.release());
}

std::unique_ptr<IPCBuffer> IPCCommunicator::generateResultBuffer(IPCResult* result)
{
    std::unique_ptr<IPCSerializer> serializer = createIPCSerializer();
    serializer->setMsg(MSG_END);
    switch (result->getType()) {
    case IPCType::INT32:
        serializer->add(result->get<int32_t>());
        break;
    case IPCType::INT64:
        serializer->add(result->get<int64_t>());
        break;
    case IPCType::FLOAT:
        serializer->add(result->get<float>());
        break;
    case IPCType::DOUBLE:
        serializer->add(result->get<double>());
        break;
    case IPCType::BYTEARRAY:
        serializer->add(result->getByteArrayContent(), result->getByteArrayLength());
        break;
	case IPCType::CHARARRAY:
        serializer->add(static_cast<const char*>(result->getData()), result->getStringLength());
        break;
    case IPCType::JSONSTRING:
        serializer->addJSON(result->getStringContent(), result->getStringLength());
        break;
    case IPCType::STRING:
        serializer->add(result->getStringContent(), result->getStringLength());
        break;
    case IPCType::JSUNDEFINED:
        serializer->addJSUndefined();
        break;
    case IPCType::VOID:
        serializer->addVoid();
        break;
    default:
        IPC_UNREACHABLE();
    }
    return serializer->finish();
}

void IPCCommunicator::doSendBufferOnly(IPCBuffer* buffer)
{
    const char* data = static_cast<const char*>(buffer->get());
    uint32_t length = buffer->length();
    doSendBufferOnly(data, length);
}

uint32_t IPCCommunicator::doReadPackage()
{
    uint32_t msg;
    uint32_t length;
    m_futexPageQueue->lockReadPage();
    void* sharedMemory = m_futexPageQueue->getCurrentReadPage();
    length = static_cast<uint32_t*>(sharedMemory)[0];
    uint32_t availableSize = m_futexPageQueue->getPageSize() - sizeof(uint32_t);
    if (length < 2 * sizeof(uint32_t)) {
        releaseBlob();
        throw IPCException("Not a vaild msg");
    }
    if (length > availableSize) {
        m_package.reset(new char[length]);
        doRecvBufferOnly(m_package.get(), length);
        return *reinterpret_cast<uint32_t*>(m_package.get());
    }
    return static_cast<uint32_t*>(sharedMemory)[1];
}

void IPCCommunicator::doSendBufferOnly(const void* _data, size_t length)
{
    const char* data = static_cast<const char*>(_data);
    size_t pageSize = m_futexPageQueue->getPageSize();
    ssize_t byteTransfered;
    uint32_t* dstLength = static_cast<uint32_t*>(m_futexPageQueue->getCurrentWritePage());
    // special handle the first part, which need a size
    // as header.
    dstLength[0] = length;

    IPC_LOGD("send bytes: length: %zu", length);
    byteTransfered = std::min(length, pageSize - sizeof(uint32_t));
    memcpy(dstLength + 1, data, byteTransfered);
    m_futexPageQueue->stepWrite();
    // multiple page package
    if (length > byteTransfered) {
        data += byteTransfered;
        length -= byteTransfered;
        IPC_LOGD("sent bytes: remaining length: %zu, transfered: %zu", length, byteTransfered);

        while (length > 0) {
            byteTransfered = doSendBufferPage(data, length, pageSize);
            data += byteTransfered;
            length -= byteTransfered;
            IPC_LOGD("sent bytes: remaining length: %zu, transfered: %zu", length, byteTransfered);
        }
    }
}

void IPCCommunicator::doRecvBufferOnly(void* _data, size_t length)
{
    char* data = static_cast<char*>(_data);
    size_t pageSize = m_futexPageQueue->getPageSize();
    bool firstRun = true;
    IPC_LOGD("recv bytes: length: %zu", length);
    while (true) {
        ssize_t byteTransfered;
        byteTransfered = std::min(length, pageSize);
        const void* src = m_futexPageQueue->getCurrentReadPage();
        // skip the package size.
        // package starts with msg.
        if (firstRun) {
            src = static_cast<const char*>(src) + sizeof(uint32_t);
            byteTransfered -= sizeof(uint32_t);
        }
        memcpy(data, src, byteTransfered);
        data += byteTransfered;
        length -= byteTransfered;
        IPC_LOGD("recv bytes: remaining length: %zu, transfered: %zu", length, byteTransfered);
        if (length > 0) {
            firstRun = false;
            m_futexPageQueue->unlockReadPageAndStep();
            m_futexPageQueue->lockReadPage();
        } else {
            break;
        }
    }
}

const char* IPCCommunicator::getBlob()
{
    if (m_package.get())
        return m_package.get() + sizeof(uint32_t);
    return static_cast<const char*>(m_futexPageQueue->getCurrentReadPage()) + sizeof(uint32_t) * 2;
}

void IPCCommunicator::releaseBlob()
{
    m_package.reset();
    m_futexPageQueue->unlockReadPageAndStep();
}

size_t IPCCommunicator::doSendBufferPage(const void* data, size_t length, size_t pageSize)
{
    ssize_t byteTransfered;
    byteTransfered = std::min(length, pageSize);
    void* dst = m_futexPageQueue->getCurrentWritePage();
    memcpy(dst, data, byteTransfered);
    m_futexPageQueue->stepWrite();
    return byteTransfered;
}
