UNPKG

rocket.chat.mqtt

Version:

It's a MQTT Server, using redis to scale horizontally.

270 lines (226 loc) 7.16 kB
// write-type.js var IS_ARRAY = require("isarray"); var Int64Buffer = require("int64-buffer"); var Uint64BE = Int64Buffer.Uint64BE; var Int64BE = Int64Buffer.Int64BE; var Bufferish = require("./bufferish"); var BufferProto = require("./bufferish-proto"); var WriteToken = require("./write-token"); var uint8 = require("./write-uint8").uint8; var ExtBuffer = require("./ext-buffer").ExtBuffer; var HAS_UINT8ARRAY = ("undefined" !== typeof Uint8Array); var HAS_MAP = ("undefined" !== typeof Map); var extmap = []; extmap[1] = 0xd4; extmap[2] = 0xd5; extmap[4] = 0xd6; extmap[8] = 0xd7; extmap[16] = 0xd8; exports.getWriteType = getWriteType; function getWriteType(options) { var token = WriteToken.getWriteToken(options); var useraw = options && options.useraw; var binarraybuffer = HAS_UINT8ARRAY && options && options.binarraybuffer; var isBuffer = binarraybuffer ? Bufferish.isArrayBuffer : Bufferish.isBuffer; var bin = binarraybuffer ? bin_arraybuffer : bin_buffer; var usemap = HAS_MAP && options && options.usemap; var map = usemap ? map_to_map : obj_to_map; var writeType = { "boolean": bool, "function": nil, "number": number, "object": (useraw ? object_raw : object), "string": _string(useraw ? raw_head_size : str_head_size), "symbol": nil, "undefined": nil }; return writeType; // false -- 0xc2 // true -- 0xc3 function bool(encoder, value) { var type = value ? 0xc3 : 0xc2; token[type](encoder, value); } function number(encoder, value) { var ivalue = value | 0; var type; if (value !== ivalue) { // float 64 -- 0xcb type = 0xcb; token[type](encoder, value); return; } else if (-0x20 <= ivalue && ivalue <= 0x7F) { // positive fixint -- 0x00 - 0x7f // negative fixint -- 0xe0 - 0xff type = ivalue & 0xFF; } else if (0 <= ivalue) { // uint 8 -- 0xcc // uint 16 -- 0xcd // uint 32 -- 0xce type = (ivalue <= 0xFF) ? 0xcc : (ivalue <= 0xFFFF) ? 0xcd : 0xce; } else { // int 8 -- 0xd0 // int 16 -- 0xd1 // int 32 -- 0xd2 type = (-0x80 <= ivalue) ? 0xd0 : (-0x8000 <= ivalue) ? 0xd1 : 0xd2; } token[type](encoder, ivalue); } // uint 64 -- 0xcf function uint64(encoder, value) { var type = 0xcf; token[type](encoder, value.toArray()); } // int 64 -- 0xd3 function int64(encoder, value) { var type = 0xd3; token[type](encoder, value.toArray()); } // str 8 -- 0xd9 // str 16 -- 0xda // str 32 -- 0xdb // fixstr -- 0xa0 - 0xbf function str_head_size(length) { return (length < 32) ? 1 : (length <= 0xFF) ? 2 : (length <= 0xFFFF) ? 3 : 5; } // raw 16 -- 0xda // raw 32 -- 0xdb // fixraw -- 0xa0 - 0xbf function raw_head_size(length) { return (length < 32) ? 1 : (length <= 0xFFFF) ? 3 : 5; } function _string(head_size) { return string; function string(encoder, value) { // prepare buffer var length = value.length; var maxsize = 5 + length * 3; encoder.offset = encoder.reserve(maxsize); var buffer = encoder.buffer; // expected header size var expected = head_size(length); // expected start point var start = encoder.offset + expected; // write string length = BufferProto.write.call(buffer, value, start); // actual header size var actual = head_size(length); // move content when needed if (expected !== actual) { var targetStart = start + actual - expected; var end = start + length; BufferProto.copy.call(buffer, buffer, targetStart, start, end); } // write header var type = (actual === 1) ? (0xa0 + length) : (actual <= 3) ? (0xd7 + actual) : 0xdb; token[type](encoder, length); // move cursor encoder.offset += length; } } function object(encoder, value) { // null if (value === null) return nil(encoder, value); // Buffer if (isBuffer(value)) return bin(encoder, value); // Array if (IS_ARRAY(value)) return array(encoder, value); // int64-buffer objects if (Uint64BE.isUint64BE(value)) return uint64(encoder, value); if (Int64BE.isInt64BE(value)) return int64(encoder, value); // ext formats var packer = encoder.codec.getExtPacker(value); if (packer) value = packer(value); if (value instanceof ExtBuffer) return ext(encoder, value); // plain old Objects or Map map(encoder, value); } function object_raw(encoder, value) { // Buffer if (isBuffer(value)) return raw(encoder, value); // others object(encoder, value); } // nil -- 0xc0 function nil(encoder, value) { var type = 0xc0; token[type](encoder, value); } // fixarray -- 0x90 - 0x9f // array 16 -- 0xdc // array 32 -- 0xdd function array(encoder, value) { var length = value.length; var type = (length < 16) ? (0x90 + length) : (length <= 0xFFFF) ? 0xdc : 0xdd; token[type](encoder, length); var encode = encoder.codec.encode; for (var i = 0; i < length; i++) { encode(encoder, value[i]); } } // bin 8 -- 0xc4 // bin 16 -- 0xc5 // bin 32 -- 0xc6 function bin_buffer(encoder, value) { var length = value.length; var type = (length < 0xFF) ? 0xc4 : (length <= 0xFFFF) ? 0xc5 : 0xc6; token[type](encoder, length); encoder.send(value); } function bin_arraybuffer(encoder, value) { bin_buffer(encoder, new Uint8Array(value)); } // fixext 1 -- 0xd4 // fixext 2 -- 0xd5 // fixext 4 -- 0xd6 // fixext 8 -- 0xd7 // fixext 16 -- 0xd8 // ext 8 -- 0xc7 // ext 16 -- 0xc8 // ext 32 -- 0xc9 function ext(encoder, value) { var buffer = value.buffer; var length = buffer.length; var type = extmap[length] || ((length < 0xFF) ? 0xc7 : (length <= 0xFFFF) ? 0xc8 : 0xc9); token[type](encoder, length); uint8[value.type](encoder); encoder.send(buffer); } // fixmap -- 0x80 - 0x8f // map 16 -- 0xde // map 32 -- 0xdf function obj_to_map(encoder, value) { var keys = Object.keys(value); var length = keys.length; var type = (length < 16) ? (0x80 + length) : (length <= 0xFFFF) ? 0xde : 0xdf; token[type](encoder, length); var encode = encoder.codec.encode; keys.forEach(function(key) { encode(encoder, key); encode(encoder, value[key]); }); } // fixmap -- 0x80 - 0x8f // map 16 -- 0xde // map 32 -- 0xdf function map_to_map(encoder, value) { if (!(value instanceof Map)) return obj_to_map(encoder, value); var length = value.size; var type = (length < 16) ? (0x80 + length) : (length <= 0xFFFF) ? 0xde : 0xdf; token[type](encoder, length); var encode = encoder.codec.encode; value.forEach(function(val, key, m) { encode(encoder, key); encode(encoder, val); }); } // raw 16 -- 0xda // raw 32 -- 0xdb // fixraw -- 0xa0 - 0xbf function raw(encoder, value) { var length = value.length; var type = (length < 32) ? (0xa0 + length) : (length <= 0xFFFF) ? 0xda : 0xdb; token[type](encoder, length); encoder.send(value); } }