/*
 * Copyright (C) 2020 Sony Interactive Entertainment Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS 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.
 */

#include "config.h"
#include "HTTPParser.h"

#include <wtf/text/StringToIntegerConversion.h>

namespace WebDriver {

HTTPParser::Phase HTTPParser::parse(Vector<uint8_t>&& data)
{
    if (!data.isEmpty()) {
        m_buffer.appendVector(WTF::move(data));

        while (true) {
            if (handlePhase() == Process::Suspend)
                break;
        }
    }

    return m_phase;
}

HTTPParser::Process HTTPParser::handlePhase()
{
    switch (m_phase) {
    case Phase::Idle: {
        String line;
        if (!readLine(line))
            return Process::Suspend;

        if (!parseFirstLine(WTF::move(line)))
            return abortProcess("Client error: invalid request line.");

        ASSERT(!m_message.method.isEmpty());
        ASSERT(!m_message.path.isEmpty());
        ASSERT(!m_message.version.isEmpty());
        m_phase = Phase::Header;

        return Process::Continue;
    }

    case Phase::Header: {
        String line;
        if (!readLine(line))
            return Process::Suspend;

        if (!line.isEmpty())
            m_message.requestHeaders.append(WTF::move(line));
        else {
            m_bodyLength = expectedBodyLength();
            m_phase = Phase::Body;
        }

        return Process::Continue;
    }

    case Phase::Body:
        if (m_buffer.size() > m_bodyLength)
            return abortProcess("Client error: don't send data after request and before response.");

        if (m_buffer.size() < m_bodyLength)
            return Process::Suspend;

        m_message.requestBody = WTF::move(m_buffer);
        m_phase = Phase::Complete;

        return Process::Suspend;

    case Phase::Complete:
        return abortProcess("Client error: don't send data after request and before response.");

    case Phase::Error:
        return abortProcess();
    }
}

HTTPParser::Process HTTPParser::abortProcess(const char* message)
{
    if (message)
        LOG_ERROR("%s", message);

    m_phase = Phase::Error;

    m_buffer.shrink(0);

    return Process::Suspend;
}

bool HTTPParser::parseFirstLine(String&& line)
{
    auto components = line.split(' ');
    if (components.size() != 3)
        return false;

    m_message.method = WTF::move(components[0]);
    m_message.path = WTF::move(components[1]);
    m_message.version = WTF::move(components[2]);
    return true;
}

bool HTTPParser::readLine(String& line)
{
    auto length = m_buffer.size();
    auto position = m_buffer.find(0x0d);
    if (position == notFound || position + 1 == length || m_buffer[position + 1] != 0x0a)
        return false;

    line = String::fromUTF8(m_buffer.span().first(position));
    if (line.isNull())
        LOG_ERROR("Client error: invalid encoding in HTTP header.");

    m_buffer.removeAt(0, position + 2);
    return true;
}

size_t HTTPParser::expectedBodyLength() const
{
    if (m_message.method == "HEAD"_s)
        return 0;

    constexpr auto name = "content-length:"_s;
    const size_t nameLength = name.length();

    for (const auto& header : m_message.requestHeaders) {
        if (header.startsWithIgnoringASCIICase(name))
            return parseIntegerAllowingTrailingJunk<size_t>(StringView { header }.substring(nameLength)).value_or(0);
    }

    return 0;
}

} // namespace WebDriver
