source: trip-planner-front/node_modules/engine.io/lib/parser-v3/index.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 10.8 KB
Line 
1// imported from https://github.com/socketio/engine.io-parser/tree/2.2.x
2
3/**
4 * Module dependencies.
5 */
6
7var utf8 = require('./utf8');
8
9/**
10 * Current protocol version.
11 */
12exports.protocol = 3;
13
14const hasBinary = (packets) => {
15 for (const packet of packets) {
16 if (packet.data instanceof ArrayBuffer || ArrayBuffer.isView(packet.data)) {
17 return true;
18 }
19 }
20 return false;
21}
22
23/**
24 * Packet types.
25 */
26
27var packets = exports.packets = {
28 open: 0 // non-ws
29 , close: 1 // non-ws
30 , ping: 2
31 , pong: 3
32 , message: 4
33 , upgrade: 5
34 , noop: 6
35};
36
37var packetslist = Object.keys(packets);
38
39/**
40 * Premade error packet.
41 */
42
43var err = { type: 'error', data: 'parser error' };
44
45const EMPTY_BUFFER = Buffer.concat([]);
46
47/**
48 * Encodes a packet.
49 *
50 * <packet type id> [ <data> ]
51 *
52 * Example:
53 *
54 * 5hello world
55 * 3
56 * 4
57 *
58 * Binary is encoded in an identical principle
59 *
60 * @api private
61 */
62
63exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
64 if (typeof supportsBinary === 'function') {
65 callback = supportsBinary;
66 supportsBinary = null;
67 }
68
69 if (typeof utf8encode === 'function') {
70 callback = utf8encode;
71 utf8encode = null;
72 }
73
74 if (Buffer.isBuffer(packet.data)) {
75 return encodeBuffer(packet, supportsBinary, callback);
76 } else if (packet.data && (packet.data.buffer || packet.data) instanceof ArrayBuffer) {
77 return encodeBuffer({ type: packet.type, data: arrayBufferToBuffer(packet.data) }, supportsBinary, callback);
78 }
79
80 // Sending data as a utf-8 string
81 var encoded = packets[packet.type];
82
83 // data fragment is optional
84 if (undefined !== packet.data) {
85 encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data);
86 }
87
88 return callback('' + encoded);
89};
90
91/**
92 * Encode Buffer data
93 */
94
95function encodeBuffer(packet, supportsBinary, callback) {
96 if (!supportsBinary) {
97 return exports.encodeBase64Packet(packet, callback);
98 }
99
100 var data = packet.data;
101 var typeBuffer = Buffer.allocUnsafe(1);
102 typeBuffer[0] = packets[packet.type];
103 return callback(Buffer.concat([typeBuffer, data]));
104}
105
106/**
107 * Encodes a packet with binary data in a base64 string
108 *
109 * @param {Object} packet, has `type` and `data`
110 * @return {String} base64 encoded message
111 */
112
113exports.encodeBase64Packet = function(packet, callback){
114 var data = Buffer.isBuffer(packet.data) ? packet.data : arrayBufferToBuffer(packet.data);
115 var message = 'b' + packets[packet.type];
116 message += data.toString('base64');
117 return callback(message);
118};
119
120/**
121 * Decodes a packet. Data also available as an ArrayBuffer if requested.
122 *
123 * @return {Object} with `type` and `data` (if any)
124 * @api private
125 */
126
127exports.decodePacket = function (data, binaryType, utf8decode) {
128 if (data === undefined) {
129 return err;
130 }
131
132 var type;
133
134 // String data
135 if (typeof data === 'string') {
136
137 type = data.charAt(0);
138
139 if (type === 'b') {
140 return exports.decodeBase64Packet(data.substr(1), binaryType);
141 }
142
143 if (utf8decode) {
144 data = tryDecode(data);
145 if (data === false) {
146 return err;
147 }
148 }
149
150 if (Number(type) != type || !packetslist[type]) {
151 return err;
152 }
153
154 if (data.length > 1) {
155 return { type: packetslist[type], data: data.substring(1) };
156 } else {
157 return { type: packetslist[type] };
158 }
159 }
160
161 // Binary data
162 if (binaryType === 'arraybuffer') {
163 // wrap Buffer/ArrayBuffer data into an Uint8Array
164 var intArray = new Uint8Array(data);
165 type = intArray[0];
166 return { type: packetslist[type], data: intArray.buffer.slice(1) };
167 }
168
169 if (data instanceof ArrayBuffer) {
170 data = arrayBufferToBuffer(data);
171 }
172 type = data[0];
173 return { type: packetslist[type], data: data.slice(1) };
174};
175
176function tryDecode(data) {
177 try {
178 data = utf8.decode(data, { strict: false });
179 } catch (e) {
180 return false;
181 }
182 return data;
183}
184
185/**
186 * Decodes a packet encoded in a base64 string.
187 *
188 * @param {String} base64 encoded message
189 * @return {Object} with `type` and `data` (if any)
190 */
191
192exports.decodeBase64Packet = function(msg, binaryType) {
193 var type = packetslist[msg.charAt(0)];
194 var data = Buffer.from(msg.substr(1), 'base64');
195 if (binaryType === 'arraybuffer') {
196 var abv = new Uint8Array(data.length);
197 for (var i = 0; i < abv.length; i++){
198 abv[i] = data[i];
199 }
200 data = abv.buffer;
201 }
202 return { type: type, data: data };
203};
204
205/**
206 * Encodes multiple messages (payload).
207 *
208 * <length>:data
209 *
210 * Example:
211 *
212 * 11:hello world2:hi
213 *
214 * If any contents are binary, they will be encoded as base64 strings. Base64
215 * encoded strings are marked with a b before the length specifier
216 *
217 * @param {Array} packets
218 * @api private
219 */
220
221exports.encodePayload = function (packets, supportsBinary, callback) {
222 if (typeof supportsBinary === 'function') {
223 callback = supportsBinary;
224 supportsBinary = null;
225 }
226
227 if (supportsBinary && hasBinary(packets)) {
228 return exports.encodePayloadAsBinary(packets, callback);
229 }
230
231 if (!packets.length) {
232 return callback('0:');
233 }
234
235 function encodeOne(packet, doneCallback) {
236 exports.encodePacket(packet, supportsBinary, false, function(message) {
237 doneCallback(null, setLengthHeader(message));
238 });
239 }
240
241 map(packets, encodeOne, function(err, results) {
242 return callback(results.join(''));
243 });
244};
245
246function setLengthHeader(message) {
247 return message.length + ':' + message;
248}
249
250/**
251 * Async array map using after
252 */
253
254function map(ary, each, done) {
255 const results = new Array(ary.length);
256 let count = 0;
257
258 for (let i = 0; i < ary.length; i++) {
259 each(ary[i], (error, msg) => {
260 results[i] = msg;
261 if (++count === ary.length) {
262 done(null, results);
263 }
264 });
265 }
266}
267
268/*
269 * Decodes data when a payload is maybe expected. Possible binary contents are
270 * decoded from their base64 representation
271 *
272 * @param {String} data, callback method
273 * @api public
274 */
275
276exports.decodePayload = function (data, binaryType, callback) {
277 if (typeof data !== 'string') {
278 return exports.decodePayloadAsBinary(data, binaryType, callback);
279 }
280
281 if (typeof binaryType === 'function') {
282 callback = binaryType;
283 binaryType = null;
284 }
285
286 if (data === '') {
287 // parser error - ignoring payload
288 return callback(err, 0, 1);
289 }
290
291 var length = '', n, msg, packet;
292
293 for (var i = 0, l = data.length; i < l; i++) {
294 var chr = data.charAt(i);
295
296 if (chr !== ':') {
297 length += chr;
298 continue;
299 }
300
301 if (length === '' || (length != (n = Number(length)))) {
302 // parser error - ignoring payload
303 return callback(err, 0, 1);
304 }
305
306 msg = data.substr(i + 1, n);
307
308 if (length != msg.length) {
309 // parser error - ignoring payload
310 return callback(err, 0, 1);
311 }
312
313 if (msg.length) {
314 packet = exports.decodePacket(msg, binaryType, false);
315
316 if (err.type === packet.type && err.data === packet.data) {
317 // parser error in individual packet - ignoring payload
318 return callback(err, 0, 1);
319 }
320
321 var more = callback(packet, i + n, l);
322 if (false === more) return;
323 }
324
325 // advance cursor
326 i += n;
327 length = '';
328 }
329
330 if (length !== '') {
331 // parser error - ignoring payload
332 return callback(err, 0, 1);
333 }
334
335};
336
337/**
338 *
339 * Converts a buffer to a utf8.js encoded string
340 *
341 * @api private
342 */
343
344function bufferToString(buffer) {
345 var str = '';
346 for (var i = 0, l = buffer.length; i < l; i++) {
347 str += String.fromCharCode(buffer[i]);
348 }
349 return str;
350}
351
352/**
353 *
354 * Converts a utf8.js encoded string to a buffer
355 *
356 * @api private
357 */
358
359function stringToBuffer(string) {
360 var buf = Buffer.allocUnsafe(string.length);
361 for (var i = 0, l = string.length; i < l; i++) {
362 buf.writeUInt8(string.charCodeAt(i), i);
363 }
364 return buf;
365}
366
367/**
368 *
369 * Converts an ArrayBuffer to a Buffer
370 *
371 * @api private
372 */
373
374function arrayBufferToBuffer(data) {
375 // data is either an ArrayBuffer or ArrayBufferView.
376 var length = data.byteLength || data.length;
377 var offset = data.byteOffset || 0;
378
379 return Buffer.from(data.buffer || data, offset, length);
380}
381
382/**
383 * Encodes multiple messages (payload) as binary.
384 *
385 * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
386 * 255><data>
387 *
388 * Example:
389 * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
390 *
391 * @param {Array} packets
392 * @return {Buffer} encoded payload
393 * @api private
394 */
395
396exports.encodePayloadAsBinary = function (packets, callback) {
397 if (!packets.length) {
398 return callback(EMPTY_BUFFER);
399 }
400
401 map(packets, encodeOneBinaryPacket, function(err, results) {
402 return callback(Buffer.concat(results));
403 });
404};
405
406function encodeOneBinaryPacket(p, doneCallback) {
407
408 function onBinaryPacketEncode(packet) {
409
410 var encodingLength = '' + packet.length;
411 var sizeBuffer;
412
413 if (typeof packet === 'string') {
414 sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
415 sizeBuffer[0] = 0; // is a string (not true binary = 0)
416 for (var i = 0; i < encodingLength.length; i++) {
417 sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
418 }
419 sizeBuffer[sizeBuffer.length - 1] = 255;
420 return doneCallback(null, Buffer.concat([sizeBuffer, stringToBuffer(packet)]));
421 }
422
423 sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
424 sizeBuffer[0] = 1; // is binary (true binary = 1)
425 for (var i = 0; i < encodingLength.length; i++) {
426 sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
427 }
428 sizeBuffer[sizeBuffer.length - 1] = 255;
429
430 doneCallback(null, Buffer.concat([sizeBuffer, packet]));
431 }
432
433 exports.encodePacket(p, true, true, onBinaryPacketEncode);
434
435}
436
437
438/*
439 * Decodes data when a payload is maybe expected. Strings are decoded by
440 * interpreting each byte as a key code for entries marked to start with 0. See
441 * description of encodePayloadAsBinary
442
443 * @param {Buffer} data, callback method
444 * @api public
445 */
446
447exports.decodePayloadAsBinary = function (data, binaryType, callback) {
448 if (typeof binaryType === 'function') {
449 callback = binaryType;
450 binaryType = null;
451 }
452
453 var bufferTail = data;
454 var buffers = [];
455 var i;
456
457 while (bufferTail.length > 0) {
458 var strLen = '';
459 var isString = bufferTail[0] === 0;
460 for (i = 1; ; i++) {
461 if (bufferTail[i] === 255) break;
462 // 310 = char length of Number.MAX_VALUE
463 if (strLen.length > 310) {
464 return callback(err, 0, 1);
465 }
466 strLen += '' + bufferTail[i];
467 }
468 bufferTail = bufferTail.slice(strLen.length + 1);
469
470 var msgLength = parseInt(strLen, 10);
471
472 var msg = bufferTail.slice(1, msgLength + 1);
473 if (isString) msg = bufferToString(msg);
474 buffers.push(msg);
475 bufferTail = bufferTail.slice(msgLength + 1);
476 }
477
478 var total = buffers.length;
479 for (i = 0; i < total; i++) {
480 var buffer = buffers[i];
481 callback(exports.decodePacket(buffer, binaryType, true), i, total);
482 }
483};
Note: See TracBrowser for help on using the repository browser.