UNPKG

message-relay-services

Version:

A simple server to route message to other services, such as email, admin, etc.

142 lines (118 loc) 4.67 kB
'use strict'; const MRUDP = require('./message_relay_udp') const dgram = require('dgram'); // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- const DEFAULT_MULTICAST_ADDR = '224.0.0.1' // ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- /** * This class constructs instances with connected UDP Sockets. * The API methods that send objects expect responses from the UDP servers. */ class Client extends MRUDP { constructor(conf,wrapper) { super(conf,wrapper) // setup client message to a server in order to request subscription, etc. this.multicast_addr = conf.multicast_addr ? conf.multicast_addr : DEFAULT_MULTICAST_ADDR this.multicast_port_map = conf.multicast_port_map } // // // // // // // ---- ---- ---- ---- ---- ---- ---- /** * * @param {string} topic * @param {string} path * @param {object} message * @param {Function} handler * @returns */ async subscribe(topic,path,message,handler) { if ( !(topic) || !(path) ) return false if ( (typeof message === 'function') && (handler === undefined) ) { handler = message message = {} } else if ( handler === undefined ) { return false } if ( this.subcriptions[`update-${topic}-${path}`] !== undefined ) { return false } let p = new Promise((resolve,reject) => { let client = dgram.createSocket(this.udp_type); // listen on a different port client.on('listening', () => { // let address = client.address(); console.log('UDP Client listening on ' + address.address + ":" + address.port); client.setBroadcast(true) client.setMulticastTTL(128); client.addMembership(this.multicast_addr); // this.subcriptions[`update-${topic}-${path}`] = client resolve(true) }); client.on('message', (mbuffer, remote) => { // This service port is set aside for just this topic, so message handling will be different // than for the typical client as there is no need to discern if the message is a response or not. // in the message relay client, `this._handle_unsolicited(message)` takes in the parsed message and emits // an event handled by the communicator in order to identify the callback, here called `handler`. // Also, since the message is on TCP or similar, the partial messages are queued and popped after earlier messages if // they are on the queue. // This handler takes the messages immediatelly from the port and assumes the message is parseable JSON. // The parsed object is passed to th handler without any tick for the JS queue. let message = mbuffer.toString() try { let mobj = JSON.parse(message) handler(mobj, remote) } catch (e) { console.log(e) } }); client.on('error',(err) => { console.log("SUBSCRIBER",err) reject(false) }) client.bind(this.multicast_port_map[topic]); }) // message._ps_op = "sub" message.topic = topic message._m_path = path // try { let promises = [] promises.push(p) promises.push(this.sendMessage(message)) return await Promise.all(promises) } catch (e) { console.log(e) return false } } /** * * @param {string} topic * @param {string} path * @returns */ async unsubscribe(topic,path) { if ( !(topic) || !(path) ) return false let client = this.subcriptions[`update-${topic}-${path}`] if ( client ) { client.dropMembership(this.multicast_addr) client.close() } let message = { "_ps_op" : "unsub", "topic" : topic } message._m_path = path try { return await this.sendMessage(message) } catch (e) { console.log(e) return false } } } // module.exports = Client; module.exports.Communicator = MRUDP.Communicator