exports.encode = function (value) { var size = sizeof(value); if (size === 0) return undefined; var buffer = bops.create(size); encode(value, buffer, 0); return buffer; };
function frameHead(length) { var buffer = bops.create(4); buffer[0] = toHexChar(length >>> 12); buffer[1] = toHexChar((length >>> 8) & 0xf); buffer[2] = toHexChar((length >>> 4) & 0xf); buffer[3] = toHexChar(length & 0xf); return buffer; }
module.exports.unsubscribe = function(opts) { var opts = opts || {} , id = opts.messageId , dup = opts.dup ? protocol.DUP_MASK : 0 , unsubs = opts.unsubscriptions version = opts.protocolVersion; var length = 0; // Check message id // if ('number' !== typeof id) { if (!check_message_id(version, id)) { return new Error('Invalid message id'); } else { if (version == protocol.VERSION13) { length += 8; } else { length += 2; } } // Check unsubs if ('object' === typeof unsubs && unsubs.length) { for (var i = 0; i < unsubs.length; i += 1) { if ('string' !== typeof unsubs[i]) { return new Error('Invalid unsubscriptions'); } length += unsubs[i].length + 2; } } else { return new Error('Invalid unsubscriptions'); } var buffer = bops.create(1 + calc_length_length(length) + length) , pos = 0; // Header buffer[pos++] = protocol.codes['unsubscribe'] << protocol.CMD_SHIFT | dup | 1 << protocol.QOS_SHIFT; // Length pos += write_length(buffer, pos, length); // Message ID if (version == protocol.VERSION13) { pos += write_message_id_len64(buffer, pos, id); } else { pos += write_number(buffer, pos, id); } // Unsubs for (var i = 0; i < unsubs.length; i++) { pos += write_string(buffer, pos, unsubs[i]); } return buffer; };
function encodeNumber(value) { var buffer = bops.create(8); if (value < 0) { bops.writeDoubleBE(buffer, -value, 0); return invert(buffer); } bops.writeDoubleBE(buffer, value, 0); return buffer; }
module.exports.suback = function(opts) { var opts = opts || {} , id = opts.messageId , granted = opts.granted , version = opts.protocolVersion; var length = 0; // Check message id // if ('number' !== typeof id) { if (!check_message_id(version, id)) { return new Error('Invalid message id'); } else { if (version == protocol.VERSION13) { length += 8; } else { length += 2; } } // Check granted qos vector if ('object' === typeof granted && granted.length) { for (var i = 0; i < granted.length; i += 1) { if ('number' !== typeof granted[i]) { return new Error('Invalid qos vector'); } length += 1; } } else { return new Error('Invalid qos vector'); } var buffer = bops.create(1 + calc_length_length(length) + length) , pos = 0; // Header bops.writeUInt8(buffer, protocol.codes['suback'] << protocol.CMD_SHIFT, pos++); // Length pos += write_length(buffer, pos, length); // Message ID if (version == protocol.VERSION13) { pos += write_message_id_len64(buffer, pos, id); } else { pos += write_number(buffer, pos, id); } // Subscriptions for (var i = 0; i < granted.length; i++) { bops.writeUInt8(buffer, granted[i], pos++); } return buffer; };
function json2buf(topics,payload,data) { if(data == undefined) { data = {}; } data["topics"] = topics; data["payload"] = payload; var lenth = 0; lenth +=2; for(var key in data) { lenth +=3; // console.log(key + ": " + data[key]); var value = data[key]; var strlen = 0; switch (typeof value){ case "number": case "string": strlen = Buffer.byteLength(value.toString()); break; case "object": // for json, example apn_json strlen = Buffer.byteLength(JSON.stringify(value)); break; default : strlen = 0; break } lenth += strlen; } var buff = bops.create(lenth), pos = 0; pos += write_number(buff, pos, lenth); for(var key in data) { if(key2commad(key)){ // console.log(key + ": " + data[key]); bops.writeUInt8(buff, key2commad(key), pos++); var value = data[key]; switch(typeof value){ case "string": case "number": inc_len = write_string(buff, pos, value.toString()); pos += inc_len; break; case "object": // for json inc_len = write_string(buff, pos, JSON.stringify(value)) pos += inc_len break; default: break } } } return buff; };
function readFirst(callback) { var length = hashes.length; var chunk = bops.create([ 0x50, 0x41, 0x43, 0x4b, // PACK 0, 0, 0, 2, // version 2 length >> 24, // Num of objects (length >> 16) & 0xff, (length >> 8) & 0xff, length & 0xff ]); first = false; sha1sum.update(chunk); callback(null, chunk); }
encode: function(message) { var keys = message.senderKey.split(':'); var ip = keys[0].split('.'); var toPack; if(message.encrypted) { toPack = [ msgpack.encode(parseInt(ip[0])), msgpack.encode(parseInt(ip[1])), msgpack.encode(parseInt(ip[2])), msgpack.encode(parseInt(ip[3])), msgpack.encode(parseInt(keys[1])), msgpack.encode(parseInt(keys[2])), msgpack.encode(true), msgpack.encode(message.key), msgpack.encode(message.executeTime), msgpack.encode(message.millisecondsSinceMidnight), msgpack.encode(message.topic), msgpack.encode(message.partition), msgpack.encode(message.type), msgpack.encode(message.payload) ]; } else { toPack = [ msgpack.encode(parseInt(ip[0])), msgpack.encode(parseInt(ip[1])), msgpack.encode(parseInt(ip[2])), msgpack.encode(parseInt(ip[3])), msgpack.encode(parseInt(keys[1])), msgpack.encode(parseInt(keys[2])), msgpack.encode(false), msgpack.encode(parseInt(message.executeTime)), msgpack.encode(parseInt(message.millisecondsSinceMidnight)), msgpack.encode(message.topic), msgpack.encode(message.partition), msgpack.encode(message.type), msgpack.encode(message.payload) ]; } var buff = bops.join(toPack); var newBuff = bops.create(buff.length + 2); bops.copy(buff, newBuff, 2, 0, buff.length); bops.writeUInt16BE(newBuff, buff.length, 0); return newBuff; }
function encodeList(items) { // TODO pass around a map of references already encoded to detect cycles var buffers = []; var chunk; for (var i = 0, end = items.length; i < end; ++i) { chunk = encode(items[i]); var type = bops.readUInt8(chunk, 0); // We need to escape a few bytes in string and buffer types to prevent confusion with the end byte if (~flatTypes.indexOf(type)) chunk = flatEscape(chunk); buffers.push(chunk); } // Close the list with an end byte buffers.push(bops.create([ 0 ])); return bops.join(buffers); }
var gen_pubs = function(opts, type) { var opts = opts || {} , id = opts.messageId , dup = (opts.dup && type === 'pubrel') ? protocol.DUP_MASK : 0 , qos = type === 'pubrel' ? 1 : 0 , version = opts.protocolVersion; var length = 0; // Check message ID // if ('number' !== typeof id) { if (!check_message_id(version, id)) { return new Error('Invalid message id'); } else { if (version == protocol.VERSION13) { length += 8; } else { length += 2; } } var buffer = bops.create(1 + calc_length_length(length) + length) , pos = 0; // Header buffer[pos++] = protocol.codes[type] << protocol.CMD_SHIFT | dup | qos << protocol.QOS_SHIFT; // Length pos += write_length(buffer, pos, length); // Message ID if (version == protocol.VERSION13) { pos += write_message_id_len64(buffer, pos, id); } else { pos += write_number(buffer, pos, id); } return buffer; }
module.exports.connack = function(opts) { var opts = opts || {} version = opts.protocolVersion , rc = opts.returnCode; // Check return code if ('number' !== typeof rc) { return new Error('Invalid return code'); } var buffer = bops.create(4) , pos = 0; bops.writeUInt8(buffer, protocol.codes['connack'] << protocol.CMD_SHIFT, pos++); pos += write_length(buffer, pos, 2); pos += write_number(buffer, pos, rc); return buffer; };
module.exports = function () { var push = inflate(onEmit, onUnused); var more = true; var chunks = []; var b = bops.create(1); return { write: write, recycle: recycle, flush: flush }; function write(byte) { b[0] = byte; push(null, b); return more; } function recycle() { push.recycle(); more = true; } function flush() { var buffer = bops.join(chunks); chunks.length = 0; return buffer; } function onEmit(err, item) { if (err) throw err; if (item === undefined) { // console.log("onEnd"); more = false; return; } chunks.push(item); } function onUnused(chunks) { // console.log("onUnused", chunks); more = false; } };
exports.toBuffer = function (data) { if (typeof data === 'string') { return bops.from(data).buffer } else if (bops.is(data)) { // If data is a TypedArrayView (Uint8Array) then copy the buffer, so the // underlying buffer will be exactly the right size. We care about this // because the Chrome `sendTo` function will be passed the underlying // ArrayBuffer. var newBuf = bops.create(data.length) bops.copy(data, newBuf, 0, 0, data.length) return newBuf.buffer } else if (data.buffer) { return data.buffer } else if (data instanceof ArrayBuffer) { return data } else { throw new Error('Cannot convert data to ArrayBuffer type') } }
if ('number' !== typeof rc) { return new Error('Invalid return code'); } var buffer = bops.create(4) , pos = 0; bops.writeUInt8(buffer, protocol.codes['connack'] << protocol.CMD_SHIFT, pos++); pos += write_length(buffer, pos, 2); pos += write_number(buffer, pos, rc); return buffer; }; // Publish var empty = bops.create(0); module.exports.publish = function(opts) { var opts = opts || {} , dup = opts.dup ? protocol.DUP_MASK : 0 , qos = opts.qos , retain = opts.retain ? protocol.RETAIN_MASK : 0 , topic = opts.topic , payload = opts.payload || empty , id = opts.messageId , version = opts.protocolVersion; var length = 0; // Topic must be a non-empty string if (!topic || 'string' !== typeof topic) { return new Error('Invalid topic');
module.exports.publish = function(opts) { var opts = opts || {} , dup = opts.dup ? protocol.DUP_MASK : 0 , qos = opts.qos , retain = opts.retain ? protocol.RETAIN_MASK : 0 , topic = opts.topic , payload = opts.payload || empty , id = opts.messageId , version = opts.protocolVersion; var length = 0; // Topic must be a non-empty string if (!topic || 'string' !== typeof topic) { return new Error('Invalid topic'); } else { length += topic.length + 2; } // get the payload length if (!bops.is(payload)) { length += Buffer.byteLength(payload); } else { length += payload.length; } // Message id must a number if qos > 0 // if (qos && 'number' !== typeof id) { if (qos && !check_message_id(version, id)) { return new Error('Invalid message id') } else if (qos) { if (version == protocol.VERSION13) { length += 8; } else { length += 2; } } var buffer = bops.create(1 + calc_length_length(length) + length) , pos = 0; // Header buffer[pos++] = protocol.codes['publish'] << protocol.CMD_SHIFT | dup | qos << protocol.QOS_SHIFT | retain; // Remaining length pos += write_length(buffer, pos, length); // Topic pos += write_string(buffer, pos, topic); // Message ID if (qos > 0) { if (version == protocol.VERSION13) { pos += write_message_id_len64(buffer, pos, id); } else { pos += write_number(buffer, pos, id); } } // Payload if (!bops.is(payload)) { write_string_no_pos(buffer, pos, payload); } else { write_buffer(buffer, pos, payload); } return buffer; };
module.exports.connect = function(opts) { var opts = opts || {} , protocolId = opts.protocolId , protocolVersion = opts.protocolVersion , will = opts.will , clean = opts.clean , keepalive = opts.keepalive , clientId = opts.clientId , username = opts.username , password = opts.password; var length = 0; // Must be a string and non-falsy if(!protocolId || typeof protocolId !== "string") { return new Error('Invalid protocol id'); } else { length += protocolId.length + 2; } // Must be a 1 byte number if (!protocolVersion || 'number' !== typeof protocolVersion || protocolVersion > 255 || protocolVersion < 0) { return new Error('Invalid protocol version'); } else { length += 1; } // Must be a non-falsy string if(!clientId || 'string' !== typeof clientId) { return new Error('Invalid client id'); } else { length += clientId.length + 2; } // Must be a two byte number if ('number' !== typeof keepalive || keepalive < 0 || keepalive > 65535) { return new Error('Invalid keepalive'); } else { length += 2; } // Connect flags length += 1; // If will exists... if (will) { // It must be an object if ('object' !== typeof will) { return new Error('Invalid will'); } // It must have topic typeof string if (!will.topic || 'string' !== typeof will.topic) { return new Error('Invalid will - invalid topic'); } else { length += will.topic.length + 2; } // TODO: should be a buffer // It must have payload typeof string if (!will.payload || 'string' !== typeof will.payload) { return new Error('Invalid will - invalid payload'); } else { length += will.payload.length + 2; } } // Username if (username && 'string' !== typeof username) { return new Error('Invalid username'); } else if (username) { length += username.length + 2; } // Password if (password && 'string' !== typeof password) { return new Error('Invalid password'); } else if (password) { length += password.length + 2; } var buffer = bops.create(1 + calc_length_length(length) + length) , pos = 0; // Generate header bops.writeUInt8(buffer, protocol.codes['connect'] << protocol.CMD_SHIFT, pos++); // Generate length pos += write_length(buffer, pos, length); // Generate protocol ID pos += write_string(buffer, pos, protocolId); bops.writeUInt8(buffer, protocolVersion, pos++); // Connect flags var flags = 0; flags |= username ? protocol.USERNAME_MASK : 0; flags |= password ? protocol.PASSWORD_MASK : 0; flags |= (will && will.retain) ? protocol.WILL_RETAIN_MASK : 0; flags |= (will && will.qos) ? will.qos << protocol.WILL_QOS_SHIFT : 0; flags |= will ? protocol.WILL_FLAG_MASK : 0; flags |= clean ? protocol.CLEAN_SESSION_MASK : 0; bops.writeUInt8(buffer, flags, pos++); // Keepalive pos += write_number(buffer, pos, keepalive); // Client ID pos += write_string(buffer, pos, clientId); // Will if (will) { pos += write_string(buffer, pos, will.topic); pos += write_string(buffer, pos, will.payload); } // Username and password if (username) pos += write_string(buffer, pos, username); if (password) pos += write_string(buffer, pos, password); return buffer; };
return function (item) { // Forward the EOS marker if (item === undefined) return emit(); // Once we're in pack mode, everything goes straight through if (state === 3) return emit(item); // Otherwise parse the data using a state machine. for (var i = 0, l = item.length; i < l; i++) { var byte = item[i]; if (state === 0) { var val = fromHexChar(byte); if (val === -1) { if (byte === PACK[0]) { offset = 1; state = 2; continue; } state = -1; throw new SyntaxError("Not a hex char: " + String.fromCharCode(byte)); } length |= val << ((--offset) * 4); if (offset === 0) { if (length === 4) { offset = 4; emit(""); } else if (length === 0) { offset = 4; emit(null); } else if (length > 4) { length -= 4; data = bops.create(length); state = 1; } else { state = -1; throw new SyntaxError("Invalid length: " + length); } } } else if (state === 1) { data[offset++] = byte; if (offset === length) { offset = 4; state = 0; length = 0; if (data[0] === 1) { emit(bops.subarray(data, 1)); } else if (data[0] === 2) { emit({progress: bops.to(bops.subarray(data, 1))}); } else if (data[0] === 3) { emit({error: bops.to(bops.subarray(data, 1))}); } else { emit(bops.to(data)); } } } else if (state === 2) { if (offset < 4 && byte === PACK[offset++]) { continue; } state = 3; emit(bops.join([PACK, bops.subarray(item, i)])); break; } else { throw new Error("pkt-line decoder in invalid state"); } } };
function apply_delta(delta, target) { var base_size_info = {size: null, buffer: null} , resized_size_info = {size: null, buffer: null} , output_buffer , out_idx , command , len , idx delta_header(delta, base_size_info) delta_header(base_size_info.buffer, resized_size_info) delta = resized_size_info.buffer idx = out_idx = 0 output_buffer = binary.create(resized_size_info.size) len = delta.length while(idx < len) { command = delta[idx++] command & 0x80 ? copy() : insert() } return output_buffer function copy() { binary.writeUInt32LE(OFFSET_BUFFER, 0, 0) binary.writeUInt32LE(LENGTH_BUFFER, 0, 0) var check = 1 , length , offset for(var x = 0; x < 4; ++x) { if(command & check) { OFFSET_BUFFER[3 - x] = delta[idx++] } check <<= 1 } for(var x = 0; x < 3; ++x) { if(command & check) { LENGTH_BUFFER[3 - x] = delta[idx++] } check <<= 1 } LENGTH_BUFFER[0] = 0 length = binary.readUInt32BE(LENGTH_BUFFER, 0) || 0x10000 offset = binary.readUInt32BE(OFFSET_BUFFER, 0) binary.copy(target, output_buffer, out_idx, offset, offset + length) out_idx += length } function insert() { binary.copy(delta, output_buffer, out_idx, idx, command + idx) idx += command out_idx += command } }
// This is Chris Dickinson's code var binary = require('bops') , Decoder = require('varint/decode.js') , vi = new Decoder // we use writeUint[8|32][LE|BE] instead of indexing // into buffers so that we get buffer-browserify compat. var OFFSET_BUFFER = binary.create(4) , LENGTH_BUFFER = binary.create(4) module.exports = apply_delta; function apply_delta(delta, target) { var base_size_info = {size: null, buffer: null} , resized_size_info = {size: null, buffer: null} , output_buffer , out_idx , command , len , idx delta_header(delta, base_size_info) delta_header(base_size_info.buffer, resized_size_info) delta = resized_size_info.buffer idx = out_idx = 0 output_buffer = binary.create(resized_size_info.size) len = delta.length
module.exports.subscribe = function(opts) { var opts = opts || {} , dup = opts.dup ? protocol.DUP_MASK : 0 , qos = opts.qos || 0 , id = opts.messageId , subs = opts.subscriptions , version = opts.protocolVersion; var length = 0; // Check mid // if ('number' !== typeof id) { if (!check_message_id(version, id)) { return new Error('Invalid message id'); } else { if (version == protocol.VERSION13) { length += 8; } else { length += 2; } } // Check subscriptions if ('object' === typeof subs && subs.length) { for (var i = 0; i < subs.length; i += 1) { var topic = subs[i].topic , qos = subs[i].qos; if ('string' !== typeof topic) { return new Error('Invalid subscriptions - invalid topic'); } if ('number' !== typeof qos) { return new Error('Invalid subscriptions - invalid qos'); } length += topic.length + 2 + 1; } } else { return new Error('Invalid subscriptions'); } var buffer = bops.create(1 + calc_length_length(length) + length) , pos = 0; // Generate header bops.writeUInt8(buffer, protocol.codes['subscribe'] << protocol.CMD_SHIFT | dup | 1 << protocol.QOS_SHIFT, pos++); // Generate length pos += write_length(buffer, pos, length); // Generate message ID if (version == protocol.VERSION13) { pos += write_message_id_len64(buffer, pos, id); } else { pos += write_number(buffer, pos, id); } // Generate subs for (var i = 0; i < subs.length; i++) { var sub = subs[i] , topic = sub.topic , qos = sub.qos; // Write topic string pos += write_string(buffer, pos, topic); // Write qos bops.writeUInt8(buffer, qos, pos++); } return buffer; };
module.exports.get = function(opts) { var opts = opts || {} , id = opts.messageId , command = opts.command , status = opts.status , data = opts.data , topics = opts.topics , payload = opts.payload , version = opts.protocolVersion; var length = 0; // Message id must a number if qos > 0 if (!check_message_id(version, id)) { return new Error('Invalid message id') } else { if (version == protocol.VERSION13) { length += 8; } else { length += 2; } } if ('number' !== typeof command) { return new Error('Invalid get - invalid command'); } else { length += 1; } // status could be 0 if (status != undefined && 'number' !== typeof status) { return new Error('Invalid get - invalid status'); } else if (status != undefined) { length += 1; } if(command == 7) { if(topics == undefined) { return new Error('Invalid publish - invalid topics'); } if(topics == payload) { return new Error('Invalid publish - invalid payload'); } data = json2buf(topics,payload,data); length += data.length; } else { length += data.length + 2; } var buffer = bops.create(1 + calc_length_length(length) + length) , pos = 0; // console.log("buffer length = " + buffer.length); // Header bops.writeUInt8(buffer, protocol.codes['get'] << protocol.CMD_SHIFT, pos++); // Length pos += write_length(buffer, pos, length); // Message ID if (version == protocol.VERSION13) { pos += write_message_id_len64(buffer, pos, id); } else { pos += write_number(buffer, pos, id); } // command bops.writeUInt8(buffer, command, pos++); // status if (status != undefined) { bops.writeUInt8(buffer, status, pos++); } if (command == 7) { write_buffer(buffer, pos, data); } else { write_string(buffer, pos, data); } return buffer; };
return function(opts) { var buf = bops.create(2); buf[0] = protocol.codes[type] << 4; buf[1] = 0; return buf; }