docs: function EventEmitter(opts) {
    opts = opts || {};
    this.name = opts.name || 'emitter #' + emitterCounter;  // for debug purpose
    emitterCounter++;
    this.id = opts.id || id;
    this.secure = !!opts.secure;
    this.cipher = opts.cipher || 'aes256';
    this.secret = opts.secret || 'secret';
    this.ttl = parseInt(opts.ttl || ttl, 10);
    // validate ttl
    if (this.ttl < ttlMin || this.ttl > ttlMax || isNaN(this.ttl)) {
      throw new Error(util.format('%s must have %d < ttl < %d', this.name, ttlMin, ttlMax));
    }
    this.interface = opts.interface;
    // validate multicast interface
    if (this.interface) {
      if (!verifyAddress(this.interface)) {
        throw new Error(util.format('%s does not have %s as a valid multicast interface', this.name, this.interface));
      }
    }
    if (opts.loopback === undefined || this.loopback === null) {
      this.loopback = true;
    } else {
      // ensure it is boolean
      this.loopback = !!(opts.loopback);
    }
    if (opts.foreignOnly === undefined || this.foreignOnly === null) {
      this.foreignOnly = false;
    } else {
      // ensure it is boolean
      this.foreignOnly = !!(opts.foreignOnly);
    }
    if (!this.loopback && this.foreignOnly) {
      throw new Error(util.format('%s can\'t listen foreign only events if loopback is false', this.name));
    }
    this.octet = opts.octet || octet;
    if (this.octet < octetMin || this.octet > octetMax) {
      throw new Error(util.format('%s must have %d < octet < %d as first octet for a valid multicast address', this.name, octetMin, octetMax));
    }
    this.port = opts.port || port;
    if (this.port < portMin || this.port > portMax) {
      throw new Error(util.format('%s must have %d < port < %d', this.name, portMin, portMax));
    }
    this.group = opts.group || group;
    if (isMulticastAddress(this.group)) {
      this.address = this.group;
    } else {
      var hash = md5(this.group);
      this.address = [this.octet,
                      hash.charCodeAt(0),
                      hash.charCodeAt(1),
                      (hash.charCodeAt(2) === 0 || hash.charCodeAt(2) === 255 ? 1 : hash.charCodeAt(2))
                     ].join('.');
    }
    this.events = opts.events || {};
    this.listeners = {};
  
    this.sender = dgram.createSocket('udp4');
    this.sender.on('error', function (err) {
      this.sender.close();
      var e = new Error(util.format('%s has encountered an event emitter error:\n', this.name));
      e.stack = err.stack;
      throw e;
    }.bind(this));
  
    this.sender.bind(function() {
      this.sender.setBroadcast(false);
      this.sender.setMulticastTTL(this.ttl);
      this.sender.setMulticastLoopback(this.loopback);
  
      debug('%s ready to emit event of the group %s', this.name, this.getAddress());
    }.bind(this));
    debug('%s new event emitter of the group %s', this.name, this.getAddress());
  }