[gtk+/broadway: 21/71] Initial sketch of websockets support
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/broadway: 21/71] Initial sketch of websockets support
- Date: Thu, 25 Nov 2010 21:17:02 +0000 (UTC)
commit 852b317b4f1f09b248ef7b28954ac28ba4560646
Author: Alexander Larsson <alexl redhat com>
Date: Fri Nov 19 14:13:13 2010 +0100
Initial sketch of websockets support
gdk/broadway/broadway.js | 15 ++++
gdk/broadway/gdkdisplay-broadway.c | 160 +++++++++++++++++++++++++++++++++++-
2 files changed, 172 insertions(+), 3 deletions(-)
---
diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
index 0d5749f..615f971 100644
--- a/gdk/broadway/broadway.js
+++ b/gdk/broadway/broadway.js
@@ -278,6 +278,21 @@ function handleLoad(event)
if (outstanding_commands.length == 1) {
handleOutstanding()
}
+
+ if ("WebSocket" in window) {
+ var loc = window.location.toString().replace("http:", "ws:");
+ loc = loc.substr(0, loc.lastIndexOf('/')) + "/input";
+ var ws = new WebSocket(loc, "broadway");
+ ws.onopen = function() {
+ ws.send("Message to send1");
+ ws.send("Message to send2");
+ };
+ ws.onmessage = function (evt) { var msg = evt.data;
+ };
+ ws.onclose = function() { };
+ } else {
+ alert("WebSocket not supported, input will not work!");
+ }
}
function connect()
diff --git a/gdk/broadway/gdkdisplay-broadway.c b/gdk/broadway/gdkdisplay-broadway.c
index b31cdc2..9f73102 100644
--- a/gdk/broadway/gdkdisplay-broadway.c
+++ b/gdk/broadway/gdkdisplay-broadway.c
@@ -153,6 +153,160 @@ set_fd_blocking (int fd)
fcntl (fd, F_SETFL, arg);
}
+static char *
+parse_line (char *line, char *key)
+{
+ char *p;
+
+ if (!g_str_has_prefix (line, key))
+ return NULL;
+ p = line + strlen (key);
+ if (*p != ':')
+ return NULL;
+ p++;
+ /* Skip optional initial space */
+ if (*p == ' ')
+ p++;
+ return p;
+}
+
+static void
+got_input (GInputStream *stream,
+ GAsyncResult *result,
+ HttpRequest *request)
+{
+ char *message;
+ gsize len;
+ GError *error = NULL;
+
+ message = g_data_input_stream_read_upto_finish (G_DATA_INPUT_STREAM (stream), result, &len, &error);
+ if (message == NULL)
+ {
+ g_print (error->message);
+ g_error_free (error);
+ exit (1);
+ }
+ g_assert (message[0] == 0);
+ g_print ("message: %s\n", message+1);
+ /* Skip past ending 0xff */
+ g_data_input_stream_read_byte (request->data, NULL, NULL);
+ g_data_input_stream_read_upto_async (request->data, "\xff", 1, 0, NULL,
+ (GAsyncReadyCallback)got_input, request);
+}
+
+static void
+start_input (HttpRequest *request)
+{
+ char **lines;
+ char *p;
+ int num_key1, num_key2;
+ guint64 key1, key2;
+ int num_space;
+ int i;
+ guint8 challenge[16];
+ char *res;
+ gsize len;
+ GChecksum *checksum;
+ char *origin, *host;
+
+ lines = g_strsplit (request->request->str, "\n", 0);
+
+ num_key1 = 0;
+ num_key2 = 0;
+ key1 = 0;
+ key2 = 0;
+ origin = NULL;
+ host = NULL;
+ for (i = 0; lines[i] != NULL; i++)
+ {
+ if ((p = parse_line (lines[i], "Sec-WebSocket-Key1")))
+ {
+ num_space = 0;
+ while (*p != 0)
+ {
+ if (g_ascii_isdigit (*p))
+ key1 = key1 * 10 + g_ascii_digit_value (*p);
+ else if (*p == ' ')
+ num_space++;
+
+ p++;
+ }
+ key1 /= num_space;
+ num_key1++;
+ }
+ else if ((p = parse_line (lines[i], "Sec-WebSocket-Key2")))
+ {
+ num_space = 0;
+ while (*p != 0)
+ {
+ if (g_ascii_isdigit (*p))
+ key2 = key2 * 10 + g_ascii_digit_value (*p);
+ else if (*p == ' ')
+ num_space++;
+
+ p++;
+ }
+ key2 /= num_space;
+ num_key2++;
+ }
+ else if ((p = parse_line (lines[i], "Origin")))
+ {
+ origin = p;
+ }
+ else if ((p = parse_line (lines[i], "Host")))
+ {
+ host = p;
+ }
+ }
+
+
+ if (num_key1 != 1 || num_key2 != 1 || origin == NULL || host == NULL)
+ {
+ g_print ("error");
+ exit (1);
+ }
+
+ challenge[0] = (key1 >> 24) & 0xff;
+ challenge[1] = (key1 >> 16) & 0xff;
+ challenge[2] = (key1 >> 8) & 0xff;
+ challenge[3] = (key1 >> 0) & 0xff;
+ challenge[4] = (key2 >> 24) & 0xff;
+ challenge[5] = (key2 >> 16) & 0xff;
+ challenge[6] = (key2 >> 8) & 0xff;
+ challenge[7] = (key2 >> 0) & 0xff;
+
+ if (!g_input_stream_read_all (G_INPUT_STREAM (request->data), challenge+8, 8, NULL, NULL, NULL))
+ {
+ g_print ("error");
+ exit (1);
+ }
+
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+ g_checksum_update (checksum, challenge, 16);
+ len = 16;
+ g_checksum_get_digest (checksum, challenge, &len);
+ g_checksum_free (checksum);
+
+ res = g_strdup_printf ("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Origin: %s\r\n"
+ "Sec-WebSocket-Location: ws://%s/input\r\n"
+ "Sec-WebSocket-Protocol: broadway\r\n"
+ "\r\n",
+ origin, host);
+
+ /* TODO: This should really be async */
+ g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+ res, strlen (res), NULL, NULL, NULL);
+ g_free (res);
+ g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+ challenge, 16, NULL, NULL, NULL);
+
+ g_data_input_stream_read_upto_async (request->data, "\xff", 1, 0, NULL,
+ (GAsyncReadyCallback)got_input, request);
+}
+
static void
start_output (HttpRequest *request)
{
@@ -160,8 +314,6 @@ start_output (HttpRequest *request)
GdkDisplayBroadway *display_broadway;
int fd;
- g_print ("start_output\n");
-
socket = g_socket_connection_get_socket (request->connection);
display_broadway = GDK_DISPLAY_BROADWAY (request->display);
@@ -256,12 +408,14 @@ got_request (HttpRequest *request)
send_data (request, "text/javascript", broadway_js, G_N_ELEMENTS(broadway_js) - 1);
else if (strcmp (escaped, "/output") == 0)
start_output (request);
+ else if (strcmp (escaped, "/input") == 0)
+ start_input (request);
else
send_error (request, 404, "File not found");
}
static void
-got_http_request_line (GOutputStream *stream,
+got_http_request_line (GInputStream *stream,
GAsyncResult *result,
HttpRequest *request)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]