/*
 * Copyright (C) 2009 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "HTTPStream"
#include <utils/Log.h>

#include "include/HTTPStream.h"

#include <sys/socket.h>

#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <media/stagefright/MediaDebug.h>

namespace android {

// static
const char *HTTPStream::kStatusKey = ":status:";

HTTPStream::HTTPStream()
    : mState(READY),
      mSocket(-1) {
}

HTTPStream::~HTTPStream() {
    disconnect();
}

status_t HTTPStream::connect(const char *server, int port) {
    Mutex::Autolock autoLock(mLock);

    status_t err = OK;

    if (mState == CONNECTED) {
        return ERROR_ALREADY_CONNECTED;
    }

    struct hostent *ent = gethostbyname(server);
    if (ent == NULL) {
        return ERROR_UNKNOWN_HOST;
    }

    CHECK_EQ(mSocket, -1);
    mSocket = socket(AF_INET, SOCK_STREAM, 0);

    if (mSocket < 0) {
        return UNKNOWN_ERROR;
    }

    setReceiveTimeout(5);  // Time out reads after 5 secs by default

    mState = CONNECTING;

    int s = mSocket;

    mLock.unlock();

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
    memset(addr.sin_zero, 0, sizeof(addr.sin_zero));

    int res = ::connect(s, (const struct sockaddr *)&addr, sizeof(addr));

    mLock.lock();

    if (mState != CONNECTING) {
        return UNKNOWN_ERROR;
    }

    if (res < 0) {
        close(mSocket);
        mSocket = -1;

        mState = READY;
        return UNKNOWN_ERROR;
    }

    mState = CONNECTED;

    return OK;
}

status_t HTTPStream::disconnect() {
    Mutex::Autolock autoLock(mLock);

    if (mState != CONNECTED && mState != CONNECTING) {
        return ERROR_NOT_CONNECTED;
    }

    CHECK(mSocket >= 0);
    close(mSocket);
    mSocket = -1;

    mState = READY;

    return OK;
}

status_t HTTPStream::send(const char *data, size_t size) {
    if (mState != CONNECTED) {
        return ERROR_NOT_CONNECTED;
    }

    while (size > 0) {
        ssize_t n = ::send(mSocket, data, size, 0);

        if (n < 0) {
            if (errno == EINTR) {
                continue;
            }

            disconnect();

            return ERROR_IO;
        } else if (n == 0) {
            disconnect();

            return ERROR_CONNECTION_LOST;
        }

        size -= (size_t)n;
        data += (size_t)n;
    }

    return OK;
}

status_t HTTPStream::send(const char *data) {
    return send(data, strlen(data));
}

// A certain application spawns a local webserver that sends invalid responses,
// specifically it terminates header line with only a newline instead of the
// CRLF (carriage-return followed by newline) required by the HTTP specs.
// The workaround accepts both behaviours but could potentially break
// legitimate responses that use a single newline to "fold" headers, which is
// why it's not yet on by default.
#define WORKAROUND_FOR_MISSING_CR       0

status_t HTTPStream::receive_line(char *line, size_t size) {
    if (mState != CONNECTED) {
        return ERROR_NOT_CONNECTED;
    }

    bool saw_CR = false;
    size_t length = 0;

    for (;;) {
        char c;
        ssize_t n = recv(mSocket, &c, 1, 0);
        if (n < 0) {
            if (errno == EINTR) {
                continue;
            }

            disconnect();

            return ERROR_IO;
        } else if (n == 0) {
            disconnect();

            return ERROR_CONNECTION_LOST;
        }

#if WORKAROUND_FOR_MISSING_CR
        if (c == '\n') {
            // We have a complete line.

            line[saw_CR ? length - 1 : length] = '\0';
            return OK;
        }
#else
        if (saw_CR &&  c == '\n') {
            // We have a complete line.

            line[length - 1] = '\0';
            return OK;
        }
#endif

        saw_CR = (c == '\r');

        if (length + 1 >= size) {
            return ERROR_MALFORMED;
        }
        line[length++] = c;
    }
}

status_t HTTPStream::receive_header(int *http_status) {
    *http_status = -1;
    mHeaders.clear();

    char line[2048];
    status_t err = receive_line(line, sizeof(line));
    if (err != OK) {
        return err;
    }

    mHeaders.add(string(kStatusKey), string(line));

    char *spacePos = strchr(line, ' ');
    if (spacePos == NULL) {
        // Malformed response?
        return UNKNOWN_ERROR;
    }

    char *status_start = spacePos + 1;
    char *status_end = status_start;
    while (isdigit(*status_end)) {
        ++status_end;
    }

    if (status_end == status_start) {
        // Malformed response, status missing?
        return UNKNOWN_ERROR;
    }

    memmove(line, status_start, status_end - status_start);
    line[status_end - status_start] = '\0';

    long tmp = strtol(line, NULL, 10);
    if (tmp < 0 || tmp > 999) {
        return UNKNOWN_ERROR;
    }

    *http_status = (int)tmp;

    for (;;) {
        err = receive_line(line, sizeof(line));
        if (err != OK) {
            return err;
        }

        if (*line == '\0') {
            // Empty line signals the end of the header.
            break;
        }

        // puts(line);

        char *colonPos = strchr(line, ':');
        if (colonPos == NULL) {
            mHeaders.add(string(line), string());
        } else {
            char *end_of_key = colonPos;
            while (end_of_key > line && isspace(end_of_key[-1])) {
                --end_of_key;
            }

            char *start_of_value = colonPos + 1;
            while (isspace(*start_of_value)) {
                ++start_of_value;
            }

            *end_of_key = '\0';

            mHeaders.add(string(line), string(start_of_value));
        }
    }

    return OK;
}

ssize_t HTTPStream::receive(void *data, size_t size) {
    size_t total = 0;
    while (total < size) {
        ssize_t n = recv(mSocket, (char *)data + total, size - total, 0);

        if (n < 0) {
            if (errno == EINTR) {
                continue;
            }

            LOGE("recv failed, errno = %d (%s)", errno, strerror(errno));

            disconnect();
            return (ssize_t)ERROR_IO;
        } else if (n == 0) {
            disconnect();

            LOGE("recv failed, server is gone, total received: %d bytes",
                 total);

            return total == 0 ? (ssize_t)ERROR_CONNECTION_LOST : total;
        }

        total += (size_t)n;
    }

    return (ssize_t)total;
}

bool HTTPStream::find_header_value(const string &key, string *value) const {
    ssize_t index = mHeaders.indexOfKey(key);
    if (index < 0) {
        value->clear();
        return false;
    }

    *value = mHeaders.valueAt(index);

    return true;
}

void HTTPStream::setReceiveTimeout(int seconds) {
    if (seconds < 0) {
        // Disable the timeout.
        seconds = 0;
    }

    struct timeval tv;
    tv.tv_usec = 0;
    tv.tv_sec = seconds;
    CHECK_EQ(0, setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)));
}

}  // namespace android

