/*
 * Copyright 2009, The Android Open Source Project
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 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.
 */

#define LOG_TAG "wdsclient"

#include "AdbConnection.h"
#include "ClientUtils.h"
#include "Device.h"
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <utils/Log.h>

void AdbConnection::close() {
    if (m_fd != -1) {
        shutdown(m_fd, SHUT_RDWR);
        ::close(m_fd);
        m_fd = -1;
    }
}

// Default adb port
#define ADB_PORT 5037

bool AdbConnection::connect() {
    // Some commands (host:devices for example) close the connection so we call
    // connect after the response.
    close();

    m_fd = socket(PF_INET, SOCK_STREAM, 0);
    if (m_fd < 0) {
        log_errno("Failed to create socket for connecting to adb");
        return false;
    }

    // Create the socket address struct
    sockaddr_in adb;
    createTcpSocket(adb, ADB_PORT);

    // Connect to adb
    if (::connect(m_fd, (sockaddr*) &adb, sizeof(adb)) < 0) {
        log_errno("Failed to connect to adb");
        return false;
    }

    // Connected
    return true;
}

// Adb protocol stuff
#define MAX_COMMAND_LENGTH 1024
#define PAYLOAD_LENGTH 4
#define PAYLOAD_FORMAT "%04X"

bool AdbConnection::sendRequest(const char* fmt, ...) const {
    if (m_fd == -1) {
        ALOGE("Connection is closed");
        return false;
    }

    // Build the command (service)
    char buf[MAX_COMMAND_LENGTH];
    va_list args;
    va_start(args, fmt);
    int res = vsnprintf(buf, MAX_COMMAND_LENGTH, fmt, args);
    va_end(args);

    ALOGV("Sending command: %04X%.*s", res, res, buf);

    // Construct the payload length
    char payloadLen[PAYLOAD_LENGTH + 1];
    snprintf(payloadLen, sizeof(payloadLen), PAYLOAD_FORMAT, res);

    // First, send the payload length
    if (send(m_fd, payloadLen, PAYLOAD_LENGTH, 0) < 0) {
        log_errno("Failure when sending payload");
        return false;
    }

    // Send the actual command
    if (send(m_fd, buf, res, 0) < 0) {
        log_errno("Failure when sending command");
        return false;
    }

    // Check for the OKAY from adb
    return checkOkayResponse();
}

static void printFailureMessage(int fd) {
    // Grab the payload length
    char lenStr[PAYLOAD_LENGTH + 1];
    int payloadLen = recv(fd, lenStr, sizeof(lenStr) - 1, 0);
    ALOG_ASSERT(payloadLen == PAYLOAD_LENGTH, "Incorrect payload size");
    lenStr[PAYLOAD_LENGTH] = 0;

    // Parse the hex payload
    payloadLen = strtol(lenStr, NULL, 16);
    if (payloadLen < 0)
        return;

    // Grab the message
    char* msg = new char[payloadLen + 1]; // include null-terminator
    int res = recv(fd, msg, payloadLen, 0);
    if (res < 0) {
        log_errno("Failure reading failure message from adb");
        return;
    } else if (res != payloadLen) {
        ALOGE("Incorrect payload length %d - expected %d", res, payloadLen);
        return;
    }
    msg[res] = 0;

    // Tell somebody about it
    ALOGE("Received failure from adb: %s", msg);

    // Cleanup
    delete[] msg;
}

#define ADB_RESPONSE_LENGTH 4

bool AdbConnection::checkOkayResponse() const {
    ALOG_ASSERT(m_fd != -1, "Connection has been closed!");

    char buf[ADB_RESPONSE_LENGTH];
    int res = recv(m_fd, buf, sizeof(buf), 0);
    if (res < 0) {
        log_errno("Failure reading response from adb");
        return false;
    }

    // Check for a response other than OKAY/FAIL
    if ((res == ADB_RESPONSE_LENGTH) && (strncmp(buf, "OKAY", res) == 0)) {
        ALOGV("Command OKAY");
        return true;
    } else if (strncmp(buf, "FAIL", ADB_RESPONSE_LENGTH) == 0) {
        // Something happened, print out the reason for failure
        printFailureMessage(m_fd);
        return false;
    }
    ALOGE("Incorrect response from adb - '%.*s'", res, buf);
    return false;
}

void AdbConnection::clearDevices() {
    for (unsigned i = 0; i < m_devices.size(); i++)
        delete m_devices.editItemAt(i);
    m_devices.clear();
}

const DeviceList& AdbConnection::getDeviceList() {
    // Clear the current device list
    clearDevices();

    if (m_fd == -1) {
        ALOGE("Connection is closed");
        return m_devices;
    }

    // Try to send the device list request
    if (!sendRequest("host:devices")) {
        ALOGE("Failed to get device list from adb");
        return m_devices;
    }

    // Get the payload length
    char lenStr[PAYLOAD_LENGTH + 1];
    int res = recv(m_fd, lenStr, sizeof(lenStr) - 1, 0);
    if (res < 0) {
        log_errno("Failure to read payload size of device list");
        return m_devices;
    }
    lenStr[PAYLOAD_LENGTH] = 0;

    // Parse the hex payload
    int payloadLen = strtol(lenStr, NULL, 16);
    if (payloadLen < 0)
        return m_devices;

    // Grab the list of devices. The format is as follows:
    // <serialno><tab><state><newline>
    char* msg = new char[payloadLen + 1];
    res = recv(m_fd, msg, payloadLen, 0);
    if (res < 0) {
        log_errno("Failure reading the device list");
        return m_devices;
    } else if (res != payloadLen) {
        ALOGE("Incorrect payload length %d - expected %d", res, payloadLen);
        return m_devices;
    }
    msg[res] = 0;

    char serial[32];
    char state[32];
    int numRead;
    char* ptr = msg;
    while (sscanf(ptr, "%31s\t%31s\n%n", serial, state, &numRead) > 1) {
        Device::DeviceType t = Device::DEVICE;
        static const char emulator[] = "emulator-";
        if (strncmp(serial, emulator, sizeof(emulator) - 1) == 0)
            t = Device::EMULATOR;
        ALOGV("Adding device %s (%s)", serial, state);
        m_devices.add(new Device(serial, t, this));

        // Reset for the next line
        ptr += numRead;
    }
    // Cleanup
    delete[] msg;

    return m_devices;
}
