diff --git a/bigbluebutton-client/resources/prod/BigBlueButton.html b/bigbluebutton-client/resources/prod/BigBlueButton.html
index 1863137962..eb2cbb062b 100755
--- a/bigbluebutton-client/resources/prod/BigBlueButton.html
+++ b/bigbluebutton-client/resources/prod/BigBlueButton.html
@@ -43,7 +43,7 @@
-
+
@@ -101,7 +101,7 @@
diff --git a/bigbluebutton-client/resources/prod/lib/bbb_webrtc_bridge_jssip.js b/bigbluebutton-client/resources/prod/lib/bbb_webrtc_bridge_jssip.js
index ab2405a8f9..a7462ae0ba 100755
--- a/bigbluebutton-client/resources/prod/lib/bbb_webrtc_bridge_jssip.js
+++ b/bigbluebutton-client/resources/prod/lib/bbb_webrtc_bridge_jssip.js
@@ -34,7 +34,7 @@ function webrtc_call(username, voiceBridge, server, callback) {
register: false,
// register_expires: null,
// no_answer_timeout: null,
- trace_sip: true,
+ trace_sip: false,
stun_servers: "stun:74.125.134.127:19302",
// turn_servers: null,
// use_preloaded_route: null,
@@ -91,7 +91,7 @@ function webrtc_call(username, voiceBridge, server, callback) {
remoteView.src = window.URL.createObjectURL(rtcSession.getRemoteStreams()[0]);
remoteStream = true;
}
- callback({'status':'started', 'localStream': localStream, 'remoteStream': remoteStream});
+ callback({'status':'started', 'localStream': localStream, 'remoteStream': remoteStream});
}
};
diff --git a/bigbluebutton-client/resources/prod/lib/jssip-0.4.0-devel.js b/bigbluebutton-client/resources/prod/lib/jssip-0.3.7.js
similarity index 84%
rename from bigbluebutton-client/resources/prod/lib/jssip-0.4.0-devel.js
rename to bigbluebutton-client/resources/prod/lib/jssip-0.3.7.js
index c38c3eabe4..4868eb9a1c 100755
--- a/bigbluebutton-client/resources/prod/lib/jssip-0.4.0-devel.js
+++ b/bigbluebutton-client/resources/prod/lib/jssip-0.3.7.js
@@ -1,21530 +1,19313 @@
-/*
- * JsSIP version 0.4.0-devel
- * Copyright (c) 2012-2014 José Luis Millán - Versatica
- * Homepage: http://jssip.net
- * License: http://jssip.net/license
- */
-
-
-/*global console: false*/
-
-/**
- * @name JsSIP
- * @namespace
- */
-(function(window) {
-
-var JsSIP = (function() {
- "use strict";
-
- var JsSIP = {};
-
- Object.defineProperties(JsSIP, {
- version: {
- get: function(){ return '0.4.0-devel'; }
- },
- name: {
- get: function(){ return 'JsSIP'; }
- }
- });
-
- return JsSIP;
-}());
-
-
-
-(function(JsSIP) {
-
-var Logger =
-(function() {
-
-var Logger = function(logger, category, label) {
- this.logger = logger;
- this.category = category;
- this.label = label;
-};
-
-
-Logger.prototype.debug = function(content) {
- this.logger.debug(this.category, this.label, content);
-};
-
-Logger.prototype.log = function(content) {
- this.logger.log(this.category, this.label, content);
-};
-
-Logger.prototype.warn = function(content) {
- this.logger.warn(this.category, this.label, content);
-};
-
-Logger.prototype.error = function(content) {
- this.logger.error(this.category, this.label, content);
-};
-
-return Logger;
-}());
-
-
-var LoggerFactory = function() {
- var logger,
- levels = {
- 'error': 0,
- 'warn': 1,
- 'log': 2,
- 'debug': 3
- },
-
- level = 2,
- builtinEnabled = true,
- connector = null;
-
- this.loggers = {};
-
- logger = this.getLogger('jssip.loggerfactory');
-
-
- Object.defineProperties(this, {
- builtinEnabled: {
- get: function(){ return builtinEnabled; },
- set: function(value){
- if (typeof value === 'boolean') {
- builtinEnabled = value;
- } else {
- logger.error('invalid "builtinEnabled" parameter value: '+ window.JSON.stringify(value));
- }
- }
- },
-
- level: {
- get: function() {return level; },
- set: function(value) {
- if (value >= 0 && value <=3) {
- level = value;
- } else if (value > 3) {
- level = 3;
- } else if (levels.hasOwnProperty(value)) {
- level = levels[value];
- } else {
- logger.error('invalid "level" parameter value: '+ window.JSON.stringify(value));
- }
- }
- },
-
- connector: {
- get: function() {return connector; },
- set: function(value){
- if(value === null || value === "" || value === undefined) {
- connector = null;
- } else if (typeof value === 'function') {
- connector = value;
- } else {
- logger.error('invalid "connector" parameter value: '+ window.JSON.stringify(value));
- }
- }
- }
- });
-};
-
-LoggerFactory.prototype.print = function(target, category, label, content) {
- var prefix = [];
-
- prefix.push(new Date());
-
- prefix.push(category);
-
- if (label) {
- prefix.push(label);
- }
-
- prefix.push('');
-
- if (typeof content === 'string') {
- target.call(console, prefix.join(' | ') + content);
- } else {
- target.call(console, content);
- }
-};
-
-LoggerFactory.prototype.debug = function(category, label, content) {
- if (this.level === 3) {
- if (this.builtinEnabled) {
- this.print(console.debug, category, label, content);
- }
-
- if (this.connector) {
- this.connector('debug', category, label, content);
- }
- }
-};
-
-LoggerFactory.prototype.log = function(category, label, content) {
- if (this.level >= 2) {
- if (this.builtinEnabled) {
- this.print(console.log, category, label, content);
- }
-
- if (this.connector) {
- this.connector('log', category, label, content);
- }
- }
-};
-
-LoggerFactory.prototype.warn = function(category, label, content) {
- if (this.level >= 1) {
- if (this.builtinEnabled) {
- this.print(console.warn, category, label, content);
- }
-
- if (this.connector) {
- this.connector('warn', category, label, content);
- }
- }
-};
-
-LoggerFactory.prototype.error = function(category, label, content) {
- if (this.builtinEnabled) {
- this.print(console.error,category, label, content);
- }
-
- if (this.connector) {
- this.connector('error', category, label, content);
- }
-};
-
-LoggerFactory.prototype.getLogger = function(category, label) {
- var logger;
-
- if (label && this.level === 3) {
- return new Logger(this, category, label);
- } else if (this.loggers[category]) {
- return this.loggers[category];
- } else {
- logger = new Logger(this, category);
- this.loggers[category] = logger;
- return logger;
- }
-};
-
-JsSIP.LoggerFactory = LoggerFactory;
-}(JsSIP));
-
-
-/**
- * @fileoverview EventEmitter
- */
-
-/**
- * @augments JsSIP
- * @class Class creating an event emitter.
- */
-(function(JsSIP) {
-var
- EventEmitter,
- Event,
- logger = new JsSIP.LoggerFactory().getLogger('jssip.eventemitter'),
- C = {
- MAX_LISTENERS: 10
- };
-
-EventEmitter = function(){};
-EventEmitter.prototype = {
- /**
- * Initialize events dictionaries.
- * @param {Array} events
- */
- initEvents: function(events) {
- var idx;
-
- if (!this.logger) {
- this.logger = logger;
- }
-
- this.maxListeners = C.MAX_LISTENERS;
-
- this.events = {};
- this.oneTimeListeners = {};
-
- for (idx in events) {
- this.events[events[idx]] = [];
- this.oneTimeListeners[events[idx]] = [];
- }
- },
-
- /**
- * Check whether an event exists or not.
- * @param {String} event
- * @returns {Boolean}
- */
- checkEvent: function(event) {
- return !!this.events[event];
- },
-
- /**
- * Add a listener to the end of the listeners array for the specified event.
- * @param {String} event
- * @param {Function} listener
- */
- addListener: function(event, listener) {
- if (listener === undefined) {
- return;
- } else if (typeof listener !== 'function') {
- this.logger.error('listener must be a function');
- return;
- } else if (!this.checkEvent(event)) {
- this.logger.error('unable to add a listener to a nonexistent event'+ event);
- return;
- }
-
- if (this.events[event].length >= this.maxListeners) {
- this.logger.warn('max listeners exceeded for event '+ event);
- }
-
- this.events[event].push(listener);
- },
-
- on: function(event, listener) {
- this.addListener(event, listener);
- },
-
- /**
- * 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) {
- this.on(event, listener);
- this.oneTimeListeners[event].push(listener);
- },
-
- /**
- * 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
- */
- removeListener: function(event, listener) {
- var events, length,
- idx = 0;
-
- if (listener === undefined) {
- return;
- } else if (typeof listener !== 'function') {
- this.logger.error('listener must be a function');
- } else if (!this.checkEvent(event)) {
- this.logger.error('unable to remove a listener from a nonexistent event'+ event);
- return;
- }
-
- events = this.events[event];
- length = events.length;
-
- while (idx < length) {
- if (events[idx] === listener) {
- events.splice(idx,1);
- } else {
- idx ++;
- }
- }
- },
-
- /**
- * Remove all listeners from the listener array for the specified event.
- * @param {String} event
- */
- removeAllListener: function(event) {
- if (!this.checkEvent(event)) {
- this.logger.error('unable to remove listeners from a nonexistent event'+ event);
- return;
- }
-
- this.events[event] = [];
- this.oneTimeListeners[event] = [];
- },
-
- /**
- * 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.maxListeners = listeners;
- },
-
- /**
- * Get the listeners for a specific event.
- * @param {String} event
- * @returns {Array} Array of listeners for the specified event.
- */
- listeners: function(event) {
- if (!this.checkEvent(event)) {
- this.logger.error('no event '+ event);
- return;
- }
-
- return this.events[event];
- },
-
- /**
- * Execute each of the listeners in order with the supplied arguments.
- * @param {String} events
- * @param {Array} args
- */
- emit: function(event, sender, data) {
- var listeners, e, idx;
-
- if (!this.checkEvent(event)) {
- this.logger.error('unable to emit a nonexistent event'+ event);
- return;
- }
-
- this.logger.log('emitting event '+ event);
-
- listeners = this.events[event];
-
- e = new JsSIP.Event(event, sender, data);
-
- listeners.forEach(function (callback) {
- try {
- callback.call(null, e);
- } catch(err) {
- this.logger.error(err.stack);
- }
- });
-
- // Remove one time listeners
- for (idx in this.oneTimeListeners[event]) {
- this.removeListener(event, this.oneTimeListeners[event][idx]);
- }
-
- this.oneTimeListeners[event] = [];
- }
-};
-
-Event = function(type, sender, data) {
- this.type = type;
- this.sender= sender;
- this.data = data;
-};
-
-EventEmitter.C = C;
-
-JsSIP.EventEmitter = EventEmitter;
-JsSIP.Event = Event;
-}(JsSIP));
-
-
-/**
- * @fileoverview JsSIP Constants
- */
-
-/**
- * JsSIP Constants.
- * @augments JsSIP
- */
-
-JsSIP.C= {
- USER_AGENT: JsSIP.name +' '+ JsSIP.version,
-
- // SIP scheme
- SIP: 'sip',
- SIPS: 'sips',
-
- // End and Failure causes
- causes: {
- // Generic error causes
- CONNECTION_ERROR: 'Connection Error',
- REQUEST_TIMEOUT: 'Request Timeout',
- SIP_FAILURE_CODE: 'SIP Failure Code',
- INTERNAL_ERROR: 'Internal Error',
-
- // SIP error causes
- BUSY: 'Busy',
- REJECTED: 'Rejected',
- REDIRECTED: 'Redirected',
- UNAVAILABLE: 'Unavailable',
- NOT_FOUND: 'Not Found',
- ADDRESS_INCOMPLETE: 'Address Incomplete',
- INCOMPATIBLE_SDP: 'Incompatible SDP',
- AUTHENTICATION_ERROR: 'Authentication Error',
- DIALOG_ERROR: 'Dialog Error',
-
- // Session error causes
- WEBRTC_NOT_SUPPORTED: 'WebRTC Not Supported',
- WEBRTC_ERROR: 'WebRTC Error',
- CANCELED: 'Canceled',
- NO_ANSWER: 'No Answer',
- EXPIRES: 'Expires',
- NO_ACK: 'No ACK',
- USER_DENIED_MEDIA_ACCESS: 'User Denied Media Access',
- BAD_MEDIA_DESCRIPTION: 'Bad Media Description',
- RTP_TIMEOUT: 'RTP Timeout'
- },
-
- SIP_ERROR_CAUSES: {
- REDIRECTED: [300,301,302,305,380],
- BUSY: [486,600],
- REJECTED: [403,603],
- NOT_FOUND: [404,604],
- UNAVAILABLE: [480,410,408,430],
- ADDRESS_INCOMPLETE: [484],
- INCOMPATIBLE_SDP: [488,606],
- AUTHENTICATION_ERROR:[401,407]
- },
-
- // SIP Methods
- ACK: 'ACK',
- BYE: 'BYE',
- CANCEL: 'CANCEL',
- INFO: 'INFO',
- INVITE: 'INVITE',
- MESSAGE: 'MESSAGE',
- NOTIFY: 'NOTIFY',
- OPTIONS: 'OPTIONS',
- REGISTER: 'REGISTER',
- UPDATE: 'UPDATE',
- SUBSCRIBE: 'SUBSCRIBE',
-
- /* SIP Response Reasons
- * DOC: http://www.iana.org/assignments/sip-parameters
- * Copied from https://github.com/versatica/OverSIP/blob/master/lib/oversip/sip/constants.rb#L7
- */
- REASON_PHRASE: {
- 100: 'Trying',
- 180: 'Ringing',
- 181: 'Call Is Being Forwarded',
- 182: 'Queued',
- 183: 'Session Progress',
- 199: 'Early Dialog Terminated', // draft-ietf-sipcore-199
- 200: 'OK',
- 202: 'Accepted', // RFC 3265
- 204: 'No Notification', //RFC 5839
- 300: 'Multiple Choices',
- 301: 'Moved Permanently',
- 302: 'Moved Temporarily',
- 305: 'Use Proxy',
- 380: 'Alternative Service',
- 400: 'Bad Request',
- 401: 'Unauthorized',
- 402: 'Payment Required',
- 403: 'Forbidden',
- 404: 'Not Found',
- 405: 'Method Not Allowed',
- 406: 'Not Acceptable',
- 407: 'Proxy Authentication Required',
- 408: 'Request Timeout',
- 410: 'Gone',
- 412: 'Conditional Request Failed', // RFC 3903
- 413: 'Request Entity Too Large',
- 414: 'Request-URI Too Long',
- 415: 'Unsupported Media Type',
- 416: 'Unsupported URI Scheme',
- 417: 'Unknown Resource-Priority', // RFC 4412
- 420: 'Bad Extension',
- 421: 'Extension Required',
- 422: 'Session Interval Too Small', // RFC 4028
- 423: 'Interval Too Brief',
- 428: 'Use Identity Header', // RFC 4474
- 429: 'Provide Referrer Identity', // RFC 3892
- 430: 'Flow Failed', // RFC 5626
- 433: 'Anonymity Disallowed', // RFC 5079
- 436: 'Bad Identity-Info', // RFC 4474
- 437: 'Unsupported Certificate', // RFC 4744
- 438: 'Invalid Identity Header', // RFC 4744
- 439: 'First Hop Lacks Outbound Support', // RFC 5626
- 440: 'Max-Breadth Exceeded', // RFC 5393
- 469: 'Bad Info Package', // draft-ietf-sipcore-info-events
- 470: 'Consent Needed', // RFC 5360
- 478: 'Unresolvable Destination', // Custom code copied from Kamailio.
- 480: 'Temporarily Unavailable',
- 481: 'Call/Transaction Does Not Exist',
- 482: 'Loop Detected',
- 483: 'Too Many Hops',
- 484: 'Address Incomplete',
- 485: 'Ambiguous',
- 486: 'Busy Here',
- 487: 'Request Terminated',
- 488: 'Not Acceptable Here',
- 489: 'Bad Event', // RFC 3265
- 491: 'Request Pending',
- 493: 'Undecipherable',
- 494: 'Security Agreement Required', // RFC 3329
- 500: 'Server Internal Error',
- 501: 'Not Implemented',
- 502: 'Bad Gateway',
- 503: 'Service Unavailable',
- 504: 'Server Time-out',
- 505: 'Version Not Supported',
- 513: 'Message Too Large',
- 580: 'Precondition Failure', // RFC 3312
- 600: 'Busy Everywhere',
- 603: 'Decline',
- 604: 'Does Not Exist Anywhere',
- 606: 'Not Acceptable'
- }
-};
-
-
-/**
- * @fileoverview Exceptions
- */
-
-/**
- * JsSIP Exceptions.
- * @augments JsSIP
- */
-(function(JsSIP) {
-var Exceptions;
-
-Exceptions= {
- ConfigurationError: (function(){
- var exception = function(parameter, value) {
- this.code = 1;
- this.name = 'CONFIGURATION_ERROR';
- this.parameter = parameter;
- this.value = value;
- this.message = (!this.value)? 'Missing parameter: '+ this.parameter : 'Invalid value '+ window.JSON.stringify(this.value) +' for parameter "'+ this.parameter +'"';
- };
- exception.prototype = new Error();
- return exception;
- }()),
-
- InvalidStateError: (function(){
- var exception = function(status) {
- this.code = 2;
- this.name = 'INVALID_STATE_ERROR';
- this.status = status;
- this.message = 'Invalid status: '+ status;
- };
- exception.prototype = new Error();
- return exception;
- }()),
-
- NotSupportedError: (function(){
- var exception = function(message) {
- this.code = 3;
- this.name = 'NOT_SUPPORTED_ERROR';
- this.message = message;
- };
- exception.prototype = new Error();
- return exception;
- }()),
-
- NotReadyError: (function(){
- var exception = function(message) {
- this.code = 4;
- this.name = 'NOT_READY_ERROR';
- this.message = message;
- };
- exception.prototype = new Error();
- return exception;
- }())
-};
-
-JsSIP.Exceptions = Exceptions;
-}(JsSIP));
-
-/**
- * @fileoverview SIP TIMERS
- */
-
-/**
- * @augments JsSIP
- */
-(function(JsSIP) {
-var Timers,
- T1 = 500,
- T2 = 4000,
- T4 = 5000;
-
-Timers = {
- T1: T1,
- T2: T2,
- T4: T4,
- TIMER_B: 64 * T1,
- TIMER_D: 0 * T1,
- TIMER_F: 64 * T1,
- TIMER_H: 64 * T1,
- TIMER_I: 0 * T1,
- TIMER_J: 0 * T1,
- TIMER_K: 0 * T4,
- TIMER_L: 64 * T1,
- TIMER_M: 64 * T1,
- PROVISIONAL_RESPONSE_INTERVAL: 60000 // See RFC 3261 Section 13.3.1.1
-};
-
-JsSIP.Timers = Timers;
-}(JsSIP));
-
-
-/**
- * @fileoverview Transport
- */
-
-/**
- * @augments JsSIP
- * @class Transport
- * @param {JsSIP.UA} ua
- * @param {Object} server ws_server Object
- */
-(function(JsSIP) {
-var Transport,
- C = {
- // Transport status codes
- STATUS_READY: 0,
- STATUS_DISCONNECTED: 1,
- STATUS_ERROR: 2
- };
-
-Transport = function(ua, server) {
-
- this.logger = ua.getLogger('jssip.transport');
- this.ua = ua;
- this.ws = null;
- this.server = server;
- this.reconnection_attempts = 0;
- this.closed = false;
- this.connected = false;
- this.reconnectTimer = null;
- this.lastTransportError = {};
-
- this.ua.transport = this;
-
- // Connect
- this.connect();
-};
-
-Transport.prototype = {
- /**
- * Send a message.
- * @param {JsSIP.OutgoingRequest|String} msg
- * @returns {Boolean}
- */
- send: function(msg) {
- var message = msg.toString();
-
- if(this.ws && this.ws.readyState === WebSocket.OPEN) {
- if (this.ua.configuration.trace_sip === true) {
- this.logger.log('sending WebSocket message:\n\n' + message + '\n');
- }
- this.ws.send(message);
- return true;
- } else {
- this.logger.warn('unable to send message, WebSocket is not open');
- return false;
- }
- },
-
- /**
- * Disconnect socket.
- */
- disconnect: function() {
- if(this.ws) {
- // Clear reconnectTimer
- window.clearTimeout(this.reconnectTimer);
-
- this.closed = true;
- this.logger.log('closing WebSocket ' + this.server.ws_uri);
- this.ws.close();
- }
-
- if (this.reconnectTimer !== null) {
- window.clearTimeout(this.reconnectTimer);
- this.reconnectTimer = null;
- this.ua.emit('disconnected', this.ua, {
- transport: this,
- code: this.lastTransportError.code,
- reason: this.lastTransportError.reason
- });
- }
- },
-
- /**
- * Connect socket.
- */
- connect: function() {
- var transport = this;
-
- if(this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {
- this.logger.log('WebSocket ' + this.server.ws_uri + ' is already connected');
- return false;
- }
-
- if(this.ws) {
- this.ws.close();
- }
-
- this.logger.log('connecting to WebSocket ' + this.server.ws_uri);
- this.ua.onTransportConnecting(this,
- (this.reconnection_attempts === 0)?1:this.reconnection_attempts);
-
- try {
- this.ws = new WebSocket(this.server.ws_uri, 'sip');
-
- this.ws.binaryType = 'arraybuffer';
-
- this.ws.onopen = function() {
- transport.onOpen();
- };
-
- this.ws.onclose = function(e) {
- transport.onClose(e);
- };
-
- this.ws.onmessage = function(e) {
- transport.onMessage(e);
- };
-
- this.ws.onerror = function(e) {
- transport.onError(e);
- };
- } catch(e) {
- this.logger.warn('error connecting to WebSocket ' + this.server.ws_uri + ': ' + e);
- this.lastTransportError.code = null;
- this.lastTransportError.reason = e.message;
- this.ua.onTransportError(this);
- }
- },
-
- // Transport Event Handlers
-
- /**
- * @event
- * @param {event} e
- */
- onOpen: function() {
- this.connected = true;
-
- this.logger.log('WebSocket ' + this.server.ws_uri + ' connected');
- // Clear reconnectTimer since we are not disconnected
- if (this.reconnectTimer !== null) {
- window.clearTimeout(this.reconnectTimer);
- this.reconnectTimer = null;
- }
- // Reset reconnection_attempts
- this.reconnection_attempts = 0;
- // Disable closed
- this.closed = false;
- // Trigger onTransportConnected callback
- this.ua.onTransportConnected(this);
- },
-
- /**
- * @event
- * @param {event} e
- */
- onClose: function(e) {
- var connected_before = this.connected;
-
- this.connected = false;
- this.lastTransportError.code = e.code;
- this.lastTransportError.reason = e.reason;
- this.logger.log('WebSocket disconnected (code: ' + e.code + (e.reason? '| reason: ' + e.reason : '') +')');
-
- if(e.wasClean === false) {
- this.logger.warn('WebSocket abrupt disconnection');
- }
- // Transport was connected
- if(connected_before === true) {
- this.ua.onTransportClosed(this);
- // Check whether the user requested to close.
- if(!this.closed) {
- this.reConnect();
- } else {
- this.ua.emit('disconnected', this.ua, {
- transport: this,
- code: this.lastTransportError.code,
- reason: this.lastTransportError.reason
- });
- }
- } else {
- // This is the first connection attempt
- //Network error
- this.ua.onTransportError(this);
- }
- },
-
- /**
- * @event
- * @param {event} e
- */
- onMessage: function(e) {
- var message, transaction,
- data = e.data;
-
- // CRLF Keep Alive response from server. Ignore it.
- if(data === '\r\n') {
- if (this.ua.configuration.trace_sip === true) {
- this.logger.log('received WebSocket message with CRLF Keep Alive response');
- }
- return;
- }
-
- // WebSocket binary message.
- else if (typeof data !== 'string') {
- try {
- data = String.fromCharCode.apply(null, new Uint8Array(data));
- } catch(evt) {
- this.logger.warn('received WebSocket binary message failed to be converted into string, message discarded');
- return;
- }
-
- if (this.ua.configuration.trace_sip === true) {
- this.logger.log('received WebSocket binary message:\n\n' + data + '\n');
- }
- }
-
- // WebSocket text message.
- else {
- if (this.ua.configuration.trace_sip === true) {
- this.logger.log('received WebSocket text message:\n\n' + data + '\n');
- }
- }
-
- message = JsSIP.Parser.parseMessage(data, this.ua);
-
- if (!message) {
- return;
- }
-
- if(this.ua.status === JsSIP.UA.C.STATUS_USER_CLOSED && message instanceof JsSIP.IncomingRequest) {
- return;
- }
-
- // Do some sanity check
- if(JsSIP.sanityCheck(message, this.ua, this)) {
- if(message instanceof JsSIP.IncomingRequest) {
- message.transport = this;
- this.ua.receiveRequest(message);
- } else if(message instanceof JsSIP.IncomingResponse) {
- /* Unike stated in 18.1.2, if a response does not match
- * any transaction, it is discarded here and no passed to the core
- * in order to be discarded there.
- */
- switch(message.method) {
- case JsSIP.C.INVITE:
- transaction = this.ua.transactions.ict[message.via_branch];
- if(transaction) {
- transaction.receiveResponse(message);
- }
- break;
- case JsSIP.C.ACK:
- // Just in case ;-)
- break;
- default:
- transaction = this.ua.transactions.nict[message.via_branch];
- if(transaction) {
- transaction.receiveResponse(message);
- }
- break;
- }
- }
- }
- },
-
- /**
- * @event
- * @param {event} e
- */
- onError: function(e) {
- this.logger.warn('WebSocket connection error: ' + e);
- },
-
- /**
- * Reconnection attempt logic.
- * @private
- */
- reConnect: function() {
- var transport = this;
-
- this.reconnection_attempts += 1;
-
- if(this.reconnection_attempts > this.ua.configuration.ws_server_max_reconnection) {
- this.logger.warn('maximum reconnection attempts for WebSocket ' + this.server.ws_uri);
- this.ua.onTransportError(this);
- } else {
- this.logger.log('trying to reconnect to WebSocket ' + this.server.ws_uri + ' (reconnection attempt ' + this.reconnection_attempts + ')');
-
- this.reconnectTimer = window.setTimeout(function() {
- transport.connect();
- transport.reconnectTimer = null;
- }, this.ua.configuration.ws_server_reconnection_timeout * 1000);
- }
- }
-};
-
-Transport.C = C;
-JsSIP.Transport = Transport;
-}(JsSIP));
-
-
-/**
- * @fileoverview SIP Message Parser
- */
-
-/**
- * Extract and parse every header of a SIP message.
- * @augments JsSIP
- * @namespace
- */
-(function(JsSIP) {
-var Parser;
-
-function getHeader(data, headerStart) {
- var
- // 'start' position of the header.
- start = headerStart,
- // 'end' position of the header.
- end = 0,
- // 'partial end' position of the header.
- partialEnd = 0;
-
- //End of message.
- if (data.substring(start, start + 2).match(/(^\r\n)/)) {
- return -2;
- }
-
- while(end === 0) {
- // Partial End of Header.
- partialEnd = data.indexOf('\r\n', start);
-
- // 'indexOf' returns -1 if the value to be found never occurs.
- if (partialEnd === -1) {
- return partialEnd;
- }
-
- if(!data.substring(partialEnd + 2, partialEnd + 4).match(/(^\r\n)/) && data.charAt(partialEnd + 2).match(/(^\s+)/)) {
- // Not the end of the message. Continue from the next position.
- start = partialEnd + 2;
- } else {
- end = partialEnd;
- }
- }
-
- return end;
-}
-
-function parseHeader(message, data, headerStart, headerEnd) {
- var header, idx, length, parsed,
- hcolonIndex = data.indexOf(':', headerStart),
- headerName = data.substring(headerStart, hcolonIndex).trim(),
- headerValue = data.substring(hcolonIndex + 1, headerEnd).trim();
-
- // If header-field is well-known, parse it.
- switch(headerName.toLowerCase()) {
- case 'via':
- case 'v':
- message.addHeader('via', headerValue);
- if(message.getHeaders('via').length === 1) {
- parsed = message.parseHeader('Via');
- if(parsed) {
- message.via = parsed;
- message.via_branch = parsed.branch;
- }
- } else {
- parsed = 0;
- }
- break;
- case 'from':
- case 'f':
- message.setHeader('from', headerValue);
- parsed = message.parseHeader('from');
- if(parsed) {
- message.from = parsed;
- message.from_tag = parsed.getParam('tag');
- }
- break;
- case 'to':
- case 't':
- message.setHeader('to', headerValue);
- parsed = message.parseHeader('to');
- if(parsed) {
- message.to = parsed;
- message.to_tag = parsed.getParam('tag');
- }
- break;
- case 'record-route':
- parsed = JsSIP.Grammar.parse(headerValue, 'Record_Route');
-
- if (parsed === -1) {
- parsed = undefined;
- }
-
- length = parsed.length;
- for (idx = 0; idx < length; idx++) {
- header = parsed[idx];
- message.addHeader('record-route', headerValue.substring(header.possition, header.offset));
- message.headers['Record-Route'][message.getHeaders('record-route').length - 1].parsed = header.parsed;
- }
- break;
- case 'call-id':
- case 'i':
- message.setHeader('call-id', headerValue);
- parsed = message.parseHeader('call-id');
- if(parsed) {
- message.call_id = headerValue;
- }
- break;
- case 'contact':
- case 'm':
- parsed = JsSIP.Grammar.parse(headerValue, 'Contact');
-
- if (parsed === -1) {
- parsed = undefined;
- }
-
- length = parsed.length;
- for (idx = 0; idx < length; idx++) {
- header = parsed[idx];
- message.addHeader('contact', headerValue.substring(header.possition, header.offset));
- message.headers['Contact'][message.getHeaders('contact').length - 1].parsed = header.parsed;
- }
- break;
- case 'content-length':
- case 'l':
- message.setHeader('content-length', headerValue);
- parsed = message.parseHeader('content-length');
- break;
- case 'content-type':
- case 'c':
- message.setHeader('content-type', headerValue);
- parsed = message.parseHeader('content-type');
- break;
- case 'cseq':
- message.setHeader('cseq', headerValue);
- parsed = message.parseHeader('cseq');
- if(parsed) {
- message.cseq = parsed.value;
- }
- if(message instanceof JsSIP.IncomingResponse) {
- message.method = parsed.method;
- }
- break;
- case 'max-forwards':
- message.setHeader('max-forwards', headerValue);
- parsed = message.parseHeader('max-forwards');
- break;
- case 'www-authenticate':
- message.setHeader('www-authenticate', headerValue);
- parsed = message.parseHeader('www-authenticate');
- break;
- case 'proxy-authenticate':
- message.setHeader('proxy-authenticate', headerValue);
- parsed = message.parseHeader('proxy-authenticate');
- break;
- default:
- // Do not parse this header.
- message.setHeader(headerName, headerValue);
- parsed = 0;
- }
-
- if (parsed === undefined) {
- return {
- error: 'error parsing header "'+ headerName +'"'
- };
- } else {
- return true;
- }
-}
-
-/** Parse SIP Message
- * @function
- * @param {String} message SIP message.
- * @param {Object} logger object.
- * @returns {JsSIP.IncomingRequest|JsSIP.IncomingResponse|undefined}
- */
-Parser = {};
-Parser.parseMessage = function(data, ua) {
- var message, firstLine, contentLength, bodyStart, parsed,
- headerStart = 0,
- headerEnd = data.indexOf('\r\n'),
- logger = ua.getLogger('jssip.parser');
-
- if(headerEnd === -1) {
- logger.warn('no CRLF found, not a SIP message, discarded');
- return;
- }
-
- // Parse first line. Check if it is a Request or a Reply.
- firstLine = data.substring(0, headerEnd);
- parsed = JsSIP.Grammar.parse(firstLine, 'Request_Response');
-
- if(parsed === -1) {
- logger.warn('error parsing first line of SIP message: "' + firstLine + '"');
- return;
- } else if(!parsed.status_code) {
- message = new JsSIP.IncomingRequest(ua);
- message.method = parsed.method;
- message.ruri = parsed.uri;
- } else {
- message = new JsSIP.IncomingResponse(ua);
- message.status_code = parsed.status_code;
- message.reason_phrase = parsed.reason_phrase;
- }
-
- message.data = data;
- headerStart = headerEnd + 2;
-
- /* Loop over every line in data. Detect the end of each header and parse
- * it or simply add to the headers collection.
- */
- while(true) {
- headerEnd = getHeader(data, headerStart);
-
- // The SIP message has normally finished.
- if(headerEnd === -2) {
- bodyStart = headerStart + 2;
- break;
- }
- // data.indexOf returned -1 due to a malformed message.
- else if(headerEnd === -1) {
- parsed.error('malformed message');
- return;
- }
-
- parsed = parseHeader(message, data, headerStart, headerEnd);
-
- if(parsed !== true) {
- logger.error(parsed.error);
- return;
- }
-
- headerStart = headerEnd + 2;
- }
-
- /* RFC3261 18.3.
- * If there are additional bytes in the transport packet
- * beyond the end of the body, they MUST be discarded.
- */
- if(message.hasHeader('content-length')) {
- contentLength = message.getHeader('content-length');
- message.body = data.substr(bodyStart, contentLength);
- } else {
- message.body = data.substring(bodyStart);
- }
-
- return message;
-};
-
-JsSIP.Parser = Parser;
-}(JsSIP));
-
-
-/**
- * @fileoverview SIP Message
- */
-
-(function(JsSIP) {
-var
- OutgoingRequest,
- IncomingMessage,
- IncomingRequest,
- IncomingResponse;
-
-/**
- * @augments JsSIP
- * @class Class for outgoing SIP request.
- * @param {String} method request method
- * @param {String} ruri request uri
- * @param {JsSIP.UA} ua
- * @param {Object} params parameters that will have priority over ua.configuration parameters:
- *
- * - cseq, call_id, from_tag, from_uri, from_display_name, to_uri, to_tag, route_set
- * @param {Object} [headers] extra headers
- * @param {String} [body]
- */
-OutgoingRequest = function(method, ruri, ua, params, extraHeaders, body) {
- var
- to,
- from,
- call_id,
- cseq;
-
- params = params || {};
-
- // Mandatory parameters check
- if(!method || !ruri || !ua) {
- return null;
- }
-
- this.logger = ua.getLogger('jssip.sipmessage');
- this.ua = ua;
- this.headers = {};
- this.method = method;
- this.ruri = ruri;
- this.body = body;
- this.extraHeaders = extraHeaders && extraHeaders.slice() || [];
-
- // Fill the Common SIP Request Headers
-
- // Route
- if (params.route_set) {
- this.setHeader('route', params.route_set);
- } else if (ua.configuration.use_preloaded_route){
- this.setHeader('route', ua.transport.server.sip_uri);
- }
-
- // Via
- // Empty Via header. Will be filled by the client transaction.
- this.setHeader('via', '');
-
- // Max-Forwards
- this.setHeader('max-forwards', JsSIP.UA.C.MAX_FORWARDS);
-
- // To
- to = (params.to_display_name || params.to_display_name === 0) ? '"' + params.to_display_name + '" ' : '';
- to += '<' + (params.to_uri || ruri) + '>';
- to += params.to_tag ? ';tag=' + params.to_tag : '';
- this.to = new JsSIP.NameAddrHeader.parse(to);
- this.setHeader('to', to);
-
- // From
- if (params.from_display_name || params.from_display_name === 0) {
- from = '"' + params.from_display_name + '" ';
- } else if (ua.configuration.display_name) {
- from = '"' + ua.configuration.display_name + '" ';
- } else {
- from = '';
- }
- from += '<' + (params.from_uri || ua.configuration.uri) + '>;tag=';
- from += params.from_tag || JsSIP.Utils.newTag();
- this.from = new JsSIP.NameAddrHeader.parse(from);
- this.setHeader('from', from);
-
- // Call-ID
- call_id = params.call_id || (ua.configuration.jssip_id + JsSIP.Utils.createRandomToken(15));
- this.call_id = call_id;
- this.setHeader('call-id', call_id);
-
- // CSeq
- cseq = params.cseq || Math.floor(Math.random() * 10000);
- this.cseq = cseq;
- this.setHeader('cseq', cseq + ' ' + method);
-};
-
-OutgoingRequest.prototype = {
- /**
- * Replace the the given header by the given value.
- * @param {String} name header name
- * @param {String | Array} value header value
- */
- setHeader: function(name, value) {
- this.headers[JsSIP.Utils.headerize(name)] = (value instanceof Array) ? value : [value];
- },
-
- /**
- * Get the value of the given header name at the given position.
- * @param {String} name header name
- * @returns {String|undefined} Returns the specified header, null if header doesn't exist.
- */
- getHeader: function(name) {
- var regexp, idx,
- length = this.extraHeaders.length,
- header = this.headers[JsSIP.Utils.headerize(name)];
-
- if(header) {
- if(header[0]) {
- return header[0];
- }
- } else {
- regexp = new RegExp('^\\s*'+ name +'\\s*:','i');
- for (idx=0; idx= this.headers[name].length) {
- this.logger.log('not so many "' + name + '" headers present');
- return;
- }
-
- header = this.headers[name][idx];
- value = header.raw;
-
- if(header.parsed) {
- return header.parsed;
- }
-
- //substitute '-' by '_' for grammar rule matching.
- parsed = JsSIP.Grammar.parse(value, name.replace(/-/g, '_'));
-
- if(parsed === -1) {
- this.headers[name].splice(idx, 1); //delete from headers
- this.logger.warn('error parsing "' + name + '" header field with value "' + value + '"');
- return;
- } else {
- header.parsed = parsed;
- return parsed;
- }
- },
-
- /**
- * Message Header attribute selector. Alias of parseHeader.
- * @param {String} name header name
- * @param {Number} [idx=0] header index
- * @returns {Object|undefined} Parsed header object, undefined if the header is not present or in case of a parsing error.
- *
- * @example
- * message.s('via',3).port
- */
- s: function(name, idx) {
- return this.parseHeader(name, idx);
- },
-
- /**
- * Replace the value of the given header by the value.
- * @param {String} name header name
- * @param {String} value header value
- */
- setHeader: function(name, value) {
- var header = { raw: value };
- this.headers[JsSIP.Utils.headerize(name)] = [header];
- },
-
- toString: function() {
- return this.data;
- }
-};
-
-/**
- * @augments IncomingMessage
- * @class Class for incoming SIP request.
- */
-IncomingRequest = function(ua) {
- this.logger = ua.getLogger('jssip.sipmessage');
- this.ua = ua;
- this.headers = {};
- this.ruri = null;
- this.transport = null;
- this.server_transaction = null;
-};
-IncomingRequest.prototype = new IncomingMessage();
-
-/**
-* Stateful reply.
-* @param {Number} code status code
-* @param {String} reason reason phrase
-* @param {Object} headers extra headers
-* @param {String} body body
-* @param {Function} [onSuccess] onSuccess callback
-* @param {Function} [onFailure] onFailure callback
-*/
-IncomingRequest.prototype.reply = function(code, reason, extraHeaders, body, onSuccess, onFailure) {
- var rr, vias, length, idx, response,
- supported = [],
- to = this.getHeader('To'),
- r = 0,
- v = 0;
-
- code = code || null;
- reason = reason || null;
-
- // Validate code and reason values
- if (!code || (code < 100 || code > 699)) {
- throw new TypeError('Invalid status_code: '+ code);
- } else if (reason && typeof reason !== 'string' && !(reason instanceof String)) {
- throw new TypeError('Invalid reason_phrase: '+ reason);
- }
-
- reason = reason || JsSIP.C.REASON_PHRASE[code] || '';
- extraHeaders = extraHeaders && extraHeaders.slice() || [];
-
- response = 'SIP/2.0 ' + code + ' ' + reason + '\r\n';
-
- if(this.method === JsSIP.C.INVITE && code > 100 && code <= 200) {
- rr = this.getHeaders('record-route');
- length = rr.length;
-
- for(r; r < length; r++) {
- response += 'Record-Route: ' + rr[r] + '\r\n';
- }
- }
-
- vias = this.getHeaders('via');
- length = vias.length;
-
- for(v; v < length; v++) {
- response += 'Via: ' + vias[v] + '\r\n';
- }
-
- if(!this.to_tag && code > 100) {
- to += ';tag=' + JsSIP.Utils.newTag();
- } else if(this.to_tag && !this.s('to').hasParam('tag')) {
- to += ';tag=' + this.to_tag;
- }
-
- response += 'To: ' + to + '\r\n';
- response += 'From: ' + this.getHeader('From') + '\r\n';
- response += 'Call-ID: ' + this.call_id + '\r\n';
- response += 'CSeq: ' + this.cseq + ' ' + this.method + '\r\n';
-
- length = extraHeaders.length;
- for (idx = 0; idx < length; idx++) {
- response += extraHeaders[idx].trim() +'\r\n';
- }
-
- // Supported
- switch (this.method) {
- case JsSIP.C.INVITE:
- if (this.ua.contact.pub_gruu || this.ua.contact.temp_gruu) {
- supported.push('gruu');
- }
- break;
- }
-
- supported.push('outbound');
-
- // Allow and Accept
- if (this.method === JsSIP.C.OPTIONS) {
- response += 'Allow: '+ JsSIP.Utils.getAllowedMethods(this.ua) +'\r\n';
- response += 'Accept: '+ JsSIP.UA.C.ACCEPTED_BODY_TYPES +'\r\n';
- } else if (code === 405) {
- response += 'Allow: '+ JsSIP.Utils.getAllowedMethods(this.ua) +'\r\n';
- }
-
- response += 'Supported: ' + supported +'\r\n';
-
- if(body) {
- length = JsSIP.Utils.str_utf8_length(body);
- response += 'Content-Type: application/sdp\r\n';
- response += 'Content-Length: ' + length + '\r\n\r\n';
- response += body;
- } else {
- response += 'Content-Length: ' + 0 + '\r\n\r\n';
- }
-
- this.server_transaction.receiveResponse(code, response, onSuccess, onFailure);
-};
-
-/**
-* Stateless reply.
-* @param {Number} code status code
-* @param {String} reason reason phrase
-*/
-IncomingRequest.prototype.reply_sl = function(code, reason) {
- var to, response,
- v = 0,
- vias = this.getHeaders('via'),
- length = vias.length;
-
- code = code || null;
- reason = reason || null;
-
- // Validate code and reason values
- if (!code || (code < 100 || code > 699)) {
- throw new TypeError('Invalid status_code: '+ code);
- } else if (reason && typeof reason !== 'string' && !(reason instanceof String)) {
- throw new TypeError('Invalid reason_phrase: '+ reason);
- }
-
- reason = reason || JsSIP.C.REASON_PHRASE[code] || '';
-
- response = 'SIP/2.0 ' + code + ' ' + reason + '\r\n';
-
- for(v; v < length; v++) {
- response += 'Via: ' + vias[v] + '\r\n';
- }
-
- to = this.getHeader('To');
-
- if(!this.to_tag && code > 100) {
- to += ';tag=' + JsSIP.Utils.newTag();
- } else if(this.to_tag && !this.s('to').hasParam('tag')) {
- to += ';tag=' + this.to_tag;
- }
-
- response += 'To: ' + to + '\r\n';
- response += 'From: ' + this.getHeader('From') + '\r\n';
- response += 'Call-ID: ' + this.call_id + '\r\n';
- response += 'CSeq: ' + this.cseq + ' ' + this.method + '\r\n';
- response += 'Content-Length: ' + 0 + '\r\n\r\n';
-
- this.transport.send(response);
-};
-
-
-/**
- * @augments IncomingMessage
- * @class Class for incoming SIP response.
- */
-IncomingResponse = function(ua) {
- this.logger = ua.getLogger('jssip.sipmessage');
- this.headers = {};
- this.status_code = null;
- this.reason_phrase = null;
-};
-IncomingResponse.prototype = new IncomingMessage();
-
-JsSIP.OutgoingRequest = OutgoingRequest;
-JsSIP.IncomingRequest = IncomingRequest;
-JsSIP.IncomingResponse = IncomingResponse;
-}(JsSIP));
-
-
-/**
- * @fileoverview SIP URI
- */
-
-/**
- * @augments JsSIP
- * @class Class creating a SIP URI.
- *
- * @param {String} [scheme]
- * @param {String} [user]
- * @param {String} host
- * @param {String} [port]
- * @param {Object} [parameters]
- * @param {Object} [headers]
- *
- */
-(function(JsSIP) {
-var URI;
-
-URI = function(scheme, user, host, port, parameters, headers) {
- var param, header;
-
- // Checks
- if(!host) {
- throw new TypeError('missing or invalid "host" parameter');
- }
-
- // Initialize parameters
- scheme = scheme || JsSIP.C.SIP;
- this.parameters = {};
- this.headers = {};
-
- for (param in parameters) {
- this.setParam(param, parameters[param]);
- }
-
- for (header in headers) {
- this.setHeader(header, headers[header]);
- }
-
- Object.defineProperties(this, {
- scheme: {
- get: function(){ return scheme; },
- set: function(value){
- scheme = value.toLowerCase();
- }
- },
-
- user: {
- get: function(){ return user; },
- set: function(value){
- user = value;
- }
- },
-
- host: {
- get: function(){ return host; },
- set: function(value){
- host = value.toLowerCase();
- }
- },
-
- port: {
- get: function(){ return port; },
- set: function(value){
- port = value === 0 ? value : (parseInt(value,10) || null);
- }
- }
- });
-};
-URI.prototype = {
- setParam: function(key, value) {
- if(key) {
- this.parameters[key.toLowerCase()] = (typeof value === 'undefined' || value === null) ? null : value.toString().toLowerCase();
- }
- },
-
- getParam: function(key) {
- if(key) {
- return this.parameters[key.toLowerCase()];
- }
- },
-
- hasParam: function(key) {
- if(key) {
- return (this.parameters.hasOwnProperty(key.toLowerCase()) && true) || false;
- }
- },
-
- deleteParam: function(parameter) {
- var value;
- parameter = parameter.toLowerCase();
- if (this.parameters.hasOwnProperty(parameter)) {
- value = this.parameters[parameter];
- delete this.parameters[parameter];
- return value;
- }
- },
-
- clearParams: function() {
- this.parameters = {};
- },
-
- setHeader: function(name, value) {
- this.headers[JsSIP.Utils.headerize(name)] = (value instanceof Array) ? value : [value];
- },
-
- getHeader: function(name) {
- if(name) {
- return this.headers[JsSIP.Utils.headerize(name)];
- }
- },
-
- hasHeader: function(name) {
- if(name) {
- return (this.headers.hasOwnProperty(JsSIP.Utils.headerize(name)) && true) || false;
- }
- },
-
- deleteHeader: function(header) {
- var value;
- header = JsSIP.Utils.headerize(header);
- if(this.headers.hasOwnProperty(header)) {
- value = this.headers[header];
- delete this.headers[header];
- return value;
- }
- },
-
- clearHeaders: function() {
- this.headers = {};
- },
-
- clone: function() {
- return new URI(
- this.scheme,
- this.user,
- this.host,
- this.port,
- window.JSON.parse(window.JSON.stringify(this.parameters)),
- window.JSON.parse(window.JSON.stringify(this.headers)));
- },
-
- toString: function(){
- var header, parameter, idx, uri,
- headers = [];
-
- uri = this.scheme + ':';
- if (this.user) {
- uri += JsSIP.Utils.escapeUser(this.user) + '@';
- }
- uri += this.host;
- if (this.port || this.port === 0) {
- uri += ':' + this.port;
- }
-
- for (parameter in this.parameters) {
- uri += ';' + parameter;
-
- if (this.parameters[parameter] !== null) {
- uri += '='+ this.parameters[parameter];
- }
- }
-
- for(header in this.headers) {
- for(idx in this.headers[header]) {
- headers.push(header + '=' + this.headers[header][idx]);
- }
- }
-
- if (headers.length > 0) {
- uri += '?' + headers.join('&');
- }
-
- return uri;
- },
-
- toAor: function(show_port){
- var aor;
-
- aor = this.scheme + ':';
- if (this.user) {
- aor += JsSIP.Utils.escapeUser(this.user) + '@';
- }
- aor += this.host;
- if (show_port && (this.port || this.port === 0)) {
- aor += ':' + this.port;
- }
-
- return aor;
- }
-};
-
-
-/**
- * Parse the given string and returns a JsSIP.URI instance or undefined if
- * it is an invalid URI.
- * @public
- * @param {String} uri
- */
-URI.parse = function(uri) {
- uri = JsSIP.Grammar.parse(uri,'SIP_URI');
-
- if (uri !== -1) {
- return uri;
- } else {
- return undefined;
- }
-};
-
-JsSIP.URI = URI;
-}(JsSIP));
-
-
-/**
- * @fileoverview JsSIP NameAddrHeader
- */
-
-/**
- * @augments JsSIP
- * @class Class creating a Name Address SIP header.
- *
- * @param {JsSIP.URI} uri
- * @param {String} [display_name]
- * @param {Object} [parameters]
- *
- */
-(function(JsSIP) {
-var NameAddrHeader;
-
-NameAddrHeader = function(uri, display_name, parameters) {
- var param;
-
- // Checks
- if(!uri || !(uri instanceof JsSIP.URI)) {
- throw new TypeError('missing or invalid "uri" parameter');
- }
-
- // Initialize parameters
- this.uri = uri;
- this.parameters = {};
-
- for (param in parameters) {
- this.setParam(param, parameters[param]);
- }
-
- Object.defineProperties(this, {
- display_name: {
- get: function() { return display_name; },
- set: function(value) {
- display_name = (value === 0) ? '0' : value;
- }
- }
- });
-};
-NameAddrHeader.prototype = {
- setParam: function(key, value) {
- if (key) {
- this.parameters[key.toLowerCase()] = (typeof value === 'undefined' || value === null) ? null : value.toString();
- }
- },
-
- getParam: function(key) {
- if(key) {
- return this.parameters[key.toLowerCase()];
- }
- },
-
- hasParam: function(key) {
- if(key) {
- return (this.parameters.hasOwnProperty(key.toLowerCase()) && true) || false;
- }
- },
-
- deleteParam: function(parameter) {
- var value;
- parameter = parameter.toLowerCase();
- if (this.parameters.hasOwnProperty(parameter)) {
- value = this.parameters[parameter];
- delete this.parameters[parameter];
- return value;
- }
- },
-
- clearParams: function() {
- this.parameters = {};
- },
-
- clone: function() {
- return new NameAddrHeader(
- this.uri.clone(),
- this.display_name,
- window.JSON.parse(window.JSON.stringify(this.parameters)));
- },
-
- toString: function() {
- var body, parameter;
-
- body = (this.display_name || this.display_name === 0) ? '"' + this.display_name + '" ' : '';
- body += '<' + this.uri.toString() + '>';
-
- for (parameter in this.parameters) {
- body += ';' + parameter;
-
- if (this.parameters[parameter] !== null) {
- body += '='+ this.parameters[parameter];
- }
- }
-
- return body;
- }
-};
-
-
-/**
- * Parse the given string and returns a JsSIP.NameAddrHeader instance or undefined if
- * it is an invalid NameAddrHeader.
- * @public
- * @param {String} name_addr_header
- */
-NameAddrHeader.parse = function(name_addr_header) {
- name_addr_header = JsSIP.Grammar.parse(name_addr_header,'Name_Addr_Header');
-
- if (name_addr_header !== -1) {
- return name_addr_header;
- } else {
- return undefined;
- }
-};
-
-JsSIP.NameAddrHeader = NameAddrHeader;
-}(JsSIP));
-
-
-/**
- * @fileoverview SIP Transactions
- */
-
-/**
- * SIP Transactions module.
- * @augments JsSIP
- */
-(function(JsSIP) {
-var
- C = {
- // Transaction states
- STATUS_TRYING: 1,
- STATUS_PROCEEDING: 2,
- STATUS_CALLING: 3,
- STATUS_ACCEPTED: 4,
- STATUS_COMPLETED: 5,
- STATUS_TERMINATED: 6,
- STATUS_CONFIRMED: 7,
-
- // Transaction types
- NON_INVITE_CLIENT: 'nict',
- NON_INVITE_SERVER: 'nist',
- INVITE_CLIENT: 'ict',
- INVITE_SERVER: 'ist'
- };
-
-/**
-* @augments JsSIP.Transactions
-* @class Non Invite Client Transaction
-* @param {JsSIP.RequestSender} request_sender
-* @param {JsSIP.OutgoingRequest} request
-* @param {JsSIP.Transport} transport
-*/
-var NonInviteClientTransaction = function(request_sender, request, transport) {
- var via,
- events = ['stateChanged'];
-
- this.type = C.NON_INVITE_CLIENT;
- this.transport = transport;
- this.id = 'z9hG4bK' + Math.floor(Math.random() * 10000000);
- this.request_sender = request_sender;
- this.request = request;
-
- this.logger = request_sender.ua.getLogger('jssip.transaction.nict', this.id);
-
- via = 'SIP/2.0/' + (request_sender.ua.configuration.hack_via_tcp ? 'TCP' : transport.server.scheme);
- via += ' ' + request_sender.ua.configuration.via_host + ';branch=' + this.id;
-
- this.request.setHeader('via', via);
-
- this.request_sender.ua.newTransaction(this);
-
- this.initEvents(events);
-};
-NonInviteClientTransaction.prototype = new JsSIP.EventEmitter();
-
-NonInviteClientTransaction.prototype.stateChanged = function(state) {
- this.state = state;
- this.emit('stateChanged', this);
-};
-
-NonInviteClientTransaction.prototype.send = function() {
- var tr = this;
-
- this.stateChanged(C.STATUS_TRYING);
- this.F = window.setTimeout(function() {tr.timer_F();}, JsSIP.Timers.TIMER_F);
-
- if(!this.transport.send(this.request)) {
- this.onTransportError();
- }
-};
-
-NonInviteClientTransaction.prototype.onTransportError = function() {
- this.logger.log('transport error occurred, deleting non-INVITE client transaction ' + this.id);
- window.clearTimeout(this.F);
- window.clearTimeout(this.K);
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- this.request_sender.onTransportError();
-};
-
-NonInviteClientTransaction.prototype.timer_F = function() {
- this.logger.log('Timer F expired for non-INVITE client transaction ' + this.id);
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- this.request_sender.onRequestTimeout();
-};
-
-NonInviteClientTransaction.prototype.timer_K = function() {
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
-};
-
-NonInviteClientTransaction.prototype.receiveResponse = function(response) {
- var
- tr = this,
- status_code = response.status_code;
-
- if(status_code < 200) {
- switch(this.state) {
- case C.STATUS_TRYING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_PROCEEDING);
- this.request_sender.receiveResponse(response);
- break;
- }
- } else {
- switch(this.state) {
- case C.STATUS_TRYING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_COMPLETED);
- window.clearTimeout(this.F);
-
- if(status_code === 408) {
- this.request_sender.onRequestTimeout();
- } else {
- this.request_sender.receiveResponse(response);
- }
-
- this.K = window.setTimeout(function() {tr.timer_K();}, JsSIP.Timers.TIMER_K);
- break;
- case C.STATUS_COMPLETED:
- break;
- }
- }
-};
-
-
-
-/**
-* @augments JsSIP.Transactions
-* @class Invite Client Transaction
-* @param {JsSIP.RequestSender} request_sender
-* @param {JsSIP.OutgoingRequest} request
-* @param {JsSIP.Transport} transport
-*/
-var InviteClientTransaction = function(request_sender, request, transport) {
- var via,
- tr = this,
- events = ['stateChanged'];
-
- this.type = C.INVITE_CLIENT;
- this.transport = transport;
- this.id = 'z9hG4bK' + Math.floor(Math.random() * 10000000);
- this.request_sender = request_sender;
- this.request = request;
-
- this.logger = request_sender.ua.getLogger('jssip.transaction.ict', this.id);
-
- via = 'SIP/2.0/' + (request_sender.ua.configuration.hack_via_tcp ? 'TCP' : transport.server.scheme);
- via += ' ' + request_sender.ua.configuration.via_host + ';branch=' + this.id;
-
- this.request.setHeader('via', via);
-
- this.request_sender.ua.newTransaction(this);
-
- // Add the cancel property to the request.
- //Will be called from the request instance, not the transaction itself.
- this.request.cancel = function(reason) {
- tr.cancel_request(tr, reason);
- };
-
- this.initEvents(events);
-};
-InviteClientTransaction.prototype = new JsSIP.EventEmitter();
-
-InviteClientTransaction.prototype.stateChanged = function(state) {
- this.state = state;
- this.emit('stateChanged', this);
-};
-
-InviteClientTransaction.prototype.send = function() {
- var tr = this;
- this.stateChanged(C.STATUS_CALLING);
- this.B = window.setTimeout(function() {
- tr.timer_B();
- }, JsSIP.Timers.TIMER_B);
-
- if(!this.transport.send(this.request)) {
- this.onTransportError();
- }
-};
-
-InviteClientTransaction.prototype.onTransportError = function() {
- this.logger.log('transport error occurred, deleting INVITE client transaction ' + this.id);
- window.clearTimeout(this.B);
- window.clearTimeout(this.D);
- window.clearTimeout(this.M);
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
-
- if (this.state !== C.STATUS_ACCEPTED) {
- this.request_sender.onTransportError();
- }
-};
-
-// RFC 6026 7.2
-InviteClientTransaction.prototype.timer_M = function() {
- this.logger.log('Timer M expired for INVITE client transaction ' + this.id);
-
- if(this.state === C.STATUS_ACCEPTED) {
- window.clearTimeout(this.B);
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- }
-};
-
-// RFC 3261 17.1.1
-InviteClientTransaction.prototype.timer_B = function() {
- this.logger.log('Timer B expired for INVITE client transaction ' + this.id);
- if(this.state === C.STATUS_CALLING) {
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
- this.request_sender.onRequestTimeout();
- }
-};
-
-InviteClientTransaction.prototype.timer_D = function() {
- this.logger.log('Timer D expired for INVITE client transaction ' + this.id);
- window.clearTimeout(this.B);
- this.stateChanged(C.STATUS_TERMINATED);
- this.request_sender.ua.destroyTransaction(this);
-};
-
-InviteClientTransaction.prototype.sendACK = function(response) {
- var tr = this;
-
- this.ack = 'ACK ' + this.request.ruri + ' SIP/2.0\r\n';
- this.ack += 'Via: ' + this.request.headers['Via'].toString() + '\r\n';
-
- if(this.request.headers['Route']) {
- this.ack += 'Route: ' + this.request.headers['Route'].toString() + '\r\n';
- }
-
- 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 += 'CSeq: ' + this.request.headers['CSeq'].toString().split(' ')[0];
- this.ack += ' ACK\r\n';
- this.ack += 'Content-Length: 0\r\n\r\n';
-
- this.D = window.setTimeout(function() {tr.timer_D();}, JsSIP.Timers.TIMER_D);
-
- this.transport.send(this.ack);
-};
-
-InviteClientTransaction.prototype.cancel_request = function(tr, reason) {
- var request = tr.request;
-
- this.cancel = JsSIP.C.CANCEL + ' ' + request.ruri + ' SIP/2.0\r\n';
- this.cancel += 'Via: ' + request.headers['Via'].toString() + '\r\n';
-
- if(this.request.headers['Route']) {
- this.cancel += 'Route: ' + request.headers['Route'].toString() + '\r\n';
- }
-
- this.cancel += 'To: ' + request.headers['To'].toString() + '\r\n';
- this.cancel += 'From: ' + request.headers['From'].toString() + '\r\n';
- this.cancel += 'Call-ID: ' + request.headers['Call-ID'].toString() + '\r\n';
- this.cancel += 'CSeq: ' + request.headers['CSeq'].toString().split(' ')[0] +
- ' CANCEL\r\n';
-
- if(reason) {
- this.cancel += 'Reason: ' + reason + '\r\n';
- }
-
- this.cancel += 'Content-Length: 0\r\n\r\n';
-
- // Send only if a provisional response (>100) has been received.
- if(this.state === C.STATUS_PROCEEDING) {
- this.transport.send(this.cancel);
- }
-};
-
-InviteClientTransaction.prototype.receiveResponse = function(response) {
- var
- tr = this,
- status_code = response.status_code;
-
- if(status_code >= 100 && status_code <= 199) {
- switch(this.state) {
- case C.STATUS_CALLING:
- this.stateChanged(C.STATUS_PROCEEDING);
- this.request_sender.receiveResponse(response);
- if(this.cancel) {
- this.transport.send(this.cancel);
- }
- break;
- case C.STATUS_PROCEEDING:
- this.request_sender.receiveResponse(response);
- break;
- }
- } else if(status_code >= 200 && status_code <= 299) {
- switch(this.state) {
- case C.STATUS_CALLING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_ACCEPTED);
- this.M = window.setTimeout(function() {
- tr.timer_M();
- }, JsSIP.Timers.TIMER_M);
- this.request_sender.receiveResponse(response);
- break;
- case C.STATUS_ACCEPTED:
- this.request_sender.receiveResponse(response);
- break;
- }
- } else if(status_code >= 300 && status_code <= 699) {
- switch(this.state) {
- case C.STATUS_CALLING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_COMPLETED);
- this.sendACK(response);
- this.request_sender.receiveResponse(response);
- break;
- case C.STATUS_COMPLETED:
- this.sendACK(response);
- break;
- }
- }
-};
-
-
-/**
- * @augments JsSIP.Transactions
- * @class ACK Client Transaction
- * @param {JsSIP.RequestSender} request_sender
- * @param {JsSIP.OutgoingRequest} request
- * @param {JsSIP.Transport} transport
- */
-var AckClientTransaction = function(request_sender, request, transport) {
- var via;
-
- this.transport = transport;
- this.id = 'z9hG4bK' + Math.floor(Math.random() * 10000000);
- this.request_sender = request_sender;
- this.request = request;
-
- this.logger = request_sender.ua.getLogger('jssip.transaction.nict', this.id);
-
- via = 'SIP/2.0/' + (request_sender.ua.configuration.hack_via_tcp ? 'TCP' : transport.server.scheme);
- via += ' ' + request_sender.ua.configuration.via_host + ';branch=' + this.id;
-
- this.request.setHeader('via', via);
-};
-AckClientTransaction.prototype = new JsSIP.EventEmitter();
-
-AckClientTransaction.prototype.send = function() {
- if(!this.transport.send(this.request)) {
- this.onTransportError();
- }
-};
-
-AckClientTransaction.prototype.onTransportError = function() {
- this.logger.log('transport error occurred, for an ACK client transaction ' + this.id);
- this.request_sender.onTransportError();
-};
-
-
-/**
-* @augments JsSIP.Transactions
-* @class Non Invite Server Transaction
-* @param {JsSIP.IncomingRequest} request
-* @param {JsSIP.UA} ua
-*/
-var NonInviteServerTransaction = function(request, ua) {
- var events = ['stateChanged'];
-
- this.type = C.NON_INVITE_SERVER;
- this.id = request.via_branch;
- this.request = request;
- this.transport = request.transport;
- this.ua = ua;
- this.last_response = '';
- request.server_transaction = this;
-
- this.logger = ua.getLogger('jssip.transaction.nist', this.id);
-
- this.state = C.STATUS_TRYING;
-
- ua.newTransaction(this);
-
- this.initEvents(events);
-};
-NonInviteServerTransaction.prototype = new JsSIP.EventEmitter();
-
-NonInviteServerTransaction.prototype.stateChanged = function(state) {
- this.state = state;
- this.emit('stateChanged', this);
-};
-
-NonInviteServerTransaction.prototype.timer_J = function() {
- this.logger.log('Timer J expired for non-INVITE server transaction ' + this.id);
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
-};
-
-NonInviteServerTransaction.prototype.onTransportError = function() {
- if (!this.transportError) {
- this.transportError = true;
-
- this.logger.log('transport error occurred, deleting non-INVITE server transaction ' + this.id);
-
- window.clearTimeout(this.J);
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
- }
-};
-
-NonInviteServerTransaction.prototype.receiveResponse = function(status_code, response, onSuccess, onFailure) {
- var tr = this;
-
- if(status_code === 100) {
- /* RFC 4320 4.1
- * 'A SIP element MUST NOT
- * send any provisional response with a
- * Status-Code other than 100 to a non-INVITE request.'
- */
- switch(this.state) {
- case C.STATUS_TRYING:
- this.stateChanged(C.STATUS_PROCEEDING);
- if(!this.transport.send(response)) {
- this.onTransportError();
- }
- break;
- case C.STATUS_PROCEEDING:
- this.last_response = response;
- if(!this.transport.send(response)) {
- this.onTransportError();
- if (onFailure) {
- onFailure();
- }
- } else if (onSuccess) {
- onSuccess();
- }
- break;
- }
- } else if(status_code >= 200 && status_code <= 699) {
- switch(this.state) {
- case C.STATUS_TRYING:
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_COMPLETED);
- this.last_response = response;
- this.J = window.setTimeout(function() {
- tr.timer_J();
- }, JsSIP.Timers.TIMER_J);
- if(!this.transport.send(response)) {
- this.onTransportError();
- if (onFailure) {
- onFailure();
- }
- } else if (onSuccess) {
- onSuccess();
- }
- break;
- case C.STATUS_COMPLETED:
- break;
- }
- }
-};
-
-/**
-* @augments JsSIP.Transactions
-* @class Invite Server Transaction
-* @param {JsSIP.IncomingRequest} request
-* @param {JsSIP.UA} ua
-*/
-var InviteServerTransaction = function(request, ua) {
- var events = ['stateChanged'];
-
- this.type = C.INVITE_SERVER;
- this.id = request.via_branch;
- this.request = request;
- this.transport = request.transport;
- this.ua = ua;
- this.last_response = '';
- request.server_transaction = this;
-
- this.logger = ua.getLogger('jssip.transaction.ist', this.id);
-
- this.state = C.STATUS_PROCEEDING;
-
- ua.newTransaction(this);
-
- this.resendProvisionalTimer = null;
-
- request.reply(100);
-
- this.initEvents(events);
-};
-InviteServerTransaction.prototype = new JsSIP.EventEmitter();
-
-InviteServerTransaction.prototype.stateChanged = function(state) {
- this.state = state;
- this.emit('stateChanged', this);
-};
-
-InviteServerTransaction.prototype.timer_H = function() {
- this.logger.log('Timer H expired for INVITE server transaction ' + this.id);
-
- if(this.state === C.STATUS_COMPLETED) {
- this.logger.warn('transactions', 'ACK for INVITE server transaction was never received, call will be terminated');
- }
-
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
-};
-
-InviteServerTransaction.prototype.timer_I = function() {
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
-};
-
-// RFC 6026 7.1
-InviteServerTransaction.prototype.timer_L = function() {
- this.logger.log('Timer L expired for INVITE server transaction ' + this.id);
-
- if(this.state === C.STATUS_ACCEPTED) {
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
- }
-};
-
-InviteServerTransaction.prototype.onTransportError = function() {
- if (!this.transportError) {
- this.transportError = true;
-
- this.logger.log('transport error occurred, deleting INVITE server transaction ' + this.id);
-
- if (this.resendProvisionalTimer !== null) {
- window.clearInterval(this.resendProvisionalTimer);
- this.resendProvisionalTimer = null;
- }
-
- window.clearTimeout(this.L);
- window.clearTimeout(this.H);
- window.clearTimeout(this.I);
-
- this.stateChanged(C.STATUS_TERMINATED);
- this.ua.destroyTransaction(this);
- }
-};
-
-InviteServerTransaction.prototype.resend_provisional = function() {
- if(!this.transport.send(this.last_response)) {
- this.onTransportError();
- }
-};
-
-// INVITE Server Transaction RFC 3261 17.2.1
-InviteServerTransaction.prototype.receiveResponse = function(status_code, response, onSuccess, onFailure) {
- var tr = this;
-
- if(status_code >= 100 && status_code <= 199) {
- switch(this.state) {
- case C.STATUS_PROCEEDING:
- if(!this.transport.send(response)) {
- this.onTransportError();
- }
- this.last_response = response;
- break;
- }
- }
-
- if(status_code > 100 && status_code <= 199 && this.state === C.STATUS_PROCEEDING) {
- // Trigger the resendProvisionalTimer only for the first non 100 provisional response.
- if(this.resendProvisionalTimer === null) {
- this.resendProvisionalTimer = window.setInterval(function() {
- tr.resend_provisional();}, JsSIP.Timers.PROVISIONAL_RESPONSE_INTERVAL);
- }
- } else if(status_code >= 200 && status_code <= 299) {
- switch(this.state) {
- case C.STATUS_PROCEEDING:
- this.stateChanged(C.STATUS_ACCEPTED);
- this.last_response = response;
- this.L = window.setTimeout(function() {
- tr.timer_L();
- }, JsSIP.Timers.TIMER_L);
-
- if (this.resendProvisionalTimer !== null) {
- window.clearInterval(this.resendProvisionalTimer);
- this.resendProvisionalTimer = null;
- }
- /* falls through */
- case C.STATUS_ACCEPTED:
- // Note that this point will be reached for proceeding tr.state also.
- if(!this.transport.send(response)) {
- this.onTransportError();
- if (onFailure) {
- onFailure();
- }
- } else if (onSuccess) {
- onSuccess();
- }
- break;
- }
- } else if(status_code >= 300 && status_code <= 699) {
- switch(this.state) {
- case C.STATUS_PROCEEDING:
- if (this.resendProvisionalTimer !== null) {
- window.clearInterval(this.resendProvisionalTimer);
- this.resendProvisionalTimer = null;
- }
-
- if(!this.transport.send(response)) {
- this.onTransportError();
- if (onFailure) {
- onFailure();
- }
- } else {
- this.stateChanged(C.STATUS_COMPLETED);
- this.H = window.setTimeout(function() {
- tr.timer_H();
- }, JsSIP.Timers.TIMER_H);
- if (onSuccess) {
- onSuccess();
- }
- }
- break;
- }
- }
-};
-
-/**
- * @function
- * @param {JsSIP.UA} ua
- * @param {JsSIP.IncomingRequest} request
- *
- * @return {boolean}
- * INVITE:
- * _true_ if retransmission
- * _false_ new request
- *
- * ACK:
- * _true_ ACK to non2xx response
- * _false_ ACK must be passed to TU (accepted state)
- * ACK to 2xx response
- *
- * CANCEL:
- * _true_ no matching invite transaction
- * _false_ matching invite transaction and no final response sent
- *
- * OTHER:
- * _true_ retransmission
- * _false_ new request
- */
-var checkTransaction = function(ua, request) {
- var tr;
-
- switch(request.method) {
- case JsSIP.C.INVITE:
- tr = ua.transactions.ist[request.via_branch];
- if(tr) {
- switch(tr.state) {
- case C.STATUS_PROCEEDING:
- tr.transport.send(tr.last_response);
- break;
-
- // RFC 6026 7.1 Invite retransmission
- //received while in C.STATUS_ACCEPTED state. Absorb it.
- case C.STATUS_ACCEPTED:
- break;
- }
- return true;
- }
- break;
- case JsSIP.C.ACK:
- tr = ua.transactions.ist[request.via_branch];
-
- // RFC 6026 7.1
- if(tr) {
- if(tr.state === C.STATUS_ACCEPTED) {
- return false;
- } else if(tr.state === C.STATUS_COMPLETED) {
- tr.state = C.STATUS_CONFIRMED;
- tr.I = window.setTimeout(function() {tr.timer_I();}, JsSIP.Timers.TIMER_I);
- return true;
- }
- }
-
- // ACK to 2XX Response.
- else {
- return false;
- }
- break;
- case JsSIP.C.CANCEL:
- tr = ua.transactions.ist[request.via_branch];
- if(tr) {
- request.reply_sl(200);
- if(tr.state === C.STATUS_PROCEEDING) {
- return false;
- } else {
- return true;
- }
- } else {
- request.reply_sl(481);
- return true;
- }
- break;
- default:
-
- // Non-INVITE Server Transaction RFC 3261 17.2.2
- tr = ua.transactions.nist[request.via_branch];
- if(tr) {
- switch(tr.state) {
- case C.STATUS_TRYING:
- break;
- case C.STATUS_PROCEEDING:
- case C.STATUS_COMPLETED:
- tr.transport.send(tr.last_response);
- break;
- }
- return true;
- }
- break;
- }
-};
-
-JsSIP.Transactions = {
- C: C,
- checkTransaction: checkTransaction,
- NonInviteClientTransaction: NonInviteClientTransaction,
- InviteClientTransaction: InviteClientTransaction,
- AckClientTransaction: AckClientTransaction,
- NonInviteServerTransaction: NonInviteServerTransaction,
- InviteServerTransaction: InviteServerTransaction
-};
-
-}(JsSIP));
-
-
-/**
- * @fileoverview SIP Dialog
- */
-
-/**
- * @augments JsSIP
- * @class Class creating a SIP dialog.
- * @param {JsSIP.RTCSession} owner
- * @param {JsSIP.IncomingRequest|JsSIP.IncomingResponse} message
- * @param {Enum} type UAC / UAS
- * @param {Enum} state JsSIP.Dialog.C.STATUS_EARLY / JsSIP.Dialog.C.STATUS_CONFIRMED
- */
-(function(JsSIP) {
-
-// Load dependencies
-var RequestSender =
-/**
- * @fileoverview In-Dialog Request Sender
- */
-
-/**
- * @augments JsSIP.Dialog
- * @class Class creating an In-dialog request sender.
- * @param {JsSIP.Dialog} dialog
- * @param {Object} applicant
- * @param {JsSIP.OutgoingRequest} request
- */
-/**
- * @fileoverview in-Dialog Request Sender
- */
-
-(function(JsSIP) {
-var RequestSender;
-
-RequestSender = function(dialog, applicant, request) {
-
- this.dialog = dialog;
- this.applicant = applicant;
- this.request = request;
-
- // RFC3261 14.1 Modifying an Existing Session. UAC Behavior.
- this.reattempt = false;
- this.reattemptTimer = null;
-};
-
-RequestSender.prototype = {
- send: function() {
- var
- self = this,
- request_sender = new JsSIP.RequestSender(this, this.dialog.owner.ua);
-
- request_sender.send();
-
- // RFC3261 14.2 Modifying an Existing Session -UAC BEHAVIOR-
- if (this.request.method === JsSIP.C.INVITE && request_sender.clientTransaction.state !== JsSIP.Transactions.C.STATUS_TERMINATED) {
- this.dialog.uac_pending_reply = true;
- request_sender.clientTransaction.on('stateChanged', function stateChanged(e){
- if (e.sender.state === JsSIP.Transactions.C.STATUS_ACCEPTED ||
- e.sender.state === JsSIP.Transactions.C.STATUS_COMPLETED ||
- e.sender.state === JsSIP.Transactions.C.STATUS_TERMINATED) {
-
- request_sender.clientTransaction.removeListener('stateChanged', stateChanged);
- self.dialog.uac_pending_reply = false;
-
- if (self.dialog.uas_pending_reply === false) {
- self.dialog.owner.onReadyToReinvite();
- }
- }
- });
- }
- },
-
- onRequestTimeout: function() {
- this.applicant.onRequestTimeout();
- },
-
- onTransportError: function() {
- this.applicant.onTransportError();
- },
-
- receiveResponse: function(response) {
- var self = this;
-
- // RFC3261 12.2.1.2 408 or 481 is received for a request within a dialog.
- if (response.status_code === 408 || response.status_code === 481) {
- this.applicant.onDialogError(response);
- } else if (response.method === JsSIP.C.INVITE && response.status_code === 491) {
- if (this.reattempt) {
- this.applicant.receiveResponse(response);
- } else {
- this.request.cseq.value = this.dialog.local_seqnum += 1;
- this.reattemptTimer = window.setTimeout(
- function() {
- if (self.applicant.owner.status !== JsSIP.RTCSession.C.STATUS_TERMINATED) {
- self.reattempt = true;
- self.request_sender.send();
- }
- },
- this.getReattemptTimeout()
- );
- }
- } else {
- this.applicant.receiveResponse(response);
- }
- }
-};
-
-return RequestSender;
-}(JsSIP));
-
-
-var Dialog,
- C = {
- // Dialog states
- STATUS_EARLY: 1,
- STATUS_CONFIRMED: 2
- };
-
-// RFC 3261 12.1
-Dialog = function(owner, message, type, state) {
- var contact;
-
- this.uac_pending_reply = false;
- this.uas_pending_reply = false;
-
- if(!message.hasHeader('contact')) {
- return {
- error: 'unable to create a Dialog without Contact header field'
- };
- }
-
- if(message instanceof JsSIP.IncomingResponse) {
- state = (message.status_code < 200) ? C.STATUS_EARLY : C.STATUS_CONFIRMED;
- } else {
- // Create confirmed dialog if state is not defined
- state = state || C.STATUS_CONFIRMED;
- }
-
- contact = message.parseHeader('contact');
-
- // RFC 3261 12.1.1
- if(type === 'UAS') {
- this.id = {
- call_id: message.call_id,
- local_tag: message.to_tag,
- remote_tag: message.from_tag,
- toString: function() {
- return this.call_id + this.local_tag + this.remote_tag;
- }
- };
- this.state = state;
- this.remote_seqnum = message.cseq;
- this.local_uri = message.parseHeader('to').uri;
- this.remote_uri = message.parseHeader('from').uri;
- this.remote_target = contact.uri;
- this.route_set = message.getHeaders('record-route');
- }
- // RFC 3261 12.1.2
- else if(type === 'UAC') {
- this.id = {
- call_id: message.call_id,
- local_tag: message.from_tag,
- remote_tag: message.to_tag,
- toString: function() {
- return this.call_id + this.local_tag + this.remote_tag;
- }
- };
- this.state = state;
- this.local_seqnum = message.cseq;
- this.local_uri = message.parseHeader('from').uri;
- this.remote_uri = message.parseHeader('to').uri;
- this.remote_target = contact.uri;
- this.route_set = message.getHeaders('record-route').reverse();
- }
-
- this.logger = owner.ua.getLogger('jssip.dialog', this.id.toString());
- 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'));
-};
-
-Dialog.prototype = {
- /**
- * @param {JsSIP.IncomingMessage} message
- * @param {Enum} UAC/UAS
- */
- update: function(message, type) {
- this.state = C.STATUS_CONFIRMED;
-
- this.logger.log('dialog '+ this.id.toString() +' changed to CONFIRMED state');
-
- if(type === 'UAC') {
- // RFC 3261 13.2.2.4
- this.route_set = message.getHeaders('record-route').reverse();
- }
- },
-
- terminate: function() {
- this.logger.log('dialog ' + this.id.toString() + ' deleted');
- delete this.owner.ua.dialogs[this.id.toString()];
- },
-
- /**
- * @param {String} method request method
- * @param {Object} extraHeaders extra headers
- * @returns {JsSIP.OutgoingRequest}
- */
-
- // RFC 3261 12.2.1.1
- createRequest: function(method, extraHeaders, body) {
- var cseq, request;
- extraHeaders = extraHeaders && extraHeaders.slice() || [];
-
- if(!this.local_seqnum) { this.local_seqnum = Math.floor(Math.random() * 10000); }
-
- cseq = (method === JsSIP.C.CANCEL || method === JsSIP.C.ACK) ? this.local_seqnum : this.local_seqnum += 1;
-
- request = new JsSIP.OutgoingRequest(
- method,
- this.remote_target,
- this.owner.ua, {
- 'cseq': cseq,
- 'call_id': this.id.call_id,
- 'from_uri': this.local_uri,
- 'from_tag': this.id.local_tag,
- 'to_uri': this.remote_uri,
- 'to_tag': this.id.remote_tag,
- 'route_set': this.route_set
- }, extraHeaders, body);
-
- request.dialog = this;
-
- return request;
- },
-
- /**
- * @param {JsSIP.IncomingRequest} request
- * @returns {Boolean}
- */
-
- // RFC 3261 12.2.2
- checkInDialogRequest: function(request) {
- var self = this;
-
- if(!this.remote_seqnum) {
- this.remote_seqnum = request.cseq;
- } else if(request.cseq < this.remote_seqnum) {
- //Do not try to reply to an ACK request.
- if (request.method !== JsSIP.C.ACK) {
- request.reply(500);
- }
- return false;
- } else if(request.cseq > this.remote_seqnum) {
- this.remote_seqnum = request.cseq;
- }
-
- switch(request.method) {
- // RFC3261 14.2 Modifying an Existing Session -UAS BEHAVIOR-
- case JsSIP.C.INVITE:
- if (this.uac_pending_reply === true) {
- request.reply(491);
- } else if (this.uas_pending_reply === true) {
- var retryAfter = (Math.random() * 10 | 0) + 1;
- request.reply(500, null, ['Retry-After:'+ retryAfter]);
- return false;
- } else {
- this.uas_pending_reply = true;
- request.server_transaction.on('stateChanged', function stateChanged(e){
- if (e.sender.state === JsSIP.Transactions.C.STATUS_ACCEPTED ||
- e.sender.state === JsSIP.Transactions.C.STATUS_COMPLETED ||
- e.sender.state === JsSIP.Transactions.C.STATUS_TERMINATED) {
-
- request.server_transaction.removeListener('stateChanged', stateChanged);
- self.uas_pending_reply = false;
-
- if (self.uac_pending_reply === false) {
- self.owner.onReadyToReinvite();
- }
- }
- });
- }
-
- // RFC3261 12.2.2 Replace the dialog`s remote target URI if the request is accepted
- if(request.hasHeader('contact')) {
- request.server_transaction.on('stateChanged', function(e){
- if (e.sender.state === JsSIP.Transactions.C.STATUS_ACCEPTED) {
- self.remote_target = request.parseHeader('contact').uri;
- }
- });
- }
- break;
- case JsSIP.C.NOTIFY:
- // RFC6665 3.2 Replace the dialog`s remote target URI if the request is accepted
- if(request.hasHeader('contact')) {
- request.server_transaction.on('stateChanged', function(e){
- if (e.sender.state === JsSIP.Transactions.C.STATUS_COMPLETED) {
- self.remote_target = request.parseHeader('contact').uri;
- }
- });
- }
- break;
- }
-
- return true;
- },
-
- sendRequest: function(applicant, method, options) {
- options = options || {};
-
- var
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- body = options.body || null,
- request = this.createRequest(method, extraHeaders, body),
- request_sender = new RequestSender(this, applicant, request);
-
- request_sender.send();
- },
-
- /**
- * @param {JsSIP.IncomingRequest} request
- */
- receiveRequest: function(request) {
- //Check in-dialog request
- if(!this.checkInDialogRequest(request)) {
- return;
- }
-
- this.owner.receiveRequest(request);
- }
-};
-
-Dialog.C = C;
-JsSIP.Dialog = Dialog;
-}(JsSIP));
-
-
-
-/**
- * @fileoverview Request Sender
- */
-
-/**
- * @augments JsSIP
- * @class Class creating a request sender.
- * @param {Object} applicant
- * @param {JsSIP.UA} ua
- */
-(function(JsSIP) {
-var RequestSender;
-
-RequestSender = function(applicant, ua) {
- this.logger = ua.getLogger('jssip.requestsender');
- this.ua = ua;
- this.applicant = applicant;
- this.method = applicant.request.method;
- this.request = applicant.request;
- this.credentials = null;
- this.challenged = false;
- this.staled = false;
-
- // If ua is in closing process or even closed just allow sending Bye and ACK
- if (ua.status === JsSIP.UA.C.STATUS_USER_CLOSED && (this.method !== JsSIP.C.BYE || this.method !== JsSIP.C.ACK)) {
- this.onTransportError();
- }
-};
-
-/**
-* Create the client transaction and send the message.
-*/
-RequestSender.prototype = {
- send: function() {
- switch(this.method) {
- case "INVITE":
- this.clientTransaction = new JsSIP.Transactions.InviteClientTransaction(this, this.request, this.ua.transport);
- break;
- case "ACK":
- this.clientTransaction = new JsSIP.Transactions.AckClientTransaction(this, this.request, this.ua.transport);
- break;
- default:
- this.clientTransaction = new JsSIP.Transactions.NonInviteClientTransaction(this, this.request, this.ua.transport);
- }
- this.clientTransaction.send();
- },
-
- /**
- * Callback fired when receiving a request timeout error from the client transaction.
- * To be re-defined by the applicant.
- * @event
- */
- onRequestTimeout: function() {
- this.applicant.onRequestTimeout();
- },
-
- /**
- * Callback fired when receiving a transport error from the client transaction.
- * To be re-defined by the applicant.
- * @event
- */
- onTransportError: function() {
- this.applicant.onTransportError();
- },
-
- /**
- * Called from client transaction when receiving a correct response to the request.
- * Authenticate request if needed or pass the response back to the applicant.
- * @param {JsSIP.IncomingResponse} response
- */
- receiveResponse: function(response) {
- var cseq, challenge, authorization_header_name,
- status_code = response.status_code;
-
- /*
- * Authentication
- * Authenticate once. _challenged_ flag used to avoid infinite authentications.
- */
- if ((status_code === 401 || status_code === 407) && this.ua.configuration.password !== null) {
-
- // Get and parse the appropriate WWW-Authenticate or Proxy-Authenticate header.
- if (response.status_code === 401) {
- challenge = response.parseHeader('www-authenticate');
- authorization_header_name = 'authorization';
- } else {
- challenge = response.parseHeader('proxy-authenticate');
- authorization_header_name = 'proxy-authorization';
- }
-
- // Verify it seems a valid challenge.
- if (! challenge) {
- this.logger.warn(response.status_code + ' with wrong or missing challenge, cannot authenticate');
- this.applicant.receiveResponse(response);
- return;
- }
-
- if (!this.challenged || (!this.staled && challenge.stale === true)) {
- if (!this.credentials) {
- this.credentials = new JsSIP.DigestAuthentication(this.ua);
- }
-
- // Verify that the challenge is really valid.
- if (!this.credentials.authenticate(this.request, challenge)) {
- this.applicant.receiveResponse(response);
- return;
- }
- this.challenged = true;
-
- if (challenge.stale) {
- this.staled = true;
- }
-
- if (response.method === JsSIP.C.REGISTER) {
- cseq = this.applicant.cseq += 1;
- } else if (this.request.dialog){
- cseq = this.request.dialog.local_seqnum += 1;
- } else {
- cseq = this.request.cseq + 1;
- this.request.cseq = cseq;
- }
- this.request.setHeader('cseq', cseq +' '+ this.method);
-
- this.request.setHeader(authorization_header_name, this.credentials.toString());
- this.send();
- } else {
- this.applicant.receiveResponse(response);
- }
- } else {
- this.applicant.receiveResponse(response);
- }
- }
-};
-
-JsSIP.RequestSender = RequestSender;
-}(JsSIP));
-
-
-/**
- * @fileoverview Registrator Agent
- */
-
-/**
- * @augments JsSIP
- * @class Class creating a registrator agent.
- * @param {JsSIP.UA} ua
- * @param {JsSIP.Transport} transport
- */
-(function(JsSIP) {
-var Registrator;
-
-Registrator = function(ua, transport) {
- var reg_id=1; //Force reg_id to 1.
-
- this.logger = ua.getLogger('jssip.registrator');
-
- this.ua = ua;
- this.transport = transport;
-
- this.registrar = ua.configuration.registrar_server;
- this.expires = ua.configuration.register_expires;
-
- // Call-ID and CSeq values RFC3261 10.2
- this.call_id = JsSIP.Utils.createRandomToken(22);
- this.cseq = 80;
-
- // this.to_uri
- this.to_uri = ua.configuration.uri;
-
- this.registrationTimer = null;
-
- // Set status
- this.registered = this.registered_before = false;
-
- // Save into ua instance
- this.ua.registrator = this;
-
- // Contact header
- this.contact = this.ua.contact.toString();
-
- // sip.ice media feature tag (RFC 5768)
- this.contact += ';+sip.ice';
-
- this.extraHeaders = [];
-
- if(reg_id) {
- this.contact += ';reg-id='+ reg_id;
- this.contact += ';+sip.instance=""';
- }
-};
-
-Registrator.prototype = {
- /**
- * @param {Object} [options]
- */
- register: function(options) {
- var request_sender, cause, extraHeaders,
- self = this;
-
- options = options || {};
-
- if (options.extraHeaders && Object.keys(options.extraHeaders).length !== 0) {
- this.extraHeaders = options.extraHeaders && options.extraHeaders.slice();
- }
-
- extraHeaders = this.extraHeaders.slice();
- extraHeaders.push('Contact: '+ this.contact + ';expires=' + this.expires);
-
- this.request = new JsSIP.OutgoingRequest(JsSIP.C.REGISTER, this.registrar, this.ua, {
- 'to_uri': this.to_uri,
- 'call_id': this.call_id,
- 'cseq': (this.cseq += 1)
- }, extraHeaders);
-
- request_sender = new JsSIP.RequestSender(this, this.ua);
-
- /**
- * @private
- */
- this.receiveResponse = function(response) {
- var contact, expires,
- contacts = response.getHeaders('contact').length;
-
- // Discard responses to older REGISTER/un-REGISTER requests.
- if(response.cseq !== this.cseq) {
- return;
- }
-
- // Clear registration timer
- if (this.registrationTimer !== null) {
- window.clearTimeout(this.registrationTimer);
- this.registrationTimer = null;
- }
-
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- // Ignore provisional responses.
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- if(response.hasHeader('expires')) {
- expires = response.getHeader('expires');
- }
-
- // Search the Contact pointing to us and update the expires value accordingly.
- if (!contacts) {
- this.logger.warn('no Contact header in response to REGISTER, response ignored');
- break;
- }
-
- while(contacts--) {
- contact = response.parseHeader('contact', contacts);
- if(contact.uri.user === this.ua.contact.uri.user) {
- expires = contact.getParam('expires');
- break;
- } else {
- contact = null;
- }
- }
-
- if (!contact) {
- this.logger.warn('no Contact header pointing to us, response ignored');
- break;
- }
-
- if(!expires) {
- expires = this.expires;
- }
-
- // Re-Register before the expiration interval has elapsed.
- // For that, decrease the expires value. ie: 3 seconds
- this.registrationTimer = window.setTimeout(function() {
- self.registrationTimer = null;
- self.register();
- }, (expires * 1000) - 3000);
-
- //Save gruu values
- if (contact.hasParam('temp-gruu')) {
- this.ua.contact.temp_gruu = contact.getParam('temp-gruu').replace(/"/g,'');
- }
- if (contact.hasParam('pub-gruu')) {
- this.ua.contact.pub_gruu = contact.getParam('pub-gruu').replace(/"/g,'');
- }
-
- this.registered = true;
- this.ua.emit('registered', this.ua, {
- response: response
- });
- break;
- // Interval too brief RFC3261 10.2.8
- case /^423$/.test(response.status_code):
- if(response.hasHeader('min-expires')) {
- // Increase our registration interval to the suggested minimum
- this.expires = response.getHeader('min-expires');
- // Attempt the registration again immediately
- this.register();
- } else { //This response MUST contain a Min-Expires header field
- this.logger.warn('423 response received for REGISTER without Min-Expires');
- this.registrationFailure(response, JsSIP.C.causes.SIP_FAILURE_CODE);
- }
- break;
- default:
- cause = JsSIP.Utils.sipErrorCause(response.status_code);
- this.registrationFailure(response, cause);
- }
- };
-
- /**
- * @private
- */
- this.onRequestTimeout = function() {
- this.registrationFailure(null, JsSIP.C.causes.REQUEST_TIMEOUT);
- };
-
- /**
- * @private
- */
- this.onTransportError = function() {
- this.registrationFailure(null, JsSIP.C.causes.CONNECTION_ERROR);
- };
-
- request_sender.send();
- },
-
- /**
- * @param {Object} [options]
- */
- unregister: function(options) {
- var extraHeaders;
-
- if(!this.registered) {
- this.logger.warn('already unregistered');
- return;
- }
-
- options = options || {};
-
- if (options.extraHeaders && Object.keys(options.extraHeaders).length !== 0) {
- this.extraHeaders = options.extraHeaders && options.extraHeaders.slice();
- }
-
- extraHeaders = this.extraHeaders.slice();
-
- this.registered = false;
-
- // Clear the registration timer.
- if (this.registrationTimer !== null) {
- window.clearTimeout(this.registrationTimer);
- this.registrationTimer = null;
- }
-
- if(options.all) {
- extraHeaders.push('Contact: *');
- extraHeaders.push('Expires: 0');
-
- this.request = new JsSIP.OutgoingRequest(JsSIP.C.REGISTER, this.registrar, this.ua, {
- 'to_uri': this.to_uri,
- 'call_id': this.call_id,
- 'cseq': (this.cseq += 1)
- }, extraHeaders);
- } else {
- extraHeaders.push('Contact: '+ this.contact + ';expires=0');
-
- this.request = new JsSIP.OutgoingRequest(JsSIP.C.REGISTER, this.registrar, this.ua, {
- 'to_uri': this.to_uri,
- 'call_id': this.call_id,
- 'cseq': (this.cseq += 1)
- }, extraHeaders);
- }
-
- var request_sender = new JsSIP.RequestSender(this, this.ua);
-
- /**
- * @private
- */
- this.receiveResponse = function(response) {
- var cause;
-
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- // Ignore provisional responses.
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- this.unregistered(response);
- break;
- default:
- cause = JsSIP.Utils.sipErrorCause(response.status_code);
- this.unregistered(response, cause);
- }
- };
-
- /**
- * @private
- */
- this.onRequestTimeout = function() {
- this.unregistered(null, JsSIP.C.causes.REQUEST_TIMEOUT);
- };
-
- /**
- * @private
- */
- this.onTransportError = function() {
- this.unregistered(null, JsSIP.C.causes.CONNECTION_ERROR);
- };
-
- request_sender.send();
- },
-
- /**
- * @private
- */
- registrationFailure: function(response, cause) {
- this.ua.emit('registrationFailed', this.ua, {
- response: response || null,
- cause: cause
- });
-
- if (this.registered) {
- this.registered = false;
- this.ua.emit('unregistered', this.ua, {
- response: response || null,
- cause: cause
- });
- }
- },
-
- /**
- * @private
- */
- unregistered: function(response, cause) {
- this.registered = false;
- this.ua.emit('unregistered', this.ua, {
- response: response || null,
- cause: cause || null
- });
- },
-
- /**
- * @private
- */
- onTransportClosed: function() {
- this.registered_before = this.registered;
- if (this.registrationTimer !== null) {
- window.clearTimeout(this.registrationTimer);
- this.registrationTimer = null;
- }
-
- if(this.registered) {
- this.registered = false;
- this.ua.emit('unregistered', this.ua);
- }
- },
-
- /**
- * @private
- */
- onTransportConnected: function() {
- this.register();
- },
-
- /**
- * @private
- */
- close: function() {
- this.registered_before = this.registered;
- this.unregister();
- }
-};
-
-JsSIP.Registrator = Registrator;
-}(JsSIP));
-
-
-/**
- * @fileoverview Session
- */
-
-/**
- * @augments JsSIP
- * @class Invite Session
- */
-(function(JsSIP) {
-
-// Load dependencies
-var Request = /**
- * @fileoverview Request
- */
-
-/**
- * @class Request
- * @param {JsSIP.RTCSession} session
- */
-(function(JsSIP) {
-
-var Request = function(session) {
- var events = [
- 'progress',
- 'succeeded',
- 'failed'
- ];
-
- this.owner = session;
-
- this.logger = session.ua.getLogger('jssip.rtcsession.request', session.id);
- this.initEvents(events);
-};
-Request.prototype = new JsSIP.EventEmitter();
-
-
-Request.prototype.send = function(method, options) {
- options = options || {};
-
- var event,
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- eventHandlers = options.eventHandlers || {},
- body = options.body || null;
-
- if (method === undefined) {
- throw new TypeError('Not enough arguments');
- }
-
- // Check RTCSession Status
- if (this.owner.status !== JsSIP.RTCSession.C.STATUS_1XX_RECEIVED &&
- this.owner.status !== JsSIP.RTCSession.C.STATUS_WAITING_FOR_ANSWER &&
- this.owner.status !== JsSIP.RTCSession.C.STATUS_WAITING_FOR_ACK &&
- this.owner.status !== JsSIP.RTCSession.C.STATUS_CONFIRMED &&
- this.owner.status !== JsSIP.RTCSession.C.STATUS_TERMINATED) {
- throw new JsSIP.Exceptions.InvalidStateError(this.owner.status);
- }
-
- /*
- * Allow sending BYE in TERMINATED status since the RTCSession
- * could had been terminated before the ACK had arrived.
- * RFC3261 Section 15, Paragraph 2
- */
- else if (this.owner.status === C.STATUS_TERMINATED && method !== JsSIP.C.BYE) {
- throw new JsSIP.Exceptions.InvalidStateError(this.owner.status);
- }
-
- // Set event handlers
- for (event in eventHandlers) {
- this.on(event, eventHandlers[event]);
- }
-
- this.owner.dialog.sendRequest(this, method, {
- extraHeaders: extraHeaders,
- body: body
- });
-};
-
-/**
- * @private
- */
-Request.prototype.receiveResponse = function(response) {
- var cause;
-
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- this.emit('progress', this, {
- originator: 'remote',
- response: response
- });
- break;
-
- case /^2[0-9]{2}$/.test(response.status_code):
- this.emit('succeeded', this, {
- originator: 'remote',
- response: response
- });
- break;
-
- default:
- cause = JsSIP.Utils.sipErrorCause(response.status_code);
- this.emit('failed', this, {
- originator: 'remote',
- response: response,
- cause: cause
- });
- break;
- }
-};
-
-/**
- * @private
- */
-Request.prototype.onRequestTimeout = function() {
- this.emit('failed', this, {
- originator: 'system',
- cause: JsSIP.C.causes.REQUEST_TIMEOUT
- });
- this.owner.onRequestTimeout();
-};
-
-/**
- * @private
- */
-Request.prototype.onTransportError = function() {
- this.emit('failed', this, {
- originator: 'system',
- cause: JsSIP.C.causes.CONNECTION_ERROR
- });
- this.owner.onTransportError();
-};
-
-/**
- * @private
- */
-Request.prototype.onDialogError = function(response) {
- this.emit('failed', this, {
- originator: 'remote',
- response: response,
- cause: JsSIP.C.causes.DIALOG_ERROR
- });
- this.owner.onDialogError(response);
-};
-
-return Request;
-}(JsSIP));
-
-var RTCMediaHandler = /**
- * @fileoverview RTCMediaHandler
- */
-
-/* RTCMediaHandler
- * @class PeerConnection helper Class.
- * @param {JsSIP.RTCSession} session
- * @param {Object} [contraints]
- */
-(function(JsSIP){
-
-var RTCMediaHandler = function(session, constraints) {
- constraints = constraints || {};
-
- this.logger = session.ua.getLogger('jssip.rtcsession.rtcmediahandler', session.id);
- this.session = session;
- this.localMedia = null;
- this.peerConnection = null;
- this.ready = true;
-
- this.init(constraints);
-};
-
-RTCMediaHandler.prototype = {
- isReady: function() {
- return this.ready;
- },
-
- createOffer: function(onSuccess, onFailure, constraints) {
- var self = this;
-
- function onSetLocalDescriptionSuccess() {
- if (self.peerConnection.iceGatheringState === 'complete' && self.peerConnection.iceConnectionState === 'connected') {
- self.ready = true;
- onSuccess(self.peerConnection.localDescription.sdp);
- } else {
- self.onIceCompleted = function() {
- self.onIceCompleted = undefined;
- self.ready = true;
- onSuccess(self.peerConnection.localDescription.sdp);
- };
- }
- }
-
- this.ready = false;
-
- this.peerConnection.createOffer(
- function(sessionDescription){
- self.setLocalDescription(
- sessionDescription,
- onSetLocalDescriptionSuccess,
- function(e) {
- self.ready = true;
- onFailure(e);
- }
- );
- },
- function(e) {
- self.ready = true;
- self.logger.error('unable to create offer');
- self.logger.error(e);
- onFailure(e);
- },
- constraints
- );
- },
-
- createAnswer: function(onSuccess, onFailure, constraints) {
- var self = this;
-
- function onSetLocalDescriptionSuccess() {
- if (self.peerConnection.iceGatheringState === 'complete' && self.peerConnection.iceConnectionState === 'connected') {
- self.ready = true;
- onSuccess(self.peerConnection.localDescription.sdp);
- } else {
- self.onIceCompleted = function() {
- self.onIceCompleted = undefined;
- self.ready = true;
- onSuccess(self.peerConnection.localDescription.sdp);
- };
- }
- }
-
- this.ready = false;
-
- this.peerConnection.createAnswer(
- function(sessionDescription){
- self.setLocalDescription(
- sessionDescription,
- onSetLocalDescriptionSuccess,
- function(e) {
- self.ready = true;
- onFailure(e);
- }
- );
- },
- function(e) {
- self.ready = true;
- self.logger.error('unable to create answer');
- self.logger.error(e);
- onFailure(e);
- },
- constraints
- );
- },
-
- setLocalDescription: function(sessionDescription, onSuccess, onFailure) {
- var self = this;
-
- this.peerConnection.setLocalDescription(
- sessionDescription,
- onSuccess,
- function(e) {
- self.logger.error('unable to set local description');
- self.logger.error(e);
- onFailure(e);
- }
- );
- },
-
- addStream: function(stream, onSuccess, onFailure, constraints) {
- try {
- this.peerConnection.addStream(stream, constraints);
- } catch(e) {
- this.logger.error('error adding stream');
- this.logger.error(e);
- onFailure();
- return;
- }
-
- onSuccess();
- },
-
- /**
- * peerConnection creation.
- * @param {Function} onSuccess Fired when there are no more ICE candidates
- */
- init: function(options) {
- options = options || {};
-
- var idx, length, server,
- self = this,
- servers = [],
- constraints = options.constraints || {},
- stun_servers = options.stun_servers || null,
- turn_servers = options.turn_servers || null,
- config = this.session.ua.configuration;
-
- if (!stun_servers) {
- stun_servers = config.stun_servers;
- }
-
- if (!turn_servers) {
- turn_servers = config.turn_servers;
- }
-
- /* Change 'url' to 'urls' whenever this issue is solved:
- * https://code.google.com/p/webrtc/issues/detail?id=2096
- */
-
- if (stun_servers.length > 0) {
- servers.push({'url': stun_servers});
- }
-
- length = turn_servers.length;
- for (idx = 0; idx < length; idx++) {
- server = turn_servers[idx];
- servers.push({
- 'url': server.urls,
- 'username': server.username,
- 'credential': server.credential
- });
- }
-
- this.peerConnection = new JsSIP.WebRTC.RTCPeerConnection({'iceServers': servers}, constraints);
-
- this.peerConnection.onaddstream = function(e) {
- self.logger.log('stream added: '+ e.stream.id);
- };
-
- this.peerConnection.onremovestream = function(e) {
- self.logger.log('stream removed: '+ e.stream.id);
- };
-
- this.peerConnection.onicecandidate = function(e) {
- if (e.candidate) {
- self.logger.log('ICE candidate received: '+ e.candidate.candidate);
- } else if (self.onIceCompleted !== undefined) {
- self.onIceCompleted();
- }
- };
-
- this.peerConnection.oniceconnectionstatechange = function() {
- self.logger.log('ICE connection state changed to "'+ this.iceConnectionState +'"');
-
- if (this.iceConnectionState === 'disconnected') {
- self.session.terminate({
- cause: JsSIP.C.causes.RTP_TIMEOUT,
- status_code: 200,
- reason_phrase: JsSIP.C.causes.RTP_TIMEOUT
- });
- }
- };
-
-
- this.peerConnection.onstatechange = function() {
- self.logger.log('PeerConnection state changed to "'+ this.readyState +'"');
- };
- },
-
- close: function() {
- this.logger.log('closing PeerConnection');
- if(this.peerConnection) {
- this.peerConnection.close();
-
- if(this.localMedia) {
- this.localMedia.stop();
- }
- }
- },
-
- /**
- * @param {Object} mediaConstraints
- * @param {Function} onSuccess
- * @param {Function} onFailure
- */
- getUserMedia: function(onSuccess, onFailure, constraints) {
- var self = this;
-
- this.logger.log('requesting access to local media');
-
- JsSIP.WebRTC.getUserMedia(constraints,
- function(stream) {
- self.logger.log('got local media stream');
- self.localMedia = stream;
- onSuccess(stream);
- },
- function(e) {
- self.logger.error('unable to get user media');
- self.logger.error(e);
- onFailure();
- }
- );
- },
-
- /**
- * Message reception.
- * @param {String} type
- * @param {String} sdp
- * @param {Function} onSuccess
- * @param {Function} onFailure
- */
- onMessage: function(type, body, onSuccess, onFailure) {
- this.peerConnection.setRemoteDescription(
- new JsSIP.WebRTC.RTCSessionDescription({type: type, sdp:body}),
- onSuccess,
- onFailure
- );
- }
-};
-
-// Return since it will be assigned to a variable.
-return RTCMediaHandler;
-}(JsSIP));
-
-var DTMF = /**
- * @fileoverview DTMF
- */
-
-/**
- * @class DTMF
- * @param {JsSIP.RTCSession} session
- */
-(function(JsSIP) {
-
-var DTMF,
- C = {
- MIN_DURATION: 70,
- MAX_DURATION: 6000,
- DEFAULT_DURATION: 100,
- MIN_INTER_TONE_GAP: 50,
- DEFAULT_INTER_TONE_GAP: 500
- };
-
-DTMF = function(session) {
- var events = [
- 'succeeded',
- 'failed'
- ];
-
- this.logger = session.ua.getLogger('jssip.rtcsession.dtmf', session.id);
- this.owner = session;
- this.direction = null;
- this.tone = null;
- this.duration = null;
-
- this.initEvents(events);
-};
-DTMF.prototype = new JsSIP.EventEmitter();
-
-
-DTMF.prototype.send = function(tone, options) {
- var event, eventHandlers, extraHeaders, body;
-
- if (tone === undefined) {
- throw new TypeError('Not enough arguments');
- }
-
- this.direction = 'outgoing';
-
- // Check RTCSession Status
- if (this.owner.status !== JsSIP.RTCSession.C.STATUS_CONFIRMED &&
- this.owner.status !== JsSIP.RTCSession.C.STATUS_WAITING_FOR_ACK) {
- throw new JsSIP.Exceptions.InvalidStateError(this.owner.status);
- }
-
- // Get DTMF options
- options = options || {};
- extraHeaders = options.extraHeaders ? options.extraHeaders.slice() : [];
- eventHandlers = options.eventHandlers || {};
-
- // Check tone type
- if (typeof tone === 'string' ) {
- tone = tone.toUpperCase();
- } else if (typeof tone === 'number') {
- tone = tone.toString();
- } else {
- throw new TypeError('Invalid tone: '+ tone);
- }
-
- // Check tone value
- if (!tone.match(/^[0-9A-D#*]$/)) {
- throw new TypeError('Invalid tone: '+ tone);
- } else {
- this.tone = tone;
- }
-
- // Duration is checked/corrected in RTCSession
- this.duration = options.duration;
-
- // Set event handlers
- for (event in eventHandlers) {
- this.on(event, eventHandlers[event]);
- }
-
- extraHeaders.push('Content-Type: application/dtmf-relay');
-
- body = "Signal= " + this.tone + "\r\n";
- body += "Duration= " + this.duration;
-
- this.owner.emit('newDTMF', this.owner, {
- originator: 'local',
- dtmf: this,
- request: this.request
- });
-
- this.owner.dialog.sendRequest(this, JsSIP.C.INFO, {
- extraHeaders: extraHeaders,
- body: body
- });
-};
-
-/**
- * @private
- */
-DTMF.prototype.receiveResponse = function(response) {
- var cause;
-
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- // Ignore provisional responses.
- break;
-
- case /^2[0-9]{2}$/.test(response.status_code):
- this.emit('succeeded', this, {
- originator: 'remote',
- response: response
- });
- break;
-
- default:
- cause = JsSIP.Utils.sipErrorCause(response.status_code);
- this.emit('failed', this, {
- originator: 'remote',
- response: response,
- cause: cause
- });
- break;
- }
-};
-
-/**
- * @private
- */
-DTMF.prototype.onRequestTimeout = function() {
- this.emit('failed', this, {
- originator: 'system',
- cause: JsSIP.C.causes.REQUEST_TIMEOUT
- });
- this.owner.onRequestTimeout();
-};
-
-/**
- * @private
- */
-DTMF.prototype.onTransportError = function() {
- this.emit('failed', this, {
- originator: 'system',
- cause: JsSIP.C.causes.CONNECTION_ERROR
- });
- this.owner.onTransportError();
-};
-
-/**
- * @private
- */
-DTMF.prototype.onDialogError = function(response) {
- this.emit('failed', this, {
- originator: 'remote',
- response: response,
- cause: JsSIP.C.causes.DIALOG_ERROR
- });
- this.owner.onDialogError(response);
-};
-
-/**
- * @private
- */
-DTMF.prototype.init_incoming = function(request) {
- var body,
- reg_tone = /^(Signal\s*?=\s*?)([0-9A-D#*]{1})(\s)?.*/,
- reg_duration = /^(Duration\s?=\s?)([0-9]{1,4})(\s)?.*/;
-
- this.direction = 'incoming';
- this.request = request;
-
- request.reply(200);
-
- if (request.body) {
- body = request.body.split('\r\n');
- if (body.length === 2) {
- if (reg_tone.test(body[0])) {
- this.tone = body[0].replace(reg_tone,"$2");
- }
- if (reg_duration.test(body[1])) {
- this.duration = parseInt(body[1].replace(reg_duration,"$2"), 10);
- }
- }
- }
-
- if (!this.tone || !this.duration) {
- this.logger.warn('invalid INFO DTMF received, discarded');
- } else {
- this.owner.emit('newDTMF', this.owner, {
- originator: 'remote',
- dtmf: this,
- request: request
- });
- }
-};
-
-DTMF.C = C;
-return DTMF;
-}(JsSIP));
-
-
-var RTCSession,
- C = {
- // RTCSession states
- STATUS_NULL: 0,
- STATUS_INVITE_SENT: 1,
- STATUS_1XX_RECEIVED: 2,
- STATUS_INVITE_RECEIVED: 3,
- STATUS_WAITING_FOR_ANSWER: 4,
- STATUS_ANSWERED: 5,
- STATUS_WAITING_FOR_ACK: 6,
- STATUS_CANCELED: 7,
- STATUS_TERMINATED: 8,
- STATUS_CONFIRMED: 9
- };
-
-
-RTCSession = function(ua) {
- var events = [
- 'connecting',
- 'progress',
- 'failed',
- 'started',
- 'ended',
- 'newDTMF',
- 'hold',
- 'unhold',
- 'muted',
- 'unmuted'
- ];
-
- this.ua = ua;
- this.status = C.STATUS_NULL;
- this.dialog = null;
- this.earlyDialogs = {};
- this.rtcMediaHandler = null;
-
- // Session Timers
- this.timers = {
- ackTimer: null,
- expiresTimer: null,
- invite2xxTimer: null,
- userNoAnswerTimer: null
- };
-
- // Session info
- this.direction = null;
- this.local_identity = null;
- this.remote_identity = null;
- this.start_time = null;
- this.end_time = null;
- this.tones = null;
-
- // Mute/Hold state
- this.audioMuted = false;
- this.videoMuted = false;
- this.local_hold = false;
- this.remote_hold = false;
-
- this.pending_actions = {
- actions: [],
-
- length: function() {
- return this.actions.length;
- },
-
- isPending: function(name){
- var
- idx = 0,
- length = this.actions.length;
-
- for (idx; idx= 700)) {
- throw new TypeError('Invalid status_code: '+ status_code);
- } else if (status_code) {
- reason_phrase = reason_phrase || JsSIP.C.REASON_PHRASE[status_code] || '';
- cancel_reason = 'SIP ;cause=' + status_code + ' ;text="' + reason_phrase + '"';
- }
-
- // Check Session Status
- if (this.status === C.STATUS_NULL) {
- this.isCanceled = true;
- this.cancelReason = cancel_reason;
- } else if (this.status === C.STATUS_INVITE_SENT) {
- if(this.received_100) {
- this.request.cancel(cancel_reason);
- } else {
- this.isCanceled = true;
- this.cancelReason = cancel_reason;
- }
- } else if(this.status === C.STATUS_1XX_RECEIVED) {
- this.request.cancel(cancel_reason);
- }
-
- this.failed('local', null, JsSIP.C.causes.CANCELED);
- break;
-
- // - UAS -
- case C.STATUS_WAITING_FOR_ANSWER:
- case C.STATUS_ANSWERED:
- this.logger.log('rejecting RTCSession');
-
- status_code = status_code || 480;
-
- if (status_code < 300 || status_code >= 700) {
- throw new TypeError('Invalid status_code: '+ status_code);
- }
-
- this.request.reply(status_code, reason_phrase, extraHeaders, body);
- this.failed('local', null, JsSIP.C.causes.REJECTED);
- break;
-
- case C.STATUS_WAITING_FOR_ACK:
- case C.STATUS_CONFIRMED:
- this.logger.log('terminating RTCSession');
-
- reason_phrase = options.reason_phrase || JsSIP.C.REASON_PHRASE[status_code] || '';
-
- if (status_code && (status_code < 200 || status_code >= 700)) {
- throw new TypeError('Invalid status_code: '+ status_code);
- } else if (status_code) {
- extraHeaders.push('Reason: SIP ;cause=' + status_code + '; text="' + reason_phrase + '"');
- }
-
- /* RFC 3261 section 15 (Terminating a session):
- *
- * "...the callee's UA MUST NOT send a BYE on a confirmed dialog
- * until it has received an ACK for its 2xx response or until the server
- * transaction times out."
- */
- if (this.status === C.STATUS_WAITING_FOR_ACK &&
- this.direction === 'incoming' &&
- this.request.server_transaction.state !== JsSIP.Transactions.C.STATUS_TERMINATED) {
-
- // Save the dialog for later restoration
- dialog = this.dialog;
-
- // Send the BYE as soon as the ACK is received...
- this.receiveRequest = function(request) {
- if(request.method === JsSIP.C.ACK) {
- this.sendRequest(JsSIP.C.BYE, {
- extraHeaders: extraHeaders,
- body: body
- });
- dialog.terminate();
- }
- };
-
- // .., or when the INVITE transaction times out
- this.request.server_transaction.on('stateChanged', function(e){
- if (e.sender.state === JsSIP.Transactions.C.STATUS_TERMINATED) {
- self.sendRequest(JsSIP.C.BYE, {
- extraHeaders: extraHeaders,
- body: body
- });
- dialog.terminate();
- }
- });
-
- this.ended('local', null, cause);
-
- // Restore the dialog into 'this' in order to be able to send the in-dialog BYE :-)
- this.dialog = dialog;
-
- // Restore the dialog into 'ua' so the ACK can reach 'this' session
- this.ua.dialogs[dialog.id.toString()] = dialog;
-
- } else {
- this.sendRequest(JsSIP.C.BYE, {
- extraHeaders: extraHeaders,
- body: body
- });
-
- this.ended('local', null, cause);
- }
- }
-
- this.close();
-};
-
-/**
- * Answer the call.
- * @param {Object} [options]
- */
-RTCSession.prototype.answer = function(options) {
- options = options || {};
-
- var idx, length, hasAudio, hasVideo,
- self = this,
- request = this.request,
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- mediaConstraints = options.mediaConstraints || {'audio':true, 'video':true},
- RTCAnswerConstraints = options.RTCAnswerConstraints || {},
- mediaStream = options.mediaStream || null,
-
- // User media succeeded
- userMediaSucceeded = function(stream) {
- self.rtcMediaHandler.addStream(
- stream,
- streamAdditionSucceeded,
- streamAdditionFailed
- );
- },
-
- // User media failed
- userMediaFailed = function() {
- request.reply(480);
- self.failed('local', null, JsSIP.C.causes.USER_DENIED_MEDIA_ACCESS);
- },
-
- // rtcMediaHandler.addStream successfully added
- streamAdditionSucceeded = function() {
- self.connecting(request);
-
- if (self.status === C.STATUS_TERMINATED) {
- return;
- }
-
- self.rtcMediaHandler.createAnswer(
- answerCreationSucceeded,
- answerCreationFailed,
- RTCAnswerConstraints
- );
- },
-
- // rtcMediaHandler.addStream failed
- streamAdditionFailed = function() {
- if (self.status === C.STATUS_TERMINATED) {
- return;
- }
-
- self.failed('system', null, JsSIP.C.causes.WEBRTC_ERROR);
- },
-
- // rtcMediaHandler.createAnswer succeeded
- answerCreationSucceeded = function(body) {
- var
- // run for reply success callback
- replySucceeded = function() {
- self.status = C.STATUS_WAITING_FOR_ACK;
-
- self.setInvite2xxTimer(request, body);
- self.setACKTimer();
- self.started('local');
- },
-
- // run for reply failure callback
- replyFailed = function() {
- self.failed('system', null, JsSIP.C.causes.CONNECTION_ERROR);
- };
-
- request.reply(200, null, extraHeaders,
- body,
- replySucceeded,
- replyFailed
- );
- },
-
- // rtcMediaHandler.createAnsewr failed
- answerCreationFailed = function() {
- if (self.status === C.STATUS_TERMINATED) {
- return;
- }
-
- self.failed('system', null, JsSIP.C.causes.WEBRTC_ERROR);
- };
-
-
- // Check Session Direction and Status
- if (this.direction !== 'incoming') {
- throw new JsSIP.Exceptions.NotSupportedError('"answer" not supported for outgoing RTCSession');
- } else if (this.status !== C.STATUS_WAITING_FOR_ANSWER) {
- throw new JsSIP.Exceptions.InvalidStateError(this.status);
- }
-
- this.status = C.STATUS_ANSWERED;
-
- // An error on dialog creation will fire 'failed' event
- if(!this.createDialog(request, 'UAS')) {
- request.reply(500, 'Missing Contact header field');
- return;
- }
-
- window.clearTimeout(this.timers.userNoAnswerTimer);
-
- extraHeaders.unshift('Contact: ' + self.contact);
-
- length = this.getRemoteStreams().length;
-
- for (idx=0; idx 0) {
- hasAudio=true;
- }
- if (this.getRemoteStreams()[idx].getVideoTracks().length > 0) {
- hasVideo=true;
- }
- }
-
- if (!hasAudio && mediaConstraints.audio === true) {
- mediaConstraints.audio = false;
- if (mediaStream) {
- length = mediaStream.getAudioTracks().length;
- for (idx=0; idx DTMF.C.MAX_DURATION) {
- this.logger.warn('"duration" value is greater than the maximum allowed, setting it to '+ DTMF.C.MAX_DURATION +' milliseconds');
- duration = DTMF.C.MAX_DURATION;
- } else {
- duration = Math.abs(duration);
- }
- options.duration = duration;
-
- // Check interToneGap
- if (interToneGap && !JsSIP.Utils.isDecimal(interToneGap)) {
- throw new TypeError('Invalid interToneGap: '+ interToneGap);
- } else if (!interToneGap) {
- interToneGap = DTMF.C.DEFAULT_INTER_TONE_GAP;
- } else if (interToneGap < DTMF.C.MIN_INTER_TONE_GAP) {
- this.logger.warn('"interToneGap" value is lower than the minimum allowed, setting it to '+ DTMF.C.MIN_INTER_TONE_GAP +' milliseconds');
- interToneGap = DTMF.C.MIN_INTER_TONE_GAP;
- } else {
- interToneGap = Math.abs(interToneGap);
- }
-
- if (this.tones) {
- // Tones are already queued, just add to the queue
- this.tones += tones;
- return;
- }
-
- // New set of tones to start sending
- this.tones = tones;
-
- var sendDTMF = function () {
- var tone, timeout,
- tones = self.tones;
-
- if (self.status === C.STATUS_TERMINATED || !tones || position >= tones.length) {
- // Stop sending DTMF
- self.tones = null;
- return;
- }
-
- tone = tones[position];
- position += 1;
-
- if (tone === ',') {
- timeout = 2000;
- } else {
- var dtmf = new DTMF(self);
- dtmf.on('failed', function(){self.tones = null;});
- dtmf.send(tone, options);
- timeout = duration + interToneGap;
- }
-
- // Set timeout for the next tone
- window.setTimeout(sendDTMF, timeout);
- };
-
- // Send the first tone
- sendDTMF();
-};
-
-/**
- * Send a generic in-dialog Request
- *
- * @param {String} method
- * @param {Object} [options]
- */
-RTCSession.prototype.sendRequest = function(method, options) {
- var request = new Request(this);
-
- request.send(method, options);
-};
-
-/**
- * Check if RTCSession is ready for a re-INVITE
- *
- * @returns {Boolean}
- */
-RTCSession.prototype.isReadyToReinvite = function() {
- // rtcMediaHandler is not ready
- if (!this.rtcMediaHandler.isReady()) {
- return;
- }
-
- // Another INVITE transaction is in progress
- if (this.dialog.uac_pending_reply === true || this.dialog.uas_pending_reply === true) {
- return false;
- } else {
- return true;
- }
-};
-
-
-/**
- * Mute
- */
-RTCSession.prototype.mute = function(options) {
- options = options || {audio:true, video:false};
-
- var
- audioMuted = false,
- videoMuted = false;
-
- if (this.audioMuted === false && options.audio) {
- audioMuted = true;
- this.audioMuted = true;
- this.toogleMuteAudio(true);
- }
-
- if (this.videoMuted === false && options.video) {
- videoMuted = true;
- this.videoMuted = true;
- this.toogleMuteVideo(true);
- }
-
- if (audioMuted === true || videoMuted === true) {
- this.onmute({
- audio: audioMuted,
- video: videoMuted
- });
- }
-};
-
-/**
- * Unmute
- */
-RTCSession.prototype.unmute = function(options) {
- options = options || {audio:true, video:true};
-
- var
- audioUnMuted = false,
- videoUnMuted = false;
-
- if (this.audioMuted === true && options.audio) {
- audioUnMuted = true;
- this.audioMuted = false;
-
- if (this.local_hold === false) {
- this.toogleMuteAudio(false);
- }
- }
-
- if (this.videoMuted === true && options.video) {
- videoUnMuted = true;
- this.videoMuted = false;
-
- if (this.local_hold === false) {
- this.toogleMuteVideo(false);
- }
- }
-
- if (audioUnMuted === true || videoUnMuted === true) {
- this.onunmute({
- audio: audioUnMuted,
- video: videoUnMuted
- });
- }
-};
-
-/**
- * isMuted
- */
-RTCSession.prototype.isMuted = function() {
- return {
- audio: this.audioMuted,
- video: this.videoMuted
- };
-};
-
-/**
- * Hold
- */
-RTCSession.prototype.hold = function() {
-
- if (this.status !== C.STATUS_WAITING_FOR_ACK && this.status !== C.STATUS_CONFIRMED) {
- throw new JsSIP.Exceptions.InvalidStateError(this.status);
- }
-
- this.toogleMuteAudio(true);
- this.toogleMuteVideo(true);
-
- if (!this.isReadyToReinvite()) {
- /* If there is a pending 'unhold' action, cancel it and don't queue this one
- * Else, if there isn't any 'hold' action, add this one to the queue
- * Else, if there is already a 'hold' action, skip
- */
- if (this.pending_actions.isPending('unhold')) {
- this.pending_actions.pop('unhold');
- return;
- } else if (!this.pending_actions.isPending('hold')) {
- this.pending_actions.push('hold');
- return;
- } else {
- return;
- }
- } else {
- if (this.local_hold === true) {
- return;
- }
- }
-
- this.onhold('local');
-
- this.sendReinvite({
- mangle: function(body){
- var idx, length;
-
- body = JsSIP.Parser.parseSDP(body);
-
- length = body.media.length;
- for (idx=0; idx JsSIP.Timers.T2) {
- timeout = JsSIP.Timers.T2;
- }
- }
- self.timers.invite2xxTimer = window.setTimeout(
- invite2xxRetransmission, timeout
- );
- }, timeout);
-};
-
-
-/**
- * RFC3261 14.2
- * If a UAS generates a 2xx response and never receives an ACK,
- * it SHOULD generate a BYE to terminate the dialog.
- */
-RTCSession.prototype.setACKTimer = function() {
- var self = this;
-
- this.timers.ackTimer = window.setTimeout(function() {
- if(self.status === C.STATUS_WAITING_FOR_ACK) {
- this.logger.log('no ACK received, terminating the call');
- window.clearTimeout(self.timers.invite2xxTimer);
- self.sendRequest(JsSIP.C.BYE);
- self.ended('remote', null, JsSIP.C.causes.NO_ACK);
- }
- }, JsSIP.Timers.TIMER_H);
-};
-
-
-
-/**
- * RTCPeerconnection handlers
- */
-RTCSession.prototype.getLocalStreams = function() {
- return this.rtcMediaHandler &&
- this.rtcMediaHandler.peerConnection &&
- this.rtcMediaHandler.peerConnection.getLocalStreams() || [];
-};
-
-RTCSession.prototype.getRemoteStreams = function() {
- return this.rtcMediaHandler &&
- this.rtcMediaHandler.peerConnection &&
- this.rtcMediaHandler.peerConnection.getRemoteStreams() || [];
-};
-
-
-/**
- * Session Management
- */
-
-/**
-* @private
-*/
-RTCSession.prototype.init_incoming = function(request) {
- var expires,
- self = this,
- contentType = request.getHeader('Content-Type');
-
- // Check body and content type
- if(!request.body || (contentType !== 'application/sdp')) {
- request.reply(415);
- return;
- }
-
- // Session parameter initialization
- this.status = C.STATUS_INVITE_RECEIVED;
- this.from_tag = request.from_tag;
- this.id = request.call_id + this.from_tag;
- this.request = request;
- this.contact = this.ua.contact.toString();
-
- this.logger = this.ua.getLogger('jssip.rtcsession', this.id);
-
- //Save the session into the ua sessions collection.
- this.ua.sessions[this.id] = this;
-
- //Get the Expires header value if exists
- if(request.hasHeader('expires')) {
- expires = request.getHeader('expires') * 1000;
- }
-
- /* Set the to_tag before
- * replying a response code that will create a dialog.
- */
- request.to_tag = JsSIP.Utils.newTag();
-
- // An error on dialog creation will fire 'failed' event
- if(!this.createDialog(request, 'UAS', true)) {
- request.reply(500, 'Missing Contact header field');
- return;
- }
-
- //Initialize Media Session
- this.rtcMediaHandler = new RTCMediaHandler(this, {
- RTCConstraints: {"optional": [{'DtlsSrtpKeyAgreement': 'true'}]}
- });
-
- this.rtcMediaHandler.onMessage(
- 'offer',
- request.body,
- /*
- * onSuccess
- * SDP Offer is valid. Fire UA newRTCSession
- */
- function() {
- request.reply(180, null, ['Contact: ' + self.contact]);
- self.status = C.STATUS_WAITING_FOR_ANSWER;
-
- // Set userNoAnswerTimer
- self.timers.userNoAnswerTimer = window.setTimeout(function() {
- request.reply(408);
- self.failed('local',null, JsSIP.C.causes.NO_ANSWER);
- }, self.ua.configuration.no_answer_timeout
- );
-
- /* Set expiresTimer
- * RFC3261 13.3.1
- */
- if (expires) {
- self.timers.expiresTimer = window.setTimeout(function() {
- if(self.status === C.STATUS_WAITING_FOR_ANSWER) {
- request.reply(487);
- self.failed('system', null, JsSIP.C.causes.EXPIRES);
- }
- }, expires
- );
- }
-
- self.newRTCSession('remote', request);
- },
- /*
- * onFailure
- * Bad media description
- */
- function(e) {
- self.logger.warn('invalid SDP');
- self.logger.warn(e);
- request.reply(488);
- }
- );
-};
-
-/**
- * @private
- */
-RTCSession.prototype.connect = function(target, options) {
- options = options || {};
-
- var event, requestParams, iceServers,
- originalTarget = target,
- eventHandlers = options.eventHandlers || {},
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- mediaConstraints = options.mediaConstraints || {audio: true, video: true},
- mediaStream = options.mediaStream || null,
- RTCConstraints = options.RTCConstraints || {},
- RTCOfferConstraints = options.RTCOfferConstraints || {},
- stun_servers = options.stun_servers || null,
- turn_servers = options.turn_servers || null;
-
- if (stun_servers) {
- iceServers = JsSIP.UA.configuration_check.optional['stun_servers'](stun_servers);
- if (!iceServers) {
- throw new TypeError('Invalid stun_servers: '+ stun_servers);
- } else {
- stun_servers = iceServers;
- }
- }
-
- if (turn_servers) {
- iceServers = JsSIP.UA.configuration_check.optional['turn_servers'](turn_servers);
- if (!iceServers){
- throw new TypeError('Invalid turn_servers: '+ turn_servers);
- } else {
- turn_servers = iceServers;
- }
- }
-
- if (target === undefined) {
- throw new TypeError('Not enough arguments');
- }
-
- // Check WebRTC support
- if (!JsSIP.WebRTC.isSupported) {
- throw new JsSIP.Exceptions.NotSupportedError('WebRTC not supported');
- }
-
- // Check target validity
- target = this.ua.normalizeTarget(target);
- if (!target) {
- throw new TypeError('Invalid target: '+ originalTarget);
- }
-
- // Check Session Status
- if (this.status !== C.STATUS_NULL) {
- throw new JsSIP.Exceptions.InvalidStateError(this.status);
- }
-
- // Set event handlers
- for (event in eventHandlers) {
- this.on(event, eventHandlers[event]);
- }
-
- // Session parameter initialization
- this.from_tag = JsSIP.Utils.newTag();
-
- // Set anonymous property
- this.anonymous = options.anonymous || false;
-
- // OutgoingSession specific parameters
- this.isCanceled = false;
- this.received_100 = false;
-
- requestParams = {from_tag: this.from_tag};
-
- this.contact = this.ua.contact.toString({
- anonymous: this.anonymous,
- outbound: true
- });
-
- if (this.anonymous) {
- requestParams.from_display_name = 'Anonymous';
- requestParams.from_uri = 'sip:anonymous@anonymous.invalid';
-
- extraHeaders.push('P-Preferred-Identity: '+ this.ua.configuration.uri.toString());
- extraHeaders.push('Privacy: id');
- }
-
- extraHeaders.push('Contact: '+ this.contact);
- extraHeaders.push('Content-Type: application/sdp');
-
- this.request = new JsSIP.OutgoingRequest(JsSIP.C.INVITE, target, this.ua, requestParams, extraHeaders);
-
- this.id = this.request.call_id + this.from_tag;
-
- this.logger = this.ua.getLogger('jssip.rtcsession', this.id);
-
- this.rtcMediaHandler = new RTCMediaHandler(this, {
- RTCConstraints: RTCConstraints,
- stun_servers: stun_servers,
- turn_servers: turn_servers
- });
-
- //Save the session into the ua sessions collection.
- this.ua.sessions[this.id] = this;
-
- this.newRTCSession('local', this.request);
-
- this.sendInitialRequest(mediaConstraints, RTCOfferConstraints, mediaStream);
-};
-
-/**
-* @private
-*/
-RTCSession.prototype.close = function() {
- var idx;
-
- if(this.status === C.STATUS_TERMINATED) {
- return;
- }
-
- this.logger.log('closing INVITE session ' + this.id);
-
- // 1st Step. Terminate media.
- if (this.rtcMediaHandler){
- this.rtcMediaHandler.close();
- }
-
- // 2nd Step. Terminate signaling.
-
- // Clear session timers
- for(idx in this.timers) {
- window.clearTimeout(this.timers[idx]);
- }
-
- // Terminate dialogs
-
- // Terminate confirmed dialog
- if(this.dialog) {
- this.dialog.terminate();
- delete this.dialog;
- }
-
- // Terminate early dialogs
- for(idx in this.earlyDialogs) {
- this.earlyDialogs[idx].terminate();
- delete this.earlyDialogs[idx];
- }
-
- this.status = C.STATUS_TERMINATED;
-
- delete this.ua.sessions[this.id];
-};
-
-/**
- * Dialog Management
- * @private
- */
-RTCSession.prototype.createDialog = function(message, type, early) {
- var dialog, early_dialog,
- local_tag = (type === 'UAS') ? message.to_tag : message.from_tag,
- remote_tag = (type === 'UAS') ? message.from_tag : message.to_tag,
- id = message.call_id + local_tag + remote_tag;
-
- early_dialog = this.earlyDialogs[id];
-
- // Early Dialog
- if (early) {
- if (early_dialog) {
- return true;
- } else {
- early_dialog = new JsSIP.Dialog(this, message, type, JsSIP.Dialog.C.STATUS_EARLY);
-
- // Dialog has been successfully created.
- if(early_dialog.error) {
- this.logger.error(dialog.error);
- this.failed('remote', message, JsSIP.C.causes.INTERNAL_ERROR);
- return false;
- } else {
- this.earlyDialogs[id] = early_dialog;
- return true;
- }
- }
- }
-
- // Confirmed Dialog
- else {
- // In case the dialog is in _early_ state, update it
- if (early_dialog) {
- early_dialog.update(message, type);
- this.dialog = early_dialog;
- delete this.earlyDialogs[id];
- return true;
- }
-
- // Otherwise, create a _confirmed_ dialog
- dialog = new JsSIP.Dialog(this, message, type);
-
- if(dialog.error) {
- this.logger.error(dialog.error);
- this.failed('remote', message, JsSIP.C.causes.INTERNAL_ERROR);
- return false;
- } else {
- this.to_tag = message.to_tag;
- this.dialog = dialog;
- return true;
- }
- }
-};
-
-/**
- * In dialog INVITE Reception
- * @private
- */
-
-RTCSession.prototype.receiveReinvite = function(request) {
- var
- sdp, idx, direction,
- self = this,
- contentType = request.getHeader('Content-Type'),
- hold = true;
-
- if (request.body) {
- if (contentType !== 'application/sdp') {
- this.logger.warn('invalid Content-Type');
- request.reply(415);
- return;
- }
-
- sdp = JsSIP.Parser.parseSDP(request.body);
-
- for (idx=0; idx < sdp.media.length; idx++) {
- direction = sdp.direction || sdp.media[idx].direction || 'sendrecv';
-
- if (direction !== 'sendonly' && direction !== 'inactive') {
- hold = false;
- }
- }
-
- this.rtcMediaHandler.onMessage(
- 'offer',
- request.body,
- /*
- * onSuccess
- * SDP Offer is valid
- */
- function() {
- self.rtcMediaHandler.createAnswer(
- function(body) {
- request.reply(200, null, ['Contact: ' + self.contact], body,
- function() {
- self.status = C.STATUS_WAITING_FOR_ACK;
- self.setInvite2xxTimer(request, body);
- self.setACKTimer();
-
- if (self.remote_hold === true && hold === false) {
- self.onunhold('remote');
- } else if (self.remote_hold === false && hold === true) {
- self.onhold('remote');
- }
- }
- );
- },
- function() {
- request.reply(500);
- }
- );
- },
- /*
- * onFailure
- * Bad media description
- */
- function(e) {
- self.logger.error(e);
- request.reply(488);
- }
- );
- }
-};
-
-
-/**
- * In dialog Request Reception
- * @private
- */
-RTCSession.prototype.receiveRequest = function(request) {
- var contentType;
-
- if(request.method === JsSIP.C.CANCEL) {
- /* RFC3261 15 States that a UAS may have accepted an invitation while a CANCEL
- * was in progress and that the UAC MAY continue with the session established by
- * any 2xx response, or MAY terminate with BYE. JsSIP does continue with the
- * established session. So the CANCEL is processed only if the session is not yet
- * established.
- */
-
- /*
- * Terminate the whole session in case the user didn't accept (or yet send the answer)
- * nor reject the request opening the session.
- */
- if(this.status === C.STATUS_WAITING_FOR_ANSWER || this.status === C.STATUS_ANSWERED) {
- this.status = C.STATUS_CANCELED;
- this.request.reply(487);
- this.failed('remote', request, JsSIP.C.causes.CANCELED);
- }
- } else {
- // Requests arriving here are in-dialog requests.
- switch(request.method) {
- case JsSIP.C.ACK:
- if(this.status === C.STATUS_WAITING_FOR_ACK) {
- window.clearTimeout(this.timers.ackTimer);
- window.clearTimeout(this.timers.invite2xxTimer);
- this.status = C.STATUS_CONFIRMED;
- }
- break;
- case JsSIP.C.BYE:
- if(this.status === C.STATUS_CONFIRMED) {
- request.reply(200);
- this.ended('remote', request, JsSIP.C.causes.BYE);
- }
- break;
- case JsSIP.C.INVITE:
- if(this.status === C.STATUS_CONFIRMED) {
- this.logger.log('re-INVITE received');
- this.receiveReinvite(request);
- }
- break;
- case JsSIP.C.INFO:
- if(this.status === C.STATUS_CONFIRMED || this.status === C.STATUS_WAITING_FOR_ACK) {
- contentType = request.getHeader('content-type');
- if (contentType && (contentType.match(/^application\/dtmf-relay/i))) {
- new DTMF(this).init_incoming(request);
- }
- }
- }
- }
-};
-
-
-/**
- * Initial Request Sender
- * @private
- */
-RTCSession.prototype.sendInitialRequest = function(mediaConstraints, RTCOfferConstraints, mediaStream) {
- var
- self = this,
- request_sender = new JsSIP.RequestSender(self, this.ua),
-
- // User media succeeded
- userMediaSucceeded = function(stream) {
- self.rtcMediaHandler.addStream(
- stream,
- streamAdditionSucceeded,
- streamAdditionFailed
- );
- },
-
- // User media failed
- userMediaFailed = function() {
- if (self.status === C.STATUS_TERMINATED) {
- return;
- }
-
- self.failed('local', null, JsSIP.C.causes.USER_DENIED_MEDIA_ACCESS);
- },
-
- // rtcMediaHandler.addStream successfully added
- streamAdditionSucceeded = function() {
- self.connecting(self.request);
-
- if (self.status === C.STATUS_TERMINATED) {
- return;
- }
-
- self.rtcMediaHandler.createOffer(
- offerCreationSucceeded,
- offerCreationFailed,
- RTCOfferConstraints
- );
- },
-
- // rtcMediaHandler.addStream failed
- streamAdditionFailed = function() {
- if (self.status === C.STATUS_TERMINATED) {
- return;
- }
-
- self.failed('system', null, JsSIP.C.causes.WEBRTC_ERROR);
- },
-
- // rtcMediaHandler.createOffer succeeded
- offerCreationSucceeded = function(offer) {
- if (self.isCanceled || self.status === C.STATUS_TERMINATED) {
- return;
- }
-
- self.request.body = offer;
- self.status = C.STATUS_INVITE_SENT;
- request_sender.send();
- },
-
- // rtcMediaHandler.createOffer failed
- offerCreationFailed = function() {
- if (self.status === C.STATUS_TERMINATED) {
- return;
- }
-
- self.failed('system', null, JsSIP.C.causes.WEBRTC_ERROR);
- };
-
- this.receiveResponse = this.receiveInviteResponse;
-
- if (mediaStream) {
- userMediaSucceeded(mediaStream);
- } else {
- this.rtcMediaHandler.getUserMedia(
- userMediaSucceeded,
- userMediaFailed,
- mediaConstraints
- );
- }
-};
-
-/**
- * Send Re-INVITE
- * @private
- */
-RTCSession.prototype.sendReinvite = function(options) {
- options = options || {};
-
- var
- self = this,
- extraHeaders = options.extraHeaders || [],
- eventHandlers = options.eventHandlers || {},
- mangle = options.mangle || null;
-
- if (eventHandlers.succeeded) {
- this.reinviteSucceeded = eventHandlers.succeeded;
- } else {
- this.reinviteSucceeded = function(){};
- }
- if (eventHandlers.failed) {
- this.reinviteFailed = eventHandlers.failed;
- } else {
- this.reinviteFailed = function(){};
- }
-
- extraHeaders.push('Contact: ' + this.contact);
- extraHeaders.push('Allow: '+ JsSIP.Utils.getAllowedMethods(this.ua));
- extraHeaders.push('Content-Type: application/sdp');
-
- this.receiveResponse = this.receiveReinviteResponse;
-
- this.rtcMediaHandler.createOffer(
- function(body){
- if (mangle) {
- body = mangle(body);
- }
-
- self.dialog.sendRequest(self, JsSIP.C.INVITE, {
- extraHeaders: extraHeaders,
- body: body
- });
- },
- function() {
- if (self.isReadyToReinvite()) {
- self.onReadyToReinvite();
- }
- self.reinviteFailed();
- }
- );
-};
-
-
-/**
- * Reception of Response for Initial INVITE
- * @private
- */
-RTCSession.prototype.receiveInviteResponse = function(response) {
- var cause, dialog,
- session = this;
-
- // Handle 2XX retransmissions and responses from forked requests
- if (this.dialog && (response.status_code >=200 && response.status_code <=299)) {
-
- /*
- * If it is a retransmission from the endpoint that established
- * the dialog, send an ACK
- */
- if (this.dialog.id.call_id === response.call_id &&
- this.dialog.id.local_tag === response.from_tag &&
- this.dialog.id.remote_tag === response.to_tag) {
- this.sendRequest(JsSIP.C.ACK);
- return;
- }
-
- // If not, send an ACK and terminate
- else {
- dialog = new JsSIP.Dialog(this, response, 'UAC');
-
- if (dialog.error !== undefined) {
- this.logger.error(dialog.error);
- return;
- }
-
- dialog.sendRequest({
- owner: {status: C.STATUS_TERMINATED},
- onRequestTimeout: function(){},
- onTransportError: function(){},
- onDialogError: function(){},
- receiveResponse: function(){}
- }, JsSIP.C.ACK);
-
- dialog.sendRequest({
- owner: {status: C.STATUS_TERMINATED},
- onRequestTimeout: function(){},
- onTransportError: function(){},
- onDialogError: function(){},
- receiveResponse: function(){}
- }, JsSIP.C.BYE);
- return;
- }
-
- } else if(this.status !== C.STATUS_INVITE_SENT && this.status !== C.STATUS_1XX_RECEIVED) {
- return;
- }
-
- // Proceed to cancellation if the user requested.
- if(this.isCanceled) {
- if(response.status_code >= 100 && response.status_code < 200) {
- this.request.cancel(this.cancelReason);
- } else if(response.status_code >= 200 && response.status_code < 299) {
- this.acceptAndTerminate(response);
- }
- return;
- }
-
- switch(true) {
- case /^100$/.test(response.status_code):
- this.received_100 = true;
- break;
- case /^1[0-9]{2}$/.test(response.status_code):
- if(this.status !== C.STATUS_INVITE_SENT && this.status !== C.STATUS_1XX_RECEIVED) {
- break;
- }
-
- // Do nothing with 1xx responses without To tag.
- if(!response.to_tag) {
- this.logger.warn('1xx response received without to tag');
- break;
- }
-
- // Create Early Dialog if 1XX comes with contact
- if(response.hasHeader('contact')) {
- // An error on dialog creation will fire 'failed' event
- if(!this.createDialog(response, 'UAC', true)) {
- break;
- }
- }
-
- if (!response.body) {
- session.status = C.STATUS_1XX_RECEIVED;
- session.progress('remote', response);
- break;
- }
-
- this.rtcMediaHandler.onMessage(
- 'pranswer',
- response.body,
- /*
- * OnSuccess.
- * SDP Answer fits with Offer.
- */
- function() {
- session.status = C.STATUS_1XX_RECEIVED;
- session.progress('remote', response);
- },
- /*
- * OnFailure.
- * SDP Answer does not fit with Offer.
- */
- function(e) {
- session.logger.warn(e);
- this.earlyDialogs[response.call_id + response.from_tag + response.to_tag].terminate();
- }
- );
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- if(!response.body) {
- this.acceptAndTerminate(response, 400, 'Missing session description');
- this.failed('remote', response, JsSIP.C.causes.BAD_MEDIA_DESCRIPTION);
- break;
- }
-
- // An error on dialog creation will fire 'failed' event
- if (!this.createDialog(response, 'UAC')) {
- break;
- }
-
- this.rtcMediaHandler.onMessage(
- 'answer',
- response.body,
- /*
- * onSuccess
- * SDP Answer fits with Offer. Media will start
- */
- function() {
- session.status = C.STATUS_CONFIRMED;
- session.sendRequest(JsSIP.C.ACK);
- session.started('remote', response);
- },
- /*
- * onFailure
- * SDP Answer does not fit the Offer. Accept the call and Terminate.
- */
- function(e) {
- session.logger.warn(e);
- session.acceptAndTerminate(response, 488, 'Not Acceptable Here');
- session.failed('remote', response, JsSIP.C.causes.BAD_MEDIA_DESCRIPTION);
- }
- );
- break;
- default:
- cause = JsSIP.Utils.sipErrorCause(response.status_code);
- this.failed('remote', response, cause);
- }
-};
-
-/**
- * Reception of Response for in-dialog INVITE
- * @private
- */
-RTCSession.prototype.receiveReinviteResponse = function(response) {
- var
- self = this,
- contentType = response.getHeader('Content-Type');
-
- if (this.status === C.STATUS_TERMINATED) {
- return;
- }
-
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- break;
- case /^2[0-9]{2}$/.test(response.status_code):
- this.status = C.STATUS_CONFIRMED;
- this.sendRequest(JsSIP.C.ACK);
-
- if(!response.body) {
- this.reinviteFailed();
- break;
- } else if (contentType !== 'application/sdp') {
- this.reinviteFailed();
- break;
- }
-
- this.rtcMediaHandler.onMessage(
- 'answer',
- response.body,
- /*
- * onSuccess
- * SDP Answer fits with Offer.
- */
- function() {
- self.reinviteSucceeded();
- },
- /*
- * onFailure
- * SDP Answer does not fit the Offer.
- */
- function() {
- self.reinviteFailed();
- }
- );
- break;
- default:
- this.reinviteFailed();
- }
-};
-
-
-
-/**
-* @private
-*/
-RTCSession.prototype.acceptAndTerminate = function(response, status_code, reason_phrase) {
- var extraHeaders = [];
-
- if (status_code) {
- reason_phrase = reason_phrase || JsSIP.C.REASON_PHRASE[status_code] || '';
- extraHeaders.push('Reason: SIP ;cause=' + status_code + '; text="' + reason_phrase + '"');
- }
-
- // An error on dialog creation will fire 'failed' event
- if (this.dialog || this.createDialog(response, 'UAC')) {
- this.sendRequest(JsSIP.C.ACK);
- this.sendRequest(JsSIP.C.BYE, {
- extraHeaders: extraHeaders
- });
- }
-};
-
-
-/*
- * @private
- */
-RTCSession.prototype.toogleMuteAudio = function(mute) {
- var streamIdx, trackIdx, tracks,
- localStreams = this.getLocalStreams();
-
- for (streamIdx in localStreams) {
- tracks = localStreams[streamIdx].getAudioTracks();
- for (trackIdx in tracks) {
- tracks[trackIdx].enabled = !mute;
- }
- }
-};
-
-/*
- * @private
- */
-RTCSession.prototype.toogleMuteVideo = function(mute) {
- var streamIdx, trackIdx, tracks,
- localStreams = this.getLocalStreams();
-
- for (streamIdx in localStreams) {
- tracks = localStreams[streamIdx].getVideoTracks();
- for (trackIdx in tracks) {
- tracks[trackIdx].enabled = !mute;
- }
- }
-};
-
-/**
- * Session Callbacks
- */
-
-/**
-* @private
-*/
-RTCSession.prototype.onTransportError = function() {
- if(this.status !== C.STATUS_TERMINATED) {
- if (this.status === C.STATUS_CONFIRMED) {
- this.ended('system', null, JsSIP.C.causes.CONNECTION_ERROR);
- } else {
- this.failed('system', null, JsSIP.C.causes.CONNECTION_ERROR);
- }
- }
-};
-
-/**
-* @private
-*/
-RTCSession.prototype.onRequestTimeout = function() {
- if(this.status !== C.STATUS_TERMINATED) {
- if (this.status === C.STATUS_CONFIRMED) {
- this.ended('system', null, JsSIP.C.causes.REQUEST_TIMEOUT);
- } else {
- this.failed('system', null, JsSIP.C.causes.REQUEST_TIMEOUT);
- }
- }
-};
-
-/**
- * @private
- */
-RTCSession.prototype.onDialogError = function(response) {
- if(this.status !== C.STATUS_TERMINATED) {
- if (this.status === C.STATUS_CONFIRMED) {
- this.ended('remote', response, JsSIP.C.causes.DIALOG_ERROR);
- } else {
- this.failed('remote', response, JsSIP.C.causes.DIALOG_ERROR);
- }
- }
-};
-
-/**
- * Internal Callbacks
- */
-
-/**
- * @private
- */
-RTCSession.prototype.newRTCSession = function(originator, request) {
- var session = this,
- event_name = 'newRTCSession';
-
- if (originator === 'remote') {
- session.direction = 'incoming';
- session.local_identity = request.to;
- session.remote_identity = request.from;
- } else if (originator === 'local'){
- session.direction = 'outgoing';
- session.local_identity = request.from;
- session.remote_identity = request.to;
- }
-
- session.ua.emit(event_name, session.ua, {
- originator: originator,
- session: session,
- request: request
- });
-};
-
-/**
- * @private
- */
-RTCSession.prototype.connecting = function(request) {
- var session = this,
- event_name = 'connecting';
-
- session.emit(event_name, session, {
- request: request
- });
-};
-
-/**
- * @private
- */
-RTCSession.prototype.progress = function(originator, response) {
- var session = this,
- event_name = 'progress';
-
- session.emit(event_name, session, {
- originator: originator,
- response: response || null
- });
-};
-
-/**
- * @private
- */
-RTCSession.prototype.started = function(originator, message) {
- var session = this,
- event_name = 'started';
-
- session.start_time = new Date();
-
- session.emit(event_name, session, {
- originator: originator,
- response: message || null
- });
-};
-
-/**
- * @private
- */
-RTCSession.prototype.ended = function(originator, message, cause) {
- var session = this,
- event_name = 'ended';
-
- session.end_time = new Date();
-
- session.close();
- session.emit(event_name, session, {
- originator: originator,
- message: message || null,
- cause: cause
- });
-};
-
-/**
- * @private
- */
-RTCSession.prototype.failed = function(originator, message, cause) {
- var session = this,
- event_name = 'failed';
-
- session.close();
- session.emit(event_name, session, {
- originator: originator,
- message: message || null,
- cause: cause
- });
-};
-
-/**
- * @private
- */
-RTCSession.prototype.onhold = function(originator) {
- if (originator === 'local') {
- this.local_hold = true;
- } else {
- this.remote_hold = true;
- }
-
- this.emit('hold', this, {
- originator: originator
- });
-};
-
-/**
- * @private
- */
-RTCSession.prototype.onunhold = function(originator) {
- if (originator === 'local') {
- this.local_hold = false;
- } else {
- this.remote_hold = false;
- }
-
- this.emit('unhold', this, {
- originator: originator
- });
-};
-
-/*
- * @private
- */
-RTCSession.prototype.onmute = function(options) {
- this.emit('muted', this, {
- audio: options.audio,
- video: options.video
- });
-};
-
-/*
- * @private
- */
-RTCSession.prototype.onunmute = function(options) {
- this.emit('unmuted', this, {
- audio: options.audio,
- video: options.video
- });
-};
-
-/*
- * @private
- */
-RTCSession.prototype.onReadyToReinvite = function() {
- var action = (this.pending_actions.length() > 0)? this.pending_actions.shift() : null;
-
- if (!action) {
- return;
- }
-
- if (action.name === 'hold') {
- this.hold();
- } else if (action.name === 'unhold') {
- this.unhold();
- }
-};
-
-
-RTCSession.C = C;
-JsSIP.RTCSession = RTCSession;
-}(JsSIP));
-
-
-/**
- * @fileoverview Message
- */
-
-/**
- * @augments JsSIP
- * @class Class creating SIP MESSAGE request.
- * @param {JsSIP.UA} ua
- */
-(function(JsSIP) {
-var Message;
-
-Message = function(ua) {
- this.ua = ua;
- this.logger = ua.getLogger('jssip.message');
-
- // Custom message empty object for high level use
- this.data = {};
-};
-Message.prototype = new JsSIP.EventEmitter();
-
-
-Message.prototype.send = function(target, body, options) {
- var request_sender, event, contentType, eventHandlers, extraHeaders,
- events = [
- 'succeeded',
- 'failed'
- ],
- originalTarget = target;
-
- if (target === undefined || body === undefined) {
- throw new TypeError('Not enough arguments');
- }
-
- // Check target validity
- target = this.ua.normalizeTarget(target);
- if (!target) {
- throw new TypeError('Invalid target: '+ originalTarget);
- }
-
- this.initEvents(events);
-
- // Get call options
- options = options || {};
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [];
- eventHandlers = options.eventHandlers || {};
- contentType = options.contentType || 'text/plain';
-
- this.content_type = contentType;
-
- // Set event handlers
- for (event in eventHandlers) {
- this.on(event, eventHandlers[event]);
- }
-
- this.closed = false;
- this.ua.applicants[this] = this;
-
- extraHeaders.push('Content-Type: '+ contentType);
-
- this.request = new JsSIP.OutgoingRequest(JsSIP.C.MESSAGE, target, this.ua, null, extraHeaders);
-
- if(body) {
- this.request.body = body;
- this.content = body;
- } else {
- this.content = null;
- }
-
- request_sender = new JsSIP.RequestSender(this, this.ua);
-
- this.newMessage('local', this.request);
-
- request_sender.send();
-};
-
-/**
-* @private
-*/
-Message.prototype.receiveResponse = function(response) {
- var cause;
-
- if(this.closed) {
- return;
- }
- switch(true) {
- case /^1[0-9]{2}$/.test(response.status_code):
- // Ignore provisional responses.
- break;
-
- case /^2[0-9]{2}$/.test(response.status_code):
- delete this.ua.applicants[this];
- this.emit('succeeded', this, {
- originator: 'remote',
- response: response
- });
- break;
-
- default:
- delete this.ua.applicants[this];
- cause = JsSIP.Utils.sipErrorCause(response.status_code);
- this.emit('failed', this, {
- originator: 'remote',
- response: response,
- cause: cause
- });
- break;
- }
-};
-
-
-/**
-* @private
-*/
-Message.prototype.onRequestTimeout = function() {
- if(this.closed) {
- return;
- }
- this.emit('failed', this, {
- originator: 'system',
- cause: JsSIP.C.causes.REQUEST_TIMEOUT
- });
-};
-
-/**
-* @private
-*/
-Message.prototype.onTransportError = function() {
- if(this.closed) {
- return;
- }
- this.emit('failed', this, {
- originator: 'system',
- cause: JsSIP.C.causes.CONNECTION_ERROR
- });
-};
-
-/**
-* @private
-*/
-Message.prototype.close = function() {
- this.closed = true;
- delete this.ua.applicants[this];
-};
-
-/**
- * @private
- */
-Message.prototype.init_incoming = function(request) {
- var transaction;
-
- this.request = request;
- this.content_type = request.getHeader('Content-Type');
-
- if (request.body) {
- this.content = request.body;
- } else {
- this.content = null;
- }
-
- this.newMessage('remote', request);
-
- transaction = this.ua.transactions.nist[request.via_branch];
-
- if (transaction && (transaction.state === JsSIP.Transactions.C.STATUS_TRYING || transaction.state === JsSIP.Transactions.C.STATUS_PROCEEDING)) {
- request.reply(200);
- }
-};
-
-/**
- * Accept the incoming Message
- * Only valid for incoming Messages
- */
-Message.prototype.accept = function(options) {
- options = options || {};
-
- var
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- body = options.body;
-
- if (this.direction !== 'incoming') {
- throw new JsSIP.Exceptions.NotSupportedError('"accept" not supported for outgoing Message');
- }
-
- this.request.reply(200, null, extraHeaders, body);
-};
-
-/**
- * Reject the incoming Message
- * Only valid for incoming Messages
- *
- * @param {Number} status_code
- * @param {String} [reason_phrase]
- */
-Message.prototype.reject = function(options) {
- options = options || {};
-
- var
- status_code = options.status_code || 480,
- reason_phrase = options.reason_phrase,
- extraHeaders = options.extraHeaders && options.extraHeaders.slice() || [],
- body = options.body;
-
- if (this.direction !== 'incoming') {
- throw new JsSIP.Exceptions.NotSupportedError('"reject" not supported for outgoing Message');
- }
-
- if (status_code < 300 || status_code >= 700) {
- throw new TypeError('Invalid status_code: '+ status_code);
- }
-
- this.request.reply(status_code, reason_phrase, extraHeaders, body);
-};
-
-/**
- * Internal Callbacks
- */
-
-/**
- * @private
- */
-Message.prototype.newMessage = function(originator, request) {
- var message = this,
- event_name = 'newMessage';
-
- if (originator === 'remote') {
- message.direction = 'incoming';
- message.local_identity = request.to;
- message.remote_identity = request.from;
- } else if (originator === 'local'){
- message.direction = 'outgoing';
- message.local_identity = request.from;
- message.remote_identity = request.to;
- }
-
- message.ua.emit(event_name, message.ua, {
- originator: originator,
- message: message,
- request: request
- });
-};
-
-JsSIP.Message = Message;
-}(JsSIP));
-
-
-/**
- * @fileoverview SIP User Agent
- */
-
-
-/**
- * @augments JsSIP
- * @class Class creating a SIP User Agent.
- */
-(function(JsSIP) {
-var UA,
- C = {
- // UA status codes
- STATUS_INIT : 0,
- STATUS_READY: 1,
- STATUS_USER_CLOSED: 2,
- STATUS_NOT_READY: 3,
-
- // UA error codes
- CONFIGURATION_ERROR: 1,
- NETWORK_ERROR: 2,
-
- /* UA events and corresponding SIP Methods.
- * Dynamically added to 'Allow' header field if the
- * corresponding event handler is set.
- */
- EVENT_METHODS: {
- 'newRTCSession': 'INVITE',
- 'newMessage': 'MESSAGE'
- },
-
- ALLOWED_METHODS: [
- 'ACK',
- 'CANCEL',
- 'BYE',
- 'OPTIONS'
- ],
-
- ACCEPTED_BODY_TYPES: [
- 'application/sdp',
- 'application/dtmf-relay'
- ],
-
- MAX_FORWARDS: 69,
- TAG_LENGTH: 10
- };
-
-UA = function(configuration) {
- var events = [
- 'connecting',
- 'connected',
- 'disconnected',
- 'newTransaction',
- 'transactionDestroyed',
- 'registered',
- 'unregistered',
- 'registrationFailed',
- 'newRTCSession',
- 'newMessage'
- ];
-
- // Set Accepted Body Types
- C.ACCEPTED_BODY_TYPES = C.ACCEPTED_BODY_TYPES.toString();
-
- this.log = new JsSIP.LoggerFactory();
- this.logger = this.getLogger('jssip.ua');
-
- this.cache = {
- credentials: {}
- };
-
- this.configuration = {};
- this.dialogs = {};
-
- //User actions outside any session/dialog (MESSAGE)
- this.applicants = {};
-
- this.sessions = {};
- this.transport = null;
- this.contact = null;
- this.status = C.STATUS_INIT;
- this.error = null;
- this.transactions = {
- nist: {},
- nict: {},
- ist: {},
- ict: {}
- };
-
- this.transportRecoverAttempts = 0;
- this.transportRecoveryTimer = null;
-
- Object.defineProperties(this, {
- transactionsCount: {
- get: function() {
- var type,
- transactions = ['nist','nict','ist','ict'],
- count = 0;
-
- for (type in transactions) {
- count += Object.keys(this.transactions[transactions[type]]).length;
- }
-
- return count;
- }
- },
-
- nictTransactionsCount: {
- get: function() {
- return Object.keys(this.transactions['nict']).length;
- }
- },
-
- nistTransactionsCount: {
- get: function() {
- return Object.keys(this.transactions['nist']).length;
- }
- },
-
- ictTransactionsCount: {
- get: function() {
- return Object.keys(this.transactions['ict']).length;
- }
- },
-
- istTransactionsCount: {
- get: function() {
- return Object.keys(this.transactions['ist']).length;
- }
- }
- });
-
- /**
- * Load configuration
- *
- * @throws {JsSIP.Exceptions.ConfigurationError}
- * @throws {TypeError}
- */
-
- if(configuration === undefined) {
- throw new TypeError('Not enough arguments');
- }
-
- // Apply log configuration if present
- if (configuration.log) {
- if (configuration.log.hasOwnProperty('builtinEnabled')) {
- this.log.builtinEnabled = configuration.log.builtinEnabled;
- }
-
- if (configuration.log.hasOwnProperty('level')) {
- this.log.level = configuration.log.level;
- }
-
- if (configuration.log.hasOwnProperty('connector')) {
- this.log.connector = configuration.log.connector;
- }
- }
-
- try {
- this.loadConfig(configuration);
- this.initEvents(events);
- } catch(e) {
- this.status = C.STATUS_NOT_READY;
- this.error = C.CONFIGURATION_ERROR;
- throw e;
- }
-
- // Initialize registrator
- this.registrator = new JsSIP.Registrator(this);
-};
-UA.prototype = new JsSIP.EventEmitter();
-
-
-//=================
-// High Level API
-//=================
-
-/**
- * Register.
- *
- *
- */
-UA.prototype.register = function(options) {
- this.configuration.register = true;
- this.registrator.register(options);
-};
-
-/**
- * Unregister.
- *
- * @param {Boolean} [all] unregister all user bindings.
- *
- */
-UA.prototype.unregister = function(options) {
- this.configuration.register = false;
- this.registrator.unregister(options);
-};
-
-/**
- * Registration state.
- * @param {Boolean}
- */
-UA.prototype.isRegistered = function() {
- if(this.registrator.registered) {
- return true;
- } else {
- return false;
- }
-};
-
-/**
- * Connection state.
- * @param {Boolean}
- */
-UA.prototype.isConnected = function() {
- if(this.transport) {
- return this.transport.connected;
- } else {
- return false;
- }
-};
-
-/**
- * Make an outgoing call.
- *
- * @param {String} target
- * @param {Object} views
- * @param {Object} [options]
- *
- * @throws {TypeError}
- *
- */
-UA.prototype.call = function(target, options) {
- var session;
-
- session = new JsSIP.RTCSession(this);
- session.connect(target, options);
-};
-
-/**
- * Send a message.
- *
- * @param {String} target
- * @param {String} body
- * @param {Object} [options]
- *
- * @throws {TypeError}
- *
- */
-UA.prototype.sendMessage = function(target, body, options) {
- var message;
-
- message = new JsSIP.Message(this);
- message.send(target, body, options);
-};
-
-/**
- * Gracefully close.
- *
- */
-UA.prototype.stop = function() {
- var session, applicant,
- ua = this;
-
- function transactionsListener() {
- if (ua.nistTransactionsCount === 0 && ua.nictTransactionsCount === 0) {
- ua.removeListener('transactionDestroyed', transactionsListener);
- ua.transport.disconnect();
- }
- }
-
- this.logger.log('user requested closure...');
-
- if(this.status === C.STATUS_USER_CLOSED) {
- this.logger.warn('UA already closed');
- return;
- }
-
- // Clear transportRecoveryTimer
- window.clearTimeout(this.transportRecoveryTimer);
-
- // Close registrator
- this.logger.log('closing registrator');
- this.registrator.close();
-
- // Run _terminate_ on every Session
- for(session in this.sessions) {
- this.logger.log('closing session ' + session);
- this.sessions[session].terminate();
- }
-
- // Run _close_ on every applicant
- for(applicant in this.applicants) {
- this.applicants[applicant].close();
- }
-
- this.status = C.STATUS_USER_CLOSED;
-
- /*
- * If the remaining transactions are all INVITE transactions, there is no need to
- * wait anymore because every session has already been closed by this method.
- * - locally originated sessions where terminated (CANCEL or BYE)
- * - remotely originated sessions where rejected (4XX) or terminated (BYE)
- * Remaining INVITE transactions belong tho sessions that where answered. This are in
- * 'accepted' state due to timers 'L' and 'M' defined in [RFC 6026]
- */
- if (this.nistTransactionsCount === 0 && this.nictTransactionsCount === 0) {
- this.transport.disconnect();
- } else {
- this.on('transactionDestroyed', transactionsListener);
- }
-};
-
-/**
- * Connect to the WS server if status = STATUS_INIT.
- * Resume UA after being closed.
- *
- */
-UA.prototype.start = function() {
- var server;
-
- this.logger.log('user requested startup...');
-
- if (this.status === C.STATUS_INIT) {
- server = this.getNextWsServer();
- new JsSIP.Transport(this, server);
- } else if(this.status === C.STATUS_USER_CLOSED) {
- this.logger.log('resuming');
- this.status = C.STATUS_READY;
- this.transport.connect();
- } else if (this.status === C.STATUS_READY) {
- this.logger.log('UA is in READY status, not resuming');
- } else {
- this.logger.error('Connection is down. Auto-Recovery system is trying to connect');
- }
-};
-
-/**
- * Normalice a string into a valid SIP request URI
- *
- * @param {String} target
- *
- * @returns {JsSIP.URI|undefined}
- */
-UA.prototype.normalizeTarget = function(target) {
- return JsSIP.Utils.normalizeTarget(target, this.configuration.hostport_params);
-};
-
-
-//===============================
-// Private (For internal use)
-//===============================
-
-UA.prototype.saveCredentials = function(credentials) {
- this.cache.credentials[credentials.realm] = this.cache.credentials[credentials.realm] || {};
- this.cache.credentials[credentials.realm][credentials.uri] = credentials;
-};
-
-UA.prototype.getCredentials = function(request) {
- var realm, credentials;
-
- realm = request.ruri.host;
-
- if (this.cache.credentials[realm] && this.cache.credentials[realm][request.ruri]) {
- credentials = this.cache.credentials[realm][request.ruri];
- credentials.method = request.method;
- }
-
- return credentials;
-};
-
-UA.prototype.getLogger = function(category, label) {
- return this.log.getLogger(category, label);
-};
-
-
-//==========================
-// Event Handlers
-//==========================
-
-/**
- * Transport Close event.
- * @private
- * @event
- * @param {JsSIP.Transport} transport.
- */
-UA.prototype.onTransportClosed = function(transport) {
- // Run _onTransportError_ callback on every client transaction using _transport_
- var type, idx, length,
- client_transactions = ['nict', 'ict', 'nist', 'ist'];
-
- transport.server.status = JsSIP.Transport.C.STATUS_DISCONNECTED;
- this.logger.log('connection state set to '+ JsSIP.Transport.C.STATUS_DISCONNECTED);
-
- length = client_transactions.length;
- for (type = 0; type < length; type++) {
- for(idx in this.transactions[client_transactions[type]]) {
- this.transactions[client_transactions[type]][idx].onTransportError();
- }
- }
-
- // Close sessions if GRUU is not being used
- if (!this.contact.pub_gruu) {
- this.closeSessionsOnTransportError();
- }
-
-};
-
-/**
- * Unrecoverable transport event.
- * Connection reattempt logic has been done and didn't success.
- * @private
- * @event
- * @param {JsSIP.Transport} transport.
- */
-UA.prototype.onTransportError = function(transport) {
- var server;
-
- this.logger.log('transport ' + transport.server.ws_uri + ' failed | connection state set to '+ JsSIP.Transport.C.STATUS_ERROR);
-
- // Close sessions.
- //Mark this transport as 'down' and try the next one
- transport.server.status = JsSIP.Transport.C.STATUS_ERROR;
-
- this.emit('disconnected', this, {
- transport: transport,
- code: transport.lastTransportError.code,
- reason: transport.lastTransportError.reason
- });
-
- server = this.getNextWsServer();
-
- if(server) {
- new JsSIP.Transport(this, server);
- }else {
- this.closeSessionsOnTransportError();
- if (!this.error || this.error !== C.NETWORK_ERROR) {
- this.status = C.STATUS_NOT_READY;
- this.error = C.NETWORK_ERROR;
- }
- // Transport Recovery process
- this.recoverTransport();
- }
-};
-
-/**
- * Transport connection event.
- * @private
- * @event
- * @param {JsSIP.Transport} transport.
- */
-UA.prototype.onTransportConnected = function(transport) {
- this.transport = transport;
-
- // Reset transport recovery counter
- this.transportRecoverAttempts = 0;
-
- transport.server.status = JsSIP.Transport.C.STATUS_READY;
- this.logger.log('connection state set to '+ JsSIP.Transport.C.STATUS_READY);
-
- if(this.status === C.STATUS_USER_CLOSED) {
- return;
- }
-
- this.status = C.STATUS_READY;
- this.error = null;
-
- if(this.configuration.register) {
- this.registrator.onTransportConnected();
- }
-
- this.emit('connected', this, {
- transport: transport
- });
-};
-
-
-/**
- * Transport connecting event
- * @private
- * @param {JsSIP.Transport} transport.
- * @param {Integer} attempts.
- */
-UA.prototype.onTransportConnecting = function(transport, attempts) {
- this.emit('connecting', this, {
- transport: transport,
- attempts: attempts
- });
-};
-
-
-/**
- * new Transaction
- * @private
- * @param {JsSIP.Transaction} transaction.
- */
-UA.prototype.newTransaction = function(transaction) {
- this.transactions[transaction.type][transaction.id] = transaction;
- this.emit('newTransaction', this, {
- transaction: transaction
- });
-};
-
-
-/**
- * new Transaction
- * @private
- * @param {JsSIP.Transaction} transaction.
- */
-UA.prototype.destroyTransaction = function(transaction) {
- delete this.transactions[transaction.type][transaction.id];
- this.emit('transactionDestroyed', this, {
- transaction: transaction
- });
-};
-
-
-//=========================
-// receiveRequest
-//=========================
-
-/**
- * Request reception
- * @private
- * @param {JsSIP.IncomingRequest} request.
- */
-UA.prototype.receiveRequest = function(request) {
- var dialog, session, message,
- method = request.method;
-
- // Check that request URI points to us
- if(request.ruri.user !== this.configuration.uri.user && request.ruri.user !== this.contact.uri.user) {
- this.logger.warn('Request-URI does not point to us');
- if (request.method !== JsSIP.C.ACK) {
- request.reply_sl(404);
- }
- return;
- }
-
- // Check request URI scheme
- if(request.ruri.scheme === JsSIP.C.SIPS) {
- request.reply_sl(416);
- return;
- }
-
- // Check transaction
- if(JsSIP.Transactions.checkTransaction(this, request)) {
- return;
- }
-
- // Create the server transaction
- if(method === JsSIP.C.INVITE) {
- new JsSIP.Transactions.InviteServerTransaction(request, this);
- } else if(method !== JsSIP.C.ACK) {
- new JsSIP.Transactions.NonInviteServerTransaction(request, this);
- }
-
- /* RFC3261 12.2.2
- * Requests that do not change in any way the state of a dialog may be
- * received within a dialog (for example, an OPTIONS request).
- * They are processed as if they had been received outside the dialog.
- */
- if(method === JsSIP.C.OPTIONS) {
- request.reply(200);
- } else if (method === JsSIP.C.MESSAGE) {
- if (!this.checkEvent('newMessage') || this.listeners('newMessage').length === 0) {
- request.reply(405);
- return;
- }
- message = new JsSIP.Message(this);
- message.init_incoming(request);
- } else if (method === JsSIP.C.INVITE) {
- if (!this.checkEvent('newRTCSession') || this.listeners('newRTCSession').length === 0) {
- request.reply(405);
- return;
- }
- }
-
- // Initial Request
- if(!request.to_tag) {
- switch(method) {
- case JsSIP.C.INVITE:
- if(JsSIP.WebRTC.isSupported) {
- session = new JsSIP.RTCSession(this);
- session.init_incoming(request);
- } else {
- this.logger.warn('INVITE received but WebRTC is not supported');
- request.reply(488);
- }
- break;
- case JsSIP.C.BYE:
- // Out of dialog BYE received
- request.reply(481);
- break;
- case JsSIP.C.CANCEL:
- session = this.findSession(request);
- if(session) {
- session.receiveRequest(request);
- } else {
- this.logger.warn('received CANCEL request for a non existent session');
- }
- break;
- case JsSIP.C.ACK:
- /* Absorb it.
- * ACK request without a corresponding Invite Transaction
- * and without To tag.
- */
- break;
- default:
- request.reply(405);
- break;
- }
- }
- // In-dialog request
- else {
- dialog = this.findDialog(request);
-
- if(dialog) {
- dialog.receiveRequest(request);
- } else if (method === JsSIP.C.NOTIFY) {
- session = this.findSession(request);
- if(session) {
- session.receiveRequest(request);
- } else {
- this.logger.warn('received NOTIFY request for a non existent session');
- request.reply(481, 'Subscription does not exist');
- }
- }
- /* RFC3261 12.2.2
- * Request with to tag, but no matching dialog found.
- * Exception: ACK for an Invite request for which a dialog has not
- * been created.
- */
- else {
- if(method !== JsSIP.C.ACK) {
- request.reply(481);
- }
- }
- }
-};
-
-//=================
-// Utils
-//=================
-
-/**
- * Get the session to which the request belongs to, if any.
- * @private
- * @param {JsSIP.IncomingRequest} request.
- * @returns {JsSIP.OutgoingSession|JsSIP.IncomingSession|null}
- */
-UA.prototype.findSession = function(request) {
- var
- sessionIDa = request.call_id + request.from_tag,
- sessionA = this.sessions[sessionIDa],
- sessionIDb = request.call_id + request.to_tag,
- sessionB = this.sessions[sessionIDb];
-
- if(sessionA) {
- return sessionA;
- } else if(sessionB) {
- return sessionB;
- } else {
- return null;
- }
-};
-
-/**
- * Get the dialog to which the request belongs to, if any.
- * @private
- * @param {JsSIP.IncomingRequest}
- * @returns {JsSIP.Dialog|null}
- */
-UA.prototype.findDialog = function(request) {
- var
- id = request.call_id + request.from_tag + request.to_tag,
- dialog = this.dialogs[id];
-
- if(dialog) {
- return dialog;
- } else {
- id = request.call_id + request.to_tag + request.from_tag;
- dialog = this.dialogs[id];
- if(dialog) {
- return dialog;
- } else {
- return null;
- }
- }
-};
-
-/**
- * Retrieve the next server to which connect.
- * @private
- * @returns {Object} ws_server
- */
-UA.prototype.getNextWsServer = function() {
- // Order servers by weight
- var idx, length, ws_server,
- candidates = [];
-
- length = this.configuration.ws_servers.length;
- for (idx = 0; idx < length; idx++) {
- ws_server = this.configuration.ws_servers[idx];
-
- if (ws_server.status === JsSIP.Transport.C.STATUS_ERROR) {
- continue;
- } else if (candidates.length === 0) {
- candidates.push(ws_server);
- } else if (ws_server.weight > candidates[0].weight) {
- candidates = [ws_server];
- } else if (ws_server.weight === candidates[0].weight) {
- candidates.push(ws_server);
- }
- }
-
- idx = Math.floor((Math.random()* candidates.length));
-
- return candidates[idx];
-};
-
-/**
- * Close all sessions on transport error.
- * @private
- */
-UA.prototype.closeSessionsOnTransportError = function() {
- var idx;
-
- // Run _transportError_ for every Session
- for(idx in this.sessions) {
- this.sessions[idx].onTransportError();
- }
- // Call registrator _onTransportClosed_
- this.registrator.onTransportClosed();
-};
-
-UA.prototype.recoverTransport = function(ua) {
- var idx, length, k, nextRetry, count, server;
-
- ua = ua || this;
- count = ua.transportRecoverAttempts;
-
- length = ua.configuration.ws_servers.length;
- for (idx = 0; idx < length; idx++) {
- ua.configuration.ws_servers[idx].status = 0;
- }
-
- server = ua.getNextWsServer();
-
- k = Math.floor((Math.random() * Math.pow(2,count)) +1);
- nextRetry = k * ua.configuration.connection_recovery_min_interval;
-
- if (nextRetry > ua.configuration.connection_recovery_max_interval) {
- this.logger.log('time for next connection attempt exceeds connection_recovery_max_interval, resetting counter');
- nextRetry = ua.configuration.connection_recovery_min_interval;
- count = 0;
- }
-
- this.logger.log('next connection attempt in '+ nextRetry +' seconds');
-
- this.transportRecoveryTimer = window.setTimeout(
- function(){
- ua.transportRecoverAttempts = count + 1;
- new JsSIP.Transport(ua, server);
- }, nextRetry * 1000);
-};
-
-/**
- * Configuration load.
- * @private
- * returns {Boolean}
- */
-UA.prototype.loadConfig = function(configuration) {
- // Settings and default values
- var parameter, value, checked_value, hostport_params, registrar_server,
- settings = {
- /* Host address
- * Value to be set in Via sent_by and host part of Contact FQDN
- */
- via_host: JsSIP.Utils.createRandomToken(12) + '.invalid',
-
- // Password
- password: null,
-
- // Registration parameters
- register_expires: 600,
- register: true,
- registrar_server: null,
-
- // Transport related parameters
- ws_server_max_reconnection: 3,
- ws_server_reconnection_timeout: 4,
-
- connection_recovery_min_interval: 2,
- connection_recovery_max_interval: 30,
-
- use_preloaded_route: false,
-
- // Session parameters
- no_answer_timeout: 60,
- stun_servers: ['stun:stun.l.google.com:19302'],
- turn_servers: [],
-
- // Logging parameters
- trace_sip: false,
-
- // Hacks
- hack_via_tcp: false,
- hack_ip_in_contact: false
- };
-
- // Pre-Configuration
-
- // Check Mandatory parameters
- for(parameter in UA.configuration_check.mandatory) {
- if(!configuration.hasOwnProperty(parameter)) {
- throw new JsSIP.Exceptions.ConfigurationError(parameter);
- } else {
- value = configuration[parameter];
- checked_value = UA.configuration_check.mandatory[parameter](value);
- if (checked_value !== undefined) {
- settings[parameter] = checked_value;
- } else {
- throw new JsSIP.Exceptions.ConfigurationError(parameter, value);
- }
- }
- }
-
- // Check Optional parameters
- for(parameter in UA.configuration_check.optional) {
- if(configuration.hasOwnProperty(parameter)) {
- value = configuration[parameter];
-
- /* If the parameter value is null, empty string, undefined, empty array
- * or it's a number with NaN value, then apply its default value.
- */
- if (JsSIP.Utils.isEmpty(value)) {
- continue;
- }
-
- checked_value = UA.configuration_check.optional[parameter](value);
- if (checked_value !== undefined) {
- settings[parameter] = checked_value;
- } else {
- throw new JsSIP.Exceptions.ConfigurationError(parameter, value);
- }
- }
- }
-
- // Sanity Checks
-
- // Connection recovery intervals
- if(settings.connection_recovery_max_interval < settings.connection_recovery_min_interval) {
- throw new JsSIP.Exceptions.ConfigurationError('connection_recovery_max_interval', settings.connection_recovery_max_interval);
- }
-
- // Post Configuration Process
-
- // Allow passing 0 number as display_name.
- if (settings.display_name === 0) {
- settings.display_name = '0';
- }
-
- // Instance-id for GRUU
- if (!settings.instance_id) {
- settings.instance_id = JsSIP.Utils.newUUID();
- }
-
- // jssip_id instance parameter. Static random tag of length 5
- settings.jssip_id = JsSIP.Utils.createRandomToken(5);
-
- // String containing settings.uri without scheme and user.
- hostport_params = settings.uri.clone();
- hostport_params.user = null;
- settings.hostport_params = hostport_params.toString().replace(/^sip:/i, '');
-
- /* Check whether authorization_user is explicitly defined.
- * Take 'settings.uri.user' value if not.
- */
- if (!settings.authorization_user) {
- settings.authorization_user = settings.uri.user;
- }
-
- /* If no 'registrar_server' is set use the 'uri' value without user portion. */
- if (!settings.registrar_server) {
- registrar_server = settings.uri.clone();
- registrar_server.user = null;
- settings.registrar_server = registrar_server;
- }
-
- // User no_answer_timeout
- settings.no_answer_timeout = settings.no_answer_timeout * 1000;
-
- // Via Host
- if (settings.hack_ip_in_contact) {
- settings.via_host = JsSIP.Utils.getRandomTestNetIP();
- }
-
- // Set empty Stun Server Set if explicitly passed an empty Array
- value = configuration.stun_servers;
- if (value instanceof Array && value.length === 0) {
- settings.stun_servers = [];
- }
-
- this.contact = {
- pub_gruu: null,
- temp_gruu: null,
- uri: new JsSIP.URI('sip', JsSIP.Utils.createRandomToken(8), settings.via_host, null, {transport: 'ws'}),
- toString: function(options){
- options = options || {};
-
- var
- anonymous = options.anonymous || null,
- outbound = options.outbound || null,
- contact = '<';
-
- if (anonymous) {
- contact += this.temp_gruu || 'sip:anonymous@anonymous.invalid;transport=ws';
- } else {
- contact += this.pub_gruu || this.uri.toString();
- }
-
- if (outbound && (anonymous ? !this.temp_gruu : !this.pub_gruu)) {
- contact += ';ob';
- }
-
- contact += '>';
-
- return contact;
- }
- };
-
- // Fill the value of the configuration_skeleton
- for(parameter in settings) {
- UA.configuration_skeleton[parameter].value = settings[parameter];
- }
-
- Object.defineProperties(this.configuration, UA.configuration_skeleton);
-
- // Clean UA.configuration_skeleton
- for(parameter in settings) {
- UA.configuration_skeleton[parameter].value = '';
- }
-
- this.logger.log('configuration parameters after validation:');
- for(parameter in settings) {
- switch(parameter) {
- case 'uri':
- case 'registrar_server':
- this.logger.log('· ' + parameter + ': ' + settings[parameter]);
- break;
- case 'password':
- this.logger.log('· ' + parameter + ': ' + 'NOT SHOWN');
- break;
- default:
- this.logger.log('· ' + parameter + ': ' + window.JSON.stringify(settings[parameter]));
- }
- }
-
- return;
-};
-
-/**
- * Configuration Object skeleton.
- * @private
- */
-UA.configuration_skeleton = (function() {
- var idx, parameter,
- skeleton = {},
- parameters = [
- // Internal parameters
- "jssip_id",
- "ws_server_max_reconnection",
- "ws_server_reconnection_timeout",
- "hostport_params",
-
- // Mandatory user configurable parameters
- "uri",
- "ws_servers",
-
- // Optional user configurable parameters
- "authorization_user",
- "connection_recovery_max_interval",
- "connection_recovery_min_interval",
- "display_name",
- "hack_via_tcp", // false.
- "hack_ip_in_contact", //false
- "instance_id",
- "no_answer_timeout", // 30 seconds.
- "password",
- "register_expires", // 600 seconds.
- "registrar_server",
- "stun_servers",
- "trace_sip",
- "turn_servers",
- "use_preloaded_route",
-
- // Post-configuration generated parameters
- "via_core_value",
- "via_host"
- ];
-
- for(idx in parameters) {
- parameter = parameters[idx];
- skeleton[parameter] = {
- value: '',
- writable: false,
- configurable: false
- };
- }
-
- skeleton['register'] = {
- value: '',
- writable: true,
- configurable: false
- };
-
- return skeleton;
-}());
-
-/**
- * Configuration checker.
- * @private
- * @return {Boolean}
- */
-UA.configuration_check = {
- mandatory: {
-
- uri: function(uri) {
- var parsed;
-
- if (!/^sip:/i.test(uri)) {
- uri = JsSIP.C.SIP + ':' + uri;
- }
- parsed = JsSIP.URI.parse(uri);
-
- if(!parsed) {
- return;
- } else if(!parsed.user) {
- return;
- } else {
- return parsed;
- }
- },
-
- ws_servers: function(ws_servers) {
- var idx, length, url;
-
- /* Allow defining ws_servers parameter as:
- * String: "host"
- * Array of Strings: ["host1", "host2"]
- * Array of Objects: [{ws_uri:"host1", weight:1}, {ws_uri:"host2", weight:0}]
- * Array of Objects and Strings: [{ws_uri:"host1"}, "host2"]
- */
- if (typeof ws_servers === 'string') {
- ws_servers = [{ws_uri: ws_servers}];
- } else if (ws_servers instanceof Array) {
- length = ws_servers.length;
- for (idx = 0; idx < length; idx++) {
- if (typeof ws_servers[idx] === 'string'){
- ws_servers[idx] = {ws_uri: ws_servers[idx]};
- }
- }
- } else {
- return;
- }
-
- if (ws_servers.length === 0) {
- return false;
- }
-
- length = ws_servers.length;
- for (idx = 0; idx < length; idx++) {
- if (!ws_servers[idx].ws_uri) {
- this.logger.error('missing "ws_uri" attribute in ws_servers parameter');
- return;
- }
- if (ws_servers[idx].weight && !Number(ws_servers[idx].weight)) {
- this.logger.error('"weight" attribute in ws_servers parameter must be a Number');
- return;
- }
-
- url = JsSIP.Grammar.parse(ws_servers[idx].ws_uri, 'absoluteURI');
-
- if(url === -1) {
- this.logger.error('invalid "ws_uri" attribute in ws_servers parameter: ' + ws_servers[idx].ws_uri);
- return;
- } else if(url.scheme !== 'wss' && url.scheme !== 'ws') {
- this.logger.error('invalid URI scheme in ws_servers parameter: ' + url.scheme);
- return;
- } else {
- ws_servers[idx].sip_uri = '';
-
- if (!ws_servers[idx].weight) {
- ws_servers[idx].weight = 0;
- }
-
- ws_servers[idx].status = 0;
- ws_servers[idx].scheme = url.scheme.toUpperCase();
- }
- }
- return ws_servers;
- }
- },
-
- optional: {
-
- authorization_user: function(authorization_user) {
- if(JsSIP.Grammar.parse('"'+ authorization_user +'"', 'quoted_string') === -1) {
- return;
- } else {
- return authorization_user;
- }
- },
-
- connection_recovery_max_interval: function(connection_recovery_max_interval) {
- var value;
- if(JsSIP.Utils.isDecimal(connection_recovery_max_interval)) {
- value = window.Number(connection_recovery_max_interval);
- if(value > 0) {
- return value;
- }
- }
- },
-
- connection_recovery_min_interval: function(connection_recovery_min_interval) {
- var value;
- if(JsSIP.Utils.isDecimal(connection_recovery_min_interval)) {
- value = window.Number(connection_recovery_min_interval);
- if(value > 0) {
- return value;
- }
- }
- },
-
- display_name: function(display_name) {
- if(JsSIP.Grammar.parse('"' + display_name + '"', 'display_name') === -1) {
- return;
- } else {
- return display_name;
- }
- },
-
- hack_via_tcp: function(hack_via_tcp) {
- if (typeof hack_via_tcp === 'boolean') {
- return hack_via_tcp;
- }
- },
-
- hack_ip_in_contact: function(hack_ip_in_contact) {
- if (typeof hack_ip_in_contact === 'boolean') {
- return hack_ip_in_contact;
- }
- },
-
- instance_id: function(instance_id) {
- if ((/^uuid:/i.test(instance_id))) {
- instance_id = instance_id.substr(5);
- }
-
- if(JsSIP.Grammar.parse(instance_id, 'uuid') === -1) {
- return;
- } else {
- return instance_id;
- }
- },
-
- no_answer_timeout: function(no_answer_timeout) {
- var value;
- if (JsSIP.Utils.isDecimal(no_answer_timeout)) {
- value = window.Number(no_answer_timeout);
- if (value > 0) {
- return value;
- }
- }
- },
-
- password: function(password) {
- return String(password);
- },
-
- register: function(register) {
- if (typeof register === 'boolean') {
- return register;
- }
- },
-
- register_expires: function(register_expires) {
- var value;
- if (JsSIP.Utils.isDecimal(register_expires)) {
- value = window.Number(register_expires);
- if (value > 0) {
- return value;
- }
- }
- },
-
- registrar_server: function(registrar_server) {
- var parsed;
-
- if (!/^sip:/i.test(registrar_server)) {
- registrar_server = JsSIP.C.SIP + ':' + registrar_server;
- }
- parsed = JsSIP.URI.parse(registrar_server);
-
- if(!parsed) {
- return;
- } else if(parsed.user) {
- return;
- } else {
- return parsed;
- }
- },
-
- stun_servers: function(stun_servers) {
- var idx, length, stun_server;
-
- if (typeof stun_servers === 'string') {
- stun_servers = [stun_servers];
- } else if (!(stun_servers instanceof Array)) {
- return;
- }
-
- length = stun_servers.length;
- for (idx = 0; idx < length; idx++) {
- stun_server = stun_servers[idx];
- if (!(/^stuns?:/.test(stun_server))) {
- stun_server = 'stun:' + stun_server;
- }
-
- if(JsSIP.Grammar.parse(stun_server, 'stun_URI') === -1) {
- return;
- } else {
- stun_servers[idx] = stun_server;
- }
- }
- return stun_servers;
- },
-
- trace_sip: function(trace_sip) {
- if (typeof trace_sip === 'boolean') {
- return trace_sip;
- }
- },
-
- turn_servers: function(turn_servers) {
- var idx, idx2, length, length2, turn_server, url;
-
- if (turn_servers instanceof Array) {
- // Do nothing
- } else {
- turn_servers = [turn_servers];
- }
-
- length = turn_servers.length;
- for (idx = 0; idx < length; idx++) {
- turn_server = turn_servers[idx];
-
- // Backward compatibility:
- //Allow defining the turn_server 'urls' with the 'server' property.
- if (turn_server.server) {
- turn_server.urls = [turn_server.server];
- }
-
- // Backward compatibility:
- //Allow defining the turn_server 'credential' with the 'password' property.
- if (turn_server.password) {
- turn_server.credential = [turn_server.password];
- }
-
- if (!turn_server.urls || !turn_server.username || !turn_server.credential) {
- return;
- }
-
- if (!(turn_server.urls instanceof Array)) {
- turn_server.urls = [turn_server.urls];
- }
-
- length2 = turn_server.urls.length;
- for (idx2 = 0; idx2 < length2; idx2++) {
- url = turn_server.urls[idx2];
-
- if (!(/^turns?:/.test(url))) {
- url = 'turn:' + url;
- }
-
- if(JsSIP.Grammar.parse(url, 'turn_URI') === -1) {
- return;
- }
- }
- }
- return turn_servers;
- },
-
- use_preloaded_route: function(use_preloaded_route) {
- if (typeof use_preloaded_route === 'boolean') {
- return use_preloaded_route;
- }
- }
- }
-};
-
-UA.C = C;
-JsSIP.UA = UA;
-}(JsSIP));
-
-
-/**
- * @fileoverview Utils
- */
-
-(function(JsSIP) {
-var Utils;
-
-Utils= {
-
- str_utf8_length: function(string) {
- return window.unescape(encodeURIComponent(string)).length;
- },
-
- isFunction: function(fn) {
- if (fn !== undefined) {
- return (Object.prototype.toString.call(fn) === '[object Function]')? true : false;
- } else {
- return false;
- }
- },
-
- isDecimal: function (num) {
- return !isNaN(num) && (parseFloat(num) === parseInt(num,10));
- },
-
- isEmpty: function(value) {
- if (value === null || value === "" || value === undefined || (value instanceof Array && value.length === 0) || (typeof(value) === 'number' && window.isNaN(value))) {
- return true;
- }
- },
-
- createRandomToken: function(size, base) {
- var i, r,
- token = '';
-
- base = base || 32;
-
- for( i=0; i < size; i++ ) {
- r = Math.random() * base|0;
- token += r.toString(base);
- }
-
- return token;
- },
-
- newTag: function() {
- return JsSIP.Utils.createRandomToken(JsSIP.UA.C.TAG_LENGTH);
- },
-
- // http://stackoverflow.com/users/109538/broofa
- newUUID: function() {
- var UUID = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
- var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
- return v.toString(16);
- });
-
- return UUID;
- },
-
- hostType: function(host) {
- if (!host) {
- return;
- } else {
- host = JsSIP.Grammar.parse(host,'host');
- if (host !== -1) {
- return host.host_type;
- }
- }
- },
-
- /**
- * Normalize SIP URI.
- * NOTE: It does not allow a SIP URI without username.
- * Accepts 'sip', 'sips' and 'tel' URIs and convert them into 'sip'.
- * Detects the domain part (if given) and properly hex-escapes the user portion.
- * If the user portion has only 'tel' number symbols the user portion is clean of 'tel' visual separators.
- * @private
- * @param {String} target
- * @param {String} [domain]
- */
- normalizeTarget: function(target, domain) {
- var uri, target_array, target_user, target_domain;
-
- // If no target is given then raise an error.
- if (!target) {
- return;
- // If a JsSIP.URI instance is given then return it.
- } else if (target instanceof JsSIP.URI) {
- return target;
-
- // If a string is given split it by '@':
- // - Last fragment is the desired domain.
- // - Otherwise append the given domain argument.
- } else if (typeof target === 'string') {
- target_array = target.split('@');
-
- switch(target_array.length) {
- case 1:
- if (!domain) {
- return;
- }
- target_user = target;
- target_domain = domain;
- break;
- case 2:
- target_user = target_array[0];
- target_domain = target_array[1];
- break;
- default:
- target_user = target_array.slice(0, target_array.length-1).join('@');
- target_domain = target_array[target_array.length-1];
- }
-
- // Remove the URI scheme (if present).
- target_user = target_user.replace(/^(sips?|tel):/i, '');
-
- // Remove 'tel' visual separators if the user portion just contains 'tel' number symbols.
- if (/^[\-\.\(\)]*\+?[0-9\-\.\(\)]+$/.test(target_user)) {
- target_user = target_user.replace(/[\-\.\(\)]/g, '');
- }
-
- // Build the complete SIP URI.
- target = JsSIP.C.SIP + ':' + JsSIP.Utils.escapeUser(target_user) + '@' + target_domain;
-
- // Finally parse the resulting URI.
- if (uri = JsSIP.URI.parse(target)) {
- return uri;
- } else {
- return;
- }
- } else {
- return;
- }
- },
-
- /**
- * Hex-escape a SIP URI user.
- * @private
- * @param {String} user
- */
- escapeUser: function(user) {
- // Don't hex-escape ':' (%3A), '+' (%2B), '?' (%3F"), '/' (%2F).
- return window.encodeURIComponent(window.decodeURIComponent(user)).replace(/%3A/ig, ':').replace(/%2B/ig, '+').replace(/%3F/ig, '?').replace(/%2F/ig, '/');
- },
-
- headerize: function(string) {
- var exceptions = {
- 'Call-Id': 'Call-ID',
- 'Cseq': 'CSeq',
- 'Www-Authenticate': 'WWW-Authenticate'
- },
- name = string.toLowerCase().replace(/_/g,'-').split('-'),
- hname = '',
- parts = name.length, part;
-
- for (part = 0; part < parts; part++) {
- if (part !== 0) {
- hname +='-';
- }
- hname += name[part].charAt(0).toUpperCase()+name[part].substring(1);
- }
- if (exceptions[hname]) {
- hname = exceptions[hname];
- }
- return hname;
- },
-
- sipErrorCause: function(status_code) {
- var cause;
-
- for (cause in JsSIP.C.SIP_ERROR_CAUSES) {
- if (JsSIP.C.SIP_ERROR_CAUSES[cause].indexOf(status_code) !== -1) {
- return JsSIP.C.causes[cause];
- }
- }
-
- return JsSIP.C.causes.SIP_FAILURE_CODE;
- },
-
- /**
- * Generate a random Test-Net IP (http://tools.ietf.org/html/rfc5735)
- * @private
- */
- getRandomTestNetIP: function() {
- function getOctet(from,to) {
- return window.Math.floor(window.Math.random()*(to-from+1)+from);
- }
- return '192.0.2.' + getOctet(1, 254);
- },
-
- getAllowedMethods: function(ua) {
- var event,
- allowed = JsSIP.UA.C.ALLOWED_METHODS.toString();
-
- for (event in JsSIP.UA.C.EVENT_METHODS) {
- if (ua.checkEvent(event) && ua.listeners(event).length > 0) {
- allowed += ','+ JsSIP.UA.C.EVENT_METHODS[event];
- }
- }
-
- return allowed;
- },
-
- // MD5 (Message-Digest Algorithm) http://www.webtoolkit.info
- calculateMD5: function(string) {
- function RotateLeft(lValue, iShiftBits) {
- return (lValue<>>(32-iShiftBits));
- }
-
- function AddUnsigned(lX,lY) {
- var lX4,lY4,lX8,lY8,lResult;
- lX8 = (lX & 0x80000000);
- lY8 = (lY & 0x80000000);
- lX4 = (lX & 0x40000000);
- lY4 = (lY & 0x40000000);
- lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
- if (lX4 & lY4) {
- return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
- }
- if (lX4 | lY4) {
- if (lResult & 0x40000000) {
- return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
- } else {
- return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
- }
- } else {
- return (lResult ^ lX8 ^ lY8);
- }
- }
-
- function F(x,y,z) {
- return (x & y) | ((~x) & z);
- }
-
- function G(x,y,z) {
- return (x & z) | (y & (~z));
- }
-
- function H(x,y,z) {
- return (x ^ y ^ z);
- }
-
- function I(x,y,z) {
- return (y ^ (x | (~z)));
- }
-
- function FF(a,b,c,d,x,s,ac) {
- a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
- return AddUnsigned(RotateLeft(a, s), b);
- }
-
- function GG(a,b,c,d,x,s,ac) {
- a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
- return AddUnsigned(RotateLeft(a, s), b);
- }
-
- function HH(a,b,c,d,x,s,ac) {
- a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
- return AddUnsigned(RotateLeft(a, s), b);
- }
-
- function II(a,b,c,d,x,s,ac) {
- a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
- return AddUnsigned(RotateLeft(a, s), b);
- }
-
- function ConvertToWordArray(string) {
- var lWordCount;
- var lMessageLength = string.length;
- var lNumberOfWords_temp1=lMessageLength + 8;
- var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
- var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
- var lWordArray=Array(lNumberOfWords-1);
- var lBytePosition = 0;
- var lByteCount = 0;
- while ( lByteCount < lMessageLength ) {
- lWordCount = (lByteCount-(lByteCount % 4))/4;
- lBytePosition = (lByteCount % 4)*8;
- lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<>>29;
- return lWordArray;
- }
-
- function WordToHex(lValue) {
- var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
- for (lCount = 0;lCount<=3;lCount++) {
- lByte = (lValue>>>(lCount*8)) & 255;
- WordToHexValue_temp = "0" + lByte.toString(16);
- WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
- }
- return WordToHexValue;
- }
-
- function Utf8Encode(string) {
- string = string.replace(/\r\n/g,"\n");
- var utftext = "";
-
- for (var n = 0; n < string.length; n++) {
- var c = string.charCodeAt(n);
-
- if (c < 128) {
- utftext += String.fromCharCode(c);
- }
- else if((c > 127) && (c < 2048)) {
- utftext += String.fromCharCode((c >> 6) | 192);
- utftext += String.fromCharCode((c & 63) | 128);
- }
- else {
- utftext += String.fromCharCode((c >> 12) | 224);
- utftext += String.fromCharCode(((c >> 6) & 63) | 128);
- utftext += String.fromCharCode((c & 63) | 128);
- }
- }
- return utftext;
- }
-
- var x=[];
- var k,AA,BB,CC,DD,a,b,c,d;
- var S11=7, S12=12, S13=17, S14=22;
- var S21=5, S22=9 , S23=14, S24=20;
- var S31=4, S32=11, S33=16, S34=23;
- var S41=6, S42=10, S43=15, S44=21;
-
- string = Utf8Encode(string);
-
- x = ConvertToWordArray(string);
-
- a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
-
- for (k=0;k 1) {
- logger.warn('More than one Via header field present in the response. Dropping the response');
- return false;
- }
-}
-
-function rfc3261_18_1_2() {
- var via_host = ua.configuration.via_host;
- if(message.via.host !== via_host) {
- logger.warn('Via host in the response does not match UA Via host value. Dropping the response');
- return false;
- }
-}
-
-function rfc3261_18_3_response() {
- var
- len = JsSIP.Utils.str_utf8_length(message.body),
- contentLength = message.getHeader('content-length');
-
- if(len < contentLength) {
- logger.warn('Message body length is lower than the value in Content-Length header field. Dropping the response');
- return false;
- }
-}
-
-// Sanity Check functions for requests and responses
-function minimumHeaders() {
- var
- mandatoryHeaders = ['from', 'to', 'call_id', 'cseq', 'via'],
- idx = mandatoryHeaders.length;
-
- while(idx--) {
- if(!message.hasHeader(mandatoryHeaders[idx])) {
- logger.warn('Missing mandatory header field : '+ mandatoryHeaders[idx] +'. Dropping the response');
- return false;
- }
- }
-}
-
-// Reply
-function reply(status_code) {
- var to,
- response = "SIP/2.0 " + status_code + " " + JsSIP.C.REASON_PHRASE[status_code] + "\r\n",
- vias = message.getHeaders('via'),
- length = vias.length,
- idx = 0;
-
- for(idx; idx < length; idx++) {
- response += "Via: " + vias[idx] + "\r\n";
- }
-
- to = message.getHeader('To');
-
- if(!message.to_tag) {
- to += ';tag=' + JsSIP.Utils.newTag();
- }
-
- response += "To: " + to + "\r\n";
- response += "From: " + message.getHeader('From') + "\r\n";
- response += "Call-ID: " + message.call_id + "\r\n";
- response += "CSeq: " + message.cseq + " " + message.method + "\r\n";
- response += "\r\n";
-
- transport.send(response);
-}
-
-requests.push(rfc3261_8_2_2_1);
-requests.push(rfc3261_16_3_4);
-requests.push(rfc3261_18_3_request);
-requests.push(rfc3261_8_2_2_2);
-
-responses.push(rfc3261_8_1_3_3);
-responses.push(rfc3261_18_1_2);
-responses.push(rfc3261_18_3_response);
-
-all.push(minimumHeaders);
-
-sanityCheck = function(m, u, t) {
- var len, pass;
-
- message = m;
- ua = u;
- transport = t;
-
- logger = ua.getLogger('jssip.sanitycheck');
-
- len = all.length;
- while(len--) {
- pass = all[len](message);
- if(pass === false) {
- return false;
- }
- }
-
- if(message instanceof JsSIP.IncomingRequest) {
- len = requests.length;
- while(len--) {
- pass = requests[len](message);
- if(pass === false) {
- return false;
- }
- }
- }
-
- else if(message instanceof JsSIP.IncomingResponse) {
- len = responses.length;
- while(len--) {
- pass = responses[len](message);
- if(pass === false) {
- return false;
- }
- }
- }
-
- //Everything is OK
- return true;
-};
-
-JsSIP.sanityCheck = sanityCheck;
-}(JsSIP));
-
-
-
-/**
- * @fileoverview SIP Digest Authentication
- */
-
-/**
- * SIP Digest Authentication.
- * @augments JsSIP.
- * @function Digest Authentication
- * @param {JsSIP.UA} ua
- */
-(function(JsSIP) {
-var DigestAuthentication;
-
-DigestAuthentication = function(ua) {
- this.logger = ua.getLogger('jssip.digestauthentication');
- this.username = ua.configuration.authorization_user;
- this.password = ua.configuration.password;
- this.cnonce = null;
- this.nc = 0;
- this.ncHex = '00000000';
- this.response = null;
-};
-
-
-/**
-* Performs Digest authentication given a SIP request and the challenge
-* received in a response to that request.
-* Returns true if credentials were successfully generated, false otherwise.
-*
-* @param {JsSIP.OutgoingRequest} request
-* @param {Object} challenge
-*/
-DigestAuthentication.prototype.authenticate = function(request, challenge) {
- // Inspect and validate the challenge.
-
- this.algorithm = challenge.algorithm;
- this.realm = challenge.realm;
- this.nonce = challenge.nonce;
- this.opaque = challenge.opaque;
- this.stale = challenge.stale;
-
- if (this.algorithm) {
- if (this.algorithm !== 'MD5') {
- this.logger.warn('challenge with Digest algorithm different than "MD5", authentication aborted');
- return false;
- }
- } else {
- this.algorithm = 'MD5';
- }
-
- if (! this.realm) {
- this.logger.warn('challenge without Digest realm, authentication aborted');
- return false;
- }
-
- if (! this.nonce) {
- this.logger.warn('challenge without Digest nonce, authentication aborted');
- return false;
- }
-
- // 'qop' can contain a list of values (Array). Let's choose just one.
- if (challenge.qop) {
- if (challenge.qop.indexOf('auth') > -1) {
- this.qop = 'auth';
- } else if (challenge.qop.indexOf('auth-int') > -1) {
- this.qop = 'auth-int';
- } else {
- // Otherwise 'qop' is present but does not contain 'auth' or 'auth-int', so abort here.
- this.logger.warn('challenge without Digest qop different than "auth" or "auth-int", authentication aborted');
- return false;
- }
- } else {
- this.qop = null;
- }
-
- // Fill other attributes.
-
- this.method = request.method;
- this.uri = request.ruri;
- this.cnonce = JsSIP.Utils.createRandomToken(12);
- this.nc += 1;
- this.updateNcHex();
-
- // nc-value = 8LHEX. Max value = 'FFFFFFFF'.
- if (this.nc === 4294967296) {
- this.nc = 1;
- this.ncHex = '00000001';
- }
-
- // Calculate the Digest "response" value.
- this.calculateResponse();
-
- return true;
-};
-
-
-/**
-* Generate Digest 'response' value.
-* @private
-*/
-DigestAuthentication.prototype.calculateResponse = function() {
- var ha1, ha2;
-
- // HA1 = MD5(A1) = MD5(username:realm:password)
- ha1 = JsSIP.Utils.calculateMD5(this.username + ":" + this.realm + ":" + this.password);
-
- if (this.qop === 'auth') {
- // HA2 = MD5(A2) = MD5(method:digestURI)
- ha2 = JsSIP.Utils.calculateMD5(this.method + ":" + this.uri);
- // response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2)
- this.response = JsSIP.Utils.calculateMD5(ha1 + ":" + this.nonce + ":" + this.ncHex + ":" + this.cnonce + ":auth:" + ha2);
-
- } else if (this.qop === 'auth-int') {
- // HA2 = MD5(A2) = MD5(method:digestURI:MD5(entityBody))
- ha2 = JsSIP.Utils.calculateMD5(this.method + ":" + this.uri + ":" + JsSIP.Utils.calculateMD5(this.body ? this.body : ""));
- // response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2)
- this.response = JsSIP.Utils.calculateMD5(ha1 + ":" + this.nonce + ":" + this.ncHex + ":" + this.cnonce + ":auth-int:" + ha2);
-
- } else if (this.qop === null) {
- // HA2 = MD5(A2) = MD5(method:digestURI)
- ha2 = JsSIP.Utils.calculateMD5(this.method + ":" + this.uri);
- // response = MD5(HA1:nonce:HA2)
- this.response = JsSIP.Utils.calculateMD5(ha1 + ":" + this.nonce + ":" + ha2);
- }
-};
-
-
-/**
-* Return the Proxy-Authorization or WWW-Authorization header value.
-*/
-DigestAuthentication.prototype.toString = function() {
- var auth_params = [];
-
- if (! this.response) {
- throw new Error('response field does not exist, cannot generate Authorization header');
- }
-
- auth_params.push('algorithm=' + this.algorithm);
- auth_params.push('username="' + this.username + '"');
- auth_params.push('realm="' + this.realm + '"');
- auth_params.push('nonce="' + this.nonce + '"');
- auth_params.push('uri="' + this.uri + '"');
- auth_params.push('response="' + this.response + '"');
- if (this.opaque) {
- auth_params.push('opaque="' + this.opaque + '"');
- }
- if (this.qop) {
- auth_params.push('qop=' + this.qop);
- auth_params.push('cnonce="' + this.cnonce + '"');
- auth_params.push('nc=' + this.ncHex);
- }
-
- return 'Digest ' + auth_params.join(', ');
-};
-
-
-/**
-* Generate the 'nc' value as required by Digest in this.ncHex by reading this.nc.
-* @private
-*/
-DigestAuthentication.prototype.updateNcHex = function() {
- var hex = Number(this.nc).toString(16);
- this.ncHex = '00000000'.substr(0, 8-hex.length) + hex;
-};
-
-JsSIP.DigestAuthentication = DigestAuthentication;
-}(JsSIP));
-
-
-/**
- * @fileoverview WebRTC
- */
-
-(function(JsSIP) {
-var WebRTC;
-
-WebRTC = {};
-
-// getUserMedia
-if (window.navigator.webkitGetUserMedia) {
- WebRTC.getUserMedia = window.navigator.webkitGetUserMedia.bind(navigator);
-}
-else if (window.navigator.mozGetUserMedia) {
- WebRTC.getUserMedia = window.navigator.mozGetUserMedia.bind(navigator);
-}
-else if (window.navigator.getUserMedia) {
- WebRTC.getUserMedia = window.navigator.getUserMedia.bind(navigator);
-}
-
-// RTCPeerConnection
-if (window.webkitRTCPeerConnection) {
- WebRTC.RTCPeerConnection = window.webkitRTCPeerConnection;
-}
-else if (window.mozRTCPeerConnection) {
- WebRTC.RTCPeerConnection = window.mozRTCPeerConnection;
-}
-else if (window.RTCPeerConnection) {
- WebRTC.RTCPeerConnection = window.RTCPeerConnection;
-}
-
-// RTCSessionDescription
-if (window.webkitRTCSessionDescription) {
- WebRTC.RTCSessionDescription = window.webkitRTCSessionDescription;
-}
-else if (window.mozRTCSessionDescription) {
- WebRTC.RTCSessionDescription = window.mozRTCSessionDescription;
-}
-else if (window.RTCSessionDescription) {
- WebRTC.RTCSessionDescription = window.RTCSessionDescription;
-}
-
-// New syntax for getting streams in Chrome M26.
-if (WebRTC.RTCPeerConnection && WebRTC.RTCPeerConnection.prototype) {
- if (!WebRTC.RTCPeerConnection.prototype.getLocalStreams) {
- WebRTC.RTCPeerConnection.prototype.getLocalStreams = function() {
- return this.localStreams;
- };
- WebRTC.RTCPeerConnection.prototype.getRemoteStreams = function() {
- return this.remoteStreams;
- };
- }
-}
-
-// isSupported attribute.
-if (WebRTC.getUserMedia && WebRTC.RTCPeerConnection && WebRTC.RTCSessionDescription) {
- WebRTC.isSupported = true;
-}
-else {
- WebRTC.isSupported = false;
-}
-
-JsSIP.WebRTC = WebRTC;
-}(JsSIP));
-
-
-if (typeof module === "object" && module && typeof module.exports === "object") {
- // Expose JsSIP as module.exports in loaders that implement the Node
- // module pattern (including browserify). Do not create the global, since
- // the user will be storing it themselves locally, and globals are frowned
- // upon in the Node module world.
- module.exports = JsSIP;
-} else {
- // Otherwise expose JsSIP to the global object as usual.
- window.JsSIP = JsSIP;
-
- // Register as a named AMD module, since JsSIP can be concatenated with other
- // files that may use define, but not via a proper concatenation script that
- // understands anonymous AMD modules. A named AMD is safest and most robust
- // way to register. Lowercase jssip is used because AMD module names are
- // derived from file names, and JsSIP is normally delivered in a lowercase
- // file name.
- if (typeof define === "function" && define.amd) {
- define("jssip", [], function () { return JsSIP; });
- }
-}
-
-})(window);
-
-JsSIP.Grammar = (function(){
- /*
- * Generated by PEG.js 0.7.0.
- *
- * http://pegjs.majda.cz/
- */
-
- function quote(s) {
- /*
- * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
- * string literal except for the closing quote character, backslash,
- * carriage return, line separator, paragraph separator, and line feed.
- * Any character may appear in the form of an escape sequence.
- *
- * For portability, we also escape escape all control and non-ASCII
- * characters. Note that "\0" and "\v" escape sequences are not used
- * because JSHint does not like the first and IE the second.
- */
- return '"' + s
- .replace(/\\/g, '\\\\') // backslash
- .replace(/"/g, '\\"') // closing quote character
- .replace(/\x08/g, '\\b') // backspace
- .replace(/\t/g, '\\t') // horizontal tab
- .replace(/\n/g, '\\n') // line feed
- .replace(/\f/g, '\\f') // form feed
- .replace(/\r/g, '\\r') // carriage return
- .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape)
- + '"';
- }
-
- var result = {
- /*
- * Parses the input with a generated parser. If the parsing is successfull,
- * returns a value explicitly or implicitly specified by the grammar from
- * which the parser was generated (see |PEG.buildParser|). If the parsing is
- * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.
- */
- parse: function(input, startRule) {
- var parseFunctions = {
- "CRLF": parse_CRLF,
- "DIGIT": parse_DIGIT,
- "ALPHA": parse_ALPHA,
- "HEXDIG": parse_HEXDIG,
- "WSP": parse_WSP,
- "OCTET": parse_OCTET,
- "DQUOTE": parse_DQUOTE,
- "SP": parse_SP,
- "HTAB": parse_HTAB,
- "alphanum": parse_alphanum,
- "reserved": parse_reserved,
- "unreserved": parse_unreserved,
- "mark": parse_mark,
- "escaped": parse_escaped,
- "LWS": parse_LWS,
- "SWS": parse_SWS,
- "HCOLON": parse_HCOLON,
- "TEXT_UTF8_TRIM": parse_TEXT_UTF8_TRIM,
- "TEXT_UTF8char": parse_TEXT_UTF8char,
- "UTF8_NONASCII": parse_UTF8_NONASCII,
- "UTF8_CONT": parse_UTF8_CONT,
- "LHEX": parse_LHEX,
- "token": parse_token,
- "token_nodot": parse_token_nodot,
- "separators": parse_separators,
- "word": parse_word,
- "STAR": parse_STAR,
- "SLASH": parse_SLASH,
- "EQUAL": parse_EQUAL,
- "LPAREN": parse_LPAREN,
- "RPAREN": parse_RPAREN,
- "RAQUOT": parse_RAQUOT,
- "LAQUOT": parse_LAQUOT,
- "COMMA": parse_COMMA,
- "SEMI": parse_SEMI,
- "COLON": parse_COLON,
- "LDQUOT": parse_LDQUOT,
- "RDQUOT": parse_RDQUOT,
- "comment": parse_comment,
- "ctext": parse_ctext,
- "quoted_string": parse_quoted_string,
- "quoted_string_clean": parse_quoted_string_clean,
- "qdtext": parse_qdtext,
- "quoted_pair": parse_quoted_pair,
- "SIP_URI_noparams": parse_SIP_URI_noparams,
- "SIP_URI": parse_SIP_URI,
- "uri_scheme": parse_uri_scheme,
- "userinfo": parse_userinfo,
- "user": parse_user,
- "user_unreserved": parse_user_unreserved,
- "password": parse_password,
- "hostport": parse_hostport,
- "host": parse_host,
- "hostname": parse_hostname,
- "domainlabel": parse_domainlabel,
- "toplabel": parse_toplabel,
- "IPv6reference": parse_IPv6reference,
- "IPv6address": parse_IPv6address,
- "h16": parse_h16,
- "ls32": parse_ls32,
- "IPv4address": parse_IPv4address,
- "dec_octet": parse_dec_octet,
- "port": parse_port,
- "uri_parameters": parse_uri_parameters,
- "uri_parameter": parse_uri_parameter,
- "transport_param": parse_transport_param,
- "user_param": parse_user_param,
- "method_param": parse_method_param,
- "ttl_param": parse_ttl_param,
- "maddr_param": parse_maddr_param,
- "lr_param": parse_lr_param,
- "other_param": parse_other_param,
- "pname": parse_pname,
- "pvalue": parse_pvalue,
- "paramchar": parse_paramchar,
- "param_unreserved": parse_param_unreserved,
- "headers": parse_headers,
- "header": parse_header,
- "hname": parse_hname,
- "hvalue": parse_hvalue,
- "hnv_unreserved": parse_hnv_unreserved,
- "Request_Response": parse_Request_Response,
- "Request_Line": parse_Request_Line,
- "Request_URI": parse_Request_URI,
- "absoluteURI": parse_absoluteURI,
- "hier_part": parse_hier_part,
- "net_path": parse_net_path,
- "abs_path": parse_abs_path,
- "opaque_part": parse_opaque_part,
- "uric": parse_uric,
- "uric_no_slash": parse_uric_no_slash,
- "path_segments": parse_path_segments,
- "segment": parse_segment,
- "param": parse_param,
- "pchar": parse_pchar,
- "scheme": parse_scheme,
- "authority": parse_authority,
- "srvr": parse_srvr,
- "reg_name": parse_reg_name,
- "query": parse_query,
- "SIP_Version": parse_SIP_Version,
- "INVITEm": parse_INVITEm,
- "ACKm": parse_ACKm,
- "OPTIONSm": parse_OPTIONSm,
- "BYEm": parse_BYEm,
- "CANCELm": parse_CANCELm,
- "REGISTERm": parse_REGISTERm,
- "SUBSCRIBEm": parse_SUBSCRIBEm,
- "NOTIFYm": parse_NOTIFYm,
- "Method": parse_Method,
- "Status_Line": parse_Status_Line,
- "Status_Code": parse_Status_Code,
- "extension_code": parse_extension_code,
- "Reason_Phrase": parse_Reason_Phrase,
- "Allow_Events": parse_Allow_Events,
- "Call_ID": parse_Call_ID,
- "Contact": parse_Contact,
- "contact_param": parse_contact_param,
- "name_addr": parse_name_addr,
- "display_name": parse_display_name,
- "contact_params": parse_contact_params,
- "c_p_q": parse_c_p_q,
- "c_p_expires": parse_c_p_expires,
- "delta_seconds": parse_delta_seconds,
- "qvalue": parse_qvalue,
- "generic_param": parse_generic_param,
- "gen_value": parse_gen_value,
- "Content_Disposition": parse_Content_Disposition,
- "disp_type": parse_disp_type,
- "disp_param": parse_disp_param,
- "handling_param": parse_handling_param,
- "Content_Encoding": parse_Content_Encoding,
- "Content_Length": parse_Content_Length,
- "Content_Type": parse_Content_Type,
- "media_type": parse_media_type,
- "m_type": parse_m_type,
- "discrete_type": parse_discrete_type,
- "composite_type": parse_composite_type,
- "extension_token": parse_extension_token,
- "x_token": parse_x_token,
- "m_subtype": parse_m_subtype,
- "m_parameter": parse_m_parameter,
- "m_value": parse_m_value,
- "CSeq": parse_CSeq,
- "CSeq_value": parse_CSeq_value,
- "Expires": parse_Expires,
- "Event": parse_Event,
- "event_type": parse_event_type,
- "From": parse_From,
- "from_param": parse_from_param,
- "tag_param": parse_tag_param,
- "Max_Forwards": parse_Max_Forwards,
- "Min_Expires": parse_Min_Expires,
- "Name_Addr_Header": parse_Name_Addr_Header,
- "Proxy_Authenticate": parse_Proxy_Authenticate,
- "challenge": parse_challenge,
- "other_challenge": parse_other_challenge,
- "auth_param": parse_auth_param,
- "digest_cln": parse_digest_cln,
- "realm": parse_realm,
- "realm_value": parse_realm_value,
- "domain": parse_domain,
- "URI": parse_URI,
- "nonce": parse_nonce,
- "nonce_value": parse_nonce_value,
- "opaque": parse_opaque,
- "stale": parse_stale,
- "algorithm": parse_algorithm,
- "qop_options": parse_qop_options,
- "qop_value": parse_qop_value,
- "Proxy_Require": parse_Proxy_Require,
- "Record_Route": parse_Record_Route,
- "rec_route": parse_rec_route,
- "Require": parse_Require,
- "Route": parse_Route,
- "route_param": parse_route_param,
- "Subscription_State": parse_Subscription_State,
- "substate_value": parse_substate_value,
- "subexp_params": parse_subexp_params,
- "event_reason_value": parse_event_reason_value,
- "Subject": parse_Subject,
- "Supported": parse_Supported,
- "To": parse_To,
- "to_param": parse_to_param,
- "Via": parse_Via,
- "via_parm": parse_via_parm,
- "via_params": parse_via_params,
- "via_ttl": parse_via_ttl,
- "via_maddr": parse_via_maddr,
- "via_received": parse_via_received,
- "via_branch": parse_via_branch,
- "response_port": parse_response_port,
- "sent_protocol": parse_sent_protocol,
- "protocol_name": parse_protocol_name,
- "transport": parse_transport,
- "sent_by": parse_sent_by,
- "via_host": parse_via_host,
- "via_port": parse_via_port,
- "ttl": parse_ttl,
- "WWW_Authenticate": parse_WWW_Authenticate,
- "extension_header": parse_extension_header,
- "header_value": parse_header_value,
- "message_body": parse_message_body,
- "stun_URI": parse_stun_URI,
- "stun_scheme": parse_stun_scheme,
- "stun_host_port": parse_stun_host_port,
- "stun_host": parse_stun_host,
- "reg_name": parse_reg_name,
- "stun_unreserved": parse_stun_unreserved,
- "sub_delims": parse_sub_delims,
- "turn_URI": parse_turn_URI,
- "turn_scheme": parse_turn_scheme,
- "turn_transport": parse_turn_transport,
- "uuid_URI": parse_uuid_URI,
- "uuid": parse_uuid,
- "hex4": parse_hex4,
- "hex8": parse_hex8,
- "hex12": parse_hex12
- };
-
- if (startRule !== undefined) {
- if (parseFunctions[startRule] === undefined) {
- throw new Error("Invalid rule name: " + quote(startRule) + ".");
- }
- } else {
- startRule = "CRLF";
- }
-
- var pos = 0;
- var reportFailures = 0;
- var rightmostFailuresPos = 0;
- var rightmostFailuresExpected = [];
-
- function padLeft(input, padding, length) {
- var result = input;
-
- var padLength = length - input.length;
- for (var i = 0; i < padLength; i++) {
- result = padding + result;
- }
-
- return result;
- }
-
- function escape(ch) {
- var charCode = ch.charCodeAt(0);
- var escapeChar;
- var length;
-
- if (charCode <= 0xFF) {
- escapeChar = 'x';
- length = 2;
- } else {
- escapeChar = 'u';
- length = 4;
- }
-
- return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
- }
-
- function matchFailed(failure) {
- if (pos < rightmostFailuresPos) {
- return;
- }
-
- if (pos > rightmostFailuresPos) {
- rightmostFailuresPos = pos;
- rightmostFailuresExpected = [];
- }
-
- rightmostFailuresExpected.push(failure);
- }
-
- function parse_CRLF() {
- var result0;
-
- if (input.substr(pos, 2) === "\r\n") {
- result0 = "\r\n";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\r\\n\"");
- }
- }
- return result0;
- }
-
- function parse_DIGIT() {
- var result0;
-
- if (/^[0-9]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[0-9]");
- }
- }
- return result0;
- }
-
- function parse_ALPHA() {
- var result0;
-
- if (/^[a-zA-Z]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[a-zA-Z]");
- }
- }
- return result0;
- }
-
- function parse_HEXDIG() {
- var result0;
-
- if (/^[0-9a-fA-F]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[0-9a-fA-F]");
- }
- }
- return result0;
- }
-
- function parse_WSP() {
- var result0;
-
- result0 = parse_SP();
- if (result0 === null) {
- result0 = parse_HTAB();
- }
- return result0;
- }
-
- function parse_OCTET() {
- var result0;
-
- if (/^[\0-\xFF]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\0-\\xFF]");
- }
- }
- return result0;
- }
-
- function parse_DQUOTE() {
- var result0;
-
- if (/^["]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\"]");
- }
- }
- return result0;
- }
-
- function parse_SP() {
- var result0;
-
- if (input.charCodeAt(pos) === 32) {
- result0 = " ";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\" \"");
- }
- }
- return result0;
- }
-
- function parse_HTAB() {
- var result0;
-
- if (input.charCodeAt(pos) === 9) {
- result0 = "\t";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\t\"");
- }
- }
- return result0;
- }
-
- function parse_alphanum() {
- var result0;
-
- if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[a-zA-Z0-9]");
- }
- }
- return result0;
- }
-
- function parse_reserved() {
- var result0;
-
- if (input.charCodeAt(pos) === 59) {
- result0 = ";";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 64) {
- result0 = "@";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_unreserved() {
- var result0;
-
- result0 = parse_alphanum();
- if (result0 === null) {
- result0 = parse_mark();
- }
- return result0;
- }
-
- function parse_mark() {
- var result0;
-
- if (input.charCodeAt(pos) === 45) {
- result0 = "-";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 95) {
- result0 = "_";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 46) {
- result0 = ".";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 33) {
- result0 = "!";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 126) {
- result0 = "~";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 42) {
- result0 = "*";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 39) {
- result0 = "'";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 40) {
- result0 = "(";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 41) {
- result0 = ")";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_escaped() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.charCodeAt(pos) === 37) {
- result0 = "%";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_HEXDIG();
- if (result1 !== null) {
- result2 = parse_HEXDIG();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, escaped) {return escaped.join(''); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_LWS() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- pos2 = pos;
- result0 = [];
- result1 = parse_WSP();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_WSP();
- }
- if (result0 !== null) {
- result1 = parse_CRLF();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos2;
- }
- } else {
- result0 = null;
- pos = pos2;
- }
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result2 = parse_WSP();
- if (result2 !== null) {
- result1 = [];
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_WSP();
- }
- } else {
- result1 = null;
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return " "; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_SWS() {
- var result0;
-
- result0 = parse_LWS();
- result0 = result0 !== null ? result0 : "";
- return result0;
- }
-
- function parse_HCOLON() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = [];
- result1 = parse_SP();
- if (result1 === null) {
- result1 = parse_HTAB();
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_SP();
- if (result1 === null) {
- result1 = parse_HTAB();
- }
- }
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ':'; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_TEXT_UTF8_TRIM() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result1 = parse_TEXT_UTF8char();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_TEXT_UTF8char();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = [];
- result3 = parse_LWS();
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_LWS();
- }
- if (result2 !== null) {
- result3 = parse_TEXT_UTF8char();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = [];
- result3 = parse_LWS();
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_LWS();
- }
- if (result2 !== null) {
- result3 = parse_TEXT_UTF8char();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_TEXT_UTF8char() {
- var result0;
-
- if (/^[!-~]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[!-~]");
- }
- }
- if (result0 === null) {
- result0 = parse_UTF8_NONASCII();
- }
- return result0;
- }
-
- function parse_UTF8_NONASCII() {
- var result0;
-
- if (/^[\x80-\uFFFF]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\x80-\\uFFFF]");
- }
- }
- return result0;
- }
-
- function parse_UTF8_CONT() {
- var result0;
-
- if (/^[\x80-\xBF]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\x80-\\xBF]");
- }
- }
- return result0;
- }
-
- function parse_LHEX() {
- var result0;
-
- result0 = parse_DIGIT();
- if (result0 === null) {
- if (/^[a-f]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[a-f]");
- }
- }
- }
- return result0;
- }
-
- function parse_token() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_token_nodot() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_separators() {
- var result0;
-
- if (input.charCodeAt(pos) === 40) {
- result0 = "(";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 41) {
- result0 = ")";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 60) {
- result0 = "<";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"<\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 62) {
- result0 = ">";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\">\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 64) {
- result0 = "@";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 59) {
- result0 = ";";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 92) {
- result0 = "\\";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\\\\"");
- }
- }
- if (result0 === null) {
- result0 = parse_DQUOTE();
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 91) {
- result0 = "[";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 93) {
- result0 = "]";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 123) {
- result0 = "{";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"{\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 125) {
- result0 = "}";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"}\"");
- }
- }
- if (result0 === null) {
- result0 = parse_SP();
- if (result0 === null) {
- result0 = parse_HTAB();
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_word() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 40) {
- result1 = "(";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 41) {
- result1 = ")";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 60) {
- result1 = "<";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"<\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 62) {
- result1 = ">";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\">\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 92) {
- result1 = "\\";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\\\\"");
- }
- }
- if (result1 === null) {
- result1 = parse_DQUOTE();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 47) {
- result1 = "/";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 91) {
- result1 = "[";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 93) {
- result1 = "]";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 63) {
- result1 = "?";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 123) {
- result1 = "{";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"{\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 125) {
- result1 = "}";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"}\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_alphanum();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 33) {
- result1 = "!";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 37) {
- result1 = "%";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"%\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 95) {
- result1 = "_";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 96) {
- result1 = "`";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"`\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 39) {
- result1 = "'";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 126) {
- result1 = "~";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 40) {
- result1 = "(";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 41) {
- result1 = ")";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 60) {
- result1 = "<";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"<\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 62) {
- result1 = ">";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\">\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 92) {
- result1 = "\\";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\\\\"");
- }
- }
- if (result1 === null) {
- result1 = parse_DQUOTE();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 47) {
- result1 = "/";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 91) {
- result1 = "[";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 93) {
- result1 = "]";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 63) {
- result1 = "?";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 123) {
- result1 = "{";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"{\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 125) {
- result1 = "}";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"}\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_STAR() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 42) {
- result1 = "*";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "*"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_SLASH() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 47) {
- result1 = "/";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "/"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_EQUAL() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "="; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_LPAREN() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 40) {
- result1 = "(";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "("; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_RPAREN() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 41) {
- result1 = ")";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ")"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_RAQUOT() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.charCodeAt(pos) === 62) {
- result0 = ">";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\">\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_SWS();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ">"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_LAQUOT() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 60) {
- result1 = "<";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"<\"");
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "<"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_COMMA() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ","; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_SEMI() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ";"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_COLON() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_SWS();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return ":"; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_LDQUOT() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- result1 = parse_DQUOTE();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "\""; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_RDQUOT() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_DQUOTE();
- if (result0 !== null) {
- result1 = parse_SWS();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {return "\""; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_comment() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_LPAREN();
- if (result0 !== null) {
- result1 = [];
- result2 = parse_ctext();
- if (result2 === null) {
- result2 = parse_quoted_pair();
- if (result2 === null) {
- result2 = parse_comment();
- }
- }
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_ctext();
- if (result2 === null) {
- result2 = parse_quoted_pair();
- if (result2 === null) {
- result2 = parse_comment();
- }
- }
- }
- if (result1 !== null) {
- result2 = parse_RPAREN();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_ctext() {
- var result0;
-
- if (/^[!-']/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[!-']");
- }
- }
- if (result0 === null) {
- if (/^[*-[]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[*-[]");
- }
- }
- if (result0 === null) {
- if (/^[\]-~]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\]-~]");
- }
- }
- if (result0 === null) {
- result0 = parse_UTF8_NONASCII();
- if (result0 === null) {
- result0 = parse_LWS();
- }
- }
- }
- }
- return result0;
- }
-
- function parse_quoted_string() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- result1 = parse_DQUOTE();
- if (result1 !== null) {
- result2 = [];
- result3 = parse_qdtext();
- if (result3 === null) {
- result3 = parse_quoted_pair();
- }
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_qdtext();
- if (result3 === null) {
- result3 = parse_quoted_pair();
- }
- }
- if (result2 !== null) {
- result3 = parse_DQUOTE();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_quoted_string_clean() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SWS();
- if (result0 !== null) {
- result1 = parse_DQUOTE();
- if (result1 !== null) {
- result2 = [];
- result3 = parse_qdtext();
- if (result3 === null) {
- result3 = parse_quoted_pair();
- }
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_qdtext();
- if (result3 === null) {
- result3 = parse_quoted_pair();
- }
- }
- if (result2 !== null) {
- result3 = parse_DQUOTE();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos-1, offset+1); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_qdtext() {
- var result0;
-
- result0 = parse_LWS();
- if (result0 === null) {
- if (input.charCodeAt(pos) === 33) {
- result0 = "!";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result0 === null) {
- if (/^[#-[]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[#-[]");
- }
- }
- if (result0 === null) {
- if (/^[\]-~]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[\\]-~]");
- }
- }
- if (result0 === null) {
- result0 = parse_UTF8_NONASCII();
- }
- }
- }
- }
- return result0;
- }
-
- function parse_quoted_pair() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- if (input.charCodeAt(pos) === 92) {
- result0 = "\\";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"\\\\\"");
- }
- }
- if (result0 !== null) {
- if (/^[\0-\t]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[\\0-\\t]");
- }
- }
- if (result1 === null) {
- if (/^[\x0B-\f]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[\\x0B-\\f]");
- }
- }
- if (result1 === null) {
- if (/^[\x0E-]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[\\x0E-]");
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_SIP_URI_noparams() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_uri_scheme();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_userinfo();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_hostport();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- try {
- data.uri = new JsSIP.URI(data.scheme, data.user, data.host, data.port);
- delete data.scheme;
- delete data.user;
- delete data.host;
- delete data.host_type;
- delete data.port;
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_SIP_URI() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_uri_scheme();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_userinfo();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_hostport();
- if (result3 !== null) {
- result4 = parse_uri_parameters();
- if (result4 !== null) {
- result5 = parse_headers();
- result5 = result5 !== null ? result5 : "";
- if (result5 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var header;
- try {
- data.uri = new JsSIP.URI(data.scheme, data.user, data.host, data.port, data.uri_params, data.uri_headers);
- delete data.scheme;
- delete data.user;
- delete data.host;
- delete data.host_type;
- delete data.port;
- delete data.uri_params;
-
- if (startRule === 'SIP_URI') { data = data.uri;}
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_uri_scheme() {
- var result0;
- var pos0;
-
- if (input.substr(pos, 3).toLowerCase() === "sip") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"sip\"");
- }
- }
- if (result0 === null) {
- pos0 = pos;
- if (input.substr(pos, 4).toLowerCase() === "sips") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"sips\"");
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.scheme = uri_scheme.toLowerCase(); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- }
- return result0;
- }
-
- function parse_userinfo() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_user();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_password();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 64) {
- result2 = "@";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.user = window.decodeURIComponent(input.substring(pos-1, offset));})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_user() {
- var result0, result1;
-
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_user_unreserved();
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_user_unreserved();
- }
- }
- }
- } else {
- result0 = null;
- }
- return result0;
- }
-
- function parse_user_unreserved() {
- var result0;
-
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 59) {
- result0 = ";";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_password() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result0 = [];
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 38) {
- result1 = "&";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 36) {
- result1 = "$";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 38) {
- result1 = "&";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 36) {
- result1 = "$";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.password = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_hostport() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_host();
- if (result0 !== null) {
- pos1 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_port();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos1;
- }
- } else {
- result1 = null;
- pos = pos1;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_host() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_IPv4address();
- if (result0 === null) {
- result0 = parse_IPv6reference();
- if (result0 === null) {
- result0 = parse_hostname();
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host = input.substring(pos, offset).toLowerCase();
- return data.host; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_hostname() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = [];
- pos2 = pos;
- result1 = parse_domainlabel();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- while (result1 !== null) {
- result0.push(result1);
- pos2 = pos;
- result1 = parse_domainlabel();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- }
- if (result0 !== null) {
- result1 = parse_toplabel();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host_type = 'domain';
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_domainlabel() {
- var result0, result1;
-
- if (/^[a-zA-Z0-9_\-]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[a-zA-Z0-9_\\-]");
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- if (/^[a-zA-Z0-9_\-]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[a-zA-Z0-9_\\-]");
- }
- }
- }
- } else {
- result0 = null;
- }
- return result0;
- }
-
- function parse_toplabel() {
- var result0, result1;
-
- if (/^[a-zA-Z0-9_\-]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[a-zA-Z0-9_\\-]");
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- if (/^[a-zA-Z0-9_\-]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[a-zA-Z0-9_\\-]");
- }
- }
- }
- } else {
- result0 = null;
- }
- return result0;
- }
-
- function parse_IPv6reference() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.charCodeAt(pos) === 91) {
- result0 = "[";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_IPv6address();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 93) {
- result2 = "]";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host_type = 'IPv6';
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_IPv6address() {
- var result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11, result12;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result7 = ":";
- pos++;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result7 !== null) {
- result8 = parse_h16();
- if (result8 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result9 = ":";
- pos++;
- } else {
- result9 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result9 !== null) {
- result10 = parse_h16();
- if (result10 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result11 = ":";
- pos++;
- } else {
- result11 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result11 !== null) {
- result12 = parse_ls32();
- if (result12 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11, result12];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result8 = ":";
- pos++;
- } else {
- result8 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result8 !== null) {
- result9 = parse_h16();
- if (result9 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result10 = ":";
- pos++;
- } else {
- result10 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result10 !== null) {
- result11 = parse_ls32();
- if (result11 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result8 = ":";
- pos++;
- } else {
- result8 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result8 !== null) {
- result9 = parse_ls32();
- if (result9 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_ls32();
- if (result7 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_ls32();
- if (result5 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_ls32();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_ls32();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- if (input.substr(pos, 2) === "::") {
- result0 = "::";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_h16();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- if (input.substr(pos, 2) === "::") {
- result1 = "::";
- pos += 2;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result7 = ":";
- pos++;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result7 !== null) {
- result8 = parse_h16();
- if (result8 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result9 = ":";
- pos++;
- } else {
- result9 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result9 !== null) {
- result10 = parse_ls32();
- if (result10 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- if (input.substr(pos, 2) === "::") {
- result2 = "::";
- pos += 2;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result8 = ":";
- pos++;
- } else {
- result8 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result8 !== null) {
- result9 = parse_ls32();
- if (result9 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- if (input.substr(pos, 2) === "::") {
- result3 = "::";
- pos += 2;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result7 = ":";
- pos++;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result7 !== null) {
- result8 = parse_ls32();
- if (result8 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos2;
- }
- } else {
- result3 = null;
- pos = pos2;
- }
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- if (input.substr(pos, 2) === "::") {
- result4 = "::";
- pos += 2;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_ls32();
- if (result7 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos2;
- }
- } else {
- result3 = null;
- pos = pos2;
- }
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos2;
- }
- } else {
- result4 = null;
- pos = pos2;
- }
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- if (input.substr(pos, 2) === "::") {
- result5 = "::";
- pos += 2;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_ls32();
- if (result6 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos2;
- }
- } else {
- result3 = null;
- pos = pos2;
- }
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos2;
- }
- } else {
- result4 = null;
- pos = pos2;
- }
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- result5 = result5 !== null ? result5 : "";
- if (result5 !== null) {
- if (input.substr(pos, 2) === "::") {
- result6 = "::";
- pos += 2;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result2 = ":";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_h16();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result3 = ":";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_h16();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos2;
- }
- } else {
- result3 = null;
- pos = pos2;
- }
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result4 = ":";
- pos++;
- } else {
- result4 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result4 !== null) {
- result5 = parse_h16();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos2;
- }
- } else {
- result4 = null;
- pos = pos2;
- }
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result5 = ":";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_h16();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- result5 = result5 !== null ? result5 : "";
- if (result5 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 58) {
- result6 = ":";
- pos++;
- } else {
- result6 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result6 !== null) {
- result7 = parse_h16();
- if (result7 !== null) {
- result6 = [result6, result7];
- } else {
- result6 = null;
- pos = pos2;
- }
- } else {
- result6 = null;
- pos = pos2;
- }
- result6 = result6 !== null ? result6 : "";
- if (result6 !== null) {
- if (input.substr(pos, 2) === "::") {
- result7 = "::";
- pos += 2;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\"::\"");
- }
- }
- if (result7 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host_type = 'IPv6';
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_h16() {
- var result0, result1, result2, result3;
- var pos0;
-
- pos0 = pos;
- result0 = parse_HEXDIG();
- if (result0 !== null) {
- result1 = parse_HEXDIG();
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result2 = parse_HEXDIG();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_HEXDIG();
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_ls32() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_h16();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_h16();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- result0 = parse_IPv4address();
- }
- return result0;
- }
-
- function parse_IPv4address() {
- var result0, result1, result2, result3, result4, result5, result6;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_dec_octet();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_dec_octet();
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result3 = ".";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_dec_octet();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result5 = ".";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_dec_octet();
- if (result6 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host_type = 'IPv4';
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_dec_octet() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 2) === "25") {
- result0 = "25";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"25\"");
- }
- }
- if (result0 !== null) {
- if (/^[0-5]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[0-5]");
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- if (input.charCodeAt(pos) === 50) {
- result0 = "2";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"2\"");
- }
- }
- if (result0 !== null) {
- if (/^[0-4]/.test(input.charAt(pos))) {
- result1 = input.charAt(pos);
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("[0-4]");
- }
- }
- if (result1 !== null) {
- result2 = parse_DIGIT();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- if (input.charCodeAt(pos) === 49) {
- result0 = "1";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"1\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result2 = parse_DIGIT();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- if (/^[1-9]/.test(input.charAt(pos))) {
- result0 = input.charAt(pos);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("[1-9]");
- }
- }
- if (result0 !== null) {
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- result0 = parse_DIGIT();
- }
- }
- }
- }
- return result0;
- }
-
- function parse_port() {
- var result0, result1, result2, result3, result4;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_DIGIT();
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result1 = parse_DIGIT();
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result2 = parse_DIGIT();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_DIGIT();
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- result4 = parse_DIGIT();
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, port) {
- port = parseInt(port.join(''));
- data.port = port;
- return port; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_uri_parameters() {
- var result0, result1, result2;
- var pos0;
-
- result0 = [];
- pos0 = pos;
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_uri_parameter();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos0;
- }
- } else {
- result1 = null;
- pos = pos0;
- }
- while (result1 !== null) {
- result0.push(result1);
- pos0 = pos;
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_uri_parameter();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos0;
- }
- } else {
- result1 = null;
- pos = pos0;
- }
- }
- return result0;
- }
-
- function parse_uri_parameter() {
- var result0;
-
- result0 = parse_transport_param();
- if (result0 === null) {
- result0 = parse_user_param();
- if (result0 === null) {
- result0 = parse_method_param();
- if (result0 === null) {
- result0 = parse_ttl_param();
- if (result0 === null) {
- result0 = parse_maddr_param();
- if (result0 === null) {
- result0 = parse_lr_param();
- if (result0 === null) {
- result0 = parse_other_param();
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_transport_param() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 10).toLowerCase() === "transport=") {
- result0 = input.substr(pos, 10);
- pos += 10;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"transport=\"");
- }
- }
- if (result0 !== null) {
- if (input.substr(pos, 3).toLowerCase() === "udp") {
- result1 = input.substr(pos, 3);
- pos += 3;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"udp\"");
- }
- }
- if (result1 === null) {
- if (input.substr(pos, 3).toLowerCase() === "tcp") {
- result1 = input.substr(pos, 3);
- pos += 3;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"tcp\"");
- }
- }
- if (result1 === null) {
- if (input.substr(pos, 4).toLowerCase() === "sctp") {
- result1 = input.substr(pos, 4);
- pos += 4;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"sctp\"");
- }
- }
- if (result1 === null) {
- if (input.substr(pos, 3).toLowerCase() === "tls") {
- result1 = input.substr(pos, 3);
- pos += 3;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"tls\"");
- }
- }
- if (result1 === null) {
- result1 = parse_token();
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, transport) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['transport'] = transport.toLowerCase(); })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_user_param() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 5).toLowerCase() === "user=") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"user=\"");
- }
- }
- if (result0 !== null) {
- if (input.substr(pos, 5).toLowerCase() === "phone") {
- result1 = input.substr(pos, 5);
- pos += 5;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"phone\"");
- }
- }
- if (result1 === null) {
- if (input.substr(pos, 2).toLowerCase() === "ip") {
- result1 = input.substr(pos, 2);
- pos += 2;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"ip\"");
- }
- }
- if (result1 === null) {
- result1 = parse_token();
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, user) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['user'] = user.toLowerCase(); })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_method_param() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 7).toLowerCase() === "method=") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"method=\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_Method();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, method) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['method'] = method; })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_ttl_param() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 4).toLowerCase() === "ttl=") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"ttl=\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_ttl();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, ttl) {
- if(!data.params) data.params={};
- data.params['ttl'] = ttl; })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_maddr_param() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 6).toLowerCase() === "maddr=") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"maddr=\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_host();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, maddr) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['maddr'] = maddr; })(pos0, result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_lr_param() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 2).toLowerCase() === "lr") {
- result0 = input.substr(pos, 2);
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"lr\"");
- }
- }
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- if(!data.uri_params) data.uri_params={};
- data.uri_params['lr'] = undefined; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_other_param() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_pname();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_pvalue();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, param, value) {
- if(!data.uri_params) data.uri_params = {};
- if (typeof value === 'undefined'){
- value = undefined;
- }
- else {
- value = value[1];
- }
- data.uri_params[param.toLowerCase()] = value && value.toLowerCase();})(pos0, result0[0], result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_pname() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result1 = parse_paramchar();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_paramchar();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, pname) {return pname.join(''); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_pvalue() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result1 = parse_paramchar();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_paramchar();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, pvalue) {return pvalue.join(''); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_paramchar() {
- var result0;
-
- result0 = parse_param_unreserved();
- if (result0 === null) {
- result0 = parse_unreserved();
- if (result0 === null) {
- result0 = parse_escaped();
- }
- }
- return result0;
- }
-
- function parse_param_unreserved() {
- var result0;
-
- if (input.charCodeAt(pos) === 91) {
- result0 = "[";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 93) {
- result0 = "]";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_headers() {
- var result0, result1, result2, result3, result4;
- var pos0, pos1;
-
- pos0 = pos;
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_header();
- if (result1 !== null) {
- result2 = [];
- pos1 = pos;
- if (input.charCodeAt(pos) === 38) {
- result3 = "&";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_header();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos1;
- }
- } else {
- result3 = null;
- pos = pos1;
- }
- while (result3 !== null) {
- result2.push(result3);
- pos1 = pos;
- if (input.charCodeAt(pos) === 38) {
- result3 = "&";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_header();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos1;
- }
- } else {
- result3 = null;
- pos = pos1;
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_header() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_hname();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_hvalue();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, hname, hvalue) {
- hname = hname.join('').toLowerCase();
- hvalue = hvalue.join('');
- if(!data.uri_headers) data.uri_headers = {};
- if (!data.uri_headers[hname]) {
- data.uri_headers[hname] = [hvalue];
- } else {
- data.uri_headers[hname].push(hvalue);
- }})(pos0, result0[0], result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_hname() {
- var result0, result1;
-
- result1 = parse_hnv_unreserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_hnv_unreserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- }
- }
- }
- } else {
- result0 = null;
- }
- return result0;
- }
-
- function parse_hvalue() {
- var result0, result1;
-
- result0 = [];
- result1 = parse_hnv_unreserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- }
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_hnv_unreserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- }
- }
- }
- return result0;
- }
-
- function parse_hnv_unreserved() {
- var result0;
-
- if (input.charCodeAt(pos) === 91) {
- result0 = "[";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"[\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 93) {
- result0 = "]";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"]\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_Request_Response() {
- var result0;
-
- result0 = parse_Status_Line();
- if (result0 === null) {
- result0 = parse_Request_Line();
- }
- return result0;
- }
-
- function parse_Request_Line() {
- var result0, result1, result2, result3, result4;
- var pos0;
-
- pos0 = pos;
- result0 = parse_Method();
- if (result0 !== null) {
- result1 = parse_SP();
- if (result1 !== null) {
- result2 = parse_Request_URI();
- if (result2 !== null) {
- result3 = parse_SP();
- if (result3 !== null) {
- result4 = parse_SIP_Version();
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Request_URI() {
- var result0;
-
- result0 = parse_SIP_URI();
- if (result0 === null) {
- result0 = parse_absoluteURI();
- }
- return result0;
- }
-
- function parse_absoluteURI() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_scheme();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_hier_part();
- if (result2 === null) {
- result2 = parse_opaque_part();
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_hier_part() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_net_path();
- if (result0 === null) {
- result0 = parse_abs_path();
- }
- if (result0 !== null) {
- pos1 = pos;
- if (input.charCodeAt(pos) === 63) {
- result1 = "?";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_query();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos1;
- }
- } else {
- result1 = null;
- pos = pos1;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_net_path() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 2) === "//") {
- result0 = "//";
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"//\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_authority();
- if (result1 !== null) {
- result2 = parse_abs_path();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_abs_path() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- if (input.charCodeAt(pos) === 47) {
- result0 = "/";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_path_segments();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_opaque_part() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_uric_no_slash();
- if (result0 !== null) {
- result1 = [];
- result2 = parse_uric();
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_uric();
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_uric() {
- var result0;
-
- result0 = parse_reserved();
- if (result0 === null) {
- result0 = parse_unreserved();
- if (result0 === null) {
- result0 = parse_escaped();
- }
- }
- return result0;
- }
-
- function parse_uric_no_slash() {
- var result0;
-
- result0 = parse_unreserved();
- if (result0 === null) {
- result0 = parse_escaped();
- if (result0 === null) {
- if (input.charCodeAt(pos) === 59) {
- result0 = ";";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 63) {
- result0 = "?";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"?\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 64) {
- result0 = "@";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_path_segments() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_segment();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- if (input.charCodeAt(pos) === 47) {
- result2 = "/";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_segment();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- if (input.charCodeAt(pos) === 47) {
- result2 = "/";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_segment();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_segment() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = [];
- result1 = parse_pchar();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_pchar();
- }
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- if (input.charCodeAt(pos) === 59) {
- result2 = ";";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- if (input.charCodeAt(pos) === 59) {
- result2 = ";";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_param() {
- var result0, result1;
-
- result0 = [];
- result1 = parse_pchar();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_pchar();
- }
- return result0;
- }
-
- function parse_pchar() {
- var result0;
-
- result0 = parse_unreserved();
- if (result0 === null) {
- result0 = parse_escaped();
- if (result0 === null) {
- if (input.charCodeAt(pos) === 58) {
- result0 = ":";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 64) {
- result0 = "@";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_scheme() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_ALPHA();
- if (result0 !== null) {
- result1 = [];
- result2 = parse_ALPHA();
- if (result2 === null) {
- result2 = parse_DIGIT();
- if (result2 === null) {
- if (input.charCodeAt(pos) === 43) {
- result2 = "+";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 45) {
- result2 = "-";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- }
- }
- }
- }
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_ALPHA();
- if (result2 === null) {
- result2 = parse_DIGIT();
- if (result2 === null) {
- if (input.charCodeAt(pos) === 43) {
- result2 = "+";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 45) {
- result2 = "-";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result2 === null) {
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.scheme= input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_authority() {
- var result0;
-
- result0 = parse_srvr();
- if (result0 === null) {
- result0 = parse_reg_name();
- }
- return result0;
- }
-
- function parse_srvr() {
- var result0, result1;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_userinfo();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 64) {
- result1 = "@";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result1 = parse_hostport();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- result0 = result0 !== null ? result0 : "";
- return result0;
- }
-
- function parse_reg_name() {
- var result0, result1;
-
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 36) {
- result1 = "$";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 64) {
- result1 = "@";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 38) {
- result1 = "&";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- if (input.charCodeAt(pos) === 36) {
- result1 = "$";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 44) {
- result1 = ",";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 59) {
- result1 = ";";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 64) {
- result1 = "@";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 38) {
- result1 = "&";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 61) {
- result1 = "=";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- if (result1 === null) {
- if (input.charCodeAt(pos) === 43) {
- result1 = "+";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- result0 = null;
- }
- return result0;
- }
-
- function parse_query() {
- var result0, result1;
-
- result0 = [];
- result1 = parse_uric();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_uric();
- }
- return result0;
- }
-
- function parse_SIP_Version() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 3).toLowerCase() === "sip") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"SIP\"");
- }
- }
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 47) {
- result1 = "/";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"/\"");
- }
- }
- if (result1 !== null) {
- result3 = parse_DIGIT();
- if (result3 !== null) {
- result2 = [];
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_DIGIT();
- }
- } else {
- result2 = null;
- }
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 46) {
- result3 = ".";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result3 !== null) {
- result5 = parse_DIGIT();
- if (result5 !== null) {
- result4 = [];
- while (result5 !== null) {
- result4.push(result5);
- result5 = parse_DIGIT();
- }
- } else {
- result4 = null;
- }
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.sip_version = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_INVITEm() {
- var result0;
-
- if (input.substr(pos, 6) === "INVITE") {
- result0 = "INVITE";
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"INVITE\"");
- }
- }
- return result0;
- }
-
- function parse_ACKm() {
- var result0;
-
- if (input.substr(pos, 3) === "ACK") {
- result0 = "ACK";
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"ACK\"");
- }
- }
- return result0;
- }
-
- function parse_OPTIONSm() {
- var result0;
-
- if (input.substr(pos, 7) === "OPTIONS") {
- result0 = "OPTIONS";
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"OPTIONS\"");
- }
- }
- return result0;
- }
-
- function parse_BYEm() {
- var result0;
-
- if (input.substr(pos, 3) === "BYE") {
- result0 = "BYE";
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"BYE\"");
- }
- }
- return result0;
- }
-
- function parse_CANCELm() {
- var result0;
-
- if (input.substr(pos, 6) === "CANCEL") {
- result0 = "CANCEL";
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"CANCEL\"");
- }
- }
- return result0;
- }
-
- function parse_REGISTERm() {
- var result0;
-
- if (input.substr(pos, 8) === "REGISTER") {
- result0 = "REGISTER";
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"REGISTER\"");
- }
- }
- return result0;
- }
-
- function parse_SUBSCRIBEm() {
- var result0;
-
- if (input.substr(pos, 9) === "SUBSCRIBE") {
- result0 = "SUBSCRIBE";
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"SUBSCRIBE\"");
- }
- }
- return result0;
- }
-
- function parse_NOTIFYm() {
- var result0;
-
- if (input.substr(pos, 6) === "NOTIFY") {
- result0 = "NOTIFY";
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"NOTIFY\"");
- }
- }
- return result0;
- }
-
- function parse_Method() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_INVITEm();
- if (result0 === null) {
- result0 = parse_ACKm();
- if (result0 === null) {
- result0 = parse_OPTIONSm();
- if (result0 === null) {
- result0 = parse_BYEm();
- if (result0 === null) {
- result0 = parse_CANCELm();
- if (result0 === null) {
- result0 = parse_REGISTERm();
- if (result0 === null) {
- result0 = parse_SUBSCRIBEm();
- if (result0 === null) {
- result0 = parse_NOTIFYm();
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- }
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.method = input.substring(pos, offset);
- return data.method; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Status_Line() {
- var result0, result1, result2, result3, result4;
- var pos0;
-
- pos0 = pos;
- result0 = parse_SIP_Version();
- if (result0 !== null) {
- result1 = parse_SP();
- if (result1 !== null) {
- result2 = parse_Status_Code();
- if (result2 !== null) {
- result3 = parse_SP();
- if (result3 !== null) {
- result4 = parse_Reason_Phrase();
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Status_Code() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_extension_code();
- if (result0 !== null) {
- result0 = (function(offset, status_code) {
- data.status_code = parseInt(status_code.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_extension_code() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_DIGIT();
- if (result0 !== null) {
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result2 = parse_DIGIT();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Reason_Phrase() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result0 = [];
- result1 = parse_reserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_UTF8_NONASCII();
- if (result1 === null) {
- result1 = parse_UTF8_CONT();
- if (result1 === null) {
- result1 = parse_SP();
- if (result1 === null) {
- result1 = parse_HTAB();
- }
- }
- }
- }
- }
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_reserved();
- if (result1 === null) {
- result1 = parse_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_UTF8_NONASCII();
- if (result1 === null) {
- result1 = parse_UTF8_CONT();
- if (result1 === null) {
- result1 = parse_SP();
- if (result1 === null) {
- result1 = parse_HTAB();
- }
- }
- }
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.reason_phrase = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Allow_Events() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_event_type();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_event_type();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_event_type();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Call_ID() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_word();
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 64) {
- result1 = "@";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"@\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_word();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Contact() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- result0 = parse_STAR();
- if (result0 === null) {
- pos1 = pos;
- result0 = parse_contact_param();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_contact_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_contact_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var idx, length;
- length = data.multi_header.length;
- for (idx = 0; idx < length; idx++) {
- if (data.multi_header[idx].parsed === null) {
- data = null;
- break;
- }
- }
- if (data !== null) {
- data = data.multi_header;
- } else {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_contact_param() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SIP_URI_noparams();
- if (result0 === null) {
- result0 = parse_name_addr();
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_contact_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_contact_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var header;
- if(!data.multi_header) data.multi_header = [];
- try {
- header = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
- delete data.uri;
- delete data.display_name;
- delete data.params;
- } catch(e) {
- header = null;
- }
- data.multi_header.push( { 'possition': pos,
- 'offset': offset,
- 'parsed': header
- });})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_name_addr() {
- var result0, result1, result2, result3;
- var pos0;
-
- pos0 = pos;
- result0 = parse_display_name();
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result1 = parse_LAQUOT();
- if (result1 !== null) {
- result2 = parse_SIP_URI();
- if (result2 !== null) {
- result3 = parse_RAQUOT();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_display_name() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_LWS();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_LWS();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 === null) {
- result0 = parse_quoted_string();
- }
- if (result0 !== null) {
- result0 = (function(offset, display_name) {
- display_name = input.substring(pos, offset).trim();
- if (display_name[0] === '\"') {
- display_name = display_name.substring(1, display_name.length-1);
- }
- data.display_name = display_name; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_contact_params() {
- var result0;
-
- result0 = parse_c_p_q();
- if (result0 === null) {
- result0 = parse_c_p_expires();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- }
- return result0;
- }
-
- function parse_c_p_q() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 1).toLowerCase() === "q") {
- result0 = input.substr(pos, 1);
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"q\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_qvalue();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, q) {
- if(!data.params) data.params = {};
- data.params['q'] = q; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_c_p_expires() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 7).toLowerCase() === "expires") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"expires\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_delta_seconds();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, expires) {
- if(!data.params) data.params = {};
- data.params['expires'] = expires; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_delta_seconds() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_DIGIT();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, delta_seconds) {
- return parseInt(delta_seconds.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_qvalue() {
- var result0, result1, result2, result3, result4;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- if (input.charCodeAt(pos) === 48) {
- result0 = "0";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"0\"");
- }
- }
- if (result0 !== null) {
- pos2 = pos;
- if (input.charCodeAt(pos) === 46) {
- result1 = ".";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_DIGIT();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_DIGIT();
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- result4 = parse_DIGIT();
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- result1 = [result1, result2, result3, result4];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return parseFloat(input.substring(pos, offset)); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_generic_param() {
- var result0, result1, result2;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- pos2 = pos;
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_gen_value();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, param, value) {
- if(!data.params) data.params = {};
- if (typeof value === 'undefined'){
- value = undefined;
- }
- else {
- value = value[1];
- }
- data.params[param.toLowerCase()] = value;})(pos0, result0[0], result0[1]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_gen_value() {
- var result0;
-
- result0 = parse_token();
- if (result0 === null) {
- result0 = parse_host();
- if (result0 === null) {
- result0 = parse_quoted_string();
- }
- }
- return result0;
- }
-
- function parse_Content_Disposition() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_disp_type();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_disp_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_disp_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_disp_type() {
- var result0;
-
- if (input.substr(pos, 6).toLowerCase() === "render") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"render\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 7).toLowerCase() === "session") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"session\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 4).toLowerCase() === "icon") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"icon\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 5).toLowerCase() === "alert") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"alert\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- }
- return result0;
- }
-
- function parse_disp_param() {
- var result0;
-
- result0 = parse_handling_param();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- return result0;
- }
-
- function parse_handling_param() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 8).toLowerCase() === "handling") {
- result0 = input.substr(pos, 8);
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"handling\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- if (input.substr(pos, 8).toLowerCase() === "optional") {
- result2 = input.substr(pos, 8);
- pos += 8;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"optional\"");
- }
- }
- if (result2 === null) {
- if (input.substr(pos, 8).toLowerCase() === "required") {
- result2 = input.substr(pos, 8);
- pos += 8;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"required\"");
- }
- }
- if (result2 === null) {
- result2 = parse_token();
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Content_Encoding() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Content_Length() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_DIGIT();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, length) {
- data = parseInt(length.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Content_Type() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_media_type();
- if (result0 !== null) {
- result0 = (function(offset) {
- data = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_media_type() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_m_type();
- if (result0 !== null) {
- result1 = parse_SLASH();
- if (result1 !== null) {
- result2 = parse_m_subtype();
- if (result2 !== null) {
- result3 = [];
- pos1 = pos;
- result4 = parse_SEMI();
- if (result4 !== null) {
- result5 = parse_m_parameter();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- while (result4 !== null) {
- result3.push(result4);
- pos1 = pos;
- result4 = parse_SEMI();
- if (result4 !== null) {
- result5 = parse_m_parameter();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- }
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_m_type() {
- var result0;
-
- result0 = parse_discrete_type();
- if (result0 === null) {
- result0 = parse_composite_type();
- }
- return result0;
- }
-
- function parse_discrete_type() {
- var result0;
-
- if (input.substr(pos, 4).toLowerCase() === "text") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"text\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 5).toLowerCase() === "image") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"image\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 5).toLowerCase() === "audio") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"audio\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 5).toLowerCase() === "video") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"video\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 11).toLowerCase() === "application") {
- result0 = input.substr(pos, 11);
- pos += 11;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"application\"");
- }
- }
- if (result0 === null) {
- result0 = parse_extension_token();
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_composite_type() {
- var result0;
-
- if (input.substr(pos, 7).toLowerCase() === "message") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"message\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 9).toLowerCase() === "multipart") {
- result0 = input.substr(pos, 9);
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"multipart\"");
- }
- }
- if (result0 === null) {
- result0 = parse_extension_token();
- }
- }
- return result0;
- }
-
- function parse_extension_token() {
- var result0;
-
- result0 = parse_token();
- if (result0 === null) {
- result0 = parse_x_token();
- }
- return result0;
- }
-
- function parse_x_token() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 2).toLowerCase() === "x-") {
- result0 = input.substr(pos, 2);
- pos += 2;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"x-\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_token();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_m_subtype() {
- var result0;
-
- result0 = parse_extension_token();
- if (result0 === null) {
- result0 = parse_token();
- }
- return result0;
- }
-
- function parse_m_parameter() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_m_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_m_value() {
- var result0;
-
- result0 = parse_token();
- if (result0 === null) {
- result0 = parse_quoted_string();
- }
- return result0;
- }
-
- function parse_CSeq() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_CSeq_value();
- if (result0 !== null) {
- result1 = parse_LWS();
- if (result1 !== null) {
- result2 = parse_Method();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_CSeq_value() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_DIGIT();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, cseq_value) {
- data.value=parseInt(cseq_value.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Expires() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_delta_seconds();
- if (result0 !== null) {
- result0 = (function(offset, expires) {data = expires; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Event() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_event_type();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, event_type) {
- data.event = event_type.join('').toLowerCase(); })(pos0, result0[0]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_event_type() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_token_nodot();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_token_nodot();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- if (input.charCodeAt(pos) === 46) {
- result2 = ".";
- pos++;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result2 !== null) {
- result3 = parse_token_nodot();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_From() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SIP_URI_noparams();
- if (result0 === null) {
- result0 = parse_name_addr();
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_from_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_from_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var tag = data.tag;
- try {
- data = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
- if (tag) {data.setParam('tag',tag)}
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_from_param() {
- var result0;
-
- result0 = parse_tag_param();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- return result0;
- }
-
- function parse_tag_param() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 3).toLowerCase() === "tag") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"tag\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, tag) {data.tag = tag; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Max_Forwards() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result1 = parse_DIGIT();
- if (result1 !== null) {
- result0 = [];
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_DIGIT();
- }
- } else {
- result0 = null;
- }
- if (result0 !== null) {
- result0 = (function(offset, forwards) {
- data = parseInt(forwards.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Min_Expires() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_delta_seconds();
- if (result0 !== null) {
- result0 = (function(offset, min_expires) {data = min_expires; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Name_Addr_Header() {
- var result0, result1, result2, result3, result4, result5, result6;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = [];
- result1 = parse_display_name();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_display_name();
- }
- if (result0 !== null) {
- result1 = parse_LAQUOT();
- if (result1 !== null) {
- result2 = parse_SIP_URI();
- if (result2 !== null) {
- result3 = parse_RAQUOT();
- if (result3 !== null) {
- result4 = [];
- pos2 = pos;
- result5 = parse_SEMI();
- if (result5 !== null) {
- result6 = parse_generic_param();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- while (result5 !== null) {
- result4.push(result5);
- pos2 = pos;
- result5 = parse_SEMI();
- if (result5 !== null) {
- result6 = parse_generic_param();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- }
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- try {
- data = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Proxy_Authenticate() {
- var result0;
-
- result0 = parse_challenge();
- return result0;
- }
-
- function parse_challenge() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
-
- pos0 = pos;
- if (input.substr(pos, 6).toLowerCase() === "digest") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"Digest\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_LWS();
- if (result1 !== null) {
- result2 = parse_digest_cln();
- if (result2 !== null) {
- result3 = [];
- pos1 = pos;
- result4 = parse_COMMA();
- if (result4 !== null) {
- result5 = parse_digest_cln();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- while (result4 !== null) {
- result3.push(result4);
- pos1 = pos;
- result4 = parse_COMMA();
- if (result4 !== null) {
- result5 = parse_digest_cln();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- }
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- if (result0 === null) {
- result0 = parse_other_challenge();
- }
- return result0;
- }
-
- function parse_other_challenge() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = parse_LWS();
- if (result1 !== null) {
- result2 = parse_auth_param();
- if (result2 !== null) {
- result3 = [];
- pos1 = pos;
- result4 = parse_COMMA();
- if (result4 !== null) {
- result5 = parse_auth_param();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- while (result4 !== null) {
- result3.push(result4);
- pos1 = pos;
- result4 = parse_COMMA();
- if (result4 !== null) {
- result5 = parse_auth_param();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- }
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_auth_param() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 === null) {
- result2 = parse_quoted_string();
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_digest_cln() {
- var result0;
-
- result0 = parse_realm();
- if (result0 === null) {
- result0 = parse_domain();
- if (result0 === null) {
- result0 = parse_nonce();
- if (result0 === null) {
- result0 = parse_opaque();
- if (result0 === null) {
- result0 = parse_stale();
- if (result0 === null) {
- result0 = parse_algorithm();
- if (result0 === null) {
- result0 = parse_qop_options();
- if (result0 === null) {
- result0 = parse_auth_param();
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_realm() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 5).toLowerCase() === "realm") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"realm\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_realm_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_realm_value() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_quoted_string_clean();
- if (result0 !== null) {
- result0 = (function(offset, realm) { data.realm = realm; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_domain() {
- var result0, result1, result2, result3, result4, result5, result6;
- var pos0, pos1;
-
- pos0 = pos;
- if (input.substr(pos, 6).toLowerCase() === "domain") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"domain\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_LDQUOT();
- if (result2 !== null) {
- result3 = parse_URI();
- if (result3 !== null) {
- result4 = [];
- pos1 = pos;
- result6 = parse_SP();
- if (result6 !== null) {
- result5 = [];
- while (result6 !== null) {
- result5.push(result6);
- result6 = parse_SP();
- }
- } else {
- result5 = null;
- }
- if (result5 !== null) {
- result6 = parse_URI();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos1;
- }
- } else {
- result5 = null;
- pos = pos1;
- }
- while (result5 !== null) {
- result4.push(result5);
- pos1 = pos;
- result6 = parse_SP();
- if (result6 !== null) {
- result5 = [];
- while (result6 !== null) {
- result5.push(result6);
- result6 = parse_SP();
- }
- } else {
- result5 = null;
- }
- if (result5 !== null) {
- result6 = parse_URI();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos1;
- }
- } else {
- result5 = null;
- pos = pos1;
- }
- }
- if (result4 !== null) {
- result5 = parse_RDQUOT();
- if (result5 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_URI() {
- var result0;
-
- result0 = parse_absoluteURI();
- if (result0 === null) {
- result0 = parse_abs_path();
- }
- return result0;
- }
-
- function parse_nonce() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 5).toLowerCase() === "nonce") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"nonce\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_nonce_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_nonce_value() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_quoted_string_clean();
- if (result0 !== null) {
- result0 = (function(offset, nonce) { data.nonce=nonce; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_opaque() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 6).toLowerCase() === "opaque") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"opaque\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_quoted_string_clean();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, opaque) { data.opaque=opaque; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_stale() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- if (input.substr(pos, 5).toLowerCase() === "stale") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"stale\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- pos1 = pos;
- if (input.substr(pos, 4).toLowerCase() === "true") {
- result2 = input.substr(pos, 4);
- pos += 4;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"true\"");
- }
- }
- if (result2 !== null) {
- result2 = (function(offset) { data.stale=true; })(pos1);
- }
- if (result2 === null) {
- pos = pos1;
- }
- if (result2 === null) {
- pos1 = pos;
- if (input.substr(pos, 5).toLowerCase() === "false") {
- result2 = input.substr(pos, 5);
- pos += 5;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"false\"");
- }
- }
- if (result2 !== null) {
- result2 = (function(offset) { data.stale=false; })(pos1);
- }
- if (result2 === null) {
- pos = pos1;
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_algorithm() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 9).toLowerCase() === "algorithm") {
- result0 = input.substr(pos, 9);
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"algorithm\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- if (input.substr(pos, 3).toLowerCase() === "md5") {
- result2 = input.substr(pos, 3);
- pos += 3;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"MD5\"");
- }
- }
- if (result2 === null) {
- if (input.substr(pos, 8).toLowerCase() === "md5-sess") {
- result2 = input.substr(pos, 8);
- pos += 8;
- } else {
- result2 = null;
- if (reportFailures === 0) {
- matchFailed("\"MD5-sess\"");
- }
- }
- if (result2 === null) {
- result2 = parse_token();
- }
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, algorithm) {
- data.algorithm=algorithm.toUpperCase(); })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_qop_options() {
- var result0, result1, result2, result3, result4, result5, result6;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- if (input.substr(pos, 3).toLowerCase() === "qop") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"qop\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_LDQUOT();
- if (result2 !== null) {
- pos1 = pos;
- result3 = parse_qop_value();
- if (result3 !== null) {
- result4 = [];
- pos2 = pos;
- if (input.charCodeAt(pos) === 44) {
- result5 = ",";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_qop_value();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- while (result5 !== null) {
- result4.push(result5);
- pos2 = pos;
- if (input.charCodeAt(pos) === 44) {
- result5 = ",";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_qop_value();
- if (result6 !== null) {
- result5 = [result5, result6];
- } else {
- result5 = null;
- pos = pos2;
- }
- } else {
- result5 = null;
- pos = pos2;
- }
- }
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos1;
- }
- } else {
- result3 = null;
- pos = pos1;
- }
- if (result3 !== null) {
- result4 = parse_RDQUOT();
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_qop_value() {
- var result0;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 8).toLowerCase() === "auth-int") {
- result0 = input.substr(pos, 8);
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"auth-int\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 4).toLowerCase() === "auth") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"auth\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- if (result0 !== null) {
- result0 = (function(offset, qop_value) {
- data.qop || (data.qop=[]);
- data.qop.push(qop_value.toLowerCase()); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Proxy_Require() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Record_Route() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_rec_route();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_rec_route();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_rec_route();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var idx, length;
- length = data.multi_header.length;
- for (idx = 0; idx < length; idx++) {
- if (data.multi_header[idx].parsed === null) {
- data = null;
- break;
- }
- }
- if (data !== null) {
- data = data.multi_header;
- } else {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_rec_route() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_name_addr();
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var header;
- if(!data.multi_header) data.multi_header = [];
- try {
- header = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
- delete data.uri;
- delete data.display_name;
- delete data.params;
- } catch(e) {
- header = null;
- }
- data.multi_header.push( { 'possition': pos,
- 'offset': offset,
- 'parsed': header
- });})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Require() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Route() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_route_param();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_route_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_route_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_route_param() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_name_addr();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_generic_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_Subscription_State() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_substate_value();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_subexp_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_subexp_params();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_substate_value() {
- var result0;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 6).toLowerCase() === "active") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"active\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 7).toLowerCase() === "pending") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"pending\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 10).toLowerCase() === "terminated") {
- result0 = input.substr(pos, 10);
- pos += 10;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"terminated\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.state = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_subexp_params() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 6).toLowerCase() === "reason") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"reason\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_event_reason_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, reason) {
- if (typeof reason !== 'undefined') data.reason = reason; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 7).toLowerCase() === "expires") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"expires\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_delta_seconds();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, expires) {
- if (typeof expires !== 'undefined') data.expires = expires; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- if (result0 === null) {
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 11).toLowerCase() === "retry_after") {
- result0 = input.substr(pos, 11);
- pos += 11;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"retry_after\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_delta_seconds();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, retry_after) {
- if (typeof retry_after !== 'undefined') data.retry_after = retry_after; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- }
- }
- return result0;
- }
-
- function parse_event_reason_value() {
- var result0;
-
- if (input.substr(pos, 11).toLowerCase() === "deactivated") {
- result0 = input.substr(pos, 11);
- pos += 11;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"deactivated\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 9).toLowerCase() === "probation") {
- result0 = input.substr(pos, 9);
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"probation\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 8).toLowerCase() === "rejected") {
- result0 = input.substr(pos, 8);
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"rejected\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 7).toLowerCase() === "timeout") {
- result0 = input.substr(pos, 7);
- pos += 7;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"timeout\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 6).toLowerCase() === "giveup") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"giveup\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 10).toLowerCase() === "noresource") {
- result0 = input.substr(pos, 10);
- pos += 10;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"noresource\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 9).toLowerCase() === "invariant") {
- result0 = input.substr(pos, 9);
- pos += 9;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"invariant\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_Subject() {
- var result0;
-
- result0 = parse_TEXT_UTF8_TRIM();
- result0 = result0 !== null ? result0 : "";
- return result0;
- }
-
- function parse_Supported() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_token();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- result0 = result0 !== null ? result0 : "";
- return result0;
- }
-
- function parse_To() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_SIP_URI_noparams();
- if (result0 === null) {
- result0 = parse_name_addr();
- }
- if (result0 !== null) {
- result1 = [];
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_to_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos2 = pos;
- result2 = parse_SEMI();
- if (result2 !== null) {
- result3 = parse_to_param();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos2;
- }
- } else {
- result2 = null;
- pos = pos2;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- var tag = data.tag;
- try {
- data = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
- if (tag) {data.setParam('tag',tag)}
- } catch(e) {
- data = -1;
- }})(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_to_param() {
- var result0;
-
- result0 = parse_tag_param();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- return result0;
- }
-
- function parse_Via() {
- var result0, result1, result2, result3;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_via_parm();
- if (result0 !== null) {
- result1 = [];
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_via_parm();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- while (result2 !== null) {
- result1.push(result2);
- pos1 = pos;
- result2 = parse_COMMA();
- if (result2 !== null) {
- result3 = parse_via_parm();
- if (result3 !== null) {
- result2 = [result2, result3];
- } else {
- result2 = null;
- pos = pos1;
- }
- } else {
- result2 = null;
- pos = pos1;
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_via_parm() {
- var result0, result1, result2, result3, result4, result5;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_sent_protocol();
- if (result0 !== null) {
- result1 = parse_LWS();
- if (result1 !== null) {
- result2 = parse_sent_by();
- if (result2 !== null) {
- result3 = [];
- pos1 = pos;
- result4 = parse_SEMI();
- if (result4 !== null) {
- result5 = parse_via_params();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- while (result4 !== null) {
- result3.push(result4);
- pos1 = pos;
- result4 = parse_SEMI();
- if (result4 !== null) {
- result5 = parse_via_params();
- if (result5 !== null) {
- result4 = [result4, result5];
- } else {
- result4 = null;
- pos = pos1;
- }
- } else {
- result4 = null;
- pos = pos1;
- }
- }
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_via_params() {
- var result0;
-
- result0 = parse_via_ttl();
- if (result0 === null) {
- result0 = parse_via_maddr();
- if (result0 === null) {
- result0 = parse_via_received();
- if (result0 === null) {
- result0 = parse_via_branch();
- if (result0 === null) {
- result0 = parse_response_port();
- if (result0 === null) {
- result0 = parse_generic_param();
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_via_ttl() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 3).toLowerCase() === "ttl") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"ttl\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_ttl();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_ttl_value) {
- data.ttl = via_ttl_value; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_via_maddr() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 5).toLowerCase() === "maddr") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"maddr\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_host();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_maddr) {
- data.maddr = via_maddr; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_via_received() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 8).toLowerCase() === "received") {
- result0 = input.substr(pos, 8);
- pos += 8;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"received\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_IPv4address();
- if (result2 === null) {
- result2 = parse_IPv6address();
- }
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_received) {
- data.received = via_received; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_via_branch() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 6).toLowerCase() === "branch") {
- result0 = input.substr(pos, 6);
- pos += 6;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"branch\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_branch) {
- data.branch = via_branch; })(pos0, result0[2]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_response_port() {
- var result0, result1, result2, result3;
- var pos0, pos1, pos2;
-
- pos0 = pos;
- pos1 = pos;
- if (input.substr(pos, 5).toLowerCase() === "rport") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"rport\"");
- }
- }
- if (result0 !== null) {
- pos2 = pos;
- result1 = parse_EQUAL();
- if (result1 !== null) {
- result2 = [];
- result3 = parse_DIGIT();
- while (result3 !== null) {
- result2.push(result3);
- result3 = parse_DIGIT();
- }
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos2;
- }
- } else {
- result1 = null;
- pos = pos2;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- if(typeof response_port !== 'undefined')
- data.rport = response_port.join(''); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_sent_protocol() {
- var result0, result1, result2, result3, result4;
- var pos0;
-
- pos0 = pos;
- result0 = parse_protocol_name();
- if (result0 !== null) {
- result1 = parse_SLASH();
- if (result1 !== null) {
- result2 = parse_token();
- if (result2 !== null) {
- result3 = parse_SLASH();
- if (result3 !== null) {
- result4 = parse_transport();
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_protocol_name() {
- var result0;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 3).toLowerCase() === "sip") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"SIP\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- if (result0 !== null) {
- result0 = (function(offset, via_protocol) {
- data.protocol = via_protocol; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_transport() {
- var result0;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 3).toLowerCase() === "udp") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"UDP\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 3).toLowerCase() === "tcp") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"TCP\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 3).toLowerCase() === "tls") {
- result0 = input.substr(pos, 3);
- pos += 3;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"TLS\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 4).toLowerCase() === "sctp") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"SCTP\"");
- }
- }
- if (result0 === null) {
- result0 = parse_token();
- }
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset, via_transport) {
- data.transport = via_transport; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_sent_by() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_via_host();
- if (result0 !== null) {
- pos1 = pos;
- result1 = parse_COLON();
- if (result1 !== null) {
- result2 = parse_via_port();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos1;
- }
- } else {
- result1 = null;
- pos = pos1;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_via_host() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_IPv4address();
- if (result0 === null) {
- result0 = parse_IPv6reference();
- if (result0 === null) {
- result0 = parse_hostname();
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.host = input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_via_port() {
- var result0, result1, result2, result3, result4;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_DIGIT();
- result0 = result0 !== null ? result0 : "";
- if (result0 !== null) {
- result1 = parse_DIGIT();
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result2 = parse_DIGIT();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result3 = parse_DIGIT();
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- result4 = parse_DIGIT();
- result4 = result4 !== null ? result4 : "";
- if (result4 !== null) {
- result0 = [result0, result1, result2, result3, result4];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, via_sent_by_port) {
- data.port = parseInt(via_sent_by_port.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_ttl() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_DIGIT();
- if (result0 !== null) {
- result1 = parse_DIGIT();
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result2 = parse_DIGIT();
- result2 = result2 !== null ? result2 : "";
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, ttl) {
- return parseInt(ttl.join('')); })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_WWW_Authenticate() {
- var result0;
-
- result0 = parse_challenge();
- return result0;
- }
-
- function parse_extension_header() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_token();
- if (result0 !== null) {
- result1 = parse_HCOLON();
- if (result1 !== null) {
- result2 = parse_header_value();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_header_value() {
- var result0, result1;
-
- result0 = [];
- result1 = parse_TEXT_UTF8char();
- if (result1 === null) {
- result1 = parse_UTF8_CONT();
- if (result1 === null) {
- result1 = parse_LWS();
- }
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_TEXT_UTF8char();
- if (result1 === null) {
- result1 = parse_UTF8_CONT();
- if (result1 === null) {
- result1 = parse_LWS();
- }
- }
- }
- return result0;
- }
-
- function parse_message_body() {
- var result0, result1;
-
- result0 = [];
- result1 = parse_OCTET();
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_OCTET();
- }
- return result0;
- }
-
- function parse_stun_URI() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_stun_scheme();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_stun_host_port();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_stun_scheme() {
- var result0;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 5).toLowerCase() === "stuns") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"stuns\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 4).toLowerCase() === "stun") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"stun\"");
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset, scheme) {
- data.scheme = scheme; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_stun_host_port() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_stun_host();
- if (result0 !== null) {
- pos1 = pos;
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_port();
- if (result2 !== null) {
- result1 = [result1, result2];
- } else {
- result1 = null;
- pos = pos1;
- }
- } else {
- result1 = null;
- pos = pos1;
- }
- result1 = result1 !== null ? result1 : "";
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_stun_host() {
- var result0;
- var pos0;
-
- pos0 = pos;
- result0 = parse_IPv4address();
- if (result0 === null) {
- result0 = parse_IPv6reference();
- if (result0 === null) {
- result0 = parse_reg_name();
- }
- }
- if (result0 !== null) {
- result0 = (function(offset, host) {
- data.host = host; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_reg_name() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result0 = [];
- result1 = parse_stun_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_sub_delims();
- }
- }
- while (result1 !== null) {
- result0.push(result1);
- result1 = parse_stun_unreserved();
- if (result1 === null) {
- result1 = parse_escaped();
- if (result1 === null) {
- result1 = parse_sub_delims();
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- return input.substring(pos, offset); })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_stun_unreserved() {
- var result0;
-
- result0 = parse_ALPHA();
- if (result0 === null) {
- result0 = parse_DIGIT();
- if (result0 === null) {
- if (input.charCodeAt(pos) === 45) {
- result0 = "-";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 46) {
- result0 = ".";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\".\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 95) {
- result0 = "_";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"_\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 126) {
- result0 = "~";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"~\"");
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_sub_delims() {
- var result0;
-
- if (input.charCodeAt(pos) === 33) {
- result0 = "!";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"!\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 36) {
- result0 = "$";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"$\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 38) {
- result0 = "&";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"&\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 39) {
- result0 = "'";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"'\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 40) {
- result0 = "(";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"(\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 41) {
- result0 = ")";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\")\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 42) {
- result0 = "*";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"*\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 43) {
- result0 = "+";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"+\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 44) {
- result0 = ",";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\",\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 59) {
- result0 = ";";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\";\"");
- }
- }
- if (result0 === null) {
- if (input.charCodeAt(pos) === 61) {
- result0 = "=";
- pos++;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"=\"");
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return result0;
- }
-
- function parse_turn_URI() {
- var result0, result1, result2, result3, result4;
- var pos0, pos1;
-
- pos0 = pos;
- result0 = parse_turn_scheme();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 58) {
- result1 = ":";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\":\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_stun_host_port();
- if (result2 !== null) {
- pos1 = pos;
- if (input.substr(pos, 11) === "?transport=") {
- result3 = "?transport=";
- pos += 11;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\"?transport=\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_transport();
- if (result4 !== null) {
- result3 = [result3, result4];
- } else {
- result3 = null;
- pos = pos1;
- }
- } else {
- result3 = null;
- pos = pos1;
- }
- result3 = result3 !== null ? result3 : "";
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_turn_scheme() {
- var result0;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 5).toLowerCase() === "turns") {
- result0 = input.substr(pos, 5);
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"turns\"");
- }
- }
- if (result0 === null) {
- if (input.substr(pos, 4).toLowerCase() === "turn") {
- result0 = input.substr(pos, 4);
- pos += 4;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"turn\"");
- }
- }
- }
- if (result0 !== null) {
- result0 = (function(offset, scheme) {
- data.scheme = scheme; })(pos0, result0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_turn_transport() {
- var result0, result1, result2;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_transport();
- if (result0 !== null) {
- if (input.substr(pos, 3).toLowerCase() === "udp") {
- result1 = input.substr(pos, 3);
- pos += 3;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"udp\"");
- }
- }
- if (result1 === null) {
- if (input.substr(pos, 3).toLowerCase() === "tcp") {
- result1 = input.substr(pos, 3);
- pos += 3;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"tcp\"");
- }
- }
- if (result1 === null) {
- result1 = [];
- result2 = parse_unreserved();
- while (result2 !== null) {
- result1.push(result2);
- result2 = parse_unreserved();
- }
- }
- }
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset) {
- data.transport = transport; })(pos0);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_uuid_URI() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- if (input.substr(pos, 5) === "uuid:") {
- result0 = "uuid:";
- pos += 5;
- } else {
- result0 = null;
- if (reportFailures === 0) {
- matchFailed("\"uuid:\"");
- }
- }
- if (result0 !== null) {
- result1 = parse_uuid();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_uuid() {
- var result0, result1, result2, result3, result4, result5, result6, result7, result8;
- var pos0, pos1;
-
- pos0 = pos;
- pos1 = pos;
- result0 = parse_hex8();
- if (result0 !== null) {
- if (input.charCodeAt(pos) === 45) {
- result1 = "-";
- pos++;
- } else {
- result1 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result1 !== null) {
- result2 = parse_hex4();
- if (result2 !== null) {
- if (input.charCodeAt(pos) === 45) {
- result3 = "-";
- pos++;
- } else {
- result3 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result3 !== null) {
- result4 = parse_hex4();
- if (result4 !== null) {
- if (input.charCodeAt(pos) === 45) {
- result5 = "-";
- pos++;
- } else {
- result5 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result5 !== null) {
- result6 = parse_hex4();
- if (result6 !== null) {
- if (input.charCodeAt(pos) === 45) {
- result7 = "-";
- pos++;
- } else {
- result7 = null;
- if (reportFailures === 0) {
- matchFailed("\"-\"");
- }
- }
- if (result7 !== null) {
- result8 = parse_hex12();
- if (result8 !== null) {
- result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8];
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- } else {
- result0 = null;
- pos = pos1;
- }
- if (result0 !== null) {
- result0 = (function(offset, uuid) {
- data = input.substring(pos+5, offset); })(pos0, result0[0]);
- }
- if (result0 === null) {
- pos = pos0;
- }
- return result0;
- }
-
- function parse_hex4() {
- var result0, result1, result2, result3;
- var pos0;
-
- pos0 = pos;
- result0 = parse_HEXDIG();
- if (result0 !== null) {
- result1 = parse_HEXDIG();
- if (result1 !== null) {
- result2 = parse_HEXDIG();
- if (result2 !== null) {
- result3 = parse_HEXDIG();
- if (result3 !== null) {
- result0 = [result0, result1, result2, result3];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_hex8() {
- var result0, result1;
- var pos0;
-
- pos0 = pos;
- result0 = parse_hex4();
- if (result0 !== null) {
- result1 = parse_hex4();
- if (result1 !== null) {
- result0 = [result0, result1];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
- function parse_hex12() {
- var result0, result1, result2;
- var pos0;
-
- pos0 = pos;
- result0 = parse_hex4();
- if (result0 !== null) {
- result1 = parse_hex4();
- if (result1 !== null) {
- result2 = parse_hex4();
- if (result2 !== null) {
- result0 = [result0, result1, result2];
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- } else {
- result0 = null;
- pos = pos0;
- }
- return result0;
- }
-
-
- function cleanupExpected(expected) {
- expected.sort();
-
- var lastExpected = null;
- var cleanExpected = [];
- for (var i = 0; i < expected.length; i++) {
- if (expected[i] !== lastExpected) {
- cleanExpected.push(expected[i]);
- lastExpected = expected[i];
- }
- }
- return cleanExpected;
- }
-
- function computeErrorPosition() {
- /*
- * The first idea was to use |String.split| to break the input up to the
- * error position along newlines and derive the line and column from
- * there. However IE's |split| implementation is so broken that it was
- * enough to prevent it.
- */
-
- var line = 1;
- var column = 1;
- var seenCR = false;
-
- for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) {
- var ch = input.charAt(i);
- if (ch === "\n") {
- if (!seenCR) { line++; }
- column = 1;
- seenCR = false;
- } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
- line++;
- column = 1;
- seenCR = true;
- } else {
- column++;
- seenCR = false;
- }
- }
-
- return { line: line, column: column };
- }
-
- var data = {};
-
- var result = parseFunctions[startRule]();
-
- /*
- * The parser is now in one of the following three states:
- *
- * 1. The parser successfully parsed the whole input.
- *
- * - |result !== null|
- * - |pos === input.length|
- * - |rightmostFailuresExpected| may or may not contain something
- *
- * 2. The parser successfully parsed only a part of the input.
- *
- * - |result !== null|
- * - |pos < input.length|
- * - |rightmostFailuresExpected| may or may not contain something
- *
- * 3. The parser did not successfully parse any part of the input.
- *
- * - |result === null|
- * - |pos === 0|
- * - |rightmostFailuresExpected| contains at least one failure
- *
- * All code following this comment (including called functions) must
- * handle these states.
- */
- if (result === null || pos !== input.length) {
- var offset = Math.max(pos, rightmostFailuresPos);
- var found = offset < input.length ? input.charAt(offset) : null;
- var errorPosition = computeErrorPosition();
-
- new this.SyntaxError(
- cleanupExpected(rightmostFailuresExpected),
- found,
- offset,
- errorPosition.line,
- errorPosition.column
- );
- return -1;
- }
-
- return data;
- },
-
- /* Returns the parser source code. */
- toSource: function() { return this._source; }
- };
-
- /* Thrown when a parser encounters a syntax error. */
-
- result.SyntaxError = function(expected, found, offset, line, column) {
- function buildMessage(expected, found) {
- var expectedHumanized, foundHumanized;
-
- switch (expected.length) {
- case 0:
- expectedHumanized = "end of input";
- break;
- case 1:
- expectedHumanized = expected[0];
- break;
- default:
- expectedHumanized = expected.slice(0, expected.length - 1).join(", ")
- + " or "
- + expected[expected.length - 1];
- }
-
- foundHumanized = found ? quote(found) : "end of input";
-
- return "Expected " + expectedHumanized + " but " + foundHumanized + " found.";
- }
-
- this.name = "SyntaxError";
- this.expected = expected;
- this.found = found;
- this.message = buildMessage(expected, found);
- this.offset = offset;
- this.line = line;
- this.column = column;
- };
-
- result.SyntaxError.prototype = Error.prototype;
-
- return result;
-})();
-
-(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= len) {
- return x; // missing argument
- }
- var arg = args[i];
- i += 1;
- switch (x) {
- case '%%':
- return '%';
- case '%s':
- return String(arg);
- case '%d':
- return Number(arg);
- case '%v':
- return '';
- }
- });
- // NB: we discard excess arguments - they are typically undefined from makeLine
-};
-
-var makeLine = function (type, obj, location) {
- var str = obj.format instanceof Function ?
- (obj.format(obj.push ? location : location[obj.name])) :
- obj.format;
-
- var args = [type + '=' + str];
- if (obj.names) {
- for (var i = 0; i < obj.names.length; i += 1) {
- var n = obj.names[i];
- if (obj.name) {
- args.push(location[obj.name][n]);
- }
- else { // for mLine and push attributes
- args.push(location[obj.names[i]]);
- }
- }
- }
- else {
- args.push(location[obj.name]);
- }
- return format.apply(null, args);
-};
-
-// RFC specified order
-// TODO: extend this with all the rest
-var defaultOuterOrder = [
- 'v', 'o', 's', 'i',
- 'u', 'e', 'p', 'c',
- 'b', 't', 'r', 'z', 'a'
-];
-var defaultInnerOrder = ['i', 'c', 'b', 'a'];
-
-
-module.exports = function (session, opts) {
- opts = opts || {};
- // ensure certain properties exist
- if (session.version == null) {
- session.version = 0; // "v=0" must be there (only defined version atm)
- }
- if (session.name == null) {
- session.name = " "; // "s= " must be there if no meaningful name set
- }
- session.media.forEach(function (mLine) {
- if (mLine.payloads == null) {
- mLine.payloads = "";
- }
- });
-
- var outerOrder = opts.outerOrder || defaultOuterOrder;
- var innerOrder = opts.innerOrder || defaultInnerOrder;
- var sdp = [];
-
- // loop through outerOrder for matching properties on session
- outerOrder.forEach(function (type) {
- grammar[type].forEach(function (obj) {
- if (obj.name in session) {
- sdp.push(makeLine(type, obj, session));
- }
- else if (obj.push in session) {
- session[obj.push].forEach(function (el) {
- sdp.push(makeLine(type, obj, el));
- });
- }
- });
- });
-
- // then for each media line, follow the innerOrder
- session.media.forEach(function (mLine) {
- sdp.push(makeLine('m', grammar.m[0], mLine));
-
- innerOrder.forEach(function (type) {
- grammar[type].forEach(function (obj) {
- if (obj.name in mLine) {
- sdp.push(makeLine(type, obj, mLine));
- }
- else if (obj.push in mLine) {
- mLine[obj.push].forEach(function (el) {
- sdp.push(makeLine(type, obj, el));
- });
- }
- });
- });
- });
-
- return sdp.join('\r\n') + '\r\n';
-};
-
-},{"./grammar":2}],5:[function(require,module,exports){
-/**
- * @fileoverview SDP Parser
- *
- * https://github.com/clux/sdp-transform
- *
- */
-
-(function(JsSIP) {
-
- var parser = require('sdp-transform');
-
- JsSIP.Parser.parseSDP = parser.parse;
- JsSIP.Parser.writeSDP = parser.write;
- JsSIP.Parser.parseFmtpConfig = parser.parseFmtpConfig;
- JsSIP.Parser.parsePayloads = parser.parsePayloads;
- JsSIP.Parser.parseRemoteCandidates = parser.parseRemoteCandidates;
-
-}(JsSIP));
-
-
-},{"sdp-transform":1}]},{},[5])
\ No newline at end of file
+/*
+ * JsSIP version 0.3.7
+ * Copyright (c) 2012-2014 José Luis Millán - Versatica
+ * Homepage: http://jssip.net
+ * License: http://jssip.net/license
+ */
+
+
+/*global console: false*/
+
+/**
+ * @name JsSIP
+ * @namespace
+ */
+(function(window) {
+
+var JsSIP = (function() {
+ "use strict";
+
+ var JsSIP = {};
+
+ Object.defineProperties(JsSIP, {
+ version: {
+ get: function(){ return '0.3.7'; }
+ },
+ name: {
+ get: function(){ return 'JsSIP'; }
+ }
+ });
+
+ return JsSIP;
+}());
+
+
+
+/**
+ * @fileoverview EventEmitter
+ */
+
+/**
+ * @augments JsSIP
+ * @class Class creating an event emitter.
+ */
+(function(JsSIP) {
+var
+ EventEmitter,
+ Event,
+ LOG_PREFIX = JsSIP.name +' | '+ 'EVENT EMITTER' +' | ';
+
+EventEmitter = function(){};
+EventEmitter.prototype = {
+ /**
+ * Initialize events dictionary.
+ * @param {Array} events
+ */
+ initEvents: function(events) {
+ var i = events.length;
+
+ this.events = {};
+ this.onceNotFired = []; // Array containing events with _once_ defined tat didn't fire yet.
+ this.maxListeners = 10;
+ this.events.newListener = function(event) { // Default newListener callback
+ console.log(LOG_PREFIX +'new listener added to event '+ event);
+ };
+
+ while (i--) {
+ console.log(LOG_PREFIX +'adding event '+ events[i]);
+ this.events[events[i]] = [];
+ }
+ },
+
+ /**
+ * Check whether an event exists or not.
+ * @param {String} event
+ * @returns {Boolean}
+ */
+ checkEvent: function(event) {
+ if (!this.events[event]) {
+ console.error(LOG_PREFIX +'no event named '+ event);
+ return false;
+ } else {
+ return true;
+ }
+ },
+
+ /**
+ * Add a listener to the end of the listeners array for the specified event.
+ * @param {String} event
+ * @param {Function} listener
+ */
+ addListener: function(event, listener) {
+ if (!this.checkEvent(event)) {
+ return;
+ }
+
+ if (this.events[event].length >= this.maxListeners) {
+ console.warn(LOG_PREFIX +'max listeners exceeded for event '+ event);
+ }
+
+ this.events[event].push(listener);
+ this.events.newListener.call(null, event);
+ },
+
+ on: function(event, listener) {
+ this.addListener(event, listener);
+ },
+
+ /**
+ * Add a one time listener for the event.
+ * The listener is invoked only the first time the event is fired, after which it is removed.
+ * @param {String} event
+ * @param {Function} listener
+ */
+ once: function(event, listener) {
+ this.events[event].unshift(listener);
+ this.onceNotFired.push(event);
+ },
+
+ /**
+ * Remove a listener from the listener array for the specified event.
+ * Caution: changes array indices in the listener array behind the listener.
+ * @param {String} event
+ * @param {Function} listener
+ */
+ removeListener: function(event, listener) {
+ if (!this.checkEvent(event)) {
+ return;
+ }
+
+ var array = this.events[event], i = 0, length = array.length;
+
+ while ( i < length ) {
+ if (array[i] && array[i].toString() === listener.toString()) {
+ array.splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+ },
+
+ /**
+ * Remove all listeners from the listener array for the specified event.
+ * @param {String} event
+ */
+ removeAllListener: function(event) {
+ if (!this.checkEvent(event)) {
+ return;
+ }
+
+ this.events[event] = [];
+ },
+
+ /**
+ * By default EventEmitter will print a warning
+ * if more than 10 listeners are added for a particular event.
+ * This function allows that limit to be modified.
+ * @param {Number} listeners
+ */
+ setMaxListeners: function(listeners) {
+ if (Number(listeners)) {
+ this.maxListeners = listeners;
+ }
+ },
+
+ /**
+ * Get the listeners for a specific event.
+ * @param {String} event
+ * @returns {Array} Array of listeners for the specified event.
+ */
+ listeners: function(event) {
+ return this.events[event];
+ },
+
+ /**
+ * Execute each of the listeners in order with the supplied arguments.
+ * @param {String} events
+ * @param {Array} args
+ */
+ emit: function(event, sender, data) {
+ var listeners, length,
+ emitter = this;
+
+ if (!this.checkEvent(event)) {
+ return;
+ }
+
+ console.log(LOG_PREFIX +'emitting event '+event);
+
+ listeners = this.events[event];
+ length = listeners.length;
+
+ var e = new JsSIP.Event(event, sender, data);
+
+ window.setTimeout(
+ function(){
+ var idx=0;
+
+ for (idx; idx this.ua.configuration.ws_server_max_reconnection) {
+ console.warn(LOG_PREFIX +'maximum reconnection attempts for WebSocket ' + this.server.ws_uri);
+ this.ua.onTransportError(this);
+ } else {
+ console.log(LOG_PREFIX +'trying to reconnect to WebSocket ' + this.server.ws_uri + ' (reconnection attempt ' + this.reconnection_attempts + ')');
+
+ this.reconnectTimer = window.setTimeout(function() {
+ transport.connect();
+ transport.reconnectTimer = null;
+ }, this.ua.configuration.ws_server_reconnection_timeout * 1000);
+ }
+ }
+};
+
+Transport.C = C;
+JsSIP.Transport = Transport;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview SIP Message Parser
+ */
+
+/**
+ * Extract and parse every header of a SIP message.
+ * @augments JsSIP
+ * @namespace
+ */
+(function(JsSIP) {
+var Parser,
+ LOG_PREFIX = JsSIP.name +' | '+ 'PARSER' +' | ';
+
+function getHeader(data, headerStart) {
+ var
+ // 'start' position of the header.
+ start = headerStart,
+ // 'end' position of the header.
+ end = 0,
+ // 'partial end' position of the header.
+ partialEnd = 0;
+
+ //End of message.
+ if (data.substring(start, start + 2).match(/(^\r\n)/)) {
+ return -2;
+ }
+
+ while(end === 0) {
+ // Partial End of Header.
+ partialEnd = data.indexOf('\r\n', start);
+
+ // 'indexOf' returns -1 if the value to be found never occurs.
+ if (partialEnd === -1) {
+ return partialEnd;
+ }
+
+ if(!data.substring(partialEnd + 2, partialEnd + 4).match(/(^\r\n)/) && data.charAt(partialEnd + 2).match(/(^\s+)/)) {
+ // Not the end of the message. Continue from the next position.
+ start = partialEnd + 2;
+ } else {
+ end = partialEnd;
+ }
+ }
+
+ return end;
+}
+
+function parseHeader(message, data, headerStart, headerEnd) {
+ var header, idx, length, parsed,
+ hcolonIndex = data.indexOf(':', headerStart),
+ headerName = data.substring(headerStart, hcolonIndex).trim(),
+ headerValue = data.substring(hcolonIndex + 1, headerEnd).trim();
+
+ // If header-field is well-known, parse it.
+ switch(headerName.toLowerCase()) {
+ case 'via':
+ case 'v':
+ message.addHeader('via', headerValue);
+ if(message.countHeader('via') === 1) {
+ parsed = message.parseHeader('Via');
+ if(parsed) {
+ message.via = parsed;
+ message.via_branch = parsed.branch;
+ }
+ } else {
+ parsed = 0;
+ }
+ break;
+ case 'from':
+ case 'f':
+ message.setHeader('from', headerValue);
+ parsed = message.parseHeader('from');
+ if(parsed) {
+ message.from = parsed;
+ message.from_tag = parsed.getParam('tag');
+ }
+ break;
+ case 'to':
+ case 't':
+ message.setHeader('to', headerValue);
+ parsed = message.parseHeader('to');
+ if(parsed) {
+ message.to = parsed;
+ message.to_tag = parsed.getParam('tag');
+ }
+ break;
+ case 'record-route':
+ parsed = JsSIP.Grammar.parse(headerValue, 'Record_Route');
+
+ if (parsed === -1) {
+ parsed = undefined;
+ }
+
+ length = parsed.length;
+ for (idx = 0; idx < length; idx++) {
+ header = parsed[idx];
+ message.addHeader('record-route', headerValue.substring(header.possition, header.offset));
+ message.headers['Record-Route'][message.countHeader('record-route')-1].parsed = header.parsed;
+ }
+ break;
+ case 'call-id':
+ case 'i':
+ message.setHeader('call-id', headerValue);
+ parsed = message.parseHeader('call-id');
+ if(parsed) {
+ message.call_id = headerValue;
+ }
+ break;
+ case 'contact':
+ case 'm':
+ parsed = JsSIP.Grammar.parse(headerValue, 'Contact');
+
+ if (parsed === -1) {
+ parsed = undefined;
+ }
+
+ length = parsed.length;
+ for (idx = 0; idx < length; idx++) {
+ header = parsed[idx];
+ message.addHeader('contact', headerValue.substring(header.possition, header.offset));
+ message.headers['Contact'][message.countHeader('contact')-1].parsed = header.parsed;
+ }
+ break;
+ case 'content-length':
+ case 'l':
+ message.setHeader('content-length', headerValue);
+ parsed = message.parseHeader('content-length');
+ break;
+ case 'content-type':
+ case 'c':
+ message.setHeader('content-type', headerValue);
+ parsed = message.parseHeader('content-type');
+ break;
+ case 'cseq':
+ message.setHeader('cseq', headerValue);
+ parsed = message.parseHeader('cseq');
+ if(parsed) {
+ message.cseq = parsed.value;
+ }
+ if(message instanceof JsSIP.IncomingResponse) {
+ message.method = parsed.method;
+ }
+ break;
+ case 'max-forwards':
+ message.setHeader('max-forwards', headerValue);
+ parsed = message.parseHeader('max-forwards');
+ break;
+ case 'www-authenticate':
+ message.setHeader('www-authenticate', headerValue);
+ parsed = message.parseHeader('www-authenticate');
+ break;
+ case 'proxy-authenticate':
+ message.setHeader('proxy-authenticate', headerValue);
+ parsed = message.parseHeader('proxy-authenticate');
+ break;
+ default:
+ // Do not parse this header.
+ message.setHeader(headerName, headerValue);
+ parsed = 0;
+ }
+
+ if (parsed === undefined) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+/** Parse SIP Message
+ * @function
+ * @param {String} message SIP message.
+ * @returns {JsSIP.IncomingRequest|JsSIP.IncomingResponse|undefined}
+ */
+Parser = {};
+Parser.parseMessage = function(data) {
+ var message, firstLine, contentLength, bodyStart, parsed,
+ headerStart = 0,
+ headerEnd = data.indexOf('\r\n');
+
+ if(headerEnd === -1) {
+ console.warn(LOG_PREFIX +'no CRLF found, not a SIP message, discarded');
+ return;
+ }
+
+ // Parse first line. Check if it is a Request or a Reply.
+ firstLine = data.substring(0, headerEnd);
+ parsed = JsSIP.Grammar.parse(firstLine, 'Request_Response');
+
+ if(parsed === -1) {
+ console.warn(LOG_PREFIX +'error parsing first line of SIP message: "' + firstLine + '"');
+ return;
+ } else if(!parsed.status_code) {
+ message = new JsSIP.IncomingRequest();
+ message.method = parsed.method;
+ message.ruri = parsed.uri;
+ } else {
+ message = new JsSIP.IncomingResponse();
+ message.status_code = parsed.status_code;
+ message.reason_phrase = parsed.reason_phrase;
+ }
+
+ message.data = data;
+ headerStart = headerEnd + 2;
+
+ /* Loop over every line in data. Detect the end of each header and parse
+ * it or simply add to the headers collection.
+ */
+ while(true) {
+ headerEnd = getHeader(data, headerStart);
+
+ // The SIP message has normally finished.
+ if(headerEnd === -2) {
+ bodyStart = headerStart + 2;
+ break;
+ }
+ // data.indexOf returned -1 due to a malformed message.
+ else if(headerEnd === -1) {
+ return;
+ }
+
+ parsed = parseHeader(message, data, headerStart, headerEnd);
+
+ if(!parsed) {
+ return;
+ }
+
+ headerStart = headerEnd + 2;
+ }
+
+ /* RFC3261 18.3.
+ * If there are additional bytes in the transport packet
+ * beyond the end of the body, they MUST be discarded.
+ */
+ if(message.hasHeader('content-length')) {
+ contentLength = message.getHeader('content-length');
+ message.body = data.substr(bodyStart, contentLength);
+ } else {
+ message.body = data.substring(bodyStart);
+ }
+
+ return message;
+};
+
+JsSIP.Parser = Parser;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview SIP Message
+ */
+
+(function(JsSIP) {
+var
+ OutgoingRequest,
+ IncomingMessage,
+ IncomingRequest,
+ IncomingResponse,
+ LOG_PREFIX = JsSIP.name +' | '+ 'SIP MESSAGE' +' | ';
+
+/**
+ * @augments JsSIP
+ * @class Class for outgoing SIP request.
+ * @param {String} method request method
+ * @param {String} ruri request uri
+ * @param {JsSIP.UA} ua
+ * @param {Object} params parameters that will have priority over ua.configuration parameters:
+ *
+ * - cseq, call_id, from_tag, from_uri, from_display_name, to_uri, to_tag, route_set
+ * @param {Object} [headers] extra headers
+ * @param {String} [body]
+ */
+OutgoingRequest = function(method, ruri, ua, params, extraHeaders, body) {
+ var
+ to,
+ from,
+ call_id,
+ cseq;
+
+ params = params || {};
+
+ // Mandatory parameters check
+ if(!method || !ruri || !ua) {
+ return null;
+ }
+
+ this.headers = {};
+ this.method = method;
+ this.ruri = ruri;
+ this.body = body;
+ this.extraHeaders = extraHeaders || [];
+
+ // Fill the Common SIP Request Headers
+
+ // Route
+ if (params.route_set) {
+ this.setHeader('route', params.route_set);
+ } else if (ua.configuration.use_preloaded_route){
+ this.setHeader('route', ua.transport.server.sip_uri);
+ }
+
+ // Via
+ // Empty Via header. Will be filled by the client transaction.
+ this.setHeader('via', '');
+
+ // Max-Forwards
+ this.setHeader('max-forwards', JsSIP.UA.C.MAX_FORWARDS);
+
+ // To
+ to = (params.to_display_name || params.to_display_name === 0) ? '"' + params.to_display_name + '" ' : '';
+ to += '<' + (params.to_uri || ruri) + '>';
+ to += params.to_tag ? ';tag=' + params.to_tag : '';
+ this.to = new JsSIP.NameAddrHeader.parse(to);
+ this.setHeader('to', to);
+
+ // From
+ if (params.from_display_name || params.from_display_name === 0) {
+ from = '"' + params.from_display_name + '" ';
+ } else if (ua.configuration.display_name) {
+ from = '"' + ua.configuration.display_name + '" ';
+ } else {
+ from = '';
+ }
+ from += '<' + (params.from_uri || ua.configuration.uri) + '>;tag=';
+ from += params.from_tag || JsSIP.Utils.newTag();
+ this.from = new JsSIP.NameAddrHeader.parse(from);
+ this.setHeader('from', from);
+
+ // Call-ID
+ call_id = params.call_id || (ua.configuration.jssip_id + JsSIP.Utils.createRandomToken(15));
+ this.call_id = call_id;
+ this.setHeader('call-id', call_id);
+
+ // CSeq
+ cseq = params.cseq || Math.floor(Math.random() * 10000);
+ this.cseq = cseq;
+ this.setHeader('cseq', cseq + ' ' + method);
+};
+
+OutgoingRequest.prototype = {
+ /**
+ * Replace the the given header by the given value.
+ * @param {String} name header name
+ * @param {String | Array} value header value
+ */
+ setHeader: function(name, value) {
+ this.headers[JsSIP.Utils.headerize(name)] = (value instanceof Array) ? value : [value];
+ },
+ toString: function() {
+ var msg = '', header, length, idx;
+
+ msg += this.method + ' ' + this.ruri + ' SIP/2.0\r\n';
+
+ for (header in this.headers) {
+ length = this.headers[header].length;
+ for (idx = 0; idx < length; idx++) {
+ msg += header + ': ' + this.headers[header][idx] + '\r\n';
+ }
+ }
+
+ length = this.extraHeaders.length;
+ for (idx = 0; idx < length; idx++) {
+ msg += this.extraHeaders[idx] +'\r\n';
+ }
+
+ msg += 'Supported: ' + JsSIP.UA.C.SUPPORTED +'\r\n';
+ msg += 'User-Agent: ' + JsSIP.C.USER_AGENT +'\r\n';
+
+ if(this.body) {
+ length = JsSIP.Utils.str_utf8_length(this.body);
+ msg += 'Content-Length: ' + length + '\r\n\r\n';
+ msg += this.body;
+ } else {
+ msg += 'Content-Length: 0\r\n\r\n';
+ }
+
+ return msg;
+ }
+};
+
+/**
+ * @augments JsSIP
+ * @class Class for incoming SIP message.
+ */
+IncomingMessage = function(){
+ this.data = null;
+ this.headers = null;
+ this.method = null;
+ this.via = null;
+ this.via_branch = null;
+ this.call_id = null;
+ this.cseq = null;
+ this.from = null;
+ this.from_tag = null;
+ this.to = null;
+ this.to_tag = null;
+ this.body = null;
+};
+
+IncomingMessage.prototype = {
+ /**
+ * Insert a header of the given name and value into the last position of the
+ * header array.
+ * @param {String} name header name
+ * @param {String} value header value
+ */
+ addHeader: function(name, value) {
+ var header = { raw: value };
+
+ name = JsSIP.Utils.headerize(name);
+
+ if(this.headers[name]) {
+ this.headers[name].push(header);
+ } else {
+ this.headers[name] = [header];
+ }
+ },
+
+ /**
+ * Count the number of headers of the given header name.
+ * @param {String} name header name
+ * @returns {Number} Number of headers with the given name
+ */
+ countHeader: function(name) {
+ var header = this.headers[JsSIP.Utils.headerize(name)];
+
+ if(header) {
+ return header.length;
+ } else {
+ return 0;
+ }
+ },
+
+ /**
+ * Get the value of the given header name at the given position.
+ * @param {String} name header name
+ * @param {Number} [idx=0] header index
+ * @returns {String|undefined} Returns the specified header, null if header doesn't exist.
+ */
+ getHeader: function(name, idx) {
+ var header = this.headers[JsSIP.Utils.headerize(name)];
+
+ idx = idx || 0;
+
+ if(header) {
+ if(header[idx]) {
+ return header[idx].raw;
+ }
+ } else {
+ return;
+ }
+ },
+
+ /**
+ * Get the header/s of the given name.
+ * @param {String} name header name
+ * @returns {Array} Array with all the headers of the specified name.
+ */
+ getHeaderAll: function(name) {
+ var idx, length,
+ header = this.headers[JsSIP.Utils.headerize(name)],
+ result = [];
+
+ if(!header) {
+ return [];
+ }
+
+ length = header.length;
+ for (idx = 0; idx < length; idx++) {
+ result.push(header[idx].raw);
+ }
+
+ return result;
+ },
+
+ /**
+ * Verify the existence of the given header.
+ * @param {String} name header name
+ * @returns {boolean} true if header with given name exists, false otherwise
+ */
+ hasHeader: function(name) {
+ return(this.headers[JsSIP.Utils.headerize(name)]) ? true : false;
+ },
+
+ /**
+ * Parse the given header on the given index.
+ * @param {String} name header name
+ * @param {Number} [idx=0] header index
+ * @returns {Object|undefined} Parsed header object, undefined if the header is not present or in case of a parsing error.
+ */
+ parseHeader: function(name, idx) {
+ var header, value, parsed;
+
+ name = JsSIP.Utils.headerize(name);
+
+ idx = idx || 0;
+
+ if(!this.headers[name]) {
+ console.log(LOG_PREFIX +'header "' + name + '" not present');
+ return;
+ } else if(idx >= this.headers[name].length) {
+ console.log(LOG_PREFIX +'not so many "' + name + '" headers present');
+ return;
+ }
+
+ header = this.headers[name][idx];
+ value = header.raw;
+
+ if(header.parsed) {
+ return header.parsed;
+ }
+
+ //substitute '-' by '_' for grammar rule matching.
+ parsed = JsSIP.Grammar.parse(value, name.replace(/-/g, '_'));
+
+ if(parsed === -1) {
+ this.headers[name].splice(idx, 1); //delete from headers
+ console.warn(LOG_PREFIX +'error parsing "' + name + '" header field with value "' + value + '"');
+ return;
+ } else {
+ header.parsed = parsed;
+ return parsed;
+ }
+ },
+
+ /**
+ * Message Header attribute selector. Alias of parseHeader.
+ * @param {String} name header name
+ * @param {Number} [idx=0] header index
+ * @returns {Object|undefined} Parsed header object, undefined if the header is not present or in case of a parsing error.
+ *
+ * @example
+ * message.s('via',3).port
+ */
+ s: function(name, idx) {
+ return this.parseHeader(name, idx);
+ },
+
+ /**
+ * Replace the value of the given header by the value.
+ * @param {String} name header name
+ * @param {String} value header value
+ */
+ setHeader: function(name, value) {
+ var header = { raw: value };
+ this.headers[JsSIP.Utils.headerize(name)] = [header];
+ },
+
+ toString: function() {
+ return this.data;
+ }
+};
+
+/**
+ * @augments IncomingMessage
+ * @class Class for incoming SIP request.
+ */
+IncomingRequest = function() {
+ this.headers = {};
+ this.ruri = null;
+ this.transport = null;
+ this.server_transaction = null;
+};
+IncomingRequest.prototype = new IncomingMessage();
+
+/**
+* Stateful reply.
+* @param {Number} code status code
+* @param {String} reason reason phrase
+* @param {Object} headers extra headers
+* @param {String} body body
+* @param {Function} [onSuccess] onSuccess callback
+* @param {Function} [onFailure] onFailure callback
+*/
+IncomingRequest.prototype.reply = function(code, reason, extraHeaders, body, onSuccess, onFailure) {
+ var rr, vias, length, idx, response,
+ to = this.getHeader('To'),
+ r = 0,
+ v = 0;
+
+ code = code || null;
+ reason = reason || null;
+
+ // Validate code and reason values
+ if (!code || (code < 100 || code > 699)) {
+ throw new TypeError('Invalid status_code: '+ code);
+ } else if (reason && typeof reason !== 'string' && !(reason instanceof String)) {
+ throw new TypeError('Invalid reason_phrase: '+ reason);
+ }
+
+ reason = reason || JsSIP.C.REASON_PHRASE[code] || '';
+ extraHeaders = extraHeaders || [];
+
+ response = 'SIP/2.0 ' + code + ' ' + reason + '\r\n';
+
+ if(this.method === JsSIP.C.INVITE && code > 100 && code <= 200) {
+ rr = this.countHeader('record-route');
+
+ for(r; r < rr; r++) {
+ response += 'Record-Route: ' + this.getHeader('record-route', r) + '\r\n';
+ }
+ }
+
+ vias = this.countHeader('via');
+
+ for(v; v < vias; v++) {
+ response += 'Via: ' + this.getHeader('via', v) + '\r\n';
+ }
+
+ if(!this.to_tag && code > 100) {
+ to += ';tag=' + JsSIP.Utils.newTag();
+ } else if(this.to_tag && !this.s('to').hasParam('tag')) {
+ to += ';tag=' + this.to_tag;
+ }
+
+ response += 'To: ' + to + '\r\n';
+ response += 'From: ' + this.getHeader('From') + '\r\n';
+ response += 'Call-ID: ' + this.call_id + '\r\n';
+ response += 'CSeq: ' + this.cseq + ' ' + this.method + '\r\n';
+
+ length = extraHeaders.length;
+ for (idx = 0; idx < length; idx++) {
+ response += extraHeaders[idx] +'\r\n';
+ }
+
+ if(body) {
+ length = JsSIP.Utils.str_utf8_length(body);
+ response += 'Content-Type: application/sdp\r\n';
+ response += 'Content-Length: ' + length + '\r\n\r\n';
+ response += body;
+ } else {
+ response += 'Content-Length: ' + 0 + '\r\n\r\n';
+ }
+
+ this.server_transaction.receiveResponse(code, response, onSuccess, onFailure);
+};
+
+/**
+* Stateless reply.
+* @param {Number} code status code
+* @param {String} reason reason phrase
+*/
+IncomingRequest.prototype.reply_sl = function(code, reason) {
+ var to, response,
+ vias = this.countHeader('via');
+
+ code = code || null;
+ reason = reason || null;
+
+ // Validate code and reason values
+ if (!code || (code < 100 || code > 699)) {
+ throw new TypeError('Invalid status_code: '+ code);
+ } else if (reason && typeof reason !== 'string' && !(reason instanceof String)) {
+ throw new TypeError('Invalid reason_phrase: '+ reason);
+ }
+
+ reason = reason || JsSIP.C.REASON_PHRASE[code] || '';
+
+ response = 'SIP/2.0 ' + code + ' ' + reason + '\r\n';
+
+ for(var v = 0; v < vias; v++) {
+ response += 'Via: ' + this.getHeader('via', v) + '\r\n';
+ }
+
+ to = this.getHeader('To');
+
+ if(!this.to_tag && code > 100) {
+ to += ';tag=' + JsSIP.Utils.newTag();
+ } else if(this.to_tag && !this.s('to').hasParam('tag')) {
+ to += ';tag=' + this.to_tag;
+ }
+
+ response += 'To: ' + to + '\r\n';
+ response += 'From: ' + this.getHeader('From') + '\r\n';
+ response += 'Call-ID: ' + this.call_id + '\r\n';
+ response += 'CSeq: ' + this.cseq + ' ' + this.method + '\r\n';
+ response += 'Content-Length: ' + 0 + '\r\n\r\n';
+
+ this.transport.send(response);
+};
+
+
+/**
+ * @augments IncomingMessage
+ * @class Class for incoming SIP response.
+ */
+IncomingResponse = function() {
+ this.headers = {};
+ this.status_code = null;
+ this.reason_phrase = null;
+};
+IncomingResponse.prototype = new IncomingMessage();
+
+JsSIP.OutgoingRequest = OutgoingRequest;
+JsSIP.IncomingRequest = IncomingRequest;
+JsSIP.IncomingResponse = IncomingResponse;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview SIP URI
+ */
+
+/**
+ * @augments JsSIP
+ * @class Class creating a SIP URI.
+ *
+ * @param {String} [scheme]
+ * @param {String} [user]
+ * @param {String} host
+ * @param {String} [port]
+ * @param {Object} [parameters]
+ * @param {Object} [headers]
+ *
+ */
+(function(JsSIP) {
+var URI;
+
+URI = function(scheme, user, host, port, parameters, headers) {
+ var param, header;
+
+ // Checks
+ if(!host) {
+ throw new TypeError('missing or invalid "host" parameter');
+ }
+
+ // Initialize parameters
+ scheme = scheme || JsSIP.C.SIP;
+ this.parameters = {};
+ this.headers = {};
+
+ for (param in parameters) {
+ this.setParam(param, parameters[param]);
+ }
+
+ for (header in headers) {
+ this.setHeader(header, headers[header]);
+ }
+
+ Object.defineProperties(this, {
+ scheme: {
+ get: function(){ return scheme; },
+ set: function(value){
+ scheme = value.toLowerCase();
+ }
+ },
+
+ user: {
+ get: function(){ return user; },
+ set: function(value){
+ user = value;
+ }
+ },
+
+ host: {
+ get: function(){ return host; },
+ set: function(value){
+ host = value.toLowerCase();
+ }
+ },
+
+ port: {
+ get: function(){ return port; },
+ set: function(value){
+ port = value === 0 ? value : (parseInt(value,10) || null);
+ }
+ }
+ });
+};
+URI.prototype = {
+ setParam: function(key, value) {
+ if(key) {
+ this.parameters[key.toLowerCase()] = (typeof value === 'undefined' || value === null) ? null : value.toString().toLowerCase();
+ }
+ },
+
+ getParam: function(key) {
+ if(key) {
+ return this.parameters[key.toLowerCase()];
+ }
+ },
+
+ hasParam: function(key) {
+ if(key) {
+ return (this.parameters.hasOwnProperty(key.toLowerCase()) && true) || false;
+ }
+ },
+
+ deleteParam: function(parameter) {
+ var value;
+ parameter = parameter.toLowerCase();
+ if (this.parameters.hasOwnProperty(parameter)) {
+ value = this.parameters[parameter];
+ delete this.parameters[parameter];
+ return value;
+ }
+ },
+
+ clearParams: function() {
+ this.parameters = {};
+ },
+
+ setHeader: function(name, value) {
+ this.headers[JsSIP.Utils.headerize(name)] = (value instanceof Array) ? value : [value];
+ },
+
+ getHeader: function(name) {
+ if(name) {
+ return this.headers[JsSIP.Utils.headerize(name)];
+ }
+ },
+
+ hasHeader: function(name) {
+ if(name) {
+ return (this.headers.hasOwnProperty(JsSIP.Utils.headerize(name)) && true) || false;
+ }
+ },
+
+ deleteHeader: function(header) {
+ var value;
+ header = JsSIP.Utils.headerize(header);
+ if(this.headers.hasOwnProperty(header)) {
+ value = this.headers[header];
+ delete this.headers[header];
+ return value;
+ }
+ },
+
+ clearHeaders: function() {
+ this.headers = {};
+ },
+
+ clone: function() {
+ return new URI(
+ this.scheme,
+ this.user,
+ this.host,
+ this.port,
+ window.JSON.parse(window.JSON.stringify(this.parameters)),
+ window.JSON.parse(window.JSON.stringify(this.headers)));
+ },
+
+ toString: function(){
+ var header, parameter, idx, uri,
+ headers = [];
+
+ uri = this.scheme + ':';
+ if (this.user) {
+ uri += JsSIP.Utils.escapeUser(this.user) + '@';
+ }
+ uri += this.host;
+ if (this.port || this.port === 0) {
+ uri += ':' + this.port;
+ }
+
+ for (parameter in this.parameters) {
+ uri += ';' + parameter;
+
+ if (this.parameters[parameter] !== null) {
+ uri += '='+ this.parameters[parameter];
+ }
+ }
+
+ for(header in this.headers) {
+ for(idx in this.headers[header]) {
+ headers.push(header + '=' + this.headers[header][idx]);
+ }
+ }
+
+ if (headers.length > 0) {
+ uri += '?' + headers.join('&');
+ }
+
+ return uri;
+ },
+
+ toAor: function(show_port){
+ var aor;
+
+ aor = this.scheme + ':';
+ if (this.user) {
+ aor += JsSIP.Utils.escapeUser(this.user) + '@';
+ }
+ aor += this.host;
+ if (show_port && (this.port || this.port === 0)) {
+ aor += ':' + this.port;
+ }
+
+ return aor;
+ }
+};
+
+
+/**
+ * Parse the given string and returns a JsSIP.URI instance or undefined if
+ * it is an invalid URI.
+ * @public
+ * @param {String} uri
+ */
+URI.parse = function(uri) {
+ uri = JsSIP.Grammar.parse(uri,'SIP_URI');
+
+ if (uri !== -1) {
+ return uri;
+ } else {
+ return undefined;
+ }
+};
+
+JsSIP.URI = URI;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview JsSIP NameAddrHeader
+ */
+
+/**
+ * @augments JsSIP
+ * @class Class creating a Name Address SIP header.
+ *
+ * @param {JsSIP.URI} uri
+ * @param {String} [display_name]
+ * @param {Object} [parameters]
+ *
+ */
+(function(JsSIP) {
+var NameAddrHeader;
+
+NameAddrHeader = function(uri, display_name, parameters) {
+ var param;
+
+ // Checks
+ if(!uri || !(uri instanceof JsSIP.URI)) {
+ throw new TypeError('missing or invalid "uri" parameter');
+ }
+
+ // Initialize parameters
+ this.uri = uri;
+ this.parameters = {};
+
+ for (param in parameters) {
+ this.setParam(param, parameters[param]);
+ }
+
+ Object.defineProperties(this, {
+ display_name: {
+ get: function() { return display_name; },
+ set: function(value) {
+ display_name = (value === 0) ? '0' : value;
+ }
+ }
+ });
+};
+NameAddrHeader.prototype = {
+ setParam: function(key, value) {
+ if (key) {
+ this.parameters[key.toLowerCase()] = (typeof value === 'undefined' || value === null) ? null : value.toString();
+ }
+ },
+
+ getParam: function(key) {
+ if(key) {
+ return this.parameters[key.toLowerCase()];
+ }
+ },
+
+ hasParam: function(key) {
+ if(key) {
+ return (this.parameters.hasOwnProperty(key.toLowerCase()) && true) || false;
+ }
+ },
+
+ deleteParam: function(parameter) {
+ var value;
+ parameter = parameter.toLowerCase();
+ if (this.parameters.hasOwnProperty(parameter)) {
+ value = this.parameters[parameter];
+ delete this.parameters[parameter];
+ return value;
+ }
+ },
+
+ clearParams: function() {
+ this.parameters = {};
+ },
+
+ clone: function() {
+ return new NameAddrHeader(
+ this.uri.clone(),
+ this.display_name,
+ window.JSON.parse(window.JSON.stringify(this.parameters)));
+ },
+
+ toString: function() {
+ var body, parameter;
+
+ body = (this.display_name || this.display_name === 0) ? '"' + this.display_name + '" ' : '';
+ body += '<' + this.uri.toString() + '>';
+
+ for (parameter in this.parameters) {
+ body += ';' + parameter;
+
+ if (this.parameters[parameter] !== null) {
+ body += '='+ this.parameters[parameter];
+ }
+ }
+
+ return body;
+ }
+};
+
+
+/**
+ * Parse the given string and returns a JsSIP.NameAddrHeader instance or undefined if
+ * it is an invalid NameAddrHeader.
+ * @public
+ * @param {String} name_addr_header
+ */
+NameAddrHeader.parse = function(name_addr_header) {
+ name_addr_header = JsSIP.Grammar.parse(name_addr_header,'Name_Addr_Header');
+
+ if (name_addr_header !== -1) {
+ return name_addr_header;
+ } else {
+ return undefined;
+ }
+};
+
+JsSIP.NameAddrHeader = NameAddrHeader;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview SIP Transactions
+ */
+
+/**
+ * SIP Transactions module.
+ * @augments JsSIP
+ */
+(function(JsSIP) {
+var Transactions,
+ LOG_PREFIX = JsSIP.name +' | '+ 'TRANSACTION' +' | ',
+ C = {
+ // Transaction states
+ STATUS_TRYING: 1,
+ STATUS_PROCEEDING: 2,
+ STATUS_CALLING: 3,
+ STATUS_ACCEPTED: 4,
+ STATUS_COMPLETED: 5,
+ STATUS_TERMINATED: 6,
+ STATUS_CONFIRMED: 7
+ };
+
+Transactions = {};
+
+/**
+* @class Client Transaction
+* @private
+*/
+var ClientTransaction = function() {
+ this.init = function(request_sender, request, transport) {
+ var via;
+
+ this.transport = transport;
+ this.id = 'z9hG4bK' + Math.floor(Math.random() * 10000000);
+ this.request_sender = request_sender;
+ this.request = request;
+
+ via = 'SIP/2.0/' + (request_sender.ua.configuration.hack_via_tcp ? 'TCP' : transport.server.scheme);
+ via += ' ' + request_sender.ua.configuration.via_host + ';branch=' + this.id;
+
+ this.request.setHeader('via', via);
+ };
+};
+
+/**
+* @class Non Invite Client Transaction Prototype
+* @private
+*/
+var NonInviteClientTransactionPrototype = function() {
+ this.send = function() {
+ var tr = this;
+
+ this.state = C.STATUS_TRYING;
+ this.F = window.setTimeout(function() {tr.timer_F();}, JsSIP.Timers.TIMER_F);
+
+ if(!this.transport.send(this.request)) {
+ this.onTransportError();
+ }
+ };
+
+ this.onTransportError = function() {
+ console.log(LOG_PREFIX +'transport error occurred, deleting non-INVITE client transaction ' + this.id);
+ window.clearTimeout(this.F);
+ window.clearTimeout(this.K);
+ delete this.request_sender.ua.transactions.nict[this.id];
+ this.request_sender.onTransportError();
+ };
+
+ this.timer_F = function() {
+ console.log(LOG_PREFIX +'Timer F expired for non-INVITE client transaction ' + this.id);
+ this.state = C.STATUS_TERMINATED;
+ this.request_sender.onRequestTimeout();
+ delete this.request_sender.ua.transactions.nict[this.id];
+ };
+
+ this.timer_K = function() {
+ this.state = C.STATUS_TERMINATED;
+ delete this.request_sender.ua.transactions.nict[this.id];
+ };
+
+ this.receiveResponse = function(response) {
+ var
+ tr = this,
+ status_code = response.status_code;
+
+ if(status_code < 200) {
+ switch(this.state) {
+ case C.STATUS_TRYING:
+ case C.STATUS_PROCEEDING:
+ this.state = C.STATUS_PROCEEDING;
+ this.request_sender.receiveResponse(response);
+ break;
+ }
+ } else {
+ switch(this.state) {
+ case C.STATUS_TRYING:
+ case C.STATUS_PROCEEDING:
+ this.state = C.STATUS_COMPLETED;
+ window.clearTimeout(this.F);
+
+ if(status_code === 408) {
+ this.request_sender.onRequestTimeout();
+ } else {
+ this.request_sender.receiveResponse(response);
+ }
+
+ this.K = window.setTimeout(function() {tr.timer_K();}, JsSIP.Timers.TIMER_K);
+ break;
+ case C.STATUS_COMPLETED:
+ break;
+ }
+ }
+ };
+};
+NonInviteClientTransactionPrototype.prototype = new ClientTransaction();
+
+
+/**
+ * @class Invite Client Transaction Prototype
+ * @private
+ */
+var InviteClientTransactionPrototype = function() {
+
+ this.send = function() {
+ var tr = this;
+ this.state = C.STATUS_CALLING;
+ this.B = window.setTimeout(function() {
+ tr.timer_B();
+ }, JsSIP.Timers.TIMER_B);
+
+ if(!this.transport.send(this.request)) {
+ this.onTransportError();
+ }
+ };
+
+ this.onTransportError = function() {
+ console.log(LOG_PREFIX +'transport error occurred, deleting INVITE client transaction ' + this.id);
+ window.clearTimeout(this.B);
+ window.clearTimeout(this.D);
+ window.clearTimeout(this.M);
+ delete this.request_sender.ua.transactions.ict[this.id];
+
+ if (this.state !== C.STATUS_ACCEPTED) {
+ this.request_sender.onTransportError();
+ }
+ };
+
+ // RFC 6026 7.2
+ this.timer_M = function() {
+ console.log(LOG_PREFIX +'Timer M expired for INVITE client transaction ' + this.id);
+
+ if(this.state === C.STATUS_ACCEPTED) {
+ this.state = C.STATUS_TERMINATED;
+ window.clearTimeout(this.B);
+ delete this.request_sender.ua.transactions.ict[this.id];
+ }
+ };
+
+ // RFC 3261 17.1.1
+ this.timer_B = function() {
+ console.log(LOG_PREFIX +'Timer B expired for INVITE client transaction ' + this.id);
+ if(this.state === C.STATUS_CALLING) {
+ this.state = C.STATUS_TERMINATED;
+ this.request_sender.onRequestTimeout();
+ delete this.request_sender.ua.transactions.ict[this.id];
+ }
+ };
+
+ this.timer_D = function() {
+ console.log(LOG_PREFIX +'Timer D expired for INVITE client transaction ' + this.id);
+ this.state = C.STATUS_TERMINATED;
+ window.clearTimeout(this.B);
+ delete this.request_sender.ua.transactions.ict[this.id];
+ };
+
+ this.sendACK = function(response) {
+ var tr = this;
+
+ this.ack = 'ACK ' + this.request.ruri + ' SIP/2.0\r\n';
+ this.ack += 'Via: ' + this.request.headers['Via'].toString() + '\r\n';
+
+ if(this.request.headers['Route']) {
+ this.ack += 'Route: ' + this.request.headers['Route'].toString() + '\r\n';
+ }
+
+ 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 += 'CSeq: ' + this.request.headers['CSeq'].toString().split(' ')[0];
+ this.ack += ' ACK\r\n\r\n';
+
+ this.D = window.setTimeout(function() {tr.timer_D();}, JsSIP.Timers.TIMER_D);
+
+ this.transport.send(this.ack);
+ };
+
+ this.cancel_request = function(tr, reason) {
+ var request = tr.request;
+
+ this.cancel = JsSIP.C.CANCEL + ' ' + request.ruri + ' SIP/2.0\r\n';
+ this.cancel += 'Via: ' + request.headers['Via'].toString() + '\r\n';
+
+ if(this.request.headers['Route']) {
+ this.cancel += 'Route: ' + request.headers['Route'].toString() + '\r\n';
+ }
+
+ this.cancel += 'To: ' + request.headers['To'].toString() + '\r\n';
+ this.cancel += 'From: ' + request.headers['From'].toString() + '\r\n';
+ this.cancel += 'Call-ID: ' + request.headers['Call-ID'].toString() + '\r\n';
+ this.cancel += 'CSeq: ' + request.headers['CSeq'].toString().split(' ')[0] +
+ ' CANCEL\r\n';
+
+ if(reason) {
+ this.cancel += 'Reason: ' + reason + '\r\n';
+ }
+
+ this.cancel += 'Content-Length: 0\r\n\r\n';
+
+ // Send only if a provisional response (>100) has been received.
+ if(this.state === C.STATUS_PROCEEDING) {
+ this.transport.send(this.cancel);
+ }
+ };
+
+ this.receiveResponse = function(response) {
+ var
+ tr = this,
+ status_code = response.status_code;
+
+ if(status_code >= 100 && status_code <= 199) {
+ switch(this.state) {
+ case C.STATUS_CALLING:
+ this.state = C.STATUS_PROCEEDING;
+ this.request_sender.receiveResponse(response);
+ if(this.cancel) {
+ this.transport.send(this.cancel);
+ }
+ break;
+ case C.STATUS_PROCEEDING:
+ this.request_sender.receiveResponse(response);
+ break;
+ }
+ } else if(status_code >= 200 && status_code <= 299) {
+ switch(this.state) {
+ case C.STATUS_CALLING:
+ case C.STATUS_PROCEEDING:
+ this.state = C.STATUS_ACCEPTED;
+ this.M = window.setTimeout(function() {
+ tr.timer_M();
+ }, JsSIP.Timers.TIMER_M);
+ this.request_sender.receiveResponse(response);
+ break;
+ case C.STATUS_ACCEPTED:
+ this.request_sender.receiveResponse(response);
+ break;
+ }
+ } else if(status_code >= 300 && status_code <= 699) {
+ switch(this.state) {
+ case C.STATUS_CALLING:
+ case C.STATUS_PROCEEDING:
+ this.state = C.STATUS_COMPLETED;
+ this.sendACK(response);
+ this.request_sender.receiveResponse(response);
+ break;
+ case C.STATUS_COMPLETED:
+ this.sendACK(response);
+ break;
+ }
+ }
+ };
+};
+InviteClientTransactionPrototype.prototype = new ClientTransaction();
+
+/**
+ * @class Server Transaction
+ * @private
+ */
+var ServerTransaction = function() {
+ this.init = function(request, ua) {
+ this.id = request.via_branch;
+ this.request = request;
+ this.transport = request.transport;
+ this.ua = ua;
+ this.last_response = '';
+ request.server_transaction = this;
+ };
+};
+
+/**
+ * @class Non Invite Server Transaction Prototype
+ * @private
+ */
+var NonInviteServerTransactionPrototype = function() {
+ this.timer_J = function() {
+ console.log(LOG_PREFIX +'Timer J expired for non-INVITE server transaction ' + this.id);
+ this.state = C.STATUS_TERMINATED;
+ delete this.ua.transactions.nist[this.id];
+ };
+
+ this.onTransportError = function() {
+ if (!this.transportError) {
+ this.transportError = true;
+
+ console.log(LOG_PREFIX +'transport error occurred, deleting non-INVITE server transaction ' + this.id);
+
+ window.clearTimeout(this.J);
+ delete this.ua.transactions.nist[this.id];
+ }
+ };
+
+ this.receiveResponse = function(status_code, response, onSuccess, onFailure) {
+ var tr = this;
+
+ if(status_code === 100) {
+ /* RFC 4320 4.1
+ * 'A SIP element MUST NOT
+ * send any provisional response with a
+ * Status-Code other than 100 to a non-INVITE request.'
+ */
+ switch(this.state) {
+ case C.STATUS_TRYING:
+ this.state = C.STATUS_PROCEEDING;
+ if(!this.transport.send(response)) {
+ this.onTransportError();
+ }
+ break;
+ case C.STATUS_PROCEEDING:
+ this.last_response = response;
+ if(!this.transport.send(response)) {
+ this.onTransportError();
+ if (onFailure) {
+ onFailure();
+ }
+ } else if (onSuccess) {
+ onSuccess();
+ }
+ break;
+ }
+ } else if(status_code >= 200 && status_code <= 699) {
+ switch(this.state) {
+ case C.STATUS_TRYING:
+ case C.STATUS_PROCEEDING:
+ this.state = C.STATUS_COMPLETED;
+ this.last_response = response;
+ this.J = window.setTimeout(function() {
+ tr.timer_J();
+ }, JsSIP.Timers.TIMER_J);
+ if(!this.transport.send(response)) {
+ this.onTransportError();
+ if (onFailure) {
+ onFailure();
+ }
+ } else if (onSuccess) {
+ onSuccess();
+ }
+ break;
+ case C.STATUS_COMPLETED:
+ break;
+ }
+ }
+ };
+};
+NonInviteServerTransactionPrototype.prototype = new ServerTransaction();
+
+/**
+ * @class Invite Server Transaction Prototype
+ * @private
+ */
+var InviteServerTransactionPrototype = function() {
+ this.timer_H = function() {
+ console.log(LOG_PREFIX +'Timer H expired for INVITE server transaction ' + this.id);
+
+ if(this.state === C.STATUS_COMPLETED) {
+ console.warn(LOG_PREFIX +'transactions', 'ACK for INVITE server transaction was never received, call will be terminated');
+ this.state = C.STATUS_TERMINATED;
+ }
+
+ delete this.ua.transactions.ist[this.id];
+ };
+
+ this.timer_I = function() {
+ this.state = C.STATUS_TERMINATED;
+ delete this.ua.transactions.ist[this.id];
+ };
+
+ // RFC 6026 7.1
+ this.timer_L = function() {
+ console.log(LOG_PREFIX +'Timer L expired for INVITE server transaction ' + this.id);
+
+ if(this.state === C.STATUS_ACCEPTED) {
+ this.state = C.STATUS_TERMINATED;
+ delete this.ua.transactions.ist[this.id];
+ }
+ };
+
+ this.onTransportError = function() {
+ if (!this.transportError) {
+ this.transportError = true;
+
+ console.log(LOG_PREFIX +'transport error occurred, deleting INVITE server transaction ' + this.id);
+
+ if (this.resendProvisionalTimer !== null) {
+ window.clearInterval(this.resendProvisionalTimer);
+ this.resendProvisionalTimer = null;
+ }
+ window.clearTimeout(this.L);
+ window.clearTimeout(this.H);
+ window.clearTimeout(this.I);
+ delete this.ua.transactions.ist[this.id];
+ }
+ };
+
+ this.resend_provisional = function() {
+ if(!this.transport.send(this.last_response)) {
+ this.onTransportError();
+ }
+ };
+
+ // INVITE Server Transaction RFC 3261 17.2.1
+ this.receiveResponse = function(status_code, response, onSuccess, onFailure) {
+ var tr = this;
+
+ if(status_code >= 100 && status_code <= 199) {
+ switch(this.state) {
+ case C.STATUS_PROCEEDING:
+ if(!this.transport.send(response)) {
+ this.onTransportError();
+ }
+ this.last_response = response;
+ break;
+ }
+ }
+
+ if(status_code > 100 && status_code <= 199 && this.state === C.STATUS_PROCEEDING) {
+ // Trigger the resendProvisionalTimer only for the first non 100 provisional response.
+ if(this.resendProvisionalTimer === null) {
+ this.resendProvisionalTimer = window.setInterval(function() {
+ tr.resend_provisional();}, JsSIP.Timers.PROVISIONAL_RESPONSE_INTERVAL);
+ }
+ } else if(status_code >= 200 && status_code <= 299) {
+ switch(this.state) {
+ case C.STATUS_PROCEEDING:
+ this.state = C.STATUS_ACCEPTED;
+ this.last_response = response;
+ this.L = window.setTimeout(function() {
+ tr.timer_L();
+ }, JsSIP.Timers.TIMER_L);
+ if (this.resendProvisionalTimer !== null) {
+ window.clearInterval(this.resendProvisionalTimer);
+ this.resendProvisionalTimer = null;
+ }
+ /* falls through */
+ case C.STATUS_ACCEPTED:
+ // Note that this point will be reached for proceeding tr.state also.
+ if(!this.transport.send(response)) {
+ this.onTransportError();
+ if (onFailure) {
+ onFailure();
+ }
+ } else if (onSuccess) {
+ onSuccess();
+ }
+ break;
+ }
+ } else if(status_code >= 300 && status_code <= 699) {
+ switch(this.state) {
+ case C.STATUS_PROCEEDING:
+ if (this.resendProvisionalTimer !== null) {
+ window.clearInterval(this.resendProvisionalTimer);
+ this.resendProvisionalTimer = null;
+ }
+ if(!this.transport.send(response)) {
+ this.onTransportError();
+ if (onFailure) {
+ onFailure();
+ }
+ } else {
+ this.state = C.STATUS_COMPLETED;
+ this.H = window.setTimeout(function() {
+ tr.timer_H();
+ }, JsSIP.Timers.TIMER_H);
+ if (onSuccess) {
+ onSuccess();
+ }
+ }
+ break;
+ }
+ }
+ };
+};
+InviteServerTransactionPrototype.prototype = new ServerTransaction();
+
+/**
+* @augments JsSIP.Transactions
+* @class Non Invite Client Transaction
+* @param {JsSIP.RequestSender} request_sender
+* @param {JsSIP.OutgoingRequest} request
+* @param {JsSIP.Transport} transport
+*/
+Transactions.NonInviteClientTransaction = function(request_sender, request, transport) {
+ this.init(request_sender, request, transport);
+ this.request_sender.ua.transactions.nict[this.id] = this;
+};
+Transactions.NonInviteClientTransaction.prototype = new NonInviteClientTransactionPrototype();
+
+/**
+* @augments JsSIP.Transactions
+* @class Invite Client Transaction
+* @param {JsSIP.RequestSender} request_sender
+* @param {JsSIP.OutgoingRequest} request
+* @param {JsSIP.Transport} transport
+*/
+Transactions.InviteClientTransaction = function(request_sender, request, transport) {
+ var tr = this;
+
+ this.init(request_sender, request, transport);
+ this.request_sender.ua.transactions.ict[this.id] = this;
+
+ // Add the cancel property to the request.
+ //Will be called from the request instance, not the transaction itself.
+ this.request.cancel = function(reason) {
+ tr.cancel_request(tr, reason);
+ };
+};
+Transactions.InviteClientTransaction.prototype = new InviteClientTransactionPrototype();
+
+Transactions.AckClientTransaction = function(request_sender, request, transport) {
+ this.init(request_sender, request, transport);
+ this.send = function() {
+ this.transport.send(request);
+ };
+};
+Transactions.AckClientTransaction.prototype = new NonInviteClientTransactionPrototype();
+
+
+/**
+* @augments JsSIP.Transactions
+* @class Non Invite Server Transaction
+* @param {JsSIP.IncomingRequest} request
+* @param {JsSIP.UA} ua
+*/
+Transactions.NonInviteServerTransaction = function(request, ua) {
+ this.init(request, ua);
+ this.state = C.STATUS_TRYING;
+
+ ua.transactions.nist[this.id] = this;
+};
+Transactions.NonInviteServerTransaction.prototype = new NonInviteServerTransactionPrototype();
+
+
+
+/**
+* @augments JsSIP.Transactions
+* @class Invite Server Transaction
+* @param {JsSIP.IncomingRequest} request
+* @param {JsSIP.UA} ua
+*/
+Transactions.InviteServerTransaction = function(request, ua) {
+ this.init(request, ua);
+ this.state = C.STATUS_PROCEEDING;
+
+ ua.transactions.ist[this.id] = this;
+
+ this.resendProvisionalTimer = null;
+
+ request.reply(100);
+};
+Transactions.InviteServerTransaction.prototype = new InviteServerTransactionPrototype();
+
+/**
+ * @function
+ * @param {JsSIP.UA} ua
+ * @param {JsSIP.IncomingRequest} request
+ *
+ * @return {boolean}
+ * INVITE:
+ * _true_ if retransmission
+ * _false_ new request
+ *
+ * ACK:
+ * _true_ ACK to non2xx response
+ * _false_ ACK must be passed to TU (accepted state)
+ * ACK to 2xx response
+ *
+ * CANCEL:
+ * _true_ no matching invite transaction
+ * _false_ matching invite transaction and no final response sent
+ *
+ * OTHER:
+ * _true_ retransmission
+ * _false_ new request
+ */
+Transactions.checkTransaction = function(ua, request) {
+ var tr;
+
+ switch(request.method) {
+ case JsSIP.C.INVITE:
+ tr = ua.transactions.ist[request.via_branch];
+ if(tr) {
+ switch(tr.state) {
+ case C.STATUS_PROCEEDING:
+ tr.transport.send(tr.last_response);
+ break;
+
+ // RFC 6026 7.1 Invite retransmission
+ //received while in C.STATUS_ACCEPTED state. Absorb it.
+ case C.STATUS_ACCEPTED:
+ break;
+ }
+ return true;
+ }
+ break;
+ case JsSIP.C.ACK:
+ tr = ua.transactions.ist[request.via_branch];
+
+ // RFC 6026 7.1
+ if(tr) {
+ if(tr.state === C.STATUS_ACCEPTED) {
+ return false;
+ } else if(tr.state === C.STATUS_COMPLETED) {
+ tr.state = C.STATUS_CONFIRMED;
+ tr.I = window.setTimeout(function() {tr.timer_I();}, JsSIP.Timers.TIMER_I);
+ return true;
+ }
+ }
+
+ // ACK to 2XX Response.
+ else {
+ return false;
+ }
+ break;
+ case JsSIP.C.CANCEL:
+ tr = ua.transactions.ist[request.via_branch];
+ if(tr) {
+ request.reply_sl(200);
+ if(tr.state === C.STATUS_PROCEEDING) {
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ request.reply_sl(481);
+ return true;
+ }
+ break;
+ default:
+
+ // Non-INVITE Server Transaction RFC 3261 17.2.2
+ tr = ua.transactions.nist[request.via_branch];
+ if(tr) {
+ switch(tr.state) {
+ case C.STATUS_TRYING:
+ break;
+ case C.STATUS_PROCEEDING:
+ case C.STATUS_COMPLETED:
+ tr.transport.send(tr.last_response);
+ break;
+ }
+ return true;
+ }
+ break;
+ }
+};
+
+Transactions.C = C;
+JsSIP.Transactions = Transactions;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview SIP Dialog
+ */
+
+/**
+ * @augments JsSIP
+ * @class Class creating a SIP dialog.
+ * @param {JsSIP.Session} session
+ * @param {JsSIP.IncomingRequest|JsSIP.IncomingResponse} message
+ * @param {Enum} type UAC / UAS
+ * @param {Enum} state JsSIP.Dialog.C.STATUS_EARLY / JsSIP.Dialog.C.STATUS_CONFIRMED
+ */
+(function(JsSIP) {
+var Dialog,
+ LOG_PREFIX = JsSIP.name +' | '+ 'DIALOG' +' | ',
+ C = {
+ // Dialog states
+ STATUS_EARLY: 1,
+ STATUS_CONFIRMED: 2
+ };
+
+// RFC 3261 12.1
+Dialog = function(session, message, type, state) {
+ var contact;
+
+ if(!message.hasHeader('contact')) {
+ console.error(LOG_PREFIX +'unable to create a Dialog without Contact header field');
+ return false;
+ }
+
+ if(message instanceof JsSIP.IncomingResponse) {
+ state = (message.status_code < 200) ? C.STATUS_EARLY : C.STATUS_CONFIRMED;
+ } else {
+ // Create confirmed dialog if state is not defined
+ state = state || C.STATUS_CONFIRMED;
+ }
+
+ contact = message.parseHeader('contact');
+
+ // RFC 3261 12.1.1
+ if(type === 'UAS') {
+ this.id = {
+ call_id: message.call_id,
+ local_tag: message.to_tag,
+ remote_tag: message.from_tag,
+ toString: function() {
+ return this.call_id + this.local_tag + this.remote_tag;
+ }
+ };
+ this.state = state;
+ this.remote_seqnum = message.cseq;
+ this.local_uri = message.parseHeader('to').uri;
+ this.remote_uri = message.parseHeader('from').uri;
+ this.remote_target = contact.uri;
+ this.route_set = message.getHeaderAll('record-route');
+ }
+ // RFC 3261 12.1.2
+ else if(type === 'UAC') {
+ this.id = {
+ call_id: message.call_id,
+ local_tag: message.from_tag,
+ remote_tag: message.to_tag,
+ toString: function() {
+ return this.call_id + this.local_tag + this.remote_tag;
+ }
+ };
+ this.state = state;
+ this.local_seqnum = message.cseq;
+ this.local_uri = message.parseHeader('from').uri;
+ this.remote_uri = message.parseHeader('to').uri;
+ this.remote_target = contact.uri;
+ this.route_set = message.getHeaderAll('record-route').reverse();
+ }
+
+ this.session = session;
+ session.ua.dialogs[this.id.toString()] = this;
+ console.log(LOG_PREFIX +'new ' + type + ' dialog created with status ' + (this.state === C.STATUS_EARLY ? 'EARLY': 'CONFIRMED'));
+};
+
+Dialog.prototype = {
+ /**
+ * @param {JsSIP.IncomingMessage} message
+ * @param {Enum} UAC/UAS
+ */
+ update: function(message, type) {
+ this.state = C.STATUS_CONFIRMED;
+
+ console.log(LOG_PREFIX +'dialog '+ this.id.toString() +' changed to CONFIRMED state');
+
+ if(type === 'UAC') {
+ // RFC 3261 13.2.2.4
+ this.route_set = message.getHeaderAll('record-route').reverse();
+ }
+ },
+
+ terminate: function() {
+ console.log(LOG_PREFIX +'dialog ' + this.id.toString() + ' deleted');
+ delete this.session.ua.dialogs[this.id.toString()];
+ },
+
+ /**
+ * @param {String} method request method
+ * @param {Object} extraHeaders extra headers
+ * @returns {JsSIP.OutgoingRequest}
+ */
+
+ // RFC 3261 12.2.1.1
+ createRequest: function(method, extraHeaders) {
+ var cseq, request;
+ extraHeaders = extraHeaders || [];
+
+ if(!this.local_seqnum) { this.local_seqnum = Math.floor(Math.random() * 10000); }
+
+ cseq = (method === JsSIP.C.CANCEL || method === JsSIP.C.ACK) ? this.local_seqnum : this.local_seqnum += 1;
+
+ request = new JsSIP.OutgoingRequest(
+ method,
+ this.remote_target,
+ this.session.ua, {
+ 'cseq': cseq,
+ 'call_id': this.id.call_id,
+ 'from_uri': this.local_uri,
+ 'from_tag': this.id.local_tag,
+ 'to_uri': this.remote_uri,
+ 'to_tag': this.id.remote_tag,
+ 'route_set': this.route_set
+ }, extraHeaders);
+
+ request.dialog = this;
+
+ return request;
+ },
+
+ /**
+ * @param {JsSIP.IncomingRequest} request
+ * @returns {Boolean}
+ */
+
+ // RFC 3261 12.2.2
+ checkInDialogRequest: function(request) {
+ if(!this.remote_seqnum) {
+ this.remote_seqnum = request.cseq;
+ } else if(request.method !== JsSIP.C.INVITE && request.cseq < this.remote_seqnum) {
+ //Do not try to reply to an ACK request.
+ if (request.method !== JsSIP.C.ACK) {
+ request.reply(500);
+ }
+ return false;
+ } else if(request.cseq > this.remote_seqnum) {
+ this.remote_seqnum = request.cseq;
+ }
+
+ switch(request.method) {
+ // RFC3261 14.2 Modifying an Existing Session -UAS BEHAVIOR-
+ case JsSIP.C.INVITE:
+ if(request.cseq < this.remote_seqnum) {
+ if(this.state === C.STATUS_EARLY) {
+ var retryAfter = (Math.random() * 10 | 0) + 1;
+ request.reply(500, null, ['Retry-After:'+ retryAfter]);
+ } else {
+ request.reply(500);
+ }
+ return false;
+ }
+ // RFC3261 14.2
+ if(this.state === C.STATUS_EARLY) {
+ request.reply(491);
+ return false;
+ }
+ // RFC3261 12.2.2 Replace the dialog`s remote target URI
+ if(request.hasHeader('contact')) {
+ this.remote_target = request.parseHeader('contact').uri;
+ }
+ break;
+ case JsSIP.C.NOTIFY:
+ // RFC6655 3.2 Replace the dialog`s remote target URI
+ if(request.hasHeader('contact')) {
+ this.remote_target = request.parseHeader('contact').uri;
+ }
+ break;
+ }
+
+ return true;
+ },
+
+ /**
+ * @param {JsSIP.IncomingRequest} request
+ */
+ receiveRequest: function(request) {
+ //Check in-dialog request
+ if(!this.checkInDialogRequest(request)) {
+ return;
+ }
+
+ this.session.receiveRequest(request);
+ }
+};
+
+Dialog.C = C;
+JsSIP.Dialog = Dialog;
+}(JsSIP));
+
+
+
+
+/**
+ * @fileoverview Request Sender
+ */
+
+/**
+ * @augments JsSIP
+ * @class Class creating a request sender.
+ * @param {Object} applicant
+ * @param {JsSIP.UA} ua
+ */
+(function(JsSIP) {
+var RequestSender,
+ LOG_PREFIX = JsSIP.name +' | '+ 'REQUEST SENDER' +' | ';
+
+RequestSender = function(applicant, ua) {
+ this.ua = ua;
+ this.applicant = applicant;
+ this.method = applicant.request.method;
+ this.request = applicant.request;
+ this.credentials = null;
+ this.challenged = false;
+ this.staled = false;
+
+ // If ua is in closing process or even closed just allow sending Bye and ACK
+ if (ua.status === JsSIP.UA.C.STATUS_USER_CLOSED && (this.method !== JsSIP.C.BYE || this.method !== JsSIP.C.ACK)) {
+ this.onTransportError();
+ }
+};
+
+/**
+* Create the client transaction and send the message.
+*/
+RequestSender.prototype = {
+ send: function() {
+ switch(this.method) {
+ case "INVITE":
+ this.clientTransaction = new JsSIP.Transactions.InviteClientTransaction(this, this.request, this.ua.transport);
+ break;
+ case "ACK":
+ this.clientTransaction = new JsSIP.Transactions.AckClientTransaction(this, this.request, this.ua.transport);
+ break;
+ default:
+ this.clientTransaction = new JsSIP.Transactions.NonInviteClientTransaction(this, this.request, this.ua.transport);
+ }
+ this.clientTransaction.send();
+ },
+
+ /**
+ * Callback fired when receiving a request timeout error from the client transaction.
+ * To be re-defined by the applicant.
+ * @event
+ */
+ onRequestTimeout: function() {
+ this.applicant.onRequestTimeout();
+ },
+
+ /**
+ * Callback fired when receiving a transport error from the client transaction.
+ * To be re-defined by the applicant.
+ * @event
+ */
+ onTransportError: function() {
+ this.applicant.onTransportError();
+ },
+
+ /**
+ * Called from client transaction when receiving a correct response to the request.
+ * Authenticate request if needed or pass the response back to the applicant.
+ * @param {JsSIP.IncomingResponse} response
+ */
+ receiveResponse: function(response) {
+ var cseq, challenge, authorization_header_name,
+ status_code = response.status_code;
+
+ /*
+ * Authentication
+ * Authenticate once. _challenged_ flag used to avoid infinite authentications.
+ */
+ if ((status_code === 401 || status_code === 407) && this.ua.configuration.password !== null) {
+
+ // Get and parse the appropriate WWW-Authenticate or Proxy-Authenticate header.
+ if (response.status_code === 401) {
+ challenge = response.parseHeader('www-authenticate');
+ authorization_header_name = 'authorization';
+ } else {
+ challenge = response.parseHeader('proxy-authenticate');
+ authorization_header_name = 'proxy-authorization';
+ }
+
+ // Verify it seems a valid challenge.
+ if (! challenge) {
+ console.warn(LOG_PREFIX + response.status_code + ' with wrong or missing challenge, cannot authenticate');
+ this.applicant.receiveResponse(response);
+ return;
+ }
+
+ if (!this.challenged || (!this.staled && challenge.stale === true)) {
+ if (!this.credentials) {
+ this.credentials = new JsSIP.DigestAuthentication(this.ua);
+ }
+
+ // Verify that the challenge is really valid.
+ if (!this.credentials.authenticate(this.request, challenge)) {
+ this.applicant.receiveResponse(response);
+ return;
+ }
+ this.challenged = true;
+
+ if (challenge.stale) {
+ this.staled = true;
+ }
+
+ if (response.method === JsSIP.C.REGISTER) {
+ cseq = this.applicant.cseq += 1;
+ } else if (this.request.dialog){
+ cseq = this.request.dialog.local_seqnum += 1;
+ } else {
+ cseq = this.request.cseq + 1;
+ this.request.cseq = cseq;
+ }
+ this.request.setHeader('cseq', cseq +' '+ this.method);
+
+ this.request.setHeader(authorization_header_name, this.credentials.toString());
+ this.send();
+ } else {
+ this.applicant.receiveResponse(response);
+ }
+ } else {
+ this.applicant.receiveResponse(response);
+ }
+ }
+};
+
+JsSIP.RequestSender = RequestSender;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview In-Dialog Request Sender
+ */
+
+/**
+ * @augments JsSIP
+ * @class Class creating an In-dialog request sender.
+ * @param {Object} applicant
+ */
+/**
+ * @fileoverview in-Dialog Request Sender
+ */
+
+(function(JsSIP) {
+var InDialogRequestSender;
+
+InDialogRequestSender = function(applicant) {
+ this.applicant = applicant;
+ this.request = applicant.request;
+};
+
+InDialogRequestSender.prototype = {
+ send: function() {
+ var request_sender = new JsSIP.RequestSender(this, this.applicant.session.ua);
+ request_sender.send();
+ },
+
+ onRequestTimeout: function() {
+ this.applicant.session.onRequestTimeout();
+ this.applicant.onRequestTimeout();
+ },
+
+ onTransportError: function() {
+ this.applicant.session.onTransportError();
+ this.applicant.onTransportError();
+ },
+
+ receiveResponse: function(response) {
+ // RFC3261 14.1. Terminate the dialog if a 408 or 481 is received from a re-Invite.
+ if (response.status_code === 408 || response.status_code === 481) {
+ this.applicant.session.ended('remote', response, JsSIP.C.causes.DIALOG_ERROR);
+ }
+ this.applicant.receiveResponse(response);
+ }
+};
+
+JsSIP.InDialogRequestSender = InDialogRequestSender;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview Registrator Agent
+ */
+
+/**
+ * @augments JsSIP
+ * @class Class creating a registrator agent.
+ * @param {JsSIP.UA} ua
+ * @param {JsSIP.Transport} transport
+ */
+(function(JsSIP) {
+var Registrator,
+ LOG_PREFIX = JsSIP.name +' | '+ 'REGISTRATOR' +' | ';
+
+Registrator = function(ua, transport) {
+ var reg_id=1; //Force reg_id to 1.
+
+ this.ua = ua;
+ this.transport = transport;
+
+ this.registrar = ua.configuration.registrar_server;
+ this.expires = ua.configuration.register_expires;
+
+ // Call-ID and CSeq values RFC3261 10.2
+ this.call_id = JsSIP.Utils.createRandomToken(22);
+ this.cseq = 80;
+
+ // this.to_uri
+ this.to_uri = ua.configuration.uri;
+
+ this.registrationTimer = null;
+
+ // Set status
+ this.registered = this.registered_before = false;
+
+ // Save into ua instance
+ this.ua.registrator = this;
+
+ // Contact header
+ this.contact = this.ua.contact.toString();
+
+ if(reg_id) {
+ this.contact += ';reg-id='+ reg_id;
+ this.contact += ';+sip.instance=""';
+ }
+};
+
+Registrator.prototype = {
+ /**
+ * @param {Object} [options]
+ */
+ register: function(options) {
+ var request_sender, cause, extraHeaders,
+ self = this;
+
+ options = options || {};
+ extraHeaders = options.extraHeaders || [];
+ extraHeaders.push('Contact: '+ this.contact + ';expires=' + this.expires);
+ extraHeaders.push('Allow: '+ JsSIP.Utils.getAllowedMethods(this.ua));
+
+ this.request = new JsSIP.OutgoingRequest(JsSIP.C.REGISTER, this.registrar, this.ua, {
+ 'to_uri': this.to_uri,
+ 'call_id': this.call_id,
+ 'cseq': (this.cseq += 1)
+ }, extraHeaders);
+
+ request_sender = new JsSIP.RequestSender(this, this.ua);
+
+ /**
+ * @private
+ */
+ this.receiveResponse = function(response) {
+ var contact, expires,
+ contacts = response.countHeader('contact');
+
+ // Discard responses to older REGISTER/un-REGISTER requests.
+ if(response.cseq !== this.cseq) {
+ return;
+ }
+
+ // Clear registration timer
+ if (this.registrationTimer !== null) {
+ window.clearTimeout(this.registrationTimer);
+ this.registrationTimer = null;
+ }
+
+ switch(true) {
+ case /^1[0-9]{2}$/.test(response.status_code):
+ // Ignore provisional responses.
+ break;
+ case /^2[0-9]{2}$/.test(response.status_code):
+ if(response.hasHeader('expires')) {
+ expires = response.getHeader('expires');
+ }
+
+ // Search the Contact pointing to us and update the expires value accordingly.
+ if (!contacts) {
+ console.warn(LOG_PREFIX +'no Contact header in response to REGISTER, response ignored');
+ break;
+ }
+
+ while(contacts--) {
+ contact = response.parseHeader('contact', contacts);
+ if(contact.uri.user === this.ua.contact.uri.user) {
+ expires = contact.getParam('expires');
+ break;
+ } else {
+ contact = null;
+ }
+ }
+
+ if (!contact) {
+ console.warn(LOG_PREFIX +'no Contact header pointing to us, response ignored');
+ break;
+ }
+
+ if(!expires) {
+ expires = this.expires;
+ }
+
+ // Re-Register before the expiration interval has elapsed.
+ // For that, decrease the expires value. ie: 3 seconds
+ this.registrationTimer = window.setTimeout(function() {
+ self.registrationTimer = null;
+ self.register();
+ }, (expires * 1000) - 3000);
+
+ //Save gruu values
+ if (contact.hasParam('temp-gruu')) {
+ this.ua.contact.temp_gruu = contact.getParam('temp-gruu').replace(/"/g,'');
+ }
+ if (contact.hasParam('pub-gruu')) {
+ this.ua.contact.pub_gruu = contact.getParam('pub-gruu').replace(/"/g,'');
+ }
+
+ this.registered = true;
+ this.ua.emit('registered', this.ua, {
+ response: response
+ });
+ break;
+ // Interval too brief RFC3261 10.2.8
+ case /^423$/.test(response.status_code):
+ if(response.hasHeader('min-expires')) {
+ // Increase our registration interval to the suggested minimum
+ this.expires = response.getHeader('min-expires');
+ // Attempt the registration again immediately
+ this.register();
+ } else { //This response MUST contain a Min-Expires header field
+ console.warn(LOG_PREFIX +'423 response received for REGISTER without Min-Expires');
+ this.registrationFailure(response, JsSIP.C.causes.SIP_FAILURE_CODE);
+ }
+ break;
+ default:
+ cause = JsSIP.Utils.sipErrorCause(response.status_code);
+ this.registrationFailure(response, cause);
+ }
+ };
+
+ /**
+ * @private
+ */
+ this.onRequestTimeout = function() {
+ this.registrationFailure(null, JsSIP.C.causes.REQUEST_TIMEOUT);
+ };
+
+ /**
+ * @private
+ */
+ this.onTransportError = function() {
+ this.registrationFailure(null, JsSIP.C.causes.CONNECTION_ERROR);
+ };
+
+ request_sender.send();
+ },
+
+ /**
+ * @param {Object} [options]
+ */
+ unregister: function(options) {
+ var extraHeaders;
+
+ if(!this.registered) {
+ console.warn(LOG_PREFIX +'already unregistered');
+ return;
+ }
+
+ options = options || {};
+ extraHeaders = options.extraHeaders || [];
+
+ this.registered = false;
+
+ // Clear the registration timer.
+ if (this.registrationTimer !== null) {
+ window.clearTimeout(this.registrationTimer);
+ this.registrationTimer = null;
+ }
+
+ if(options.all) {
+ extraHeaders.push('Contact: *');
+ extraHeaders.push('Expires: 0');
+
+ this.request = new JsSIP.OutgoingRequest(JsSIP.C.REGISTER, this.registrar, this.ua, {
+ 'to_uri': this.to_uri,
+ 'call_id': this.call_id,
+ 'cseq': (this.cseq += 1)
+ }, extraHeaders);
+ } else {
+ extraHeaders.push('Contact: '+ this.contact + ';expires=0');
+
+ this.request = new JsSIP.OutgoingRequest(JsSIP.C.REGISTER, this.registrar, this.ua, {
+ 'to_uri': this.to_uri,
+ 'call_id': this.call_id,
+ 'cseq': (this.cseq += 1)
+ }, extraHeaders);
+ }
+
+ var request_sender = new JsSIP.RequestSender(this, this.ua);
+
+ /**
+ * @private
+ */
+ this.receiveResponse = function(response) {
+ var cause;
+
+ switch(true) {
+ case /^1[0-9]{2}$/.test(response.status_code):
+ // Ignore provisional responses.
+ break;
+ case /^2[0-9]{2}$/.test(response.status_code):
+ this.unregistered(response);
+ break;
+ default:
+ cause = JsSIP.Utils.sipErrorCause(response.status_code);
+ this.unregistered(response, cause);
+ }
+ };
+
+ /**
+ * @private
+ */
+ this.onRequestTimeout = function() {
+ this.unregistered(null, JsSIP.C.causes.REQUEST_TIMEOUT);
+ };
+
+ /**
+ * @private
+ */
+ this.onTransportError = function() {
+ this.unregistered(null, JsSIP.C.causes.CONNECTION_ERROR);
+ };
+
+ request_sender.send();
+ },
+
+ /**
+ * @private
+ */
+ registrationFailure: function(response, cause) {
+ this.ua.emit('registrationFailed', this.ua, {
+ response: response || null,
+ cause: cause
+ });
+
+ if (this.registered) {
+ this.registered = false;
+ this.ua.emit('unregistered', this.ua, {
+ response: response || null,
+ cause: cause
+ });
+ }
+ },
+
+ /**
+ * @private
+ */
+ unregistered: function(response, cause) {
+ this.registered = false;
+ this.ua.emit('unregistered', this.ua, {
+ response: response || null,
+ cause: cause || null
+ });
+ },
+
+ /**
+ * @private
+ */
+ onTransportClosed: function() {
+ this.registered_before = this.registered;
+ if (this.registrationTimer !== null) {
+ window.clearTimeout(this.registrationTimer);
+ this.registrationTimer = null;
+ }
+
+ if(this.registered) {
+ this.registered = false;
+ this.ua.emit('unregistered', this.ua);
+ }
+ },
+
+ /**
+ * @private
+ */
+ onTransportConnected: function() {
+ this.register();
+ },
+
+ /**
+ * @private
+ */
+ close: function() {
+ this.registered_before = this.registered;
+ this.unregister();
+ }
+};
+
+JsSIP.Registrator = Registrator;
+}(JsSIP));
+
+
+/**
+ * @fileoverview Session
+ */
+
+/**
+ * @augments JsSIP
+ * @class Invite Session
+ */
+(function(JsSIP) {
+
+// Load dependencies
+var RequestSender = /**
+ * @fileoverview RequestSender
+ */
+
+/**
+ * @class Session RequestSender
+ * @param {JsSIP.RTCSession | RTCSession applicant} applicant
+ * @param {JsSIP.OutgoingRequest} [request]
+ */
+(function(JsSIP){
+
+var RequestSender = function(applicant, request) {
+ this.applicant = applicant;
+ this.request = request || applicant.request;
+ this.session = (applicant instanceof JsSIP.RTCSession)? applicant : applicant.session;
+ this.reattempt = false;
+ this.reatemptTimer = null;
+ this.request_sender = new JsSIP.InDialogRequestSender(this);
+};
+
+RequestSender.prototype = {
+ receiveResponse: function(response) {
+ var
+ self = this,
+ status_code = response.status_code;
+
+ if (response.method === JsSIP.C.INVITE && status_code === 491) {
+ if (!this.reattempt) {
+ this.request.cseq.value = this.request.dialog.local_seqnum += 1;
+ this.reatemptTimer = window.setTimeout(
+ function() {
+ if (self.session.status !== JsSIP.RTCSession.C.STATUS_TERMINATED) {
+ self.reattempt = true;
+ self.request_sender.send();
+ }
+ },
+ this.getReattemptTimeout()
+ );
+ } else {
+ this.applicant.receiveResponse(response);
+ }
+ } else {
+ this.applicant.receiveResponse(response);
+ }
+ },
+
+ send: function() {
+ this.request_sender.send();
+ },
+
+ onRequestTimeout: function() {
+ this.applicant.onRequestTimeout();
+ },
+
+ onTransportError: function() {
+ this.applicant.onTransportError();
+ },
+
+ // RFC3261 14.1
+ getReattemptTimeout: function() {
+ if(this.session.direction === 'outgoing') {
+ return (Math.random() * (4 - 2.1) + 2.1).toFixed(2);
+ } else {
+ return (Math.random() * 2).toFixed(2);
+ }
+ }
+};
+
+return RequestSender;
+}(JsSIP));
+
+var RTCMediaHandler = /**
+ * @fileoverview RTCMediaHandler
+ */
+
+/* RTCMediaHandler
+ * @class PeerConnection helper Class.
+ * @param {JsSIP.RTCSession} session
+ * @param {Object} [contraints]
+ */
+(function(JsSIP){
+
+var RTCMediaHandler = function(session, constraints) {
+ constraints = constraints || {};
+
+ this.session = session;
+ this.localMedia = null;
+ this.peerConnection = null;
+
+ this.init(constraints);
+};
+
+RTCMediaHandler.prototype = {
+
+ createOffer: function(onSuccess, onFailure) {
+ var
+ self = this,
+ sent = false;
+
+ this.onIceCompleted = function() {
+ if (!sent) {
+ sent = true;
+ onSuccess(self.peerConnection.localDescription.sdp);
+ }
+ };
+
+ this.peerConnection.createOffer(
+ function(sessionDescription){
+ self.setLocalDescription(
+ sessionDescription,
+ onFailure
+ );
+ },
+ function(e) {
+ console.error(LOG_PREFIX +'unable to create offer');
+ console.error(e);
+ onFailure();
+ }
+ );
+ },
+
+ createAnswer: function(onSuccess, onFailure) {
+ var
+ self = this,
+ sent = false;
+
+ this.onIceCompleted = function() {
+ if (!sent) {
+ sent = true;
+ onSuccess(self.peerConnection.localDescription.sdp);
+ }
+ };
+
+ this.peerConnection.createAnswer(
+ function(sessionDescription){
+ self.setLocalDescription(
+ sessionDescription,
+ onFailure
+ );
+ },
+ function(e) {
+ console.error(LOG_PREFIX +'unable to create answer');
+ console.error(e);
+ onFailure();
+ }
+ );
+ },
+
+ setLocalDescription: function(sessionDescription, onFailure) {
+ this.peerConnection.setLocalDescription(
+ sessionDescription,
+ function(){},
+ function(e) {
+ console.error(LOG_PREFIX +'unable to set local description');
+ console.error(e);
+ onFailure();
+ }
+ );
+ },
+
+ addStream: function(stream, onSuccess, onFailure, constraints) {
+ try {
+ this.peerConnection.addStream(stream, constraints);
+ } catch(e) {
+ console.error(LOG_PREFIX +'error adding stream');
+ console.error(e);
+ onFailure();
+ return;
+ }
+
+ onSuccess();
+ },
+
+ /**
+ * peerConnection creation.
+ * @param {Function} onSuccess Fired when there are no more ICE candidates
+ */
+ init: function(constraints) {
+ var idx, length, server,
+ self = this,
+ servers = [],
+ config = this.session.ua.configuration;
+
+ servers.push({'url': config.stun_servers});
+
+ length = config.turn_servers.length;
+ for (idx = 0; idx < length; idx++) {
+ server = config.turn_servers[idx];
+ servers.push({
+ 'url': server.urls,
+ 'username': server.username,
+ 'credential': server.password
+ });
+ }
+
+ this.peerConnection = new JsSIP.WebRTC.RTCPeerConnection({'iceServers': servers}, constraints);
+
+ this.peerConnection.onaddstream = function(e) {
+ console.log(LOG_PREFIX +'stream added: '+ e.stream.id);
+ };
+
+ this.peerConnection.onremovestream = function(e) {
+ console.log(LOG_PREFIX +'stream removed: '+ e.stream.id);
+ };
+
+ this.peerConnection.onicecandidate = function(e) {
+ if (e.candidate) {
+ console.log(LOG_PREFIX +'ICE candidate received: '+ e.candidate.candidate);
+ } else if (self.onIceCompleted !== undefined) {
+ self.onIceCompleted();
+ }
+ };
+
+ // To be deprecated as per https://code.google.com/p/webrtc/issues/detail?id=1393
+ this.peerConnection.ongatheringchange = function(e) {
+ if (e.currentTarget.iceGatheringState === 'complete' && this.iceConnectionState !== 'closed') {
+ self.onIceCompleted();
+ }
+ };
+
+ this.peerConnection.onicechange = function() {
+ console.log(LOG_PREFIX +'ICE connection state changed to "'+ this.iceConnectionState +'"');
+ };
+
+ this.peerConnection.onstatechange = function() {
+ console.log(LOG_PREFIX +'PeerConnection state changed to "'+ this.readyState +'"');
+ };
+ },
+
+ close: function() {
+ console.log(LOG_PREFIX + 'closing PeerConnection');
+ if(this.peerConnection) {
+ this.peerConnection.close();
+
+ if(this.localMedia) {
+ this.localMedia.stop();
+ }
+ }
+ },
+
+ /**
+ * @param {Object} mediaConstraints
+ * @param {Function} onSuccess
+ * @param {Function} onFailure
+ */
+ getUserMedia: function(onSuccess, onFailure, constraints) {
+ var self = this;
+
+ console.log(LOG_PREFIX + 'requesting access to local media');
+
+ JsSIP.WebRTC.getUserMedia(constraints,
+ function(stream) {
+ console.log(LOG_PREFIX + 'got local media stream');
+ self.localMedia = stream;
+ onSuccess(stream);
+ },
+ function(e) {
+ console.error(LOG_PREFIX +'unable to get user media');
+ console.error(e);
+ onFailure();
+ }
+ );
+ },
+
+ /**
+ * Message reception.
+ * @param {String} type
+ * @param {String} sdp
+ * @param {Function} onSuccess
+ * @param {Function} onFailure
+ */
+ onMessage: function(type, body, onSuccess, onFailure) {
+ this.peerConnection.setRemoteDescription(
+ new JsSIP.WebRTC.RTCSessionDescription({type: type, sdp:body}),
+ onSuccess,
+ onFailure
+ );
+ }
+};
+
+// Return since it will be assigned to a variable.
+return RTCMediaHandler;
+}(JsSIP));
+
+var DTMF = /**
+ * @fileoverview DTMF
+ */
+
+/**
+ * @class DTMF
+ * @param {JsSIP.RTCSession} session
+ */
+(function(JsSIP) {
+
+var DTMF,
+ C = {
+ MIN_DURATION: 70,
+ MAX_DURATION: 6000,
+ DEFAULT_DURATION: 100,
+ MIN_INTER_TONE_GAP: 50,
+ DEFAULT_INTER_TONE_GAP: 500
+ };
+
+DTMF = function(session) {
+ var events = [
+ 'succeeded',
+ 'failed'
+ ];
+
+ this.session = session;
+ this.direction = null;
+ this.tone = null;
+ this.duration = null;
+
+ this.initEvents(events);
+};
+DTMF.prototype = new JsSIP.EventEmitter();
+
+
+DTMF.prototype.send = function(tone, options) {
+ var request_sender, event, eventHandlers, extraHeaders;
+
+ if (tone === undefined) {
+ throw new TypeError('Not enough arguments');
+ }
+
+ this.direction = 'outgoing';
+
+ // Check RTCSession Status
+ if (this.session.status !== JsSIP.RTCSession.C.STATUS_CONFIRMED && this.session.status !== JsSIP.RTCSession.C.STATUS_WAITING_FOR_ACK) {
+ throw new JsSIP.Exceptions.InvalidStateError(this.session.status);
+ }
+
+ // Get DTMF options
+ options = options || {};
+ extraHeaders = options.extraHeaders ? options.extraHeaders.slice() : [];
+ eventHandlers = options.eventHandlers || {};
+
+ // Check tone type
+ if (typeof tone === 'string' ) {
+ tone = tone.toUpperCase();
+ } else if (typeof tone === 'number') {
+ tone = tone.toString();
+ } else {
+ throw new TypeError('Invalid tone: '+ tone);
+ }
+
+ // Check tone value
+ if (!tone.match(/^[0-9A-D#*]$/)) {
+ throw new TypeError('Invalid tone: '+ tone);
+ } else {
+ this.tone = tone;
+ }
+
+ // Duration is checked/corrected in RTCSession
+ this.duration = options.duration;
+
+ // Set event handlers
+ for (event in eventHandlers) {
+ this.on(event, eventHandlers[event]);
+ }
+
+ extraHeaders.push('Content-Type: application/dtmf-relay');
+
+ this.request = this.session.dialog.createRequest(JsSIP.C.INFO, extraHeaders);
+
+ this.request.body = "Signal= " + this.tone + "\r\n";
+ this.request.body += "Duration= " + this.duration;
+
+ request_sender = new RequestSender(this);
+
+ this.session.emit('newDTMF', this.session, {
+ originator: 'local',
+ dtmf: this,
+ request: this.request
+ });
+
+ request_sender.send();
+};
+
+/**
+ * @private
+ */
+DTMF.prototype.receiveResponse = function(response) {
+ var cause;
+
+ switch(true) {
+ case /^1[0-9]{2}$/.test(response.status_code):
+ // Ignore provisional responses.
+ break;
+
+ case /^2[0-9]{2}$/.test(response.status_code):
+ this.emit('succeeded', this, {
+ originator: 'remote',
+ response: response
+ });
+ break;
+
+ default:
+ cause = JsSIP.Utils.sipErrorCause(response.status_code);
+ this.emit('failed', this, {
+ originator: 'remote',
+ response: response,
+ cause: cause
+ });
+ break;
+ }
+};
+
+/**
+ * @private
+ */
+DTMF.prototype.onRequestTimeout = function() {
+ this.emit('failed', this, {
+ originator: 'system',
+ cause: JsSIP.C.causes.REQUEST_TIMEOUT
+ });
+};
+
+/**
+ * @private
+ */
+DTMF.prototype.onTransportError = function() {
+ this.emit('failed', this, {
+ originator: 'system',
+ cause: JsSIP.C.causes.CONNECTION_ERROR
+ });
+};
+
+/**
+ * @private
+ */
+DTMF.prototype.init_incoming = function(request) {
+ var body,
+ reg_tone = /^(Signal\s*?=\s*?)([0-9A-D#*]{1})(\s)?.*/,
+ reg_duration = /^(Duration\s?=\s?)([0-9]{1,4})(\s)?.*/;
+
+ this.direction = 'incoming';
+ this.request = request;
+
+ request.reply(200);
+
+ if (request.body) {
+ body = request.body.split('\r\n');
+ if (body.length === 2) {
+ if (reg_tone.test(body[0])) {
+ this.tone = body[0].replace(reg_tone,"$2");
+ }
+ if (reg_duration.test(body[1])) {
+ this.duration = parseInt(body[1].replace(reg_duration,"$2"), 10);
+ }
+ }
+ }
+
+ if (!this.tone || !this.duration) {
+ console.warn(LOG_PREFIX +'invalid INFO DTMF received, discarded');
+ } else {
+ this.session.emit('newDTMF', this.session, {
+ originator: 'remote',
+ dtmf: this,
+ request: request
+ });
+ }
+};
+
+DTMF.C = C;
+return DTMF;
+}(JsSIP));
+
+
+var RTCSession,
+ LOG_PREFIX = JsSIP.name +' | '+ 'RTC SESSION' +' | ',
+ C = {
+ // RTCSession states
+ STATUS_NULL: 0,
+ STATUS_INVITE_SENT: 1,
+ STATUS_1XX_RECEIVED: 2,
+ STATUS_INVITE_RECEIVED: 3,
+ STATUS_WAITING_FOR_ANSWER: 4,
+ STATUS_ANSWERED: 5,
+ STATUS_WAITING_FOR_ACK: 6,
+ STATUS_CANCELED: 7,
+ STATUS_TERMINATED: 8,
+ STATUS_CONFIRMED: 9
+ };
+
+
+RTCSession = function(ua) {
+ var events = [
+ 'progress',
+ 'failed',
+ 'started',
+ 'ended',
+ 'newDTMF'
+ ];
+
+ this.ua = ua;
+ this.status = C.STATUS_NULL;
+ this.dialog = null;
+ this.earlyDialogs = {};
+ this.rtcMediaHandler = null;
+
+ // Session Timers
+ this.timers = {
+ ackTimer: null,
+ expiresTimer: null,
+ invite2xxTimer: null,
+ userNoAnswerTimer: null
+ };
+
+ // Session info
+ this.direction = null;
+ this.local_identity = null;
+ this.remote_identity = null;
+ this.start_time = null;
+ this.end_time = null;
+ this.tones = null;
+
+ // Custom session empty object for high level use
+ this.data = {};
+
+ this.initEvents(events);
+};
+RTCSession.prototype = new JsSIP.EventEmitter();
+
+
+/**
+ * User API
+ */
+
+/**
+ * Terminate the call.
+ * @param {Object} [options]
+ */
+RTCSession.prototype.terminate = function(options) {
+ options = options || {};
+
+ var cancel_reason,
+ status_code = options.status_code,
+ reason_phrase = options.reason_phrase,
+ extraHeaders = options.extraHeaders || [],
+ body = options.body;
+
+ // Check Session Status
+ if (this.status === C.STATUS_TERMINATED) {
+ throw new JsSIP.Exceptions.InvalidStateError(this.status);
+ }
+
+ switch(this.status) {
+ // - UAC -
+ case C.STATUS_NULL:
+ case C.STATUS_INVITE_SENT:
+ case C.STATUS_1XX_RECEIVED:
+ console.log(LOG_PREFIX +'canceling RTCSession');
+
+ if (status_code && (status_code < 200 || status_code >= 700)) {
+ throw new TypeError('Invalid status_code: '+ status_code);
+ } else if (status_code) {
+ reason_phrase = reason_phrase || JsSIP.C.REASON_PHRASE[status_code] || '';
+ cancel_reason = 'SIP ;cause=' + status_code + ' ;text="' + reason_phrase + '"';
+ }
+
+ // Check Session Status
+ if (this.status === C.STATUS_NULL) {
+ this.isCanceled = true;
+ this.cancelReason = cancel_reason;
+ } else if (this.status === C.STATUS_INVITE_SENT) {
+ if(this.received_100) {
+ this.request.cancel(cancel_reason);
+ } else {
+ this.isCanceled = true;
+ this.cancelReason = cancel_reason;
+ }
+ } else if(this.status === C.STATUS_1XX_RECEIVED) {
+ this.request.cancel(cancel_reason);
+ }
+
+ this.failed('local', null, JsSIP.C.causes.CANCELED);
+ break;
+
+ // - UAS -
+ case C.STATUS_WAITING_FOR_ANSWER:
+ case C.STATUS_ANSWERED:
+ console.log(LOG_PREFIX +'rejecting RTCSession');
+
+ status_code = status_code || 480;
+
+ if (status_code < 300 || status_code >= 700) {
+ throw new TypeError('Invalid status_code: '+ status_code);
+ }
+
+ this.request.reply(status_code, reason_phrase, extraHeaders, body);
+ this.failed('local', null, JsSIP.C.causes.REJECTED);
+ break;
+ case C.STATUS_WAITING_FOR_ACK:
+ case C.STATUS_CONFIRMED:
+ console.log(LOG_PREFIX +'terminating RTCSession');
+
+ // Send Bye
+ this.sendBye(options);
+ this.ended('local', null, JsSIP.C.causes.BYE);
+ break;
+ }
+
+ this.close();
+};
+
+/**
+ * Answer the call.
+ * @param {Object} [options]
+ */
+RTCSession.prototype.answer = function(options) {
+ options = options || {};
+
+ var
+ self = this,
+ request = this.request,
+ extraHeaders = options.extraHeaders || [],
+ mediaConstraints = options.mediaConstraints || {'audio':true, 'video':true},
+
+ // User media succeeded
+ userMediaSucceeded = function(stream) {
+ self.rtcMediaHandler.addStream(
+ stream,
+ streamAdditionSucceeded,
+ streamAdditionFailed
+ );
+ },
+
+ // User media failed
+ userMediaFailed = function() {
+ request.reply(480);
+ self.failed('local', null, JsSIP.C.causes.USER_DENIED_MEDIA_ACCESS);
+ },
+
+ // rtcMediaHandler.addStream successfully added
+ streamAdditionSucceeded = function() {
+ self.rtcMediaHandler.createAnswer(
+ answerCreationSucceeded,
+ answerCreationFailed
+ );
+ },
+
+ // rtcMediaHandler.addStream failed
+ streamAdditionFailed = function() {
+ if (self.status === C.STATUS_TERMINATED) {
+ return;
+ }
+
+ self.failed('local', null, JsSIP.C.causes.WEBRTC_ERROR);
+ },
+
+ // rtcMediaHandler.createAnswer succeeded
+ answerCreationSucceeded = function(body) {
+ var
+ // run for reply success callback
+ replySucceeded = function() {
+ var timeout = JsSIP.Timers.T1;
+
+ self.status = C.STATUS_WAITING_FOR_ACK;
+
+ /**
+ * RFC3261 13.3.1.4
+ * Response retransmissions cannot be accomplished by transaction layer
+ * since it is destroyed when receiving the first 2xx answer
+ */
+ self.timers.invite2xxTimer = window.setTimeout(function invite2xxRetransmission() {
+ if (self.status !== C.STATUS_WAITING_FOR_ACK) {
+ return;
+ }
+
+ request.reply(200, null, ['Contact: '+ self.contact], body);
+
+ if (timeout < JsSIP.Timers.T2) {
+ timeout = timeout * 2;
+ if (timeout > JsSIP.Timers.T2) {
+ timeout = JsSIP.Timers.T2;
+ }
+ }
+ self.timers.invite2xxTimer = window.setTimeout(
+ invite2xxRetransmission, timeout
+ );
+ },
+ timeout
+ );
+
+ /**
+ * RFC3261 14.2
+ * If a UAS generates a 2xx response and never receives an ACK,
+ * it SHOULD generate a BYE to terminate the dialog.
+ */
+ self.timers.ackTimer = window.setTimeout(function() {
+ if(self.status === C.STATUS_WAITING_FOR_ACK) {
+ console.log(LOG_PREFIX + 'no ACK received, terminating the call');
+ window.clearTimeout(self.timers.invite2xxTimer);
+ self.sendBye();
+ self.ended('remote', null, JsSIP.C.causes.NO_ACK);
+ }
+ },
+ JsSIP.Timers.TIMER_H
+ );
+
+ self.started('local');
+ },
+
+ // run for reply failure callback
+ replyFailed = function() {
+ self.failed('system', null, JsSIP.C.causes.CONNECTION_ERROR);
+ };
+
+ extraHeaders.push('Contact: ' + self.contact);
+
+ request.reply(200, null, extraHeaders,
+ body,
+ replySucceeded,
+ replyFailed
+ );
+ },
+
+ // rtcMediaHandler.createAnsewr failed
+ answerCreationFailed = function() {
+ if (self.status === C.STATUS_TERMINATED) {
+ return;
+ }
+
+ self.failed('local', null, JsSIP.C.causes.WEBRTC_ERROR);
+ };
+
+
+ // Check Session Direction and Status
+ if (this.direction !== 'incoming') {
+ throw new TypeError('Invalid method "answer" for an outgoing call');
+ } else if (this.status !== C.STATUS_WAITING_FOR_ANSWER) {
+ throw new JsSIP.Exceptions.InvalidStateError(this.status);
+ }
+
+ this.status = C.STATUS_ANSWERED;
+
+ // An error on dialog creation will fire 'failed' event
+ if(!this.createDialog(request, 'UAS')) {
+ request.reply(500, 'Missing Contact header field');
+ return;
+ }
+
+ window.clearTimeout(this.timers.userNoAnswerTimer);
+
+ this.rtcMediaHandler.getUserMedia(
+ userMediaSucceeded,
+ userMediaFailed,
+ mediaConstraints
+ );
+};
+
+/**
+ * Send a DTMF
+ *
+ * @param {String|Number} tones
+ * @param {Object} [options]
+ */
+RTCSession.prototype.sendDTMF = function(tones, options) {
+ var duration, interToneGap,
+ position = 0,
+ self = this;
+
+ options = options || {};
+ duration = options.duration || null;
+ interToneGap = options.interToneGap || null;
+
+ if (tones === undefined) {
+ throw new TypeError('Not enough arguments');
+ }
+
+ // Check Session Status
+ if (this.status !== C.STATUS_CONFIRMED && this.status !== C.STATUS_WAITING_FOR_ACK) {
+ throw new JsSIP.Exceptions.InvalidStateError(this.status);
+ }
+
+ // Check tones
+ if (!tones || (typeof tones !== 'string' && typeof tones !== 'number') || !tones.toString().match(/^[0-9A-D#*,]+$/i)) {
+ throw new TypeError('Invalid tones: '+ tones);
+ }
+
+ tones = tones.toString();
+
+ // Check duration
+ if (duration && !JsSIP.Utils.isDecimal(duration)) {
+ throw new TypeError('Invalid tone duration: '+ duration);
+ } else if (!duration) {
+ duration = DTMF.C.DEFAULT_DURATION;
+ } else if (duration < DTMF.C.MIN_DURATION) {
+ console.warn(LOG_PREFIX +'"duration" value is lower than the minimum allowed, setting it to '+ DTMF.C.MIN_DURATION+ ' milliseconds');
+ duration = DTMF.C.MIN_DURATION;
+ } else if (duration > DTMF.C.MAX_DURATION) {
+ console.warn(LOG_PREFIX +'"duration" value is greater than the maximum allowed, setting it to '+ DTMF.C.MAX_DURATION +' milliseconds');
+ duration = DTMF.C.MAX_DURATION;
+ } else {
+ duration = Math.abs(duration);
+ }
+ options.duration = duration;
+
+ // Check interToneGap
+ if (interToneGap && !JsSIP.Utils.isDecimal(interToneGap)) {
+ throw new TypeError('Invalid interToneGap: '+ interToneGap);
+ } else if (!interToneGap) {
+ interToneGap = DTMF.C.DEFAULT_INTER_TONE_GAP;
+ } else if (interToneGap < DTMF.C.MIN_INTER_TONE_GAP) {
+ console.warn(LOG_PREFIX +'"interToneGap" value is lower than the minimum allowed, setting it to '+ DTMF.C.MIN_INTER_TONE_GAP +' milliseconds');
+ interToneGap = DTMF.C.MIN_INTER_TONE_GAP;
+ } else {
+ interToneGap = Math.abs(interToneGap);
+ }
+
+ if (this.tones) {
+ // Tones are already queued, just add to the queue
+ this.tones += tones;
+ return;
+ }
+
+ // New set of tones to start sending
+ this.tones = tones;
+
+ var sendDTMF = function () {
+ var tone, timeout,
+ tones = self.tones;
+
+ if (self.status === C.STATUS_TERMINATED || !tones || position >= tones.length) {
+ // Stop sending DTMF
+ self.tones = null;
+ return;
+ }
+
+ tone = tones[position];
+ position += 1;
+
+ if (tone === ',') {
+ timeout = 2000;
+ } else {
+ var dtmf = new DTMF(self);
+ dtmf.on('failed', function(){self.tones = null;});
+ dtmf.send(tone, options);
+ timeout = duration + interToneGap;
+ }
+
+ // Set timeout for the next tone
+ window.setTimeout(sendDTMF, timeout);
+ };
+
+ // Send the first tone
+ sendDTMF();
+};
+
+
+/**
+ * RTCPeerconnection handlers
+ */
+RTCSession.prototype.getLocalStreams = function() {
+ return this.rtcMediaHandler &&
+ this.rtcMediaHandler.peerConnection &&
+ this.rtcMediaHandler.peerConnection.getLocalStreams() || [];
+};
+
+RTCSession.prototype.getRemoteStreams = function() {
+ return this.rtcMediaHandler &&
+ this.rtcMediaHandler.peerConnection &&
+ this.rtcMediaHandler.peerConnection.getRemoteStreams() || [];
+};
+
+
+/**
+ * Session Management
+ */
+
+/**
+* @private
+*/
+RTCSession.prototype.init_incoming = function(request) {
+ var expires,
+ self = this,
+ contentType = request.getHeader('Content-Type');
+
+ // Check body and content type
+ if(!request.body || (contentType !== 'application/sdp')) {
+ request.reply(415);
+ return;
+ }
+
+ // Session parameter initialization
+ this.status = C.STATUS_INVITE_RECEIVED;
+ this.from_tag = request.from_tag;
+ this.id = request.call_id + this.from_tag;
+ this.request = request;
+ this.contact = this.ua.contact.toString();
+
+ //Save the session into the ua sessions collection.
+ this.ua.sessions[this.id] = this;
+
+ //Get the Expires header value if exists
+ if(request.hasHeader('expires')) {
+ expires = request.getHeader('expires') * 1000;
+ }
+
+ /* Set the to_tag before
+ * replying a response code that will create a dialog.
+ */
+ request.to_tag = JsSIP.Utils.newTag();
+
+ // An error on dialog creation will fire 'failed' event
+ if(!this.createDialog(request, 'UAS', true)) {
+ request.reply(500, 'Missing Contact header field');
+ return;
+ }
+
+ //Initialize Media Session
+ this.rtcMediaHandler = new RTCMediaHandler(this,
+ {"optional": [{'DtlsSrtpKeyAgreement': 'true'}]}
+ );
+ this.rtcMediaHandler.onMessage(
+ 'offer',
+ request.body,
+ /*
+ * onSuccess
+ * SDP Offer is valid. Fire UA newRTCSession
+ */
+ function() {
+ request.reply(180, null, ['Contact: ' + self.contact]);
+ self.status = C.STATUS_WAITING_FOR_ANSWER;
+
+ // Set userNoAnswerTimer
+ self.timers.userNoAnswerTimer = window.setTimeout(function() {
+ request.reply(408);
+ self.failed('local',null, JsSIP.C.causes.NO_ANSWER);
+ }, self.ua.configuration.no_answer_timeout
+ );
+
+ /* Set expiresTimer
+ * RFC3261 13.3.1
+ */
+ if (expires) {
+ self.timers.expiresTimer = window.setTimeout(function() {
+ if(self.status === C.STATUS_WAITING_FOR_ANSWER) {
+ request.reply(487);
+ self.failed('system', null, JsSIP.C.causes.EXPIRES);
+ }
+ }, expires
+ );
+ }
+
+ self.newRTCSession('remote', request);
+ },
+ /*
+ * onFailure
+ * Bad media description
+ */
+ function(e) {
+ console.warn(LOG_PREFIX +'invalid SDP');
+ console.warn(e);
+ request.reply(488);
+ }
+ );
+};
+
+/**
+ * @private
+ */
+RTCSession.prototype.connect = function(target, options) {
+ options = options || {};
+
+ var event, requestParams,
+ invalidTarget = false,
+ eventHandlers = options.eventHandlers || {},
+ extraHeaders = options.extraHeaders || [],
+ mediaConstraints = options.mediaConstraints || {audio: true, video: true},
+ RTCConstraints = options.RTCConstraints || {};
+
+ if (target === undefined) {
+ throw new TypeError('Not enough arguments');
+ }
+
+ // Check Session Status
+ if (this.status !== C.STATUS_NULL) {
+ throw new JsSIP.Exceptions.InvalidStateError(this.status);
+ }
+
+ // Set event handlers
+ for (event in eventHandlers) {
+ this.on(event, eventHandlers[event]);
+ }
+
+ // Check target validity
+ try {
+ target = JsSIP.Utils.normalizeURI(target, this.ua.configuration.hostport_params);
+ } catch(e) {
+ target = JsSIP.URI.parse(JsSIP.C.INVALID_TARGET_URI);
+ invalidTarget = true;
+ }
+
+ // Session parameter initialization
+ this.from_tag = JsSIP.Utils.newTag();
+ this.rtcMediaHandler = new RTCMediaHandler(this, RTCConstraints);
+
+ // Set anonymous property
+ this.anonymous = options.anonymous;
+
+ // OutgoingSession specific parameters
+ this.isCanceled = false;
+ this.received_100 = false;
+
+ requestParams = {from_tag: this.from_tag};
+
+ this.contact = this.ua.contact.toString({
+ anonymous: this.anonymous,
+ outbound: true
+ });
+
+ if (this.anonymous) {
+ requestParams.from_display_name = 'Anonymous';
+ requestParams.from_uri = 'sip:anonymous@anonymous.invalid';
+
+ extraHeaders.push('P-Preferred-Identity: '+ this.ua.configuration.uri.toString());
+ extraHeaders.push('Privacy: id');
+ }
+
+ extraHeaders.push('Contact: '+ this.contact);
+ extraHeaders.push('Allow: '+ JsSIP.Utils.getAllowedMethods(this.ua));
+ extraHeaders.push('Content-Type: application/sdp');
+
+ this.request = new JsSIP.OutgoingRequest(JsSIP.C.INVITE, target, this.ua, requestParams, extraHeaders);
+
+ this.id = this.request.call_id + this.from_tag;
+
+ //Save the session into the ua sessions collection.
+ this.ua.sessions[this.id] = this;
+
+ this.newRTCSession('local', this.request);
+
+ if (invalidTarget) {
+ this.failed('local', null, JsSIP.C.causes.INVALID_TARGET);
+ } else if (!JsSIP.WebRTC.isSupported) {
+ this.failed('local', null, JsSIP.C.causes.WEBRTC_NOT_SUPPORTED);
+ } else {
+ this.sendInitialRequest(mediaConstraints);
+ }
+};
+
+/**
+* @private
+*/
+RTCSession.prototype.close = function() {
+ var idx;
+
+ if(this.status === C.STATUS_TERMINATED) {
+ return;
+ }
+
+ console.log(LOG_PREFIX +'closing INVITE session ' + this.id);
+
+ // 1st Step. Terminate media.
+ if (this.rtcMediaHandler){
+ this.rtcMediaHandler.close();
+ }
+
+ // 2nd Step. Terminate signaling.
+
+ // Clear session timers
+ for(idx in this.timers) {
+ window.clearTimeout(this.timers[idx]);
+ }
+
+ // Terminate dialogs
+
+ // Terminate confirmed dialog
+ if(this.dialog) {
+ this.dialog.terminate();
+ delete this.dialog;
+ }
+
+ // Terminate early dialogs
+ for(idx in this.earlyDialogs) {
+ this.earlyDialogs[idx].terminate();
+ delete this.earlyDialogs[idx];
+ }
+
+ this.status = C.STATUS_TERMINATED;
+
+ delete this.ua.sessions[this.id];
+};
+
+/**
+ * Dialog Management
+ * @private
+ */
+RTCSession.prototype.createDialog = function(message, type, early) {
+ var dialog, early_dialog,
+ local_tag = (type === 'UAS') ? message.to_tag : message.from_tag,
+ remote_tag = (type === 'UAS') ? message.from_tag : message.to_tag,
+ id = message.call_id + local_tag + remote_tag;
+
+ early_dialog = this.earlyDialogs[id];
+
+ // Early Dialog
+ if (early) {
+ if (early_dialog) {
+ return true;
+ } else {
+ early_dialog = new JsSIP.Dialog(this, message, type, JsSIP.Dialog.C.STATUS_EARLY);
+
+ // Dialog has been successfully created.
+ if(early_dialog.id) {
+ this.earlyDialogs[id] = early_dialog;
+ return true;
+ }
+ // Dialog not created due to an error.
+ else {
+ this.failed('remote', message, JsSIP.C.causes.INTERNAL_ERROR);
+ return false;
+ }
+ }
+ }
+
+ // Confirmed Dialog
+ else {
+ // In case the dialog is in _early_ state, update it
+ if (early_dialog) {
+ early_dialog.update(message, type);
+ this.dialog = early_dialog;
+ delete this.earlyDialogs[id];
+ return true;
+ }
+
+ // Otherwise, create a _confirmed_ dialog
+ dialog = new JsSIP.Dialog(this, message, type);
+
+ if(dialog.id) {
+ this.to_tag = message.to_tag;
+ this.dialog = dialog;
+ return true;
+ }
+ // Dialog not created due to an error
+ else {
+ this.failed('remote', message, JsSIP.C.causes.INTERNAL_ERROR);
+ return false;
+ }
+ }
+};
+
+
+/**
+ * In dialog Request Reception
+ * @private
+ */
+RTCSession.prototype.receiveRequest = function(request) {
+ var contentType;
+
+ if(request.method === JsSIP.C.CANCEL) {
+ /* RFC3261 15 States that a UAS may have accepted an invitation while a CANCEL
+ * was in progress and that the UAC MAY continue with the session established by
+ * any 2xx response, or MAY terminate with BYE. JsSIP does continue with the
+ * established session. So the CANCEL is processed only if the session is not yet
+ * established.
+ */
+
+ /*
+ * Terminate the whole session in case the user didn't accept nor reject the
+ *request opening the session.
+ */
+ if(this.status === C.STATUS_WAITING_FOR_ANSWER) {
+ this.status = C.STATUS_CANCELED;
+ this.request.reply(487);
+ this.failed('remote', request, JsSIP.C.causes.CANCELED);
+ }
+ } else {
+ // Requests arriving here are in-dialog requests.
+ switch(request.method) {
+ case JsSIP.C.ACK:
+ if(this.status === C.STATUS_WAITING_FOR_ACK) {
+ window.clearTimeout(this.timers.ackTimer);
+ window.clearTimeout(this.timers.invite2xxTimer);
+ this.status = C.STATUS_CONFIRMED;
+ }
+ break;
+ case JsSIP.C.BYE:
+ if(this.status === C.STATUS_CONFIRMED) {
+ request.reply(200);
+ this.ended('remote', request, JsSIP.C.causes.BYE);
+ }
+ break;
+ case JsSIP.C.INVITE:
+ if(this.status === C.STATUS_CONFIRMED) {
+ console.log(LOG_PREFIX +'re-INVITE received');
+ }
+ break;
+ case JsSIP.C.INFO:
+ if(this.status === C.STATUS_CONFIRMED || this.status === C.STATUS_WAITING_FOR_ACK) {
+ contentType = request.getHeader('content-type');
+ if (contentType && (contentType.match(/^application\/dtmf-relay/i))) {
+ new DTMF(this).init_incoming(request);
+ }
+ }
+ }
+ }
+};
+
+
+/**
+ * Initial Request Sender
+ * @private
+ */
+RTCSession.prototype.sendInitialRequest = function(constraints) {
+ var
+ self = this,
+ request_sender = new JsSIP.RequestSender(self, this.ua),
+
+ // User media succeeded
+ userMediaSucceeded = function(stream) {
+ self.rtcMediaHandler.addStream(
+ stream,
+ streamAdditionSucceeded,
+ streamAdditionFailed
+ );
+ },
+
+ // User media failed
+ userMediaFailed = function() {
+ if (self.status === C.STATUS_TERMINATED) {
+ return;
+ }
+
+ self.failed('local', null, JsSIP.C.causes.USER_DENIED_MEDIA_ACCESS);
+ },
+
+ // rtcMediaHandler.addStream successfully added
+ streamAdditionSucceeded = function() {
+ self.rtcMediaHandler.createOffer(
+ offerCreationSucceeded,
+ offerCreationFailed
+ );
+ },
+
+ // rtcMediaHandler.addStream failed
+ streamAdditionFailed = function() {
+ if (self.status === C.STATUS_TERMINATED) {
+ return;
+ }
+
+ self.failed('local', null, JsSIP.C.causes.WEBRTC_ERROR);
+ },
+
+ // rtcMediaHandler.createOffer succeeded
+ offerCreationSucceeded = function(offer) {
+ if (self.isCanceled || self.status === C.STATUS_TERMINATED) {
+ return;
+ }
+
+ self.request.body = offer;
+ self.status = C.STATUS_INVITE_SENT;
+ request_sender.send();
+ },
+
+ // rtcMediaHandler.createOffer failed
+ offerCreationFailed = function() {
+ if (self.status === C.STATUS_TERMINATED) {
+ return;
+ }
+
+ self.failed('local', null, JsSIP.C.causes.WEBRTC_ERROR);
+ };
+
+ this.rtcMediaHandler.getUserMedia(
+ userMediaSucceeded,
+ userMediaFailed,
+ constraints
+ );
+};
+
+/**
+ * Reception of Response for Initial Request
+ * @private
+ */
+RTCSession.prototype.receiveResponse = function(response) {
+ var cause,
+ session = this;
+
+ if(this.status !== C.STATUS_INVITE_SENT && this.status !== C.STATUS_1XX_RECEIVED) {
+ return;
+ }
+
+ // Proceed to cancellation if the user requested.
+ if(this.isCanceled) {
+ if(response.status_code >= 100 && response.status_code < 200) {
+ this.request.cancel(this.cancelReason);
+ } else if(response.status_code >= 200 && response.status_code < 299) {
+ this.acceptAndTerminate(response);
+ }
+ return;
+ }
+
+ switch(true) {
+ case /^100$/.test(response.status_code):
+ this.received_100 = true;
+ break;
+ case /^1[0-9]{2}$/.test(response.status_code):
+ // Do nothing with 1xx responses without To tag.
+ if(!response.to_tag) {
+ console.warn(LOG_PREFIX +'1xx response received without to tag');
+ break;
+ }
+
+ // Create Early Dialog if 1XX comes with contact
+ if(response.hasHeader('contact')) {
+ // An error on dialog creation will fire 'failed' event
+ this.createDialog(response, 'UAC', true);
+ }
+
+ this.status = C.STATUS_1XX_RECEIVED;
+ this.progress('remote', response);
+ break;
+ case /^2[0-9]{2}$/.test(response.status_code):
+ // Do nothing if this.dialog is already confirmed
+ if (this.dialog) {
+ break;
+ }
+
+ if(!response.body) {
+ this.acceptAndTerminate(response, 400, 'Missing session description');
+ this.failed('remote', response, JsSIP.C.causes.BAD_MEDIA_DESCRIPTION);
+ break;
+ }
+
+ // An error on dialog creation will fire 'failed' event
+ if (!this.createDialog(response, 'UAC')) {
+ break;
+ }
+
+ this.rtcMediaHandler.onMessage(
+ 'answer',
+ response.body,
+ /*
+ * onSuccess
+ * SDP Answer fits with Offer. Media will start
+ */
+ function() {
+ session.status = C.STATUS_CONFIRMED;
+ session.sendACK();
+ session.started('remote', response);
+ },
+ /*
+ * onFailure
+ * SDP Answer does not fit the Offer. Accept the call and Terminate.
+ */
+ function(e) {
+ console.warn(e);
+ session.acceptAndTerminate(response, 488, 'Not Acceptable Here');
+ session.failed('remote', response, JsSIP.C.causes.BAD_MEDIA_DESCRIPTION);
+ }
+ );
+ break;
+ default:
+ cause = JsSIP.Utils.sipErrorCause(response.status_code);
+ this.failed('remote', response, cause);
+ }
+};
+
+
+/**
+* @private
+*/
+RTCSession.prototype.acceptAndTerminate = function(response, status_code, reason_phrase) {
+ // Send ACK and BYE
+ // An error on dialog creation will fire 'failed' event
+ if (this.dialog || this.createDialog(response, 'UAC')) {
+ this.sendACK();
+ this.sendBye({
+ status_code: status_code,
+ reason_phrase: reason_phrase
+ });
+ }
+};
+
+/**
+* @private
+*/
+RTCSession.prototype.sendACK = function() {
+ var request = this.dialog.createRequest(JsSIP.C.ACK);
+
+ this.sendRequest(request);
+};
+
+/**
+* @private
+*/
+RTCSession.prototype.sendBye = function(options) {
+ options = options || {};
+
+ var request, reason,
+ status_code = options.status_code,
+ reason_phrase = options.reason_phrase || JsSIP.C.REASON_PHRASE[status_code] || '',
+ extraHeaders = options.extraHeaders || [],
+ body = options.body;
+
+ if (status_code && (status_code < 200 || status_code >= 700)) {
+ throw new TypeError('Invalid status_code: '+ status_code);
+ } else if (status_code) {
+ reason = 'SIP ;cause=' + status_code + '; text="' + reason_phrase + '"';
+ extraHeaders.push('Reason: '+ reason);
+ }
+
+ request = this.dialog.createRequest(JsSIP.C.BYE, extraHeaders);
+ request.body = body;
+
+ this.sendRequest(request);
+};
+
+/**
+ * @private
+ */
+RTCSession.prototype.sendRequest = function(request) {
+ var request_sender = new RequestSender(this, request);
+ request_sender.send();
+};
+
+/**
+ * Session Callbacks
+ */
+
+/**
+* Callback to be called from UA instance when TransportError occurs
+* @private
+*/
+RTCSession.prototype.onTransportError = function() {
+ if(this.status !== C.STATUS_TERMINATED) {
+ if (this.status === C.STATUS_CONFIRMED) {
+ this.ended('system', null, JsSIP.C.causes.CONNECTION_ERROR);
+ } else {
+ this.failed('system', null, JsSIP.C.causes.CONNECTION_ERROR);
+ }
+ }
+};
+
+/**
+* Callback to be called from UA instance when RequestTimeout occurs
+* @private
+*/
+RTCSession.prototype.onRequestTimeout = function() {
+ if(this.status !== C.STATUS_TERMINATED) {
+ if (this.status === C.STATUS_CONFIRMED) {
+ this.ended('system', null, JsSIP.C.causes.REQUEST_TIMEOUT);
+ } else {
+ this.failed('system', null, JsSIP.C.causes.CONNECTION_ERROR);
+ }
+ }
+};
+
+/**
+ * Internal Callbacks
+ */
+
+/**
+ * @private
+ */
+RTCSession.prototype.newRTCSession = function(originator, request) {
+ var session = this,
+ event_name = 'newRTCSession';
+
+ if (originator === 'remote') {
+ session.direction = 'incoming';
+ session.local_identity = request.to;
+ session.remote_identity = request.from;
+ } else if (originator === 'local'){
+ session.direction = 'outgoing';
+ session.local_identity = request.from;
+ session.remote_identity = request.to;
+ }
+
+ session.ua.emit(event_name, session.ua, {
+ originator: originator,
+ session: session,
+ request: request
+ });
+};
+
+/**
+ * @private
+ */
+RTCSession.prototype.connecting = function(originator, request) {
+ var session = this,
+ event_name = 'connecting';
+
+ session.emit(event_name, session, {
+ originator: 'local',
+ request: request
+ });
+};
+
+/**
+ * @private
+ */
+RTCSession.prototype.progress = function(originator, response) {
+ var session = this,
+ event_name = 'progress';
+
+ session.emit(event_name, session, {
+ originator: originator,
+ response: response || null
+ });
+};
+
+/**
+ * @private
+ */
+RTCSession.prototype.started = function(originator, message) {
+ var session = this,
+ event_name = 'started';
+
+ session.start_time = new Date();
+
+ session.emit(event_name, session, {
+ originator: originator,
+ response: message || null
+ });
+};
+
+/**
+ * @private
+ */
+RTCSession.prototype.ended = function(originator, message, cause) {
+ var session = this,
+ event_name = 'ended';
+
+ session.end_time = new Date();
+
+ session.close();
+ session.emit(event_name, session, {
+ originator: originator,
+ message: message || null,
+ cause: cause
+ });
+};
+
+/**
+ * @private
+ */
+RTCSession.prototype.failed = function(originator, message, cause) {
+ var session = this,
+ event_name = 'failed';
+
+ session.close();
+ session.emit(event_name, session, {
+ originator: originator,
+ message: message || null,
+ cause: cause
+ });
+};
+
+
+RTCSession.C = C;
+JsSIP.RTCSession = RTCSession;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview Message
+ */
+
+/**
+ * @augments JsSIP
+ * @class Class creating SIP MESSAGE request.
+ * @param {JsSIP.UA} ua
+ */
+(function(JsSIP) {
+var Message;
+
+Message = function(ua) {
+ this.ua = ua;
+ this.direction = null;
+ this.local_identity = null;
+ this.remote_identity = null;
+
+ // Custom message empty object for high level use
+ this.data = {};
+};
+Message.prototype = new JsSIP.EventEmitter();
+
+
+Message.prototype.send = function(target, body, options) {
+ var request_sender, event, contentType, eventHandlers, extraHeaders,
+ events = [
+ 'succeeded',
+ 'failed'
+ ],
+ invalidTarget = false;
+
+ if (target === undefined || body === undefined) {
+ throw new TypeError('Not enough arguments');
+ }
+
+ this.initEvents(events);
+
+ // Get call options
+ options = options || {};
+ extraHeaders = options.extraHeaders || [];
+ eventHandlers = options.eventHandlers || {};
+ contentType = options.contentType || 'text/plain';
+
+ // Set event handlers
+ for (event in eventHandlers) {
+ this.on(event, eventHandlers[event]);
+ }
+
+ // Check target validity
+ try {
+ target = JsSIP.Utils.normalizeURI(target, this.ua.configuration.hostport_params);
+ } catch(e) {
+ target = JsSIP.URI.parse(JsSIP.C.INVALID_TARGET_URI);
+ invalidTarget = true;
+ }
+
+ // Message parameter initialization
+ this.direction = 'outgoing';
+ this.local_identity = this.ua.configuration.uri;
+ this.remote_identity = target;
+
+ this.closed = false;
+ this.ua.applicants[this] = this;
+
+ extraHeaders.push('Content-Type: '+ contentType);
+
+ this.request = new JsSIP.OutgoingRequest(JsSIP.C.MESSAGE, target, this.ua, null, extraHeaders);
+
+ if(body) {
+ this.request.body = body;
+ }
+
+ request_sender = new JsSIP.RequestSender(this, this.ua);
+
+ this.ua.emit('newMessage', this.ua, {
+ originator: 'local',
+ message: this,
+ request: this.request
+ });
+
+ if (invalidTarget) {
+ this.emit('failed', this, {
+ originator: 'local',
+ cause: JsSIP.C.causes.INVALID_TARGET
+ });
+ } else {
+ request_sender.send();
+ }
+};
+
+/**
+* @private
+*/
+Message.prototype.receiveResponse = function(response) {
+ var cause;
+
+ if(this.closed) {
+ return;
+ }
+ switch(true) {
+ case /^1[0-9]{2}$/.test(response.status_code):
+ // Ignore provisional responses.
+ break;
+
+ case /^2[0-9]{2}$/.test(response.status_code):
+ delete this.ua.applicants[this];
+ this.emit('succeeded', this, {
+ originator: 'remote',
+ response: response
+ });
+ break;
+
+ default:
+ delete this.ua.applicants[this];
+ cause = JsSIP.Utils.sipErrorCause(response.status_code);
+ this.emit('failed', this, {
+ originator: 'remote',
+ response: response,
+ cause: cause
+ });
+ break;
+ }
+};
+
+
+/**
+* @private
+*/
+Message.prototype.onRequestTimeout = function() {
+ if(this.closed) {
+ return;
+ }
+ this.emit('failed', this, {
+ originator: 'system',
+ cause: JsSIP.C.causes.REQUEST_TIMEOUT
+ });
+};
+
+/**
+* @private
+*/
+Message.prototype.onTransportError = function() {
+ if(this.closed) {
+ return;
+ }
+ this.emit('failed', this, {
+ originator: 'system',
+ cause: JsSIP.C.causes.CONNECTION_ERROR
+ });
+};
+
+/**
+* @private
+*/
+Message.prototype.close = function() {
+ this.closed = true;
+ delete this.ua.applicants[this];
+};
+
+/**
+ * @private
+ */
+Message.prototype.init_incoming = function(request) {
+ var transaction,
+ contentType = request.getHeader('content-type');
+
+ this.direction = 'incoming';
+ this.request = request;
+ this.local_identity = request.to.uri;
+ this.remote_identity = request.from.uri;
+
+ if (contentType && (contentType.match(/^text\/plain(\s*;\s*.+)*$/i) || contentType.match(/^text\/html(\s*;\s*.+)*$/i))) {
+ this.ua.emit('newMessage', this.ua, {
+ originator: 'remote',
+ message: this,
+ request: request
+ });
+
+ transaction = this.ua.transactions.nist[request.via_branch];
+
+ if (transaction && (transaction.state === JsSIP.Transactions.C.STATUS_TRYING || transaction.state === JsSIP.Transactions.C.STATUS_PROCEEDING)) {
+ request.reply(200);
+ }
+ } else {
+ request.reply(415, null, ['Accept: text/plain, text/html']);
+ }
+};
+
+/**
+ * Accept the incoming Message
+ * Only valid for incoming Messages
+ */
+Message.prototype.accept = function(options) {
+ options = options || {};
+
+ var
+ extraHeaders = options.extraHeaders || [],
+ body = options.body;
+
+ if (this.direction !== 'incoming') {
+ throw new TypeError('Invalid method "accept" for an outgoing message');
+ }
+
+ this.request.reply(200, null, extraHeaders, body);
+};
+
+/**
+ * Reject the incoming Message
+ * Only valid for incoming Messages
+ *
+ * @param {Number} status_code
+ * @param {String} [reason_phrase]
+ */
+Message.prototype.reject = function(options) {
+ options = options || {};
+
+ var
+ status_code = options.status_code || 480,
+ reason_phrase = options.reason_phrase,
+ extraHeaders = options.extraHeaders || [],
+ body = options.body;
+
+ if (this.direction !== 'incoming') {
+ throw new TypeError('Invalid method "reject" for an outgoing message');
+ }
+
+ if (status_code < 300 || status_code >= 700) {
+ throw new TypeError('Invalid status_code: '+ status_code);
+ }
+
+ this.request.reply(status_code, reason_phrase, extraHeaders, body);
+};
+
+JsSIP.Message = Message;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview SIP User Agent
+ */
+
+
+/**
+ * @augments JsSIP
+ * @class Class creating a SIP User Agent.
+ */
+(function(JsSIP) {
+var UA,
+ LOG_PREFIX = JsSIP.name +' | '+ 'UA' +' | ',
+ C = {
+ // UA status codes
+ STATUS_INIT : 0,
+ STATUS_READY: 1,
+ STATUS_USER_CLOSED: 2,
+ STATUS_NOT_READY: 3,
+
+ // UA error codes
+ CONFIGURATION_ERROR: 1,
+ NETWORK_ERROR: 2,
+
+ /* UA events and corresponding SIP Methods.
+ * Dynamically added to 'Allow' header field if the
+ * corresponding event handler is set.
+ */
+ EVENT_METHODS: {
+ 'newRTCSession': 'INVITE',
+ 'newMessage': 'MESSAGE'
+ },
+
+ ALLOWED_METHODS: [
+ 'ACK',
+ 'CANCEL',
+ 'BYE',
+ 'OPTIONS'
+ ],
+
+ ACCEPTED_BODY_TYPES: [
+ 'application/sdp',
+ 'application/dtmf-relay'
+ ],
+
+ SUPPORTED: 'path, outbound, gruu',
+
+ MAX_FORWARDS: 69,
+ TAG_LENGTH: 10
+ };
+
+UA = function(configuration) {
+ var events = [
+ 'connected',
+ 'disconnected',
+ 'registered',
+ 'unregistered',
+ 'registrationFailed',
+ 'newRTCSession',
+ 'newMessage'
+ ];
+
+ // Set Accepted Body Types
+ C.ACCEPTED_BODY_TYPES = C.ACCEPTED_BODY_TYPES.toString();
+
+ this.cache = {
+ credentials: {}
+ };
+
+ this.configuration = {};
+ this.dialogs = {};
+
+ //User actions outside any session/dialog (MESSAGE)
+ this.applicants = {};
+
+ this.sessions = {};
+ this.transport = null;
+ this.contact = null;
+ this.status = C.STATUS_INIT;
+ this.error = null;
+ this.transactions = {
+ nist: {},
+ nict: {},
+ ist: {},
+ ict: {}
+ };
+
+ this.transportRecoverAttempts = 0;
+ this.transportRecoveryTimer = null;
+
+ /**
+ * Load configuration
+ *
+ * @throws {JsSIP.Exceptions.ConfigurationError}
+ * @throws {TypeError}
+ */
+
+ if(configuration === undefined) {
+ throw new TypeError('Not enough arguments');
+ }
+
+ try {
+ this.loadConfig(configuration);
+ this.initEvents(events);
+ } catch(e) {
+ this.status = C.STATUS_NOT_READY;
+ this.error = C.CONFIGURATION_ERROR;
+ throw e;
+ }
+
+ // Initialize registrator
+ this.registrator = new JsSIP.Registrator(this);
+};
+UA.prototype = new JsSIP.EventEmitter();
+
+//=================
+// High Level API
+//=================
+
+/**
+ * Register.
+ *
+ *
+ */
+UA.prototype.register = function(options) {
+ this.configuration.register = true;
+ this.registrator.register(options);
+};
+
+/**
+ * Unregister.
+ *
+ * @param {Boolean} [all] unregister all user bindings.
+ *
+ */
+UA.prototype.unregister = function(options) {
+ this.configuration.register = false;
+ this.registrator.unregister(options);
+};
+
+/**
+ * Registration state.
+ * @param {Boolean}
+ */
+UA.prototype.isRegistered = function() {
+ if(this.registrator.registered) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * Connection state.
+ * @param {Boolean}
+ */
+UA.prototype.isConnected = function() {
+ if(this.transport) {
+ return this.transport.connected;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * Make an outgoing call.
+ *
+ * @param {String} target
+ * @param {Object} views
+ * @param {Object} [options]
+ *
+ * @throws {TypeError}
+ *
+ */
+UA.prototype.call = function(target, options) {
+ var session;
+
+ session = new JsSIP.RTCSession(this);
+ session.connect(target, options);
+};
+
+/**
+ * Send a message.
+ *
+ * @param {String} target
+ * @param {String} body
+ * @param {Object} [options]
+ *
+ * @throws {TypeError}
+ *
+ */
+UA.prototype.sendMessage = function(target, body, options) {
+ var message;
+
+ message = new JsSIP.Message(this);
+ message.send(target, body, options);
+};
+
+/**
+ * Gracefully close.
+ *
+ */
+UA.prototype.stop = function() {
+ var session, applicant,
+ ua = this;
+
+ console.log(LOG_PREFIX +'user requested closure...');
+
+ if(this.status === C.STATUS_USER_CLOSED) {
+ console.warn('UA already closed');
+ return;
+ }
+
+ // Clear transportRecoveryTimer
+ window.clearTimeout(this.transportRecoveryTimer);
+
+ // Close registrator
+ console.log(LOG_PREFIX +'closing registrator');
+ this.registrator.close();
+
+ // Run _terminate_ on every Session
+ for(session in this.sessions) {
+ console.log(LOG_PREFIX +'closing session ' + session);
+ this.sessions[session].terminate();
+ }
+
+ // Run _close_ on every applicant
+ for(applicant in this.applicants) {
+ this.applicants[applicant].close();
+ }
+
+ this.status = C.STATUS_USER_CLOSED;
+ this.shutdownGraceTimer = window.setTimeout(
+ function() { ua.transport.disconnect(); },
+ '5000'
+ );
+};
+
+/**
+ * Connect to the WS server if status = STATUS_INIT.
+ * Resume UA after being closed.
+ *
+ */
+UA.prototype.start = function() {
+ var server;
+
+ console.log(LOG_PREFIX +'user requested startup...');
+
+ if (this.status === C.STATUS_INIT) {
+ server = this.getNextWsServer();
+ new JsSIP.Transport(this, server);
+ } else if(this.status === C.STATUS_USER_CLOSED) {
+ console.log(LOG_PREFIX +'resuming');
+ this.status = C.STATUS_READY;
+ this.transport.connect();
+ } else if (this.status === C.STATUS_READY) {
+ console.log(LOG_PREFIX +'UA is in READY status, not resuming');
+ } else {
+ console.error('Connection is down. Auto-Recovery system is trying to connect');
+ }
+};
+
+
+//===============================
+// Private (For internal use)
+//===============================
+
+UA.prototype.saveCredentials = function(credentials) {
+ this.cache.credentials[credentials.realm] = this.cache.credentials[credentials.realm] || {};
+ this.cache.credentials[credentials.realm][credentials.uri] = credentials;
+};
+
+UA.prototype.getCredentials = function(request) {
+ var realm, credentials;
+
+ realm = request.ruri.host;
+
+ if (this.cache.credentials[realm] && this.cache.credentials[realm][request.ruri]) {
+ credentials = this.cache.credentials[realm][request.ruri];
+ credentials.method = request.method;
+ }
+
+ return credentials;
+};
+
+
+//==========================
+// Event Handlers
+//==========================
+
+/**
+ * Transport Close event.
+ * @private
+ * @event
+ * @param {JsSIP.Transport} transport.
+ */
+UA.prototype.onTransportClosed = function(transport) {
+ // Run _onTransportError_ callback on every client transaction using _transport_
+ var type, idx, length,
+ client_transactions = ['nict', 'ict', 'nist', 'ist'];
+
+ transport.server.status = JsSIP.Transport.C.STATUS_DISCONNECTED;
+ console.log(LOG_PREFIX +'connection state set to '+ JsSIP.Transport.C.STATUS_DISCONNECTED);
+
+ length = client_transactions.length;
+ for (type = 0; type < length; type++) {
+ for(idx in this.transactions[client_transactions[type]]) {
+ this.transactions[client_transactions[type]][idx].onTransportError();
+ }
+ }
+
+ // Close sessions if GRUU is not being used
+ if (!this.contact.pub_gruu) {
+ this.closeSessionsOnTransportError();
+ }
+
+};
+
+/**
+ * Unrecoverable transport event.
+ * Connection reattempt logic has been done and didn't success.
+ * @private
+ * @event
+ * @param {JsSIP.Transport} transport.
+ */
+UA.prototype.onTransportError = function(transport) {
+ var server;
+
+ console.log(LOG_PREFIX +'transport ' + transport.server.ws_uri + ' failed | connection state set to '+ JsSIP.Transport.C.STATUS_ERROR);
+
+ // Close sessions.
+ //Mark this transport as 'down' and try the next one
+ transport.server.status = JsSIP.Transport.C.STATUS_ERROR;
+
+ this.emit('disconnected', this, {
+ transport: transport,
+ code: transport.lastTransportError.code,
+ reason: transport.lastTransportError.reason
+ });
+
+ server = this.getNextWsServer();
+
+ if(server) {
+ new JsSIP.Transport(this, server);
+ }else {
+ this.closeSessionsOnTransportError();
+ if (!this.error || this.error !== C.NETWORK_ERROR) {
+ this.status = C.STATUS_NOT_READY;
+ this.error = C.NETWORK_ERROR;
+ }
+ // Transport Recovery process
+ this.recoverTransport();
+ }
+};
+
+/**
+ * Transport connection event.
+ * @private
+ * @event
+ * @param {JsSIP.Transport} transport.
+ */
+UA.prototype.onTransportConnected = function(transport) {
+ this.transport = transport;
+
+ // Reset transport recovery counter
+ this.transportRecoverAttempts = 0;
+
+ transport.server.status = JsSIP.Transport.C.STATUS_READY;
+ console.log(LOG_PREFIX +'connection state set to '+ JsSIP.Transport.C.STATUS_READY);
+
+ if(this.status === C.STATUS_USER_CLOSED) {
+ return;
+ }
+
+ this.status = C.STATUS_READY;
+ this.error = null;
+ this.emit('connected', this, {
+ transport: transport
+ });
+
+ if(this.configuration.register) {
+ this.registrator.onTransportConnected();
+ }
+};
+
+//=========================
+// receiveRequest
+//=========================
+
+/**
+ * Request reception
+ * @private
+ * @param {JsSIP.IncomingRequest} request.
+ */
+UA.prototype.receiveRequest = function(request) {
+ var dialog, session, message,
+ method = request.method;
+
+ // Check that Ruri points to us
+ if(request.ruri.user !== this.configuration.uri.user && request.ruri.user !== this.contact.uri.user) {
+ console.warn(LOG_PREFIX +'Request-URI does not point to us');
+ if (request.method !== JsSIP.C.ACK) {
+ request.reply_sl(404);
+ }
+ return;
+ }
+
+ // Check transaction
+ if(JsSIP.Transactions.checkTransaction(this, request)) {
+ return;
+ }
+
+ // Create the server transaction
+ if(method === JsSIP.C.INVITE) {
+ new JsSIP.Transactions.InviteServerTransaction(request, this);
+ } else if(method !== JsSIP.C.ACK) {
+ new JsSIP.Transactions.NonInviteServerTransaction(request, this);
+ }
+
+ /* RFC3261 12.2.2
+ * Requests that do not change in any way the state of a dialog may be
+ * received within a dialog (for example, an OPTIONS request).
+ * They are processed as if they had been received outside the dialog.
+ */
+ if(method === JsSIP.C.OPTIONS) {
+ request.reply(200, null, [
+ 'Allow: '+ JsSIP.Utils.getAllowedMethods(this),
+ 'Accept: '+ C.ACCEPTED_BODY_TYPES
+ ]);
+ } else if (method === JsSIP.C.MESSAGE) {
+ if (!this.checkEvent('newMessage') || this.listeners('newMessage').length === 0) {
+ request.reply(405, null, ['Allow: '+ JsSIP.Utils.getAllowedMethods(this)]);
+ return;
+ }
+ message = new JsSIP.Message(this);
+ message.init_incoming(request);
+ }
+
+ // Initial Request
+ if(!request.to_tag) {
+ if(!this.isRegistered()) {
+ // High user does not want to be contacted
+ request.reply(410);
+ return;
+ }
+
+ switch(method) {
+ case JsSIP.C.INVITE:
+ if(JsSIP.WebRTC.isSupported) {
+ session = new JsSIP.RTCSession(this);
+ session.init_incoming(request);
+ } else {
+ console.warn(LOG_PREFIX +'INVITE received but WebRTC is not supported');
+ request.reply(488);
+ }
+ break;
+ case JsSIP.C.BYE:
+ // Out of dialog BYE received
+ request.reply(481);
+ break;
+ case JsSIP.C.CANCEL:
+ session = this.findSession(request);
+ if(session) {
+ session.receiveRequest(request);
+ } else {
+ console.warn(LOG_PREFIX +'received CANCEL request for a non existent session');
+ }
+ break;
+ case JsSIP.C.ACK:
+ /* Absorb it.
+ * ACK request without a corresponding Invite Transaction
+ * and without To tag.
+ */
+ break;
+ default:
+ request.reply(405);
+ break;
+ }
+ }
+ // In-dialog request
+ else {
+ dialog = this.findDialog(request);
+
+ if(dialog) {
+ dialog.receiveRequest(request);
+ } else if (method === JsSIP.C.NOTIFY) {
+ session = this.findSession(request);
+ if(session) {
+ session.receiveRequest(request);
+ } else {
+ console.warn(LOG_PREFIX +'received NOTIFY request for a non existent session');
+ request.reply(481, 'Subscription does not exist');
+ }
+ }
+ /* RFC3261 12.2.2
+ * Request with to tag, but no matching dialog found.
+ * Exception: ACK for an Invite request for which a dialog has not
+ * been created.
+ */
+ else {
+ if(method !== JsSIP.C.ACK) {
+ request.reply(481);
+ }
+ }
+ }
+};
+
+//=================
+// Utils
+//=================
+
+/**
+ * Get the session to which the request belongs to, if any.
+ * @private
+ * @param {JsSIP.IncomingRequest} request.
+ * @returns {JsSIP.OutgoingSession|JsSIP.IncomingSession|null}
+ */
+UA.prototype.findSession = function(request) {
+ var
+ sessionIDa = request.call_id + request.from_tag,
+ sessionA = this.sessions[sessionIDa],
+ sessionIDb = request.call_id + request.to_tag,
+ sessionB = this.sessions[sessionIDb];
+
+ if(sessionA) {
+ return sessionA;
+ } else if(sessionB) {
+ return sessionB;
+ } else {
+ return null;
+ }
+};
+
+/**
+ * Get the dialog to which the request belongs to, if any.
+ * @private
+ * @param {JsSIP.IncomingRequest}
+ * @returns {JsSIP.Dialog|null}
+ */
+UA.prototype.findDialog = function(request) {
+ var
+ id = request.call_id + request.from_tag + request.to_tag,
+ dialog = this.dialogs[id];
+
+ if(dialog) {
+ return dialog;
+ } else {
+ id = request.call_id + request.to_tag + request.from_tag;
+ dialog = this.dialogs[id];
+ if(dialog) {
+ return dialog;
+ } else {
+ return null;
+ }
+ }
+};
+
+/**
+ * Retrieve the next server to which connect.
+ * @private
+ * @returns {Object} ws_server
+ */
+UA.prototype.getNextWsServer = function() {
+ // Order servers by weight
+ var idx, length, ws_server,
+ candidates = [];
+
+ length = this.configuration.ws_servers.length;
+ for (idx = 0; idx < length; idx++) {
+ ws_server = this.configuration.ws_servers[idx];
+
+ if (ws_server.status === JsSIP.Transport.C.STATUS_ERROR) {
+ continue;
+ } else if (candidates.length === 0) {
+ candidates.push(ws_server);
+ } else if (ws_server.weight > candidates[0].weight) {
+ candidates = [ws_server];
+ } else if (ws_server.weight === candidates[0].weight) {
+ candidates.push(ws_server);
+ }
+ }
+
+ idx = Math.floor((Math.random()* candidates.length));
+
+ return candidates[idx];
+};
+
+/**
+ * Close all sessions on transport error.
+ * @private
+ */
+UA.prototype.closeSessionsOnTransportError = function() {
+ var idx;
+
+ // Run _transportError_ for every Session
+ for(idx in this.sessions) {
+ this.sessions[idx].onTransportError();
+ }
+ // Call registrator _onTransportClosed_
+ this.registrator.onTransportClosed();
+};
+
+UA.prototype.recoverTransport = function(ua) {
+ var idx, length, k, nextRetry, count, server;
+
+ ua = ua || this;
+ count = ua.transportRecoverAttempts;
+
+ length = ua.configuration.ws_servers.length;
+ for (idx = 0; idx < length; idx++) {
+ ua.configuration.ws_servers[idx].status = 0;
+ }
+
+ server = ua.getNextWsServer();
+
+ k = Math.floor((Math.random() * Math.pow(2,count)) +1);
+ nextRetry = k * ua.configuration.connection_recovery_min_interval;
+
+ if (nextRetry > ua.configuration.connection_recovery_max_interval) {
+ console.log(LOG_PREFIX + 'time for next connection attempt exceeds connection_recovery_max_interval, resetting counter');
+ nextRetry = ua.configuration.connection_recovery_min_interval;
+ count = 0;
+ }
+
+ console.log(LOG_PREFIX + 'next connection attempt in '+ nextRetry +' seconds');
+
+ this.transportRecoveryTimer = window.setTimeout(
+ function(){
+ ua.transportRecoverAttempts = count + 1;
+ new JsSIP.Transport(ua, server);
+ }, nextRetry * 1000);
+};
+
+/**
+ * Configuration load.
+ * @private
+ * returns {Boolean}
+ */
+UA.prototype.loadConfig = function(configuration) {
+ // Settings and default values
+ var parameter, value, checked_value, hostport_params, registrar_server,
+ settings = {
+ /* Host address
+ * Value to be set in Via sent_by and host part of Contact FQDN
+ */
+ via_host: JsSIP.Utils.createRandomToken(12) + '.invalid',
+
+ // Password
+ password: null,
+
+ // Registration parameters
+ register_expires: 600,
+ register_min_expires: 120,
+ register: true,
+ registrar_server: null,
+
+ // Transport related parameters
+ ws_server_max_reconnection: 3,
+ ws_server_reconnection_timeout: 4,
+
+ connection_recovery_min_interval: 2,
+ connection_recovery_max_interval: 30,
+
+ use_preloaded_route: false,
+
+ // Session parameters
+ no_answer_timeout: 60,
+ stun_servers: ['stun:stun.l.google.com:19302'],
+ turn_servers: [],
+
+ // Logging parameters
+ trace_sip: false,
+
+ // Hacks
+ hack_via_tcp: false,
+ hack_ip_in_contact: false
+ };
+
+ // Pre-Configuration
+
+ // Check Mandatory parameters
+ for(parameter in UA.configuration_check.mandatory) {
+ if(!configuration.hasOwnProperty(parameter)) {
+ throw new JsSIP.Exceptions.ConfigurationError(parameter);
+ } else {
+ value = configuration[parameter];
+ checked_value = UA.configuration_check.mandatory[parameter](value);
+ if (checked_value !== undefined) {
+ settings[parameter] = checked_value;
+ } else {
+ throw new JsSIP.Exceptions.ConfigurationError(parameter, value);
+ }
+ }
+ }
+
+ // Check Optional parameters
+ for(parameter in UA.configuration_check.optional) {
+ if(configuration.hasOwnProperty(parameter)) {
+ value = configuration[parameter];
+
+ // If the parameter value is null, empty string or undefined then apply its default value.
+ if(value === null || value === "" || value === undefined) { continue; }
+ // If it's a number with NaN value then also apply its default value.
+ // NOTE: JS does not allow "value === NaN", the following does the work:
+ else if(typeof(value) === 'number' && window.isNaN(value)) { continue; }
+
+ checked_value = UA.configuration_check.optional[parameter](value);
+ if (checked_value !== undefined) {
+ settings[parameter] = checked_value;
+ } else {
+ throw new JsSIP.Exceptions.ConfigurationError(parameter, value);
+ }
+ }
+ }
+
+ // Sanity Checks
+
+ // Connection recovery intervals
+ if(settings.connection_recovery_max_interval < settings.connection_recovery_min_interval) {
+ throw new JsSIP.Exceptions.ConfigurationError('connection_recovery_max_interval', settings.connection_recovery_max_interval);
+ }
+
+ // Post Configuration Process
+
+ // Allow passing 0 number as display_name.
+ if (settings.display_name === 0) {
+ settings.display_name = '0';
+ }
+
+ // Instance-id for GRUU
+ settings.instance_id = JsSIP.Utils.newUUID();
+
+ // jssip_id instance parameter. Static random tag of length 5
+ settings.jssip_id = JsSIP.Utils.createRandomToken(5);
+
+ // String containing settings.uri without scheme and user.
+ hostport_params = settings.uri.clone();
+ hostport_params.user = null;
+ settings.hostport_params = hostport_params.toString().replace(/^sip:/i, '');
+
+ /* Check whether authorization_user is explicitly defined.
+ * Take 'settings.uri.user' value if not.
+ */
+ if (!settings.authorization_user) {
+ settings.authorization_user = settings.uri.user;
+ }
+
+ /* If no 'registrar_server' is set use the 'uri' value without user portion. */
+ if (!settings.registrar_server) {
+ registrar_server = settings.uri.clone();
+ registrar_server.user = null;
+ settings.registrar_server = registrar_server;
+ }
+
+ // User no_answer_timeout
+ settings.no_answer_timeout = settings.no_answer_timeout * 1000;
+
+ // Via Host
+ if (settings.hack_ip_in_contact) {
+ settings.via_host = JsSIP.Utils.getRandomTestNetIP();
+ }
+
+ this.contact = {
+ pub_gruu: null,
+ temp_gruu: null,
+ uri: new JsSIP.URI('sip', JsSIP.Utils.createRandomToken(8), settings.via_host, null, {transport: 'ws'}),
+ toString: function(options){
+ options = options || {};
+
+ var
+ anonymous = options.anonymous || null,
+ outbound = options.outbound || null,
+ contact = '<';
+
+ if (anonymous) {
+ contact += this.temp_gruu || 'sip:anonymous@anonymous.invalid;transport=ws';
+ } else {
+ contact += this.pub_gruu || this.uri.toString();
+ }
+
+ if (outbound) {
+ contact += ';ob';
+ }
+
+ contact += '>';
+
+ return contact;
+ }
+ };
+
+ // Fill the value of the configuration_skeleton
+ console.log(LOG_PREFIX + 'configuration parameters after validation:');
+ for(parameter in settings) {
+ switch(parameter) {
+ case 'uri':
+ case 'registrar_server':
+ console.log('· ' + parameter + ': ' + settings[parameter]);
+ break;
+ case 'password':
+ console.log('· ' + parameter + ': ' + 'NOT SHOWN');
+ break;
+ default:
+ console.log('· ' + parameter + ': ' + window.JSON.stringify(settings[parameter]));
+ }
+ UA.configuration_skeleton[parameter].value = settings[parameter];
+ }
+
+ Object.defineProperties(this.configuration, UA.configuration_skeleton);
+
+ // Clean UA.configuration_skeleton
+ for(parameter in settings) {
+ UA.configuration_skeleton[parameter].value = '';
+ }
+
+ return;
+};
+
+
+/**
+ * Configuration Object skeleton.
+ * @private
+ */
+UA.configuration_skeleton = (function() {
+ var idx, parameter,
+ skeleton = {},
+ parameters = [
+ // Internal parameters
+ "instance_id",
+ "jssip_id",
+ "register_min_expires",
+ "ws_server_max_reconnection",
+ "ws_server_reconnection_timeout",
+ "hostport_params",
+
+ // Mandatory user configurable parameters
+ "uri",
+ "ws_servers",
+
+ // Optional user configurable parameters
+ "authorization_user",
+ "connection_recovery_max_interval",
+ "connection_recovery_min_interval",
+ "display_name",
+ "hack_via_tcp", // false.
+ "hack_ip_in_contact", //false
+ "no_answer_timeout", // 30 seconds.
+ "password",
+ "register_expires", // 600 seconds.
+ "registrar_server",
+ "stun_servers",
+ "trace_sip",
+ "turn_servers",
+ "use_preloaded_route",
+
+ // Post-configuration generated parameters
+ "via_core_value",
+ "via_host"
+ ];
+
+ for(idx in parameters) {
+ parameter = parameters[idx];
+ skeleton[parameter] = {
+ value: '',
+ writable: false,
+ configurable: false
+ };
+ }
+
+ skeleton['register'] = {
+ value: '',
+ writable: true,
+ configurable: false
+ };
+
+ return skeleton;
+}());
+
+/**
+ * Configuration checker.
+ * @private
+ * @return {Boolean}
+ */
+UA.configuration_check = {
+ mandatory: {
+
+ uri: function(uri) {
+ var parsed;
+
+ if (!/^sip:/i.test(uri)) {
+ uri = JsSIP.C.SIP + ':' + uri;
+ }
+ parsed = JsSIP.URI.parse(uri);
+
+ if(!parsed) {
+ return;
+ } else if(!parsed.user) {
+ return;
+ } else {
+ return parsed;
+ }
+ },
+
+ ws_servers: function(ws_servers) {
+ var idx, length, url;
+
+ /* Allow defining ws_servers parameter as:
+ * String: "host"
+ * Array of Strings: ["host1", "host2"]
+ * Array of Objects: [{ws_uri:"host1", weight:1}, {ws_uri:"host2", weight:0}]
+ * Array of Objects and Strings: [{ws_uri:"host1"}, "host2"]
+ */
+ if (typeof ws_servers === 'string') {
+ ws_servers = [{ws_uri: ws_servers}];
+ } else if (ws_servers instanceof Array) {
+ length = ws_servers.length;
+ for (idx = 0; idx < length; idx++) {
+ if (typeof ws_servers[idx] === 'string'){
+ ws_servers[idx] = {ws_uri: ws_servers[idx]};
+ }
+ }
+ } else {
+ return;
+ }
+
+ if (ws_servers.length === 0) {
+ return false;
+ }
+
+ length = ws_servers.length;
+ for (idx = 0; idx < length; idx++) {
+ if (!ws_servers[idx].ws_uri) {
+ console.error(LOG_PREFIX +'missing "ws_uri" attribute in ws_servers parameter');
+ return;
+ }
+ if (ws_servers[idx].weight && !Number(ws_servers[idx].weight)) {
+ console.error(LOG_PREFIX +'"weight" attribute in ws_servers parameter must be a Number');
+ return;
+ }
+
+ url = JsSIP.Grammar.parse(ws_servers[idx].ws_uri, 'absoluteURI');
+
+ if(url === -1) {
+ console.error(LOG_PREFIX +'invalid "ws_uri" attribute in ws_servers parameter: ' + ws_servers[idx].ws_uri);
+ return;
+ } else if(url.scheme !== 'wss' && url.scheme !== 'ws') {
+ console.error(LOG_PREFIX +'invalid URI scheme in ws_servers parameter: ' + url.scheme);
+ return;
+ } else {
+ ws_servers[idx].sip_uri = '';
+
+ if (!ws_servers[idx].weight) {
+ ws_servers[idx].weight = 0;
+ }
+
+ ws_servers[idx].status = 0;
+ ws_servers[idx].scheme = url.scheme.toUpperCase();
+ }
+ }
+ return ws_servers;
+ }
+ },
+
+ optional: {
+
+ authorization_user: function(authorization_user) {
+ if(JsSIP.Grammar.parse('"'+ authorization_user +'"', 'quoted_string') === -1) {
+ return;
+ } else {
+ return authorization_user;
+ }
+ },
+
+ connection_recovery_max_interval: function(connection_recovery_max_interval) {
+ var value;
+ if(JsSIP.Utils.isDecimal(connection_recovery_max_interval)) {
+ value = window.Number(connection_recovery_max_interval);
+ if(value > 0) {
+ return value;
+ }
+ }
+ },
+
+ connection_recovery_min_interval: function(connection_recovery_min_interval) {
+ var value;
+ if(JsSIP.Utils.isDecimal(connection_recovery_min_interval)) {
+ value = window.Number(connection_recovery_min_interval);
+ if(value > 0) {
+ return value;
+ }
+ }
+ },
+
+ display_name: function(display_name) {
+ if(JsSIP.Grammar.parse('"' + display_name + '"', 'display_name') === -1) {
+ return;
+ } else {
+ return display_name;
+ }
+ },
+
+ hack_via_tcp: function(hack_via_tcp) {
+ if (typeof hack_via_tcp === 'boolean') {
+ return hack_via_tcp;
+ }
+ },
+
+ hack_ip_in_contact: function(hack_ip_in_contact) {
+ if (typeof hack_ip_in_contact === 'boolean') {
+ return hack_ip_in_contact;
+ }
+ },
+
+ no_answer_timeout: function(no_answer_timeout) {
+ var value;
+ if (JsSIP.Utils.isDecimal(no_answer_timeout)) {
+ value = window.Number(no_answer_timeout);
+ if (value > 0) {
+ return value;
+ }
+ }
+ },
+
+ password: function(password) {
+ return String(password);
+ },
+
+ register: function(register) {
+ if (typeof register === 'boolean') {
+ return register;
+ }
+ },
+
+ register_expires: function(register_expires) {
+ var value;
+ if (JsSIP.Utils.isDecimal(register_expires)) {
+ value = window.Number(register_expires);
+ if (value > 0) {
+ return value;
+ }
+ }
+ },
+
+ registrar_server: function(registrar_server) {
+ var parsed;
+
+ if (!/^sip:/i.test(registrar_server)) {
+ registrar_server = JsSIP.C.SIP + ':' + registrar_server;
+ }
+ parsed = JsSIP.URI.parse(registrar_server);
+
+ if(!parsed) {
+ return;
+ } else if(parsed.user) {
+ return;
+ } else {
+ return parsed;
+ }
+ },
+
+ stun_servers: function(stun_servers) {
+ var idx, length, stun_server;
+
+ if (typeof stun_servers === 'string') {
+ stun_servers = [stun_servers];
+ } else if (!(stun_servers instanceof Array)) {
+ return;
+ }
+
+ length = stun_servers.length;
+ for (idx = 0; idx < length; idx++) {
+ stun_server = stun_servers[idx];
+ if (!(/^stuns?:/.test(stun_server))) {
+ stun_server = 'stun:' + stun_server;
+ }
+
+ if(JsSIP.Grammar.parse(stun_server, 'stun_URI') === -1) {
+ return;
+ } else {
+ stun_servers[idx] = stun_server;
+ }
+ }
+ return stun_servers;
+ },
+
+ trace_sip: function(trace_sip) {
+ if (typeof trace_sip === 'boolean') {
+ return trace_sip;
+ }
+ },
+
+ turn_servers: function(turn_servers) {
+ var idx, length, turn_server, url;
+
+ if (turn_servers instanceof Array) {
+ // Do nothing
+ } else {
+ turn_servers = [turn_servers];
+ }
+
+ length = turn_servers.length;
+ for (idx = 0; idx < length; idx++) {
+ turn_server = turn_servers[idx];
+
+ // Backward 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 || !turn_server.username || !turn_server.password) {
+ return;
+ }
+
+ if (!turn_server.urls instanceof Array) {
+ turn_server.urls = [turn_server.urls];
+ }
+
+ length = turn_server.urls.length;
+ for (idx = 0; idx < length; idx++) {
+ url = turn_server.urls[idx];
+
+ if (!(/^turns?:/.test(url))) {
+ url = 'turn:' + url;
+ }
+
+ if(JsSIP.Grammar.parse(url, 'turn_URI') === -1) {
+ return;
+ }
+ }
+ }
+ return turn_servers;
+ },
+
+ use_preloaded_route: function(use_preloaded_route) {
+ if (typeof use_preloaded_route === 'boolean') {
+ return use_preloaded_route;
+ }
+ }
+ }
+};
+
+UA.C = C;
+JsSIP.UA = UA;
+}(JsSIP));
+
+
+
+/**
+ * @fileoverview Utils
+ */
+
+(function(JsSIP) {
+var Utils;
+
+Utils= {
+
+ str_utf8_length: function(string) {
+ return window.unescape(encodeURIComponent(string)).length;
+ },
+
+ isFunction: function(fn) {
+ if (fn !== undefined) {
+ return (Object.prototype.toString.call(fn) === '[object Function]')? true : false;
+ } else {
+ return false;
+ }
+ },
+
+ isDecimal: function (num) {
+ return !isNaN(num) && (parseFloat(num) === parseInt(num,10));
+ },
+
+ createRandomToken: function(size, base) {
+ var i, r,
+ token = '';
+
+ base = base || 32;
+
+ for( i=0; i < size; i++ ) {
+ r = Math.random() * base|0;
+ token += r.toString(base);
+ }
+
+ return token;
+ },
+
+ newTag: function() {
+ return JsSIP.Utils.createRandomToken(JsSIP.UA.C.TAG_LENGTH);
+ },
+
+ // http://stackoverflow.com/users/109538/broofa
+ newUUID: function() {
+ var UUID = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
+ return v.toString(16);
+ });
+
+ return UUID;
+ },
+
+ hostType: function(host) {
+ if (!host) {
+ return;
+ } else {
+ host = JsSIP.Grammar.parse(host,'host');
+ if (host !== -1) {
+ return host.host_type;
+ }
+ }
+ },
+
+ /**
+ * Normalize SIP URI.
+ * NOTE: It does not allow a SIP URI without username.
+ * Accepts 'sip', 'sips' and 'tel' URIs and convert them into 'sip'.
+ * Detects the domain part (if given) and properly hex-escapes the user portion.
+ * If the user portion has only 'tel' number symbols the user portion is clean of 'tel' visual separators.
+ * @private
+ * @param {String} target
+ * @param {String} [domain]
+ */
+ normalizeURI: function(target, domain) {
+ var uri, target_array, target_user, target_domain,
+ original_target = target;
+
+ // If no target is given then raise an error.
+ if (!target) {
+ throw new JsSIP.Exceptions.InvalidTargetError(original_target);
+
+ // If a JsSIP.URI instance is given then return it.
+ } else if (target instanceof JsSIP.URI) {
+ return target;
+
+ // If a string is given split it by '@':
+ // - Last fragment is the desired domain.
+ // - Otherwise append the given domain argument.
+ } else if (typeof target === 'string') {
+ target_array = target.split('@');
+
+ switch(target_array.length) {
+ case 1:
+ if (!domain) {
+ throw new JsSIP.Exceptions.InvalidTargetError(original_target);
+ }
+ target_user = target;
+ target_domain = domain;
+ break;
+ case 2:
+ target_user = target_array[0];
+ target_domain = target_array[1];
+ break;
+ default:
+ target_user = target_array.slice(0, target_array.length-1).join('@');
+ target_domain = target_array[target_array.length-1];
+ }
+
+ // Remove the URI scheme (if present).
+ target_user = target_user.replace(/^(sips?|tel):/i, '');
+
+ // Remove 'tel' visual separators if the user portion just contains 'tel' number symbols.
+ if (/^[\-\.\(\)]*\+?[0-9\-\.\(\)]+$/.test(target_user)) {
+ target_user = target_user.replace(/[\-\.\(\)]/g, '');
+ }
+
+ // Build the complete SIP URI.
+ target = JsSIP.C.SIP + ':' + JsSIP.Utils.escapeUser(target_user) + '@' + target_domain;
+
+ // Finally parse the resulting URI.
+ if (uri = JsSIP.URI.parse(target)) {
+ return uri;
+ } else {
+ throw new JsSIP.Exceptions.InvalidTargetError(original_target);
+ }
+ }
+
+ // Otherwise raise an error.
+ else {
+ throw new JsSIP.Exceptions.InvalidTargetError(original_target);
+ }
+ },
+
+ /**
+ * Hex-escape a SIP URI user.
+ * @private
+ * @param {String} user
+ */
+ escapeUser: function(user) {
+ // Don't hex-escape ':' (%3A), '+' (%2B), '?' (%3F"), '/' (%2F).
+ return window.encodeURIComponent(window.decodeURIComponent(user)).replace(/%3A/ig, ':').replace(/%2B/ig, '+').replace(/%3F/ig, '?').replace(/%2F/ig, '/');
+ },
+
+ headerize: function(string) {
+ var exceptions = {
+ 'Call-Id': 'Call-ID',
+ 'Cseq': 'CSeq',
+ 'Www-Authenticate': 'WWW-Authenticate'
+ },
+ name = string.toLowerCase().replace(/_/g,'-').split('-'),
+ hname = '',
+ parts = name.length, part;
+
+ for (part = 0; part < parts; part++) {
+ if (part !== 0) {
+ hname +='-';
+ }
+ hname += name[part].charAt(0).toUpperCase()+name[part].substring(1);
+ }
+ if (exceptions[hname]) {
+ hname = exceptions[hname];
+ }
+ return hname;
+ },
+
+ sipErrorCause: function(status_code) {
+ var cause;
+
+ for (cause in JsSIP.C.SIP_ERROR_CAUSES) {
+ if (JsSIP.C.SIP_ERROR_CAUSES[cause].indexOf(status_code) !== -1) {
+ return JsSIP.C.causes[cause];
+ }
+ }
+
+ return JsSIP.C.causes.SIP_FAILURE_CODE;
+ },
+
+ /**
+ * Generate a random Test-Net IP (http://tools.ietf.org/html/rfc5735)
+ * @private
+ */
+ getRandomTestNetIP: function() {
+ function getOctet(from,to) {
+ return window.Math.floor(window.Math.random()*(to-from+1)+from);
+ }
+ return '192.0.2.' + getOctet(1, 254);
+ },
+
+ getAllowedMethods: function(ua) {
+ var event,
+ allowed = JsSIP.UA.C.ALLOWED_METHODS.toString();
+
+ for (event in JsSIP.UA.C.EVENT_METHODS) {
+ if (ua.checkEvent(event) && ua.listeners(event).length > 0) {
+ allowed += ','+ JsSIP.UA.C.EVENT_METHODS[event];
+ }
+ }
+
+ return allowed;
+ },
+
+ // MD5 (Message-Digest Algorithm) http://www.webtoolkit.info
+ calculateMD5: function(string) {
+ function RotateLeft(lValue, iShiftBits) {
+ return (lValue<>>(32-iShiftBits));
+ }
+
+ function AddUnsigned(lX,lY) {
+ var lX4,lY4,lX8,lY8,lResult;
+ lX8 = (lX & 0x80000000);
+ lY8 = (lY & 0x80000000);
+ lX4 = (lX & 0x40000000);
+ lY4 = (lY & 0x40000000);
+ lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
+ if (lX4 & lY4) {
+ return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
+ }
+ if (lX4 | lY4) {
+ if (lResult & 0x40000000) {
+ return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
+ } else {
+ return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
+ }
+ } else {
+ return (lResult ^ lX8 ^ lY8);
+ }
+ }
+
+ function F(x,y,z) {
+ return (x & y) | ((~x) & z);
+ }
+
+ function G(x,y,z) {
+ return (x & z) | (y & (~z));
+ }
+
+ function H(x,y,z) {
+ return (x ^ y ^ z);
+ }
+
+ function I(x,y,z) {
+ return (y ^ (x | (~z)));
+ }
+
+ function FF(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+
+ function GG(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+
+ function HH(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+
+ function II(a,b,c,d,x,s,ac) {
+ a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
+ return AddUnsigned(RotateLeft(a, s), b);
+ }
+
+ function ConvertToWordArray(string) {
+ var lWordCount;
+ var lMessageLength = string.length;
+ var lNumberOfWords_temp1=lMessageLength + 8;
+ var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
+ var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
+ var lWordArray=Array(lNumberOfWords-1);
+ var lBytePosition = 0;
+ var lByteCount = 0;
+ while ( lByteCount < lMessageLength ) {
+ lWordCount = (lByteCount-(lByteCount % 4))/4;
+ lBytePosition = (lByteCount % 4)*8;
+ lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<>>29;
+ return lWordArray;
+ }
+
+ function WordToHex(lValue) {
+ var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
+ for (lCount = 0;lCount<=3;lCount++) {
+ lByte = (lValue>>>(lCount*8)) & 255;
+ WordToHexValue_temp = "0" + lByte.toString(16);
+ WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
+ }
+ return WordToHexValue;
+ }
+
+ function Utf8Encode(string) {
+ string = string.replace(/\r\n/g,"\n");
+ var utftext = "";
+
+ for (var n = 0; n < string.length; n++) {
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ }
+ else if((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ }
+ return utftext;
+ }
+
+ var x=[];
+ var k,AA,BB,CC,DD,a,b,c,d;
+ var S11=7, S12=12, S13=17, S14=22;
+ var S21=5, S22=9 , S23=14, S24=20;
+ var S31=4, S32=11, S33=16, S34=23;
+ var S41=6, S42=10, S43=15, S44=21;
+
+ string = Utf8Encode(string);
+
+ x = ConvertToWordArray(string);
+
+ a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
+
+ for (k=0;k 1) {
+ console.warn(LOG_PREFIX +'More than one Via header field present in the response. Dropping the response');
+ return false;
+ }
+}
+
+function rfc3261_18_1_2() {
+ var via_host = ua.configuration.via_host;
+ if(message.via.host !== via_host) {
+ console.warn(LOG_PREFIX +'Via host in the response does not match UA Via host value. Dropping the response');
+ return false;
+ }
+}
+
+function rfc3261_18_3_response() {
+ var
+ len = JsSIP.Utils.str_utf8_length(message.body),
+ contentLength = message.getHeader('content-length');
+
+ if(len < contentLength) {
+ console.warn(LOG_PREFIX +'Message body length is lower than the value in Content-Length header field. Dropping the response');
+ return false;
+ }
+}
+
+// Sanity Check functions for requests and responses
+function minimumHeaders() {
+ var
+ mandatoryHeaders = ['from', 'to', 'call_id', 'cseq', 'via'],
+ idx = mandatoryHeaders.length;
+
+ while(idx--) {
+ if(!message.hasHeader(mandatoryHeaders[idx])) {
+ console.warn(LOG_PREFIX +'Missing mandatory header field : '+ mandatoryHeaders[idx] +'. Dropping the response');
+ return false;
+ }
+ }
+}
+
+// Reply
+function reply(status_code) {
+ var to,
+ response = "SIP/2.0 " + status_code + " " + JsSIP.C.REASON_PHRASE[status_code] + "\r\n",
+ via_length = message.countHeader('via'),
+ idx = 0;
+
+ for(idx; idx < via_length; idx++) {
+ response += "Via: " + message.getHeader('via', idx) + "\r\n";
+ }
+
+ to = message.getHeader('To');
+
+ if(!message.to_tag) {
+ to += ';tag=' + JsSIP.Utils.newTag();
+ }
+
+ response += "To: " + to + "\r\n";
+ response += "From: " + message.getHeader('From') + "\r\n";
+ response += "Call-ID: " + message.call_id + "\r\n";
+ response += "CSeq: " + message.cseq + " " + message.method + "\r\n";
+ response += "\r\n";
+
+ transport.send(response);
+}
+
+requests.push(rfc3261_8_2_2_1);
+requests.push(rfc3261_16_3_4);
+requests.push(rfc3261_18_3_request);
+requests.push(rfc3261_8_2_2_2);
+
+responses.push(rfc3261_8_1_3_3);
+responses.push(rfc3261_18_1_2);
+responses.push(rfc3261_18_3_response);
+
+all.push(minimumHeaders);
+
+sanityCheck = function(m, u, t) {
+ var len, pass;
+
+ message = m;
+ ua = u;
+ transport = t;
+
+ len = all.length;
+ while(len--) {
+ pass = all[len](message);
+ if(pass === false) {
+ return false;
+ }
+ }
+
+ if(message instanceof JsSIP.IncomingRequest) {
+ len = requests.length;
+ while(len--) {
+ pass = requests[len](message);
+ if(pass === false) {
+ return false;
+ }
+ }
+ }
+
+ else if(message instanceof JsSIP.IncomingResponse) {
+ len = responses.length;
+ while(len--) {
+ pass = responses[len](message);
+ if(pass === false) {
+ return false;
+ }
+ }
+ }
+
+ //Everything is OK
+ return true;
+};
+
+JsSIP.sanityCheck = sanityCheck;
+}(JsSIP));
+
+
+
+
+/**
+ * @fileoverview SIP Digest Authentication
+ */
+
+/**
+ * SIP Digest Authentication.
+ * @augments JsSIP.
+ * @function Digest Authentication
+ * @param {JsSIP.UA} ua
+ */
+(function(JsSIP) {
+var DigestAuthentication,
+ LOG_PREFIX = JsSIP.name +' | '+ 'DIGEST AUTHENTICATION' +' | ';
+
+DigestAuthentication = function(ua) {
+ this.username = ua.configuration.authorization_user;
+ this.password = ua.configuration.password;
+ this.cnonce = null;
+ this.nc = 0;
+ this.ncHex = '00000000';
+ this.response = null;
+};
+
+
+/**
+* Performs Digest authentication given a SIP request and the challenge
+* received in a response to that request.
+* Returns true if credentials were successfully generated, false otherwise.
+*
+* @param {JsSIP.OutgoingRequest} request
+* @param {Object} challenge
+*/
+DigestAuthentication.prototype.authenticate = function(request, challenge) {
+ // Inspect and validate the challenge.
+
+ this.algorithm = challenge.algorithm;
+ this.realm = challenge.realm;
+ this.nonce = challenge.nonce;
+ this.opaque = challenge.opaque;
+ this.stale = challenge.stale;
+
+ if (this.algorithm) {
+ if (this.algorithm !== 'MD5') {
+ console.warn(LOG_PREFIX + 'challenge with Digest algorithm different than "MD5", authentication aborted');
+ return false;
+ }
+ } else {
+ this.algorithm = 'MD5';
+ }
+
+ if (! this.realm) {
+ console.warn(LOG_PREFIX + 'challenge without Digest realm, authentication aborted');
+ return false;
+ }
+
+ if (! this.nonce) {
+ console.warn(LOG_PREFIX + 'challenge without Digest nonce, authentication aborted');
+ return false;
+ }
+
+ // 'qop' can contain a list of values (Array). Let's choose just one.
+ if (challenge.qop) {
+ if (challenge.qop.indexOf('auth') > -1) {
+ this.qop = 'auth';
+ } else if (challenge.qop.indexOf('auth-int') > -1) {
+ this.qop = 'auth-int';
+ } else {
+ // Otherwise 'qop' is present but does not contain 'auth' or 'auth-int', so abort here.
+ console.warn(LOG_PREFIX + 'challenge without Digest qop different than "auth" or "auth-int", authentication aborted');
+ return false;
+ }
+ } else {
+ this.qop = null;
+ }
+
+ // Fill other attributes.
+
+ this.method = request.method;
+ this.uri = request.ruri;
+ this.cnonce = JsSIP.Utils.createRandomToken(12);
+ this.nc += 1;
+ this.updateNcHex();
+
+ // nc-value = 8LHEX. Max value = 'FFFFFFFF'.
+ if (this.nc === 4294967296) {
+ this.nc = 1;
+ this.ncHex = '00000001';
+ }
+
+ // Calculate the Digest "response" value.
+ this.calculateResponse();
+
+ return true;
+};
+
+
+/**
+* Generate Digest 'response' value.
+* @private
+*/
+DigestAuthentication.prototype.calculateResponse = function() {
+ var ha1, ha2;
+
+ // HA1 = MD5(A1) = MD5(username:realm:password)
+ ha1 = JsSIP.Utils.calculateMD5(this.username + ":" + this.realm + ":" + this.password);
+
+ if (this.qop === 'auth') {
+ // HA2 = MD5(A2) = MD5(method:digestURI)
+ ha2 = JsSIP.Utils.calculateMD5(this.method + ":" + this.uri);
+ // response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2)
+ this.response = JsSIP.Utils.calculateMD5(ha1 + ":" + this.nonce + ":" + this.ncHex + ":" + this.cnonce + ":auth:" + ha2);
+
+ } else if (this.qop === 'auth-int') {
+ // HA2 = MD5(A2) = MD5(method:digestURI:MD5(entityBody))
+ ha2 = JsSIP.Utils.calculateMD5(this.method + ":" + this.uri + ":" + JsSIP.Utils.calculateMD5(this.body ? this.body : ""));
+ // response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2)
+ this.response = JsSIP.Utils.calculateMD5(ha1 + ":" + this.nonce + ":" + this.ncHex + ":" + this.cnonce + ":auth-int:" + ha2);
+
+ } else if (this.qop === null) {
+ // HA2 = MD5(A2) = MD5(method:digestURI)
+ ha2 = JsSIP.Utils.calculateMD5(this.method + ":" + this.uri);
+ // response = MD5(HA1:nonce:HA2)
+ this.response = JsSIP.Utils.calculateMD5(ha1 + ":" + this.nonce + ":" + ha2);
+ }
+};
+
+
+/**
+* Return the Proxy-Authorization or WWW-Authorization header value.
+*/
+DigestAuthentication.prototype.toString = function() {
+ var auth_params = [];
+
+ if (! this.response) {
+ throw new Error('response field does not exist, cannot generate Authorization header');
+ }
+
+ auth_params.push('algorithm=' + this.algorithm);
+ auth_params.push('username="' + this.username + '"');
+ auth_params.push('realm="' + this.realm + '"');
+ auth_params.push('nonce="' + this.nonce + '"');
+ auth_params.push('uri="' + this.uri + '"');
+ auth_params.push('response="' + this.response + '"');
+ if (this.opaque) {
+ auth_params.push('opaque="' + this.opaque + '"');
+ }
+ if (this.qop) {
+ auth_params.push('qop=' + this.qop);
+ auth_params.push('cnonce="' + this.cnonce + '"');
+ auth_params.push('nc=' + this.ncHex);
+ }
+
+ return 'Digest ' + auth_params.join(', ');
+};
+
+
+/**
+* Generate the 'nc' value as required by Digest in this.ncHex by reading this.nc.
+* @private
+*/
+DigestAuthentication.prototype.updateNcHex = function() {
+ var hex = Number(this.nc).toString(16);
+ this.ncHex = '00000000'.substr(0, 8-hex.length) + hex;
+};
+
+JsSIP.DigestAuthentication = DigestAuthentication;
+}(JsSIP));
+
+
+/**
+ * @fileoverview WebRTC
+ */
+
+(function(JsSIP) {
+var WebRTC;
+
+WebRTC = {};
+
+// getUserMedia
+if (window.navigator.webkitGetUserMedia) {
+ WebRTC.getUserMedia = window.navigator.webkitGetUserMedia.bind(navigator);
+}
+else if (window.navigator.mozGetUserMedia) {
+ WebRTC.getUserMedia = window.navigator.mozGetUserMedia.bind(navigator);
+}
+else if (window.navigator.getUserMedia) {
+ WebRTC.getUserMedia = window.navigator.getUserMedia.bind(navigator);
+}
+
+// RTCPeerConnection
+if (window.webkitRTCPeerConnection) {
+ WebRTC.RTCPeerConnection = window.webkitRTCPeerConnection;
+}
+else if (window.mozRTCPeerConnection) {
+ WebRTC.RTCPeerConnection = window.mozRTCPeerConnection;
+}
+else if (window.RTCPeerConnection) {
+ WebRTC.RTCPeerConnection = window.RTCPeerConnection;
+}
+
+// RTCSessionDescription
+if (window.webkitRTCSessionDescription) {
+ WebRTC.RTCSessionDescription = window.webkitRTCSessionDescription;
+}
+else if (window.mozRTCSessionDescription) {
+ WebRTC.RTCSessionDescription = window.mozRTCSessionDescription;
+}
+else if (window.RTCSessionDescription) {
+ WebRTC.RTCSessionDescription = window.RTCSessionDescription;
+}
+
+// New syntax for getting streams in Chrome M26.
+if (WebRTC.RTCPeerConnection && WebRTC.RTCPeerConnection.prototype) {
+ if (!WebRTC.RTCPeerConnection.prototype.getLocalStreams) {
+ WebRTC.RTCPeerConnection.prototype.getLocalStreams = function() {
+ return this.localStreams;
+ };
+ WebRTC.RTCPeerConnection.prototype.getRemoteStreams = function() {
+ return this.remoteStreams;
+ };
+ }
+}
+
+// isSupported attribute.
+if (WebRTC.getUserMedia && WebRTC.RTCPeerConnection && WebRTC.RTCSessionDescription) {
+ WebRTC.isSupported = true;
+}
+else {
+ WebRTC.isSupported = false;
+}
+
+JsSIP.WebRTC = WebRTC;
+}(JsSIP));
+
+
+
+window.JsSIP = JsSIP;
+}(window));
+
+
+JsSIP.Grammar = (function(){
+ /*
+ * Generated by PEG.js 0.7.0.
+ *
+ * http://pegjs.majda.cz/
+ */
+
+ function quote(s) {
+ /*
+ * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a
+ * string literal except for the closing quote character, backslash,
+ * carriage return, line separator, paragraph separator, and line feed.
+ * Any character may appear in the form of an escape sequence.
+ *
+ * For portability, we also escape escape all control and non-ASCII
+ * characters. Note that "\0" and "\v" escape sequences are not used
+ * because JSHint does not like the first and IE the second.
+ */
+ return '"' + s
+ .replace(/\\/g, '\\\\') // backslash
+ .replace(/"/g, '\\"') // closing quote character
+ .replace(/\x08/g, '\\b') // backspace
+ .replace(/\t/g, '\\t') // horizontal tab
+ .replace(/\n/g, '\\n') // line feed
+ .replace(/\f/g, '\\f') // form feed
+ .replace(/\r/g, '\\r') // carriage return
+ .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape)
+ + '"';
+ }
+
+ var result = {
+ /*
+ * Parses the input with a generated parser. If the parsing is successfull,
+ * returns a value explicitly or implicitly specified by the grammar from
+ * which the parser was generated (see |PEG.buildParser|). If the parsing is
+ * unsuccessful, throws |PEG.parser.SyntaxError| describing the error.
+ */
+ parse: function(input, startRule) {
+ var parseFunctions = {
+ "CRLF": parse_CRLF,
+ "DIGIT": parse_DIGIT,
+ "ALPHA": parse_ALPHA,
+ "HEXDIG": parse_HEXDIG,
+ "WSP": parse_WSP,
+ "OCTET": parse_OCTET,
+ "DQUOTE": parse_DQUOTE,
+ "SP": parse_SP,
+ "HTAB": parse_HTAB,
+ "alphanum": parse_alphanum,
+ "reserved": parse_reserved,
+ "unreserved": parse_unreserved,
+ "mark": parse_mark,
+ "escaped": parse_escaped,
+ "LWS": parse_LWS,
+ "SWS": parse_SWS,
+ "HCOLON": parse_HCOLON,
+ "TEXT_UTF8_TRIM": parse_TEXT_UTF8_TRIM,
+ "TEXT_UTF8char": parse_TEXT_UTF8char,
+ "UTF8_NONASCII": parse_UTF8_NONASCII,
+ "UTF8_CONT": parse_UTF8_CONT,
+ "LHEX": parse_LHEX,
+ "token": parse_token,
+ "token_nodot": parse_token_nodot,
+ "separators": parse_separators,
+ "word": parse_word,
+ "STAR": parse_STAR,
+ "SLASH": parse_SLASH,
+ "EQUAL": parse_EQUAL,
+ "LPAREN": parse_LPAREN,
+ "RPAREN": parse_RPAREN,
+ "RAQUOT": parse_RAQUOT,
+ "LAQUOT": parse_LAQUOT,
+ "COMMA": parse_COMMA,
+ "SEMI": parse_SEMI,
+ "COLON": parse_COLON,
+ "LDQUOT": parse_LDQUOT,
+ "RDQUOT": parse_RDQUOT,
+ "comment": parse_comment,
+ "ctext": parse_ctext,
+ "quoted_string": parse_quoted_string,
+ "quoted_string_clean": parse_quoted_string_clean,
+ "qdtext": parse_qdtext,
+ "quoted_pair": parse_quoted_pair,
+ "SIP_URI_noparams": parse_SIP_URI_noparams,
+ "SIP_URI": parse_SIP_URI,
+ "uri_scheme": parse_uri_scheme,
+ "userinfo": parse_userinfo,
+ "user": parse_user,
+ "user_unreserved": parse_user_unreserved,
+ "password": parse_password,
+ "hostport": parse_hostport,
+ "host": parse_host,
+ "hostname": parse_hostname,
+ "domainlabel": parse_domainlabel,
+ "toplabel": parse_toplabel,
+ "IPv6reference": parse_IPv6reference,
+ "IPv6address": parse_IPv6address,
+ "h16": parse_h16,
+ "ls32": parse_ls32,
+ "IPv4address": parse_IPv4address,
+ "dec_octet": parse_dec_octet,
+ "port": parse_port,
+ "uri_parameters": parse_uri_parameters,
+ "uri_parameter": parse_uri_parameter,
+ "transport_param": parse_transport_param,
+ "user_param": parse_user_param,
+ "method_param": parse_method_param,
+ "ttl_param": parse_ttl_param,
+ "maddr_param": parse_maddr_param,
+ "lr_param": parse_lr_param,
+ "other_param": parse_other_param,
+ "pname": parse_pname,
+ "pvalue": parse_pvalue,
+ "paramchar": parse_paramchar,
+ "param_unreserved": parse_param_unreserved,
+ "headers": parse_headers,
+ "header": parse_header,
+ "hname": parse_hname,
+ "hvalue": parse_hvalue,
+ "hnv_unreserved": parse_hnv_unreserved,
+ "Request_Response": parse_Request_Response,
+ "Request_Line": parse_Request_Line,
+ "Request_URI": parse_Request_URI,
+ "absoluteURI": parse_absoluteURI,
+ "hier_part": parse_hier_part,
+ "net_path": parse_net_path,
+ "abs_path": parse_abs_path,
+ "opaque_part": parse_opaque_part,
+ "uric": parse_uric,
+ "uric_no_slash": parse_uric_no_slash,
+ "path_segments": parse_path_segments,
+ "segment": parse_segment,
+ "param": parse_param,
+ "pchar": parse_pchar,
+ "scheme": parse_scheme,
+ "authority": parse_authority,
+ "srvr": parse_srvr,
+ "reg_name": parse_reg_name,
+ "query": parse_query,
+ "SIP_Version": parse_SIP_Version,
+ "INVITEm": parse_INVITEm,
+ "ACKm": parse_ACKm,
+ "OPTIONSm": parse_OPTIONSm,
+ "BYEm": parse_BYEm,
+ "CANCELm": parse_CANCELm,
+ "REGISTERm": parse_REGISTERm,
+ "SUBSCRIBEm": parse_SUBSCRIBEm,
+ "NOTIFYm": parse_NOTIFYm,
+ "Method": parse_Method,
+ "Status_Line": parse_Status_Line,
+ "Status_Code": parse_Status_Code,
+ "extension_code": parse_extension_code,
+ "Reason_Phrase": parse_Reason_Phrase,
+ "Allow_Events": parse_Allow_Events,
+ "Call_ID": parse_Call_ID,
+ "Contact": parse_Contact,
+ "contact_param": parse_contact_param,
+ "name_addr": parse_name_addr,
+ "display_name": parse_display_name,
+ "contact_params": parse_contact_params,
+ "c_p_q": parse_c_p_q,
+ "c_p_expires": parse_c_p_expires,
+ "delta_seconds": parse_delta_seconds,
+ "qvalue": parse_qvalue,
+ "generic_param": parse_generic_param,
+ "gen_value": parse_gen_value,
+ "Content_Disposition": parse_Content_Disposition,
+ "disp_type": parse_disp_type,
+ "disp_param": parse_disp_param,
+ "handling_param": parse_handling_param,
+ "Content_Encoding": parse_Content_Encoding,
+ "Content_Length": parse_Content_Length,
+ "Content_Type": parse_Content_Type,
+ "media_type": parse_media_type,
+ "m_type": parse_m_type,
+ "discrete_type": parse_discrete_type,
+ "composite_type": parse_composite_type,
+ "extension_token": parse_extension_token,
+ "x_token": parse_x_token,
+ "m_subtype": parse_m_subtype,
+ "m_parameter": parse_m_parameter,
+ "m_value": parse_m_value,
+ "CSeq": parse_CSeq,
+ "CSeq_value": parse_CSeq_value,
+ "Expires": parse_Expires,
+ "Event": parse_Event,
+ "event_type": parse_event_type,
+ "From": parse_From,
+ "from_param": parse_from_param,
+ "tag_param": parse_tag_param,
+ "Max_Forwards": parse_Max_Forwards,
+ "Min_Expires": parse_Min_Expires,
+ "Name_Addr_Header": parse_Name_Addr_Header,
+ "Proxy_Authenticate": parse_Proxy_Authenticate,
+ "challenge": parse_challenge,
+ "other_challenge": parse_other_challenge,
+ "auth_param": parse_auth_param,
+ "digest_cln": parse_digest_cln,
+ "realm": parse_realm,
+ "realm_value": parse_realm_value,
+ "domain": parse_domain,
+ "URI": parse_URI,
+ "nonce": parse_nonce,
+ "nonce_value": parse_nonce_value,
+ "opaque": parse_opaque,
+ "stale": parse_stale,
+ "algorithm": parse_algorithm,
+ "qop_options": parse_qop_options,
+ "qop_value": parse_qop_value,
+ "Proxy_Require": parse_Proxy_Require,
+ "Record_Route": parse_Record_Route,
+ "rec_route": parse_rec_route,
+ "Require": parse_Require,
+ "Route": parse_Route,
+ "route_param": parse_route_param,
+ "Subscription_State": parse_Subscription_State,
+ "substate_value": parse_substate_value,
+ "subexp_params": parse_subexp_params,
+ "event_reason_value": parse_event_reason_value,
+ "Subject": parse_Subject,
+ "Supported": parse_Supported,
+ "To": parse_To,
+ "to_param": parse_to_param,
+ "Via": parse_Via,
+ "via_parm": parse_via_parm,
+ "via_params": parse_via_params,
+ "via_ttl": parse_via_ttl,
+ "via_maddr": parse_via_maddr,
+ "via_received": parse_via_received,
+ "via_branch": parse_via_branch,
+ "response_port": parse_response_port,
+ "sent_protocol": parse_sent_protocol,
+ "protocol_name": parse_protocol_name,
+ "transport": parse_transport,
+ "sent_by": parse_sent_by,
+ "via_host": parse_via_host,
+ "via_port": parse_via_port,
+ "ttl": parse_ttl,
+ "WWW_Authenticate": parse_WWW_Authenticate,
+ "extension_header": parse_extension_header,
+ "header_value": parse_header_value,
+ "message_body": parse_message_body,
+ "stun_URI": parse_stun_URI,
+ "stun_scheme": parse_stun_scheme,
+ "stun_host_port": parse_stun_host_port,
+ "stun_host": parse_stun_host,
+ "reg_name": parse_reg_name,
+ "stun_unreserved": parse_stun_unreserved,
+ "sub_delims": parse_sub_delims,
+ "turn_URI": parse_turn_URI,
+ "turn_scheme": parse_turn_scheme,
+ "turn_transport": parse_turn_transport
+ };
+
+ if (startRule !== undefined) {
+ if (parseFunctions[startRule] === undefined) {
+ throw new Error("Invalid rule name: " + quote(startRule) + ".");
+ }
+ } else {
+ startRule = "CRLF";
+ }
+
+ var pos = 0;
+ var reportFailures = 0;
+ var rightmostFailuresPos = 0;
+ var rightmostFailuresExpected = [];
+
+ function padLeft(input, padding, length) {
+ var result = input;
+
+ var padLength = length - input.length;
+ for (var i = 0; i < padLength; i++) {
+ result = padding + result;
+ }
+
+ return result;
+ }
+
+ function escape(ch) {
+ var charCode = ch.charCodeAt(0);
+ var escapeChar;
+ var length;
+
+ if (charCode <= 0xFF) {
+ escapeChar = 'x';
+ length = 2;
+ } else {
+ escapeChar = 'u';
+ length = 4;
+ }
+
+ return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length);
+ }
+
+ function matchFailed(failure) {
+ if (pos < rightmostFailuresPos) {
+ return;
+ }
+
+ if (pos > rightmostFailuresPos) {
+ rightmostFailuresPos = pos;
+ rightmostFailuresExpected = [];
+ }
+
+ rightmostFailuresExpected.push(failure);
+ }
+
+ function parse_CRLF() {
+ var result0;
+
+ if (input.substr(pos, 2) === "\r\n") {
+ result0 = "\r\n";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"\\r\\n\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_DIGIT() {
+ var result0;
+
+ if (/^[0-9]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[0-9]");
+ }
+ }
+ return result0;
+ }
+
+ function parse_ALPHA() {
+ var result0;
+
+ if (/^[a-zA-Z]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[a-zA-Z]");
+ }
+ }
+ return result0;
+ }
+
+ function parse_HEXDIG() {
+ var result0;
+
+ if (/^[0-9a-fA-F]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[0-9a-fA-F]");
+ }
+ }
+ return result0;
+ }
+
+ function parse_WSP() {
+ var result0;
+
+ result0 = parse_SP();
+ if (result0 === null) {
+ result0 = parse_HTAB();
+ }
+ return result0;
+ }
+
+ function parse_OCTET() {
+ var result0;
+
+ if (/^[\0-\xFF]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[\\0-\\xFF]");
+ }
+ }
+ return result0;
+ }
+
+ function parse_DQUOTE() {
+ var result0;
+
+ if (/^["]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[\"]");
+ }
+ }
+ return result0;
+ }
+
+ function parse_SP() {
+ var result0;
+
+ if (input.charCodeAt(pos) === 32) {
+ result0 = " ";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\" \"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_HTAB() {
+ var result0;
+
+ if (input.charCodeAt(pos) === 9) {
+ result0 = "\t";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"\\t\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_alphanum() {
+ var result0;
+
+ if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[a-zA-Z0-9]");
+ }
+ }
+ return result0;
+ }
+
+ function parse_reserved() {
+ var result0;
+
+ if (input.charCodeAt(pos) === 59) {
+ result0 = ";";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 47) {
+ result0 = "/";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 63) {
+ result0 = "?";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result0 = ":";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 64) {
+ result0 = "@";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"@\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 38) {
+ result0 = "&";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result0 = "=";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result0 = "+";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result0 = "$";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result0 = ",";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_unreserved() {
+ var result0;
+
+ result0 = parse_alphanum();
+ if (result0 === null) {
+ result0 = parse_mark();
+ }
+ return result0;
+ }
+
+ function parse_mark() {
+ var result0;
+
+ if (input.charCodeAt(pos) === 45) {
+ result0 = "-";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 95) {
+ result0 = "_";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"_\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 46) {
+ result0 = ".";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 33) {
+ result0 = "!";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"!\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 126) {
+ result0 = "~";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"~\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 42) {
+ result0 = "*";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"*\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 39) {
+ result0 = "'";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"'\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 40) {
+ result0 = "(";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"(\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 41) {
+ result0 = ")";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\")\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_escaped() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 37) {
+ result0 = "%";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"%\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_HEXDIG();
+ if (result1 !== null) {
+ result2 = parse_HEXDIG();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, escaped) {return escaped.join(''); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_LWS() {
+ var result0, result1, result2;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ pos2 = pos;
+ result0 = [];
+ result1 = parse_WSP();
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_WSP();
+ }
+ if (result0 !== null) {
+ result1 = parse_CRLF();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos2;
+ }
+ } else {
+ result0 = null;
+ pos = pos2;
+ }
+ result0 = result0 !== null ? result0 : "";
+ if (result0 !== null) {
+ result2 = parse_WSP();
+ if (result2 !== null) {
+ result1 = [];
+ while (result2 !== null) {
+ result1.push(result2);
+ result2 = parse_WSP();
+ }
+ } else {
+ result1 = null;
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return " "; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_SWS() {
+ var result0;
+
+ result0 = parse_LWS();
+ result0 = result0 !== null ? result0 : "";
+ return result0;
+ }
+
+ function parse_HCOLON() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = [];
+ result1 = parse_SP();
+ if (result1 === null) {
+ result1 = parse_HTAB();
+ }
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_SP();
+ if (result1 === null) {
+ result1 = parse_HTAB();
+ }
+ }
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_SWS();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return ':'; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_TEXT_UTF8_TRIM() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result1 = parse_TEXT_UTF8char();
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_TEXT_UTF8char();
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result1 = [];
+ pos2 = pos;
+ result2 = [];
+ result3 = parse_LWS();
+ while (result3 !== null) {
+ result2.push(result3);
+ result3 = parse_LWS();
+ }
+ if (result2 !== null) {
+ result3 = parse_TEXT_UTF8char();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos2 = pos;
+ result2 = [];
+ result3 = parse_LWS();
+ while (result3 !== null) {
+ result2.push(result3);
+ result3 = parse_LWS();
+ }
+ if (result2 !== null) {
+ result3 = parse_TEXT_UTF8char();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_TEXT_UTF8char() {
+ var result0;
+
+ if (/^[!-~]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[!-~]");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_UTF8_NONASCII();
+ }
+ return result0;
+ }
+
+ function parse_UTF8_NONASCII() {
+ var result0;
+
+ if (/^[\x80-\uFFFF]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[\\x80-\\uFFFF]");
+ }
+ }
+ return result0;
+ }
+
+ function parse_UTF8_CONT() {
+ var result0;
+
+ if (/^[\x80-\xBF]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[\\x80-\\xBF]");
+ }
+ }
+ return result0;
+ }
+
+ function parse_LHEX() {
+ var result0;
+
+ result0 = parse_DIGIT();
+ if (result0 === null) {
+ if (/^[a-f]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[a-f]");
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_token() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result1 = parse_alphanum();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 45) {
+ result1 = "-";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 46) {
+ result1 = ".";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 33) {
+ result1 = "!";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"!\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 37) {
+ result1 = "%";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"%\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 42) {
+ result1 = "*";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"*\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 95) {
+ result1 = "_";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"_\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 96) {
+ result1 = "`";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"`\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 39) {
+ result1 = "'";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"'\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 126) {
+ result1 = "~";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"~\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_alphanum();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 45) {
+ result1 = "-";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 46) {
+ result1 = ".";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 33) {
+ result1 = "!";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"!\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 37) {
+ result1 = "%";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"%\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 42) {
+ result1 = "*";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"*\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 95) {
+ result1 = "_";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"_\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 96) {
+ result1 = "`";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"`\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 39) {
+ result1 = "'";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"'\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 126) {
+ result1 = "~";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"~\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_token_nodot() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result1 = parse_alphanum();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 45) {
+ result1 = "-";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 33) {
+ result1 = "!";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"!\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 37) {
+ result1 = "%";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"%\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 42) {
+ result1 = "*";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"*\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 95) {
+ result1 = "_";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"_\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 96) {
+ result1 = "`";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"`\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 39) {
+ result1 = "'";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"'\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 126) {
+ result1 = "~";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"~\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_alphanum();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 45) {
+ result1 = "-";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 33) {
+ result1 = "!";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"!\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 37) {
+ result1 = "%";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"%\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 42) {
+ result1 = "*";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"*\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 95) {
+ result1 = "_";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"_\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 96) {
+ result1 = "`";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"`\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 39) {
+ result1 = "'";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"'\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 126) {
+ result1 = "~";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"~\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_separators() {
+ var result0;
+
+ if (input.charCodeAt(pos) === 40) {
+ result0 = "(";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"(\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 41) {
+ result0 = ")";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\")\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 60) {
+ result0 = "<";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"<\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 62) {
+ result0 = ">";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\">\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 64) {
+ result0 = "@";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"@\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result0 = ",";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 59) {
+ result0 = ";";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result0 = ":";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 92) {
+ result0 = "\\";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"\\\\\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_DQUOTE();
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 47) {
+ result0 = "/";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 91) {
+ result0 = "[";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"[\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 93) {
+ result0 = "]";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"]\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 63) {
+ result0 = "?";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result0 = "=";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 123) {
+ result0 = "{";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"{\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 125) {
+ result0 = "}";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"}\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_SP();
+ if (result0 === null) {
+ result0 = parse_HTAB();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_word() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result1 = parse_alphanum();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 45) {
+ result1 = "-";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 46) {
+ result1 = ".";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 33) {
+ result1 = "!";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"!\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 37) {
+ result1 = "%";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"%\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 42) {
+ result1 = "*";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"*\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 95) {
+ result1 = "_";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"_\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 96) {
+ result1 = "`";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"`\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 39) {
+ result1 = "'";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"'\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 126) {
+ result1 = "~";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"~\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 40) {
+ result1 = "(";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"(\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 41) {
+ result1 = ")";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\")\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 60) {
+ result1 = "<";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"<\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 62) {
+ result1 = ">";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\">\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 92) {
+ result1 = "\\";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"\\\\\"");
+ }
+ }
+ if (result1 === null) {
+ result1 = parse_DQUOTE();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 47) {
+ result1 = "/";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 91) {
+ result1 = "[";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"[\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 93) {
+ result1 = "]";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"]\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 63) {
+ result1 = "?";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 123) {
+ result1 = "{";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"{\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 125) {
+ result1 = "}";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"}\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_alphanum();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 45) {
+ result1 = "-";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 46) {
+ result1 = ".";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 33) {
+ result1 = "!";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"!\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 37) {
+ result1 = "%";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"%\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 42) {
+ result1 = "*";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"*\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 95) {
+ result1 = "_";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"_\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 96) {
+ result1 = "`";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"`\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 39) {
+ result1 = "'";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"'\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 126) {
+ result1 = "~";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"~\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 40) {
+ result1 = "(";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"(\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 41) {
+ result1 = ")";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\")\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 60) {
+ result1 = "<";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"<\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 62) {
+ result1 = ">";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\">\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 92) {
+ result1 = "\\";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"\\\\\"");
+ }
+ }
+ if (result1 === null) {
+ result1 = parse_DQUOTE();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 47) {
+ result1 = "/";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 91) {
+ result1 = "[";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"[\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 93) {
+ result1 = "]";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"]\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 63) {
+ result1 = "?";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 123) {
+ result1 = "{";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"{\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 125) {
+ result1 = "}";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"}\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_STAR() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 42) {
+ result1 = "*";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"*\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_SWS();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return "*"; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_SLASH() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 47) {
+ result1 = "/";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_SWS();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return "/"; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_EQUAL() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 61) {
+ result1 = "=";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_SWS();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return "="; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_LPAREN() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 40) {
+ result1 = "(";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"(\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_SWS();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return "("; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_RPAREN() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 41) {
+ result1 = ")";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\")\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_SWS();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return ")"; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_RAQUOT() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 62) {
+ result0 = ">";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\">\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_SWS();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return ">"; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_LAQUOT() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 60) {
+ result1 = "<";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"<\"");
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return "<"; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_COMMA() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 44) {
+ result1 = ",";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_SWS();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return ","; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_SEMI() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 59) {
+ result1 = ";";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_SWS();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return ";"; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_COLON() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_SWS();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return ":"; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_LDQUOT() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ result1 = parse_DQUOTE();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return "\""; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_RDQUOT() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_DQUOTE();
+ if (result0 !== null) {
+ result1 = parse_SWS();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {return "\""; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_comment() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_LPAREN();
+ if (result0 !== null) {
+ result1 = [];
+ result2 = parse_ctext();
+ if (result2 === null) {
+ result2 = parse_quoted_pair();
+ if (result2 === null) {
+ result2 = parse_comment();
+ }
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ result2 = parse_ctext();
+ if (result2 === null) {
+ result2 = parse_quoted_pair();
+ if (result2 === null) {
+ result2 = parse_comment();
+ }
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_RPAREN();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_ctext() {
+ var result0;
+
+ if (/^[!-']/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[!-']");
+ }
+ }
+ if (result0 === null) {
+ if (/^[*-[]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[*-[]");
+ }
+ }
+ if (result0 === null) {
+ if (/^[\]-~]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[\\]-~]");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_UTF8_NONASCII();
+ if (result0 === null) {
+ result0 = parse_LWS();
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_quoted_string() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ result1 = parse_DQUOTE();
+ if (result1 !== null) {
+ result2 = [];
+ result3 = parse_qdtext();
+ if (result3 === null) {
+ result3 = parse_quoted_pair();
+ }
+ while (result3 !== null) {
+ result2.push(result3);
+ result3 = parse_qdtext();
+ if (result3 === null) {
+ result3 = parse_quoted_pair();
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_DQUOTE();
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_quoted_string_clean() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SWS();
+ if (result0 !== null) {
+ result1 = parse_DQUOTE();
+ if (result1 !== null) {
+ result2 = [];
+ result3 = parse_qdtext();
+ if (result3 === null) {
+ result3 = parse_quoted_pair();
+ }
+ while (result3 !== null) {
+ result2.push(result3);
+ result3 = parse_qdtext();
+ if (result3 === null) {
+ result3 = parse_quoted_pair();
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_DQUOTE();
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ return input.substring(pos-1, offset+1); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_qdtext() {
+ var result0;
+
+ result0 = parse_LWS();
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 33) {
+ result0 = "!";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"!\"");
+ }
+ }
+ if (result0 === null) {
+ if (/^[#-[]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[#-[]");
+ }
+ }
+ if (result0 === null) {
+ if (/^[\]-~]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[\\]-~]");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_UTF8_NONASCII();
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_quoted_pair() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ if (input.charCodeAt(pos) === 92) {
+ result0 = "\\";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"\\\\\"");
+ }
+ }
+ if (result0 !== null) {
+ if (/^[\0-\t]/.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[\\0-\\t]");
+ }
+ }
+ if (result1 === null) {
+ if (/^[\x0B-\f]/.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[\\x0B-\\f]");
+ }
+ }
+ if (result1 === null) {
+ if (/^[\x0E-]/.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[\\x0E-]");
+ }
+ }
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_SIP_URI_noparams() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_uri_scheme();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_userinfo();
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ result3 = parse_hostport();
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ try {
+ data.uri = new JsSIP.URI(data.scheme, data.user, data.host, data.port);
+ delete data.scheme;
+ delete data.user;
+ delete data.host;
+ delete data.host_type;
+ delete data.port;
+ } catch(e) {
+ data = -1;
+ }})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_SIP_URI() {
+ var result0, result1, result2, result3, result4, result5;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_uri_scheme();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_userinfo();
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ result3 = parse_hostport();
+ if (result3 !== null) {
+ result4 = parse_uri_parameters();
+ if (result4 !== null) {
+ result5 = parse_headers();
+ result5 = result5 !== null ? result5 : "";
+ if (result5 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ var header;
+ try {
+ data.uri = new JsSIP.URI(data.scheme, data.user, data.host, data.port, data.uri_params, data.uri_headers);
+ delete data.scheme;
+ delete data.user;
+ delete data.host;
+ delete data.host_type;
+ delete data.port;
+ delete data.uri_params;
+
+ if (startRule === 'SIP_URI') { data = data.uri;}
+ } catch(e) {
+ data = -1;
+ }})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_uri_scheme() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 3).toLowerCase() === "sip") {
+ result0 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"sip\"");
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, uri_scheme) {
+ data.scheme = uri_scheme.toLowerCase(); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_userinfo() {
+ var result0, result1, result2;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_user();
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_password();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 64) {
+ result2 = "@";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"@\"");
+ }
+ }
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.user = window.decodeURIComponent(input.substring(pos-1, offset));})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_user() {
+ var result0, result1;
+
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ result1 = parse_user_unreserved();
+ }
+ }
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ result1 = parse_user_unreserved();
+ }
+ }
+ }
+ } else {
+ result0 = null;
+ }
+ return result0;
+ }
+
+ function parse_user_unreserved() {
+ var result0;
+
+ if (input.charCodeAt(pos) === 38) {
+ result0 = "&";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result0 = "=";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result0 = "+";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result0 = "$";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result0 = ",";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 59) {
+ result0 = ";";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 63) {
+ result0 = "?";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 47) {
+ result0 = "/";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_password() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result0 = [];
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 38) {
+ result1 = "&";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result1 = "=";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result1 = "$";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result1 = ",";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 38) {
+ result1 = "&";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result1 = "=";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result1 = "$";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result1 = ",";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.password = input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_hostport() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_host();
+ if (result0 !== null) {
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_port();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos1;
+ }
+ } else {
+ result1 = null;
+ pos = pos1;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_host() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_hostname();
+ if (result0 === null) {
+ result0 = parse_IPv4address();
+ if (result0 === null) {
+ result0 = parse_IPv6reference();
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.host = input.substring(pos, offset).toLowerCase();
+ return data.host; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_hostname() {
+ var result0, result1, result2;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = [];
+ pos2 = pos;
+ result1 = parse_domainlabel();
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 46) {
+ result2 = ".";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ while (result1 !== null) {
+ result0.push(result1);
+ pos2 = pos;
+ result1 = parse_domainlabel();
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 46) {
+ result2 = ".";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_toplabel();
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 46) {
+ result2 = ".";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.host_type = 'domain';
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_domainlabel() {
+ var result0, result1;
+
+ if (/^[a-zA-Z0-9_\-]/.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[a-zA-Z0-9_\\-]");
+ }
+ }
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ if (/^[a-zA-Z0-9_\-]/.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[a-zA-Z0-9_\\-]");
+ }
+ }
+ }
+ } else {
+ result0 = null;
+ }
+ return result0;
+ }
+
+ function parse_toplabel() {
+ var result0, result1;
+
+ if (/^[a-zA-Z_\-]/.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[a-zA-Z_\\-]");
+ }
+ }
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ if (/^[a-zA-Z_\-]/.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[a-zA-Z_\\-]");
+ }
+ }
+ }
+ } else {
+ result0 = null;
+ }
+ return result0;
+ }
+
+ function parse_IPv6reference() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 91) {
+ result0 = "[";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"[\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_IPv6address();
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 93) {
+ result2 = "]";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"]\"");
+ }
+ }
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.host_type = 'IPv6';
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_IPv6address() {
+ var result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11, result12;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_h16();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_h16();
+ if (result2 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result3 = ":";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_h16();
+ if (result4 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result5 = ":";
+ pos++;
+ } else {
+ result5 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result5 !== null) {
+ result6 = parse_h16();
+ if (result6 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result7 = ":";
+ pos++;
+ } else {
+ result7 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result7 !== null) {
+ result8 = parse_h16();
+ if (result8 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result9 = ":";
+ pos++;
+ } else {
+ result9 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result9 !== null) {
+ result10 = parse_h16();
+ if (result10 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result11 = ":";
+ pos++;
+ } else {
+ result11 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result11 !== null) {
+ result12 = parse_ls32();
+ if (result12 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11, result12];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ if (input.substr(pos, 2) === "::") {
+ result0 = "::";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_h16();
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result4 = ":";
+ pos++;
+ } else {
+ result4 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_h16();
+ if (result5 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result6 = ":";
+ pos++;
+ } else {
+ result6 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result6 !== null) {
+ result7 = parse_h16();
+ if (result7 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result8 = ":";
+ pos++;
+ } else {
+ result8 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result8 !== null) {
+ result9 = parse_h16();
+ if (result9 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result10 = ":";
+ pos++;
+ } else {
+ result10 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result10 !== null) {
+ result11 = parse_ls32();
+ if (result11 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10, result11];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ if (input.substr(pos, 2) === "::") {
+ result0 = "::";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_h16();
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result4 = ":";
+ pos++;
+ } else {
+ result4 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_h16();
+ if (result5 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result6 = ":";
+ pos++;
+ } else {
+ result6 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result6 !== null) {
+ result7 = parse_h16();
+ if (result7 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result8 = ":";
+ pos++;
+ } else {
+ result8 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result8 !== null) {
+ result9 = parse_ls32();
+ if (result9 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ if (input.substr(pos, 2) === "::") {
+ result0 = "::";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_h16();
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result4 = ":";
+ pos++;
+ } else {
+ result4 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_h16();
+ if (result5 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result6 = ":";
+ pos++;
+ } else {
+ result6 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result6 !== null) {
+ result7 = parse_ls32();
+ if (result7 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ if (input.substr(pos, 2) === "::") {
+ result0 = "::";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_h16();
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result4 = ":";
+ pos++;
+ } else {
+ result4 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_ls32();
+ if (result5 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ if (input.substr(pos, 2) === "::") {
+ result0 = "::";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_h16();
+ if (result1 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_ls32();
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ if (input.substr(pos, 2) === "::") {
+ result0 = "::";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_ls32();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ if (input.substr(pos, 2) === "::") {
+ result0 = "::";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_h16();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ result0 = parse_h16();
+ if (result0 !== null) {
+ if (input.substr(pos, 2) === "::") {
+ result1 = "::";
+ pos += 2;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_h16();
+ if (result2 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result3 = ":";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_h16();
+ if (result4 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result5 = ":";
+ pos++;
+ } else {
+ result5 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result5 !== null) {
+ result6 = parse_h16();
+ if (result6 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result7 = ":";
+ pos++;
+ } else {
+ result7 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result7 !== null) {
+ result8 = parse_h16();
+ if (result8 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result9 = ":";
+ pos++;
+ } else {
+ result9 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result9 !== null) {
+ result10 = parse_ls32();
+ if (result10 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ result0 = parse_h16();
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_h16();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ if (input.substr(pos, 2) === "::") {
+ result2 = "::";
+ pos += 2;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result4 = ":";
+ pos++;
+ } else {
+ result4 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_h16();
+ if (result5 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result6 = ":";
+ pos++;
+ } else {
+ result6 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result6 !== null) {
+ result7 = parse_h16();
+ if (result7 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result8 = ":";
+ pos++;
+ } else {
+ result8 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result8 !== null) {
+ result9 = parse_ls32();
+ if (result9 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ result0 = parse_h16();
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_h16();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ if (input.substr(pos, 2) === "::") {
+ result3 = "::";
+ pos += 2;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_h16();
+ if (result4 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result5 = ":";
+ pos++;
+ } else {
+ result5 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result5 !== null) {
+ result6 = parse_h16();
+ if (result6 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result7 = ":";
+ pos++;
+ } else {
+ result7 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result7 !== null) {
+ result8 = parse_ls32();
+ if (result8 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ result0 = parse_h16();
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_h16();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result3 = ":";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_h16();
+ if (result4 !== null) {
+ result3 = [result3, result4];
+ } else {
+ result3 = null;
+ pos = pos2;
+ }
+ } else {
+ result3 = null;
+ pos = pos2;
+ }
+ result3 = result3 !== null ? result3 : "";
+ if (result3 !== null) {
+ if (input.substr(pos, 2) === "::") {
+ result4 = "::";
+ pos += 2;
+ } else {
+ result4 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_h16();
+ if (result5 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result6 = ":";
+ pos++;
+ } else {
+ result6 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result6 !== null) {
+ result7 = parse_ls32();
+ if (result7 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ result0 = parse_h16();
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_h16();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result3 = ":";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_h16();
+ if (result4 !== null) {
+ result3 = [result3, result4];
+ } else {
+ result3 = null;
+ pos = pos2;
+ }
+ } else {
+ result3 = null;
+ pos = pos2;
+ }
+ result3 = result3 !== null ? result3 : "";
+ if (result3 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result4 = ":";
+ pos++;
+ } else {
+ result4 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_h16();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos2;
+ }
+ } else {
+ result4 = null;
+ pos = pos2;
+ }
+ result4 = result4 !== null ? result4 : "";
+ if (result4 !== null) {
+ if (input.substr(pos, 2) === "::") {
+ result5 = "::";
+ pos += 2;
+ } else {
+ result5 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result5 !== null) {
+ result6 = parse_ls32();
+ if (result6 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ result0 = parse_h16();
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_h16();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result3 = ":";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_h16();
+ if (result4 !== null) {
+ result3 = [result3, result4];
+ } else {
+ result3 = null;
+ pos = pos2;
+ }
+ } else {
+ result3 = null;
+ pos = pos2;
+ }
+ result3 = result3 !== null ? result3 : "";
+ if (result3 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result4 = ":";
+ pos++;
+ } else {
+ result4 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_h16();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos2;
+ }
+ } else {
+ result4 = null;
+ pos = pos2;
+ }
+ result4 = result4 !== null ? result4 : "";
+ if (result4 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result5 = ":";
+ pos++;
+ } else {
+ result5 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result5 !== null) {
+ result6 = parse_h16();
+ if (result6 !== null) {
+ result5 = [result5, result6];
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ result5 = result5 !== null ? result5 : "";
+ if (result5 !== null) {
+ if (input.substr(pos, 2) === "::") {
+ result6 = "::";
+ pos += 2;
+ } else {
+ result6 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result6 !== null) {
+ result7 = parse_h16();
+ if (result7 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ pos1 = pos;
+ result0 = parse_h16();
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_h16();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result2 = ":";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_h16();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result3 = ":";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_h16();
+ if (result4 !== null) {
+ result3 = [result3, result4];
+ } else {
+ result3 = null;
+ pos = pos2;
+ }
+ } else {
+ result3 = null;
+ pos = pos2;
+ }
+ result3 = result3 !== null ? result3 : "";
+ if (result3 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result4 = ":";
+ pos++;
+ } else {
+ result4 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_h16();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos2;
+ }
+ } else {
+ result4 = null;
+ pos = pos2;
+ }
+ result4 = result4 !== null ? result4 : "";
+ if (result4 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result5 = ":";
+ pos++;
+ } else {
+ result5 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result5 !== null) {
+ result6 = parse_h16();
+ if (result6 !== null) {
+ result5 = [result5, result6];
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ result5 = result5 !== null ? result5 : "";
+ if (result5 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result6 = ":";
+ pos++;
+ } else {
+ result6 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result6 !== null) {
+ result7 = parse_h16();
+ if (result7 !== null) {
+ result6 = [result6, result7];
+ } else {
+ result6 = null;
+ pos = pos2;
+ }
+ } else {
+ result6 = null;
+ pos = pos2;
+ }
+ result6 = result6 !== null ? result6 : "";
+ if (result6 !== null) {
+ if (input.substr(pos, 2) === "::") {
+ result7 = "::";
+ pos += 2;
+ } else {
+ result7 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"::\"");
+ }
+ }
+ if (result7 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6, result7];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.host_type = 'IPv6';
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_h16() {
+ var result0, result1, result2, result3;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_HEXDIG();
+ if (result0 !== null) {
+ result1 = parse_HEXDIG();
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result2 = parse_HEXDIG();
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ result3 = parse_HEXDIG();
+ result3 = result3 !== null ? result3 : "";
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_ls32() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_h16();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_h16();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ if (result0 === null) {
+ result0 = parse_IPv4address();
+ }
+ return result0;
+ }
+
+ function parse_IPv4address() {
+ var result0, result1, result2, result3, result4, result5, result6;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_dec_octet();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 46) {
+ result1 = ".";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_dec_octet();
+ if (result2 !== null) {
+ if (input.charCodeAt(pos) === 46) {
+ result3 = ".";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_dec_octet();
+ if (result4 !== null) {
+ if (input.charCodeAt(pos) === 46) {
+ result5 = ".";
+ pos++;
+ } else {
+ result5 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result5 !== null) {
+ result6 = parse_dec_octet();
+ if (result6 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5, result6];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.host_type = 'IPv4';
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_dec_octet() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 2) === "25") {
+ result0 = "25";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"25\"");
+ }
+ }
+ if (result0 !== null) {
+ if (/^[0-5]/.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[0-5]");
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ if (result0 === null) {
+ pos0 = pos;
+ if (input.charCodeAt(pos) === 50) {
+ result0 = "2";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"2\"");
+ }
+ }
+ if (result0 !== null) {
+ if (/^[0-4]/.test(input.charAt(pos))) {
+ result1 = input.charAt(pos);
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("[0-4]");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_DIGIT();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ if (result0 === null) {
+ pos0 = pos;
+ if (input.charCodeAt(pos) === 49) {
+ result0 = "1";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"1\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_DIGIT();
+ if (result1 !== null) {
+ result2 = parse_DIGIT();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ if (result0 === null) {
+ pos0 = pos;
+ if (/^[1-9]/.test(input.charAt(pos))) {
+ result0 = input.charAt(pos);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("[1-9]");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_DIGIT();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ if (result0 === null) {
+ result0 = parse_DIGIT();
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_port() {
+ var result0, result1, result2, result3, result4;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_DIGIT();
+ result0 = result0 !== null ? result0 : "";
+ if (result0 !== null) {
+ result1 = parse_DIGIT();
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result2 = parse_DIGIT();
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ result3 = parse_DIGIT();
+ result3 = result3 !== null ? result3 : "";
+ if (result3 !== null) {
+ result4 = parse_DIGIT();
+ result4 = result4 !== null ? result4 : "";
+ if (result4 !== null) {
+ result0 = [result0, result1, result2, result3, result4];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, port) {
+ port = parseInt(port.join(''));
+ data.port = port;
+ return port; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_uri_parameters() {
+ var result0, result1, result2;
+ var pos0;
+
+ result0 = [];
+ pos0 = pos;
+ if (input.charCodeAt(pos) === 59) {
+ result1 = ";";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_uri_parameter();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos0;
+ }
+ } else {
+ result1 = null;
+ pos = pos0;
+ }
+ while (result1 !== null) {
+ result0.push(result1);
+ pos0 = pos;
+ if (input.charCodeAt(pos) === 59) {
+ result1 = ";";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_uri_parameter();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos0;
+ }
+ } else {
+ result1 = null;
+ pos = pos0;
+ }
+ }
+ return result0;
+ }
+
+ function parse_uri_parameter() {
+ var result0;
+
+ result0 = parse_transport_param();
+ if (result0 === null) {
+ result0 = parse_user_param();
+ if (result0 === null) {
+ result0 = parse_method_param();
+ if (result0 === null) {
+ result0 = parse_ttl_param();
+ if (result0 === null) {
+ result0 = parse_maddr_param();
+ if (result0 === null) {
+ result0 = parse_lr_param();
+ if (result0 === null) {
+ result0 = parse_other_param();
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_transport_param() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 10).toLowerCase() === "transport=") {
+ result0 = input.substr(pos, 10);
+ pos += 10;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"transport=\"");
+ }
+ }
+ if (result0 !== null) {
+ if (input.substr(pos, 3).toLowerCase() === "udp") {
+ result1 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"udp\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.substr(pos, 3).toLowerCase() === "tcp") {
+ result1 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"tcp\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.substr(pos, 4).toLowerCase() === "sctp") {
+ result1 = input.substr(pos, 4);
+ pos += 4;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"sctp\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.substr(pos, 3).toLowerCase() === "tls") {
+ result1 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"tls\"");
+ }
+ }
+ if (result1 === null) {
+ result1 = parse_token();
+ }
+ }
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, transport) {
+ if(!data.uri_params) data.uri_params={};
+ data.uri_params['transport'] = transport.toLowerCase(); })(pos0, result0[1]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_user_param() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 5).toLowerCase() === "user=") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"user=\"");
+ }
+ }
+ if (result0 !== null) {
+ if (input.substr(pos, 5).toLowerCase() === "phone") {
+ result1 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"phone\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.substr(pos, 2).toLowerCase() === "ip") {
+ result1 = input.substr(pos, 2);
+ pos += 2;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"ip\"");
+ }
+ }
+ if (result1 === null) {
+ result1 = parse_token();
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, user) {
+ if(!data.uri_params) data.uri_params={};
+ data.uri_params['user'] = user.toLowerCase(); })(pos0, result0[1]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_method_param() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 7).toLowerCase() === "method=") {
+ result0 = input.substr(pos, 7);
+ pos += 7;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"method=\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_Method();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, method) {
+ if(!data.uri_params) data.uri_params={};
+ data.uri_params['method'] = method; })(pos0, result0[1]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_ttl_param() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 4).toLowerCase() === "ttl=") {
+ result0 = input.substr(pos, 4);
+ pos += 4;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"ttl=\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_ttl();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, ttl) {
+ if(!data.params) data.params={};
+ data.params['ttl'] = ttl; })(pos0, result0[1]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_maddr_param() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 6).toLowerCase() === "maddr=") {
+ result0 = input.substr(pos, 6);
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"maddr=\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_host();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, maddr) {
+ if(!data.uri_params) data.uri_params={};
+ data.uri_params['maddr'] = maddr; })(pos0, result0[1]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_lr_param() {
+ var result0, result1, result2;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 2).toLowerCase() === "lr") {
+ result0 = input.substr(pos, 2);
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"lr\"");
+ }
+ }
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 61) {
+ result1 = "=";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_token();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ if(!data.uri_params) data.uri_params={};
+ data.uri_params['lr'] = undefined; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_other_param() {
+ var result0, result1, result2;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_pname();
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 61) {
+ result1 = "=";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_pvalue();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, param, value) {
+ if(!data.uri_params) data.uri_params = {};
+ if (typeof value === 'undefined'){
+ value = undefined;
+ }
+ else {
+ value = value[1];
+ }
+ data.uri_params[param.toLowerCase()] = value && value.toLowerCase();})(pos0, result0[0], result0[1]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_pname() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result1 = parse_paramchar();
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_paramchar();
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, pname) {return pname.join(''); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_pvalue() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result1 = parse_paramchar();
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_paramchar();
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, pvalue) {return pvalue.join(''); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_paramchar() {
+ var result0;
+
+ result0 = parse_param_unreserved();
+ if (result0 === null) {
+ result0 = parse_unreserved();
+ if (result0 === null) {
+ result0 = parse_escaped();
+ }
+ }
+ return result0;
+ }
+
+ function parse_param_unreserved() {
+ var result0;
+
+ if (input.charCodeAt(pos) === 91) {
+ result0 = "[";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"[\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 93) {
+ result0 = "]";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"]\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 47) {
+ result0 = "/";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result0 = ":";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 38) {
+ result0 = "&";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result0 = "+";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result0 = "$";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_headers() {
+ var result0, result1, result2, result3, result4;
+ var pos0, pos1;
+
+ pos0 = pos;
+ if (input.charCodeAt(pos) === 63) {
+ result0 = "?";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_header();
+ if (result1 !== null) {
+ result2 = [];
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 38) {
+ result3 = "&";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_header();
+ if (result4 !== null) {
+ result3 = [result3, result4];
+ } else {
+ result3 = null;
+ pos = pos1;
+ }
+ } else {
+ result3 = null;
+ pos = pos1;
+ }
+ while (result3 !== null) {
+ result2.push(result3);
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 38) {
+ result3 = "&";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_header();
+ if (result4 !== null) {
+ result3 = [result3, result4];
+ } else {
+ result3 = null;
+ pos = pos1;
+ }
+ } else {
+ result3 = null;
+ pos = pos1;
+ }
+ }
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_header() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_hname();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 61) {
+ result1 = "=";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_hvalue();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, hname, hvalue) {
+ hname = hname.join('').toLowerCase();
+ hvalue = hvalue.join('');
+ if(!data.uri_headers) data.uri_headers = {};
+ if (!data.uri_headers[hname]) {
+ data.uri_headers[hname] = [hvalue];
+ } else {
+ data.uri_headers[hname].push(hvalue);
+ }})(pos0, result0[0], result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_hname() {
+ var result0, result1;
+
+ result1 = parse_hnv_unreserved();
+ if (result1 === null) {
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ }
+ }
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_hnv_unreserved();
+ if (result1 === null) {
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ }
+ }
+ }
+ } else {
+ result0 = null;
+ }
+ return result0;
+ }
+
+ function parse_hvalue() {
+ var result0, result1;
+
+ result0 = [];
+ result1 = parse_hnv_unreserved();
+ if (result1 === null) {
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ }
+ }
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_hnv_unreserved();
+ if (result1 === null) {
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_hnv_unreserved() {
+ var result0;
+
+ if (input.charCodeAt(pos) === 91) {
+ result0 = "[";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"[\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 93) {
+ result0 = "]";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"]\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 47) {
+ result0 = "/";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 63) {
+ result0 = "?";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result0 = ":";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result0 = "+";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result0 = "$";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_Request_Response() {
+ var result0;
+
+ result0 = parse_Status_Line();
+ if (result0 === null) {
+ result0 = parse_Request_Line();
+ }
+ return result0;
+ }
+
+ function parse_Request_Line() {
+ var result0, result1, result2, result3, result4;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_Method();
+ if (result0 !== null) {
+ result1 = parse_SP();
+ if (result1 !== null) {
+ result2 = parse_Request_URI();
+ if (result2 !== null) {
+ result3 = parse_SP();
+ if (result3 !== null) {
+ result4 = parse_SIP_Version();
+ if (result4 !== null) {
+ result0 = [result0, result1, result2, result3, result4];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Request_URI() {
+ var result0;
+
+ result0 = parse_SIP_URI();
+ if (result0 === null) {
+ result0 = parse_absoluteURI();
+ }
+ return result0;
+ }
+
+ function parse_absoluteURI() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_scheme();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_hier_part();
+ if (result2 === null) {
+ result2 = parse_opaque_part();
+ }
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_hier_part() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_net_path();
+ if (result0 === null) {
+ result0 = parse_abs_path();
+ }
+ if (result0 !== null) {
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 63) {
+ result1 = "?";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_query();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos1;
+ }
+ } else {
+ result1 = null;
+ pos = pos1;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_net_path() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 2) === "//") {
+ result0 = "//";
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"//\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_authority();
+ if (result1 !== null) {
+ result2 = parse_abs_path();
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_abs_path() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ if (input.charCodeAt(pos) === 47) {
+ result0 = "/";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_path_segments();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_opaque_part() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_uric_no_slash();
+ if (result0 !== null) {
+ result1 = [];
+ result2 = parse_uric();
+ while (result2 !== null) {
+ result1.push(result2);
+ result2 = parse_uric();
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_uric() {
+ var result0;
+
+ result0 = parse_reserved();
+ if (result0 === null) {
+ result0 = parse_unreserved();
+ if (result0 === null) {
+ result0 = parse_escaped();
+ }
+ }
+ return result0;
+ }
+
+ function parse_uric_no_slash() {
+ var result0;
+
+ result0 = parse_unreserved();
+ if (result0 === null) {
+ result0 = parse_escaped();
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 59) {
+ result0 = ";";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 63) {
+ result0 = "?";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result0 = ":";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 64) {
+ result0 = "@";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"@\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 38) {
+ result0 = "&";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result0 = "=";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result0 = "+";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result0 = "$";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result0 = ",";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_path_segments() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_segment();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 47) {
+ result2 = "/";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_segment();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 47) {
+ result2 = "/";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_segment();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_segment() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = [];
+ result1 = parse_pchar();
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_pchar();
+ }
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 59) {
+ result2 = ";";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 59) {
+ result2 = ";";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_param() {
+ var result0, result1;
+
+ result0 = [];
+ result1 = parse_pchar();
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_pchar();
+ }
+ return result0;
+ }
+
+ function parse_pchar() {
+ var result0;
+
+ result0 = parse_unreserved();
+ if (result0 === null) {
+ result0 = parse_escaped();
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result0 = ":";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 64) {
+ result0 = "@";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"@\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 38) {
+ result0 = "&";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result0 = "=";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result0 = "+";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result0 = "$";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result0 = ",";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_scheme() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_ALPHA();
+ if (result0 !== null) {
+ result1 = [];
+ result2 = parse_ALPHA();
+ if (result2 === null) {
+ result2 = parse_DIGIT();
+ if (result2 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result2 = "+";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result2 === null) {
+ if (input.charCodeAt(pos) === 45) {
+ result2 = "-";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result2 === null) {
+ if (input.charCodeAt(pos) === 46) {
+ result2 = ".";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ result2 = parse_ALPHA();
+ if (result2 === null) {
+ result2 = parse_DIGIT();
+ if (result2 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result2 = "+";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result2 === null) {
+ if (input.charCodeAt(pos) === 45) {
+ result2 = "-";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result2 === null) {
+ if (input.charCodeAt(pos) === 46) {
+ result2 = ".";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.scheme= input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_authority() {
+ var result0;
+
+ result0 = parse_srvr();
+ if (result0 === null) {
+ result0 = parse_reg_name();
+ }
+ return result0;
+ }
+
+ function parse_srvr() {
+ var result0, result1;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_userinfo();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 64) {
+ result1 = "@";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"@\"");
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ result0 = result0 !== null ? result0 : "";
+ if (result0 !== null) {
+ result1 = parse_hostport();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ result0 = result0 !== null ? result0 : "";
+ return result0;
+ }
+
+ function parse_reg_name() {
+ var result0, result1;
+
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result1 = "$";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result1 = ",";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 59) {
+ result1 = ";";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 64) {
+ result1 = "@";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"@\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 38) {
+ result1 = "&";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result1 = "=";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result1 = "$";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result1 = ",";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 59) {
+ result1 = ";";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 64) {
+ result1 = "@";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"@\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 38) {
+ result1 = "&";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result1 = "=";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result1 = "+";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ result0 = null;
+ }
+ return result0;
+ }
+
+ function parse_query() {
+ var result0, result1;
+
+ result0 = [];
+ result1 = parse_uric();
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_uric();
+ }
+ return result0;
+ }
+
+ function parse_SIP_Version() {
+ var result0, result1, result2, result3, result4, result5;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 3).toLowerCase() === "sip") {
+ result0 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"SIP\"");
+ }
+ }
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 47) {
+ result1 = "/";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"/\"");
+ }
+ }
+ if (result1 !== null) {
+ result3 = parse_DIGIT();
+ if (result3 !== null) {
+ result2 = [];
+ while (result3 !== null) {
+ result2.push(result3);
+ result3 = parse_DIGIT();
+ }
+ } else {
+ result2 = null;
+ }
+ if (result2 !== null) {
+ if (input.charCodeAt(pos) === 46) {
+ result3 = ".";
+ pos++;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result3 !== null) {
+ result5 = parse_DIGIT();
+ if (result5 !== null) {
+ result4 = [];
+ while (result5 !== null) {
+ result4.push(result5);
+ result5 = parse_DIGIT();
+ }
+ } else {
+ result4 = null;
+ }
+ if (result4 !== null) {
+ result0 = [result0, result1, result2, result3, result4];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.sip_version = input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_INVITEm() {
+ var result0;
+
+ if (input.substr(pos, 6) === "INVITE") {
+ result0 = "INVITE";
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"INVITE\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_ACKm() {
+ var result0;
+
+ if (input.substr(pos, 3) === "ACK") {
+ result0 = "ACK";
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"ACK\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_OPTIONSm() {
+ var result0;
+
+ if (input.substr(pos, 7) === "OPTIONS") {
+ result0 = "OPTIONS";
+ pos += 7;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"OPTIONS\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_BYEm() {
+ var result0;
+
+ if (input.substr(pos, 3) === "BYE") {
+ result0 = "BYE";
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"BYE\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_CANCELm() {
+ var result0;
+
+ if (input.substr(pos, 6) === "CANCEL") {
+ result0 = "CANCEL";
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"CANCEL\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_REGISTERm() {
+ var result0;
+
+ if (input.substr(pos, 8) === "REGISTER") {
+ result0 = "REGISTER";
+ pos += 8;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"REGISTER\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_SUBSCRIBEm() {
+ var result0;
+
+ if (input.substr(pos, 9) === "SUBSCRIBE") {
+ result0 = "SUBSCRIBE";
+ pos += 9;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"SUBSCRIBE\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_NOTIFYm() {
+ var result0;
+
+ if (input.substr(pos, 6) === "NOTIFY") {
+ result0 = "NOTIFY";
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"NOTIFY\"");
+ }
+ }
+ return result0;
+ }
+
+ function parse_Method() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_INVITEm();
+ if (result0 === null) {
+ result0 = parse_ACKm();
+ if (result0 === null) {
+ result0 = parse_OPTIONSm();
+ if (result0 === null) {
+ result0 = parse_BYEm();
+ if (result0 === null) {
+ result0 = parse_CANCELm();
+ if (result0 === null) {
+ result0 = parse_REGISTERm();
+ if (result0 === null) {
+ result0 = parse_SUBSCRIBEm();
+ if (result0 === null) {
+ result0 = parse_NOTIFYm();
+ if (result0 === null) {
+ result0 = parse_token();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.method = input.substring(pos, offset);
+ return data.method; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Status_Line() {
+ var result0, result1, result2, result3, result4;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_SIP_Version();
+ if (result0 !== null) {
+ result1 = parse_SP();
+ if (result1 !== null) {
+ result2 = parse_Status_Code();
+ if (result2 !== null) {
+ result3 = parse_SP();
+ if (result3 !== null) {
+ result4 = parse_Reason_Phrase();
+ if (result4 !== null) {
+ result0 = [result0, result1, result2, result3, result4];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Status_Code() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_extension_code();
+ if (result0 !== null) {
+ result0 = (function(offset, status_code) {
+ data.status_code = parseInt(status_code.join('')); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_extension_code() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_DIGIT();
+ if (result0 !== null) {
+ result1 = parse_DIGIT();
+ if (result1 !== null) {
+ result2 = parse_DIGIT();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Reason_Phrase() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result0 = [];
+ result1 = parse_reserved();
+ if (result1 === null) {
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ result1 = parse_UTF8_NONASCII();
+ if (result1 === null) {
+ result1 = parse_UTF8_CONT();
+ if (result1 === null) {
+ result1 = parse_SP();
+ if (result1 === null) {
+ result1 = parse_HTAB();
+ }
+ }
+ }
+ }
+ }
+ }
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_reserved();
+ if (result1 === null) {
+ result1 = parse_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ result1 = parse_UTF8_NONASCII();
+ if (result1 === null) {
+ result1 = parse_UTF8_CONT();
+ if (result1 === null) {
+ result1 = parse_SP();
+ if (result1 === null) {
+ result1 = parse_HTAB();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.reason_phrase = input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Allow_Events() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_event_type();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_event_type();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_event_type();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Call_ID() {
+ var result0, result1, result2;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_word();
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 64) {
+ result1 = "@";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"@\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_word();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data = input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Contact() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ result0 = parse_STAR();
+ if (result0 === null) {
+ pos1 = pos;
+ result0 = parse_contact_param();
+ if (result0 !== null) {
+ result1 = [];
+ pos2 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_contact_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos2 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_contact_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ var idx, length;
+ length = data.multi_header.length;
+ for (idx = 0; idx < length; idx++) {
+ if (data.multi_header[idx].parsed === null) {
+ data = null;
+ break;
+ }
+ }
+ if (data !== null) {
+ data = data.multi_header;
+ } else {
+ data = -1;
+ }})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_contact_param() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SIP_URI_noparams();
+ if (result0 === null) {
+ result0 = parse_name_addr();
+ }
+ if (result0 !== null) {
+ result1 = [];
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_contact_params();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_contact_params();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ var header;
+ if(!data.multi_header) data.multi_header = [];
+ try {
+ header = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
+ delete data.uri;
+ delete data.display_name;
+ delete data.params;
+ } catch(e) {
+ header = null;
+ }
+ data.multi_header.push( { 'possition': pos,
+ 'offset': offset,
+ 'parsed': header
+ });})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_name_addr() {
+ var result0, result1, result2, result3;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_display_name();
+ result0 = result0 !== null ? result0 : "";
+ if (result0 !== null) {
+ result1 = parse_LAQUOT();
+ if (result1 !== null) {
+ result2 = parse_SIP_URI();
+ if (result2 !== null) {
+ result3 = parse_RAQUOT();
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_display_name() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ result1 = [];
+ pos2 = pos;
+ result2 = parse_LWS();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos2 = pos;
+ result2 = parse_LWS();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 === null) {
+ result0 = parse_quoted_string();
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, display_name) {
+ display_name = input.substring(pos, offset).trim();
+ if (display_name[0] === '\"') {
+ display_name = display_name.substring(1, display_name.length-1);
+ }
+ data.display_name = display_name; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_contact_params() {
+ var result0;
+
+ result0 = parse_c_p_q();
+ if (result0 === null) {
+ result0 = parse_c_p_expires();
+ if (result0 === null) {
+ result0 = parse_generic_param();
+ }
+ }
+ return result0;
+ }
+
+ function parse_c_p_q() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 1).toLowerCase() === "q") {
+ result0 = input.substr(pos, 1);
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"q\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_qvalue();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, q) {
+ if(!data.params) data.params = {};
+ data.params['q'] = q; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_c_p_expires() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 7).toLowerCase() === "expires") {
+ result0 = input.substr(pos, 7);
+ pos += 7;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"expires\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_delta_seconds();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, expires) {
+ if(!data.params) data.params = {};
+ data.params['expires'] = expires; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_delta_seconds() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result1 = parse_DIGIT();
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_DIGIT();
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, delta_seconds) {
+ return parseInt(delta_seconds.join('')); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_qvalue() {
+ var result0, result1, result2, result3, result4;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 48) {
+ result0 = "0";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"0\"");
+ }
+ }
+ if (result0 !== null) {
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 46) {
+ result1 = ".";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_DIGIT();
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ result3 = parse_DIGIT();
+ result3 = result3 !== null ? result3 : "";
+ if (result3 !== null) {
+ result4 = parse_DIGIT();
+ result4 = result4 !== null ? result4 : "";
+ if (result4 !== null) {
+ result1 = [result1, result2, result3, result4];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ return parseFloat(input.substring(pos, offset)); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_generic_param() {
+ var result0, result1, result2;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ pos2 = pos;
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_gen_value();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, param, value) {
+ if(!data.params) data.params = {};
+ if (typeof value === 'undefined'){
+ value = undefined;
+ }
+ else {
+ value = value[1];
+ }
+ data.params[param.toLowerCase()] = value;})(pos0, result0[0], result0[1]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_gen_value() {
+ var result0;
+
+ result0 = parse_token();
+ if (result0 === null) {
+ result0 = parse_host();
+ if (result0 === null) {
+ result0 = parse_quoted_string();
+ }
+ }
+ return result0;
+ }
+
+ function parse_Content_Disposition() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_disp_type();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_disp_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_disp_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_disp_type() {
+ var result0;
+
+ if (input.substr(pos, 6).toLowerCase() === "render") {
+ result0 = input.substr(pos, 6);
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"render\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 7).toLowerCase() === "session") {
+ result0 = input.substr(pos, 7);
+ pos += 7;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"session\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 4).toLowerCase() === "icon") {
+ result0 = input.substr(pos, 4);
+ pos += 4;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"icon\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 5).toLowerCase() === "alert") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"alert\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_token();
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_disp_param() {
+ var result0;
+
+ result0 = parse_handling_param();
+ if (result0 === null) {
+ result0 = parse_generic_param();
+ }
+ return result0;
+ }
+
+ function parse_handling_param() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 8).toLowerCase() === "handling") {
+ result0 = input.substr(pos, 8);
+ pos += 8;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"handling\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ if (input.substr(pos, 8).toLowerCase() === "optional") {
+ result2 = input.substr(pos, 8);
+ pos += 8;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"optional\"");
+ }
+ }
+ if (result2 === null) {
+ if (input.substr(pos, 8).toLowerCase() === "required") {
+ result2 = input.substr(pos, 8);
+ pos += 8;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"required\"");
+ }
+ }
+ if (result2 === null) {
+ result2 = parse_token();
+ }
+ }
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Content_Encoding() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Content_Length() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result1 = parse_DIGIT();
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_DIGIT();
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, length) {
+ data = parseInt(length.join('')); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Content_Type() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_media_type();
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data = input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_media_type() {
+ var result0, result1, result2, result3, result4, result5;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_m_type();
+ if (result0 !== null) {
+ result1 = parse_SLASH();
+ if (result1 !== null) {
+ result2 = parse_m_subtype();
+ if (result2 !== null) {
+ result3 = [];
+ pos1 = pos;
+ result4 = parse_SEMI();
+ if (result4 !== null) {
+ result5 = parse_m_parameter();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ while (result4 !== null) {
+ result3.push(result4);
+ pos1 = pos;
+ result4 = parse_SEMI();
+ if (result4 !== null) {
+ result5 = parse_m_parameter();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ }
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_m_type() {
+ var result0;
+
+ result0 = parse_discrete_type();
+ if (result0 === null) {
+ result0 = parse_composite_type();
+ }
+ return result0;
+ }
+
+ function parse_discrete_type() {
+ var result0;
+
+ if (input.substr(pos, 4).toLowerCase() === "text") {
+ result0 = input.substr(pos, 4);
+ pos += 4;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"text\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 5).toLowerCase() === "image") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"image\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 5).toLowerCase() === "audio") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"audio\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 5).toLowerCase() === "video") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"video\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 11).toLowerCase() === "application") {
+ result0 = input.substr(pos, 11);
+ pos += 11;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"application\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_extension_token();
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_composite_type() {
+ var result0;
+
+ if (input.substr(pos, 7).toLowerCase() === "message") {
+ result0 = input.substr(pos, 7);
+ pos += 7;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"message\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 9).toLowerCase() === "multipart") {
+ result0 = input.substr(pos, 9);
+ pos += 9;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"multipart\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_extension_token();
+ }
+ }
+ return result0;
+ }
+
+ function parse_extension_token() {
+ var result0;
+
+ result0 = parse_token();
+ if (result0 === null) {
+ result0 = parse_x_token();
+ }
+ return result0;
+ }
+
+ function parse_x_token() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 2).toLowerCase() === "x-") {
+ result0 = input.substr(pos, 2);
+ pos += 2;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"x-\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_token();
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_m_subtype() {
+ var result0;
+
+ result0 = parse_extension_token();
+ if (result0 === null) {
+ result0 = parse_token();
+ }
+ return result0;
+ }
+
+ function parse_m_parameter() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_m_value();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_m_value() {
+ var result0;
+
+ result0 = parse_token();
+ if (result0 === null) {
+ result0 = parse_quoted_string();
+ }
+ return result0;
+ }
+
+ function parse_CSeq() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_CSeq_value();
+ if (result0 !== null) {
+ result1 = parse_LWS();
+ if (result1 !== null) {
+ result2 = parse_Method();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_CSeq_value() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result1 = parse_DIGIT();
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_DIGIT();
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, cseq_value) {
+ data.value=parseInt(cseq_value.join('')); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Expires() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_delta_seconds();
+ if (result0 !== null) {
+ result0 = (function(offset, expires) {data = expires; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Event() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_event_type();
+ if (result0 !== null) {
+ result1 = [];
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_generic_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_generic_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, event_type) {
+ data.event = event_type.join('').toLowerCase(); })(pos0, result0[0]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_event_type() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_token_nodot();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 46) {
+ result2 = ".";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_token_nodot();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 46) {
+ result2 = ".";
+ pos++;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result2 !== null) {
+ result3 = parse_token_nodot();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_From() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SIP_URI_noparams();
+ if (result0 === null) {
+ result0 = parse_name_addr();
+ }
+ if (result0 !== null) {
+ result1 = [];
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_from_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_from_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ var tag = data.tag;
+ try {
+ data = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
+ if (tag) {data.setParam('tag',tag)}
+ } catch(e) {
+ data = -1;
+ }})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_from_param() {
+ var result0;
+
+ result0 = parse_tag_param();
+ if (result0 === null) {
+ result0 = parse_generic_param();
+ }
+ return result0;
+ }
+
+ function parse_tag_param() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 3).toLowerCase() === "tag") {
+ result0 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"tag\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_token();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, tag) {data.tag = tag; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Max_Forwards() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result1 = parse_DIGIT();
+ if (result1 !== null) {
+ result0 = [];
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_DIGIT();
+ }
+ } else {
+ result0 = null;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, forwards) {
+ data = parseInt(forwards.join('')); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Min_Expires() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_delta_seconds();
+ if (result0 !== null) {
+ result0 = (function(offset, min_expires) {data = min_expires; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Name_Addr_Header() {
+ var result0, result1, result2, result3, result4, result5, result6;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = [];
+ result1 = parse_display_name();
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_display_name();
+ }
+ if (result0 !== null) {
+ result1 = parse_LAQUOT();
+ if (result1 !== null) {
+ result2 = parse_SIP_URI();
+ if (result2 !== null) {
+ result3 = parse_RAQUOT();
+ if (result3 !== null) {
+ result4 = [];
+ pos2 = pos;
+ result5 = parse_SEMI();
+ if (result5 !== null) {
+ result6 = parse_generic_param();
+ if (result6 !== null) {
+ result5 = [result5, result6];
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ while (result5 !== null) {
+ result4.push(result5);
+ pos2 = pos;
+ result5 = parse_SEMI();
+ if (result5 !== null) {
+ result6 = parse_generic_param();
+ if (result6 !== null) {
+ result5 = [result5, result6];
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ }
+ if (result4 !== null) {
+ result0 = [result0, result1, result2, result3, result4];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ try {
+ data = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
+ } catch(e) {
+ data = -1;
+ }})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Proxy_Authenticate() {
+ var result0;
+
+ result0 = parse_challenge();
+ return result0;
+ }
+
+ function parse_challenge() {
+ var result0, result1, result2, result3, result4, result5;
+ var pos0, pos1;
+
+ pos0 = pos;
+ if (input.substr(pos, 6).toLowerCase() === "digest") {
+ result0 = input.substr(pos, 6);
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"Digest\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_LWS();
+ if (result1 !== null) {
+ result2 = parse_digest_cln();
+ if (result2 !== null) {
+ result3 = [];
+ pos1 = pos;
+ result4 = parse_COMMA();
+ if (result4 !== null) {
+ result5 = parse_digest_cln();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ while (result4 !== null) {
+ result3.push(result4);
+ pos1 = pos;
+ result4 = parse_COMMA();
+ if (result4 !== null) {
+ result5 = parse_digest_cln();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ }
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ if (result0 === null) {
+ result0 = parse_other_challenge();
+ }
+ return result0;
+ }
+
+ function parse_other_challenge() {
+ var result0, result1, result2, result3, result4, result5;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ result1 = parse_LWS();
+ if (result1 !== null) {
+ result2 = parse_auth_param();
+ if (result2 !== null) {
+ result3 = [];
+ pos1 = pos;
+ result4 = parse_COMMA();
+ if (result4 !== null) {
+ result5 = parse_auth_param();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ while (result4 !== null) {
+ result3.push(result4);
+ pos1 = pos;
+ result4 = parse_COMMA();
+ if (result4 !== null) {
+ result5 = parse_auth_param();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ }
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_auth_param() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_token();
+ if (result2 === null) {
+ result2 = parse_quoted_string();
+ }
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_digest_cln() {
+ var result0;
+
+ result0 = parse_realm();
+ if (result0 === null) {
+ result0 = parse_domain();
+ if (result0 === null) {
+ result0 = parse_nonce();
+ if (result0 === null) {
+ result0 = parse_opaque();
+ if (result0 === null) {
+ result0 = parse_stale();
+ if (result0 === null) {
+ result0 = parse_algorithm();
+ if (result0 === null) {
+ result0 = parse_qop_options();
+ if (result0 === null) {
+ result0 = parse_auth_param();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_realm() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 5).toLowerCase() === "realm") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"realm\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_realm_value();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_realm_value() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_quoted_string_clean();
+ if (result0 !== null) {
+ result0 = (function(offset, realm) { data.realm = realm; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_domain() {
+ var result0, result1, result2, result3, result4, result5, result6;
+ var pos0, pos1;
+
+ pos0 = pos;
+ if (input.substr(pos, 6).toLowerCase() === "domain") {
+ result0 = input.substr(pos, 6);
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"domain\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_LDQUOT();
+ if (result2 !== null) {
+ result3 = parse_URI();
+ if (result3 !== null) {
+ result4 = [];
+ pos1 = pos;
+ result6 = parse_SP();
+ if (result6 !== null) {
+ result5 = [];
+ while (result6 !== null) {
+ result5.push(result6);
+ result6 = parse_SP();
+ }
+ } else {
+ result5 = null;
+ }
+ if (result5 !== null) {
+ result6 = parse_URI();
+ if (result6 !== null) {
+ result5 = [result5, result6];
+ } else {
+ result5 = null;
+ pos = pos1;
+ }
+ } else {
+ result5 = null;
+ pos = pos1;
+ }
+ while (result5 !== null) {
+ result4.push(result5);
+ pos1 = pos;
+ result6 = parse_SP();
+ if (result6 !== null) {
+ result5 = [];
+ while (result6 !== null) {
+ result5.push(result6);
+ result6 = parse_SP();
+ }
+ } else {
+ result5 = null;
+ }
+ if (result5 !== null) {
+ result6 = parse_URI();
+ if (result6 !== null) {
+ result5 = [result5, result6];
+ } else {
+ result5 = null;
+ pos = pos1;
+ }
+ } else {
+ result5 = null;
+ pos = pos1;
+ }
+ }
+ if (result4 !== null) {
+ result5 = parse_RDQUOT();
+ if (result5 !== null) {
+ result0 = [result0, result1, result2, result3, result4, result5];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_URI() {
+ var result0;
+
+ result0 = parse_absoluteURI();
+ if (result0 === null) {
+ result0 = parse_abs_path();
+ }
+ return result0;
+ }
+
+ function parse_nonce() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 5).toLowerCase() === "nonce") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"nonce\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_nonce_value();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_nonce_value() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_quoted_string_clean();
+ if (result0 !== null) {
+ result0 = (function(offset, nonce) { data.nonce=nonce; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_opaque() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 6).toLowerCase() === "opaque") {
+ result0 = input.substr(pos, 6);
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"opaque\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_quoted_string_clean();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, opaque) { data.opaque=opaque; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_stale() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ if (input.substr(pos, 5).toLowerCase() === "stale") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"stale\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ pos1 = pos;
+ if (input.substr(pos, 4).toLowerCase() === "true") {
+ result2 = input.substr(pos, 4);
+ pos += 4;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"true\"");
+ }
+ }
+ if (result2 !== null) {
+ result2 = (function(offset) { data.stale=true; })(pos1);
+ }
+ if (result2 === null) {
+ pos = pos1;
+ }
+ if (result2 === null) {
+ pos1 = pos;
+ if (input.substr(pos, 5).toLowerCase() === "false") {
+ result2 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"false\"");
+ }
+ }
+ if (result2 !== null) {
+ result2 = (function(offset) { data.stale=false; })(pos1);
+ }
+ if (result2 === null) {
+ pos = pos1;
+ }
+ }
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_algorithm() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 9).toLowerCase() === "algorithm") {
+ result0 = input.substr(pos, 9);
+ pos += 9;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"algorithm\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ if (input.substr(pos, 3).toLowerCase() === "md5") {
+ result2 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"MD5\"");
+ }
+ }
+ if (result2 === null) {
+ if (input.substr(pos, 8).toLowerCase() === "md5-sess") {
+ result2 = input.substr(pos, 8);
+ pos += 8;
+ } else {
+ result2 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"MD5-sess\"");
+ }
+ }
+ if (result2 === null) {
+ result2 = parse_token();
+ }
+ }
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, algorithm) {
+ data.algorithm=algorithm.toUpperCase(); })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_qop_options() {
+ var result0, result1, result2, result3, result4, result5, result6;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ if (input.substr(pos, 3).toLowerCase() === "qop") {
+ result0 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"qop\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_LDQUOT();
+ if (result2 !== null) {
+ pos1 = pos;
+ result3 = parse_qop_value();
+ if (result3 !== null) {
+ result4 = [];
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 44) {
+ result5 = ",";
+ pos++;
+ } else {
+ result5 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ if (result5 !== null) {
+ result6 = parse_qop_value();
+ if (result6 !== null) {
+ result5 = [result5, result6];
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ while (result5 !== null) {
+ result4.push(result5);
+ pos2 = pos;
+ if (input.charCodeAt(pos) === 44) {
+ result5 = ",";
+ pos++;
+ } else {
+ result5 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ if (result5 !== null) {
+ result6 = parse_qop_value();
+ if (result6 !== null) {
+ result5 = [result5, result6];
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ } else {
+ result5 = null;
+ pos = pos2;
+ }
+ }
+ if (result4 !== null) {
+ result3 = [result3, result4];
+ } else {
+ result3 = null;
+ pos = pos1;
+ }
+ } else {
+ result3 = null;
+ pos = pos1;
+ }
+ if (result3 !== null) {
+ result4 = parse_RDQUOT();
+ if (result4 !== null) {
+ result0 = [result0, result1, result2, result3, result4];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_qop_value() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 8).toLowerCase() === "auth-int") {
+ result0 = input.substr(pos, 8);
+ pos += 8;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"auth-int\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 4).toLowerCase() === "auth") {
+ result0 = input.substr(pos, 4);
+ pos += 4;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"auth\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_token();
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, qop_value) {
+ data.qop || (data.qop=[]);
+ data.qop.push(qop_value.toLowerCase()); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Proxy_Require() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Record_Route() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_rec_route();
+ if (result0 !== null) {
+ result1 = [];
+ pos2 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_rec_route();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos2 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_rec_route();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ var idx, length;
+ length = data.multi_header.length;
+ for (idx = 0; idx < length; idx++) {
+ if (data.multi_header[idx].parsed === null) {
+ data = null;
+ break;
+ }
+ }
+ if (data !== null) {
+ data = data.multi_header;
+ } else {
+ data = -1;
+ }})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_rec_route() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_name_addr();
+ if (result0 !== null) {
+ result1 = [];
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_generic_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_generic_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ var header;
+ if(!data.multi_header) data.multi_header = [];
+ try {
+ header = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
+ delete data.uri;
+ delete data.display_name;
+ delete data.params;
+ } catch(e) {
+ header = null;
+ }
+ data.multi_header.push( { 'possition': pos,
+ 'offset': offset,
+ 'parsed': header
+ });})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Require() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Route() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_route_param();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_route_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_route_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_route_param() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_name_addr();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_generic_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_generic_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_Subscription_State() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_substate_value();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_subexp_params();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_subexp_params();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_substate_value() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 6).toLowerCase() === "active") {
+ result0 = input.substr(pos, 6);
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"active\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 7).toLowerCase() === "pending") {
+ result0 = input.substr(pos, 7);
+ pos += 7;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"pending\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 10).toLowerCase() === "terminated") {
+ result0 = input.substr(pos, 10);
+ pos += 10;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"terminated\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_token();
+ }
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.state = input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_subexp_params() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 6).toLowerCase() === "reason") {
+ result0 = input.substr(pos, 6);
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"reason\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_event_reason_value();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, reason) {
+ if (typeof reason !== 'undefined') data.reason = reason; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ if (result0 === null) {
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 7).toLowerCase() === "expires") {
+ result0 = input.substr(pos, 7);
+ pos += 7;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"expires\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_delta_seconds();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, expires) {
+ if (typeof expires !== 'undefined') data.expires = expires; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ if (result0 === null) {
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 11).toLowerCase() === "retry_after") {
+ result0 = input.substr(pos, 11);
+ pos += 11;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"retry_after\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_delta_seconds();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, retry_after) {
+ if (typeof retry_after !== 'undefined') data.retry_after = retry_after; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ if (result0 === null) {
+ result0 = parse_generic_param();
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_event_reason_value() {
+ var result0;
+
+ if (input.substr(pos, 11).toLowerCase() === "deactivated") {
+ result0 = input.substr(pos, 11);
+ pos += 11;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"deactivated\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 9).toLowerCase() === "probation") {
+ result0 = input.substr(pos, 9);
+ pos += 9;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"probation\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 8).toLowerCase() === "rejected") {
+ result0 = input.substr(pos, 8);
+ pos += 8;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"rejected\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 7).toLowerCase() === "timeout") {
+ result0 = input.substr(pos, 7);
+ pos += 7;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"timeout\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 6).toLowerCase() === "giveup") {
+ result0 = input.substr(pos, 6);
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"giveup\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 10).toLowerCase() === "noresource") {
+ result0 = input.substr(pos, 10);
+ pos += 10;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"noresource\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 9).toLowerCase() === "invariant") {
+ result0 = input.substr(pos, 9);
+ pos += 9;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"invariant\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_token();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_Subject() {
+ var result0;
+
+ result0 = parse_TEXT_UTF8_TRIM();
+ result0 = result0 !== null ? result0 : "";
+ return result0;
+ }
+
+ function parse_Supported() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_token();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ result0 = result0 !== null ? result0 : "";
+ return result0;
+ }
+
+ function parse_To() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_SIP_URI_noparams();
+ if (result0 === null) {
+ result0 = parse_name_addr();
+ }
+ if (result0 !== null) {
+ result1 = [];
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_to_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos2 = pos;
+ result2 = parse_SEMI();
+ if (result2 !== null) {
+ result3 = parse_to_param();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ } else {
+ result2 = null;
+ pos = pos2;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ var tag = data.tag;
+ try {
+ data = new JsSIP.NameAddrHeader(data.uri, data.display_name, data.params);
+ if (tag) {data.setParam('tag',tag)}
+ } catch(e) {
+ data = -1;
+ }})(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_to_param() {
+ var result0;
+
+ result0 = parse_tag_param();
+ if (result0 === null) {
+ result0 = parse_generic_param();
+ }
+ return result0;
+ }
+
+ function parse_Via() {
+ var result0, result1, result2, result3;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_via_parm();
+ if (result0 !== null) {
+ result1 = [];
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_via_parm();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ while (result2 !== null) {
+ result1.push(result2);
+ pos1 = pos;
+ result2 = parse_COMMA();
+ if (result2 !== null) {
+ result3 = parse_via_parm();
+ if (result3 !== null) {
+ result2 = [result2, result3];
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ } else {
+ result2 = null;
+ pos = pos1;
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_via_parm() {
+ var result0, result1, result2, result3, result4, result5;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_sent_protocol();
+ if (result0 !== null) {
+ result1 = parse_LWS();
+ if (result1 !== null) {
+ result2 = parse_sent_by();
+ if (result2 !== null) {
+ result3 = [];
+ pos1 = pos;
+ result4 = parse_SEMI();
+ if (result4 !== null) {
+ result5 = parse_via_params();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ while (result4 !== null) {
+ result3.push(result4);
+ pos1 = pos;
+ result4 = parse_SEMI();
+ if (result4 !== null) {
+ result5 = parse_via_params();
+ if (result5 !== null) {
+ result4 = [result4, result5];
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ } else {
+ result4 = null;
+ pos = pos1;
+ }
+ }
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_via_params() {
+ var result0;
+
+ result0 = parse_via_ttl();
+ if (result0 === null) {
+ result0 = parse_via_maddr();
+ if (result0 === null) {
+ result0 = parse_via_received();
+ if (result0 === null) {
+ result0 = parse_via_branch();
+ if (result0 === null) {
+ result0 = parse_response_port();
+ if (result0 === null) {
+ result0 = parse_generic_param();
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_via_ttl() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 3).toLowerCase() === "ttl") {
+ result0 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"ttl\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_ttl();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, via_ttl_value) {
+ data.ttl = via_ttl_value; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_via_maddr() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 5).toLowerCase() === "maddr") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"maddr\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_host();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, via_maddr) {
+ data.maddr = via_maddr; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_via_received() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 8).toLowerCase() === "received") {
+ result0 = input.substr(pos, 8);
+ pos += 8;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"received\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_IPv4address();
+ if (result2 === null) {
+ result2 = parse_IPv6address();
+ }
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, via_received) {
+ data.received = via_received; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_via_branch() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 6).toLowerCase() === "branch") {
+ result0 = input.substr(pos, 6);
+ pos += 6;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"branch\"");
+ }
+ }
+ if (result0 !== null) {
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = parse_token();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, via_branch) {
+ data.branch = via_branch; })(pos0, result0[2]);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_response_port() {
+ var result0, result1, result2, result3;
+ var pos0, pos1, pos2;
+
+ pos0 = pos;
+ pos1 = pos;
+ if (input.substr(pos, 5).toLowerCase() === "rport") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"rport\"");
+ }
+ }
+ if (result0 !== null) {
+ pos2 = pos;
+ result1 = parse_EQUAL();
+ if (result1 !== null) {
+ result2 = [];
+ result3 = parse_DIGIT();
+ while (result3 !== null) {
+ result2.push(result3);
+ result3 = parse_DIGIT();
+ }
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ } else {
+ result1 = null;
+ pos = pos2;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ if(typeof response_port !== 'undefined')
+ data.rport = response_port.join(''); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_sent_protocol() {
+ var result0, result1, result2, result3, result4;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_protocol_name();
+ if (result0 !== null) {
+ result1 = parse_SLASH();
+ if (result1 !== null) {
+ result2 = parse_token();
+ if (result2 !== null) {
+ result3 = parse_SLASH();
+ if (result3 !== null) {
+ result4 = parse_transport();
+ if (result4 !== null) {
+ result0 = [result0, result1, result2, result3, result4];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_protocol_name() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 3).toLowerCase() === "sip") {
+ result0 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"SIP\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_token();
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, via_protocol) {
+ data.protocol = via_protocol; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_transport() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 3).toLowerCase() === "udp") {
+ result0 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"UDP\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 3).toLowerCase() === "tcp") {
+ result0 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"TCP\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 3).toLowerCase() === "tls") {
+ result0 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"TLS\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 4).toLowerCase() === "sctp") {
+ result0 = input.substr(pos, 4);
+ pos += 4;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"SCTP\"");
+ }
+ }
+ if (result0 === null) {
+ result0 = parse_token();
+ }
+ }
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, via_transport) {
+ data.transport = via_transport; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_sent_by() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_via_host();
+ if (result0 !== null) {
+ pos1 = pos;
+ result1 = parse_COLON();
+ if (result1 !== null) {
+ result2 = parse_via_port();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos1;
+ }
+ } else {
+ result1 = null;
+ pos = pos1;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_via_host() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_hostname();
+ if (result0 === null) {
+ result0 = parse_IPv4address();
+ if (result0 === null) {
+ result0 = parse_IPv6reference();
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.host = input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_via_port() {
+ var result0, result1, result2, result3, result4;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_DIGIT();
+ result0 = result0 !== null ? result0 : "";
+ if (result0 !== null) {
+ result1 = parse_DIGIT();
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result2 = parse_DIGIT();
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ result3 = parse_DIGIT();
+ result3 = result3 !== null ? result3 : "";
+ if (result3 !== null) {
+ result4 = parse_DIGIT();
+ result4 = result4 !== null ? result4 : "";
+ if (result4 !== null) {
+ result0 = [result0, result1, result2, result3, result4];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, via_sent_by_port) {
+ data.port = parseInt(via_sent_by_port.join('')); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_ttl() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_DIGIT();
+ if (result0 !== null) {
+ result1 = parse_DIGIT();
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result2 = parse_DIGIT();
+ result2 = result2 !== null ? result2 : "";
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, ttl) {
+ return parseInt(ttl.join('')); })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_WWW_Authenticate() {
+ var result0;
+
+ result0 = parse_challenge();
+ return result0;
+ }
+
+ function parse_extension_header() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_token();
+ if (result0 !== null) {
+ result1 = parse_HCOLON();
+ if (result1 !== null) {
+ result2 = parse_header_value();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_header_value() {
+ var result0, result1;
+
+ result0 = [];
+ result1 = parse_TEXT_UTF8char();
+ if (result1 === null) {
+ result1 = parse_UTF8_CONT();
+ if (result1 === null) {
+ result1 = parse_LWS();
+ }
+ }
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_TEXT_UTF8char();
+ if (result1 === null) {
+ result1 = parse_UTF8_CONT();
+ if (result1 === null) {
+ result1 = parse_LWS();
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_message_body() {
+ var result0, result1;
+
+ result0 = [];
+ result1 = parse_OCTET();
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_OCTET();
+ }
+ return result0;
+ }
+
+ function parse_stun_URI() {
+ var result0, result1, result2;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_stun_scheme();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_stun_host_port();
+ if (result2 !== null) {
+ result0 = [result0, result1, result2];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_stun_scheme() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 5).toLowerCase() === "stuns") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"stuns\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 4).toLowerCase() === "stun") {
+ result0 = input.substr(pos, 4);
+ pos += 4;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"stun\"");
+ }
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, scheme) {
+ data.scheme = scheme; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_stun_host_port() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_stun_host();
+ if (result0 !== null) {
+ pos1 = pos;
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_port();
+ if (result2 !== null) {
+ result1 = [result1, result2];
+ } else {
+ result1 = null;
+ pos = pos1;
+ }
+ } else {
+ result1 = null;
+ pos = pos1;
+ }
+ result1 = result1 !== null ? result1 : "";
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_stun_host() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ result0 = parse_IPv4address();
+ if (result0 === null) {
+ result0 = parse_IPv6reference();
+ if (result0 === null) {
+ result0 = parse_reg_name();
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, host) {
+ data.host = host; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_reg_name() {
+ var result0, result1;
+ var pos0;
+
+ pos0 = pos;
+ result0 = [];
+ result1 = parse_stun_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ result1 = parse_sub_delims();
+ }
+ }
+ while (result1 !== null) {
+ result0.push(result1);
+ result1 = parse_stun_unreserved();
+ if (result1 === null) {
+ result1 = parse_escaped();
+ if (result1 === null) {
+ result1 = parse_sub_delims();
+ }
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ return input.substring(pos, offset); })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_stun_unreserved() {
+ var result0;
+
+ result0 = parse_ALPHA();
+ if (result0 === null) {
+ result0 = parse_DIGIT();
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 45) {
+ result0 = "-";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"-\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 46) {
+ result0 = ".";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\".\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 95) {
+ result0 = "_";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"_\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 126) {
+ result0 = "~";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"~\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_sub_delims() {
+ var result0;
+
+ if (input.charCodeAt(pos) === 33) {
+ result0 = "!";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"!\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 36) {
+ result0 = "$";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"$\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 38) {
+ result0 = "&";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"&\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 39) {
+ result0 = "'";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"'\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 40) {
+ result0 = "(";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"(\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 41) {
+ result0 = ")";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\")\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 42) {
+ result0 = "*";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"*\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 43) {
+ result0 = "+";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"+\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 44) {
+ result0 = ",";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\",\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 59) {
+ result0 = ";";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\";\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.charCodeAt(pos) === 61) {
+ result0 = "=";
+ pos++;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"=\"");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result0;
+ }
+
+ function parse_turn_URI() {
+ var result0, result1, result2, result3, result4;
+ var pos0, pos1;
+
+ pos0 = pos;
+ result0 = parse_turn_scheme();
+ if (result0 !== null) {
+ if (input.charCodeAt(pos) === 58) {
+ result1 = ":";
+ pos++;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\":\"");
+ }
+ }
+ if (result1 !== null) {
+ result2 = parse_stun_host_port();
+ if (result2 !== null) {
+ pos1 = pos;
+ if (input.substr(pos, 11) === "?transport=") {
+ result3 = "?transport=";
+ pos += 11;
+ } else {
+ result3 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"?transport=\"");
+ }
+ }
+ if (result3 !== null) {
+ result4 = parse_transport();
+ if (result4 !== null) {
+ result3 = [result3, result4];
+ } else {
+ result3 = null;
+ pos = pos1;
+ }
+ } else {
+ result3 = null;
+ pos = pos1;
+ }
+ result3 = result3 !== null ? result3 : "";
+ if (result3 !== null) {
+ result0 = [result0, result1, result2, result3];
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ } else {
+ result0 = null;
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_turn_scheme() {
+ var result0;
+ var pos0;
+
+ pos0 = pos;
+ if (input.substr(pos, 5).toLowerCase() === "turns") {
+ result0 = input.substr(pos, 5);
+ pos += 5;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"turns\"");
+ }
+ }
+ if (result0 === null) {
+ if (input.substr(pos, 4).toLowerCase() === "turn") {
+ result0 = input.substr(pos, 4);
+ pos += 4;
+ } else {
+ result0 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"turn\"");
+ }
+ }
+ }
+ if (result0 !== null) {
+ result0 = (function(offset, scheme) {
+ data.scheme = scheme; })(pos0, result0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+ function parse_turn_transport() {
+ var result0, result1, result2;
+ var pos0, pos1;
+
+ pos0 = pos;
+ pos1 = pos;
+ result0 = parse_transport();
+ if (result0 !== null) {
+ if (input.substr(pos, 3).toLowerCase() === "udp") {
+ result1 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"udp\"");
+ }
+ }
+ if (result1 === null) {
+ if (input.substr(pos, 3).toLowerCase() === "tcp") {
+ result1 = input.substr(pos, 3);
+ pos += 3;
+ } else {
+ result1 = null;
+ if (reportFailures === 0) {
+ matchFailed("\"tcp\"");
+ }
+ }
+ if (result1 === null) {
+ result1 = [];
+ result2 = parse_unreserved();
+ while (result2 !== null) {
+ result1.push(result2);
+ result2 = parse_unreserved();
+ }
+ }
+ }
+ if (result1 !== null) {
+ result0 = [result0, result1];
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ } else {
+ result0 = null;
+ pos = pos1;
+ }
+ if (result0 !== null) {
+ result0 = (function(offset) {
+ data.transport = transport; })(pos0);
+ }
+ if (result0 === null) {
+ pos = pos0;
+ }
+ return result0;
+ }
+
+
+ function cleanupExpected(expected) {
+ expected.sort();
+
+ var lastExpected = null;
+ var cleanExpected = [];
+ for (var i = 0; i < expected.length; i++) {
+ if (expected[i] !== lastExpected) {
+ cleanExpected.push(expected[i]);
+ lastExpected = expected[i];
+ }
+ }
+ return cleanExpected;
+ }
+
+ function computeErrorPosition() {
+ /*
+ * The first idea was to use |String.split| to break the input up to the
+ * error position along newlines and derive the line and column from
+ * there. However IE's |split| implementation is so broken that it was
+ * enough to prevent it.
+ */
+
+ var line = 1;
+ var column = 1;
+ var seenCR = false;
+
+ for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) {
+ var ch = input.charAt(i);
+ if (ch === "\n") {
+ if (!seenCR) { line++; }
+ column = 1;
+ seenCR = false;
+ } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
+ line++;
+ column = 1;
+ seenCR = true;
+ } else {
+ column++;
+ seenCR = false;
+ }
+ }
+
+ return { line: line, column: column };
+ }
+
+ var data = {};
+
+ var result = parseFunctions[startRule]();
+
+ /*
+ * The parser is now in one of the following three states:
+ *
+ * 1. The parser successfully parsed the whole input.
+ *
+ * - |result !== null|
+ * - |pos === input.length|
+ * - |rightmostFailuresExpected| may or may not contain something
+ *
+ * 2. The parser successfully parsed only a part of the input.
+ *
+ * - |result !== null|
+ * - |pos < input.length|
+ * - |rightmostFailuresExpected| may or may not contain something
+ *
+ * 3. The parser did not successfully parse any part of the input.
+ *
+ * - |result === null|
+ * - |pos === 0|
+ * - |rightmostFailuresExpected| contains at least one failure
+ *
+ * All code following this comment (including called functions) must
+ * handle these states.
+ */
+ if (result === null || pos !== input.length) {
+ var offset = Math.max(pos, rightmostFailuresPos);
+ var found = offset < input.length ? input.charAt(offset) : null;
+ var errorPosition = computeErrorPosition();
+
+ new this.SyntaxError(
+ cleanupExpected(rightmostFailuresExpected),
+ found,
+ offset,
+ errorPosition.line,
+ errorPosition.column
+ );
+ return -1;
+ }
+
+ return data;
+ },
+
+ /* Returns the parser source code. */
+ toSource: function() { return this._source; }
+ };
+
+ /* Thrown when a parser encounters a syntax error. */
+
+ result.SyntaxError = function(expected, found, offset, line, column) {
+ function buildMessage(expected, found) {
+ var expectedHumanized, foundHumanized;
+
+ switch (expected.length) {
+ case 0:
+ expectedHumanized = "end of input";
+ break;
+ case 1:
+ expectedHumanized = expected[0];
+ break;
+ default:
+ expectedHumanized = expected.slice(0, expected.length - 1).join(", ")
+ + " or "
+ + expected[expected.length - 1];
+ }
+
+ foundHumanized = found ? quote(found) : "end of input";
+
+ return "Expected " + expectedHumanized + " but " + foundHumanized + " found.";
+ }
+
+ this.name = "SyntaxError";
+ this.expected = expected;
+ this.found = found;
+ this.message = buildMessage(expected, found);
+ this.offset = offset;
+ this.line = line;
+ this.column = column;
+ };
+
+ result.SyntaxError.prototype = Error.prototype;
+
+ return result;
+})();
\ No newline at end of file
diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/WebRtcCallManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/WebRtcCallManager.as
index b2c60d91ce..6c1ffa0373 100755
--- a/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/WebRtcCallManager.as
+++ b/bigbluebutton-client/src/org/bigbluebutton/modules/phone/managers/WebRtcCallManager.as
@@ -2,7 +2,11 @@ package org.bigbluebutton.modules.phone.managers
{
import com.asfusion.mate.events.Dispatcher;
+ import flash.events.TimerEvent;
import flash.external.ExternalInterface;
+ import flash.utils.Timer;
+
+ import flexlib.scheduling.timelineClasses.TimeRangeDescriptorUtil;
import mx.controls.Alert;
import mx.events.CloseEvent;
@@ -107,6 +111,8 @@ package org.bigbluebutton.modules.phone.managers
dispatcher.dispatchEvent(new UseFlashModeCommand());
}
+ private var t:Timer;
+
public function handleWebRtcEchoTestHasAudioEvent():void {
state = STOP_ECHO_THEN_JOIN_CONF;
endEchoTest();
@@ -115,7 +121,11 @@ package org.bigbluebutton.modules.phone.managers
* after. (richard mar 28, 2014)
*/
//echoTestDone = true;
- joinVoiceConference();
+ t = new Timer(1000, 1);
+ t.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void {
+ joinVoiceConference();
+ });
+ t.start();
}
public function handleWebRtcConfCallStartedEvent():void {