var mqttServer = net.createServer(function (stream) { var client = mqttCon(stream) var clients = {} client.on('connect', function (packet) { console.log('MQTT Client connected ' + packet.clientId) client.connack({ returnCode: 0 }) client.id = packet.clientId clients[client.id] = client }) client.on('pingreq', function (packet) { client.pingresp() }) client.on('subscribe', function (packet) { var granted = [] for (var i = 0; i < packet.subscriptions.length; i++) { var subscription = packet.subscriptions[i] console.log('MQTT Client ' + client.id + ' subscribed to ' + subscription.topic) granted.push(subscription.qos) } client.suback({ granted: granted, messageId: packet.messageId }) }) client.on('close', function (packet) { delete clients[client.id] console.log('MQTT Client closed connection ' + client.id) }) client.on('disconnect', function (packet) { client.stream.end() console.log('MQTT Client disconnected ' + client.id) }) client.on('error', function (packet) { if (!clients[client.id]) return delete clients[client.id] client.stream.end() }) events.on('mqtt:broadcast', function (topic, payload) { var clientIds = Object.keys(clients) clientIds.forEach(function (id) { clients[id].publish({ topic: topic, payload: payload }) }) }) })
server.on('connection', function(stream) { var conn = mqttCon(stream); conn.on('connect', function() { console.log('connected'); }); conn.on('publish', function(packet) { // console.log(packet); conn.puback({ messageId: packet.messageId }) }); conn.on('pingreq', function() { conn.pingresp(); }); // conn is your MQTT connection! });
this.server.on('connection', function(stream) { var socket = MqttCon(stream); socket['id'] = curId++; socket.on('connect', function(pkg) { console.log('connected'); sendHandshake(socket, self); }); socket.on('publish', function(pkg) { pkg = Coder.decodeServer(pkg.payload, self.servicesMap); try { processMsg(socket, self, pkg); } catch (err) { var resp = Coder.encodeServer(pkg.id, [cloneError(err)]); // doSend(socket, resp); logger.error('process rpc message error %s', err.stack); } }); socket.on('pingreq', function() { socket.pingresp(); }); socket.on('error', function() { self.onSocketClose(socket); }); socket.on('close', function() { self.onSocketClose(socket); }); self.sockets[socket.id] = socket; socket.on('disconnect', function(reason) { self.onSocketClose(socket); }); });
socket.on('connection', stream => { let client; if (ws) { client = mqtt(wsStream(stream)); } else { client = mqtt(stream); } // Store unique connection identifier client.__secret = Date.now() + '_' + Math.round(Math.random() * 10000); client.on('connect', options => { // set client id client.id = options.clientId; client.cleanSession = options.cleanSession === undefined ? options.cleanSession : options.clean; client._keepalive = options.keepalive; // get possible old client let oldClient = clients[client.id]; if (config.user) { if (config.user !== options.username || config.pass !== (options.password || '').toString()) { adapter.log.warn(`Client [${client.id}] has invalid password(${options.password}) or username(${options.username})`); client.connack({returnCode: 4}); if (oldClient) { // delete existing client delete clients[client.id]; updateClients(); oldClient.destroy(); } client.destroy(); return; } } if (oldClient) { adapter.log.info(`Client [${client.id}] reconnected. Old secret ${clients[client.id].__secret}. New secret ${client.__secret}`); // need to destroy the old client if (client.__secret !== clients[client.id].__secret) { // it is another socket!! // It was following situation: // - old connection was active // - new connection is on the same TCP // Just forget him // oldClient.destroy(); } } else { adapter.log.info(`Client [${client.id}] connected with secret ${client.__secret}`); } let sessionPresent = false; if (!client.cleanSession && adapter.config.storeClientsTime !== 0) { if (persistentSessions[client.id]) { sessionPresent = true; persistentSessions[client.id].lastSeen = Date.now(); } else { persistentSessions[client.id] = { _subsID: {}, _subs: {}, messages: [], lastSeen: Date.now() }; } client._messages = persistentSessions[client.id].messages; persistentSessions[client.id].connected = true; } else if (client.cleanSession && persistentSessions[client.id]) { delete persistentSessions[client.id]; } client._messages = client._messages || []; client.connack({returnCode: 0, sessionPresent}); clients[client.id] = client; updateClients(); if (options.will) { // the client's will message options. object that supports the following properties: // topic: the will topic. string // payload: the will payload. string // qos: will qos level. number // retain: will retain flag. boolean client._will = JSON.parse(JSON.stringify(options.will)); let id; if (topic2id[client._will.topic]) { id = topic2id[client._will.topic].id || convertTopic2id(client._will.topic, false, config.prefix, adapter.namespace); } else { id = convertTopic2id(client._will.topic, false, config.prefix, adapter.namespace); } checkObject(id, client._will.topic); //something went wrong while JSON.parse, so payload of last will not handeled correct as buffer client._will.payload = options.will.payload; adapter.log.debug(`Client [${client.id}] with last will ${JSON.stringify(client._will)}`); } // Send all subscribed variables to client if (config.publishAllOnStart) { // Give to client 2 seconds to send subscribe client._sendOnStart = setTimeout(() => { client._sendOnStart = null; let list = []; // If client still connected for (let id in states) { if (states.hasOwnProperty(id)) { list.push(id); } } sendStates2Client(client, list); }, adapter.config.sendOnStartInterval); } if (persistentSessions[client.id]) { client._subsID = persistentSessions[client.id]._subsID; client._subs = persistentSessions[client.id]._subs; if (persistentSessions[client.id].messages.length) { // give to the client a little bit time client._resendonStart = setTimeout(clientId => { client._resendonStart = null; resendMessages2Client(client, persistentSessions[clientId].messages); }, 100, client.id); } } //set timeout for stream to 1,5 times keepalive [MQTT-3.1.2-24]. if (client._keepalive !== 0) { let streamtimeout_sec = 1.5 * client._keepalive; stream.setTimeout(streamtimeout_sec * 1000); adapter.log.debug(`Client [${client.id}] with keepalive ${client._keepalive} set timeout to ${streamtimeout_sec} seconds`); } }); client.on('publish', packet => { if (clients[client.id] && client.__secret !== clients[client.id].__secret) { return adapter.log.debug(`Old client ${client.id} with secret ${client.__secret} sends publish. Ignore! Actual secret is ${clients[client.id].__secret}`); } if (persistentSessions[client.id]) { persistentSessions[client.id].lastSeen = Date.now(); } if (packet.qos === 1) { // send PUBACK to client client.puback({ messageId: packet.messageId }); } else if (packet.qos === 2) { const pack = client._messages.find(e => e.messageId === packet.messageId); if (pack) { // duplicate message => ignore adapter.log.warn(`Client [${client.id}] Ignored duplicate message with ID: ${packet.messageId}`); return; } else { packet.ts = Date.now(); packet.cmd = 'pubrel'; packet.count = 0; client._messages.push(packet); client.pubrec({ messageId: packet.messageId }); return; } } receivedTopic(packet, client); }); // response for QoS2 client.on('pubrec', packet => { if (clients[client.id] && client.__secret !== clients[client.id].__secret) { return adapter.log.debug(`Old client ${client.id} with secret ${client.__secret} sends pubrec. Ignore! Actual secret is ${clients[client.id].__secret}`); } if (persistentSessions[client.id]) { persistentSessions[client.id].lastSeen = Date.now(); } // remove this message from queue let frame = client._messages.find(e => e.messageId === packet.messageId); if (frame) { client.pubrel({ messageId: packet.messageId }); } else { adapter.log.warn(`Client [${client.id}] Received pubrec on ${client.id} for unknown messageId ${packet.messageId}`); } }); // response for QoS2 client.on('pubcomp', packet => { if (clients[client.id] && client.__secret !== clients[client.id].__secret) { return adapter.log.debug(`Old client ${client.id} with secret ${client.__secret} sends pubcomp. Ignore! Actual secret is ${clients[client.id].__secret}`); } if (persistentSessions[client.id]) { persistentSessions[client.id].lastSeen = Date.now(); } let pos = null; // remove this message from queue client._messages.forEach((e, i) => { if (e.messageId === packet.messageId) { pos = i; return false; } }); if (pos !== null) { client._messages.splice(pos, 1); } else { adapter.log.warn(`Client [${client.id}] Received pubcomp for unknown message ID: ${packet.messageId}`); } }); // response for QoS2 client.on('pubrel', packet => { if (clients[client.id] && client.__secret !== clients[client.id].__secret) { return adapter.log.debug(`Old client ${client.id} with secret ${client.__secret} sends pubrel. Ignore! Actual secret is ${clients[client.id].__secret}`); } if (persistentSessions[client.id]) { persistentSessions[client.id].lastSeen = Date.now(); } // remove this message from queue let frame = client._messages.find(e => e.messageId === packet.messageId); if (frame) { client.pubcomp({ messageId: packet.messageId }); receivedTopic(frame, client); } else { adapter.log.warn(`Client [${client.id}] Received pubrel on ${client.id} for unknown messageId ${packet.messageId}`); } }); // response for QoS1 client.on('puback', packet => { if (clients[client.id] && client.__secret !== clients[client.id].__secret) { return adapter.log.debug(`Old client ${client.id} with secret ${client.__secret} sends puback. Ignore! Actual secret is ${clients[client.id].__secret}`); } if (persistentSessions[client.id]) { persistentSessions[client.id].lastSeen = Date.now(); } // remove this message from queue let pos = null; // remove this message from queue client._messages.forEach((e, i) => { if (e.messageId === packet.messageId) { pos = i; return false; } }); if (pos !== null) { adapter.log.debug(`Client [${client.id}] Received puback for ${client.id} message ID: ${packet.messageId}`); client._messages.splice(pos, 1); } else { adapter.log.warn(`Client [${client.id}] Received puback for unknown message ID: ${packet.messageId}`); } }); client.on('subscribe', packet => { if (clients[client.id] && client.__secret !== clients[client.id].__secret) { return adapter.log.debug(`Old client ${client.id} with secret ${client.__secret} sends subscribe. Ignore! Actual secret is ${clients[client.id].__secret}`); } if (persistentSessions[client.id]) { persistentSessions[client.id].lastSeen = Date.now(); } const granted = []; if (!client._subsID) client._subsID = {}; if (!client._subs) client._subs = {}; for (let i = 0; i < packet.subscriptions.length; i++) { granted.push(packet.subscriptions[i].qos); const topic = packet.subscriptions[i].topic; let id; if (topic2id[topic]) { id = topic2id[topic].id || convertTopic2id(topic, false, config.prefix, adapter.namespace); } else { id = convertTopic2id(topic, false, config.prefix, adapter.namespace); } if (!id) { adapter.log.error(`Client [${client.id}] Invalid topic: ${topic}`); continue; } // if pattern without wildcards if (id.indexOf('*') === -1 && id.indexOf('#') === -1 && id.indexOf('+') === -1) { // If state is unknown => create mqtt.X.topic if (!topic2id[topic]) { checkObject(id, topic, (err, id) => { adapter.log.info(`Client [${client.id}] subscribes on topic "${topic}"`); client._subsID[id] = {id, qos: packet.subscriptions[i].qos}; }); } else { client._subsID[topic2id[topic].id] = {id: topic2id[topic].id, qos: packet.subscriptions[i].qos}; adapter.log.info(`Client [${client.id}] subscribes on "${topic2id[topic].id}"`); if (adapter.config.publishOnSubscribe) { adapter.log.info(`Client [${client.id}] publishOnSubscribe`); sendState2Client(client, topic2id[topic].id, states[topic2id[topic].id]); } } } else { let pattern = topic; // remove prefix if (pattern.startsWith(adapter.config.prefix)) { pattern = pattern.substring(adapter.config.prefix.length); } pattern = pattern.replace(/\//g, '.'); if (pattern[0] === '.') pattern = pattern.substring(1); // add simple pattern let regText = pattern2RegEx(pattern); client._subs[topic] = { regex: new RegExp(regText), qos: packet.subscriptions[i].qos, pattern: pattern }; adapter.log.info(`Client [${client.id}] subscribes on "${topic}" with regex /${regText}/`); // add simple mqtt.0.pattern pattern = adapter.namespace + '/' + pattern; regText = pattern2RegEx(pattern); client._subs[adapter.namespace + '/' + topic] = { regex: new RegExp(regText), qos: packet.subscriptions[i].qos, pattern: pattern }; adapter.log.info(`Client [${client.id}] subscribes on "${topic}" with regex /${regText}/`); if (adapter.config.publishOnSubscribe) { adapter.log.info(`Client [${client.id}] publishOnSubscribe send all known states`); for (const savedId in states) { if (states.hasOwnProperty(savedId) && checkPattern(client._subs, savedId)) { sendState2Client(client, savedId, states[savedId]); } } } } } client.suback({granted: granted, messageId: packet.messageId}); }); client.on('unsubscribe', packet => { if (clients[client.id] && client.__secret !== clients[client.id].__secret) { return adapter.log.debug(`Old client ${client.id} with secret ${client.__secret} sends unsubscribe. Ignore! Actual secret is ${clients[client.id].__secret}`); } if (persistentSessions[client.id]) { persistentSessions[client.id].lastSeen = Date.now(); } for (let i = 0; i < packet.unsubscriptions.length; i++) { const topic = packet.unsubscriptions[i]; let id; if (topic2id[topic]) { id = topic2id[topic].id || convertTopic2id(topic, false, config.prefix, adapter.namespace); } else { id = convertTopic2id(topic, false, config.prefix, adapter.namespace); } if (!id) { adapter.log.error(`Client [${client.id}] unsubscribes from invalid topic: ${topic}`); continue; } // if pattern without wildcards if (id.indexOf('*') === -1 && id.indexOf('#') === -1 && id.indexOf('+') === -1) { // If state is known if (topic2id[topic]) { let _id = topic2id[topic].id; if (client._subsID[_id]) { delete client._subsID[_id]; adapter.log.info(`Client [${client.id}] unsubscribes on "${_id}"`); } else { adapter.log.info(`Client [${client.id}] unsubscribes on unknown "${_id}"`); } } else { adapter.log.info(`Client [${client.id}] unsubscribes on unknown "${_id}"`); } } else { let pattern = topic.replace(/\//g, '.'); if (pattern[0] === '.') pattern = pattern.substring(1); // add simple pattern if (client._subs[topic]) { adapter.log.info(`Client [${client.id}] unsubscribes on "${topic}"`); delete client._subs[topic]; if (client._subs[adapter.namespace + '/' + topic]) {// add simple mqtt.0.pattern delete client._subs[adapter.namespace + '/' + topic]; adapter.log.info(`Client [${client.id}] unsubscribes on "${adapter.namespace}/${topic}"`); } } else { adapter.log.warn(`Client [${client.id}] unsubscribes on unknwon "${topic}"`); } } } client.unsuback({messageId: packet.messageId}); }); client.on('pingreq', (/*packet*/) => { if (clients[client.id] && client.__secret !== clients[client.id].__secret) { return adapter.log.debug(`Old client ${client.id} with secret ${client.__secret} sends pingreq. Ignore! Actual secret is ${clients[client.id].__secret}`); } if (persistentSessions[client.id]) { persistentSessions[client.id].lastSeen = Date.now(); } adapter.log.debug(`Client [${client.id}] pingreq`); client.pingresp(); }); // connection error handling client.on('close', had_error => clientClose(client, had_error ? 'closed because of error' : 'closed')); client.on('error', e => clientClose(client, e)); client.on('disconnect', () => clientClose(client, 'disconnected')); // client lost without close stream.on('timeout', () => clientClose(client, 'timeout')); });
var doPublish = function(conn, topic, message, qos, period) { setInterval(function() { conn.publish({ topic: topic, payload: message, qos: qos, messageId: (1 << 16) - 1, // Required if qos > 0. retain: false }, function() { console.log('PUBLISH: %s [%s]: %s %s', new Date(), Date.now(), topic, message); }); }, period); }; var stream = net.createConnection(argv.port, argv.host), conn = mqtt(stream); conn.connect({ protocolId: 'MQIsdp', protocolVersion: 3, keepalive: argv.keepalive, clientId: argv.clientid, username: argv.username, password: argv.password }); conn .on('connack', function(packet) { if (packet.returnCode) { console.error('Failed to connect.'); process.exit(1);
MailBox.prototype.connect = function(tracer, cb) { tracer && tracer.info('client', __filename, 'connect', 'mqtt-mailbox try to connect'); if (this.connected) { tracer && tracer.error('client', __filename, 'connect', 'mailbox has already connected'); return cb(new Error('mailbox has already connected.')); } var self = this; var stream = net.createConnection(this.port, this.host); this.socket = MqttCon(stream); var connectTimeout = setTimeout(function() { logger.error('rpc client %s connect to remote server %s timeout', self.serverId, self.id); self.emit('close', self.id); }, CONNECT_TIMEOUT); this.socket.connect({ clientId: 'MQTT_RPC_' + Date.now() }, function() { if (self.connected) { return; } clearTimeout(connectTimeout); self.connected = true; if (self.bufferMsg) { self._interval = setInterval(function() { flush(self); }, self.interval); } self.setupKeepAlive(); }); this.socket.on('publish', function(pkg) { if(pkg.topic == Constants['TOPIC_HANDSHAKE']) { upgradeHandshake(self, pkg.payload); return cb(); } try { pkg = Coder.decodeClient(pkg.payload); processMsg(self, pkg); } catch (err) { logger.error('rpc client %s process remote server %s message with error: %s', self.serverId, self.id, err.stack); } }); this.socket.on('error', function(err) { logger.error('rpc socket %s is error, remote server %s host: %s, port: %s', self.serverId, self.id, self.host, self.port); self.emit('close', self.id); self.close(); }); this.socket.on('pingresp', function() { self.lastPong = Date.now(); }); this.socket.on('disconnect', function(reason) { logger.error('rpc socket %s is disconnect from remote server %s, reason: %s', self.serverId, self.id, reason); var reqs = self.requests; for (var id in reqs) { var ReqCb = reqs[id]; ReqCb(tracer, new Error(self.serverId + ' disconnect with remote server ' + self.id)); } self.emit('close', self.id); }); };
MqttClient.prototype.connect = function(host, port, cb) { cb = cb || function() {} if (this.connected) { return cb(new Error('MqttClient has already connected.')); } if (host) { this.host = host; } else { host = this.host; } if (port) { this.port = port; } else { port = this.port; } var self = this; this.closed = false; var stream = net.createConnection(this.port, this.host); this.socket = MqttCon(stream); // logger.info('try to connect %s %s', this.host, this.port); this.socket.connect({ clientId: this.clientId }); this.addTimeout(); this.socket.on('connack', function() { if (self.connected) { return; } self.connected = true; self.setupKeepAlive(); if (self.connectedTimes++ == 1) { self.emit('connect'); cb(); } else { self.emit('reconnect'); } }); this.socket.on('publish', function(pkg) { var topic = pkg.topic; var msg = pkg.payload.toString(); msg = JSON.parse(msg); // logger.debug('[MqttClient] publish %s %j', topic, msg); self.emit(topic, msg); }); this.socket.on('close', function() { logger.error('mqtt socket is close, remote server host: %s, port: %s', host, port); self.onSocketClose(); }); this.socket.on('error', function(err) { logger.error('mqtt socket is error, remote server host: %s, port: %s', host, port); // self.emit('error', new Error('[MqttClient] socket is error, remote server ' + host + ':' + port)); self.onSocketClose(); }); this.socket.on('pingresp', function() { self.lastPong = Date.now(); }); this.socket.on('disconnect', function() { logger.error('mqtt socket is disconnect, remote server host: %s, port: %s', host, port); self.emit('disconnect', self.id); self.onSocketClose(); }); this.socket.on('timeout', function(reconnectFlag) { if (reconnectFlag) { self.reconnect(); } else { self.exit(); } }) }
socket.on('connection', stream => { let client; if (ws) { client = mqtt(wsStream(stream)); } else { client = mqtt(stream); } client.on('connect', function (packet) { client.id = packet.clientId; clients[client.id] = client; if (config.user) { if (config.user !== packet.username || config.pass !== packet.password.toString()) { console.error('Client [' + packet.clientId + '] has invalid password(' + packet.password + ') or username(' + packet.username + ')'); client.connack({returnCode: 4}); if (clients[client.id]) delete clients[client.id]; client.stream.end(); return; } } console.log('Client [' + packet.clientId + '] connected: user - ' + packet.username + ', pass - ' + packet.password); client.connack({returnCode: 0}); client.publish({topic: 'testServer/connected', payload: 'true'}); }); client.on('publish', function (packet) { console.log('Client [' + client.id + '] publishes "' + packet.topic + '": ' + packet.payload); for (let k in clients) { clients[k].publish({topic: packet.topic, payload: packet.payload}); } }); client.on('subscribe', function (packet) { let granted = []; console.log('Client [' + client.id + '] subscribes on "' + JSON.stringify(packet.subscriptions) + '"'); for (let i = 0; i < packet.subscriptions.length; i++) { granted.push(packet.subscriptions[i].qos); } client.suback({granted: granted, messageId: packet.messageId}); }); client.on('pingreq', function (packet) { console.log('Client [' + client.id + '] pingreq'); client.pingresp(); }); client.on('disconnect', function (packet) { if (clients[client.id]) delete clients[client.id]; console.log('Client [' + client.id + '] disconnected'); client.stream.end(); }); client.on('close', function (err) { if (clients[client.id]) delete clients[client.id]; console.log('Client [' + client.id + '] closed'); }); client.on('error', function (err) { if (clients[client.id]) delete clients[client.id]; console.log('[' + client.id + '] ' + err); client.stream.end(); }); });
this.switcher.on('connection', function(socket) { var mqttClient = MqttConnection(socket); gensocket(mqttClient); });