summaryrefslogtreecommitdiff
path: root/spicemsg.js
diff options
context:
space:
mode:
authorJeremy White <jwhite@codeweavers.com>2012-06-04 17:22:01 +0300
committerAlon Levy <alevy@redhat.com>2012-06-04 17:22:01 +0300
commitf8f622157c174ba3facc088646484ccba99acc69 (patch)
tree88d99c83e53fa8509a8ca33a6e9f6bdc015e5791 /spicemsg.js
initial
Diffstat (limited to 'spicemsg.js')
-rw-r--r--spicemsg.js791
1 files changed, 791 insertions, 0 deletions
diff --git a/spicemsg.js b/spicemsg.js
new file mode 100644
index 0000000..41b001d
--- /dev/null
+++ b/spicemsg.js
@@ -0,0 +1,791 @@
+"use strict";
+/*
+ Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com>
+
+ This file is part of spice-html5.
+
+ spice-html5 is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ spice-html5 is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with spice-html5. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*----------------------------------------------------------------------------
+** Spice messages
+** This file contains classes for passing messages to and from
+** a spice server. This file should arguably be generated from
+** spice.proto, but it was instead put together by hand.
+**--------------------------------------------------------------------------*/
+function SpiceLinkHeader(a, at)
+{
+ this.magic = SPICE_MAGIC;
+ this.major_version = SPICE_VERSION_MAJOR;
+ this.minor_version = SPICE_VERSION_MINOR;
+ this.size = 0;
+ if (a !== undefined)
+ this.from_buffer(a, at);
+}
+
+SpiceLinkHeader.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.magic = "";
+ for (var i = 0; i < 4; i++)
+ this.magic += String.fromCharCode(dv.getUint8(at + i));
+ at += 4;
+
+ this.major_version = dv.getUint32(at, true); at += 4;
+ this.minor_version = dv.getUint32(at, true); at += 4;
+ this.size = dv.getUint32(at, true); at += 4;
+ },
+
+ to_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ for (var i = 0; i < 4; i++)
+ dv.setUint8(at + i, this.magic.charCodeAt(i));
+ at += 4;
+
+ dv.setUint32(at, this.major_version, true); at += 4;
+ dv.setUint32(at, this.minor_version, true); at += 4;
+ dv.setUint32(at, this.size, true); at += 4;
+ },
+ buffer_size: function()
+ {
+ return 16;
+ },
+}
+
+function SpiceLinkMess(a, at)
+{
+ this.connection_id = 0;
+ this.channel_type = 0;
+ this.channel_id = 0;
+ this.common_caps = [];
+ this.channel_caps = [];
+
+ if (a !== undefined)
+ this.from_buffer(a, at);
+}
+
+SpiceLinkMess.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var i;
+ var orig_at = at;
+ var dv = new SpiceDataView(a);
+ this.connection_id = dv.getUint32(at, true); at += 4;
+ this.channel_type = dv.getUint8(at, true); at++;
+ this.channel_id = dv.getUint8(at, true); at++;
+ var num_common_caps = dv.getUint32(at, true); at += 4;
+ var num_channel_caps = dv.getUint32(at, true); at += 4;
+ var caps_offset = dv.getUint32(at, true); at += 4;
+
+ at = orig_at + caps_offset;
+ this.common_caps = [];
+ for (i = 0; i < num_common_caps; i++)
+ {
+ this.common_caps.unshift(dv.getUint32(at, true)); at += 4;
+ }
+
+ this.channel_caps = [];
+ for (i = 0; i < num_channel_caps; i++)
+ {
+ this.channel_caps.unshift(dv.getUint32(at, true)); at += 4;
+ }
+ },
+
+ to_buffer: function(a, at)
+ {
+ at = at || 0;
+ var orig_at = at;
+ var i;
+ var dv = new SpiceDataView(a);
+ dv.setUint32(at, this.connection_id, true); at += 4;
+ dv.setUint8(at, this.channel_type, true); at++;
+ dv.setUint8(at, this.channel_id, true); at++;
+ dv.setUint32(at, this.common_caps.length, true); at += 4;
+ dv.setUint32(at, this.channel_caps.length, true); at += 4;
+ dv.setUint32(at, (at - orig_at) + 4, true); at += 4;
+
+ for (i = 0; i < this.common_caps.length; i++)
+ {
+ dv.setUint32(at, this.common_caps[i], true); at += 4;
+ }
+
+ for (i = 0; i < this.channel_caps.length; i++)
+ {
+ dv.setUint32(at, this.channel_caps[i], true); at += 4;
+ }
+ },
+ buffer_size: function()
+ {
+ return 18 + (4 * this.common_caps.length) + (4 * this.channel_caps.length);
+ }
+}
+
+function SpiceLinkReply(a, at)
+{
+ this.error = 0;
+ this.pub_key = undefined;
+ this.common_caps = [];
+ this.channel_caps = [];
+
+ if (a !== undefined)
+ this.from_buffer(a, at);
+}
+
+SpiceLinkReply.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var i;
+ var orig_at = at;
+ var dv = new SpiceDataView(a);
+ this.error = dv.getUint32(at, true); at += 4;
+
+ this.pub_key = create_rsa_from_mb(a, at);
+ at += SPICE_TICKET_PUBKEY_BYTES;
+
+ var num_common_caps = dv.getUint32(at, true); at += 4;
+ var num_channel_caps = dv.getUint32(at, true); at += 4;
+ var caps_offset = dv.getUint32(at, true); at += 4;
+
+ at = orig_at + caps_offset;
+ this.common_caps = [];
+ for (i = 0; i < num_common_caps; i++)
+ {
+ this.common_caps.unshift(dv.getUint32(at, true)); at += 4;
+ }
+
+ this.channel_caps = [];
+ for (i = 0; i < num_channel_caps; i++)
+ {
+ this.channel_caps.unshift(dv.getUint32(at, true)); at += 4;
+ }
+ },
+}
+
+function SpiceLinkAuthTicket(a, at)
+{
+ this.auth_mechanism = 0;
+ this.encrypted_data = undefined;
+}
+
+SpiceLinkAuthTicket.prototype =
+{
+ to_buffer: function(a, at)
+ {
+ at = at || 0;
+ var i;
+ var dv = new SpiceDataView(a);
+ dv.setUint32(at, this.auth_mechanism, true); at += 4;
+ for (i = 0; i < SPICE_TICKET_KEY_PAIR_LENGTH / 8; i++)
+ {
+ if (this.encrypted_data && i < this.encrypted_data.length)
+ dv.setUint8(at, this.encrypted_data[i], true);
+ else
+ dv.setUint8(at, 0, true);
+ at++;
+ }
+ },
+ buffer_size: function()
+ {
+ return 4 + (SPICE_TICKET_KEY_PAIR_LENGTH / 8);
+ }
+}
+
+function SpiceLinkAuthReply(a, at)
+{
+ this.auth_code = 0;
+ if (a !== undefined)
+ this.from_buffer(a, at);
+}
+
+SpiceLinkAuthReply.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.auth_code = dv.getUint32(at, true); at += 4;
+ },
+ buffer_size: function()
+ {
+ return 4;
+ }
+}
+
+function SpiceMiniData(a, at)
+{
+ this.type = 0;
+ this.size = 0;
+ this.data = undefined;
+ if (a !== undefined)
+ this.from_buffer(a, at);
+}
+
+SpiceMiniData.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var i;
+ var dv = new SpiceDataView(a);
+ this.type = dv.getUint16(at, true); at += 2;
+ this.size = dv.getUint32(at, true); at += 4;
+ if (a.byteLength > at)
+ {
+ this.data = a.slice(at);
+ at += this.data.byteLength;
+ }
+ },
+ to_buffer : function(a, at)
+ {
+ at = at || 0;
+ var i;
+ var dv = new SpiceDataView(a);
+ dv.setUint16(at, this.type, true); at += 2;
+ dv.setUint32(at, this.data ? this.data.byteLength : 0, true); at += 4;
+ if (this.data && this.data.byteLength > 0)
+ {
+ var u8arr = new Uint8Array(this.data);
+ for (i = 0; i < u8arr.length; i++, at++)
+ dv.setUint8(at, u8arr[i], true);
+ }
+ },
+ build_msg : function(in_type, extra)
+ {
+ this.type = in_type;
+ this.size = extra.buffer_size();
+ this.data = new ArrayBuffer(this.size);
+ extra.to_buffer(this.data);
+ },
+ buffer_size: function()
+ {
+ if (this.data)
+ return 6 + this.data.byteLength;
+ else
+ return 6;
+ },
+}
+
+function SpiceMsgChannels(a, at)
+{
+ this.num_of_channels = 0;
+ this.channels = [];
+ if (a !== undefined)
+ this.from_buffer(a, at);
+}
+
+SpiceMsgChannels.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var i;
+ var dv = new SpiceDataView(a);
+ this.num_of_channels = dv.getUint32(at, true); at += 4;
+ for (i = 0; i < this.num_of_channels; i++)
+ {
+ var chan = new SpiceChannelId();
+ at = chan.from_dv(dv, at, a);
+ this.channels.push(chan);
+ }
+ },
+}
+
+function SpiceMsgMainInit(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgMainInit.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.session_id = dv.getUint32(at, true); at += 4;
+ this.display_channels_hint = dv.getUint32(at, true); at += 4;
+ this.supported_mouse_modes = dv.getUint32(at, true); at += 4;
+ this.current_mouse_mode = dv.getUint32(at, true); at += 4;
+ this.agent_connected = dv.getUint32(at, true); at += 4;
+ this.agent_tokens = dv.getUint32(at, true); at += 4;
+ this.multi_media_time = dv.getUint32(at, true); at += 4;
+ this.ram_hint = dv.getUint32(at, true); at += 4;
+ },
+}
+
+function SpiceMsgMainMouseMode(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgMainMouseMode.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.supported_modes = dv.getUint16(at, true); at += 2;
+ this.current_mode = dv.getUint16(at, true); at += 2;
+ },
+}
+
+function SpiceMsgSetAck(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgSetAck.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.generation = dv.getUint32(at, true); at += 4;
+ this.window = dv.getUint32(at, true); at += 4;
+ },
+}
+
+function SpiceMsgcAckSync(ack)
+{
+ this.generation = ack.generation;
+}
+
+SpiceMsgcAckSync.prototype =
+{
+ to_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ dv.setUint32(at, this.generation, true); at += 4;
+ },
+ buffer_size: function()
+ {
+ return 4;
+ }
+}
+
+function SpiceMsgcMainMouseModeRequest(mode)
+{
+ this.mode = mode;
+}
+
+SpiceMsgcMainMouseModeRequest.prototype =
+{
+ to_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ dv.setUint16(at, this.mode, true); at += 2;
+ },
+ buffer_size: function()
+ {
+ return 2;
+ }
+}
+
+function SpiceMsgNotify(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgNotify.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var i;
+ var dv = new SpiceDataView(a);
+ this.time_stamp = [];
+ this.time_stamp[0] = dv.getUint32(at, true); at += 4;
+ this.time_stamp[1] = dv.getUint32(at, true); at += 4;
+ this.severity = dv.getUint32(at, true); at += 4;
+ this.visibility = dv.getUint32(at, true); at += 4;
+ this.what = dv.getUint32(at, true); at += 4;
+ this.message_len = dv.getUint32(at, true); at += 4;
+ this.message = "";
+ for (i = 0; i < this.message_len; i++)
+ {
+ var c = dv.getUint8(at, true); at++;
+ this.message += String.fromCharCode(c);
+ }
+ },
+}
+
+function SpiceMsgcDisplayInit()
+{
+ this.pixmap_cache_id = 1;
+ this.glz_dictionary_id = 0;
+ this.pixmap_cache_size = 10 * 1024 * 1024;
+ this.glz_dictionary_window_size = 0;
+}
+
+SpiceMsgcDisplayInit.prototype =
+{
+ to_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ dv.setUint8(at, this.pixmap_cache_id, true); at++;
+ dv.setUint32(at, 0, true); at += 4;
+ dv.setUint32(at, this.pixmap_cache_size, true); at += 4;
+ dv.setUint8(at, this.glz_dictionary_id, true); at++;
+ dv.setUint32(at, this.glz_dictionary_window_size, true); at += 4;
+ },
+ buffer_size: function()
+ {
+ return 14;
+ }
+}
+
+function SpiceMsgDisplayBase()
+{
+}
+
+SpiceMsgDisplayBase.prototype =
+{
+ from_dv : function(dv, at, mb)
+ {
+ this.surface_id = dv.getUint32(at, true); at += 4;
+ this.box = new SpiceRect;
+ at = this.box.from_dv(dv, at, mb);
+ this.clip = new SpiceClip;
+ return this.clip.from_dv(dv, at, mb);
+ },
+}
+
+function SpiceMsgDisplayDrawCopy(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgDisplayDrawCopy.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.base = new SpiceMsgDisplayBase;
+ at = this.base.from_dv(dv, at, a);
+ this.data = new SpiceCopy;
+ return this.data.from_dv(dv, at, a);
+ },
+}
+
+function SpiceMsgDisplayDrawFill(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgDisplayDrawFill.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.base = new SpiceMsgDisplayBase;
+ at = this.base.from_dv(dv, at, a);
+ this.data = new SpiceFill;
+ return this.data.from_dv(dv, at, a);
+ },
+}
+
+function SpiceMsgDisplayCopyBits(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgDisplayCopyBits.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.base = new SpiceMsgDisplayBase;
+ at = this.base.from_dv(dv, at, a);
+ this.src_pos = new SpicePoint;
+ return this.src_pos.from_dv(dv, at, a);
+ },
+}
+
+
+function SpiceMsgSurfaceCreate(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgSurfaceCreate.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.surface = new SpiceSurface;
+ return this.surface.from_dv(dv, at, a);
+ },
+}
+
+function SpiceMsgSurfaceDestroy(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgSurfaceDestroy.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.surface_id = dv.getUint32(at, true); at += 4;
+ },
+}
+
+function SpiceMsgInputsInit(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgInputsInit.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.keyboard_modifiers = dv.getUint16(at, true); at += 2;
+ return at;
+ },
+}
+
+function SpiceMsgInputsKeyModifiers(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgInputsKeyModifiers.prototype =
+{
+ from_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.keyboard_modifiers = dv.getUint16(at, true); at += 2;
+ return at;
+ },
+}
+
+function SpiceMsgCursorInit(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgCursorInit.prototype =
+{
+ from_buffer: function(a, at, mb)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.position = new SpicePoint16;
+ at = this.position.from_dv(dv, at, mb);
+ this.trail_length = dv.getUint16(at, true); at += 2;
+ this.trail_frequency = dv.getUint16(at, true); at += 2;
+ this.visible = dv.getUint8(at, true); at ++;
+ this.cursor = new SpiceCursor;
+ return this.cursor.from_dv(dv, at, a);
+ },
+}
+
+
+function SpiceMsgCursorSet(a, at)
+{
+ this.from_buffer(a, at);
+}
+
+SpiceMsgCursorSet.prototype =
+{
+ from_buffer: function(a, at, mb)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ this.position = new SpicePoint16;
+ at = this.position.from_dv(dv, at, mb);
+ this.visible = dv.getUint8(at, true); at ++;
+ this.cursor = new SpiceCursor;
+ return this.cursor.from_dv(dv, at, a);
+ },
+}
+
+
+function SpiceMsgcMousePosition(sc, e)
+{
+ // FIXME - figure out how to correctly compute display_id
+ this.display_id = 0;
+ this.buttons_state = sc.buttons_state;
+ if (e)
+ {
+ this.x = e.clientX - sc.display.surfaces[sc.display.primary_surface].canvas.offsetLeft;
+ this.y = e.clientY - sc.display.surfaces[sc.display.primary_surface].canvas.offsetTop;
+ sc.mousex = this.x;
+ sc.mousey = this.y;
+ }
+ else
+ {
+ this.x = this.y = this.buttons_state = 0;
+ }
+}
+
+SpiceMsgcMousePosition.prototype =
+{
+ to_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ dv.setUint32(at, this.x, true); at += 4;
+ dv.setUint32(at, this.y, true); at += 4;
+ dv.setUint16(at, this.buttons_state, true); at += 2;
+ dv.setUint8(at, this.display_id, true); at += 1;
+ return at;
+ },
+ buffer_size: function()
+ {
+ return 11;
+ }
+}
+
+function SpiceMsgcMouseMotion(sc, e)
+{
+ // FIXME - figure out how to correctly compute display_id
+ this.display_id = 0;
+ this.buttons_state = sc.buttons_state;
+ if (e)
+ {
+ this.x = e.clientX - sc.display.surfaces[sc.display.primary_surface].canvas.offsetLeft;
+ this.y = e.clientY - sc.display.surfaces[sc.display.primary_surface].canvas.offsetTop;
+
+ if (sc.mousex !== undefined)
+ {
+ this.x -= sc.mousex;
+ this.y -= sc.mousey;
+ }
+ sc.mousex = e.clientX - sc.display.surfaces[sc.display.primary_surface].canvas.offsetLeft;
+ sc.mousey = e.clientY - sc.display.surfaces[sc.display.primary_surface].canvas.offsetTop;
+ }
+ else
+ {
+ this.x = this.y = this.buttons_state = 0;
+ }
+}
+
+/* Use the same functions as for MousePosition */
+SpiceMsgcMouseMotion.prototype.to_buffer = SpiceMsgcMousePosition.prototype.to_buffer;
+SpiceMsgcMouseMotion.prototype.buffer_size = SpiceMsgcMousePosition.prototype.buffer_size;
+
+function SpiceMsgcMousePress(sc, e)
+{
+ if (e)
+ {
+ this.button = e.button + 1;
+ this.buttons_state = 1 << e.button;
+ sc.buttons_state = this.buttons_state;
+ }
+ else
+ {
+ this.button = SPICE_MOUSE_BUTTON_LEFT;
+ this.buttons_state = SPICE_MOUSE_BUTTON_MASK_LEFT;
+ }
+}
+
+SpiceMsgcMousePress.prototype =
+{
+ to_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ dv.setUint8(at, this.button, true); at ++;
+ dv.setUint16(at, this.buttons_state, true); at += 2;
+ return at;
+ },
+ buffer_size: function()
+ {
+ return 3;
+ }
+}
+
+function SpiceMsgcMouseRelease(sc, e)
+{
+ if (e)
+ {
+ this.button = e.button + 1;
+ this.buttons_state = 0;
+ sc.buttons_state = this.buttons_state;
+ }
+ else
+ {
+ this.button = SPICE_MOUSE_BUTTON_LEFT;
+ this.buttons_state = 0;
+ }
+}
+
+/* Use the same functions as for MousePress */
+SpiceMsgcMouseRelease.prototype.to_buffer = SpiceMsgcMousePress.prototype.to_buffer;
+SpiceMsgcMouseRelease.prototype.buffer_size = SpiceMsgcMousePress.prototype.buffer_size;
+
+
+function SpiceMsgcKeyDown(e)
+{
+ if (e)
+ {
+ this.code = keycode_to_start_scan(e.keyCode);
+ }
+ else
+ {
+ this.code = 0;
+ }
+}
+
+SpiceMsgcKeyDown.prototype =
+{
+ to_buffer: function(a, at)
+ {
+ at = at || 0;
+ var dv = new SpiceDataView(a);
+ dv.setUint32(at, this.code, true); at += 4;
+ return at;
+ },
+ buffer_size: function()
+ {
+ return 4;
+ }
+}
+
+function SpiceMsgcKeyUp(e)
+{
+ if (e)
+ {
+ this.code = keycode_to_end_scan(e.keyCode);
+ }
+ else
+ {
+ this.code = 0;
+ }
+}
+
+/* Use the same functions as for KeyDown */
+SpiceMsgcKeyUp.prototype.to_buffer = SpiceMsgcKeyDown.prototype.to_buffer;
+SpiceMsgcKeyUp.prototype.buffer_size = SpiceMsgcKeyDown.prototype.buffer_size;