/** * Module dependencies. */ var util = require('./util') /** * Packet types. */ var packets = exports.packets = { open: 0 // non-ws , close: 1 // non-ws , ping: 2 , pong: 3 , message: 4 , upgrade: 5 , noop: 6 }; var packetslist = util.keys(packets); /** * Premade error packet. */ var err = { type: 'error', data: 'parser error' } /** * Encodes a packet. * * [ `:` ] * * 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 += String(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). * * :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.charAt(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; };