Пример #1
0
static void *server_socket_thread(void * arg)
{
    int serverfd, fd;
    struct sockaddr addr;
    socklen_t alen;
    int port = (int)arg;

    D("transport: server_socket_thread() starting\n");
    serverfd = -1;
    for(;;) {
        if(serverfd == -1) {
            serverfd = socket_inaddr_any_server(port, SOCK_STREAM);
            if(serverfd < 0) {
                D("server: cannot bind socket yet\n");
                sdb_sleep_ms(1000);
                continue;
            }
            close_on_exec(serverfd);
        }

        alen = sizeof(addr);
        D("server: trying to get new connection from %d\n", port);
        fd = sdb_socket_accept(serverfd, &addr, &alen);
        if(fd >= 0) {
            D("server: new connection on fd %d\n", fd);
            close_on_exec(fd);
            disable_tcp_nagle(fd);
            register_socket_transport(fd, "host", port, 1, NULL);
        }
    }
    D("transport: server_socket_thread() exiting\n");
    return 0;
}
int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error) {
    int fd = -1;

#if ADB_HOST
    if (find_emulator_transport_by_adb_port(adb_port) != nullptr) {
        return -1;
    }

    const char *host = getenv("ADBHOST");
    if (host) {
        fd = network_connect(host, adb_port, SOCK_STREAM, 0, error);
    }
#endif
    if (fd < 0) {
        fd = network_loopback_client(adb_port, SOCK_STREAM, error);
    }

    if (fd >= 0) {
        D("client: connected on remote on fd %d", fd);
        close_on_exec(fd);
        disable_tcp_nagle(fd);
        std::string serial = android::base::StringPrintf("emulator-%d", console_port);
        if (register_socket_transport(fd, serial.c_str(), adb_port, 1) == 0) {
            return 0;
        }
        adb_close(fd);
    }
    return -1;
}
Пример #3
0
int local_connect_arbitrary_ports(int console_port, int sdb_port, const char *device_name)
{
    char buf[64];
    int  fd = -1;

#if SDB_HOST
    const char *host = getenv("SDBHOST");
    if (host) {
        fd = socket_network_client(host, sdb_port, SOCK_STREAM);
    }
#endif
    if (fd < 0) {
        fd = socket_loopback_client(sdb_port, SOCK_STREAM);
    }

    if (fd >= 0) {
        D("client: connected on remote on fd %d\n", fd);
        close_on_exec(fd);
        disable_tcp_nagle(fd);
        snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port);
        register_socket_transport(fd, buf, sdb_port, 1, device_name);
        return 0;
    }
    return -1;
}
Пример #4
0
static void connect_device(const std::string& address, std::string* response) {
    if (address.empty()) {
        *response = "empty address";
        return;
    }

    std::string serial;
    std::string host;
    int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
    if (!parse_host_and_port(address, &serial, &host, &port, response)) {
        return;
    }

    std::string error;
    int fd = network_connect(host.c_str(), port, SOCK_STREAM, 10, &error);
    if (fd == -1) {
        *response = android::base::StringPrintf("unable to connect to %s: %s",
                                                serial.c_str(), error.c_str());
        return;
    }

    D("client: connected %s remote on fd %d", serial.c_str(), fd);
    close_on_exec(fd);
    disable_tcp_nagle(fd);

    int ret = register_socket_transport(fd, serial.c_str(), port, 0);
    if (ret < 0) {
        adb_close(fd);
        *response = android::base::StringPrintf("already connected to %s", serial.c_str());
    } else {
        *response = android::base::StringPrintf("connected to %s", serial.c_str());
    }
}
static void server_socket_thread(void* arg) {
    int serverfd, fd;
    sockaddr_storage ss;
    sockaddr *addrp = reinterpret_cast<sockaddr*>(&ss);
    socklen_t alen;
    int port = (int) (uintptr_t) arg;

    adb_thread_setname("server socket");
    D("transport: server_socket_thread() starting");
    serverfd = -1;
    for(;;) {
        if(serverfd == -1) {
            std::string error;
            serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error);
            if(serverfd < 0) {
                D("server: cannot bind socket yet: %s", error.c_str());
                adb_sleep_ms(1000);
                continue;
            }
            close_on_exec(serverfd);
        }

        alen = sizeof(ss);
        D("server: trying to get new connection from %d", port);
        fd = adb_socket_accept(serverfd, addrp, &alen);
        if(fd >= 0) {
            D("server: new connection on fd %d", fd);
            close_on_exec(fd);
            disable_tcp_nagle(fd);
            register_socket_transport(fd, "host", port, 1);
        }
    }
    D("transport: server_socket_thread() exiting");
}
int local_connect_arbitrary_ports(int console_port, int adb_port)
{
    char buf[64];
    int  fd = -1;

#if ADB_HOST
    const char *host = getenv("ADBHOST");
    if (host) {
        fd = socket_network_client(host, adb_port, SOCK_STREAM);
    }
#endif
    if (fd < 0) {
        fd = socket_loopback_client(adb_port, SOCK_STREAM);
    }

    if (fd >= 0) {
        D("client: connected on remote on fd %d\n", fd);
        close_on_exec(fd);
        disable_tcp_nagle(fd);
        snprintf(buf, sizeof buf, "emulator-%d", console_port);
        register_socket_transport(fd, buf, adb_port, 1);
        return 0;
    }
    return -1;
}
Пример #7
0
static void server_socket_thread(void* arg) {
    int serverfd, fd;
    int port = (int) (uintptr_t) arg;

    adb_thread_setname("server socket");
    D("transport: server_socket_thread() starting");
    serverfd = -1;
    for(;;) {
        if(serverfd == -1) {
            std::string error;
            serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error);
            if(serverfd < 0) {
                D("server: cannot bind socket yet: %s", error.c_str());
                std::this_thread::sleep_for(1s);
                continue;
            }
            close_on_exec(serverfd);
        }

        D("server: trying to get new connection from %d", port);
        fd = adb_socket_accept(serverfd, nullptr, nullptr);
        if(fd >= 0) {
            D("server: new connection on fd %d", fd);
            close_on_exec(fd);
            disable_tcp_nagle(fd);
            std::string serial = android::base::StringPrintf("host-%d", fd);
            if (register_socket_transport(fd, serial.c_str(), port, 1) != 0) {
                adb_close(fd);
            }
        }
    }
    D("transport: server_socket_thread() exiting");
}
Пример #8
0
static int connect_device(char* host, char* buffer, int buffer_size)
{
    int port, fd;
    char* portstr = strchr(host, ':');
    char hostbuf[100];
    char serial[100];
    int ret;

    strncpy(hostbuf, host, sizeof(hostbuf) - 1);
    if (portstr) {
        if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
            snprintf(buffer, buffer_size, "bad host name %s", host);
            return 0;
        }
        // zero terminate the host at the point we found the colon
        hostbuf[portstr - host] = 0;
        if (sscanf(portstr + 1, "%d", &port) == 0) {
            snprintf(buffer, buffer_size, "bad port number %s", portstr);
            return 0;
        }
    } else {
        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
    }

    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);

    fd = socket_network_client_timeout(hostbuf, port, SOCK_STREAM, 10);
    if (fd < 0) {
        snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
        return 0;
    }

    D("client: connected on remote on fd %d\n", fd);
    close_on_exec(fd);
    disable_tcp_nagle(fd);
    enable_keepalive(fd);
    ret = register_socket_transport(fd, serial, port, 0);
    if (ret < 0) {
        adb_close(fd);
        snprintf(buffer, buffer_size, "already connected to %s", serial);
        return 0;
    } else {
        snprintf(buffer, buffer_size, "connected to %s", serial);
    }
    return 1;
}
static void connect_device(const std::string& host, std::string* response) {
    if (host.empty()) {
        *response = "empty host name";
        return;
    }

    std::vector<std::string> pieces = android::base::Split(host, ":");
    const std::string& hostname = pieces[0];

    int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
    if (pieces.size() > 1) {
        if (sscanf(pieces[1].c_str(), "%d", &port) != 1) {
            *response = android::base::StringPrintf("bad port number %s", pieces[1].c_str());
            return;
        }
    }

    // This may look like we're putting 'host' back together,
    // but we're actually inserting the default port if necessary.
    std::string serial = android::base::StringPrintf("%s:%d", hostname.c_str(), port);

    int fd = socket_network_client_timeout(hostname.c_str(), port, SOCK_STREAM, 10);
    if (fd < 0) {
        *response = android::base::StringPrintf("unable to connect to %s:%d",
                                                hostname.c_str(), port);
        return;
    }

    D("client: connected on remote on fd %d\n", fd);
    close_on_exec(fd);
    disable_tcp_nagle(fd);

    int ret = register_socket_transport(fd, serial.c_str(), port, 0);
    if (ret < 0) {
        adb_close(fd);
        *response = android::base::StringPrintf("already connected to %s", serial.c_str());
    } else {
        *response = android::base::StringPrintf("connected to %s", serial.c_str());
    }
}
/* A worker thread that monitors host connections, and registers a transport for
 * every new host connection. This thread replaces server_socket_thread on
 * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD
 * pipe to communicate with adbd daemon inside the guest. This is done in order
 * to provide more robust communication channel between ADB host and guest. The
 * main issue with server_socket_thread approach is that it runs on top of TCP,
 * and thus is sensitive to network disruptions. For instance, the
 * ConnectionManager may decide to reset all network connections, in which case
 * the connection between ADB host and guest will be lost. To make ADB traffic
 * independent from the network, we use here 'adb' QEMUD service to transfer data
 * between the host, and the guest. See external/qemu/android/adb-*.* that
 * implements the emulator's side of the protocol. Another advantage of using
 * QEMUD approach is that ADB will be up much sooner, since it doesn't depend
 * anymore on network being set up.
 * The guest side of the protocol contains the following phases:
 * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service
 *   is opened, and it becomes clear whether or not emulator supports that
 *   protocol.
 * - Wait for the ADB host to create connection with the guest. This is done by
 *   sending an 'accept' request to the adb QEMUD service, and waiting on
 *   response.
 * - When new ADB host connection is accepted, the connection with adb QEMUD
 *   service is registered as the transport, and a 'start' request is sent to the
 *   adb QEMUD service, indicating that the guest is ready to receive messages.
 *   Note that the guest will ignore messages sent down from the emulator before
 *   the transport registration is completed. That's why we need to send the
 *   'start' request after the transport is registered.
 */
static void *qemu_socket_thread(void * arg)
{
/* 'accept' request to the adb QEMUD service. */
static const char _accept_req[] = "accept";
/* 'start' request to the adb QEMUD service. */
static const char _start_req[]  = "start";
/* 'ok' reply from the adb QEMUD service. */
static const char _ok_resp[]    = "ok";

    const int port = (int) (uintptr_t) arg;
    int res, fd;
    char tmp[256];
    char con_name[32];

    D("transport: qemu_socket_thread() starting\n");

    /* adb QEMUD service connection request. */
    snprintf(con_name, sizeof(con_name), "qemud:adb:%d", port);

    /* Connect to the adb QEMUD service. */
    fd = qemu_pipe_open(con_name);
    if (fd < 0) {
        /* This could be an older version of the emulator, that doesn't
         * implement adb QEMUD service. Fall back to the old TCP way. */
        D("adb service is not available. Falling back to TCP socket.\n");
        adb_thread_create(server_socket_thread, arg);
        return 0;
    }

    for(;;) {
        /*
         * Wait till the host creates a new connection.
         */

        /* Send the 'accept' request. */
        res = adb_write(fd, _accept_req, strlen(_accept_req));
        if ((size_t)res == strlen(_accept_req)) {
            /* Wait for the response. In the response we expect 'ok' on success,
             * or 'ko' on failure. */
            res = adb_read(fd, tmp, sizeof(tmp));
            if (res != 2 || memcmp(tmp, _ok_resp, 2)) {
                D("Accepting ADB host connection has failed.\n");
                adb_close(fd);
            } else {
                /* Host is connected. Register the transport, and start the
                 * exchange. */
                register_socket_transport(fd, "host", port, 1);
                adb_write(fd, _start_req, strlen(_start_req));
            }

            /* Prepare for accepting of the next ADB host connection. */
            fd = qemu_pipe_open(con_name);
            if (fd < 0) {
                D("adb service become unavailable.\n");
                return 0;
            }
        } else {
            D("Unable to send the '%s' request to ADB service.\n", _accept_req);
            return 0;
        }
    }
    D("transport: qemu_socket_thread() exiting\n");
    return 0;
}