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) {
        W("No callback for AsyncSocketConnector for socket '%s'",
          sock_address_to_string(address));
        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

    /* Create a looper for asynchronous I/O. */
    if (looper == NULL) {
        connector->looper = looper_newCore();
        if (connector->looper == NULL) {
            E("Unable to create I/O looper for AsyncSocketConnector for socket '%s'",
              _asc_socket_string(connector));
            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. */
    loopTimer_init(connector->connector_timer, connector->looper,
                   _on_async_socket_connector_retry, connector);

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

    return connector;
}
static const char *sock_address_strfamily(SockAddress *s)
{
    switch (sock_address_get_family(s)) {
    case SOCKET_IN6:   return "ipv6";
    case SOCKET_INET:  return "ipv4";
    case SOCKET_UNIX:  return "unix";
    default:           return "????";
    }
}
void*
netPipe_initFromAddress( void* hwpipe, const SockAddress*  address, Looper* looper )
{
    NetPipe*     pipe;

    ANEW0(pipe);

    pipe->hwpipe = hwpipe;
    pipe->state  = STATE_INIT;

    {
        AsyncStatus  status;

        int  fd = socket_create( sock_address_get_family(address), SOCKET_STREAM );
        if (fd < 0) {
            D("%s: Could create socket from address family!", __FUNCTION__);
            netPipe_free(pipe);
            return NULL;
        }

        loopIo_init(pipe->io, looper, fd, netPipe_io_func, pipe);
        asyncConnector_init(pipe->connector, address, pipe->io);
        pipe->state = STATE_CONNECTING;

        status = asyncConnector_run(pipe->connector);
        if (status == ASYNC_ERROR) {
            D("%s: Could not connect to socket: %s",
              __FUNCTION__, errno_str);
            netPipe_free(pipe);
            return NULL;
        }
        if (status == ASYNC_COMPLETE) {
            pipe->state = STATE_CONNECTED;
            netPipe_resetState(pipe);
        }
    }

    return pipe;
}
int inet_listen_opts(QemuOpts *opts, int port_offset)
{
    SockAddress**  list;
    SockAddress*   e;
    unsigned       flags = SOCKET_LIST_PASSIVE;
    const char *addr;
    char port[33];
    char uaddr[256+1];
    char uport[33];
    int slisten,to,try_next,nn;

#ifdef CONFIG_ANDROID
    const char* socket_fd = qemu_opt_get(opts, "socket");
    if (socket_fd) {
        return atoi(socket_fd);
    }
#endif

    if ((qemu_opt_get(opts, "host") == NULL) ||
        (qemu_opt_get(opts, "port") == NULL)) {
        fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
        return -1;
    }
    pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
    addr = qemu_opt_get(opts, "host");

    to = qemu_opt_get_number(opts, "to", 0);
    if (qemu_opt_get_bool(opts, "ipv4", 0))
        flags |= SOCKET_LIST_FORCE_INET;
    if (qemu_opt_get_bool(opts, "ipv6", 0))
        flags |= SOCKET_LIST_FORCE_IN6;

    /* lookup */
    if (port_offset)
        snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);

    list = sock_address_list_create( strlen(addr) ? addr : NULL,
                                       port,
                                       flags );
    if (list == NULL) {
        fprintf(stderr,"%s: getaddrinfo(%s,%s): %s\n", __FUNCTION__,
                addr, port, errno_str);
        return -1;
    }

    /* create socket + bind */
    for (nn = 0; list[nn] != NULL; nn++) {
        SocketFamily  family;

        e      = list[nn];
        family = sock_address_get_family(e);

        sock_address_get_numeric_info(e, uaddr, sizeof uaddr, uport, sizeof uport);
        slisten = socket_create(family, SOCKET_STREAM);
        if (slisten < 0) {
            fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
                    sock_address_strfamily(e), errno_str);
            continue;
        }

        socket_set_xreuseaddr(slisten);
#ifdef IPV6_V6ONLY
        /* listen on both ipv4 and ipv6 */
        if (family == SOCKET_IN6) {
            socket_set_ipv6only(slisten);
        }
#endif

        for (;;) {
            if (socket_bind(slisten, e) == 0) {
                if (sockets_debug)
                    fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
                        sock_address_strfamily(e), uaddr, sock_address_get_port(e));
                goto listen;
            }
            socket_close(slisten);
            try_next = to && (sock_address_get_port(e) <= to + port_offset);
            if (!try_next || sockets_debug)
                fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
                        sock_address_strfamily(e), uaddr, sock_address_get_port(e),
                        strerror(errno));
            if (try_next) {
                sock_address_set_port(e, sock_address_get_port(e) + 1);
                continue;
            }
            break;
        }
    }
    sock_address_list_free(list);
    fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
    return -1;

listen:
    if (socket_listen(slisten,1) != 0) {
        perror("listen");
        socket_close(slisten);
        return -1;
    }
    snprintf(uport, sizeof(uport), "%d", sock_address_get_port(e) - port_offset);
    qemu_opt_set(opts, "host", uaddr);
    qemu_opt_set(opts, "port", uport);
    qemu_opt_set(opts, "ipv6", (e->family == SOCKET_IN6) ? "on" : "off");
    qemu_opt_set(opts, "ipv4", (e->family != SOCKET_IN6) ? "on" : "off");
    sock_address_list_free(list);
    return slisten;
}
int inet_dgram_opts(QemuOpts *opts)
{
    SockAddress**  peer_list = NULL;
    SockAddress**  local_list = NULL;
    SockAddress*   e;
    unsigned       flags = 0;
    const char *addr;
    const char *port;
    char uaddr[INET6_ADDRSTRLEN+1];
    char uport[33];
    int sock = -1;
    int nn;

    /* lookup peer addr */
    addr = qemu_opt_get(opts, "host");
    port = qemu_opt_get(opts, "port");
    if (addr == NULL || strlen(addr) == 0) {
        addr = "localhost";
    }
    if (port == NULL || strlen(port) == 0) {
        fprintf(stderr, "inet_dgram: port not specified\n");
        return -1;
    }

    flags = SOCKET_LIST_DGRAM;
    if (qemu_opt_get_bool(opts, "ipv4", 0)) {
        flags &= SOCKET_LIST_FORCE_IN6;
        flags |= SOCKET_LIST_FORCE_INET;
    }
    if (qemu_opt_get_bool(opts, "ipv6", 0)) {
        flags &= SOCKET_LIST_FORCE_INET;
        flags |= SOCKET_LIST_FORCE_IN6;
    }

    peer_list = sock_address_list_create(addr, port, flags);
    if (peer_list == NULL) {
        fprintf(stderr,"getaddrinfo(%s,%s): %s\n",
                addr, port, errno_str);
        return -1;
    }

    /* lookup local addr */
    addr = qemu_opt_get(opts, "localaddr");
    port = qemu_opt_get(opts, "localport");
    if (addr == NULL || strlen(addr) == 0) {
        addr = NULL;
    }
    if (!port || strlen(port) == 0)
        port = "0";

    flags = SOCKET_LIST_DGRAM | SOCKET_LIST_PASSIVE;
    local_list = sock_address_list_create(addr, port, flags);
    if (local_list == NULL) {
        fprintf(stderr,"getaddrinfo(%s,%s): %s\n",
                addr, port, errno_str);
        goto EXIT;
    }

    if (sock_address_get_numeric_info(local_list[0],
                                       uaddr, INET6_ADDRSTRLEN,
                                       uport, 32)) {
        fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
        goto EXIT;
    }

    for (nn = 0; peer_list[nn] != NULL; nn++) {
        SockAddress *local = local_list[0];
        e    = peer_list[nn];
        sock = socket_create(sock_address_get_family(e), SOCKET_DGRAM);
        if (sock < 0) {
            fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
            sock_address_strfamily(e), errno_str);
            continue;
        }
        socket_set_xreuseaddr(sock);

        /* bind socket */
        if (socket_bind(sock, local) < 0) {
            fprintf(stderr,"%s: bind(%s,%s,%s): OK\n", __FUNCTION__,
                sock_address_strfamily(local), addr, port);
            socket_close(sock);
            continue;
        }

        /* connect to peer */
        if (socket_connect(sock,e) < 0) {
            if (sockets_debug)
                fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
                        sock_address_strfamily(e),
                        sock_address_to_string(e), addr, port, strerror(errno));
            socket_close(sock);
            continue;
        }
        if (sockets_debug)
            fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
                        sock_address_strfamily(e),
                        sock_address_to_string(e), addr, port);

        goto EXIT;
    }
    sock = -1;
EXIT:
    if (local_list)
        sock_address_list_free(local_list);
    if (peer_list)
        sock_address_list_free(peer_list);
    return sock;
}
int inet_connect_opts(QemuOpts *opts)
{
    SockAddress**  list;
    SockAddress*   e;
    unsigned       flags = 0;
    const char *addr;
    const char *port;
    int sock, nn;

#ifdef CONFIG_ANDROID
    const char* socket_fd = qemu_opt_get(opts, "socket");
    if (socket_fd) {
        return atoi(socket_fd);
    }
#endif

    addr = qemu_opt_get(opts, "host");
    port = qemu_opt_get(opts, "port");
    if (addr == NULL || port == NULL) {
        fprintf(stderr, "inet_connect: host and/or port not specified\n");
        return -1;
    }

    if (qemu_opt_get_bool(opts, "ipv4", 0)) {
        flags &= SOCKET_LIST_FORCE_IN6;
        flags |= SOCKET_LIST_FORCE_INET;
    }
    if (qemu_opt_get_bool(opts, "ipv6", 0)) {
        flags &= SOCKET_LIST_FORCE_INET;
        flags |= SOCKET_LIST_FORCE_IN6;
    }

    /* lookup */
    list = sock_address_list_create(addr, port, flags);
    if (list == NULL) {
        fprintf(stderr,"getaddrinfo(%s,%s): %s\n",
                addr, port, errno_str);
        return -1;
    }

    for (nn = 0; list[nn] != NULL; nn++) {
        e     = list[nn];
        sock = socket_create(sock_address_get_family(e), SOCKET_STREAM);
        if (sock < 0) {
            fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
            sock_address_strfamily(e), errno_str);
            continue;
        }
        socket_set_xreuseaddr(sock);

        /* connect to peer */
        if (socket_connect(sock,e) < 0) {
            if (sockets_debug)
                fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
                        sock_address_strfamily(e),
                        sock_address_to_string(e), addr, port, strerror(errno));
            socket_close(sock);
            continue;
        }
        if (sockets_debug)
            fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
                        sock_address_strfamily(e),
                        sock_address_to_string(e), addr, port);

        goto EXIT;
    }
    sock = -1;
EXIT:
    sock_address_list_free(list);
    return sock;
}
Beispiel #7
0
/* Attaches starting UI to a running core process.
 * This routine is called from main() when -attach-core parameter is set,
 * indicating that this UI instance should attach to a running core, rather than
 * start a new core process.
 * Param:
 *  opts Android options containing non-NULL attach_core.
 * Return:
 *  0 on success, or -1 on failure.
 */
static int
attach_to_core(AndroidOptions* opts) {
    int iter;
    SockAddress console_socket;
    SockAddress** sockaddr_list;
    QEmulator* emulator;

    // Parse attach_core param extracting the host name, and the port name.
    char* console_address = strdup(opts->attach_core);
    char* host_name = console_address;
    char* port_num = strchr(console_address, ':');
    if (port_num == NULL) {
        // The host name is ommited, indicating the localhost
        host_name = "localhost";
        port_num = console_address;
    } else if (port_num == console_address) {
        // Invalid.
        derror("Invalid value %s for -attach-core parameter\n",
               opts->attach_core);
        return -1;
    } else {
        *port_num = '\0';
        port_num++;
        if (*port_num == '\0') {
            // Invalid.
            derror("Invalid value %s for -attach-core parameter\n",
                   opts->attach_core);
            return -1;
        }
    }

    /* Create socket address list for the given address, and pull appropriate
     * address to use for connection. Note that we're fine copying that address
     * out of the list, since INET and IN6 will entirely fit into SockAddress
     * structure. */
    sockaddr_list =
        sock_address_list_create(host_name, port_num, SOCKET_LIST_FORCE_INET);
    free(console_address);
    if (sockaddr_list == NULL) {
        derror("Unable to resolve address %s: %s\n",
               opts->attach_core, errno_str);
        return -1;
    }
    for (iter = 0; sockaddr_list[iter] != NULL; iter++) {
        if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_INET ||
            sock_address_get_family(sockaddr_list[iter]) == SOCKET_IN6) {
            memcpy(&console_socket, sockaddr_list[iter], sizeof(SockAddress));
            break;
        }
    }
    if (sockaddr_list[iter] == NULL) {
        derror("Unable to resolve address %s. Note that 'port' parameter passed to -attach-core\n"
               "must be resolvable into an IP address.\n", opts->attach_core);
        sock_address_list_free(sockaddr_list);
        return -1;
    }
    sock_address_list_free(sockaddr_list);

    if (attachUiImpl_create(&console_socket)) {
        return -1;
    }

    // Save core's port, and set the title.
    android_base_port = sock_address_get_port(&console_socket);
    emulator = qemulator_get();
    qemulator_set_title(emulator);

    return 0;
}