Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save kanaka/554137 to your computer and use it in GitHub Desktop.

Select an option

Save kanaka/554137 to your computer and use it in GitHub Desktop.
From 1fd701bfddafe631cc0f36155beb33277c7513e2 Mon Sep 17 00:00:00 2001
From: Joel Martin <github@martintribe.org>
Date: Fri, 27 Aug 2010 15:14:51 -0500
Subject: [PATCH] Allow ver 75 and fix header response.
Detect if client is version 75 or 76 and respond appropriately. Also,
parse the path from the request and return the correct Location field
using the host and path.
Also fix some i386 compile errors:
- Hide ivshmem.c under kvm
- type cast some variables in prints
---
Makefile.target | 2 +-
hw/ivshmem.c | 2 +-
ui/vnc.c | 70 ++++++++++++++++++++++++++++++++++++++++++++-----------
ui/vnc.h | 3 +-
4 files changed, 60 insertions(+), 17 deletions(-)
diff --git a/Makefile.target b/Makefile.target
index b791492..c8281e9 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -191,7 +191,7 @@ obj-y += rtl8139.o
obj-y += e1000.o
# Inter-VM PCI shared memory
-obj-y += ivshmem.o
+obj-$(CONFIG_KVM) += ivshmem.o
# Hardware support
obj-i386-y += vga.o
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index bbb5cba..2cc9e16 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -353,7 +353,7 @@ static int check_shm_size(IVShmemState *s, int fd) {
if (s->ivshmem_size > buf.st_size) {
fprintf(stderr, "IVSHMEM ERROR: Requested memory size greater");
fprintf(stderr, " than shared object size (%" PRIu64 " > %ld)\n",
- s->ivshmem_size, buf.st_size);
+ (long long unsigned int) s->ivshmem_size, (long int) buf.st_size);
return -1;
} else {
return 0;
diff --git a/ui/vnc.c b/ui/vnc.c
index 6503508..a551dce 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1075,7 +1075,11 @@ long vnc_client_write_buf(VncState *vs, const uint8_t *data, size_t datalen)
#endif /* CONFIG_VNC_TLS */
ret = send(vs->csock, (const void *)data, datalen, 0);
VNC_DEBUG("Wrote wire %p %zd -> %ld\n", data, datalen, ret);
- VNC_DEBUG("data {\n%s\n}\n", data);
+ if (vs->websockets && vs->encode_ws) {
+ VNC_DEBUG("data {\n%s\n}\n", data+1);
+ } else {
+ VNC_DEBUG("data {\n%s\n}\n", data);
+ }
return vnc_client_io_error(vs, ret, socket_error());
}
@@ -1238,7 +1242,7 @@ static int vnc_client_read_when(VncState *vs, Buffer *buf)
size_t len = vs->read_handler_expect;
int ret;
- VNC_DEBUG("read when: %ld %ld\n", buf->offset, len);
+ VNC_DEBUG("read when: %ld %ld\n", (long int)buf->offset, (long int) len);
if (buf->offset < len) {
return 0;
@@ -1378,8 +1382,8 @@ void vnc_client_read(void *opaque)
}
#endif
- VNC_DEBUG("payload size - %ld %ld\n", payload_size,
- frame_size);
+ VNC_DEBUG("payload size - %ld %ld\n", (long int) payload_size,
+ (long int) frame_size);
buffer_append_b64dec(&vs->ws_input, payload, payload_size);
{
Buffer tmp;
@@ -2543,24 +2547,38 @@ static int vncws_challenge(VncState *vs, uint8_t *challenge,
size_t size)
{
uint8_t response[16];
+ char prefix[5], space[2];
- ws_compute_challenge(vs->key1, vs->key2, challenge, response);
+ if (vs->ws_version == 75) {
+ VNC_DEBUG("ws: using version 75\n");
+ snprintf(prefix, 5, "%s", "");
+ space[0] = ' ';
+ space[1] = '\0';
+ } else if (vs->ws_version == 76) {
+ VNC_DEBUG("ws: using version 76\n");
+ snprintf(prefix, 5, "%s", "Sec-");
+ space[0] = '\0';
+ ws_compute_challenge(vs->key1, vs->key2, challenge, response);
+ }
VNC_DEBUG("ws: sending headers\n");
/* compute challenge junk */
vnc_printf(vs,
- "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
+ "HTTP/1.1 101 Web%sSocket Protocol Handshake\r\n"
"Upgrade: WebSocket\r\n"
"Connection: Upgrade\r\n"
- "Sec-WebSocket-Origin: %s\r\n",
- vs->origin);
+ "%sWebSocket-Origin: %s\r\n",
+ space, prefix, vs->origin);
- vnc_printf(vs, "Sec-WebSocket-Location: %s\r\n",
- "ws://localhost:8787/?b64encode");
- vnc_printf(vs, "Sec-WebSocket-Protocol: %s\r\n", "sample");
+ vnc_printf(vs, "%sWebSocket-Location: %s://%s%s\r\n",
+ prefix, "ws", vs->host, vs->path);
+ vnc_printf(vs, "%sWebSocket-Protocol: %s\r\n", prefix, "sample");
vnc_write(vs, "\r\n", 2);
- vnc_write(vs, response, 16);
+ if (vs->ws_version == 76) {
+ VNC_DEBUG("ws: sending response\n");
+ vnc_write(vs, response, 16);
+ }
vnc_flush(vs);
VNC_DEBUG("ws: sent headers\n");
@@ -2580,8 +2598,14 @@ static int vncws_field_line(VncState *vs, uint8_t *line, size_t size)
int i, j;
if (size == 2) {
- VNC_DEBUG("ws: waiting for challenge\n");
- vnc_read_when(vs, vncws_challenge, 8);
+ if (vs->ws_version == 75) {
+ vncws_challenge(vs, NULL, 0);
+ } else if (vs->ws_version == 76) {
+ VNC_DEBUG("ws: waiting for challenge\n");
+ vnc_read_when(vs, vncws_challenge, 8);
+ } else {
+ VNC_DEBUG("ws: could not detect version\n");
+ }
return 0;
}
@@ -2634,10 +2658,13 @@ static int vncws_field_line(VncState *vs, uint8_t *line, size_t size)
value);
}
} else if (strcmp(name, "Sec-WebSocket-Key1") == 0) {
+ vs->ws_version = 76;
vs->key1 = qemu_strdup(value);
} else if (strcmp(name, "Sec-WebSocket-Key2") == 0) {
+ vs->ws_version = 76;
vs->key2 = qemu_strdup(value);
} else if (strcmp(name, "Sec-WebSocket-Protocol") == 0) {
+ vs->ws_version = 76;
vs->protocol = qemu_strdup(value);
}
@@ -2646,8 +2673,22 @@ static int vncws_field_line(VncState *vs, uint8_t *line, size_t size)
static int vncws_request_line(VncState *vs, uint8_t *buffer, size_t size)
{
+ int i, j;
+ char *line = (char *)buffer, value[1024];
/* parse request line */
VNC_DEBUG("ws: received request %s", buffer);
+ if (strncmp((char *)buffer, "GET ", 4) == 0) {
+ j = 0;
+ for (i=4; i < size; i++, j++) {
+ if (line[i] == ' ') {
+ break;
+ }
+ value[j] = line[i];
+ }
+ value[j] = 0;
+ vs->path = qemu_strdup(value);
+ }
+ /* Parse the rest of the fields */
vnc_read_until(vs, vncws_field_line, "\r\n", 2);
return 0;
}
@@ -2655,6 +2696,7 @@ static int vncws_request_line(VncState *vs, uint8_t *buffer, size_t size)
static void vncws_connect(VncState *vs)
{
VNC_DEBUG("Starting WebSockets session\n");
+ vs->ws_version = 75; // Default
vnc_read_until(vs, vncws_request_line, "\r\n", 2);
}
diff --git a/ui/vnc.h b/ui/vnc.h
index fad8766..b1dfda0 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -208,6 +208,7 @@ struct VncState
int client_height;
int websockets;
int encode_ws;
+ int ws_version;
uint32_t vnc_encoding;
@@ -245,7 +246,7 @@ struct VncState
size_t read_until_buflen;
char *key1, *key2;
- char *host, *origin, *location, *protocol;
+ char *path, *host, *origin, *location, *protocol;
int fields;
/* input */
--
1.6.0.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment