multicast-events

Emit an event on a machine and listen it on a different machine (or process).

Usage no npm install needed!

<script type="module">
  import multicastEvents from 'https://cdn.skypack.dev/multicast-events';
</script>

README

Multicast Events

If you need to emit an event from a machine listening it on another machine (or a different process), you can simply use this module to do it. It uses a multicast AMP message: when a node application add a listener for an event, it joins into a multicast group. Using this technique the message is handled only by the listener into the same multicast group (and listening on the same UDP port) and is not necessary to drop unwanted messages inside the application. All events are (optionally) encrypted.

Installation

Install multicast-events as usual:

$ npm install multicast-events --save

Options

Below the options for the EventEmitter constructor:

var EventEmitter = require('multicast-events').EventEmitter;
var emitter = new EventEmitter(opts);

where opts is an Object with this properties:

  • name (String): the name assigned to the instance for debug purpose. The default value is 'emitter #n' where n is a counter.
  • id (String): the identifier of the application. The default value is 'default'.
  • secure (Boolean): Set true to enable the messages encryption. The default value is false.
  • cipher (String): the cipher used to encrypt/decrypt the messages. The default value is 'aes256'.
  • secret (String): the shared secret password used to encrypt/decrypt all messages. The default value is 'secret'.
  • ttl (Number): the number of IP hops that a packet is allowed to go through. The default value is 64.
  • interface (String): if not specified, every listener will add membership to all valid interfaces. The interface must be a valid multicast address (from 224.0.0.1 to 239.255.255.254).
  • loopback (Boolean): when this option is set, multicast packets will also be received on the local interface. The default value is true.
  • foreignOnly (Boolean) This option only makes sense when loopback is true. In this case, if foreignOnly is true, the events are handled ONLY by a process other than the one that issued the event. The default value is false.
  • octet (Number): the first octet used for the generated multicast address. The default value is 239.
  • port (Number): the port used as base to generate a unique port used for every event. The default value is 1967.
  • group (String): all events can be grouped into the same multicast domain generated using this option. It can be a string or a valid multicast address. The default value is 'events'.
  • events (Object): every event correspond to a unique UDP port; if this port is not free, you can override it using this option: { eventName: portNumber }.

Methods

addListener( event, listener )

Add a listener for the specified event

Parameters

  • event: (String) The event.
  • listener: (Function) The function to call when the event occurs. Note: the last argument used to call the listener is a rinfo object whit some information about the sender ( address, family, port, size).

Returns

  • EventEmitter
Example
var EventEmitter = require('multicast-events').EventEmitter;
var emitter = new EventEmitter();
emitter.on('test', function (data, rinfo) {
  console.log(rinfo);
  // example of the result into your terminal session
  // { address: '192.168.2.36', family: 'IPv4', port: 51036, size: 33 } 
});

on( event, listener )

Is an alias for addListener method.

once( event, listener )

Add a listener for the specified event, but the listener is removed after the first call.

Parameters

  • event: (String) The event.
  • listener: (Function) The function to call when the event occurs.

Returns

  • EventEmitter

removeListener( event, listener )

Remove the listener for the specified event.

Parameters

  • event: (String) The event.
  • listener: (Function) The function to remove when the event occurs.

Returns

  • EventEmitter

off( event, listener )

Is an alias for removeListener method.

removeAllListeners( [event] )

Remove all listener or only all listeners for the event if specified.

Parameters

  • event: (String) (optional) The event.

Returns

  • EventEmitter

hasListeners( event )

Verify if the event has at least one listener.

Parameters

  • event: (String) The event.

Returns

  • Boolean True if the event has at least one listener.

Usage

The usage is the same of the standard EventEmitter (with the additional methods).

Example

Create a new javascript file and save it as app1.js:

var EventEmitter = require('multicast-events').EventEmitter;

var emitter = new EventEmitter({
  name: 'emitter on app1',
  loopback: false
});
emitter.on('event-name', function (data) { console.log('listener on app1: ', data); });

emitter.emit('event-name', '--> emit from emitter on app1');

Create a new javascript file and save it as app2.js:

var EventEmitter = require('multicast-events').EventEmitter;

var emitter = new EventEmitter({
  name: 'emitter on app2'
});
emitter.on('event-name', function (data) { console.log('listener on app2: ', data); });

emitter.emit('event-name', '--> emit from emitter on app2');

Open a terminal window and run the first application:

$ DEBUG=events node app1.js

  events emitter on app1 new event emitter of the group 239.22.144.139 +0ms
  events emitter on app1 add listener for "event-name" to 239.22.144.139:30618 +4ms function (data) { console.log('listener on app1: ', data); }
  events emitter on app1 ready to emit event of the group 239.22.144.139 +2ms
  events emitter on app1 ready to handle "event-name" at 239.22.144.139:30618 +0ms
  events emitter on app1 emit "event-name" to 239.22.144.139:30618 +1ms [ 'event-name', '--> emit from emitter on app1' ]
  events emitter on app1 handle "event-name" from "192.168.2.37:55761" with arguments +7s [ '--> emit from emitter on app2' ]

Open a new terminal window and run the second application:

$ DEBUG=events node app2.js

  events emitter on app2 new event emitter of the group 239.22.144.139 +0ms
  events emitter on app2 add listener for "event-name" to 239.22.144.139:30618 +3ms function (data) { console.log('listener on app2: ', data); }
  events emitter on app2 ready to emit event of the group 239.22.144.139 +3ms
  events emitter on app2 ready to handle "event-name" at 239.22.144.139:30618 +0ms
  events emitter on app2 emit "event-name" to 239.22.144.139:30618 +0ms [ 'event-name', '--> emit from emitter on app2' ]
  events emitter on app2 handle "event-name" from "192.168.2.37:55761" with arguments +2ms [ '--> emit from emitter on app2' ]
listener on app2:  --> emit from emitter on app2

On the first terminal window now you see a new line:

listener on app1:  --> emit from emitter on app2

As you can see, the event emitter.emit(...) on the app1.js is not handled because the emitter has the option loopback = false, whereas the event emitter.emit(...) on the app2.js is handled both in app2.js and app1.js (because when not specified the loopback parameter is true).

See the content of the example folder.

To avoid a node process to handle their own events listening only the events from another node process, you can set the EventEmitter as in the previous example or setting foreignOnly option on both EventEmitter:

// first application
var EventEmitter = require('multicast-events').EventEmitter;

var emitter = new EventEmitter({
  name: 'emitter on app1',
  foreignOnly: true
});
emitter.on('event-name', function (data) { console.log('listener on app1: ', data); });

// this event is handled only on the second application
emitter.emit('event-name', '--> emit from emitter on app1');

// second application
var EventEmitter = require('multicast-events').EventEmitter;

var emitter = new EventEmitter({
  name: 'emitter on app2',
  foreignOnly: true
});
emitter.on('event-name', function (data) { console.log('listener on app2: ', data); });

// this event is handled only on the first application
emitter.emit('event-name', '--> emit from emitter on app2');

Documentation

To create your own documentation you must install JSDuck and type in your terminal:

$ cd /path-of-package
$ ./gen_doc.sh

Run Tests

As usual I use mocha as test framework:

$ npm test