diff mbox

[3/7] qemu-char: Wait until socket connect to report connected

Message ID 1393979937-9082-4-git-send-email-minyard@acm.org
State New
Headers show

Commit Message

Corey Minyard March 5, 2014, 12:38 a.m. UTC
From: Corey Minyard <cminyard@mvista.com>

The socket code was reporting that a socket connection was connected
as soon as the connect call was issued.  If the connection failed, it
would then report it was not connected.  With the reconnect code, it's
better to wait until the connection is actually operational before
reporting that the socket is connected.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
---
 qemu-char.c | 49 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 40 insertions(+), 9 deletions(-)
diff mbox

Patch

diff --git a/qemu-char.c b/qemu-char.c
index d9838aa..6d6dd36 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2310,9 +2310,10 @@  static CharDriverState *qemu_chr_open_udp(CharDriverState *chr, QemuOpts *opts)
 typedef struct {
 
     GIOChannel *chan, *listen_chan;
+    int waitsrc;
     guint listen_tag;
     int fd, listen_fd;
-    int connected;
+    enum { TCP_NOT_CONNECTED, TCP_WAITING_CONNECT, TCP_CONNECTED } state;
     int max_size;
     int do_telnetopt;
     int do_nodelay;
@@ -2325,7 +2326,7 @@  static gboolean tcp_chr_accept(GIOChannel *chan, GIOCondition cond, void *opaque
 static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     TCPCharDriver *s = chr->opaque;
-    if (s->connected) {
+    if (s->state == TCP_CONNECTED) {
         return io_channel_send(s->chan, buf, len);
     } else {
         /* XXX: indicate an error ? */
@@ -2337,7 +2338,7 @@  static int tcp_chr_read_poll(void *opaque)
 {
     CharDriverState *chr = opaque;
     TCPCharDriver *s = chr->opaque;
-    if (!s->connected)
+    if (s->state != TCP_CONNECTED)
         return 0;
     s->max_size = qemu_chr_be_can_write(chr);
     return s->max_size;
@@ -2482,7 +2483,7 @@  static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
     uint8_t buf[READ_BUF_LEN];
     int len, size;
 
-    if (!s->connected || s->max_size <= 0) {
+    if (s->state != TCP_CONNECTED || s->max_size <= 0) {
         return TRUE;
     }
     len = sizeof(buf);
@@ -2491,7 +2492,7 @@  static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
     size = tcp_chr_recv(chr, (void *)buf, len);
     if (size == 0) {
         /* connection closed */
-        s->connected = 0;
+        s->state = TCP_NOT_CONNECTED;
         if (s->listen_chan) {
             s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr);
         }
@@ -2518,17 +2519,48 @@  CharDriverState *qemu_chr_open_eventfd(CharDriverState *chr, int eventfd)
 }
 #endif
 
-static void tcp_chr_connect(void *opaque)
+static gboolean tcp_wait_connect(GIOChannel *source,
+                                 GIOCondition condition,
+                                 gpointer opaque)
 {
     CharDriverState *chr = opaque;
     TCPCharDriver *s = chr->opaque;
 
-    s->connected = 1;
+    if (s->state != TCP_WAITING_CONNECT) {
+        return FALSE;
+    }
+    if (condition & G_IO_ERR || condition & G_IO_HUP) {
+        /* The connected failed */
+        s->state = TCP_NOT_CONNECTED;
+        g_io_channel_unref(s->chan);
+        s->chan = NULL;
+        closesocket(s->fd);
+        s->fd = -1;
+        return FALSE;
+    }
+
+    s->state = TCP_CONNECTED;
     if (s->chan) {
         chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll,
                                            tcp_chr_read, chr);
     }
     qemu_chr_be_generic_open(chr);
+    return FALSE;
+}
+
+static void tcp_chr_connect(void *opaque)
+{
+    CharDriverState *chr = opaque;
+    TCPCharDriver *s = chr->opaque;
+
+    s->state = TCP_WAITING_CONNECT;
+    if (s->chan) {
+        /* Wait until write becomes ready before reporting connected. */
+        s->waitsrc = g_io_add_watch(s->chan,
+                                    G_IO_OUT | G_IO_HUP | G_IO_ERR,
+                                    tcp_wait_connect,
+                                    chr);
+    }
 }
 
 #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
@@ -2650,7 +2682,7 @@  static CharDriverState *qemu_chr_open_socket_fd(CharDriverState *chr,
 
     s = g_malloc0(sizeof(TCPCharDriver));
 
-    s->connected = 0;
+    s->state = TCP_NOT_CONNECTED;
     s->fd = -1;
     s->listen_fd = -1;
     s->msgfd = -1;
@@ -2695,7 +2727,6 @@  static CharDriverState *qemu_chr_open_socket_fd(CharDriverState *chr,
             s->do_telnetopt = 1;
         }
     } else {
-        s->connected = 1;
         s->fd = fd;
         socket_set_nodelay(fd);
         s->chan = io_channel_from_socket(s->fd);