Files
socket.io/lib/parser.js
Vladimir Dronnikov 01260064cf fixed encoder
2012-01-16 12:21:41 -05:00

155 lines
2.6 KiB
JavaScript

/**
* Packet types.
*/
var packets = exports.packets = {
open: 0 // non-ws
, close: 1 // non-ws
, ping: 2
, pong: 3
, message: 4
, error: 5
, upgrade: 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 !== packet.data) {
encoded += packet.data;
}
return '' + encoded;
};
/**
* Decodes a packet.
*
* @return {Object} with `type` and `data` (if any)
* @api private
*/
exports.decodePacket = function (data) {
var type = data.charAt(0)
if (Number(type) != type || !packetslist[type]) return err;
if (data.length > 1) {
return { type: packetslist[type], data: data.substring(1) };
} else {
return { type: packetslist[type] };
}
};
/**
* 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) {
if (data == '') {
// parser error - ignoring payload
return [err];
}
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];
}
if (msg.length) {
packet = exports.decodePacket(msg);
if (err.type == packet.type && err.data == packet.data) {
// parser error in individual packet - ignoring payload
return [err];
}
packets.push(packet);
}
// advance cursor
i += n;
length = ''
}
}
if (length != '') {
// parser error - ignoring payload
return [err];
}
return packets;
};