forked from AuroraMiddleware/gtk
Initial sketch of websockets support
This commit is contained in:
parent
f11a7d2fde
commit
852b317b4f
@ -278,6 +278,21 @@ function handleLoad(event)
|
|||||||
if (outstanding_commands.length == 1) {
|
if (outstanding_commands.length == 1) {
|
||||||
handleOutstanding()
|
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()
|
function connect()
|
||||||
|
@ -153,6 +153,160 @@ set_fd_blocking (int fd)
|
|||||||
fcntl (fd, F_SETFL, arg);
|
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
|
static void
|
||||||
start_output (HttpRequest *request)
|
start_output (HttpRequest *request)
|
||||||
{
|
{
|
||||||
@ -160,8 +314,6 @@ start_output (HttpRequest *request)
|
|||||||
GdkDisplayBroadway *display_broadway;
|
GdkDisplayBroadway *display_broadway;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
g_print ("start_output\n");
|
|
||||||
|
|
||||||
socket = g_socket_connection_get_socket (request->connection);
|
socket = g_socket_connection_get_socket (request->connection);
|
||||||
|
|
||||||
display_broadway = GDK_DISPLAY_BROADWAY (request->display);
|
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);
|
send_data (request, "text/javascript", broadway_js, G_N_ELEMENTS(broadway_js) - 1);
|
||||||
else if (strcmp (escaped, "/output") == 0)
|
else if (strcmp (escaped, "/output") == 0)
|
||||||
start_output (request);
|
start_output (request);
|
||||||
|
else if (strcmp (escaped, "/input") == 0)
|
||||||
|
start_input (request);
|
||||||
else
|
else
|
||||||
send_error (request, 404, "File not found");
|
send_error (request, 404, "File not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
got_http_request_line (GOutputStream *stream,
|
got_http_request_line (GInputStream *stream,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
HttpRequest *request)
|
HttpRequest *request)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user