generate.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. var protocol = require('./protocol');
  2. var crypto = require('crypto');
  3. /* TODO: consider rewriting these functions using buffers instead
  4. * of arrays
  5. */
  6. /* Publish */
  7. module.exports.publish = function(opts) {
  8. opts = opts || {};
  9. var dup = opts.dup ? protocol.DUP_MASK : 0;
  10. var qos = opts.qos || 0;
  11. var retain = opts.retain ? protocol.RETAIN_MASK : 0;
  12. var topic = opts.topic;
  13. var payload = opts.payload || new Buffer(0);
  14. var id = (typeof opts.messageId === 'undefined') ? randint() : opts.messageId;
  15. var packet = {header: 0, payload: []};
  16. /* Check required fields */
  17. if (typeof topic !== 'string' || topic.length <= 0) return null;
  18. /* if payload is a string, we'll convert it into a buffer */
  19. if(typeof payload == 'string') {
  20. payload = new Buffer(payload);
  21. }
  22. /* accepting only a buffer for payload */
  23. if (!Buffer.isBuffer(payload)) return null;
  24. if (typeof qos !== 'number' || qos < 0 || qos > 2) return null;
  25. if (typeof id !== 'number' || id < 0 || id > 0xFFFF) return null;
  26. /* Generate header */
  27. packet.header = protocol.codes.publish << protocol.CMD_SHIFT | dup | qos << protocol.QOS_SHIFT | retain;
  28. /* Topic name */
  29. packet.payload = packet.payload.concat(gen_string(topic));
  30. /* Message ID */
  31. if (qos > 0) packet.payload = packet.payload.concat(gen_number(id));
  32. var buf = new Buffer([packet.header]
  33. .concat(gen_length(packet.payload.length + payload.length))
  34. .concat(packet.payload));
  35. return Buffer.concat([buf, payload]);
  36. };
  37. /* Requires length be a number > 0 */
  38. var gen_length = function(length) {
  39. if(typeof length !== "number") return null;
  40. if(length < 0) return null;
  41. var len = [];
  42. var digit = 0;
  43. do {
  44. digit = length % 128 | 0;
  45. length = length / 128 | 0;
  46. if (length > 0) {
  47. digit = digit | 0x80;
  48. }
  49. len.push(digit);
  50. } while (length > 0);
  51. return len;
  52. };
  53. var gen_string = function(str, without_length) { /* based on code in (from http://farhadi.ir/downloads/utf8.js) */
  54. if(arguments.length < 2) without_length = false;
  55. if(typeof str !== "string") return null;
  56. if(typeof without_length !== "boolean") return null;
  57. var string = [];
  58. var length = 0;
  59. for(var i = 0; i < str.length; i++) {
  60. var code = str.charCodeAt(i);
  61. if (code < 128) {
  62. string.push(code); ++length;
  63. } else if (code < 2048) {
  64. string.push(192 + ((code >> 6 ) )); ++length;
  65. string.push(128 + ((code ) & 63)); ++length;
  66. } else if (code < 65536) {
  67. string.push(224 + ((code >> 12) )); ++length;
  68. string.push(128 + ((code >> 6 ) & 63)); ++length;
  69. string.push(128 + ((code ) & 63)); ++length;
  70. } else if (code < 2097152) {
  71. string.push(240 + ((code >> 18) )); ++length;
  72. string.push(128 + ((code >> 12) & 63)); ++length;
  73. string.push(128 + ((code >> 6 ) & 63)); ++length;
  74. string.push(128 + ((code ) & 63)); ++length;
  75. } else {
  76. throw new Error("Can't encode character with code " + code);
  77. }
  78. }
  79. return without_length ? string : gen_number(length).concat(string);
  80. };
  81. var gen_number = function(num) {
  82. var number = [num >> 8, num & 0x00FF];
  83. return number;
  84. };
  85. var randint = function() { return Math.floor(Math.random() * 0xFFFF); };