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

/*
 * Encapsulates exchange protocol between the emulator, and an Android device
 * that is connected to the host via USB. The communication is established over
 * a TCP port forwarding, enabled by ADB.
 */

#include "android/async-socket-connector.h"

#include "android/utils/debug.h"
#include "android/utils/iolooper.h"
#include "android/utils/panic.h"

#include <assert.h>

#define  E(...)    derror(__VA_ARGS__)
#define  W(...)    dwarning(__VA_ARGS__)
#define  D(...)    VERBOSE_PRINT(asconnector,__VA_ARGS__)
#define  D_ACTIVE  VERBOSE_CHECK(asconnector)

#define TRACE_ON    0

#if TRACE_ON
#define  T(...)    VERBOSE_PRINT(asconnector,__VA_ARGS__)
#else
#define  T(...)
#endif

/********************************************************************************
 *                             Internals
 *******************************************************************************/

struct AsyncSocketConnector {
    /* TCP address for the connection. */
    SockAddress     address;
    /* I/O looper for asynchronous I/O. */
    Looper*         looper;
    /* I/O port for asynchronous connection. */
    LoopIo*         connector_io;
    /* Timer that is used to retry asynchronous connections. */
    LoopTimer*      connector_timer;
    /* Asynchronous connector to the socket. */
    AsyncConnector  connector[1];
    /* Callback to invoke on connection events. */
    asc_event_cb    on_connected_cb;
    /* An opaque parameter to pass to the connection callback. */
    void*           on_connected_cb_opaque;
    /* Retry timeout in milliseconds. */
    int             retry_to;
    /* Socket descriptor for the connection. */
    int             fd;
    /* Number of outstanding references to the connector. */
    int             ref_count;
    /* Flags whether (1) or not (0) connector owns the looper. */
    int             owns_looper;
};

/* Asynchronous I/O looper callback invoked by the connector.
 * Param:
 *  opaque - AsyncSocketConnector instance.
 *  fd, events - Standard I/O callback parameters.
 */
static void _on_async_socket_connector_io(void* opaque, int fd, unsigned events);

/* Gets socket's address string. */
AINLINED const char*
_asc_socket_string(AsyncSocketConnector* connector, char* buf, size_t len)
{
    return sock_address_to_string(&connector->address, buf, len);
}

/* Destroys AsyncSocketConnector instance.
 * Param:
 *  connector - Initialized AsyncSocketConnector instance.
 */
static void
_async_socket_connector_free(AsyncSocketConnector* connector)
{
    char tmp[256];
    if (connector != NULL) {
        T("ASC %s: Connector is destroying...", _asc_socket_string(connector, tmp, sizeof(tmp)));

        /* Stop all activities. */
        if (asyncConnector_stop(connector->connector) == 0) {
            /* Connection was in progress. We need to destroy I/O descriptor for
             * that connection. */
            D("ASC %s: Stopped async connection in progress.",
              _asc_socket_string(connector, tmp, sizeof(tmp)));
            loopIo_free(connector->connector_io);
        }

        /* Free allocated resources. */
        if (connector->looper != NULL) {
            loopTimer_free(connector->connector_timer);
            if (connector->owns_looper) {
                looper_free(connector->looper);
            }
        }

        if (connector->fd >= 0) {
            socket_close(connector->fd);
        }

        T("ASC %s: Connector is destroyed", _asc_socket_string(connector, tmp, sizeof(tmp)));

        sock_address_done(&connector->address);

        AFREE(connector);
    }
}

/* Opens connection socket.
 * Param:
 *  connector - Initialized AsyncSocketConnector instance.
 * Return:
 *  0 on success, or -1 on failure.
 */
static int
_async_socket_connector_open_socket(AsyncSocketConnector* connector)
{
    char tmp[256];
    /* Open socket. */
    connector->fd = socket_create_inet(SOCKET_STREAM);
    if (connector->fd < 0) {
        D("ASC %s: Unable to create socket: %d -> %s",
          _asc_socket_string(connector, tmp, sizeof(tmp)), errno, strerror(errno));
        return -1;
    }

    /* Prepare for async I/O on the connector. */
    socket_set_nonblock(connector->fd);

    T("ASC %s: Connector socket is opened with FD = %d",
      _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);

    return 0;
}

/* Closes connection socket.
 * Param:
 *  connector - Initialized AsyncSocketConnector instance.
 * Return:
 *  0 on success, or -1 on failure.
 */
static void
_async_socket_connector_close_socket(AsyncSocketConnector* connector)
{
#if TRACE_ON
    char tmp[256];
#endif
    if (connector->fd >= 0) {
        socket_close(connector->fd);
        T("ASC %s: Connector socket FD = %d is closed.",
          _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);
        connector->fd = -1;
    }
}

/* Asynchronous connector (AsyncConnector instance) has completed connection
 *  attempt.
 * Param:
 *  connector - Initialized AsyncSocketConnector instance. Note: When this
 *      callback is called, the caller has referenced passed connector object,
 *      So, it's guaranteed that this connector is not going to be destroyed
 *      while this routine executes.
 *  status - Status of the connection attempt.
 */
static void
_on_async_socket_connector_connecting(AsyncSocketConnector* connector,
                                      AsyncStatus status)
{
    AsyncIOAction action = ASIO_ACTION_DONE;
    char tmp[256];

    switch (status) {
        case ASYNC_COMPLETE:
            loopIo_free(connector->connector_io);
            D("Socket '%s' is connected", _asc_socket_string(connector, tmp, sizeof(tmp)));
            /* Invoke "on connected" callback */
            action = connector->on_connected_cb(connector->on_connected_cb_opaque,
                                                connector, ASIO_STATE_SUCCEEDED);
            break;

        case ASYNC_ERROR:
            loopIo_free(connector->connector_io);
            D("Error while connecting to socket '%s': %d -> %s",
              _asc_socket_string(connector, tmp, sizeof(tmp)), errno, strerror(errno));
            /* Invoke "on connected" callback */
            action = connector->on_connected_cb(connector->on_connected_cb_opaque,
                                                connector, ASIO_STATE_FAILED);
            break;

        case ASYNC_NEED_MORE:
            T("ASC %s: Waiting on connection to complete. Connector FD = %d",
              _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);
            return;
    }

    if (action == ASIO_ACTION_RETRY) {
        D("ASC %s: Retrying connection. Connector FD = %d",
          _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);
        loopTimer_startRelative(connector->connector_timer, connector->retry_to);
    } else if (action == ASIO_ACTION_ABORT) {
        D("ASC %s: Client has aborted connection. Connector FD = %d",
          _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);
    }
}

static void
_on_async_socket_connector_io(void* opaque, int fd, unsigned events)
{
    AsyncSocketConnector* const connector = (AsyncSocketConnector*)opaque;

    /* Reference the connector while we're handing I/O. */
    async_socket_connector_reference(connector);

    /* Notify the client that another connection attempt is about to start. */
    const AsyncIOAction action =
        connector->on_connected_cb(connector->on_connected_cb_opaque,
                                   connector, ASIO_STATE_CONTINUES);
    if (action != ASIO_ACTION_ABORT) {
        /* Complete socket connection. */
        const AsyncStatus status = asyncConnector_run(connector->connector);
        _on_async_socket_connector_connecting(connector, status);
    } else {
        char tmp[256];
        D("ASC %s: Client has aborted connection. Connector FD = %d",
          _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);
    }

    /* Release the connector after we're done with handing I/O. */
    async_socket_connector_release(connector);
}

/* Retry connection timer callback.
 * Param:
 *  opaque - AsyncSocketConnector instance.
 */
static void
_on_async_socket_connector_retry(void* opaque, LoopTimer* timer)
{
    AsyncStatus status;
    AsyncSocketConnector* const connector = (AsyncSocketConnector*)opaque;
    char tmp[256];

    T("ASC %s: Reconnect timer expired. Connector FD = %d",
              _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);

    /* Reference the connector while we're in callback. */
    async_socket_connector_reference(connector);

    /* Invoke the callback to notify about a connection retry attempt. */
    AsyncIOAction action =
        connector->on_connected_cb(connector->on_connected_cb_opaque,
                                   connector, ASIO_STATE_RETRYING);

    if (action != ASIO_ACTION_ABORT) {
        /* Close handle opened for the previous (failed) attempt. */
        _async_socket_connector_close_socket(connector);

        /* Retry connection attempt. */
        if (_async_socket_connector_open_socket(connector) == 0) {
            connector->connector_io = loopIo_new(connector->looper,
                                                 connector->fd,
                                                 _on_async_socket_connector_io,
                                                 connector);
            status = asyncConnector_init(connector->connector,
                                         &connector->address,
                                         connector->connector_io);
        } else {
            status = ASYNC_ERROR;
        }

        _on_async_socket_connector_connecting(connector, status);
    } else {
        D("ASC %s: Client has aborted connection. Connector FD = %d",
          _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);
    }

    /* Release the connector after we're done with the callback. */
    async_socket_connector_release(connector);
}

/********************************************************************************
 *                       Async connector implementation
 *******************************************************************************/

AsyncSocketConnector*
async_socket_connector_new(const SockAddress* address,
                           int retry_to,
                           asc_event_cb cb,
                           void* cb_opaque,
                           Looper* looper)
{
    AsyncSocketConnector* connector;

    if (cb == NULL) {
        char tmp[256];
        W("No callback for AsyncSocketConnector for socket '%s'",
          sock_address_to_string(address, tmp, sizeof(tmp)));
        errno = EINVAL;
        return NULL;
    }

    ANEW0(connector);

    connector->fd = -1;
    connector->retry_to = retry_to;
    connector->on_connected_cb = cb;
    connector->on_connected_cb_opaque = cb_opaque;
    connector->ref_count = 1;

    /* Copy socket address. */
#ifdef _WIN32
    connector->address = *address;
#else
    if (sock_address_get_family(address) == SOCKET_UNIX) {
        sock_address_init_unix(&connector->address, sock_address_get_path(address));
    } else {
        connector->address = *address;
    }
#endif

    char tmp[256];
    /* Create a looper for asynchronous I/O. */
    if (looper == NULL) {
        connector->looper = looper_newGeneric();
        if (connector->looper == NULL) {
            E("Unable to create I/O looper for AsyncSocketConnector for socket '%s'",
              _asc_socket_string(connector, tmp, sizeof(tmp)));
            cb(cb_opaque, connector, ASIO_STATE_FAILED);
            _async_socket_connector_free(connector);
            return NULL;
        }
        connector->owns_looper = 1;
    } else {
        connector->looper = looper;
        connector->owns_looper = 0;
    }

    /* Create a timer that will be used for connection retries. */
    connector->connector_timer = loopTimer_new(
            connector->looper,
            _on_async_socket_connector_retry,
            connector);

    T("ASC %s: New connector object", _asc_socket_string(connector, tmp, sizeof(tmp)));

    return connector;
}

int
async_socket_connector_reference(AsyncSocketConnector* connector)
{
    assert(connector->ref_count > 0);
    connector->ref_count++;
    return connector->ref_count;
}

int
async_socket_connector_release(AsyncSocketConnector* connector)
{
    assert(connector->ref_count > 0);
    connector->ref_count--;
    if (connector->ref_count == 0) {
        /* Last reference has been dropped. Destroy this object. */
        _async_socket_connector_free(connector);
        return 0;
    }
    return connector->ref_count;
}

void
async_socket_connector_connect(AsyncSocketConnector* connector)
{
    AsyncStatus status;
    char tmp[256];

    T("ASC %s: Handling connect request. Connector FD = %d",
      _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);

    if (_async_socket_connector_open_socket(connector) == 0) {
        const AsyncIOAction action =
            connector->on_connected_cb(connector->on_connected_cb_opaque,
                                       connector, ASIO_STATE_STARTED);
        if (action == ASIO_ACTION_ABORT) {
            D("ASC %s: Client has aborted connection. Connector FD = %d",
              _asc_socket_string(connector, tmp, sizeof(tmp)), connector->fd);
            return;
        } else {
            connector->connector_io = loopIo_new(connector->looper,
                                                 connector->fd,
                                                 _on_async_socket_connector_io,
                                                 connector);
            status = asyncConnector_init(connector->connector,
                                         &connector->address,
                                         connector->connector_io);
        }
    } else {
        status = ASYNC_ERROR;
    }

    _on_async_socket_connector_connecting(connector, status);
}

int
async_socket_connector_pull_fd(AsyncSocketConnector* connector)
{
    const int fd = connector->fd;
    if (fd >= 0) {
        connector->fd = -1;
    }
#if TRACE_ON
    char tmp[256];
#endif
    T("ASC %s: Client has pulled connector FD %d", _asc_socket_string(connector, tmp, sizeof(tmp)), fd);

    return fd;
}
