qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 6/7] Add tight protocol awareness to vnc.c
Date: Thu, 29 Jan 2009 12:24:57 +0100	[thread overview]
Message-ID: <1233228298-4844-7-git-send-email-agraf@suse.de> (raw)
In-Reply-To: <1233228298-4844-6-git-send-email-agraf@suse.de>

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

  reply	other threads:[~2009-01-29 11:25 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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           ` Alexander Graf [this message]
2009-01-29 11:24             ` [Qemu-devel] [PATCH 7/7] Add tight encoding (jpeg) to vnc.c 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1233228298-4844-7-git-send-email-agraf@suse.de \
    --to=agraf@suse.de \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).