From abec7cd6617dd72480e8c3cb009f128b14746639 Mon Sep 17 00:00:00 2001 From: David Kebler Date: Sat, 27 Apr 2019 12:08:28 -0700 Subject: [PATCH] 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 --- package.json | 5 +++-- src/client.js | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 56449f2..ff5b0f8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@uci/mqtt", - "version": "0.1.10", + "version": "0.1.11", "description": "mqtt client with json payloads and mqtt custom broker", "main": "src", "scripts": { @@ -31,7 +31,8 @@ "is-plain-object": "^2.0.4", "lodash.merge": "^4.6.1", "lodash.union": "^4.6.0", - "lodash.xor": "^4.5.0" + "lodash.xor": "^4.5.0", + "mqtt-match": "^2.0.2" }, "devDependencies": { "chai": "^4.2.0", diff --git a/src/client.js b/src/client.js index fc9b478..3d1d38b 100644 --- a/src/client.js +++ b/src/client.js @@ -6,6 +6,7 @@ import union from 'lodash.union' import xor from 'lodash.xor' import logger from '@uci-utils/logger' import isPlainObject from 'is-plain-object' +import isTopicMatch from 'mqtt-match' let log = {} @@ -31,6 +32,7 @@ class MQTTClient { id: this.id }) 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 this.topics = Array.isArray(opts.topics) ? opts.topics @@ -154,8 +156,17 @@ class MQTTClient { // payload had no command that use topic as cmd else packet = { cmd: 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}) - // TODO!!!!!!!!!! make sure cmd/topic is not the same as subscribed topics or can make an infinite loop + log.debug({method:'_listen', line:159, msg:'processed packet back to broker', res:res, topics:this.topics}) + 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) } }