diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 127 |
1 files changed, 56 insertions, 71 deletions
diff --git a/net/socket.c b/net/socket.c index b8c931e762..dcae1ae2c0 100644 --- a/net/socket.c +++ b/net/socket.c @@ -489,106 +489,91 @@ static int net_socket_listen_init(NetClientState *peer, { NetClientState *nc; NetSocketState *s; - SocketAddress *saddr; - int ret; - Error *local_error = NULL; + struct sockaddr_in saddr; + int fd, ret; - saddr = socket_parse(host_str, &local_error); - if (saddr == NULL) { - error_report_err(local_error); + if (parse_host_port(&saddr, host_str) < 0) + return -1; + + fd = qemu_socket(PF_INET, SOCK_STREAM, 0); + if (fd < 0) { + perror("socket"); return -1; } + qemu_set_nonblock(fd); + + socket_set_fast_reuse(fd); - ret = socket_listen(saddr, &local_error); + ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { - qapi_free_SocketAddress(saddr); - error_report_err(local_error); + perror("bind"); + closesocket(fd); + return -1; + } + ret = listen(fd, 0); + if (ret < 0) { + perror("listen"); + closesocket(fd); return -1; } nc = qemu_new_net_client(&net_socket_info, peer, model, name); s = DO_UPCAST(NetSocketState, nc, nc); s->fd = -1; - s->listen_fd = ret; + s->listen_fd = fd; s->nc.link_down = true; net_socket_rs_init(&s->rs, net_socket_rs_finalize); qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); - qapi_free_SocketAddress(saddr); return 0; } -typedef struct { - NetClientState *peer; - SocketAddress *saddr; - char *model; - char *name; -} socket_connect_data; - -static void socket_connect_data_free(socket_connect_data *c) -{ - qapi_free_SocketAddress(c->saddr); - g_free(c->model); - g_free(c->name); - g_free(c); -} - -static void net_socket_connected(int fd, Error *err, void *opaque) -{ - socket_connect_data *c = opaque; - NetSocketState *s; - char *addr_str = NULL; - Error *local_error = NULL; - - addr_str = socket_address_to_string(c->saddr, &local_error); - if (addr_str == NULL) { - error_report_err(local_error); - closesocket(fd); - goto end; - } - - s = net_socket_fd_init(c->peer, c->model, c->name, fd, true); - if (!s) { - closesocket(fd); - goto end; - } - - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "socket: connect to %s", addr_str); - -end: - g_free(addr_str); - socket_connect_data_free(c); -} - static int net_socket_connect_init(NetClientState *peer, const char *model, const char *name, const char *host_str) { - socket_connect_data *c = g_new0(socket_connect_data, 1); - int fd = -1; - Error *local_error = NULL; + NetSocketState *s; + int fd, connected, ret; + struct sockaddr_in saddr; - c->peer = peer; - c->model = g_strdup(model); - c->name = g_strdup(name); - c->saddr = socket_parse(host_str, &local_error); - if (c->saddr == NULL) { - goto err; - } + if (parse_host_port(&saddr, host_str) < 0) + return -1; - fd = socket_connect(c->saddr, net_socket_connected, c, &local_error); + fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { - goto err; + perror("socket"); + return -1; } + qemu_set_nonblock(fd); + connected = 0; + for(;;) { + ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); + if (ret < 0) { + if (errno == EINTR || errno == EWOULDBLOCK) { + /* continue */ + } else if (errno == EINPROGRESS || + errno == EALREADY || + errno == EINVAL) { + break; + } else { + perror("connect"); + closesocket(fd); + return -1; + } + } else { + connected = 1; + break; + } + } + s = net_socket_fd_init(peer, model, name, fd, connected); + if (!s) + return -1; + snprintf(s->nc.info_str, sizeof(s->nc.info_str), + "socket: connect to %s:%d", + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; - -err: - error_report_err(local_error); - socket_connect_data_free(c); - return -1; } static int net_socket_mcast_init(NetClientState *peer, |