Files
socket.io/lib/parser.js

162 lines
2.8 KiB
JavaScript

/**
* Packet types.
*/
var packets = exports.packets = {
open: 0 // non-ws
, close: 1 // non-ws
, ping: 2
, pong: 3
, message: 4
, error: 5
, noop: 6
};
var packetslist = Object.keys(packets);
/**
* Premade error packet.
*/
var err = { type: 'error', data: 'parser error' }
/**
* Encodes a packet.
*
* <packet type id> [ `:` <data> ]
*
* Example:
*
* 5:hello world
* 3
* 4
*
* @api private
*/
exports.encodePacket = function (packet) {
var encoded = packets[packet.type]
// data fragment is optional
if ('undefined' != typeof packet.data) {
encoded += ':' + packet.data;
}
return '' + encoded;
};
/**
* Decodes a packet.
*
* @return {Object} with `type` and `data` (if any)
* @api private
*/
exports.decodePacket = function (data) {
if (':' === data[1]) {
var pieces = data.match(/([0-9]+):(.*)?/)
if (!pieces) {
// parser error - ignoring packet
return err;
}
var type = pieces[1]
, data = pieces[2]
if (!packetslist[type]) {
// parser error - ignoring packet
return err;
}
return { type: packetslist[type], data: undefined === data ? '' : data };
} else {
if (Number(data) != data || !packetslist[data]) return err;
return { type: packetslist[data] };
}
};
/**
* Encodes multiple messages (payload).
*
* <length>:data
*
* Example:
*
* 11:hello world2:hi
*
* @param {Array} packets
* @api private
*/
exports.encodePayload = function (packets) {
if (!packets.length) {
return '0:';
}
var encoded = ''
, message
for (var i = 0, l = packets.length; i < l; i++) {
message = exports.encodePacket(packets[i]);
encoded += message.length + ':' + message;
}
return encoded;
};
/*
* Decodes data when a payload is maybe expected.
*
* @param {String} data
* @return {Array} packets
* @api public
*/
exports.decodePayload = function (data) {
var packets = []
, length = ''
, n, msg, packet
for (var i = 0, l = data.length; i < l; i++) {
var chr = data[i]
if (':' != chr) {
length += chr;
} else {
if ('' == length || (length != (n = Number(length)))) {
// parser error - ignoring payload
return [err];
}
msg = data.substr(i + 1, n);
if (length != msg.length) {
// parser error - ignoring payload
return [err];
}
packet = exports.decodePacket(msg);
if (err.type == packet.type && err.data == packet.data) {
// parser error in individual packet - ignoring payload
return [err];
}
packets.push(msg);
// advance cursor
i += n;
length = ''
}
}
if (length != '') {
// parser error - ignoring payload
return [err];
}
return packets;
};