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; }
/* 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; }