Patchwork [16/17] chardev: add udp support to qapi

login
register
mail settings
Submitter Gerd Hoffmann
Date Feb. 28, 2013, 7:50 a.m.
Message ID <1362037809-27836-17-git-send-email-kraxel@redhat.com>
Download mbox | patch
Permalink /patch/223795/
State New
Headers show

Comments

Gerd Hoffmann - Feb. 28, 2013, 7:50 a.m.
This patch adds 'udb' support to qapi.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/qemu/sockets.h |    1 +
 qapi-schema.json       |   16 +++++++++++++++-
 qemu-char.c            |   44 ++++++++++++++++++++++++++------------------
 util/qemu-sockets.c    |   25 +++++++++++++++++++++++++
 4 files changed, 67 insertions(+), 19 deletions(-)
Eric Blake - March 8, 2013, 4:36 p.m.
On 02/28/2013 12:50 AM, Gerd Hoffmann wrote:
> This patch adds 'udb' support to qapi.

If it's not too late:

s/udb/udp/

> 
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
Gerd Hoffmann - March 11, 2013, 7:58 a.m.
On 03/08/13 17:36, Eric Blake wrote:
> On 02/28/2013 12:50 AM, Gerd Hoffmann wrote:
>> This patch adds 'udb' support to qapi.
> 
> If it's not too late:
> 
> s/udb/udp/

It's not, need to rebase after flow control series, I'll fix it up
along the way.

cheers,
  Gerd

Patch

diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 803ae17..463f8b8 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -69,6 +69,7 @@  SocketAddress *socket_parse(const char *str, Error **errp);
 int socket_connect(SocketAddress *addr, Error **errp,
                    NonBlockingConnectHandler *callback, void *opaque);
 int socket_listen(SocketAddress *addr, Error **errp);
+int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
 
 /* Old, ipv4 only bits.  Don't use for new code. */
 int parse_host_port(struct sockaddr_in *saddr, const char *str);
diff --git a/qapi-schema.json b/qapi-schema.json
index 59c025f..ba023fb 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3166,7 +3166,7 @@ 
 ##
 # @ChardevSocket:
 #
-# Configuration info for socket chardevs.
+# Configuration info for (stream) socket chardevs.
 #
 # @addr: socket address to listen on (server=true)
 #        or connect to (server=false)
@@ -3185,6 +3185,19 @@ 
                                      '*telnet'  : 'bool' } }
 
 ##
+# @ChardevDgram:
+#
+# Configuration info for datagram socket chardevs.
+#
+# @remote: remote address
+# @local: #optional local address
+#
+# Since: 1.5
+##
+{ 'type': 'ChardevDgram', 'data': { 'remote' : 'SocketAddress',
+                                    '*local' : 'SocketAddress' } }
+
+##
 # @ChardevMux:
 #
 # Configuration info for mux chardevs.
@@ -3272,6 +3285,7 @@ 
                                        'parallel': 'ChardevHostdev',
                                        'pipe'   : 'ChardevHostdev',
                                        'socket' : 'ChardevSocket',
+                                       'dgram'  : 'ChardevDgram',
                                        'pty'    : 'ChardevDummy',
                                        'null'   : 'ChardevDummy',
                                        'mux'    : 'ChardevMux',
diff --git a/qemu-char.c b/qemu-char.c
index a18d88d..d16c34f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2057,21 +2057,14 @@  static void udp_chr_close(CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
+static CharDriverState *qemu_chr_open_udp_fd(int fd)
 {
     CharDriverState *chr = NULL;
     NetCharDriver *s = NULL;
-    Error *local_err = NULL;
-    int fd = -1;
 
     chr = g_malloc0(sizeof(CharDriverState));
     s = g_malloc0(sizeof(NetCharDriver));
 
-    fd = inet_dgram_opts(opts, &local_err);
-    if (fd < 0) {
-        goto return_err;
-    }
-
     s->fd = fd;
     s->bufcnt = 0;
     s->bufptr = 0;
@@ -2080,18 +2073,18 @@  static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
     chr->chr_update_read_handler = udp_chr_update_read_handler;
     chr->chr_close = udp_chr_close;
     return chr;
+}
 
-return_err:
-    if (local_err) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-    }
-    g_free(chr);
-    g_free(s);
-    if (fd >= 0) {
-        closesocket(fd);
+static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
+{
+    Error *local_err = NULL;
+    int fd = -1;
+
+    fd = inet_dgram_opts(opts, &local_err);
+    if (fd < 0) {
+        return NULL;
     }
-    return NULL;
+    return qemu_chr_open_udp_fd(fd);
 }
 
 /***********************************************************/
@@ -3489,6 +3482,18 @@  static CharDriverState *qmp_chardev_open_socket(ChardevSocket *sock,
                                    is_telnet, is_waitconnect, errp);
 }
 
+static CharDriverState *qmp_chardev_open_dgram(ChardevDgram *dgram,
+                                               Error **errp)
+{
+    int fd;
+
+    fd = socket_dgram(dgram->remote, dgram->local, errp);
+    if (error_is_set(errp)) {
+        return NULL;
+    }
+    return qemu_chr_open_udp_fd(fd);
+}
+
 ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
                                Error **errp)
 {
@@ -3518,6 +3523,9 @@  ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
     case CHARDEV_BACKEND_KIND_SOCKET:
         chr = qmp_chardev_open_socket(backend->socket, errp);
         break;
+    case CHARDEV_BACKEND_KIND_DGRAM:
+        chr = qmp_chardev_open_dgram(backend->dgram, errp);
+        break;
 #ifdef HAVE_CHARDEV_TTY
     case CHARDEV_BACKEND_KIND_PTY:
         chr = qemu_chr_open_pty(id, ret);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 1350ccc..d14b673 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -945,6 +945,31 @@  int socket_listen(SocketAddress *addr, Error **errp)
     return fd;
 }
 
+int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
+{
+    QemuOpts *opts;
+    int fd;
+
+    opts = qemu_opts_create_nofail(&dummy_opts);
+    switch (remote->kind) {
+    case SOCKET_ADDRESS_KIND_INET:
+        qemu_opt_set(opts, "host", remote->inet->host);
+        qemu_opt_set(opts, "port", remote->inet->port);
+        if (local) {
+            qemu_opt_set(opts, "localaddr", local->inet->host);
+            qemu_opt_set(opts, "localport", local->inet->port);
+        }
+        fd = inet_dgram_opts(opts, errp);
+        break;
+
+    default:
+        error_setg(errp, "socket type unsupported for datagram");
+        return -1;
+    }
+    qemu_opts_del(opts);
+    return fd;
+}
+
 #ifdef _WIN32
 static void socket_cleanup(void)
 {