From 82e201c38ad81b466611eaa719765c9d3df59a49 Mon Sep 17 00:00:00 2001
Message-Id: <82e201c38ad81b466611eaa719765c9d3df59a49.1368111914.git.minovotn@redhat.com>
In-Reply-To: <405603258af5154387bea676be1f904b6713f6ae.1368111913.git.minovotn@redhat.com>
References: <405603258af5154387bea676be1f904b6713f6ae.1368111913.git.minovotn@redhat.com>
From: Amit Shah <amit.shah@redhat.com>
Date: Wed, 24 Apr 2013 08:18:10 +0200
Subject: [PATCH 36/65] qemu-char: convert UDP to GIOChannel

RH-Author: Amit Shah <amit.shah@redhat.com>
Message-id: <a44e29ecf6676d9a458a91b92a9a837d2c855f8e.1366724981.git.amit.shah@redhat.com>
Patchwork-id: 50814
O-Subject: [RHEL6.5 qemu-kvm PATCH 36/65] qemu-char: convert UDP to GIOChannel
Bugzilla: 909059
RH-Acked-by: Hans de Goede <hdegoede@redhat.com>
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>

From: Anthony Liguori <aliguori@us.ibm.com>

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Message-id: 775a2bd666a3d1fa008656bf97191b7573c6ffb5.1362505276.git.amit.shah@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
(cherry picked from commit 76a9644b711541472d9fb3a9b418acd55d9464a1)

Signed-off-by: Amit Shah <amit.shah@redhat.com>

Conflicts:
	qemu-char.c
---
 qemu-char.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 57 insertions(+), 11 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 qemu-char.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 57 insertions(+), 11 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 208fd89..deba461 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -652,6 +652,26 @@ static GIOChannel *io_channel_from_fd(int fd)
     return chan;
 }
 
+static GIOChannel *io_channel_from_socket(int fd)
+{
+    GIOChannel *chan;
+
+    if (fd == -1) {
+        return NULL;
+    }
+
+#ifdef _WIN32
+    chan = g_io_channel_win32_new_socket(fd);
+#else
+    chan = g_io_channel_unix_new(fd);
+#endif
+
+    g_io_channel_set_encoding(chan, NULL, NULL);
+    g_io_channel_set_buffered(chan, FALSE);
+
+    return chan;
+}
+
 static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
 {
     GIOStatus status;
@@ -1905,6 +1925,8 @@ static CharDriverState *qemu_chr_open_win_file_out(QemuOpts *opts)
 
 typedef struct {
     int fd;
+    GIOChannel *chan;
+    guint tag;
     uint8_t buf[READ_BUF_LEN];
     int bufcnt;
     int bufptr;
@@ -1914,8 +1936,17 @@ typedef struct {
 static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     NetCharDriver *s = chr->opaque;
+    gsize bytes_written;
+    GIOStatus status;
+
+    status = g_io_channel_write_chars(s->chan, (const gchar *)buf, len, &bytes_written, NULL);
+    if (status == G_IO_STATUS_EOF) {
+        return 0;
+    } else if (status != G_IO_STATUS_NORMAL) {
+        return -1;
+    }
 
-    return send(s->fd, (const void *)buf, len, 0);
+    return bytes_written;
 }
 
 static int udp_chr_read_poll(void *opaque)
@@ -1936,17 +1967,22 @@ static int udp_chr_read_poll(void *opaque)
     return s->max_size;
 }
 
-static void udp_chr_read(void *opaque)
+static gboolean udp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
 {
     CharDriverState *chr = opaque;
     NetCharDriver *s = chr->opaque;
+    gsize bytes_read = 0;
+    GIOStatus status;
 
     if (s->max_size == 0)
-        return;
-    s->bufcnt = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0);
+        return FALSE;
+    status = g_io_channel_read_chars(s->chan, (gchar *)s->buf, sizeof(s->buf),
+                                     &bytes_read, NULL);
+    s->bufcnt = bytes_read;
     s->bufptr = s->bufcnt;
-    if (s->bufcnt <= 0)
-        return;
+    if (status != G_IO_STATUS_NORMAL) {
+        return FALSE;
+    }
 
     s->bufptr = 0;
     while (s->max_size > 0 && s->bufptr < s->bufcnt) {
@@ -1954,23 +1990,32 @@ static void udp_chr_read(void *opaque)
         s->bufptr++;
         s->max_size = qemu_chr_be_can_write(chr);
     }
+
+    return TRUE;
 }
 
 static void udp_chr_update_read_handler(CharDriverState *chr)
 {
     NetCharDriver *s = chr->opaque;
 
-    if (s->fd >= 0) {
-        qemu_set_fd_handler2(s->fd, udp_chr_read_poll,
-                             udp_chr_read, NULL, chr);
+    if (s->tag) {
+        g_source_remove(s->tag);
+        s->tag = 0;
+    }
+
+    if (s->chan) {
+        s->tag = io_add_watch_poll(s->chan, udp_chr_read_poll, udp_chr_read, chr);
     }
 }
 
 static void udp_chr_close(CharDriverState *chr)
 {
     NetCharDriver *s = chr->opaque;
-    if (s->fd >= 0) {
-        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
+    if (s->tag) {
+        g_source_remove(s->tag);
+    }
+    if (s->chan) {
+        g_io_channel_unref(s->chan);
         closesocket(s->fd);
     }
     qemu_free(s);
@@ -1993,6 +2038,7 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
     }
 
     s->fd = fd;
+    s->chan = io_channel_from_socket(s->fd);
     s->bufcnt = 0;
     s->bufptr = 0;
     chr->opaque = s;
-- 
1.7.11.7

