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

Submitted by Luiz Capitulino on Jan. 8, 2010, 9:47 p.m.

Details

Message ID 1262987236-2943-6-git-send-email-lcapitulino@redhat.com
State New
Headers show

Commit Message

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 hide | download patch | download mbox

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 */