aboutsummaryrefslogtreecommitdiffhomepage
path: root/node_modules/socket.io-parser/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/socket.io-parser/index.js')
-rw-r--r--node_modules/socket.io-parser/index.js400
1 files changed, 400 insertions, 0 deletions
diff --git a/node_modules/socket.io-parser/index.js b/node_modules/socket.io-parser/index.js
new file mode 100644
index 0000000..ea206ea
--- /dev/null
+++ b/node_modules/socket.io-parser/index.js
@@ -0,0 +1,400 @@
+
+/**
+ * Module dependencies.
+ */
+
+var debug = require('debug')('socket.io-parser');
+var Emitter = require('component-emitter');
+var hasBin = require('has-binary2');
+var binary = require('./binary');
+var isBuf = require('./is-buffer');
+
+/**
+ * Protocol version.
+ *
+ * @api public
+ */
+
+exports.protocol = 4;
+
+/**
+ * Packet types.
+ *
+ * @api public
+ */
+
+exports.types = [
+ 'CONNECT',
+ 'DISCONNECT',
+ 'EVENT',
+ 'ACK',
+ 'ERROR',
+ 'BINARY_EVENT',
+ 'BINARY_ACK'
+];
+
+/**
+ * Packet type `connect`.
+ *
+ * @api public
+ */
+
+exports.CONNECT = 0;
+
+/**
+ * Packet type `disconnect`.
+ *
+ * @api public
+ */
+
+exports.DISCONNECT = 1;
+
+/**
+ * Packet type `event`.
+ *
+ * @api public
+ */
+
+exports.EVENT = 2;
+
+/**
+ * Packet type `ack`.
+ *
+ * @api public
+ */
+
+exports.ACK = 3;
+
+/**
+ * Packet type `error`.
+ *
+ * @api public
+ */
+
+exports.ERROR = 4;
+
+/**
+ * Packet type 'binary event'
+ *
+ * @api public
+ */
+
+exports.BINARY_EVENT = 5;
+
+/**
+ * Packet type `binary ack`. For acks with binary arguments.
+ *
+ * @api public
+ */
+
+exports.BINARY_ACK = 6;
+
+/**
+ * Encoder constructor.
+ *
+ * @api public
+ */
+
+exports.Encoder = Encoder;
+
+/**
+ * Decoder constructor.
+ *
+ * @api public
+ */
+
+exports.Decoder = Decoder;
+
+/**
+ * A socket.io Encoder instance
+ *
+ * @api public
+ */
+
+function Encoder() {}
+
+/**
+ * Encode a packet as a single string if non-binary, or as a
+ * buffer sequence, depending on packet type.
+ *
+ * @param {Object} obj - packet object
+ * @param {Function} callback - function to handle encodings (likely engine.write)
+ * @return Calls callback with Array of encodings
+ * @api public
+ */
+
+Encoder.prototype.encode = function(obj, callback){
+ if ((obj.type === exports.EVENT || obj.type === exports.ACK) && hasBin(obj.data)) {
+ obj.type = obj.type === exports.EVENT ? exports.BINARY_EVENT : exports.BINARY_ACK;
+ }
+
+ debug('encoding packet %j', obj);
+
+ if (exports.BINARY_EVENT === obj.type || exports.BINARY_ACK === obj.type) {
+ encodeAsBinary(obj, callback);
+ }
+ else {
+ var encoding = encodeAsString(obj);
+ callback([encoding]);
+ }
+};
+
+/**
+ * Encode packet as string.
+ *
+ * @param {Object} packet
+ * @return {String} encoded
+ * @api private
+ */
+
+function encodeAsString(obj) {
+
+ // first is type
+ var str = '' + obj.type;
+
+ // attachments if we have them
+ if (exports.BINARY_EVENT === obj.type || exports.BINARY_ACK === obj.type) {
+ str += obj.attachments + '-';
+ }
+
+ // if we have a namespace other than `/`
+ // we append it followed by a comma `,`
+ if (obj.nsp && '/' !== obj.nsp) {
+ str += obj.nsp + ',';
+ }
+
+ // immediately followed by the id
+ if (null != obj.id) {
+ str += obj.id;
+ }
+
+ // json data
+ if (null != obj.data) {
+ str += JSON.stringify(obj.data);
+ }
+
+ debug('encoded %j as %s', obj, str);
+ return str;
+}
+
+/**
+ * Encode packet as 'buffer sequence' by removing blobs, and
+ * deconstructing packet into object with placeholders and
+ * a list of buffers.
+ *
+ * @param {Object} packet
+ * @return {Buffer} encoded
+ * @api private
+ */
+
+function encodeAsBinary(obj, callback) {
+
+ function writeEncoding(bloblessData) {
+ var deconstruction = binary.deconstructPacket(bloblessData);
+ var pack = encodeAsString(deconstruction.packet);
+ var buffers = deconstruction.buffers;
+
+ buffers.unshift(pack); // add packet info to beginning of data list
+ callback(buffers); // write all the buffers
+ }
+
+ binary.removeBlobs(obj, writeEncoding);
+}
+
+/**
+ * A socket.io Decoder instance
+ *
+ * @return {Object} decoder
+ * @api public
+ */
+
+function Decoder() {
+ this.reconstructor = null;
+}
+
+/**
+ * Mix in `Emitter` with Decoder.
+ */
+
+Emitter(Decoder.prototype);
+
+/**
+ * Decodes an ecoded packet string into packet JSON.
+ *
+ * @param {String} obj - encoded packet
+ * @return {Object} packet
+ * @api public
+ */
+
+Decoder.prototype.add = function(obj) {
+ var packet;
+ if (typeof obj === 'string') {
+ packet = decodeString(obj);
+ if (exports.BINARY_EVENT === packet.type || exports.BINARY_ACK === packet.type) { // binary packet's json
+ this.reconstructor = new BinaryReconstructor(packet);
+
+ // no attachments, labeled binary but no binary data to follow
+ if (this.reconstructor.reconPack.attachments === 0) {
+ this.emit('decoded', packet);
+ }
+ } else { // non-binary full packet
+ this.emit('decoded', packet);
+ }
+ }
+ else if (isBuf(obj) || obj.base64) { // raw binary data
+ if (!this.reconstructor) {
+ throw new Error('got binary data when not reconstructing a packet');
+ } else {
+ packet = this.reconstructor.takeBinaryData(obj);
+ if (packet) { // received final buffer
+ this.reconstructor = null;
+ this.emit('decoded', packet);
+ }
+ }
+ }
+ else {
+ throw new Error('Unknown type: ' + obj);
+ }
+};
+
+/**
+ * Decode a packet String (JSON data)
+ *
+ * @param {String} str
+ * @return {Object} packet
+ * @api private
+ */
+
+function decodeString(str) {
+ var i = 0;
+ // look up type
+ var p = {
+ type: Number(str.charAt(0))
+ };
+
+ if (null == exports.types[p.type]) return error();
+
+ // look up attachments if type binary
+ if (exports.BINARY_EVENT === p.type || exports.BINARY_ACK === p.type) {
+ var buf = '';
+ while (str.charAt(++i) !== '-') {
+ buf += str.charAt(i);
+ if (i == str.length) break;
+ }
+ if (buf != Number(buf) || str.charAt(i) !== '-') {
+ throw new Error('Illegal attachments');
+ }
+ p.attachments = Number(buf);
+ }
+
+ // look up namespace (if any)
+ if ('/' === str.charAt(i + 1)) {
+ p.nsp = '';
+ while (++i) {
+ var c = str.charAt(i);
+ if (',' === c) break;
+ p.nsp += c;
+ if (i === str.length) break;
+ }
+ } else {
+ p.nsp = '/';
+ }
+
+ // look up id
+ var next = str.charAt(i + 1);
+ if ('' !== next && Number(next) == next) {
+ p.id = '';
+ while (++i) {
+ var c = str.charAt(i);
+ if (null == c || Number(c) != c) {
+ --i;
+ break;
+ }
+ p.id += str.charAt(i);
+ if (i === str.length) break;
+ }
+ p.id = Number(p.id);
+ }
+
+ // look up json data
+ if (str.charAt(++i)) {
+ p = tryParse(p, str.substr(i));
+ }
+
+ debug('decoded %s as %j', str, p);
+ return p;
+}
+
+function tryParse(p, str) {
+ try {
+ p.data = JSON.parse(str);
+ } catch(e){
+ return error();
+ }
+ return p;
+}
+
+/**
+ * Deallocates a parser's resources
+ *
+ * @api public
+ */
+
+Decoder.prototype.destroy = function() {
+ if (this.reconstructor) {
+ this.reconstructor.finishedReconstruction();
+ }
+};
+
+/**
+ * A manager of a binary event's 'buffer sequence'. Should
+ * be constructed whenever a packet of type BINARY_EVENT is
+ * decoded.
+ *
+ * @param {Object} packet
+ * @return {BinaryReconstructor} initialized reconstructor
+ * @api private
+ */
+
+function BinaryReconstructor(packet) {
+ this.reconPack = packet;
+ this.buffers = [];
+}
+
+/**
+ * Method to be called when binary data received from connection
+ * after a BINARY_EVENT packet.
+ *
+ * @param {Buffer | ArrayBuffer} binData - the raw binary data received
+ * @return {null | Object} returns null if more binary data is expected or
+ * a reconstructed packet object if all buffers have been received.
+ * @api private
+ */
+
+BinaryReconstructor.prototype.takeBinaryData = function(binData) {
+ this.buffers.push(binData);
+ if (this.buffers.length === this.reconPack.attachments) { // done with buffer list
+ var packet = binary.reconstructPacket(this.reconPack, this.buffers);
+ this.finishedReconstruction();
+ return packet;
+ }
+ return null;
+};
+
+/**
+ * Cleans up binary packet reconstruction variables.
+ *
+ * @api private
+ */
+
+BinaryReconstructor.prototype.finishedReconstruction = function() {
+ this.reconPack = null;
+ this.buffers = [];
+};
+
+function error() {
+ return {
+ type: exports.ERROR,
+ data: 'parser error'
+ };
+}