All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL] vnc patch collection
@ 2012-02-10 10:09 Gerd Hoffmann
  2012-02-10 10:09 ` [Qemu-devel] [PATCH 1/4] Fix vnc memory corruption with width = 1400 Gerd Hoffmann
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2012-02-10 10:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

Here comes my vnc patch collection again.  Rebased to latest master.
gained one more patch.  All patches have been on the list before, the
last patch just once, the other ones multiple times.  Seems nobody wants
tp pick them up, MAINTAINERS has no vnc entry too, so I'll try a straigt
pull request this time, hoping to get the bits merged finally.

please pull,
  Gerd

The following changes since commit 57c83dacfe179bf061b8fa79d9553ebabe4d2ff4:

  make: Remove duplicate use of GLIB_CFLAGS (2012-02-09 20:44:38 +0400)

are available in the git repository at:
  git://git.kraxel.org/qemu vnc.2

Gerd Hoffmann (4):
      Fix vnc memory corruption with width = 1400
      vnc: fix ctrl key in vnc terminal emulation
      vnc: implement shared flag handling.
      vnc: lift modifier keys on client disconnect.

 qemu-options.hx |   13 +++++
 ui/vnc.c        |  135 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 ui/vnc.h        |   16 +++++++
 3 files changed, 161 insertions(+), 3 deletions(-)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 1/4] Fix vnc memory corruption with width = 1400
  2012-02-10 10:09 [Qemu-devel] [PULL] vnc patch collection Gerd Hoffmann
@ 2012-02-10 10:09 ` Gerd Hoffmann
  2012-02-10 10:09 ` [Qemu-devel] [PATCH 2/4] vnc: fix ctrl key in vnc terminal emulation Gerd Hoffmann
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2012-02-10 10:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

vnc assumes that the screen width is a multiple of 16 in several places.
If this is not the case vnc will overrun buffers, corrupt memory, make
qemu crash.

This is the minimum fix for this bug. It makes sure we don't overrun the
scanline, thereby fixing the segfault.  The rendering is *not* correct
though, there is a black border at the right side of the screen, 8
pixels wide because 1400 % 16 == 8.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/vnc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 16b79ec..5752bf8 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2445,7 +2445,7 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
             guest_ptr  = guest_row;
             server_ptr = server_row;
 
-            for (x = 0; x < vd->guest.ds->width;
+            for (x = 0; x + 15 < vd->guest.ds->width;
                     x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
                 if (!test_and_clear_bit((x / 16), vd->guest.dirty[y]))
                     continue;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 2/4] vnc: fix ctrl key in vnc terminal emulation
  2012-02-10 10:09 [Qemu-devel] [PULL] vnc patch collection Gerd Hoffmann
  2012-02-10 10:09 ` [Qemu-devel] [PATCH 1/4] Fix vnc memory corruption with width = 1400 Gerd Hoffmann
@ 2012-02-10 10:09 ` Gerd Hoffmann
  2012-02-10 10:09 ` [Qemu-devel] [PATCH 3/4] vnc: implement shared flag handling Gerd Hoffmann
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2012-02-10 10:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Make the control keys for terminals on the vnc display
(i.e. qemu -vnc :0 -serial vc) work.  Makes the terminals
alot more usable as typing Ctrl-C in your serial console
actually has the desired effect ;)

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/vnc.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 5752bf8..810582b 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1552,9 +1552,11 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
         else
             kbd_put_keycode(keycode | SCANCODE_UP);
     } else {
+        bool numlock = vs->modifiers_state[0x45];
+        bool control = (vs->modifiers_state[0x1d] ||
+                        vs->modifiers_state[0x9d]);
         /* QEMU console emulation */
         if (down) {
-            int numlock = vs->modifiers_state[0x45];
             switch (keycode) {
             case 0x2a:                          /* Left Shift */
             case 0x36:                          /* Right Shift */
@@ -1642,7 +1644,11 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
                 break;
 
             default:
-                kbd_put_keysym(sym);
+                if (control) {
+                    kbd_put_keysym(sym & 0x1f);
+                } else {
+                    kbd_put_keysym(sym);
+                }
                 break;
             }
         }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 3/4] vnc: implement shared flag handling.
  2012-02-10 10:09 [Qemu-devel] [PULL] vnc patch collection Gerd Hoffmann
  2012-02-10 10:09 ` [Qemu-devel] [PATCH 1/4] Fix vnc memory corruption with width = 1400 Gerd Hoffmann
  2012-02-10 10:09 ` [Qemu-devel] [PATCH 2/4] vnc: fix ctrl key in vnc terminal emulation Gerd Hoffmann
@ 2012-02-10 10:09 ` Gerd Hoffmann
  2012-02-10 10:10 ` [Qemu-devel] [PATCH 4/4] vnc: lift modifier keys on client disconnect Gerd Hoffmann
  2012-02-16  1:37 ` [Qemu-devel] [PULL] vnc patch collection Anthony Liguori
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2012-02-10 10:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

VNC clients send a shared flag in the client init message.  Up to now
qemu completely ignores this.  This patch implements shared flag
handling.  It comes with three policies:  By default qemu behaves as one
would expect:  Asking for a exclusive access grants exclusive access to
the client connecting.  There is also a desktop sharing mode which
disallows exclusive connects (so one forgetting -shared wouldn't drop
everybody else) and a compatibility mode which mimics the traditional
(but non-conforming) qemu behavior.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 qemu-options.hx |   13 +++++++
 ui/vnc.c        |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ui/vnc.h        |   16 +++++++++
 3 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index f577cc8..4bb3617 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1095,6 +1095,19 @@ This can be really helpful to save bandwidth when playing videos. Disabling
 adaptive encodings allows to restore the original static behavior of encodings
 like Tight.
 
+@item share=[allow-exclusive|force-shared|ignore]
+
+Set display sharing policy.  'allow-exclusive' allows clients to ask
+for exclusive access.  As suggested by the rfb spec this is
+implemented by dropping other connections.  Connecting multiple
+clients in parallel requires all clients asking for a shared session
+(vncviewer: -shared switch).  This is the default.  'force-shared'
+disables exclusive client access.  Useful for shared desktop sessions,
+where you don't want someone forgetting specify -shared disconnect
+everybody else.  'ignore' completely ignores the shared flag and
+allows everybody connect unconditionally.  Doesn't conform to the rfb
+spec but is traditional qemu behavior.
+
 @end table
 ETEXI
 
diff --git a/ui/vnc.c b/ui/vnc.c
index 810582b..83a9b15 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -47,6 +47,29 @@ static DisplayChangeListener *dcl;
 
 static int vnc_cursor_define(VncState *vs);
 
+static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
+{
+#ifdef _VNC_DEBUG
+    static const char *mn[] = {
+        [0]                           = "undefined",
+        [VNC_SHARE_MODE_CONNECTING]   = "connecting",
+        [VNC_SHARE_MODE_SHARED]       = "shared",
+        [VNC_SHARE_MODE_EXCLUSIVE]    = "exclusive",
+        [VNC_SHARE_MODE_DISCONNECTED] = "disconnected",
+    };
+    fprintf(stderr, "%s/%d: %s -> %s\n", __func__,
+            vs->csock, mn[vs->share_mode], mn[mode]);
+#endif
+
+    if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
+        vs->vd->num_exclusive--;
+    }
+    vs->share_mode = mode;
+    if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
+        vs->vd->num_exclusive++;
+    }
+}
+
 static char *addr_to_string(const char *format,
                             struct sockaddr_storage *sa,
                             socklen_t salen) {
@@ -997,6 +1020,7 @@ static void vnc_disconnect_start(VncState *vs)
 {
     if (vs->csock == -1)
         return;
+    vnc_set_share_mode(vs, VNC_SHARE_MODE_DISCONNECTED);
     qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
     closesocket(vs->csock);
     vs->csock = -1;
@@ -2054,8 +2078,67 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
 static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
 {
     char buf[1024];
+    VncShareMode mode;
     int size;
 
+    mode = data[0] ? VNC_SHARE_MODE_SHARED : VNC_SHARE_MODE_EXCLUSIVE;
+    switch (vs->vd->share_policy) {
+    case VNC_SHARE_POLICY_IGNORE:
+        /*
+         * Ignore the shared flag.  Nothing to do here.
+         *
+         * Doesn't conform to the rfb spec but is traditional qemu
+         * behavior, thus left here as option for compatibility
+         * reasons.
+         */
+        break;
+    case VNC_SHARE_POLICY_ALLOW_EXCLUSIVE:
+        /*
+         * Policy: Allow clients ask for exclusive access.
+         *
+         * Implementation: When a client asks for exclusive access,
+         * disconnect all others. Shared connects are allowed as long
+         * as no exclusive connection exists.
+         *
+         * This is how the rfb spec suggests to handle the shared flag.
+         */
+        if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
+            VncState *client;
+            QTAILQ_FOREACH(client, &vs->vd->clients, next) {
+                if (vs == client) {
+                    continue;
+                }
+                if (client->share_mode != VNC_SHARE_MODE_EXCLUSIVE &&
+                    client->share_mode != VNC_SHARE_MODE_SHARED) {
+                    continue;
+                }
+                vnc_disconnect_start(client);
+            }
+        }
+        if (mode == VNC_SHARE_MODE_SHARED) {
+            if (vs->vd->num_exclusive > 0) {
+                vnc_disconnect_start(vs);
+                return 0;
+            }
+        }
+        break;
+    case VNC_SHARE_POLICY_FORCE_SHARED:
+        /*
+         * Policy: Shared connects only.
+         * Implementation: Disallow clients asking for exclusive access.
+         *
+         * Useful for shared desktop sessions where you don't want
+         * someone forgetting to say -shared when running the vnc
+         * client disconnect everybody else.
+         */
+        if (mode == VNC_SHARE_MODE_EXCLUSIVE) {
+            vnc_disconnect_start(vs);
+            return 0;
+        }
+        break;
+    }
+    vnc_set_share_mode(vs, mode);
+
     vs->client_width = ds_get_width(vs->ds);
     vs->client_height = ds_get_height(vs->ds);
     vnc_write_u16(vs, vs->client_width);
@@ -2562,6 +2645,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
 
     vnc_client_cache_addr(vs);
     vnc_qmp_event(vs, QEVENT_VNC_CONNECTED);
+    vnc_set_share_mode(vs, VNC_SHARE_MODE_CONNECTING);
 
     vs->vd = vd;
     vs->ds = vd->ds;
@@ -2755,6 +2839,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
 
     if (!(vs->display = strdup(display)))
         return -1;
+    vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
 
     options = display;
     while ((options = strchr(options, ','))) {
@@ -2810,6 +2895,19 @@ int vnc_display_open(DisplayState *ds, const char *display)
             vs->lossy = true;
         } else if (strncmp(options, "non-adapative", 13) == 0) {
             vs->non_adaptive = true;
+        } else if (strncmp(options, "share=", 6) == 0) {
+            if (strncmp(options+6, "ignore", 6) == 0) {
+                vs->share_policy = VNC_SHARE_POLICY_IGNORE;
+            } else if (strncmp(options+6, "allow-exclusive", 15) == 0) {
+                vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
+            } else if (strncmp(options+6, "force-shared", 12) == 0) {
+                vs->share_policy = VNC_SHARE_POLICY_FORCE_SHARED;
+            } else {
+                fprintf(stderr, "unknown vnc share= option\n");
+                g_free(vs->display);
+                vs->display = NULL;
+                return -1;
+            }
         }
     }
 
diff --git a/ui/vnc.h b/ui/vnc.h
index 66689f1..0bd1fc6 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -122,9 +122,24 @@ struct VncSurface
     DisplaySurface *ds;
 };
 
+typedef enum VncShareMode {
+    VNC_SHARE_MODE_CONNECTING = 1,
+    VNC_SHARE_MODE_SHARED,
+    VNC_SHARE_MODE_EXCLUSIVE,
+    VNC_SHARE_MODE_DISCONNECTED,
+} VncShareMode;
+
+typedef enum VncSharePolicy {
+    VNC_SHARE_POLICY_IGNORE = 1,
+    VNC_SHARE_POLICY_ALLOW_EXCLUSIVE,
+    VNC_SHARE_POLICY_FORCE_SHARED,
+} VncSharePolicy;
+
 struct VncDisplay
 {
     QTAILQ_HEAD(, VncState) clients;
+    int num_exclusive;
+    VncSharePolicy share_policy;
     QEMUTimer *timer;
     int timer_interval;
     int lsock;
@@ -250,6 +265,7 @@ struct VncState
     int last_y;
     int client_width;
     int client_height;
+    VncShareMode share_mode;
 
     uint32_t vnc_encoding;
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 4/4] vnc: lift modifier keys on client disconnect.
  2012-02-10 10:09 [Qemu-devel] [PULL] vnc patch collection Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2012-02-10 10:09 ` [Qemu-devel] [PATCH 3/4] vnc: implement shared flag handling Gerd Hoffmann
@ 2012-02-10 10:10 ` Gerd Hoffmann
  2012-02-16  1:37 ` [Qemu-devel] [PULL] vnc patch collection Anthony Liguori
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2012-02-10 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

For any modifier key (shift, ctrl, alt) still pressed on disconnect
inject a key-up event into the guest.  The vnc client is gone, it will
not do that, so qemu has to do it instead.

Without this keys will get stuck, making the guest act in weird ways
after reconnecting.  Reproducer: exit vnc client via Alt-F4, guest
continues to see the pressed alt key and will not react to key events
in any useful way until you tap the alt key once to unstuck it.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/vnc.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 83a9b15..02b71bc 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -46,6 +46,7 @@ static VncDisplay *vnc_display; /* needed for info vnc */
 static DisplayChangeListener *dcl;
 
 static int vnc_cursor_define(VncState *vs);
+static void vnc_release_modifiers(VncState *vs);
 
 static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
 {
@@ -1051,6 +1052,7 @@ static void vnc_disconnect_finish(VncState *vs)
     vnc_sasl_client_cleanup(vs);
 #endif /* CONFIG_VNC_SASL */
     audio_del(vs);
+    vnc_release_modifiers(vs);
 
     QTAILQ_REMOVE(&vs->vd->clients, vs, next);
 
@@ -1679,6 +1681,29 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
     }
 }
 
+static void vnc_release_modifiers(VncState *vs)
+{
+    static const int keycodes[] = {
+        /* shift, control, alt keys, both left & right */
+        0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8,
+    };
+    int i, keycode;
+
+    if (!is_graphic_console()) {
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(keycodes); i++) {
+        keycode = keycodes[i];
+        if (!vs->modifiers_state[keycode]) {
+            continue;
+        }
+        if (keycode & SCANCODE_GREY) {
+            kbd_put_keycode(SCANCODE_EMUL0);
+        }
+        kbd_put_keycode(keycode | SCANCODE_UP);
+    }
+}
+
 static void key_event(VncState *vs, int down, uint32_t sym)
 {
     int keycode;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PULL] vnc patch collection
  2012-02-10 10:09 [Qemu-devel] [PULL] vnc patch collection Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2012-02-10 10:10 ` [Qemu-devel] [PATCH 4/4] vnc: lift modifier keys on client disconnect Gerd Hoffmann
@ 2012-02-16  1:37 ` Anthony Liguori
  4 siblings, 0 replies; 6+ messages in thread
From: Anthony Liguori @ 2012-02-16  1:37 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On 02/10/2012 04:09 AM, Gerd Hoffmann wrote:
>    Hi,
>
> Here comes my vnc patch collection again.  Rebased to latest master.
> gained one more patch.  All patches have been on the list before, the
> last patch just once, the other ones multiple times.  Seems nobody wants
> tp pick them up, MAINTAINERS has no vnc entry too, so I'll try a straigt
> pull request this time, hoping to get the bits merged finally.
>
> please pull,

Pulled.  Thanks.

Regards,

Anthony Liguori

>    Gerd
>
> The following changes since commit 57c83dacfe179bf061b8fa79d9553ebabe4d2ff4:
>
>    make: Remove duplicate use of GLIB_CFLAGS (2012-02-09 20:44:38 +0400)
>
> are available in the git repository at:
>    git://git.kraxel.org/qemu vnc.2
>
> Gerd Hoffmann (4):
>        Fix vnc memory corruption with width = 1400
>        vnc: fix ctrl key in vnc terminal emulation
>        vnc: implement shared flag handling.
>        vnc: lift modifier keys on client disconnect.
>
>   qemu-options.hx |   13 +++++
>   ui/vnc.c        |  135 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>   ui/vnc.h        |   16 +++++++
>   3 files changed, 161 insertions(+), 3 deletions(-)
>
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-02-16  1:37 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-10 10:09 [Qemu-devel] [PULL] vnc patch collection Gerd Hoffmann
2012-02-10 10:09 ` [Qemu-devel] [PATCH 1/4] Fix vnc memory corruption with width = 1400 Gerd Hoffmann
2012-02-10 10:09 ` [Qemu-devel] [PATCH 2/4] vnc: fix ctrl key in vnc terminal emulation Gerd Hoffmann
2012-02-10 10:09 ` [Qemu-devel] [PATCH 3/4] vnc: implement shared flag handling Gerd Hoffmann
2012-02-10 10:10 ` [Qemu-devel] [PATCH 4/4] vnc: lift modifier keys on client disconnect Gerd Hoffmann
2012-02-16  1:37 ` [Qemu-devel] [PULL] vnc patch collection Anthony Liguori

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.