Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIP.EventEmitter inherits from Node's EventEmitter #66

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions src/ClientContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,7 @@ var ClientContext;

ClientContext = function (ua, method, target, options) {
var params, extraHeaders,
originalTarget = target,
events = [
'progress',
'accepted',
'rejected',
'failed',
'cancel'
];
originalTarget = target;

if (target === undefined) {
throw new TypeError('Not enough arguments');
Expand Down Expand Up @@ -47,8 +40,6 @@ ClientContext = function (ua, method, target, options) {
}

this.data = {};

this.initEvents(events);
};
ClientContext.prototype = new SIP.EventEmitter();

Expand Down
2 changes: 1 addition & 1 deletion src/Dialog/RequestSender.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ RequestSender.prototype = {
this.state === SIP.Transactions.C.STATUS_COMPLETED ||
this.state === SIP.Transactions.C.STATUS_TERMINATED) {

this.off('stateChanged', stateChanged);
this.removeListener('stateChanged', stateChanged);
self.dialog.uac_pending_reply = false;

if (self.dialog.uas_pending_reply === false) {
Expand Down
3 changes: 1 addition & 2 deletions src/Dialogs.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ Dialog = function(owner, message, type, state) {
this.owner = owner;
owner.ua.dialogs[this.id.toString()] = this;
this.logger.log('new ' + type + ' dialog created with status ' + (this.state === C.STATUS_EARLY ? 'EARLY': 'CONFIRMED'));
owner.initMoreEvents(['dialog']);
owner.emit('dialog', this);
};

Expand Down Expand Up @@ -192,7 +191,7 @@ Dialog.prototype = {
this.state === SIP.Transactions.C.STATUS_COMPLETED ||
this.state === SIP.Transactions.C.STATUS_TERMINATED) {

this.off('stateChanged', stateChanged);
this.removeListener('stateChanged', stateChanged);
self.uas_pending_reply = false;

if (self.uac_pending_reply === false) {
Expand Down
219 changes: 27 additions & 192 deletions src/EventEmitter.js
Original file line number Diff line number Diff line change
@@ -1,200 +1,35 @@
/**
* @fileoverview EventEmitter
*/
var NodeEventEmitter = require('events').EventEmitter;

/**
* @augments SIP
* @class Class creating an event emitter.
*/
module.exports = function (SIP) {
var
EventEmitter,
logger = new SIP.LoggerFactory().getLogger('sip.eventemitter'),
C = {
MAX_LISTENERS: 10
};
module.exports = function (console) {

EventEmitter = function(){};
EventEmitter.prototype = {
/**
* Initialize events dictionaries.
* @param {Array} events
*/
initEvents: function(events) {
this.events = {};
function EventEmitter () {
NodeEventEmitter.call(this);
}

return this.initMoreEvents(events);
},

initMoreEvents: function(events) {
var idx;

if (!this.logger) {
this.logger = logger;
}

this.maxListeners = C.MAX_LISTENERS;

for (idx = 0; idx < events.length; idx++) {
if (!this.events[events[idx]]) {
this.logger.log('adding event '+ events[idx]);
this.events[events[idx]] = [];
} else {
this.logger.log('skipping event '+ events[idx]+ ' - Event exists');
}
}

return this;
},

/**
* Check whether an event exists or not.
* @param {String} event
* @returns {Boolean}
*/
checkEvent: function(event) {
return !!(this.events && this.events[event]);
},

/**
* Check whether an event exists and has at least one listener or not.
* @param {String} event
* @returns {Boolean}
*/
checkListener: function(event) {
return this.checkEvent(event) && this.events[event].length > 0;
},

/**
* Add a listener to the end of the listeners array for the specified event.
* @param {String} event
* @param {Function} listener
*/
on: function(event, listener, bindTarget) {
if (listener === undefined) {
return this;
} else if (typeof listener !== 'function') {
this.logger.error('listener must be a function');
return this;
} else if (!this.checkEvent(event)) {
this.logger.error('unable to add a listener to a nonexistent event '+ event);
throw new TypeError('Invalid or uninitialized event: ' + event);
}

var listenerObj = { listener: listener };
if (bindTarget) {
listenerObj.bindTarget = bindTarget;
}

if (this.events[event].length >= this.maxListeners) {
this.logger.warn('max listeners exceeded for event '+ event);
return this;
}

this.events[event].push(listenerObj);
this.logger.log('new listener added to event '+ event);
return this;
},

/**
* Add a one time listener for the specified event.
* The listener is invoked only the next time the event is fired, then it is removed.
* @param {String} event
* @param {Function} listener
*/
once: function(event, listener, bindTarget) {
var self = this;
function listenOnce () {
listener.apply(this, arguments);
self.off(event, listenOnce, bindTarget);
}

return this.on(event, listenOnce, bindTarget);
},

/**
* Remove a listener from the listener array for the specified event.
* Note that the order of the array elements will change after removing the listener
* @param {String} event
* @param {Function} listener
*/
off: function(event, listener, bindTarget) {
var events, length,
idx = 0;

if (listener && typeof listener !== 'function') {
this.logger.error('listener must be a function');
return this;
} else if (!event) {
for (idx in this.events) {
this.events[idx] = [];
}
return this;
} else if (!this.checkEvent(event)) {
this.logger.error('unable to remove a listener from a nonexistent event '+ event);
throw new TypeError('Invalid or uninitialized event: ' + event);
}

events = this.events[event];
length = events.length;

while (idx < length) {
if (events[idx] &&
(!listener || events[idx].listener === listener) &&
(!bindTarget || events[idx].bindTarget === bindTarget)) {
events.splice(idx,1);
} else {
idx ++;
}
}

return this;
},

/**
* By default EventEmitter will print a warning
* if more than C.MAX_LISTENERS listeners are added for a particular event.
* This function allows that limit to be modified.
* @param {Number} listeners
*/
setMaxListeners: function(listeners) {
if (typeof listeners !== 'number' || listeners < 0) {
this.logger.error('listeners must be a positive number');
return this;
}

this.maxListeners = listeners;
return this;
},

/**
* Execute each of the listeners in order with the supplied arguments.
* @param {String} events
* @param {Array} args
*/
emit: function(event) {
if (!this.checkEvent(event)) {
this.logger.error('unable to emit a nonexistent event '+ event);
throw new TypeError('Invalid or uninitialized event: ' + event);
}

this.logger.log('emitting event '+ event);

// Fire event listeners
var args = Array.prototype.slice.call(arguments, 1);
this.events[event].slice().forEach(function (listener) {
try {
listener.listener.apply(listener.bindTarget || this, args);
} catch(err) {
this.logger.error(err.stack);
}
}, this);

return this;
EventEmitter.prototype = Object.create(NodeEventEmitter.prototype, {
constructor: {
value: EventEmitter,
enumerable: false,
writable: true,
configurable: true
}
});

EventEmitter.prototype.off = function off (eventName, listener) {
var warning = '';
warning += 'SIP.EventEmitter#off is deprecated and may be removed in future SIP.js versions.\n';
warning += 'Please use removeListener or removeAllListeners instead.\n';
warning += 'See here for more details:\n';
warning += 'http://nodejs.org/api/events.html#events_emitter_removelistener_event_listener';
console.warn(warning);

if (arguments.length < 2) {
return this.removeAllListeners.apply(this, arguments);
} else {
return this.removeListener(eventName, listener);
}
};

EventEmitter.C = C;
return EventEmitter;

SIP.EventEmitter = EventEmitter;
};
7 changes: 1 addition & 6 deletions src/RegisterContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ var RegisterContext;

RegisterContext = function (ua) {
var params = {},
regId = 1,
events = [
'registered',
'unregistered'
];
regId = 1;

this.registrar = ua.configuration.registrarServer;
this.expires = ua.configuration.registerExpires;
Expand Down Expand Up @@ -42,7 +38,6 @@ RegisterContext = function (ua) {
this.registered = false;

this.logger = ua.getLogger('sip.registercontext');
this.initMoreEvents(events);
};

RegisterContext.prototype = {
Expand Down
2 changes: 1 addition & 1 deletion src/SIP.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Object.defineProperties(SIP, {

require('./Utils')(SIP, environment);
SIP.LoggerFactory = require('./LoggerFactory')(environment.console);
require('./EventEmitter')(SIP);
SIP.EventEmitter = require('./EventEmitter')(environment.console);
SIP.C = require('./Constants')(SIP.name, SIP.version);
SIP.Exceptions = require('./Exceptions');
SIP.Timers = require('./Timers')(environment.timers);
Expand Down
8 changes: 0 additions & 8 deletions src/ServerContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@ module.exports = function (SIP) {
var ServerContext;

ServerContext = function (ua, request) {
var events = [
'progress',
'accepted',
'rejected',
'failed'
];
this.ua = ua;
this.logger = ua.getLogger('sip.servercontext');
this.request = request;
Expand All @@ -29,8 +23,6 @@ ServerContext = function (ua, request) {

this.localIdentity = request.to;
this.remoteIdentity = request.from;

this.initEvents(events);
};

ServerContext.prototype = new SIP.EventEmitter();
Expand Down
Loading