0.1.11 use topic match to protect against reply packets having same topic and subscribed (which causes infinite loop with broker)

added settable error topic 'error' by default.  Any errors can be sent to broker with that topic
master
David Kebler 2019-04-27 12:08:28 -07:00
parent 6eab513dc4
commit abec7cd661
2 changed files with 16 additions and 4 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@uci/mqtt", "name": "@uci/mqtt",
"version": "0.1.10", "version": "0.1.11",
"description": "mqtt client with json payloads and mqtt custom broker", "description": "mqtt client with json payloads and mqtt custom broker",
"main": "src", "main": "src",
"scripts": { "scripts": {
@ -31,7 +31,8 @@
"is-plain-object": "^2.0.4", "is-plain-object": "^2.0.4",
"lodash.merge": "^4.6.1", "lodash.merge": "^4.6.1",
"lodash.union": "^4.6.0", "lodash.union": "^4.6.0",
"lodash.xor": "^4.5.0" "lodash.xor": "^4.5.0",
"mqtt-match": "^2.0.2"
}, },
"devDependencies": { "devDependencies": {
"chai": "^4.2.0", "chai": "^4.2.0",

View File

@ -6,6 +6,7 @@ import union from 'lodash.union'
import xor from 'lodash.xor' import xor from 'lodash.xor'
import logger from '@uci-utils/logger' import logger from '@uci-utils/logger'
import isPlainObject from 'is-plain-object' import isPlainObject from 'is-plain-object'
import isTopicMatch from 'mqtt-match'
let log = {} let log = {}
@ -31,6 +32,7 @@ class MQTTClient {
id: this.id id: this.id
}) })
this.url = opts.url || null this.url = opts.url || null
this.error = opts.error || 'error' // error topic
// subscription topics can be string of commna delimited or array of strings. If none they by default topic is id // subscription topics can be string of commna delimited or array of strings. If none they by default topic is id
this.topics = Array.isArray(opts.topics) this.topics = Array.isArray(opts.topics)
? opts.topics ? opts.topics
@ -154,8 +156,17 @@ class MQTTClient {
// payload had no command that use topic as cmd // payload had no command that use topic as cmd
else packet = { cmd: topic } else packet = { cmd: topic }
let res = (await this._packetProcess(packet, topic)) || {} let res = (await this._packetProcess(packet, topic)) || {}
log.debug({method:'_listen', line:159, msg:'processed packet back to broker - cmd: should NOT be a subscribed topic or infinite loop!', res:res, topics:this.topics}) log.debug({method:'_listen', line:159, msg:'processed packet back to broker', res:res, topics:this.topics})
// TODO!!!!!!!!!! make sure cmd/topic is not the same as subscribed topics or can make an infinite loop if (this.topics.some(topic => isTopicMatch(topic,res.cmd))) {
if (this.topics.some( topic => isTopicMatch(topic,this.error))) {
log.warn({method:'_listen', line:165, msg:'unable to send error, subscried to error topic', subscribed:this.topics, errorTopic:this.error})
return
}
else {
res = {cmd:'error', msg:`unable to send this response, response topic '${res.cmd}'' matches a topic [${this.topics}] - subscribed to by sender`, response:res, subcribed:this.topics}
log.warn({method:'_listen', line:168,msg:'sent mqtt error message', error:res})
}
}
this.send(res) this.send(res)
} }
} }