]> Git Repo - qemu.git/blobdiff - net/socket.c
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
[qemu.git] / net / socket.c
index b8c931e762841e480675b89e2c1455617cb8576d..f85ef7d61b998abc051615b323ac75baaabf34e1 100644 (file)
@@ -174,7 +174,7 @@ static void net_socket_send(void *opaque)
         closesocket(s->fd);
 
         s->fd = -1;
-        net_socket_rs_init(&s->rs, net_socket_rs_finalize);
+        net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
         s->nc.link_down = true;
         memset(s->nc.info_str, 0, sizeof(s->nc.info_str));
 
@@ -366,7 +366,7 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
     s->fd = fd;
     s->listen_fd = -1;
     s->send_fn = net_socket_send_dgram;
-    net_socket_rs_init(&s->rs, net_socket_rs_finalize);
+    net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
     net_socket_read_poll(s, true);
 
     /* mcast: save bound address as dst */
@@ -417,7 +417,7 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer,
 
     s->fd = fd;
     s->listen_fd = -1;
-    net_socket_rs_init(&s->rs, net_socket_rs_finalize);
+    net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
 
     /* Disable Nagle algorithm on TCP sockets to reduce latency */
     socket_set_nodelay(fd);
@@ -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);
+    net_socket_rs_init(&s->rs, net_socket_rs_finalize, false);
 
     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,
This page took 0.025689 seconds and 4 git commands to generate.