123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- /* Protocol - protocol constants */
- const 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 (const k in protocol.types) {
- const 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.VARBYTEINT_MASK = 0x7F
- protocol.VARBYTEINT_FIN_MASK = 0x80
- protocol.VARBYTEINT_MAX = 268435455
- /* 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 (const prop in protocol.properties) {
- const 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(qos => {
- return [0, 1].map(dup => {
- return [0, 1].map(retain => {
- const buf = Buffer.alloc(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])
- protocol.VERSION131 = Buffer.from([131])
- protocol.VERSION132 = Buffer.from([132])
- /* QoS */
- protocol.QOS = [0, 1, 2].map(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])
- }
|