qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/7] Add tight support to VNC
@ 2009-01-29 11:24 Alexander Graf
  2009-01-29 11:24 ` [Qemu-devel] [PATCH 1/7] Split VNC defines to vnc.h Alexander Graf
  0 siblings, 1 reply; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 11:24 UTC (permalink / raw)
  To: qemu-devel

The current tight implementation only supports raw and hextile encodings.
While this is perfectly fine for local networks, it would be good to
support tight encodings for remote access as well.

This patchset implements fundamental tight protocol and tight encoding
support, implementing jpeg compression.

Using this set as a basis, other tight encodings can be easily added as
well, like ZRLE or ZLIBHEX. I will work on that, but this is intrusive
enough for one set already ;-).

Alexander Graf (7):
  Split VNC defines to vnc.h
  Use VNC protocol defines
  Fix invalid #if in vnc.c when debugging is enabled
  Make vnc buffer big-chunk aware
  Split vnc authentication code
  Add tight protocol awareness to vnc.c
  Add tight encoding (jpeg) to vnc.c

 Makefile.target |    4 +
 configure       |   25 +++
 vnc.c           |  500 ++++++++++++++++++++++++++++++++++++++++++-------------
 vnc.h           |  130 ++++++++++++++
 4 files changed, 539 insertions(+), 120 deletions(-)
 create mode 100644 vnc.h

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

* [Qemu-devel] [PATCH 1/7] Split VNC defines to vnc.h
  2009-01-29 11:24 [Qemu-devel] [PATCH 0/7] Add tight support to VNC Alexander Graf
@ 2009-01-29 11:24 ` Alexander Graf
  2009-01-29 11:24   ` [Qemu-devel] [PATCH 2/7] Use VNC protocol defines Alexander Graf
  2009-01-29 15:22   ` [Qemu-devel] Re: [PATCH 1/7] Split VNC defines to vnc.h Anthony Liguori
  0 siblings, 2 replies; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 11:24 UTC (permalink / raw)
  To: qemu-devel

The VNC protocol contains quite some constants, some of which are
currently hardcoded in the vnc.c code. This is not exactly pretty.

Let's move all those constants out to vnc.h, so they are clearly
separated. While at it, I also included other defines that will be
used later in this patch series.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 vnc.c |   36 +-----------------
 vnc.h |  130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 131 insertions(+), 35 deletions(-)
 create mode 100644 vnc.h

diff --git a/vnc.c b/vnc.c
index 2b3a6eb..e88f38f 100644
--- a/vnc.c
+++ b/vnc.c
@@ -32,6 +32,7 @@
 
 #define VNC_REFRESH_INTERVAL (1000 / 30)
 
+#include "vnc.h"
 #include "vnc_keysym.h"
 #include "keymaps.c"
 #include "d3des.h"
@@ -88,41 +89,6 @@ typedef void VncSendHextileTile(VncState *vs,
 
 #define VNC_AUTH_CHALLENGE_SIZE 16
 
-enum {
-    VNC_AUTH_INVALID = 0,
-    VNC_AUTH_NONE = 1,
-    VNC_AUTH_VNC = 2,
-    VNC_AUTH_RA2 = 5,
-    VNC_AUTH_RA2NE = 6,
-    VNC_AUTH_TIGHT = 16,
-    VNC_AUTH_ULTRA = 17,
-    VNC_AUTH_TLS = 18,
-    VNC_AUTH_VENCRYPT = 19
-};
-
-#ifdef CONFIG_VNC_TLS
-enum {
-    VNC_WIREMODE_CLEAR,
-    VNC_WIREMODE_TLS,
-};
-
-enum {
-    VNC_AUTH_VENCRYPT_PLAIN = 256,
-    VNC_AUTH_VENCRYPT_TLSNONE = 257,
-    VNC_AUTH_VENCRYPT_TLSVNC = 258,
-    VNC_AUTH_VENCRYPT_TLSPLAIN = 259,
-    VNC_AUTH_VENCRYPT_X509NONE = 260,
-    VNC_AUTH_VENCRYPT_X509VNC = 261,
-    VNC_AUTH_VENCRYPT_X509PLAIN = 262,
-};
-
-#define X509_CA_CERT_FILE "ca-cert.pem"
-#define X509_CA_CRL_FILE "ca-crl.pem"
-#define X509_SERVER_KEY_FILE "server-key.pem"
-#define X509_SERVER_CERT_FILE "server-cert.pem"
-
-#endif /* CONFIG_VNC_TLS */
-
 struct VncState
 {
     QEMUTimer *timer;
diff --git a/vnc.h b/vnc.h
new file mode 100644
index 0000000..ae69bc3
--- /dev/null
+++ b/vnc.h
@@ -0,0 +1,130 @@
+#ifndef __VNCTIGHT_H
+#define __VNCTIGHT_H
+
+/*****************************************************************************
+ *
+ * Authentication modes
+ *
+ *****************************************************************************/
+
+enum {
+    VNC_AUTH_INVALID = 0,
+    VNC_AUTH_NONE = 1,
+    VNC_AUTH_VNC = 2,
+    VNC_AUTH_RA2 = 5,
+    VNC_AUTH_RA2NE = 6,
+    VNC_AUTH_TIGHT = 16,
+    VNC_AUTH_ULTRA = 17,
+    VNC_AUTH_TLS = 18,
+    VNC_AUTH_VENCRYPT = 19
+};
+
+#define VNC_AUTH_NONE_SIG "NOAUTH__"
+#define VNC_AUTH_VNC_SIG  "VNCAUTH_"
+
+#ifdef CONFIG_VNC_TLS
+enum {
+    VNC_WIREMODE_CLEAR,
+    VNC_WIREMODE_TLS,
+};
+
+enum {
+    VNC_AUTH_VENCRYPT_PLAIN = 256,
+    VNC_AUTH_VENCRYPT_TLSNONE = 257,
+    VNC_AUTH_VENCRYPT_TLSVNC = 258,
+    VNC_AUTH_VENCRYPT_TLSPLAIN = 259,
+    VNC_AUTH_VENCRYPT_X509NONE = 260,
+    VNC_AUTH_VENCRYPT_X509VNC = 261,
+    VNC_AUTH_VENCRYPT_X509PLAIN = 262,
+};
+
+#define X509_CA_CERT_FILE "ca-cert.pem"
+#define X509_CA_CRL_FILE "ca-crl.pem"
+#define X509_SERVER_KEY_FILE "server-key.pem"
+#define X509_SERVER_CERT_FILE "server-cert.pem"
+
+#endif /* CONFIG_VNC_TLS */
+
+/*****************************************************************************
+ *
+ * Encoding types
+ *
+ *****************************************************************************/
+
+#define VNC_ENCODING_RAW                  0x00000000
+#define VNC_ENCODING_COPYRECT             0x00000001
+#define VNC_ENCODING_RRE                  0x00000002
+#define VNC_ENCODING_CORRE                0x00000004
+#define VNC_ENCODING_HEXTILE              0x00000005
+#define VNC_ENCODING_ZLIB                 0x00000006
+#define VNC_ENCODING_TIGHT                0x00000007
+#define VNC_ENCODING_ZLIBHEX              0x00000008
+#define VNC_ENCODING_ZRLE                 0x00000010
+#define VNC_ENCODING_COMPRESSLEVEL0       0xFFFFFF00
+#define VNC_ENCODING_QUALITYLEVEL0        0xFFFFFFE0
+#define VNC_ENCODING_XCURSOR              0xFFFFFF10
+#define VNC_ENCODING_RICH_CURSOR          0xFFFFFF11
+#define VNC_ENCODING_POINTER_POS          0xFFFFFF18
+#define VNC_ENCODING_LASTRECT             0xFFFFFF20
+#define VNC_ENCODING_DESKTOPRESIZE        0xFFFFFF21
+#define VNC_ENCODING_POINTER_TYPE_CHANGE  0XFFFFFEFF
+#define VNC_ENCODING_EXT_KEY_EVENT        0XFFFFFEFE
+#define VNC_ENCODING_AUDIO                0XFFFFFEFD
+#define VNC_ENCODING_WMVi                 0x574D5669
+
+/* signatures for basic encoding types */
+#define VNC_ENCODING_RAW_SIG              "RAW_____"
+#define VNC_ENCODING_COPYRECT_SIG         "COPYRECT"
+#define VNC_ENCODING_RRE_SIG              "RRE_____"
+#define VNC_ENCODING_CORRE_SIG            "CORRE___"
+#define VNC_ENCODING_HEXTILE_SIG          "HEXTILE_"
+#define VNC_ENCODING_ZLIB_SIG             "ZLIB____"
+#define VNC_ENCODING_TIGHT_SIG            "TIGHT___"
+#define VNC_ENCODING_ZLIBHEX_SIG          "ZLIBHEX_"
+#define VNC_ENCODING_ZRLE_SIG             "ZRLE____"
+#define VNC_ENCODING_COMPRESSLEVEL0_SIG   "COMPRLVL"
+#define VNC_ENCODING_QUALITYLEVEL0_SIG    "JPEGQLVL"
+
+/*****************************************************************************
+ *
+ * Other tight constants
+ *
+ *****************************************************************************/
+
+/*
+ * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC.
+ */
+
+#define VNC_VENDOR_STANDARD        "STDV"
+#define VNC_VENDOR_TRIDIA          "TRDV"
+#define VNC_VENDOR_TIGHT           "TGHT"
+
+#define VNC_TIGHT_CCB_RESET_MASK   (0x0f)
+#define VNC_TIGHT_CCB_TYPE_MASK    (0x0f << 4)
+#define VNC_TIGHT_CCB_TYPE_FILL    (0x08 << 4)
+#define VNC_TIGHT_CCB_TYPE_JPEG    (0x09 << 4)
+#define VNC_TIGHT_CCB_BASIC_MAX    (0x07 << 4)
+#define VNC_TIGHT_CCB_BASIC_ZLIB   (0x03 << 4)
+#define VNC_TIGHT_CCB_BASIC_FILTER (0x04 << 4)
+
+/*****************************************************************************
+ *
+ * Features
+ *
+ *****************************************************************************/
+
+#define VNC_FEATURE_RESIZE                   0
+#define VNC_FEATURE_HEXTILE                  1
+#define VNC_FEATURE_POINTER_TYPE_CHANGE      2
+#define VNC_FEATURE_WMVI                     3
+#define VNC_FEATURE_TIGHT                    4
+#define VNC_FEATURE_TIGHT_PROTOCOL           5
+
+#define VNC_FEATURE_RESIZE_MASK              (1 << VNC_FEATURE_RESIZE)
+#define VNC_FEATURE_HEXTILE_MASK             (1 << VNC_FEATURE_HEXTILE)
+#define VNC_FEATURE_POINTER_TYPE_CHANGE_MASK (1 << VNC_FEATURE_POINTER_TYPE_CHANGE)
+#define VNC_FEATURE_WMVI_MASK                (1 << VNC_FEATURE_WMVI)
+#define VNC_FEATURE_TIGHT_MASK               (1 << VNC_FEATURE_TIGHT)
+#define VNC_FEATURE_TIGHT_PROTOCOL_MASK      (1 << VNC_FEATURE_TIGHT_PROTOCOL)
+
+#endif /* __VNCTIGHT_H */
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 2/7] Use VNC protocol defines
  2009-01-29 11:24 ` [Qemu-devel] [PATCH 1/7] Split VNC defines to vnc.h Alexander Graf
@ 2009-01-29 11:24   ` Alexander Graf
  2009-01-29 11:24     ` [Qemu-devel] [PATCH 3/7] Fix invalid #if in vnc.c when debugging is enabled Alexander Graf
  2009-01-29 15:22   ` [Qemu-devel] Re: [PATCH 1/7] Split VNC defines to vnc.h Anthony Liguori
  1 sibling, 1 reply; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 11:24 UTC (permalink / raw)
  To: qemu-devel

Now that we have nice defines for all sorts of constants, let's
use them!

This patch also takes the "feature variables", currently called has_*
into a single feature int. This way adding new features is a lot
easier and doesn't clutter the VncState struct.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 vnc.c |   97 +++++++++++++++++++++++++++++++++-------------------------------
 1 files changed, 50 insertions(+), 47 deletions(-)

diff --git a/vnc.c b/vnc.c
index e88f38f..6b885d3 100644
--- a/vnc.c
+++ b/vnc.c
@@ -98,10 +98,7 @@ struct VncState
     int need_update;
     uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
     char *old_data;
-    int has_resize;
-    int has_hextile;
-    int has_pointer_type_change;
-    int has_WMVi;
+    uint32_t features;
     int absolute;
     int last_x;
     int last_y;
@@ -164,6 +161,10 @@ void do_info_vnc(void)
     }
 }
 
+static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
+    return (vs->features & (1 << feature));
+}
+
 /* TODO
    1) Get the queue working for IO.
    2) there is some weirdness when using the -S option (the screen is grey
@@ -277,11 +278,12 @@ static void vnc_dpy_resize(DisplayState *ds)
                    ds_get_height(ds) != vs->serverds.height;
     vs->serverds = *(ds->surface);
     if (size_changed) {
-        if (vs->csock != -1 && vs->has_resize) {
+        if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
             vnc_write_u8(vs, 0);  /* msg id */
             vnc_write_u8(vs, 0);
             vnc_write_u16(vs, 1); /* number of rects */
-            vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), -223);
+            vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
+                                   VNC_ENCODING_DESKTOPRESIZE);
             vnc_flush(vs);
         }
     }
@@ -378,7 +380,7 @@ static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h
     int i;
     uint8_t *row;
 
-    vnc_framebuffer_update(vs, x, y, w, h, 0);
+    vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
 
     row = ds_get_data(vs->ds) + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
     for (i = 0; i < h; i++) {
@@ -429,7 +431,7 @@ static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, i
     int has_fg, has_bg;
     uint8_t *last_fg, *last_bg;
 
-    vnc_framebuffer_update(vs, x, y, w, h, 5);
+    vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
 
     last_fg = (uint8_t *) malloc(vs->serverds.pf.bytes_per_pixel);
     last_bg = (uint8_t *) malloc(vs->serverds.pf.bytes_per_pixel);
@@ -448,7 +450,7 @@ static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, i
 
 static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 {
-	if (vs->has_hextile)
+	if (vnc_has_feature(vs, VNC_FEATURE_HEXTILE))
 	    send_framebuffer_update_hextile(vs, x, y, w, h);
 	else
 	    send_framebuffer_update_raw(vs, x, y, w, h);
@@ -463,7 +465,7 @@ static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_
     vnc_write_u8(vs, 0);  /* msg id */
     vnc_write_u8(vs, 0);
     vnc_write_u16(vs, 1); /* number of rects */
-    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
+    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, VNC_ENCODING_COPYRECT);
     vnc_write_u16(vs, src_x);
     vnc_write_u16(vs, src_y);
     vnc_flush(vs);
@@ -919,12 +921,13 @@ static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
 
 static void check_pointer_type_change(VncState *vs, int absolute)
 {
-    if (vs->has_pointer_type_change && vs->absolute != absolute) {
+    if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE) && vs->absolute != absolute) {
 	vnc_write_u8(vs, 0);
 	vnc_write_u8(vs, 0);
 	vnc_write_u16(vs, 1);
 	vnc_framebuffer_update(vs, absolute, 0,
-			       ds_get_width(vs->ds), ds_get_height(vs->ds), -257);
+			       ds_get_width(vs->ds), ds_get_height(vs->ds),
+                               VNC_ENCODING_POINTER_TYPE_CHANGE);
 	vnc_flush(vs);
     }
     vs->absolute = absolute;
@@ -950,7 +953,7 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
 	kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1),
 			y * 0x7FFF / (ds_get_height(vs->ds) - 1),
 			dz, buttons);
-    } else if (vs->has_pointer_type_change) {
+    } else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
 	x -= 0x7FFF;
 	y -= 0x7FFF;
 
@@ -1140,7 +1143,8 @@ static void send_ext_key_event_ack(VncState *vs)
     vnc_write_u8(vs, 0);
     vnc_write_u8(vs, 0);
     vnc_write_u16(vs, 1);
-    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), -258);
+    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
+                           VNC_ENCODING_EXT_KEY_EVENT);
     vnc_flush(vs);
 }
 
@@ -1149,50 +1153,50 @@ static void send_ext_audio_ack(VncState *vs)
     vnc_write_u8(vs, 0);
     vnc_write_u8(vs, 0);
     vnc_write_u16(vs, 1);
-    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), -259);
+    vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds),
+                           VNC_ENCODING_AUDIO);
     vnc_flush(vs);
 }
 
 static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
 {
     int i;
+    unsigned int enc = 0;
 
-    vs->has_hextile = 0;
-    vs->has_resize = 0;
-    vs->has_pointer_type_change = 0;
-    vs->has_WMVi = 0;
+    vs->features = 0;
     vs->absolute = -1;
     dcl->dpy_copy = NULL;
 
     for (i = n_encodings - 1; i >= 0; i--) {
-	switch (encodings[i]) {
-	case 0: /* Raw */
-	    vs->has_hextile = 0;
-	    break;
-	case 1: /* CopyRect */
-	    dcl->dpy_copy = vnc_copy;
-	    break;
-	case 5: /* Hextile */
-	    vs->has_hextile = 1;
-	    break;
-	case -223: /* DesktopResize */
-	    vs->has_resize = 1;
-	    break;
-	case -257:
-	    vs->has_pointer_type_change = 1;
-	    break;
-        case -258:
+        enc = encodings[i];
+        switch (enc) {
+        case VNC_ENCODING_RAW:
+            break;
+        case VNC_ENCODING_COPYRECT:
+            dcl->dpy_copy = vnc_copy;
+            break;
+        case VNC_ENCODING_HEXTILE:
+            vs->features |= VNC_FEATURE_HEXTILE_MASK;
+            break;
+        case VNC_ENCODING_DESKTOPRESIZE:
+            vs->features |= VNC_FEATURE_RESIZE_MASK;
+            break;
+        case VNC_ENCODING_POINTER_TYPE_CHANGE:
+            vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
+            break;
+        case VNC_ENCODING_EXT_KEY_EVENT:
             send_ext_key_event_ack(vs);
             break;
-        case -259:
+        case VNC_ENCODING_AUDIO:
             send_ext_audio_ack(vs);
             break;
-        case 0x574D5669:
-            vs->has_WMVi = 1;
+        case VNC_ENCODING_WMVi:
+            vs->features |= VNC_FEATURE_WMVI_MASK;
             break;
-	default:
-	    break;
-	}
+        default:
+             printf("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
+            break;
+        }
     }
 
     check_pointer_type_change(vs, kbd_mouse_is_absolute());
@@ -1306,12 +1310,13 @@ static void vnc_colordepth(DisplayState *ds)
 {
     struct VncState *vs = ds->opaque;
 
-    if (vs->csock != -1 && vs->has_WMVi) {
+    if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_WMVI)) {
         /* Sending a WMVi message to notify the client*/
         vnc_write_u8(vs, 0);  /* msg id */
         vnc_write_u8(vs, 0);
         vnc_write_u16(vs, 1); /* number of rects */
-        vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds), 0x574D5669);
+        vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
+                               VNC_ENCODING_WMVi);
         pixel_format_message(vs);
         vnc_flush(vs);
     } else {
@@ -2079,9 +2084,7 @@ static void vnc_connect(VncState *vs)
     vnc_read_when(vs, protocol_version, 12);
     memset(vs->old_data, 0, ds_get_linesize(vs->ds) * ds_get_height(vs->ds));
     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
-    vs->has_resize = 0;
-    vs->has_hextile = 0;
-    vs->has_WMVi = 0;
+    vs->features = 0;
     dcl->dpy_copy = NULL;
     vnc_update_client(vs);
     reset_keys(vs);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 3/7] Fix invalid #if in vnc.c when debugging is enabled
  2009-01-29 11:24   ` [Qemu-devel] [PATCH 2/7] Use VNC protocol defines Alexander Graf
@ 2009-01-29 11:24     ` Alexander Graf
  2009-01-29 11:24       ` [Qemu-devel] [PATCH 4/7] Make vnc buffer big-chunk aware Alexander Graf
  0 siblings, 1 reply; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 11:24 UTC (permalink / raw)
  To: qemu-devel

While running with debugging enabled, I found an #if testing for
an undefined value, not defined(value). This patch fixes that.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 vnc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/vnc.c b/vnc.c
index 6b885d3..4b17f85 100644
--- a/vnc.c
+++ b/vnc.c
@@ -47,7 +47,7 @@
 #ifdef _VNC_DEBUG
 #define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
 
-#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
+#if defined(CONFIG_VNC_TLS) && _VNC_DEBUG >= 2
 /* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
 static void vnc_debug_gnutls_log(int level, const char* str) {
     VNC_DEBUG("%d %s", level, str);
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 4/7] Make vnc buffer big-chunk aware
  2009-01-29 11:24     ` [Qemu-devel] [PATCH 3/7] Fix invalid #if in vnc.c when debugging is enabled Alexander Graf
@ 2009-01-29 11:24       ` Alexander Graf
  2009-01-29 11:24         ` [Qemu-devel] [PATCH 5/7] Split vnc authentication code Alexander Graf
  2009-01-29 15:11         ` [Qemu-devel] Re: [PATCH 4/7] Make vnc buffer big-chunk aware Anthony Liguori
  0 siblings, 2 replies; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 11:24 UTC (permalink / raw)
  To: qemu-devel

Currently writing to buffers is protected by buffer_reserve.
Unfortunately, is reserves at most 1024 bytes more than we currently
have, so if we want to write a 2048 bytes chunk, we overwrite
random memory.

This patch addresses this in a pretty dumb but easy way.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 vnc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/vnc.c b/vnc.c
index 4b17f85..d0d9580 100644
--- a/vnc.c
+++ b/vnc.c
@@ -592,7 +592,7 @@ static int vnc_listen_poll(void *opaque)
 
 static void buffer_reserve(Buffer *buffer, size_t len)
 {
-    if ((buffer->capacity - buffer->offset) < len) {
+    while ((buffer->capacity - buffer->offset) < len) {
 	buffer->capacity += (len + 1024);
 	buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity);
 	if (buffer->buffer == NULL) {
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 5/7] Split vnc authentication code
  2009-01-29 11:24       ` [Qemu-devel] [PATCH 4/7] Make vnc buffer big-chunk aware Alexander Graf
@ 2009-01-29 11:24         ` Alexander Graf
  2009-01-29 11:24           ` [Qemu-devel] [PATCH 6/7] Add tight protocol awareness to vnc.c Alexander Graf
  2009-01-29 15:11         ` [Qemu-devel] Re: [PATCH 4/7] Make vnc buffer big-chunk aware Anthony Liguori
  1 sibling, 1 reply; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 11:24 UTC (permalink / raw)
  To: qemu-devel

This patch splits the authentication code, mostly for readability
reasons.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 vnc.c |   67 ++++++++++++++++++++++++++++++++++------------------------------
 1 files changed, 36 insertions(+), 31 deletions(-)

diff --git a/vnc.c b/vnc.c
index d0d9580..b4b0843 100644
--- a/vnc.c
+++ b/vnc.c
@@ -180,6 +180,7 @@ static void vnc_write_u8(VncState *vs, uint8_t value);
 static void vnc_flush(VncState *vs);
 static void vnc_update_client(void *opaque);
 static void vnc_client_read(void *opaque);
+static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len);
 
 static void vnc_colordepth(DisplayState *ds);
 
@@ -1555,6 +1556,39 @@ static int start_auth_vnc(VncState *vs)
     return 0;
 }
 
+static int vnc_start_auth(VncState *vs, int auth)
+{
+    switch (auth) {
+    case VNC_AUTH_NONE:
+        VNC_DEBUG("Accept auth none\n");
+        if (vs->minor >= 8) {
+            vnc_write_u32(vs, 0); /* Accept auth completion */
+            vnc_flush(vs);
+        }
+        vnc_read_when(vs, protocol_client_init, 1);
+        break;
+    case VNC_AUTH_VNC:
+        VNC_DEBUG("Start VNC auth\n");
+        return start_auth_vnc(vs);
+#ifdef CONFIG_VNC_TLS
+    case VNC_AUTH_VENCRYPT:
+        VNC_DEBUG("Accept VeNCrypt auth\n");;
+        return start_auth_vencrypt(vs);
+#endif /* CONFIG_VNC_TLS */
+    default: /* Should not be possible, but just in case */
+        VNC_DEBUG("Reject auth %d unknown\n", auth);
+        vnc_write_u8(vs, 1);
+        if (vs->minor >= 8) {
+            static const char err[] = "Authentication failed";
+            vnc_write_u32(vs, sizeof(err));
+            vnc_write(vs, err, sizeof(err));
+        }
+        vnc_client_error(vs);
+    }
+
+    return 0;
+}
+
 
 #ifdef CONFIG_VNC_TLS
 #define DH_BITS 1024
@@ -1979,37 +2013,8 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
        }
        vnc_client_error(vs);
     } else { /* Accept requested auth */
-       VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
-       switch (vs->auth) {
-       case VNC_AUTH_NONE:
-           VNC_DEBUG("Accept auth none\n");
-           if (vs->minor >= 8) {
-               vnc_write_u32(vs, 0); /* Accept auth completion */
-               vnc_flush(vs);
-           }
-           vnc_read_when(vs, protocol_client_init, 1);
-           break;
-
-       case VNC_AUTH_VNC:
-           VNC_DEBUG("Start VNC auth\n");
-           return start_auth_vnc(vs);
-
-#ifdef CONFIG_VNC_TLS
-       case VNC_AUTH_VENCRYPT:
-           VNC_DEBUG("Accept VeNCrypt auth\n");;
-           return start_auth_vencrypt(vs);
-#endif /* CONFIG_VNC_TLS */
-
-       default: /* Should not be possible, but just in case */
-           VNC_DEBUG("Reject auth %d\n", vs->auth);
-           vnc_write_u8(vs, 1);
-           if (vs->minor >= 8) {
-               static const char err[] = "Authentication failed";
-               vnc_write_u32(vs, sizeof(err));
-               vnc_write(vs, err, sizeof(err));
-           }
-           vnc_client_error(vs);
-       }
+       VNC_DEBUG("Client requested auth %d\n", auth);
+       return vnc_start_auth(vs, data[0]);
     }
     return 0;
 }
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 6/7] Add tight protocol awareness to vnc.c
  2009-01-29 11:24         ` [Qemu-devel] [PATCH 5/7] Split vnc authentication code Alexander Graf
@ 2009-01-29 11:24           ` Alexander Graf
  2009-01-29 11:24             ` [Qemu-devel] [PATCH 7/7] Add tight encoding (jpeg) " Alexander Graf
  2009-01-29 15:13             ` [Qemu-devel] Re: [PATCH 6/7] Add tight protocol awareness " Anthony Liguori
  0 siblings, 2 replies; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 11:24 UTC (permalink / raw)
  To: qemu-devel

This patch enables the vnc server to understand the tight protocol.

Basically, negotiation if tight is existing happens through the
authentication code. If a special authentication called VNC_AUTH_TIGHT
is used, the real authentication is stacked afterwards and tight
extensions exist.

In order to make it easier to add different encodings later, this
patch also adds "preferred encoding" awareness, only saves the
last preferred encoding though.

This way the client can choose which protocol it wants to use the
most.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 vnc.c |  122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/vnc.c b/vnc.c
index b4b0843..86e2a1b 100644
--- a/vnc.c
+++ b/vnc.c
@@ -103,6 +103,10 @@ struct VncState
     int last_x;
     int last_y;
 
+    int vnc_encoding;
+    unsigned int tight_quality;
+    unsigned int tight_compression;
+
     int major;
     int minor;
 
@@ -451,10 +455,14 @@ static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, i
 
 static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 {
-	if (vnc_has_feature(vs, VNC_FEATURE_HEXTILE))
+    switch(vs->vnc_encoding) {
+	case VNC_ENCODING_HEXTILE:
 	    send_framebuffer_update_hextile(vs, x, y, w, h);
-	else
+	    break;
+	default:
 	    send_framebuffer_update_raw(vs, x, y, w, h);
+	    break;
+    }    
 }
 
 static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
@@ -1165,19 +1173,38 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
     unsigned int enc = 0;
 
     vs->features = 0;
+    vs->vnc_encoding = 0;
+    vs->tight_compression=0;
+    vs->tight_quality=9;
     vs->absolute = -1;
     dcl->dpy_copy = NULL;
 
     for (i = n_encodings - 1; i >= 0; i--) {
         enc = encodings[i];
         switch (enc) {
+        case VNC_ENCODING_RRE:
+        case VNC_ENCODING_CORRE:
+        case VNC_ENCODING_ZLIB:
+        case VNC_ENCODING_ZLIBHEX:
+        case VNC_ENCODING_ZRLE:
+        case VNC_ENCODING_LASTRECT:
+        case VNC_ENCODING_POINTER_POS:
+        case VNC_ENCODING_RICH_CURSOR:
+        case VNC_ENCODING_XCURSOR:
+            /* Ingore - at least for now... */
+            break;
         case VNC_ENCODING_RAW:
+            vs->vnc_encoding = enc;
             break;
         case VNC_ENCODING_COPYRECT:
             dcl->dpy_copy = vnc_copy;
             break;
         case VNC_ENCODING_HEXTILE:
             vs->features |= VNC_FEATURE_HEXTILE_MASK;
+            vs->vnc_encoding = enc;
+            break;
+        case VNC_ENCODING_TIGHT:
+            vs->features |= VNC_FEATURE_TIGHT_MASK;
             break;
         case VNC_ENCODING_DESKTOPRESIZE:
             vs->features |= VNC_FEATURE_RESIZE_MASK;
@@ -1194,6 +1221,12 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
         case VNC_ENCODING_WMVi:
             vs->features |= VNC_FEATURE_WMVI_MASK;
             break;
+        case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9:
+            vs->tight_compression = (enc & 0x0F);
+            break;
+        case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9:
+            vs->tight_quality = (enc & 0x0F);
+            break;
         default:
              printf("Unknown encoding: %d (0x%.8x): %d\n", i, enc, enc);
             break;
@@ -1461,6 +1494,36 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
     return 0;
 }
 
+static void write_tight_capability(VncState *vs, int encoding,
+                                   const char *signature, const char *vendor)
+{
+	vnc_write_u32(vs, encoding);
+	vnc_write(vs, vendor, 4);
+	vnc_write(vs, signature, 8);
+}
+
+static void write_tight_interaction_capabilities(VncState *vs)
+{
+    VNC_DEBUG("Sending Tight capabilities...\n");
+    vnc_write_u16(vs, 0); /* nServerMessageTypes  */
+    vnc_write_u16(vs, 0); /* nClientMessageTypes  */ 
+    vnc_write_u16(vs, 5); /* nEncodingTypes */
+    vnc_write_u16(vs, 0); /* pad */
+    write_tight_capability(vs, VNC_ENCODING_TIGHT, VNC_ENCODING_TIGHT_SIG,
+                           VNC_VENDOR_TIGHT);
+    write_tight_capability(vs, VNC_ENCODING_RAW, VNC_ENCODING_RAW_SIG,
+                           VNC_VENDOR_STANDARD);
+    write_tight_capability(vs, VNC_ENCODING_HEXTILE, VNC_ENCODING_HEXTILE_SIG,
+                           VNC_VENDOR_STANDARD);
+    write_tight_capability(vs, VNC_ENCODING_COMPRESSLEVEL0,
+                           VNC_ENCODING_COMPRESSLEVEL0_SIG, VNC_VENDOR_TIGHT);
+    write_tight_capability(vs, VNC_ENCODING_QUALITYLEVEL0,
+                           VNC_ENCODING_QUALITYLEVEL0_SIG, VNC_VENDOR_TIGHT);
+
+    vnc_flush(vs);
+}
+
+
 static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
 {
     char buf[1024];
@@ -1480,6 +1543,9 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
     vnc_write(vs, buf, size);
     vnc_flush(vs);
 
+    if(vnc_has_feature(vs, VNC_FEATURE_TIGHT_PROTOCOL))
+        write_tight_interaction_capabilities(vs);
+    
     vnc_read_when(vs, protocol_client_msg, 1);
 
     return 0;
@@ -1556,6 +1622,32 @@ static int start_auth_vnc(VncState *vs)
     return 0;
 }
 
+static int start_auth_tight(VncState *vs)
+{
+    vnc_write_u32(vs, 0); /* no tunnel types */
+    vnc_write_u32(vs, 1); /* num auth types */
+        
+    switch(vs->auth) {
+        case VNC_AUTH_NONE:
+            write_tight_capability(vs, VNC_AUTH_NONE, VNC_AUTH_NONE_SIG,
+                                   VNC_VENDOR_STANDARD);
+            break;
+        case VNC_AUTH_VNC:
+            write_tight_capability(vs, VNC_AUTH_VNC, VNC_AUTH_VNC_SIG,
+                                   VNC_VENDOR_STANDARD);
+            break;
+        default:
+            VNC_DEBUG("Unknown subset of tight auth: %d", vs->auth);
+            vnc_write_u32(vs, -1);
+            vnc_write(vs, "BAD_", 4);
+            vnc_write(vs, "UNKNOWN_", 8);
+    }
+    
+    vnc_flush(vs);
+    vnc_read_when(vs, protocol_client_auth, 4);
+    return 0;
+}
+
 static int vnc_start_auth(VncState *vs, int auth)
 {
     switch (auth) {
@@ -1570,12 +1662,22 @@ static int vnc_start_auth(VncState *vs, int auth)
     case VNC_AUTH_VNC:
         VNC_DEBUG("Start VNC auth\n");
         return start_auth_vnc(vs);
+    case VNC_AUTH_TIGHT:
+        /* If we know we're on tight here, we ran into recursion */
+        if (vnc_has_feature(vs, VNC_FEATURE_TIGHT_PROTOCOL)) {
+            VNC_DEBUG("Danger! Server sent us tight auth request twice!\n");
+            goto tight_recursion;
+        }
+        vs->features |= VNC_FEATURE_TIGHT_PROTOCOL_MASK;
+        VNC_DEBUG("Start VNC tight auth\n");
+        return start_auth_tight(vs);
 #ifdef CONFIG_VNC_TLS
     case VNC_AUTH_VENCRYPT:
         VNC_DEBUG("Accept VeNCrypt auth\n");;
         return start_auth_vencrypt(vs);
 #endif /* CONFIG_VNC_TLS */
     default: /* Should not be possible, but just in case */
+    tight_recursion:
         VNC_DEBUG("Reject auth %d unknown\n", auth);
         vnc_write_u8(vs, 1);
         if (vs->minor >= 8) {
@@ -2001,10 +2103,15 @@ static int start_auth_vencrypt(VncState *vs)
 
 static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
 {
+    int auth = data[0];
+
+    if (len == 4)
+        auth = read_s32(data, 0);
     /* We only advertise 1 auth scheme at a time, so client
      * must pick the one we sent. Verify this */
-    if (data[0] != vs->auth) { /* Reject auth */
-       VNC_DEBUG("Reject auth %d\n", (int)data[0]);
+    if ((auth != vs->auth) &&
+        (auth != VNC_AUTH_TIGHT)) { /* Reject auth */
+       VNC_DEBUG("Reject auth %d != %d\n", auth, vs->auth);
        vnc_write_u32(vs, 1);
        if (vs->minor >= 8) {
            static const char err[] = "Authentication failed";
@@ -2014,7 +2121,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
        vnc_client_error(vs);
     } else { /* Accept requested auth */
        VNC_DEBUG("Client requested auth %d\n", auth);
-       return vnc_start_auth(vs, data[0]);
+       return vnc_start_auth(vs, auth);
     }
     return 0;
 }
@@ -2068,9 +2175,10 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
             vnc_client_error(vs);
        }
     } else {
-	VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
-	vnc_write_u8(vs, 1); /* num auth */
+	VNC_DEBUG("Telling client we support auth %d and tight\n", vs->auth);
+	vnc_write_u8(vs, 2); /* num auth */
 	vnc_write_u8(vs, vs->auth);
+	vnc_write_u8(vs, VNC_AUTH_TIGHT);
 	vnc_read_when(vs, protocol_client_auth, 1);
 	vnc_flush(vs);
     }
-- 
1.6.0.2

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

* [Qemu-devel] [PATCH 7/7] Add tight encoding (jpeg) to vnc.c
  2009-01-29 11:24           ` [Qemu-devel] [PATCH 6/7] Add tight protocol awareness to vnc.c Alexander Graf
@ 2009-01-29 11:24             ` Alexander Graf
  2009-01-29 15:17               ` [Qemu-devel] " Anthony Liguori
  2009-01-29 15:13             ` [Qemu-devel] Re: [PATCH 6/7] Add tight protocol awareness " Anthony Liguori
  1 sibling, 1 reply; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 11:24 UTC (permalink / raw)
  To: qemu-devel

Because we can now speak the tight protocol, let's use it to
transmit jpeg data to the client!

This patch adds a really easy implementation of the jpeg tight
encoding. Tight in general can do a lot more, but let's take small
steps here and see how things perform.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 Makefile.target |    4 +
 configure       |   25 ++++++++
 vnc.c           |  178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 207 insertions(+), 0 deletions(-)

diff --git a/Makefile.target b/Makefile.target
index a091ce9..7b54748 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -554,6 +554,10 @@ CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
 LIBS += $(CONFIG_VNC_TLS_LIBS)
 endif
 
+ifdef CONFIG_VNC_JPEG
+LIBS += $(CONFIG_VNC_JPEG_LIBS)
+endif
+
 ifdef CONFIG_BLUEZ
 LIBS += $(CONFIG_BLUEZ_LIBS)
 endif
diff --git a/configure b/configure
index c3fbbbe..44e2e0b 100755
--- a/configure
+++ b/configure
@@ -164,6 +164,7 @@ fmod_lib=""
 fmod_inc=""
 oss_lib=""
 vnc_tls="yes"
+vnc_jpeg="yes"
 bsd="no"
 linux="no"
 solaris="no"
@@ -387,6 +388,8 @@ for opt do
   ;;
   --disable-vnc-tls) vnc_tls="no"
   ;;
+  --disable-jpeg) vnc_jpeg="no"
+  ;;
   --disable-slirp) slirp="no"
   ;;
   --disable-vde) vde="no"
@@ -544,6 +547,7 @@ echo "                           Available cards: $audio_possible_cards"
 echo "  --enable-mixemu          enable mixer emulation"
 echo "  --disable-brlapi         disable BrlAPI"
 echo "  --disable-vnc-tls        disable TLS encryption for VNC server"
+echo "  --disable-jpeg           disable JPEG compression for VNC server"
 echo "  --disable-curses         disable curses output"
 echo "  --disable-bluez          disable bluez stack connectivity"
 echo "  --disable-kvm            disable KVM acceleration support"
@@ -823,6 +827,21 @@ EOF
 fi
 
 ##########################################
+# VNC JPEG detection
+if test "$vnc_jpeg" = "yes" ; then
+cat > $TMPC <<EOF
+#include <jpeglib.h>
+int main(void) { jpeg_compress_struct s; jpeg_create_compress(&s); return 0; }
+EOF
+    vnc_jpeg_libs="-ljpeg"
+    if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} $TMPC $vnc_jpeg_libs > /dev/null 2> /dev/null ; then
+	:
+    else
+	vnc_tls="no"
+    fi
+fi
+
+##########################################
 # vde libraries probe
 if test "$vde" = "yes" ; then
   cat > $TMPC << EOF
@@ -1130,6 +1149,7 @@ if test "$vnc_tls" = "yes" ; then
     echo "    TLS CFLAGS    $vnc_tls_cflags"
     echo "    TLS LIBS      $vnc_tls_libs"
 fi
+echo "VNC JPEG support  $vnc_jpeg"
 if test -n "$sparc_cpu"; then
     echo "Target Sparc Arch $sparc_cpu"
 fi
@@ -1371,6 +1391,11 @@ if test "$vnc_tls" = "yes" ; then
   echo "CONFIG_VNC_TLS_LIBS=$vnc_tls_libs" >> $config_mak
   echo "#define CONFIG_VNC_TLS 1" >> $config_h
 fi
+if test "$vnc_jpeg" = "yes" ; then
+  echo "CONFIG_VNC_JPEG=yes" >> $config_mak
+  echo "CONFIG_VNC_JPEG_LIBS=$vnc_jpeg_libs" >> $config_mak
+  echo "#define CONFIG_VNC_JPEG 1" >> $config_h
+fi
 qemu_version=`head $source_path/VERSION`
 echo "VERSION=$qemu_version" >>$config_mak
 echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
diff --git a/vnc.c b/vnc.c
index 86e2a1b..7a7ec94 100644
--- a/vnc.c
+++ b/vnc.c
@@ -37,6 +37,10 @@
 #include "keymaps.c"
 #include "d3des.h"
 
+#ifdef CONFIG_VNC_JPEG
+#include <jpeglib.h>
+#endif /* CONFIG_VNC_JPEG */
+
 #ifdef CONFIG_VNC_TLS
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
@@ -144,6 +148,11 @@ struct VncState
     size_t read_handler_expect;
     /* input */
     uint8_t modifiers_state[256];
+
+#ifdef CONFIG_VNC_JPEG
+    Buffer jpeg_buffer;
+    struct jpeg_destination_mgr jpeg_dst_manager;
+#endif /* CONFIG_VNC_JPEG */
 };
 
 static VncState *vnc_state; /* needed for info vnc */
@@ -185,6 +194,8 @@ static void vnc_flush(VncState *vs);
 static void vnc_update_client(void *opaque);
 static void vnc_client_read(void *opaque);
 static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len);
+static void buffer_reserve(Buffer *buffer, size_t len);
+static void buffer_reset(Buffer *buffer);
 
 static void vnc_colordepth(DisplayState *ds);
 
@@ -453,9 +464,172 @@ static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, i
 
 }
 
+#ifdef CONFIG_VNC_JPEG
+/* This is called once per encoding */
+static void jpeg_init_destination(j_compress_ptr cinfo)
+{
+    VncState *vs = (VncState*)cinfo->client_data;
+    Buffer *buffer = &vs->jpeg_buffer;
+
+    cinfo->dest->next_output_byte = (JOCTET *)buffer->buffer + buffer->offset;
+    cinfo->dest->free_in_buffer = (size_t)(buffer->capacity - buffer->offset);
+}
+
+/* This is called when we ran out of buffer (shouldn't happen!) */
+static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo)
+{
+    VncState *vs = (VncState*)cinfo->client_data;
+    Buffer *buffer = &vs->jpeg_buffer;
+
+    buffer->offset = buffer->capacity;
+    buffer_reserve(buffer, 2048);
+    jpeg_init_destination(cinfo);
+    return TRUE;
+}
+
+/* This is called when we are done processing data */
+static void jpeg_term_destination(j_compress_ptr cinfo)
+{
+    VncState *vs = (VncState*)cinfo->client_data;
+    Buffer *buffer = &vs->jpeg_buffer;
+
+    buffer->offset = buffer->capacity - cinfo->dest->free_in_buffer;
+}
+
+
+static void vnc_send_compact_size(VncState *vs, int len) 
+{
+    char buf[3];
+    int lpc = 0;
+    int bytes = 0;
+
+    /* Adapted from SendCompressedData() in Xvnc/programs/Xserver/hw/vnc/tight.c */
+    buf[bytes++] = len & 0x7F;
+    if (len > 0x7F) {
+	buf[bytes-1] |= 0x80;
+	buf[bytes++] = len >> 7 & 0x7F;
+	if (len > 0x3FFF) {
+	    buf[bytes-1] |= 0x80;
+	    buf[bytes++] = len >> 14 & 0xFF;
+	}
+    }
+
+    for(lpc = 0; lpc < bytes; lpc++) {
+	vnc_write_u8(vs, buf[lpc]);
+    }
+}
+
+static int32_t read_s32(uint8_t *data, size_t offset);
+static void jpeg_row2pixel(VncState *vs, char *in, char *out, int len)
+{
+    char *pi = in;
+    char *po = out;
+    int depth = vs->serverds.pf.bytes_per_pixel;
+    int i;
+
+    for (i = 0; i < len; i++) {
+        uint32_t v;
+        uint8_t r, g, b;
+        switch (depth) {
+            case 1:
+                po[0] = pi[0];
+                po[1] = pi[0];
+                po[2] = pi[0];
+                continue;
+                break;
+            case 2:
+                v = *((uint16_t*)pi);
+                break;
+            case 4:
+                v = *((uint32_t*)pi);
+                break;
+        }
+        r = ((((v & vs->serverds.pf.rmask) >> vs->serverds.pf.rshift)
+            << vs->clientds.pf.rbits) >> vs->serverds.pf.rbits);
+        g = ((((v & vs->serverds.pf.gmask) >> vs->serverds.pf.gshift)
+            << vs->clientds.pf.gbits) >> vs->serverds.pf.gbits);
+        b = ((((v & vs->serverds.pf.bmask) >> vs->serverds.pf.bshift)
+            << vs->clientds.pf.bbits) >> vs->serverds.pf.bbits);
+
+        po[0] = r;
+        po[1] = g;
+        po[2] = b;
+
+        pi += depth;
+        po += 3; // RGB
+    }
+}
+
+static void send_framebuffer_update_tight(VncState *vs, int x, int y, int w, int h)
+{
+    struct jpeg_compress_struct cinfo;
+    struct jpeg_error_mgr jerr;
+    uint8_t *row = ds_get_data(vs->ds) +
+                   y * ds_get_linesize(vs->ds) +
+                   x * ds_get_bytes_per_pixel(vs->ds);
+    int dy;
+    JSAMPROW row_pointer[1];
+
+    if(vnc_has_feature(vs, VNC_FEATURE_HEXTILE) && (w * h) < 300) {
+	/* Below a certain size its actually more efficient to send hextiles
+	 * Take a rough stab in the dark at 300 for text-based displays */
+	 send_framebuffer_update_hextile(vs, x, y, w, h);
+	 return;
+    }
+    
+    vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_TIGHT);
+
+    // XXX For now let's be stupid and always send JPEG data. Tight can do a lot more!
+
+    // Indicate its a Jpeg data stream
+    vnc_write_u8(vs, VNC_TIGHT_CCB_TYPE_JPEG);
+
+    // Compress data
+    cinfo.client_data = vs;
+    cinfo.err = jpeg_std_error(&jerr);
+    jpeg_create_compress(&cinfo);
+    cinfo.image_width = w;
+    cinfo.image_height = h;
+    cinfo.input_components = 3;
+    cinfo.in_color_space = JCS_RGB;
+
+    jpeg_set_defaults(&cinfo);
+    jpeg_set_quality(&cinfo, (vs->tight_quality+1) * 10, TRUE);
+
+    buffer_reserve(&vs->jpeg_buffer, 1024);
+    vs->jpeg_dst_manager.init_destination = jpeg_init_destination;
+    vs->jpeg_dst_manager.empty_output_buffer = jpeg_empty_output_buffer;
+    vs->jpeg_dst_manager.term_destination = jpeg_term_destination;
+    cinfo.dest = &vs->jpeg_dst_manager;
+
+    jpeg_start_compress(&cinfo, TRUE);
+
+    row_pointer[0] = qemu_malloc(3 * w);
+    for (dy = 0; dy < h; dy++) {
+        jpeg_row2pixel(vs, (char*)row, (char*)row_pointer[0], w);
+        jpeg_write_scanlines(&cinfo, row_pointer, 1);
+        row += ds_get_linesize(vs->ds);
+    }
+    qemu_free(row_pointer[0]);
+
+    jpeg_finish_compress(&cinfo);
+    jpeg_destroy_compress(&cinfo);
+
+    VNC_DEBUG("JPEG: Sending %d bytes of jpeg data\n", (int)vs->jpeg_buffer.offset);
+    vnc_send_compact_size(vs, vs->jpeg_buffer.offset);
+    vnc_write(vs, vs->jpeg_buffer.buffer, vs->jpeg_buffer.offset);
+    buffer_reset(&vs->jpeg_buffer);
+}
+#endif /* CONFIG_VNC_JPEG */
+
 static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
 {
     switch(vs->vnc_encoding) {
+#ifdef CONFIG_VNC_JPEG
+	case VNC_ENCODING_TIGHT:
+	    send_framebuffer_update_tight(vs, x, y, w, h);
+	    break;
+#endif /* CONFIG_VNC_JPEG */
 	case VNC_ENCODING_HEXTILE:
 	    send_framebuffer_update_hextile(vs, x, y, w, h);
 	    break;
@@ -1204,7 +1378,11 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
             vs->vnc_encoding = enc;
             break;
         case VNC_ENCODING_TIGHT:
+#ifdef CONFIG_VNC_JPEG
+            buffer_reset(&vs->jpeg_buffer);
+#endif
             vs->features |= VNC_FEATURE_TIGHT_MASK;
+            vs->vnc_encoding = enc;
             break;
         case VNC_ENCODING_DESKTOPRESIZE:
             vs->features |= VNC_FEATURE_RESIZE_MASK;
-- 
1.6.0.2

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

* [Qemu-devel] Re: [PATCH 4/7] Make vnc buffer big-chunk aware
  2009-01-29 11:24       ` [Qemu-devel] [PATCH 4/7] Make vnc buffer big-chunk aware Alexander Graf
  2009-01-29 11:24         ` [Qemu-devel] [PATCH 5/7] Split vnc authentication code Alexander Graf
@ 2009-01-29 15:11         ` Anthony Liguori
  2009-01-29 15:16           ` Alexander Graf
  1 sibling, 1 reply; 20+ messages in thread
From: Anthony Liguori @ 2009-01-29 15:11 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel

Alexander Graf wrote:
> Currently writing to buffers is protected by buffer_reserve.
> Unfortunately, is reserves at most 1024 bytes more than we currently
> have, so if we want to write a 2048 bytes chunk, we overwrite
> random memory.
>   

Yikes!

> This patch addresses this in a pretty dumb but easy way.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
>  vnc.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/vnc.c b/vnc.c
> index 4b17f85..d0d9580 100644
> --- a/vnc.c
> +++ b/vnc.c
> @@ -592,7 +592,7 @@ static int vnc_listen_poll(void *opaque)
>  
>  static void buffer_reserve(Buffer *buffer, size_t len)
>  {
> -    if ((buffer->capacity - buffer->offset) < len) {
> +    while ((buffer->capacity - buffer->offset) < len) {
>  	buffer->capacity += (len + 1024);
>   

Okay, I no longer believe you.

If we want to write len bytes, and we increase capacity by (len + 1024) 
bytes, then we should be fine.  The reason it's len + 1024 vs just len 
is to avoid many qemu_realloc()s on many small reservations (like for 
adding u32s).

Regards,

Anthony Liguori
>  	buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity);
>  	if (buffer->buffer == NULL) {
>   

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

* [Qemu-devel] Re: [PATCH 6/7] Add tight protocol awareness to vnc.c
  2009-01-29 11:24           ` [Qemu-devel] [PATCH 6/7] Add tight protocol awareness to vnc.c Alexander Graf
  2009-01-29 11:24             ` [Qemu-devel] [PATCH 7/7] Add tight encoding (jpeg) " Alexander Graf
@ 2009-01-29 15:13             ` Anthony Liguori
  2009-01-29 15:24               ` Alexander Graf
  1 sibling, 1 reply; 20+ messages in thread
From: Anthony Liguori @ 2009-01-29 15:13 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel

Alexander Graf wrote:
> This patch enables the vnc server to understand the tight protocol.
>
> Basically, negotiation if tight is existing happens through the
> authentication code. If a special authentication called VNC_AUTH_TIGHT
> is used, the real authentication is stacked afterwards and tight
> extensions exist.
>   

This is wrong.  The way the standard works is that the client advertises 
the Tight encoding via SetEncodingTypes.  That's all that should be 
needed.  The VNC_AUTH_TIGHT thing is a Tight extension that shouldn't be 
needed for implementing tight encoding.

Regards,

Anthony Liguori

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

* [Qemu-devel] Re: [PATCH 4/7] Make vnc buffer big-chunk aware
  2009-01-29 15:11         ` [Qemu-devel] Re: [PATCH 4/7] Make vnc buffer big-chunk aware Anthony Liguori
@ 2009-01-29 15:16           ` Alexander Graf
  0 siblings, 0 replies; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 15:16 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel@nongnu.org





On 29.01.2009, at 16:11, Anthony Liguori <anthony@codemonkey.ws> wrote:

> Alexander Graf wrote:
>> Currently writing to buffers is protected by buffer_reserve.
>> Unfortunately, is reserves at most 1024 bytes more than we currently
>> have, so if we want to write a 2048 bytes chunk, we overwrite
>> random memory.
>>
>
> Yikes!
>
>> This patch addresses this in a pretty dumb but easy way.
>>
>> Signed-off-by: Alexander Graf <agraf@suse.de>
>> ---
>> vnc.c |    2 +-
>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/vnc.c b/vnc.c
>> index 4b17f85..d0d9580 100644
>> --- a/vnc.c
>> +++ b/vnc.c
>> @@ -592,7 +592,7 @@ static int vnc_listen_poll(void *opaque)
>>  static void buffer_reserve(Buffer *buffer, size_t len)
>> {
>> -    if ((buffer->capacity - buffer->offset) < len) {
>> +    while ((buffer->capacity - buffer->offset) < len) {
>>    buffer->capacity += (len + 1024);
>>
>
> Okay, I no longer believe you.
>
> If we want to write len bytes, and we increase capacity by (len +  
> 1024) bytes, then we should be fine.  The reason it's len + 1024 vs  
> just len is to avoid many qemu_realloc()s on many small reservations  
> (like for adding u32s).

Ugh. I must've been really tired there :o. You're right, the code does  
look good.

Alex

>
>
> Regards,
>
> Anthony Liguori
>>    buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity);
>>    if (buffer->buffer == NULL) {
>>
>

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

* [Qemu-devel] Re: [PATCH 7/7] Add tight encoding (jpeg) to vnc.c
  2009-01-29 11:24             ` [Qemu-devel] [PATCH 7/7] Add tight encoding (jpeg) " Alexander Graf
@ 2009-01-29 15:17               ` Anthony Liguori
  2009-01-29 15:23                 ` Stefano Stabellini
  0 siblings, 1 reply; 20+ messages in thread
From: Anthony Liguori @ 2009-01-29 15:17 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel

Alexander Graf wrote:
> Because we can now speak the tight protocol, let's use it to
> transmit jpeg data to the client!
>
> This patch adds a really easy implementation of the jpeg tight
> encoding. Tight in general can do a lot more, but let's take small
> steps here and see how things perform.
>
> Signed-off-by: Alexander Graf <agraf@suse.de>
>   

I don't really like the idea of taking this.  Tight is supported by a 
lot of clients and is usually very high on the preferred list.  However, 
most servers do not enable jpeg compression by default because it's lossy.

If we implement Tight and then use jpeg by default, for most clients, 
the default is going to be lossy encoding.  While lossy isn't so bad for 
high detailed images (like pictures), it's pretty terrible for simple, 
high contrast images (like windows in a desktop).

TightVNC has some sophisticated heuristics for determining whether to 
use jpeg or not (when it's enabled).  I think that sort of heuristic is 
a prerequisite for enabling tight's jpeg support.

FWIW, Tight essentially does hextile encoding but adds zlib 
compression.  That's probably a better place to start as it should 
outperform hextile while remaining lossless.

Regards,

Anthony Liguori

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

* [Qemu-devel] Re: [PATCH 1/7] Split VNC defines to vnc.h
  2009-01-29 11:24 ` [Qemu-devel] [PATCH 1/7] Split VNC defines to vnc.h Alexander Graf
  2009-01-29 11:24   ` [Qemu-devel] [PATCH 2/7] Use VNC protocol defines Alexander Graf
@ 2009-01-29 15:22   ` Anthony Liguori
  2009-01-29 15:29     ` Alexander Graf
  1 sibling, 1 reply; 20+ messages in thread
From: Anthony Liguori @ 2009-01-29 15:22 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel

Alexander Graf wrote:
> The VNC protocol contains quite some constants, some of which are
> currently hardcoded in the vnc.c code. This is not exactly pretty.
>
> Let's move all those constants out to vnc.h, so they are clearly
> separated. While at it, I also included other defines that will be
> used later in this patch series.
>   

A much needed change.

> diff --git a/vnc.h b/vnc.h
> new file mode 100644
> index 0000000..ae69bc3
> --- /dev/null
> +++ b/vnc.h
> @@ -0,0 +1,130 @@
> +#ifndef __VNCTIGHT_H
> +#define __VNCTIGHT_H
> +
> +/*****************************************************************************
> + *
> + * Authentication modes
> + *
> + *****************************************************************************/
> +
> +enum {
> +    VNC_AUTH_INVALID = 0,
> +    VNC_AUTH_NONE = 1,
> +    VNC_AUTH_VNC = 2,
> +    VNC_AUTH_RA2 = 5,
> +    VNC_AUTH_RA2NE = 6,
> +    VNC_AUTH_TIGHT = 16,
> +    VNC_AUTH_ULTRA = 17,
> +    VNC_AUTH_TLS = 18,
> +    VNC_AUTH_VENCRYPT = 19
> +};
> +
> +#define VNC_AUTH_NONE_SIG "NOAUTH__"
> +#define VNC_AUTH_VNC_SIG  "VNCAUTH_"
>   

These AUTH sigs are not part of the standard as far as I'm aware of it.  
This is the VNC_AUTH_TIGHT stuff?  I'd rather not do that.

> +
> +#define VNC_ENCODING_RAW                  0x00000000
> +#define VNC_ENCODING_COPYRECT             0x00000001
> +#define VNC_ENCODING_RRE                  0x00000002
> +#define VNC_ENCODING_CORRE                0x00000004
> +#define VNC_ENCODING_HEXTILE              0x00000005
> +#define VNC_ENCODING_ZLIB                 0x00000006
> +#define VNC_ENCODING_TIGHT                0x00000007
> +#define VNC_ENCODING_ZLIBHEX              0x00000008
>   

This was never standardized.

> +#define VNC_ENCODING_ZRLE                 0x00000010
> +#define VNC_ENCODING_COMPRESSLEVEL0       0xFFFFFF00
> +#define VNC_ENCODING_QUALITYLEVEL0        0xFFFFFFE0
> +#define VNC_ENCODING_XCURSOR              0xFFFFFF10
> +#define VNC_ENCODING_RICH_CURSOR          0xFFFFFF11
> +#define VNC_ENCODING_POINTER_POS          0xFFFFFF18
>   
Nor was this.
> +#define VNC_ENCODING_LASTRECT             0xFFFFFF20
>   
Nor this.
> +#define VNC_ENCODING_DESKTOPRESIZE        0xFFFFFF21
> +#define VNC_ENCODING_POINTER_TYPE_CHANGE  0XFFFFFEFF
> +#define VNC_ENCODING_EXT_KEY_EVENT        0XFFFFFEFE
> +#define VNC_ENCODING_AUDIO                0XFFFFFEFD
> +#define VNC_ENCODING_WMVi                 0x574D5669
> +
> +/* signatures for basic encoding types */
> +#define VNC_ENCODING_RAW_SIG              "RAW_____"
> +#define VNC_ENCODING_COPYRECT_SIG         "COPYRECT"
> +#define VNC_ENCODING_RRE_SIG              "RRE_____"
> +#define VNC_ENCODING_CORRE_SIG            "CORRE___"
> +#define VNC_ENCODING_HEXTILE_SIG          "HEXTILE_"
> +#define VNC_ENCODING_ZLIB_SIG             "ZLIB____"
> +#define VNC_ENCODING_TIGHT_SIG            "TIGHT___"
> +#define VNC_ENCODING_ZLIBHEX_SIG          "ZLIBHEX_"
> +#define VNC_ENCODING_ZRLE_SIG             "ZRLE____"
> +#define VNC_ENCODING_COMPRESSLEVEL0_SIG   "COMPRLVL"
> +#define VNC_ENCODING_QUALITYLEVEL0_SIG    "JPEGQLVL"
>   

These are not part of the standard either.  I'm not sure what they do.

> +/*****************************************************************************
> + *
> + * Other tight constants
> + *
> + *****************************************************************************/
> +
> +/*
> + * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC.
> + */
> +
> +#define VNC_VENDOR_STANDARD        "STDV"
> +#define VNC_VENDOR_TRIDIA          "TRDV"
> +#define VNC_VENDOR_TIGHT           "TGHT"
>   

This also is not part of the standard.

Regards,

Anthony Liguori

> +#define VNC_TIGHT_CCB_RESET_MASK   (0x0f)
> +#define VNC_TIGHT_CCB_TYPE_MASK    (0x0f << 4)
> +#define VNC_TIGHT_CCB_TYPE_FILL    (0x08 << 4)
> +#define VNC_TIGHT_CCB_TYPE_JPEG    (0x09 << 4)
> +#define VNC_TIGHT_CCB_BASIC_MAX    (0x07 << 4)
> +#define VNC_TIGHT_CCB_BASIC_ZLIB   (0x03 << 4)
> +#define VNC_TIGHT_CCB_BASIC_FILTER (0x04 << 4)
> +
> +/*****************************************************************************
> + *
> + * Features
> + *
> + *****************************************************************************/
> +
> +#define VNC_FEATURE_RESIZE                   0
> +#define VNC_FEATURE_HEXTILE                  1
> +#define VNC_FEATURE_POINTER_TYPE_CHANGE      2
> +#define VNC_FEATURE_WMVI                     3
> +#define VNC_FEATURE_TIGHT                    4
> +#define VNC_FEATURE_TIGHT_PROTOCOL           5
> +
> +#define VNC_FEATURE_RESIZE_MASK              (1 << VNC_FEATURE_RESIZE)
> +#define VNC_FEATURE_HEXTILE_MASK             (1 << VNC_FEATURE_HEXTILE)
> +#define VNC_FEATURE_POINTER_TYPE_CHANGE_MASK (1 << VNC_FEATURE_POINTER_TYPE_CHANGE)
> +#define VNC_FEATURE_WMVI_MASK                (1 << VNC_FEATURE_WMVI)
> +#define VNC_FEATURE_TIGHT_MASK               (1 << VNC_FEATURE_TIGHT)
> +#define VNC_FEATURE_TIGHT_PROTOCOL_MASK      (1 << VNC_FEATURE_TIGHT_PROTOCOL)
> +
> +#endif /* __VNCTIGHT_H */
>   

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

* Re: [Qemu-devel] Re: [PATCH 7/7] Add tight encoding (jpeg) to vnc.c
  2009-01-29 15:17               ` [Qemu-devel] " Anthony Liguori
@ 2009-01-29 15:23                 ` Stefano Stabellini
  2009-01-29 15:47                   ` Anthony Liguori
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Stabellini @ 2009-01-29 15:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alexander Graf

Anthony Liguori wrote:

> If we implement Tight and then use jpeg by default, for most clients,
> the default is going to be lossy encoding.  While lossy isn't so bad for
> high detailed images (like pictures), it's pretty terrible for simple,
> high contrast images (like windows in a desktop).
> 
> TightVNC has some sophisticated heuristics for determining whether to
> use jpeg or not (when it's enabled).  I think that sort of heuristic is
> a prerequisite for enabling tight's jpeg support.
> 
> FWIW, Tight essentially does hextile encoding but adds zlib
> compression.  That's probably a better place to start as it should
> outperform hextile while remaining lossless.
> 

Another thing to consider is that using jpeg compression is going to
worsen qemu performances, so I think it should be used only when
necessary, e.g. the network connection between client and server is  bad.

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

* [Qemu-devel] Re: [PATCH 6/7] Add tight protocol awareness to vnc.c
  2009-01-29 15:13             ` [Qemu-devel] Re: [PATCH 6/7] Add tight protocol awareness " Anthony Liguori
@ 2009-01-29 15:24               ` Alexander Graf
  2009-01-29 15:43                 ` Anthony Liguori
  0 siblings, 1 reply; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 15:24 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel

Anthony Liguori wrote:
> Alexander Graf wrote:
>> This patch enables the vnc server to understand the tight protocol.
>>
>> Basically, negotiation if tight is existing happens through the
>> authentication code. If a special authentication called VNC_AUTH_TIGHT
>> is used, the real authentication is stacked afterwards and tight
>> extensions exist.
>>   
>
> This is wrong.  The way the standard works is that the client
> advertises the Tight encoding via SetEncodingTypes.  That's all that
> should be needed.  The VNC_AUTH_TIGHT thing is a Tight extension that
> shouldn't be needed for implementing tight encoding.

So how am I supposed to do the write_tight_interaction_capabilities()
thing? I don't see how we advertise to the guest that we do support
tight encoding if we can't tell it that we do.

Alex
>
> Regards,
>
> Anthony Liguori

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

* [Qemu-devel] Re: [PATCH 1/7] Split VNC defines to vnc.h
  2009-01-29 15:22   ` [Qemu-devel] Re: [PATCH 1/7] Split VNC defines to vnc.h Anthony Liguori
@ 2009-01-29 15:29     ` Alexander Graf
  2009-01-29 15:46       ` Anthony Liguori
  0 siblings, 1 reply; 20+ messages in thread
From: Alexander Graf @ 2009-01-29 15:29 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel

Anthony Liguori wrote:
> Alexander Graf wrote:
>> The VNC protocol contains quite some constants, some of which are
>> currently hardcoded in the vnc.c code. This is not exactly pretty.
>>
>> Let's move all those constants out to vnc.h, so they are clearly
>> separated. While at it, I also included other defines that will be
>> used later in this patch series.
>>   
>
> A much needed change.
>
>> diff --git a/vnc.h b/vnc.h
>> new file mode 100644
>> index 0000000..ae69bc3
>> --- /dev/null
>> +++ b/vnc.h
>> @@ -0,0 +1,130 @@
>> +#ifndef __VNCTIGHT_H
>> +#define __VNCTIGHT_H
>> +
>> +/*****************************************************************************
>>
>> + *
>> + * Authentication modes
>> + *
>> +
>> *****************************************************************************/
>>
>> +
>> +enum {
>> +    VNC_AUTH_INVALID = 0,
>> +    VNC_AUTH_NONE = 1,
>> +    VNC_AUTH_VNC = 2,
>> +    VNC_AUTH_RA2 = 5,
>> +    VNC_AUTH_RA2NE = 6,
>> +    VNC_AUTH_TIGHT = 16,
>> +    VNC_AUTH_ULTRA = 17,
>> +    VNC_AUTH_TLS = 18,
>> +    VNC_AUTH_VENCRYPT = 19
>> +};
>> +
>> +#define VNC_AUTH_NONE_SIG "NOAUTH__"
>> +#define VNC_AUTH_VNC_SIG  "VNCAUTH_"
>>   
>
> These AUTH sigs are not part of the standard as far as I'm aware of
> it.  This is the VNC_AUTH_TIGHT stuff?  I'd rather not do that.

Right. That is the follow-up from AUTH_TIGHT. Tight uses signatures in
general as addition to normal codes. The same thing applies to the
encoding signatures. These are required for the "Hey client, I know
these encodings" packet.

>
>> +
>> +#define VNC_ENCODING_RAW                  0x00000000
>> +#define VNC_ENCODING_COPYRECT             0x00000001
>> +#define VNC_ENCODING_RRE                  0x00000002
>> +#define VNC_ENCODING_CORRE                0x00000004
>> +#define VNC_ENCODING_HEXTILE              0x00000005
>> +#define VNC_ENCODING_ZLIB                 0x00000006
>> +#define VNC_ENCODING_TIGHT                0x00000007
>> +#define VNC_ENCODING_ZLIBHEX              0x00000008
>>   
>
> This was never standardized.

>From rfbproto.h of current tightvnc:

#define rfbEncodingRaw       0
#define rfbEncodingCopyRect  1
#define rfbEncodingRRE       2
#define rfbEncodingCoRRE     4
#define rfbEncodingHextile   5
#define rfbEncodingZlib      6
#define rfbEncodingTight     7
#define rfbEncodingZlibHex   8
#define rfbEncodingZRLE     16
[...]
#define rfbEncodingXCursor         0xFFFFFF10
#define rfbEncodingRichCursor      0xFFFFFF11
#define rfbEncodingPointerPos      0xFFFFFF18

#define rfbEncodingLastRect        0xFFFFFF20
#define rfbEncodingNewFBSize       0xFFFFFF21

Where else should I look for defines? I'd rather have them here and if
anything collide than not in any header files.

>
>> +#define VNC_ENCODING_ZRLE                 0x00000010
>> +#define VNC_ENCODING_COMPRESSLEVEL0       0xFFFFFF00
>> +#define VNC_ENCODING_QUALITYLEVEL0        0xFFFFFFE0
>> +#define VNC_ENCODING_XCURSOR              0xFFFFFF10
>> +#define VNC_ENCODING_RICH_CURSOR          0xFFFFFF11
>> +#define VNC_ENCODING_POINTER_POS          0xFFFFFF18
>>   
> Nor was this.
>> +#define VNC_ENCODING_LASTRECT             0xFFFFFF20
>>   
> Nor this.
>> +#define VNC_ENCODING_DESKTOPRESIZE        0xFFFFFF21
>> +#define VNC_ENCODING_POINTER_TYPE_CHANGE  0XFFFFFEFF
>> +#define VNC_ENCODING_EXT_KEY_EVENT        0XFFFFFEFE
>> +#define VNC_ENCODING_AUDIO                0XFFFFFEFD
>> +#define VNC_ENCODING_WMVi                 0x574D5669
>> +
>> +/* signatures for basic encoding types */
>> +#define VNC_ENCODING_RAW_SIG              "RAW_____"
>> +#define VNC_ENCODING_COPYRECT_SIG         "COPYRECT"
>> +#define VNC_ENCODING_RRE_SIG              "RRE_____"
>> +#define VNC_ENCODING_CORRE_SIG            "CORRE___"
>> +#define VNC_ENCODING_HEXTILE_SIG          "HEXTILE_"
>> +#define VNC_ENCODING_ZLIB_SIG             "ZLIB____"
>> +#define VNC_ENCODING_TIGHT_SIG            "TIGHT___"
>> +#define VNC_ENCODING_ZLIBHEX_SIG          "ZLIBHEX_"
>> +#define VNC_ENCODING_ZRLE_SIG             "ZRLE____"
>> +#define VNC_ENCODING_COMPRESSLEVEL0_SIG   "COMPRLVL"
>> +#define VNC_ENCODING_QUALITYLEVEL0_SIG    "JPEGQLVL"
>>   
>
> These are not part of the standard either.  I'm not sure what they do.
>
>> +/*****************************************************************************
>>
>> + *
>> + * Other tight constants
>> + *
>> +
>> *****************************************************************************/
>>
>> +
>> +/*
>> + * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and
>> TightVNC.
>> + */
>> +
>> +#define VNC_VENDOR_STANDARD        "STDV"
>> +#define VNC_VENDOR_TRIDIA          "TRDV"
>> +#define VNC_VENDOR_TIGHT           "TGHT"
>>   
>
> This also is not part of the standard.
>
> Regards,
>
> Anthony Liguori
>
>> +#define VNC_TIGHT_CCB_RESET_MASK   (0x0f)
>> +#define VNC_TIGHT_CCB_TYPE_MASK    (0x0f << 4)
>> +#define VNC_TIGHT_CCB_TYPE_FILL    (0x08 << 4)
>> +#define VNC_TIGHT_CCB_TYPE_JPEG    (0x09 << 4)
>> +#define VNC_TIGHT_CCB_BASIC_MAX    (0x07 << 4)
>> +#define VNC_TIGHT_CCB_BASIC_ZLIB   (0x03 << 4)
>> +#define VNC_TIGHT_CCB_BASIC_FILTER (0x04 << 4)
>> +
>> +/*****************************************************************************
>>
>> + *
>> + * Features
>> + *
>> +
>> *****************************************************************************/
>>
>> +
>> +#define VNC_FEATURE_RESIZE                   0
>> +#define VNC_FEATURE_HEXTILE                  1
>> +#define VNC_FEATURE_POINTER_TYPE_CHANGE      2
>> +#define VNC_FEATURE_WMVI                     3
>> +#define VNC_FEATURE_TIGHT                    4
>> +#define VNC_FEATURE_TIGHT_PROTOCOL           5
>> +
>> +#define VNC_FEATURE_RESIZE_MASK              (1 << VNC_FEATURE_RESIZE)
>> +#define VNC_FEATURE_HEXTILE_MASK             (1 << VNC_FEATURE_HEXTILE)
>> +#define VNC_FEATURE_POINTER_TYPE_CHANGE_MASK (1 <<
>> VNC_FEATURE_POINTER_TYPE_CHANGE)
>> +#define VNC_FEATURE_WMVI_MASK                (1 << VNC_FEATURE_WMVI)
>> +#define VNC_FEATURE_TIGHT_MASK               (1 << VNC_FEATURE_TIGHT)
>> +#define VNC_FEATURE_TIGHT_PROTOCOL_MASK      (1 <<
>> VNC_FEATURE_TIGHT_PROTOCOL)
>> +
>> +#endif /* __VNCTIGHT_H */
>>   
>

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

* [Qemu-devel] Re: [PATCH 6/7] Add tight protocol awareness to vnc.c
  2009-01-29 15:24               ` Alexander Graf
@ 2009-01-29 15:43                 ` Anthony Liguori
  0 siblings, 0 replies; 20+ messages in thread
From: Anthony Liguori @ 2009-01-29 15:43 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel

Alexander Graf wrote:
> Anthony Liguori wrote:
>   
>> Alexander Graf wrote:
>>     
>>> This patch enables the vnc server to understand the tight protocol.
>>>
>>> Basically, negotiation if tight is existing happens through the
>>> authentication code. If a special authentication called VNC_AUTH_TIGHT
>>> is used, the real authentication is stacked afterwards and tight
>>> extensions exist.
>>>   
>>>       
>> This is wrong.  The way the standard works is that the client
>> advertises the Tight encoding via SetEncodingTypes.  That's all that
>> should be needed.  The VNC_AUTH_TIGHT thing is a Tight extension that
>> shouldn't be needed for implementing tight encoding.
>>     
>
> So how am I supposed to do the write_tight_interaction_capabilities()
> thing? I don't see how we advertise to the guest that we do support
> tight encoding if we can't tell it that we do.
>   

The server doesn't advertise encodings to the client.  The client 
advertises supported encodings to the server and the server chooses to 
use whatever one it would like to (that is supports).  A server is 
supposed to ignore encodings that it doesn't know about.

Regards,

Anthony Liguori

> Alex
>   
>> Regards,
>>
>> Anthony Liguori
>>     
>
>   

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

* [Qemu-devel] Re: [PATCH 1/7] Split VNC defines to vnc.h
  2009-01-29 15:29     ` Alexander Graf
@ 2009-01-29 15:46       ` Anthony Liguori
  0 siblings, 0 replies; 20+ messages in thread
From: Anthony Liguori @ 2009-01-29 15:46 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel

Alexander Graf wrote:
> Anthony Liguori wrote:
>   
>> Alexander Graf wrote:
>>     
>>> The VNC protocol contains quite some constants, some of which are
>>> currently hardcoded in the vnc.c code. This is not exactly pretty.
>>>
>>> Let's move all those constants out to vnc.h, so they are clearly
>>> separated. While at it, I also included other defines that will be
>>> used later in this patch series.
>>>   
>>>       
>> A much needed change.
>>
>>     
>>> diff --git a/vnc.h b/vnc.h
>>> new file mode 100644
>>> index 0000000..ae69bc3
>>> --- /dev/null
>>> +++ b/vnc.h
>>> @@ -0,0 +1,130 @@
>>> +#ifndef __VNCTIGHT_H
>>> +#define __VNCTIGHT_H
>>> +
>>> +/*****************************************************************************
>>>
>>> + *
>>> + * Authentication modes
>>> + *
>>> +
>>> *****************************************************************************/
>>>
>>> +
>>> +enum {
>>> +    VNC_AUTH_INVALID = 0,
>>> +    VNC_AUTH_NONE = 1,
>>> +    VNC_AUTH_VNC = 2,
>>> +    VNC_AUTH_RA2 = 5,
>>> +    VNC_AUTH_RA2NE = 6,
>>> +    VNC_AUTH_TIGHT = 16,
>>> +    VNC_AUTH_ULTRA = 17,
>>> +    VNC_AUTH_TLS = 18,
>>> +    VNC_AUTH_VENCRYPT = 19
>>> +};
>>> +
>>> +#define VNC_AUTH_NONE_SIG "NOAUTH__"
>>> +#define VNC_AUTH_VNC_SIG  "VNCAUTH_"
>>>   
>>>       
>> These AUTH sigs are not part of the standard as far as I'm aware of
>> it.  This is the VNC_AUTH_TIGHT stuff?  I'd rather not do that.
>>     
>
> Right. That is the follow-up from AUTH_TIGHT. Tight uses signatures in
> general as addition to normal codes. The same thing applies to the
> encoding signatures. These are required for the "Hey client, I know
> these encodings" packet.
>
>   
>>> +
>>> +#define VNC_ENCODING_RAW                  0x00000000
>>> +#define VNC_ENCODING_COPYRECT             0x00000001
>>> +#define VNC_ENCODING_RRE                  0x00000002
>>> +#define VNC_ENCODING_CORRE                0x00000004
>>> +#define VNC_ENCODING_HEXTILE              0x00000005
>>> +#define VNC_ENCODING_ZLIB                 0x00000006
>>> +#define VNC_ENCODING_TIGHT                0x00000007
>>> +#define VNC_ENCODING_ZLIBHEX              0x00000008
>>>   
>>>       
>> This was never standardized.
>>     
>
> From rfbproto.h of current tightvnc:
>
> #define rfbEncodingRaw       0
> #define rfbEncodingCopyRect  1
> #define rfbEncodingRRE       2
> #define rfbEncodingCoRRE     4
> #define rfbEncodingHextile   5
> #define rfbEncodingZlib      6
> #define rfbEncodingTight     7
> #define rfbEncodingZlibHex   8
> #define rfbEncodingZRLE     16
> [...]
> #define rfbEncodingXCursor         0xFFFFFF10
> #define rfbEncodingRichCursor      0xFFFFFF11
> #define rfbEncodingPointerPos      0xFFFFFF18
>
> #define rfbEncodingLastRect        0xFFFFFF20
> #define rfbEncodingNewFBSize       0xFFFFFF21
>
> Where else should I look for defines? I'd rather have them here and if
> anything collide than not in any header files.
>   

http://www.realvnc.com/docs/rfbproto.pdf is where the protocol is 
defined.  Early in VNC's life, when TightVNC first fork()'d from 
RealVNC, there was no formal protocol definition.  This led to some 
incompatible implementations so if you want to maintain compatibility 
with the largest number of clients, it's best to stick to what's defined 
by the standard.

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] Re: [PATCH 7/7] Add tight encoding (jpeg) to vnc.c
  2009-01-29 15:23                 ` Stefano Stabellini
@ 2009-01-29 15:47                   ` Anthony Liguori
  0 siblings, 0 replies; 20+ messages in thread
From: Anthony Liguori @ 2009-01-29 15:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Alexander Graf

Stefano Stabellini wrote:
> Anthony Liguori wrote:
>
>   
>> If we implement Tight and then use jpeg by default, for most clients,
>> the default is going to be lossy encoding.  While lossy isn't so bad for
>> high detailed images (like pictures), it's pretty terrible for simple,
>> high contrast images (like windows in a desktop).
>>
>> TightVNC has some sophisticated heuristics for determining whether to
>> use jpeg or not (when it's enabled).  I think that sort of heuristic is
>> a prerequisite for enabling tight's jpeg support.
>>
>> FWIW, Tight essentially does hextile encoding but adds zlib
>> compression.  That's probably a better place to start as it should
>> outperform hextile while remaining lossless.
>>
>>     
>
> Another thing to consider is that using jpeg compression is going to
> worsen qemu performances, so I think it should be used only when
> necessary, e.g. the network connection between client and server is  bad.
>   

Most clients I know do not enable JPEG by default.  It requires a user 
to explicitly do so.

Regards,

Anthony Liguori

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

* [Qemu-devel] [PATCH 3/7] Fix invalid #if in vnc.c when debugging is enabled
  2009-01-30 14:38   ` [Qemu-devel] [PATCH 2/7] Use VNC protocol defines Alexander Graf
@ 2009-01-30 14:38     ` Alexander Graf
  0 siblings, 0 replies; 20+ messages in thread
From: Alexander Graf @ 2009-01-30 14:38 UTC (permalink / raw)
  To: qemu-devel

While running with debugging enabled, I found an #if testing for
an undefined value, not defined(value). This patch fixes that.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 vnc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/vnc.c b/vnc.c
index 6b885d3..4b17f85 100644
--- a/vnc.c
+++ b/vnc.c
@@ -47,7 +47,7 @@
 #ifdef _VNC_DEBUG
 #define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
 
-#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
+#if defined(CONFIG_VNC_TLS) && _VNC_DEBUG >= 2
 /* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
 static void vnc_debug_gnutls_log(int level, const char* str) {
     VNC_DEBUG("%d %s", level, str);
-- 
1.6.0.2

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

end of thread, other threads:[~2009-01-30 14:38 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-29 11:24 [Qemu-devel] [PATCH 0/7] Add tight support to VNC Alexander Graf
2009-01-29 11:24 ` [Qemu-devel] [PATCH 1/7] Split VNC defines to vnc.h Alexander Graf
2009-01-29 11:24   ` [Qemu-devel] [PATCH 2/7] Use VNC protocol defines Alexander Graf
2009-01-29 11:24     ` [Qemu-devel] [PATCH 3/7] Fix invalid #if in vnc.c when debugging is enabled Alexander Graf
2009-01-29 11:24       ` [Qemu-devel] [PATCH 4/7] Make vnc buffer big-chunk aware Alexander Graf
2009-01-29 11:24         ` [Qemu-devel] [PATCH 5/7] Split vnc authentication code Alexander Graf
2009-01-29 11:24           ` [Qemu-devel] [PATCH 6/7] Add tight protocol awareness to vnc.c Alexander Graf
2009-01-29 11:24             ` [Qemu-devel] [PATCH 7/7] Add tight encoding (jpeg) " Alexander Graf
2009-01-29 15:17               ` [Qemu-devel] " Anthony Liguori
2009-01-29 15:23                 ` Stefano Stabellini
2009-01-29 15:47                   ` Anthony Liguori
2009-01-29 15:13             ` [Qemu-devel] Re: [PATCH 6/7] Add tight protocol awareness " Anthony Liguori
2009-01-29 15:24               ` Alexander Graf
2009-01-29 15:43                 ` Anthony Liguori
2009-01-29 15:11         ` [Qemu-devel] Re: [PATCH 4/7] Make vnc buffer big-chunk aware Anthony Liguori
2009-01-29 15:16           ` Alexander Graf
2009-01-29 15:22   ` [Qemu-devel] Re: [PATCH 1/7] Split VNC defines to vnc.h Anthony Liguori
2009-01-29 15:29     ` Alexander Graf
2009-01-29 15:46       ` Anthony Liguori
  -- strict thread matches above, loose matches on Subject: below --
2009-01-30 14:38 [Qemu-devel] [PATCH 0/7] Add zlib support to VNC server Alexander Graf
2009-01-30 14:38 ` [Qemu-devel] [PATCH 1/7] Split VNC defines to vnc.h Alexander Graf
2009-01-30 14:38   ` [Qemu-devel] [PATCH 2/7] Use VNC protocol defines Alexander Graf
2009-01-30 14:38     ` [Qemu-devel] [PATCH 3/7] Fix invalid #if in vnc.c when debugging is enabled Alexander Graf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).