'use strict' var Buffer = require('safe-buffer').Buffer /* Protocol - protocol constants */ var protocol = module.exports /* Command code => mnemonic */ protocol.types = { 0: 'reserved', 1: 'connect', 2: 'connack', 3: 'publish', 4: 'puback', 5: 'pubrec', 6: 'pubrel', 7: 'pubcomp', 8: 'subscribe', 9: 'suback', 10: 'unsubscribe', 11: 'unsuback', 12: 'pingreq', 13: 'pingresp', 14: 'disconnect', 15: 'auth' } /* Mnemonic => Command code */ protocol.codes = {} for (var k in protocol.types) { var v = protocol.types[k] protocol.codes[v] = k } /* Header */ protocol.CMD_SHIFT = 4 protocol.CMD_MASK = 0xF0 protocol.DUP_MASK = 0x08 protocol.QOS_MASK = 0x03 protocol.QOS_SHIFT = 1 protocol.RETAIN_MASK = 0x01 /* Length */ protocol.LENGTH_MASK = 0x7F protocol.LENGTH_FIN_MASK = 0x80 /* Connack */ protocol.SESSIONPRESENT_MASK = 0x01 protocol.SESSIONPRESENT_HEADER = Buffer.from([protocol.SESSIONPRESENT_MASK]) protocol.CONNACK_HEADER = Buffer.from([protocol.codes['connack'] << protocol.CMD_SHIFT]) /* Connect */ protocol.USERNAME_MASK = 0x80 protocol.PASSWORD_MASK = 0x40 protocol.WILL_RETAIN_MASK = 0x20 protocol.WILL_QOS_MASK = 0x18 protocol.WILL_QOS_SHIFT = 3 protocol.WILL_FLAG_MASK = 0x04 protocol.CLEAN_SESSION_MASK = 0x02 protocol.CONNECT_HEADER = Buffer.from([protocol.codes['connect'] << protocol.CMD_SHIFT]) /* Properties */ protocol.properties = { sessionExpiryInterval: 17, willDelayInterval: 24, receiveMaximum: 33, maximumPacketSize: 39, topicAliasMaximum: 34, requestResponseInformation: 25, requestProblemInformation: 23, userProperties: 38, authenticationMethod: 21, authenticationData: 22, payloadFormatIndicator: 1, messageExpiryInterval: 2, contentType: 3, responseTopic: 8, correlationData: 9, maximumQoS: 36, retainAvailable: 37, assignedClientIdentifier: 18, reasonString: 31, wildcardSubscriptionAvailable: 40, subscriptionIdentifiersAvailable: 41, sharedSubscriptionAvailable: 42, serverKeepAlive: 19, responseInformation: 26, serverReference: 28, topicAlias: 35, subscriptionIdentifier: 11 } protocol.propertiesCodes = {} for (var prop in protocol.properties) { var id = protocol.properties[prop] protocol.propertiesCodes[id] = prop } protocol.propertiesTypes = { sessionExpiryInterval: 'int32', willDelayInterval: 'int32', receiveMaximum: 'int16', maximumPacketSize: 'int32', topicAliasMaximum: 'int16', requestResponseInformation: 'byte', requestProblemInformation: 'byte', userProperties: 'pair', authenticationMethod: 'string', authenticationData: 'binary', payloadFormatIndicator: 'byte', messageExpiryInterval: 'int32', contentType: 'string', responseTopic: 'string', correlationData: 'binary', maximumQoS: 'int8', retainAvailable: 'byte', assignedClientIdentifier: 'string', reasonString: 'string', wildcardSubscriptionAvailable: 'byte', subscriptionIdentifiersAvailable: 'byte', sharedSubscriptionAvailable: 'byte', serverKeepAlive: 'int16', responseInformation: 'string', serverReference: 'string', topicAlias: 'int16', subscriptionIdentifier: 'var' } function genHeader (type) { return [0, 1, 2].map(function (qos) { return [0, 1].map(function (dup) { return [0, 1].map(function (retain) { var buf = new Buffer(1) buf.writeUInt8( protocol.codes[type] << protocol.CMD_SHIFT | (dup ? protocol.DUP_MASK : 0) | qos << protocol.QOS_SHIFT | retain, 0, true) return buf }) }) }) } /* Publish */ protocol.PUBLISH_HEADER = genHeader('publish') /* Subscribe */ protocol.SUBSCRIBE_HEADER = genHeader('subscribe') protocol.SUBSCRIBE_OPTIONS_QOS_MASK = 0x03 protocol.SUBSCRIBE_OPTIONS_NL_MASK = 0x01 protocol.SUBSCRIBE_OPTIONS_NL_SHIFT = 2 protocol.SUBSCRIBE_OPTIONS_RAP_MASK = 0x01 protocol.SUBSCRIBE_OPTIONS_RAP_SHIFT = 3 protocol.SUBSCRIBE_OPTIONS_RH_MASK = 0x03 protocol.SUBSCRIBE_OPTIONS_RH_SHIFT = 4 protocol.SUBSCRIBE_OPTIONS_RH = [0x00, 0x10, 0x20] protocol.SUBSCRIBE_OPTIONS_NL = 0x04 protocol.SUBSCRIBE_OPTIONS_RAP = 0x08 protocol.SUBSCRIBE_OPTIONS_QOS = [0x00, 0x01, 0x02] /* Unsubscribe */ protocol.UNSUBSCRIBE_HEADER = genHeader('unsubscribe') /* Confirmations */ protocol.ACKS = { unsuback: genHeader('unsuback'), puback: genHeader('puback'), pubcomp: genHeader('pubcomp'), pubrel: genHeader('pubrel'), pubrec: genHeader('pubrec') } protocol.SUBACK_HEADER = Buffer.from([protocol.codes['suback'] << protocol.CMD_SHIFT]) /* Protocol versions */ protocol.VERSION3 = Buffer.from([3]) protocol.VERSION4 = Buffer.from([4]) protocol.VERSION5 = Buffer.from([5]) /* QoS */ protocol.QOS = [0, 1, 2].map(function (qos) { return Buffer.from([qos]) }) /* Empty packets */ protocol.EMPTY = { pingreq: Buffer.from([protocol.codes['pingreq'] << 4, 0]), pingresp: Buffer.from([protocol.codes['pingresp'] << 4, 0]), disconnect: Buffer.from([protocol.codes['disconnect'] << 4, 0]) }