spice-html5-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data/COPYING +674 -0
  2. data/COPYING.LESSER +165 -0
  3. data/LICENSE.txt +15 -0
  4. data/README.md +35 -0
  5. data/lib/spice-html5-rails/version.rb +7 -0
  6. data/lib/spice-html5-rails.rb +10 -0
  7. data/vendor/assets/javascripts/spice-html5.js +25 -0
  8. data/vendor/assets/javascripts/spiceHTML5/atKeynames.js +183 -0
  9. data/vendor/assets/javascripts/spiceHTML5/bitmap.js +51 -0
  10. data/vendor/assets/javascripts/spiceHTML5/cursor.js +92 -0
  11. data/vendor/assets/javascripts/spiceHTML5/display.js +806 -0
  12. data/vendor/assets/javascripts/spiceHTML5/enums.js +282 -0
  13. data/vendor/assets/javascripts/spiceHTML5/inputs.js +271 -0
  14. data/vendor/assets/javascripts/spiceHTML5/lz.js +166 -0
  15. data/vendor/assets/javascripts/spiceHTML5/main.js +177 -0
  16. data/vendor/assets/javascripts/spiceHTML5/png.js +256 -0
  17. data/vendor/assets/javascripts/spiceHTML5/quic.js +1335 -0
  18. data/vendor/assets/javascripts/spiceHTML5/spiceconn.js +455 -0
  19. data/vendor/assets/javascripts/spiceHTML5/spicedataview.js +96 -0
  20. data/vendor/assets/javascripts/spiceHTML5/spicemsg.js +883 -0
  21. data/vendor/assets/javascripts/spiceHTML5/spicetype.js +480 -0
  22. data/vendor/assets/javascripts/spiceHTML5/thirdparty/jsbn.js +589 -0
  23. data/vendor/assets/javascripts/spiceHTML5/thirdparty/prng4.js +79 -0
  24. data/vendor/assets/javascripts/spiceHTML5/thirdparty/rng.js +102 -0
  25. data/vendor/assets/javascripts/spiceHTML5/thirdparty/rsa.js +146 -0
  26. data/vendor/assets/javascripts/spiceHTML5/thirdparty/sha1.js +346 -0
  27. data/vendor/assets/javascripts/spiceHTML5/ticket.js +250 -0
  28. data/vendor/assets/javascripts/spiceHTML5/utils.js +261 -0
  29. data/vendor/assets/javascripts/spiceHTML5/wire.js +123 -0
  30. metadata +108 -0
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com>
4
+
5
+ This file is part of spice-html5.
6
+
7
+ spice-html5 is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ spice-html5 is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with spice-html5. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+ var SHA_DIGEST_LENGTH = 20;
22
+
23
+ /*----------------------------------------------------------------------------
24
+ ** General ticket RSA encryption functions - just good enough to
25
+ ** support what we need to send back an encrypted ticket.
26
+ **--------------------------------------------------------------------------*/
27
+
28
+
29
+ /*----------------------------------------------------------------------------
30
+ ** OAEP padding functions. Inspired by the OpenSSL implementation.
31
+ **--------------------------------------------------------------------------*/
32
+ function MGF1(mask, seed)
33
+ {
34
+ var i, j, outlen;
35
+ for (i = 0, outlen = 0; outlen < mask.length; i++)
36
+ {
37
+ var combo_buf = new String;
38
+
39
+ for (j = 0; j < seed.length; j++)
40
+ combo_buf += String.fromCharCode(seed[j]);
41
+ combo_buf += String.fromCharCode((i >> 24) & 255);
42
+ combo_buf += String.fromCharCode((i >> 16) & 255);
43
+ combo_buf += String.fromCharCode((i >> 8) & 255);
44
+ combo_buf += String.fromCharCode((i) & 255);
45
+
46
+ var combo_hash = rstr_sha1(combo_buf);
47
+ for (j = 0; j < combo_hash.length && outlen < mask.length; j++, outlen++)
48
+ {
49
+ mask[outlen] = combo_hash.charCodeAt(j);
50
+ }
51
+ }
52
+ }
53
+
54
+
55
+ function RSA_padding_add_PKCS1_OAEP(tolen, from, param)
56
+ {
57
+ var seed = new Array(SHA_DIGEST_LENGTH);
58
+ var rand = new SecureRandom();
59
+ rand.nextBytes(seed);
60
+
61
+ var dblen = tolen - 1 - seed.length;
62
+ var db = new Array(dblen);
63
+ var padlen = dblen - from.length - 1;
64
+ var i;
65
+
66
+ if (param === undefined)
67
+ param = "";
68
+
69
+ if (padlen < SHA_DIGEST_LENGTH)
70
+ {
71
+ console.log("Error - data too large for key size.");
72
+ return null;
73
+ }
74
+
75
+ for (i = 0; i < padlen; i++)
76
+ db[i] = 0;
77
+
78
+ var param_hash = rstr_sha1(param);
79
+ for (i = 0; i < param_hash.length; i++)
80
+ db[i] = param_hash.charCodeAt(i);
81
+
82
+ db[padlen] = 1;
83
+ for (i = 0; i < from.length; i++)
84
+ db[i + padlen + 1] = from.charCodeAt(i);
85
+
86
+ var dbmask = new Array(dblen);
87
+ if (MGF1(dbmask, seed) < 0)
88
+ return null;
89
+
90
+ for (i = 0; i < dbmask.length; i++)
91
+ db[i] ^= dbmask[i];
92
+
93
+
94
+ var seedmask = Array(SHA_DIGEST_LENGTH);
95
+ if (MGF1(seedmask, db) < 0)
96
+ return null;
97
+
98
+ for (i = 0; i < seedmask.length; i++)
99
+ seed[i] ^= seedmask[i];
100
+
101
+ var ret = new String;
102
+ ret += String.fromCharCode(0);
103
+ for (i = 0; i < seed.length; i++)
104
+ ret += String.fromCharCode(seed[i]);
105
+ for (i = 0; i < db.length; i++)
106
+ ret += String.fromCharCode(db[i]);
107
+ return ret;
108
+ }
109
+
110
+
111
+ function asn_get_length(u8, at)
112
+ {
113
+ var len = u8[at++];
114
+ if (len > 0x80)
115
+ {
116
+ if (len != 0x81)
117
+ {
118
+ console.log("Error: we lazily don't support keys bigger than 255 bytes. It'd be easy to fix.");
119
+ return null;
120
+ }
121
+ len = u8[at++];
122
+ }
123
+
124
+ return [ at, len];
125
+ }
126
+
127
+ function find_sequence(u8, at)
128
+ {
129
+ var lenblock;
130
+ at = at || 0;
131
+ if (u8[at++] != 0x30)
132
+ {
133
+ console.log("Error: public key should start with a sequence flag.");
134
+ return null;
135
+ }
136
+
137
+ lenblock = asn_get_length(u8, at);
138
+ if (! lenblock)
139
+ return null;
140
+ return lenblock;
141
+ }
142
+
143
+ /*----------------------------------------------------------------------------
144
+ ** Extract an RSA key from a memory buffer
145
+ **--------------------------------------------------------------------------*/
146
+ function create_rsa_from_mb(mb, at)
147
+ {
148
+ var u8 = new Uint8Array(mb);
149
+ var lenblock;
150
+ var seq;
151
+ var ba;
152
+ var i;
153
+ var ret;
154
+
155
+ /* We have a sequence which contains a sequence followed by a bit string */
156
+ seq = find_sequence(u8, at);
157
+ if (! seq)
158
+ return null;
159
+
160
+ at = seq[0];
161
+ seq = find_sequence(u8, at);
162
+ if (! seq)
163
+ return null;
164
+
165
+ /* Skip over the contained sequence */
166
+ at = seq[0] + seq[1];
167
+ if (u8[at++] != 0x3)
168
+ {
169
+ console.log("Error: expecting bit string next.");
170
+ return null;
171
+ }
172
+
173
+ /* Get the bit string, which is *itself* a sequence. Having fun yet? */
174
+ lenblock = asn_get_length(u8, at);
175
+ if (! lenblock)
176
+ return null;
177
+
178
+ at = lenblock[0];
179
+ if (u8[at] != 0 && u8[at + 1] != 0x30)
180
+ {
181
+ console.log("Error: unexpected values in bit string.");
182
+ return null;
183
+ }
184
+
185
+ /* Okay, now we have a sequence of two binary values, we hope. */
186
+ seq = find_sequence(u8, at + 1);
187
+ if (! seq)
188
+ return null;
189
+
190
+ at = seq[0];
191
+ if (u8[at++] != 0x02)
192
+ {
193
+ console.log("Error: expecting integer n next.");
194
+ return null;
195
+ }
196
+ lenblock = asn_get_length(u8, at);
197
+ if (! lenblock)
198
+ return null;
199
+ at = lenblock[0];
200
+
201
+ ba = new Array(lenblock[1]);
202
+ for (i = 0; i < lenblock[1]; i++)
203
+ ba[i] = u8[at + i];
204
+
205
+ ret = new RSAKey();
206
+ ret.n = new BigInteger(ba);
207
+
208
+ at += lenblock[1];
209
+
210
+ if (u8[at++] != 0x02)
211
+ {
212
+ console.log("Error: expecting integer e next.");
213
+ return null;
214
+ }
215
+ lenblock = asn_get_length(u8, at);
216
+ if (! lenblock)
217
+ return null;
218
+ at = lenblock[0];
219
+
220
+ ret.e = u8[at++];
221
+ for (i = 1; i < lenblock[1]; i++)
222
+ {
223
+ ret.e <<= 8;
224
+ ret.e |= u8[at++];
225
+ }
226
+
227
+ return ret;
228
+ }
229
+
230
+ function rsa_encrypt(rsa, str)
231
+ {
232
+ var i;
233
+ var ret = [];
234
+ var oaep = RSA_padding_add_PKCS1_OAEP((rsa.n.bitLength()+7)>>3, str);
235
+ if (! oaep)
236
+ return null;
237
+
238
+ var ba = new Array(oaep.length);
239
+
240
+ for (i = 0; i < oaep.length; i++)
241
+ ba[i] = oaep.charCodeAt(i);
242
+ var bigint = new BigInteger(ba);
243
+ var enc = rsa.doPublic(bigint);
244
+ var h = enc.toString(16);
245
+ if ((h.length & 1) != 0)
246
+ h = "0" + h;
247
+ for (i = 0; i < h.length; i += 2)
248
+ ret[i / 2] = parseInt(h.substring(i, i + 2), 16);
249
+ return ret;
250
+ }
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com>
4
+
5
+ This file is part of spice-html5.
6
+
7
+ spice-html5 is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ spice-html5 is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with spice-html5. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+ /*----------------------------------------------------------------------------
22
+ ** Utility settings and functions for Spice
23
+ **--------------------------------------------------------------------------*/
24
+ var DEBUG = 0;
25
+ var DUMP_DRAWS = false;
26
+ var DUMP_CANVASES = false;
27
+
28
+
29
+ /*----------------------------------------------------------------------------
30
+ ** combine_array_buffers
31
+ ** Combine two array buffers.
32
+ ** FIXME - this can't be optimal. See wire.js about eliminating the need.
33
+ **--------------------------------------------------------------------------*/
34
+ function combine_array_buffers(a1, a2)
35
+ {
36
+ var in1 = new Uint8Array(a1);
37
+ var in2 = new Uint8Array(a2);
38
+ var ret = new ArrayBuffer(a1.byteLength + a2.byteLength);
39
+ var out = new Uint8Array(ret);
40
+ var o = 0;
41
+ var i;
42
+ for (i = 0; i < in1.length; i++)
43
+ out[o++] = in1[i];
44
+ for (i = 0; i < in2.length; i++)
45
+ out[o++] = in2[i];
46
+
47
+ return ret;
48
+ }
49
+
50
+ /*----------------------------------------------------------------------------
51
+ ** hexdump_buffer
52
+ **--------------------------------------------------------------------------*/
53
+ function hexdump_buffer(a)
54
+ {
55
+ var mg = new Uint8Array(a);
56
+ var hex = "";
57
+ var str = "";
58
+ var last_zeros = 0;
59
+ for (var i = 0; i < mg.length; i++)
60
+ {
61
+ var h = Number(mg[i]).toString(16);
62
+ if (h.length == 1)
63
+ hex += "0";
64
+ hex += h + " ";
65
+
66
+ str += String.fromCharCode(mg[i]);
67
+
68
+ if ((i % 16 == 15) || (i == (mg.length - 1)))
69
+ {
70
+ while (i % 16 != 15)
71
+ {
72
+ hex += " ";
73
+ i++;
74
+ }
75
+
76
+ if (last_zeros == 0)
77
+ console.log(hex + " | " + str);
78
+
79
+ if (hex == "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ")
80
+ {
81
+ if (last_zeros == 1)
82
+ {
83
+ console.log(".");
84
+ last_zeros++;
85
+ }
86
+ else if (last_zeros == 0)
87
+ last_zeros++;
88
+ }
89
+ else
90
+ last_zeros = 0;
91
+
92
+ hex = str = "";
93
+ }
94
+ }
95
+ }
96
+
97
+ /*----------------------------------------------------------------------------
98
+ ** Converting keycodes to AT scancodes is very hard.
99
+ ** luckly there are some resources on the web and in the Xorg driver that help
100
+ ** us figure out what browser depenend keycodes match to what scancodes.
101
+ **
102
+ ** This will most likely not work for non US keyboard and browsers other than
103
+ ** modern Chrome and FireFox.
104
+ **--------------------------------------------------------------------------*/
105
+ var common_scanmap = [];
106
+ common_scanmap['Q'.charCodeAt(0)] = KEY_Q;
107
+ common_scanmap['W'.charCodeAt(0)] = KEY_W;
108
+ common_scanmap['E'.charCodeAt(0)] = KEY_E;
109
+ common_scanmap['R'.charCodeAt(0)] = KEY_R;
110
+ common_scanmap['T'.charCodeAt(0)] = KEY_T;
111
+ common_scanmap['Y'.charCodeAt(0)] = KEY_Y;
112
+ common_scanmap['U'.charCodeAt(0)] = KEY_U;
113
+ common_scanmap['I'.charCodeAt(0)] = KEY_I;
114
+ common_scanmap['O'.charCodeAt(0)] = KEY_O;
115
+ common_scanmap['P'.charCodeAt(0)] = KEY_P;
116
+ common_scanmap['A'.charCodeAt(0)] = KEY_A;
117
+ common_scanmap['S'.charCodeAt(0)] = KEY_S;
118
+ common_scanmap['D'.charCodeAt(0)] = KEY_D;
119
+ common_scanmap['F'.charCodeAt(0)] = KEY_F;
120
+ common_scanmap['G'.charCodeAt(0)] = KEY_G;
121
+ common_scanmap['H'.charCodeAt(0)] = KEY_H;
122
+ common_scanmap['J'.charCodeAt(0)] = KEY_J;
123
+ common_scanmap['K'.charCodeAt(0)] = KEY_K;
124
+ common_scanmap['L'.charCodeAt(0)] = KEY_L;
125
+ common_scanmap['Z'.charCodeAt(0)] = KEY_Z;
126
+ common_scanmap['X'.charCodeAt(0)] = KEY_X;
127
+ common_scanmap['C'.charCodeAt(0)] = KEY_C;
128
+ common_scanmap['V'.charCodeAt(0)] = KEY_V;
129
+ common_scanmap['B'.charCodeAt(0)] = KEY_B;
130
+ common_scanmap['N'.charCodeAt(0)] = KEY_N;
131
+ common_scanmap['M'.charCodeAt(0)] = KEY_M;
132
+ common_scanmap[' '.charCodeAt(0)] = KEY_Space;
133
+ common_scanmap[13] = KEY_Enter;
134
+ common_scanmap[27] = KEY_Escape;
135
+ common_scanmap[8] = KEY_BackSpace;
136
+ common_scanmap[9] = KEY_Tab;
137
+ common_scanmap[16] = KEY_ShiftL;
138
+ common_scanmap[17] = KEY_LCtrl;
139
+ common_scanmap[18] = KEY_Alt;
140
+ common_scanmap[20] = KEY_CapsLock;
141
+ common_scanmap[144] = KEY_NumLock;
142
+ common_scanmap[112] = KEY_F1;
143
+ common_scanmap[113] = KEY_F2;
144
+ common_scanmap[114] = KEY_F3;
145
+ common_scanmap[115] = KEY_F4;
146
+ common_scanmap[116] = KEY_F5;
147
+ common_scanmap[117] = KEY_F6;
148
+ common_scanmap[118] = KEY_F7;
149
+ common_scanmap[119] = KEY_F8;
150
+ common_scanmap[120] = KEY_F9;
151
+ common_scanmap[121] = KEY_F10;
152
+ common_scanmap[122] = KEY_F11;
153
+ common_scanmap[123] = KEY_F12;
154
+
155
+ /* These externded scancodes do not line up with values from atKeynames */
156
+ common_scanmap[42] = 99;
157
+ common_scanmap[19] = 101; // Break
158
+ common_scanmap[111] = 0xE035; // KP_Divide
159
+ common_scanmap[106] = 0xE037; // KP_Multiply
160
+ common_scanmap[36] = 0xE047; // Home
161
+ common_scanmap[38] = 0xE048; // Up
162
+ common_scanmap[33] = 0xE049; // PgUp
163
+ common_scanmap[37] = 0xE04B; // Left
164
+ common_scanmap[39] = 0xE04D; // Right
165
+ common_scanmap[35] = 0xE04F; // End
166
+ common_scanmap[40] = 0xE050; // Down
167
+ common_scanmap[34] = 0xE051; // PgDown
168
+ common_scanmap[45] = 0xE052; // Insert
169
+ common_scanmap[46] = 0xE053; // Delete
170
+ common_scanmap[44] = 0x2A37; // Print
171
+
172
+ /* These are not common between ALL browsers but are between Firefox and DOM3 */
173
+ common_scanmap['1'.charCodeAt(0)] = KEY_1;
174
+ common_scanmap['2'.charCodeAt(0)] = KEY_2;
175
+ common_scanmap['3'.charCodeAt(0)] = KEY_3;
176
+ common_scanmap['4'.charCodeAt(0)] = KEY_4;
177
+ common_scanmap['5'.charCodeAt(0)] = KEY_5;
178
+ common_scanmap['6'.charCodeAt(0)] = KEY_6;
179
+ common_scanmap['7'.charCodeAt(0)] = KEY_7;
180
+ common_scanmap['8'.charCodeAt(0)] = KEY_8;
181
+ common_scanmap['9'.charCodeAt(0)] = KEY_9;
182
+ common_scanmap['0'.charCodeAt(0)] = KEY_0;
183
+ common_scanmap[145] = KEY_ScrollLock;
184
+ common_scanmap[103] = KEY_KP_7;
185
+ common_scanmap[104] = KEY_KP_8;
186
+ common_scanmap[105] = KEY_KP_9;
187
+ common_scanmap[100] = KEY_KP_4;
188
+ common_scanmap[101] = KEY_KP_5;
189
+ common_scanmap[102] = KEY_KP_6;
190
+ common_scanmap[107] = KEY_KP_Plus;
191
+ common_scanmap[97] = KEY_KP_1;
192
+ common_scanmap[98] = KEY_KP_2;
193
+ common_scanmap[99] = KEY_KP_3;
194
+ common_scanmap[96] = KEY_KP_0;
195
+ common_scanmap[110] = KEY_KP_Decimal;
196
+ common_scanmap[191] = KEY_Slash;
197
+ common_scanmap[190] = KEY_Period;
198
+ common_scanmap[188] = KEY_Comma;
199
+ common_scanmap[220] = KEY_BSlash;
200
+ common_scanmap[192] = KEY_Tilde;
201
+ common_scanmap[222] = KEY_Quote;
202
+ common_scanmap[219] = KEY_LBrace;
203
+ common_scanmap[221] = KEY_RBrace;
204
+
205
+ common_scanmap[91] = 0xE05B; //KEY_LMeta
206
+ common_scanmap[92] = 0xE05C; //KEY_RMeta
207
+ common_scanmap[93] = 0xE05D; //KEY_Menu
208
+
209
+ /* Firefox/Mozilla codes */
210
+ var firefox_scanmap = [];
211
+ firefox_scanmap[109] = KEY_Minus;
212
+ firefox_scanmap[61] = KEY_Equal;
213
+ firefox_scanmap[59] = KEY_SemiColon;
214
+
215
+ /* DOM3 codes */
216
+ var DOM_scanmap = [];
217
+ DOM_scanmap[189] = KEY_Minus;
218
+ DOM_scanmap[187] = KEY_Equal;
219
+ DOM_scanmap[186] = KEY_SemiColon;
220
+
221
+ function get_scancode(code)
222
+ {
223
+ if (common_scanmap[code] === undefined)
224
+ {
225
+ if (navigator.userAgent.indexOf("Firefox") != -1)
226
+ return firefox_scanmap[code];
227
+ else
228
+ return DOM_scanmap[code];
229
+ }
230
+ else
231
+ return common_scanmap[code];
232
+ }
233
+
234
+ function keycode_to_start_scan(code)
235
+ {
236
+ var scancode = get_scancode(code);
237
+ if (scancode === undefined)
238
+ {
239
+ alert('no map for ' + code);
240
+ return 0;
241
+ }
242
+
243
+ if (scancode < 0x100) {
244
+ return scancode;
245
+ } else {
246
+ return 0xe0 | ((scancode - 0x100) << 8);
247
+ }
248
+ }
249
+
250
+ function keycode_to_end_scan(code)
251
+ {
252
+ var scancode = get_scancode(code);
253
+ if (scancode === undefined)
254
+ return 0;
255
+
256
+ if (scancode < 0x100) {
257
+ return scancode | 0x80;
258
+ } else {
259
+ return 0x80e0 | ((scancode - 0x100) << 8);
260
+ }
261
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com>
4
+
5
+ This file is part of spice-html5.
6
+
7
+ spice-html5 is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU Lesser General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ spice-html5 is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Lesser General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public License
18
+ along with spice-html5. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+ /*--------------------------------------------------------------------------------------
22
+ ** SpiceWireReader
23
+ ** This class will receive messages from a WebSocket and relay it to a given
24
+ ** callback. It will optionally save and pass along a header, useful in processing
25
+ ** the mini message format.
26
+ **--------------------------------------------------------------------------------------*/
27
+ function SpiceWireReader(sc, callback)
28
+ {
29
+ this.sc = sc;
30
+ this.callback = callback;
31
+ this.needed = 0;
32
+
33
+ this.buffers = [];
34
+
35
+ this.sc.ws.wire_reader = this;
36
+ this.sc.ws.binaryType = "arraybuffer";
37
+ this.sc.ws.addEventListener('message', wire_blob_catcher);
38
+ }
39
+
40
+ SpiceWireReader.prototype =
41
+ {
42
+
43
+ /*------------------------------------------------------------------------
44
+ ** Process messages coming in from our WebSocket
45
+ **----------------------------------------------------------------------*/
46
+ inbound: function (mb)
47
+ {
48
+ var at;
49
+
50
+ /* Just buffer if we don't need anything yet */
51
+ if (this.needed == 0)
52
+ {
53
+ this.buffers.push(mb);
54
+ return;
55
+ }
56
+
57
+ /* Optimization - if we have just one inbound block, and it's
58
+ suitable for our needs, just use it. */
59
+ if (this.buffers.length == 0 && mb.byteLength >= this.needed)
60
+ {
61
+ if (mb.byteLength > this.needed)
62
+ {
63
+ this.buffers.push(mb.slice(this.needed));
64
+ mb = mb.slice(0, this.needed);
65
+ }
66
+ this.callback.call(this.sc, mb,
67
+ this.saved_msg_header || undefined);
68
+ }
69
+ else
70
+ {
71
+ this.buffers.push(mb);
72
+ }
73
+
74
+
75
+ /* If we have fragments that add up to what we need, combine them */
76
+ /* FIXME - it would be faster to revise the processing code to handle
77
+ ** multiple fragments directly. Essentially, we should be
78
+ ** able to do this without any slice() or combine_array_buffers() calls */
79
+ while (this.buffers.length > 1 && this.buffers[0].byteLength < this.needed)
80
+ {
81
+ var mb1 = this.buffers.shift();
82
+ var mb2 = this.buffers.shift();
83
+
84
+ this.buffers.unshift(combine_array_buffers(mb1, mb2));
85
+ }
86
+
87
+
88
+ while (this.buffers.length > 0 && this.buffers[0].byteLength >= this.needed)
89
+ {
90
+ mb = this.buffers.shift();
91
+ if (mb.byteLength > this.needed)
92
+ {
93
+ this.buffers.unshift(mb.slice(this.needed));
94
+ mb = mb.slice(0, this.needed);
95
+ }
96
+ this.callback.call(this.sc, mb,
97
+ this.saved_msg_header || undefined);
98
+ }
99
+
100
+ },
101
+
102
+ request: function(n)
103
+ {
104
+ this.needed = n;
105
+ },
106
+
107
+ save_header: function(h)
108
+ {
109
+ this.saved_msg_header = h;
110
+ },
111
+
112
+ clear_header: function()
113
+ {
114
+ this.saved_msg_header = undefined;
115
+ },
116
+ }
117
+
118
+ function wire_blob_catcher(e)
119
+ {
120
+ DEBUG > 1 && console.log(">> WebSockets.onmessage");
121
+ DEBUG > 1 && console.log("id " + this.wire_reader.sc.connection_id +"; type " + this.wire_reader.sc.type);
122
+ SpiceWireReader.prototype.inbound.call(this.wire_reader, e.data);
123
+ }