Comparing version 0.7.8 to 0.8.0
{ | ||
"name": "sip.js", | ||
"version": "0.7.8", | ||
"version": "0.8.0", | ||
"authors": [ | ||
@@ -5,0 +5,0 @@ "James Criscuolo <james@onsip.com>", |
@@ -8,3 +8,3 @@ ## What you need to build SIP.js | ||
* [Install Node.js via package manager](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager) | ||
* [Install Node.js via package manager](https://github.com/nodejs/node/wiki) | ||
* [Install Node.js from sources](http://nodejs.org) | ||
@@ -32,7 +32,2 @@ | ||
Install grunt-cli globally: | ||
``` | ||
$ npm install -g grunt-cli | ||
``` | ||
Enter the directory and install the Node.js dependencies: | ||
@@ -43,18 +38,13 @@ ``` | ||
Make sure you have `grunt` installed by testing: | ||
Build and test | ||
``` | ||
$ grunt -version | ||
$ npm run build && npm run commandLineTest | ||
``` | ||
Finally, run `grunt` command with no arguments to get a complete version of SIP.js: | ||
``` | ||
$ grunt | ||
``` | ||
The built version of SIP.js will be available in the `dist/` subdirectory in both flavors: normal (uncompressed) and minified, both linted with [JSLint](http://jslint.com/). There are copies of each file with the version number in the title in that subdirectory as well | ||
The built version of SIP.js will be available in the `dist/` subdirectory in both flavors: normal (uncompressed) and minified, both linted with [JSLint](http://jslint.com/). There will be also a file named `dist/sip-devel.js` which is an exact copy of the uncompressed file. | ||
## Development version | ||
Run `grunt devel` for just generating the `dist/sip-devel.js` file. An uncompressed SIP.js source file named `sip-devel.js` will be created in `dist` directory. | ||
Run `npm run build` for just generating the `dist/sip.js` file. An uncompressed SIP.js source file named `sip.js` will be created in `dist` directory. | ||
@@ -64,5 +54,6 @@ | ||
SIP.js includes test units based on [Jasmine](http://pivotal.github.io/jasmine/). Test units use the `dist/sip-devel.js` file. Run the tests as follows: | ||
SIP.js includes test units based on [Jasmine](http://pivotal.github.io/jasmine/). Test units use the `dist/sip.js` file. Run the tests as follows: | ||
``` | ||
$ grunt test | ||
$ npm run commandLineTest | ||
$ npm run browserTest | ||
@@ -80,4 +71,3 @@ Running "jasmine:components" (jasmine) task | ||
``` | ||
$ grunt grammar | ||
$ npm run build | ||
``` | ||
And then build SIP.js again as explained above. |
@@ -5,3 +5,3 @@ { | ||
"description": "A simple, intuitive, and powerful JavaScript signaling library", | ||
"version": "0.7.8", | ||
"version": "0.8.0", | ||
"main": "src/index.js", | ||
@@ -30,24 +30,25 @@ "browser": { | ||
"devDependencies": { | ||
"beefy": "^2.1.5", | ||
"browserify": "^4.1.8", | ||
"grunt": "~0.4.0", | ||
"grunt-browserify": "^4.0.1", | ||
"grunt-cli": "~0.1.6", | ||
"grunt-contrib-copy": "^0.5.0", | ||
"grunt-contrib-jasmine": "^1.0.3", | ||
"grunt-contrib-jshint": ">0.5.0", | ||
"grunt-contrib-uglify": "~0.2.0", | ||
"grunt-peg": "~1.3.1", | ||
"grunt-trimtrailingspaces": "^0.4.0", | ||
"pegjs": "^0.8.0" | ||
"eslint": "^4.5.0", | ||
"eslint-loader": "^1.9.0", | ||
"jasmine-core": "^2.6.4", | ||
"karma": "^1.7.0", | ||
"karma-cli": "^1.0.1", | ||
"karma-jasmine": "^1.1.0", | ||
"karma-jasmine-html-reporter": "^0.2.2", | ||
"karma-mocha-reporter": "^2.2.3", | ||
"karma-phantomjs-launcher": "^1.0.4", | ||
"pegjs": "^0.10.0", | ||
"pegjs-loader": "^0.5.2", | ||
"uglifyjs-webpack-plugin": "^0.4.6", | ||
"webpack": "^3.5.5" | ||
}, | ||
"engines": { | ||
"node": ">=0.12" | ||
"node": ">=4.0" | ||
}, | ||
"license": "MIT", | ||
"scripts": { | ||
"repl": "beefy test/repl.js --open", | ||
"build": "grunt build", | ||
"prepublish": "cd src/Grammar && mkdir -p dist && pegjs --extra-options-file peg.json src/Grammar.pegjs dist/Grammar.js", | ||
"test": "grunt travis --verbose" | ||
"build": "webpack --progress && cp dist/sip.js dist/sip-$npm_package_version.js && cp dist/sip.min.js dist/sip-$npm_package_version.min.js", | ||
"browserTest": "sleep 2 && open http://0.0.0.0:9876/debug.html & karma start --reporters kjhtml --no-single-run", | ||
"commandLineTest": "karma start --reporters mocha --browsers PhantomJS --single-run", | ||
"buildAndTest": "npm run build && npm run commandLineTest" | ||
}, | ||
@@ -54,0 +55,0 @@ "dependencies": { |
@@ -49,6 +49,2 @@ "use strict"; | ||
self.dialog.uac_pending_reply = false; | ||
if (self.dialog.uas_pending_reply === false) { | ||
self.dialog.owner.onReadyToReinvite(); | ||
} | ||
} | ||
@@ -55,0 +51,0 @@ }); |
@@ -85,6 +85,2 @@ "use strict"; | ||
//RENDERBODY | ||
if (this.state === C.STATUS_EARLY && (!owner.hasOffer)) { | ||
this.mediaHandler = owner.mediaHandlerFactory(owner); | ||
} | ||
} | ||
@@ -117,4 +113,5 @@ | ||
this.logger.log('dialog ' + this.id.toString() + ' deleted'); | ||
if (this.mediaHandler && this.state !== C.STATUS_CONFIRMED) { | ||
this.mediaHandler.peerConnection.close(); | ||
if (this.sessionDescriptionHandler && this.state !== C.STATUS_CONFIRMED) { | ||
// TODO: This should call .close() on the handler when implemented | ||
this.sessionDescriptionHandler.close(); | ||
} | ||
@@ -177,4 +174,2 @@ delete this.owner.ua.dialogs[this.id.toString()]; | ||
return false; | ||
} else if(request.cseq > this.remote_seqnum) { | ||
this.remote_seqnum = request.cseq; | ||
} | ||
@@ -187,5 +182,6 @@ | ||
request.reply(491); | ||
} else if (this.uas_pending_reply === true) { | ||
} else if (this.uas_pending_reply === true && request.cseq > this.remote_seqnum) { | ||
var retryAfter = (Math.random() * 10 | 0) + 1; | ||
request.reply(500, null, ['Retry-After:' + retryAfter]); | ||
this.remote_seqnum = request.cseq; | ||
return false; | ||
@@ -201,6 +197,2 @@ } else { | ||
self.uas_pending_reply = false; | ||
if (self.uac_pending_reply === false) { | ||
self.owner.onReadyToReinvite(); | ||
} | ||
} | ||
@@ -231,2 +223,6 @@ }); | ||
if(request.cseq > this.remote_seqnum) { | ||
this.remote_seqnum = request.cseq; | ||
} | ||
return true; | ||
@@ -233,0 +229,0 @@ }, |
@@ -34,14 +34,4 @@ "use strict"; | ||
MediaStream: getPrefixedProperty(toplevel, 'MediaStream'), | ||
getUserMedia: getPrefixedProperty(toplevel.navigator, 'getUserMedia'), | ||
RTCPeerConnection: getPrefixedProperty(toplevel, 'RTCPeerConnection'), | ||
RTCSessionDescription: getPrefixedProperty(toplevel, 'RTCSessionDescription'), | ||
addEventListener: getPrefixedProperty(toplevel, 'addEventListener'), | ||
removeEventListener: getPrefixedProperty(toplevel, 'removeEventListener'), | ||
HTMLMediaElement: toplevel.HTMLMediaElement, | ||
attachMediaStream: toplevel.attachMediaStream, | ||
createObjectURL: toplevel.URL && toplevel.URL.createObjectURL, | ||
revokeObjectURL: toplevel.URL && toplevel.URL.revokeObjectURL | ||
removeEventListener: getPrefixedProperty(toplevel, 'removeEventListener') | ||
}; |
"use strict"; | ||
var NodeEventEmitter = require('events').EventEmitter; | ||
module.exports = function (console) { | ||
module.exports = function () { | ||
@@ -21,19 +21,4 @@ // Don't use `new SIP.EventEmitter()` for inheriting. | ||
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); | ||
} | ||
}; | ||
return EventEmitter; | ||
}; |
@@ -52,3 +52,13 @@ "use strict"; | ||
return exception; | ||
}()), | ||
RenegotiationError: (function(){ | ||
var exception = function(message) { | ||
this.code = 5; | ||
this.name = 'RENEGOTIATION_ERROR'; | ||
this.message = message; | ||
}; | ||
exception.prototype = new Error(); | ||
return exception; | ||
}()) | ||
}; |
"use strict"; | ||
var Grammar = require('./Grammar/dist/Grammar'); | ||
var Grammar = require('./Grammar/src/Grammar.pegjs'); | ||
@@ -4,0 +4,0 @@ module.exports = function (SIP) { |
## SIP Parser Grammar | ||
SIP uses [PEG.js](https://github.com/dmajda/pegjs) to build its parser grammar, a PEG based parser generator for JavaScript. | ||
SIP,js uses [PEG.js](https://github.com/dmajda/pegjs) to build its parser grammar, a PEG based parser generator for JavaScript. | ||
@@ -10,3 +10,2 @@ The grammar source is defined in PEG format in `src/Grammar.pegjs` file. It must be converted to JavaScript by using PEG.js | ||
In order to use the `pegjs` node command, install PEG.js globally: | ||
@@ -21,3 +20,3 @@ ``` | ||
* Automatically by running `grunt grammar` in the SIP root directory. | ||
* Automatically by running `npm run build` in the SIP.js root directory. | ||
* Manually by following steps below one by one: | ||
@@ -24,0 +23,0 @@ |
@@ -205,3 +205,5 @@ "use strict"; | ||
this.registered_before = this.registered; | ||
this.unregister(options); | ||
if (this.registered) { | ||
this.unregister(options); | ||
} | ||
}, | ||
@@ -215,4 +217,3 @@ | ||
if(!this.registered && !options.all) { | ||
this.logger.warn('already unregistered'); | ||
return; | ||
this.logger.warn('Already unregistered, but sending an unregister anyways.'); | ||
} | ||
@@ -219,0 +220,0 @@ |
@@ -24,3 +24,3 @@ /** | ||
SIP.LoggerFactory = require('./LoggerFactory')(environment.console); | ||
SIP.EventEmitter = require('./EventEmitter')(environment.console); | ||
SIP.EventEmitter = require('./EventEmitter')(); | ||
SIP.C = require('./Constants')(SIP.name, SIP.version); | ||
@@ -38,3 +38,3 @@ SIP.Exceptions = require('./Exceptions'); | ||
require('./RegisterContext')(SIP); | ||
SIP.MediaHandler = require('./MediaHandler')(SIP.EventEmitter); | ||
SIP.SessionDescriptionHandler = require('./SessionDescriptionHandler')(SIP.EventEmitter); | ||
require('./ClientContext')(SIP); | ||
@@ -44,10 +44,12 @@ require('./ServerContext')(SIP); | ||
require('./Subscription')(SIP); | ||
SIP.WebRTC = require('./WebRTC')(SIP, environment); | ||
require('./UA')(SIP, environment); | ||
SIP.Hacks = require('./Hacks')(SIP); | ||
require('./SanityCheck')(SIP); | ||
SIP.DigestAuthentication = require('./DigestAuthentication')(SIP.Utils); | ||
SIP.Grammar = require('./Grammar')(SIP); | ||
SIP.WebRTC = { | ||
Modifiers: require('./WebRTC/Modifiers')(SIP), | ||
Simple: require('./WebRTC/Simple')(SIP) | ||
}; | ||
return SIP; | ||
}; |
@@ -443,2 +443,3 @@ "use strict"; | ||
*/ | ||
// TODO: Get rid of callbacks and make promise based | ||
IncomingRequest.prototype.reply = function(code, reason, extraHeaders, body, onSuccess, onFailure) { | ||
@@ -445,0 +446,0 @@ var rr, vias, length, idx, response, |
@@ -33,2 +33,3 @@ "use strict"; | ||
} | ||
this.requestedExpires = this.expires; | ||
@@ -106,3 +107,3 @@ options.extraHeaders.push('Event: ' + this.event); | ||
if (expires && expires <= this.expires) { | ||
if (expires && expires <= this.requestedExpires) { | ||
// Preserve new expires value for subsequent requests | ||
@@ -109,0 +110,0 @@ this.expires = expires; |
@@ -232,22 +232,45 @@ "use strict"; | ||
InviteClientTransaction.prototype.sendACK = function(response) { | ||
var tr = this; | ||
InviteClientTransaction.prototype.sendACK = function(options) { | ||
// TODO: Move PRACK stuff into the transaction layer. That is really where it should be | ||
this.ack = 'ACK ' + this.request.ruri + ' SIP/2.0\r\n'; | ||
this.ack += 'Via: ' + this.request.headers['Via'].toString() + '\r\n'; | ||
var self = this, | ||
ruri; | ||
options = options || {}; | ||
if(this.request.headers['Route']) { | ||
this.ack += 'Route: ' + this.request.headers['Route'].toString() + '\r\n'; | ||
if (this.response.getHeader('contact')) { | ||
ruri = this.response.getHeader('contact').replace(/</g, '').replace(/>/g, ''); | ||
} else { | ||
ruri = this.request.ruri; | ||
} | ||
var ack = new SIP.OutgoingRequest( | ||
"ACK", | ||
ruri, | ||
this.request.ua, | ||
{ | ||
cseq: this.response.cseq, | ||
call_id: this.response.call_id, | ||
from_uri: this.response.from.uri, | ||
from_tag: this.response.from_tag, | ||
to_uri: this.response.to.uri, | ||
to_tag: this.response.to_tag, | ||
route_set: this.response.getHeaders('record-route').reverse() | ||
}, | ||
options.extraHeaders || [], | ||
options.body | ||
); | ||
this.ack += 'To: ' + response.getHeader('to') + '\r\n'; | ||
this.ack += 'From: ' + this.request.headers['From'].toString() + '\r\n'; | ||
this.ack += 'Call-ID: ' + this.request.headers['Call-ID'].toString() + '\r\n'; | ||
this.ack += 'Content-Length: 0\r\n'; | ||
this.ack += 'CSeq: ' + this.request.headers['CSeq'].toString().split(' ')[0]; | ||
this.ack += ' ACK\r\n\r\n'; | ||
this.ackSender = new SIP.RequestSender({ | ||
request: ack, | ||
onRequestTimeout: this.request_sender.applicant.applicant ? this.request_sender.applicant.applicant.onRequestTimeout : function() { | ||
self.logger.warn("ACK Request timed out"); | ||
}, | ||
onTransportError: this.request_sender.applicant.applicant ? this.request_sender.applicant.applicant.onRequestTransportError : function() { | ||
self.loigger.warn("ACK Request had a transport error"); | ||
}, | ||
receiveResponse: options.receiveResponse || function() { | ||
self.logger.warn("Received a response to an ACK which was unexpected. Dropping Response."); | ||
} | ||
}, this.request.ua).send(); | ||
this.D = SIP.Timers.setTimeout(tr.timer_D.bind(tr), SIP.Timers.TIMER_D); | ||
this.transport.send(this.ack); | ||
return ack; | ||
}; | ||
@@ -292,2 +315,16 @@ | ||
// This may create a circular dependency... | ||
response.transaction = this; | ||
if (this.response && | ||
this.response.status_code === response.status_code && | ||
this.response.cseq === response.cseq) { | ||
this.logger.debug("ICT Received a retransmission for cseq: " + response.cseq); | ||
if (this.ackSender) { | ||
this.ackSender.send(); | ||
} | ||
return; | ||
} | ||
this.response = response; | ||
if(status_code >= 100 && status_code <= 199) { | ||
@@ -323,7 +360,7 @@ switch(this.state) { | ||
this.stateChanged(C.STATUS_COMPLETED); | ||
this.sendACK(response); | ||
this.sendACK(); | ||
this.request_sender.receiveResponse(response); | ||
break; | ||
case C.STATUS_COMPLETED: | ||
this.sendACK(response); | ||
this.sendACK(); | ||
break; | ||
@@ -690,3 +727,2 @@ } | ||
} | ||
break; | ||
default: | ||
@@ -693,0 +729,0 @@ |
@@ -283,3 +283,3 @@ "use strict"; | ||
try { | ||
data = String.fromCharCode.apply(null, new Uint8Array(data)); | ||
data = String.fromCharCode.apply(null, Buffer.alloc(data)); | ||
} catch(evt) { | ||
@@ -348,3 +348,4 @@ this.logger.warn('received WebSocket binary message failed to be converted into string, message discarded'); | ||
onError: function(e) { | ||
this.logger.warn('WebSocket connection error: ' + JSON.stringify(e)); | ||
this.logger.warn('WebSocket connection error: '); | ||
this.logger.warn(e); | ||
}, | ||
@@ -351,0 +352,0 @@ |
181
src/UA.js
@@ -5,7 +5,7 @@ "use strict"; | ||
* @class Class creating a SIP User Agent. | ||
* @param {function returning SIP.MediaHandler} [configuration.mediaHandlerFactory] | ||
* A function will be invoked by each of the UA's Sessions to build the MediaHandler for that Session. | ||
* If no (or a falsy) value is provided, each Session will use a default (WebRTC) MediaHandler. | ||
* @param {function returning SIP.sessionDescriptionHandler} [configuration.sessionDescriptionHandlerFactory] | ||
* A function will be invoked by each of the UA's Sessions to build the sessionDescriptionHandler for that Session. | ||
* If no (or a falsy) value is provided, each Session will use a default (WebRTC) sessionDescriptionHandler. | ||
* | ||
* @param {Object} [configuration.media] gets passed to SIP.MediaHandler.getDescription as mediaHint | ||
* @param {Object} [configuration.media] gets passed to SIP.sessionDescriptionHandler.getDescription as mediaHint | ||
*/ | ||
@@ -231,3 +231,3 @@ module.exports = function (SIP, environment) { | ||
* @param {Object} views | ||
* @param {Object} [options.media] gets passed to SIP.MediaHandler.getDescription as mediaHint | ||
* @param {Object} [options.media] gets passed to SIP.sessionDescriptionHandler.getDescription as mediaHint | ||
* | ||
@@ -237,4 +237,4 @@ * @throws {TypeError} | ||
*/ | ||
UA.prototype.invite = function(target, options) { | ||
var context = new SIP.InviteClientContext(this, target, options); | ||
UA.prototype.invite = function(target, options, modifiers) { | ||
var context = new SIP.InviteClientContext(this, target, options, modifiers); | ||
@@ -596,3 +596,2 @@ this.afterConnected(context.invite.bind(context)); | ||
method = request.method, | ||
transaction, | ||
replaces, | ||
@@ -650,3 +649,3 @@ replacedDialog, | ||
// Let those methods pass through to normal processing for now. | ||
transaction = new SIP.ServerContext(this, request); | ||
new SIP.ServerContext(this, request); | ||
} | ||
@@ -678,13 +677,5 @@ | ||
var isMediaSupported = this.configuration.mediaHandlerFactory.isSupported; | ||
if(!isMediaSupported || isMediaSupported()) { | ||
session = new SIP.InviteServerContext(this, request); | ||
session.replacee = replacedDialog && replacedDialog.owner; | ||
session.on('invite', function() { | ||
self.emit('invite', this); | ||
}); | ||
} else { | ||
this.logger.warn('INVITE received but WebRTC is not supported'); | ||
request.reply(488); | ||
} | ||
session = new SIP.InviteServerContext(this, request); | ||
session.replacee = replacedDialog && replacedDialog.owner; | ||
self.emit('invite', session); | ||
break; | ||
@@ -936,6 +927,3 @@ case SIP.C.BYE: | ||
// Session parameters | ||
iceCheckingTimeout: 5000, | ||
noAnswerTimeout: 60, | ||
stunServers: ['stun:stun.l.google.com:19302'], | ||
turnServers: [], | ||
@@ -950,5 +938,11 @@ // Logging parameters | ||
hackAllowUnregisteredOptionTags: false, | ||
hackCleanJitsiSdpImageattr: false, | ||
hackStripTcp: false, | ||
// Session Description Handler Options | ||
sessionDescriptionHandlerFactoryOptions: { | ||
constraints: {}, | ||
iceCheckingTimeout: 5000, | ||
rtcConfiguration: {}, | ||
}, | ||
contactName: SIP.Utils.createRandomToken(8), // user name in user part | ||
contactTransport: 'ws', | ||
@@ -968,3 +962,3 @@ forceRport: false, | ||
mediaHandlerFactory: SIP.WebRTC.MediaHandler.defaultFactory, | ||
sessionDescriptionHandlerFactory: require('./WebRTC/SessionDescriptionHandler')(SIP).defaultFactory, | ||
@@ -975,3 +969,3 @@ authenticationFactory: checkAuthenticationFactory(function authenticationFactory (ua) { | ||
allowLegacyNotifications: false | ||
allowLegacyNotifications: false, | ||
}; | ||
@@ -1018,6 +1012,2 @@ | ||
SIP.Utils.optionsOverride(configuration, 'rel100', 'reliable', true, this.logger, SIP.C.supported.UNSUPPORTED); | ||
var emptyArraysAllowed = ['stunServers', 'turnServers']; | ||
// Check Optional parameters | ||
@@ -1030,3 +1020,3 @@ for(parameter in configCheck.optional) { | ||
// If the parameter value is an empty array, but shouldn't be, apply its default value. | ||
if (value instanceof Array && value.length === 0 && emptyArraysAllowed.indexOf(parameter) < 0) { continue; } | ||
if (value instanceof Array && value.length === 0) { continue; } | ||
@@ -1110,3 +1100,3 @@ // If the parameter value is null, empty string, or undefined then apply its default value. | ||
temp_gruu: null, | ||
uri: new SIP.URI('sip', SIP.Utils.createRandomToken(8), settings.viaHost, null, {transport: settings.contactTransport}), | ||
uri: new SIP.URI('sip', settings.contactName, settings.viaHost, null, {transport: settings.contactTransport}), | ||
toString: function(options){ | ||
@@ -1136,5 +1126,2 @@ options = options || {}; | ||
// media overrides mediaConstraints | ||
SIP.Utils.optionsOverride(settings, 'media', 'mediaConstraints', true, this.logger); | ||
var skeleton = {}; | ||
@@ -1157,3 +1144,3 @@ // Fill the value of the configuration_skeleton | ||
case 'registrarServer': | ||
case 'mediaHandlerFactory': | ||
case 'sessionDescriptionHandlerFactory': | ||
this.logger.log('· ' + parameter + ': ' + settings[parameter]); | ||
@@ -1308,8 +1295,2 @@ break; | ||
iceCheckingTimeout: function(iceCheckingTimeout) { | ||
if(SIP.Utils.isDecimal(iceCheckingTimeout)) { | ||
return Math.max(500, iceCheckingTimeout); | ||
} | ||
}, | ||
hackWssInTransport: function(hackWssInTransport) { | ||
@@ -1327,14 +1308,2 @@ if (typeof hackWssInTransport === 'boolean') { | ||
hackCleanJitsiSdpImageattr: function(hackCleanJitsiSdpImageattr) { | ||
if (typeof hackCleanJitsiSdpImageattr === 'boolean') { | ||
return hackCleanJitsiSdpImageattr; | ||
} | ||
}, | ||
hackStripTcp: function(hackStripTcp) { | ||
if (typeof hackStripTcp === 'boolean') { | ||
return hackStripTcp; | ||
} | ||
}, | ||
contactTransport: function(contactTransport) { | ||
@@ -1466,27 +1435,2 @@ if (typeof contactTransport === 'string') { | ||
stunServers: function(stunServers) { | ||
var idx, length, stun_server; | ||
if (typeof stunServers === 'string') { | ||
stunServers = [stunServers]; | ||
} else if (!(stunServers instanceof Array)) { | ||
return; | ||
} | ||
length = stunServers.length; | ||
for (idx = 0; idx < length; idx++) { | ||
stun_server = stunServers[idx]; | ||
if (!(/^stuns?:/.test(stun_server))) { | ||
stun_server = 'stun:' + stun_server; | ||
} | ||
if(SIP.Grammar.parse(stun_server, 'stun_URI') === -1) { | ||
return; | ||
} else { | ||
stunServers[idx] = stun_server; | ||
} | ||
} | ||
return stunServers; | ||
}, | ||
traceSip: function(traceSip) { | ||
@@ -1498,45 +1442,2 @@ if (typeof traceSip === 'boolean') { | ||
turnServers: function(turnServers) { | ||
var idx, jdx, length, turn_server, num_turn_server_urls, url; | ||
if (turnServers instanceof Array) { | ||
// Do nothing | ||
} else { | ||
turnServers = [turnServers]; | ||
} | ||
length = turnServers.length; | ||
for (idx = 0; idx < length; idx++) { | ||
turn_server = turnServers[idx]; | ||
//Backwards compatibility: Allow defining the turn_server url with the 'server' property. | ||
if (turn_server.server) { | ||
turn_server.urls = [turn_server.server]; | ||
} | ||
if (!turn_server.urls) { | ||
return; | ||
} | ||
if (turn_server.urls instanceof Array) { | ||
num_turn_server_urls = turn_server.urls.length; | ||
} else { | ||
turn_server.urls = [turn_server.urls]; | ||
num_turn_server_urls = 1; | ||
} | ||
for (jdx = 0; jdx < num_turn_server_urls; jdx++) { | ||
url = turn_server.urls[jdx]; | ||
if (!(/^turns?:/.test(url))) { | ||
url = 'turn:' + url; | ||
} | ||
if(SIP.Grammar.parse(url, 'turn_URI') === -1) { | ||
return; | ||
} | ||
} | ||
} | ||
return turnServers; | ||
}, | ||
rtcpMuxPolicy: function(rtcpMuxPolicy) { | ||
@@ -1592,23 +1493,11 @@ if (typeof rtcpMuxPolicy === 'string') { | ||
mediaHandlerFactory: function(mediaHandlerFactory) { | ||
if (mediaHandlerFactory instanceof Function) { | ||
var promisifiedFactory = function promisifiedFactory () { | ||
var mediaHandler = mediaHandlerFactory.apply(this, arguments); | ||
sessionDescriptionHandlerFactory: function(sessionDescriptionHandlerFactory) { | ||
if (sessionDescriptionHandlerFactory instanceof Function) { | ||
return sessionDescriptionHandlerFactory; | ||
} | ||
}, | ||
function patchMethod (methodName) { | ||
var method = mediaHandler[methodName]; | ||
if (method.length > 1) { | ||
var callbacksFirst = methodName === 'getDescription'; | ||
mediaHandler[methodName] = SIP.Utils.promisify(mediaHandler, methodName, callbacksFirst); | ||
} | ||
} | ||
patchMethod('getDescription'); | ||
patchMethod('setDescription'); | ||
return mediaHandler; | ||
}; | ||
promisifiedFactory.isSupported = mediaHandlerFactory.isSupported; | ||
return promisifiedFactory; | ||
sessionDescriptionHandlerFactoryOptions: function(options) { | ||
if (typeof options === 'object') { | ||
return options; | ||
} | ||
@@ -1629,2 +1518,8 @@ }, | ||
} | ||
}, | ||
contactName: function(contactName) { | ||
if (typeof contactName === 'string') { | ||
return contactName; | ||
} | ||
} | ||
@@ -1631,0 +1526,0 @@ } |
@@ -22,13 +22,7 @@ "use strict"; | ||
promisify: function promisify (object, methodName, callbacksFirst) { | ||
var oldMethod = object[methodName]; | ||
return function promisifiedMethod (arg, onSuccess, onFailure) { | ||
return new Utils.Promise(function (resolve, reject) { | ||
var oldArgs = [arg, resolve, reject]; | ||
if (callbacksFirst) { | ||
oldArgs = [resolve, reject, arg]; | ||
} | ||
oldMethod.apply(object, oldArgs); | ||
}).then(onSuccess, onFailure); | ||
}; | ||
reducePromises: function reducePromises(arr, val) { | ||
return arr.reduce(function(acc, fn) { | ||
acc = acc.then(fn); | ||
return acc; | ||
}, SIP.Utils.Promise.resolve(val)); | ||
}, | ||
@@ -182,9 +176,6 @@ | ||
target = SIP.C.SIP + ':' + SIP.Utils.escapeUser(target_user) + '@' + target_domain; | ||
// Finally parse the resulting URI. | ||
uri = SIP.URI.parse(target); | ||
// Finally parse the resulting URI. | ||
if (uri = SIP.URI.parse(target)) { | ||
return uri; | ||
} else { | ||
return; | ||
} | ||
return uri; | ||
} else { | ||
@@ -191,0 +182,0 @@ return; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
1596489
33727
1
0
0
13
53