Patchwork [5/7] VNC: Cache client info at connection time

login
register
mail settings
Submitter Luiz Capitulino
Date Jan. 8, 2010, 9:47 p.m.
Message ID <1262987236-2943-6-git-send-email-lcapitulino@redhat.com>
Download mbox | patch
Permalink /patch/42539/
State New
Headers show

Comments

Luiz Capitulino - Jan. 8, 2010, 9:47 p.m.
When a disconnection happens the client's socket on QEMU
side may become invalid, this way it won't be possible
to query it to get client information, which is going to
be needed by the future VNC disconnect QMP event.

To always have this information available we query the
socket at connection time and cache the client info in
struct VncState.

Note that the caching occurs in protocol_client_init(),
meaning that client information is only available _after_
the client has successfully authenticated if an
authentication method is being used.

This is also true for 'query-vnc' or 'info vnc'. If any
kind of authentication is enabled and the client is
connected but didn't authenticate yet, its info won't
be available.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 vnc.c |   19 ++++++++++++-------
 vnc.h |    2 ++
 2 files changed, 14 insertions(+), 7 deletions(-)

Patch

diff --git a/vnc.c b/vnc.c
index a6e54f3..f340d08 100644
--- a/vnc.c
+++ b/vnc.c
@@ -230,14 +230,14 @@  static int vnc_server_info_put(QDict *qdict)
     return 0;
 }
 
-static QDict *do_info_vnc_client(Monitor *mon, VncState *client)
+static void vnc_client_cache_info(VncState *client)
 {
     QDict *qdict;
 
     qdict = qdict_new();
     if (vnc_qdict_remote_addr(qdict, client->csock) < 0) {
         QDECREF(qdict);
-        return NULL;
+        return;
     }
 
 #ifdef CONFIG_VNC_TLS
@@ -254,7 +254,7 @@  static QDict *do_info_vnc_client(Monitor *mon, VncState *client)
     }
 #endif
 
-    return qdict;
+    client->info = QOBJECT(qdict);
 }
 
 static void info_vnc_iter(QObject *obj, void *opaque)
@@ -337,16 +337,17 @@  void do_info_vnc(Monitor *mon, QObject **ret_data)
     if (vnc_display == NULL || vnc_display->display == NULL) {
         *ret_data = qobject_from_jsonf("{ 'enabled': false }");
     } else {
-        QDict *qdict;
         QList *clist;
 
         clist = qlist_new();
         if (vnc_display->clients) {
             VncState *client = vnc_display->clients;
             while (client) {
-                qdict = do_info_vnc_client(mon, client);
-                if (qdict)
-                    qlist_append(clist, qdict);
+                if (client->info) {
+                    /* incref so that it's not freed by upper layers */
+                    qobject_incref(client->info);
+                    qlist_append_obj(clist, client->info);
+                }
                 client = client->next;
             }
         }
@@ -1099,6 +1100,8 @@  static void vnc_disconnect_finish(VncState *vs)
     if (!vs->vd->clients)
         dcl->idle = 1;
 
+    qobject_decref(vs->info);
+
     vnc_remove_timer(vs->vd);
     qemu_free(vs);
 }
@@ -2053,6 +2056,8 @@  static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
     char buf[1024];
     int size;
 
+    vnc_client_cache_info(vs);
+
     vnc_write_u16(vs, ds_get_width(vs->ds));
     vnc_write_u16(vs, ds_get_height(vs->ds));
 
diff --git a/vnc.h b/vnc.h
index fcc6824..1210824 100644
--- a/vnc.h
+++ b/vnc.h
@@ -144,6 +144,8 @@  struct VncState
     VncStateSASL sasl;
 #endif
 
+    QObject *info;
+
     Buffer output;
     Buffer input;
     /* current output mode information */