/*
 * JsSIP v3.4.3
 * the Javascript SIP library
 * Copyright: 2012-2020 José Luis Millán <jmillan@aliax.net> (https://github.com/jmillan)
 * Homepage: https://jssip.net
 * License: MIT
 */

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JsSIP = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";

function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

var Utils = require('./Utils');

var JsSIP_C = require('./Constants');

var Grammar = require('./Grammar');

var URI = require('./URI');

var Socket = require('./Socket');

var Exceptions = require('./Exceptions'); // Default settings.


exports.settings = {
  // SIP authentication.
  authorization_user: null,
  password: null,
  realm: null,
  ha1: null,
  // SIP account.
  display_name: null,
  uri: null,
  contact_uri: null,
  // SIP instance id (GRUU).
  instance_id: null,
  // Preloaded SIP Route header field.
  use_preloaded_route: false,
  // Session parameters.
  session_timers: true,
  session_timers_refresh_method: JsSIP_C.UPDATE,
  no_answer_timeout: 60,
  // Registration parameters.
  register: true,
  register_expires: 600,
  registrar_server: null,
  // Connection options.
  sockets: null,
  connection_recovery_max_interval: JsSIP_C.CONNECTION_RECOVERY_MAX_INTERVAL,
  connection_recovery_min_interval: JsSIP_C.CONNECTION_RECOVERY_MIN_INTERVAL,

  /*
   * Host address.
   * Value to be set in Via sent_by and host part of Contact FQDN.
  */
  via_host: "".concat(Utils.createRandomToken(12), ".invalid")
}; // Configuration checks.

var checks = {
  mandatory: {
    sockets: function sockets(_sockets2) {
      /* Allow defining sockets parameter as:
       *  Socket: socket
       *  Array of Socket: [socket1, socket2]
       *  Array of Objects: [{socket: socket1, weight:1}, {socket: Socket2, weight:0}]
       *  Array of Objects and Socket: [{socket: socket1}, socket2]
       */
      var _sockets = [];

      if (Socket.isSocket(_sockets2)) {
        _sockets.push({
          socket: _sockets2
        });
      } else if (Array.isArray(_sockets2) && _sockets2.length) {
        var _iterator = _createForOfIteratorHelper(_sockets2),
            _step;

        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var socket = _step.value;

            if (Object.prototype.hasOwnProperty.call(socket, 'socket') && Socket.isSocket(socket.socket)) {
              _sockets.push(socket);
            } else if (Socket.isSocket(socket)) {
              _sockets.push({
                socket: socket
              });
            }
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }
      } else {
        return;
      }

      return _sockets;
    },
    uri: function uri(_uri) {
      if (!/^sip:/i.test(_uri)) {
        _uri = "".concat(JsSIP_C.SIP, ":").concat(_uri);
      }

      var parsed = URI.parse(_uri);

      if (!parsed) {
        return;
      } else if (!parsed.user) {
        return;
      } else {
        return parsed;
      }
    }
  },
  optional: {
    authorization_user: function authorization_user(_authorization_user) {
      if (Grammar.parse("\"".concat(_authorization_user, "\""), 'quoted_string') === -1) {
        return;
      } else {
        return _authorization_user;
      }
    },
    authorization_jwt: function authorization_jwt(_authorization_jwt) {
      if (typeof _authorization_jwt === 'string') {
        return _authorization_jwt;
      }
    },
    user_agent: function user_agent(_user_agent) {
      if (typeof _user_agent === 'string') {
        return _user_agent;
      }
    },
    connection_recovery_max_interval: function connection_recovery_max_interval(_connection_recovery_max_interval) {
      if (Utils.isDecimal(_connection_recovery_max_interval)) {
        var value = Number(_connection_recovery_max_interval);

        if (value > 0) {
          return value;
        }
      }
    },
    connection_recovery_min_interval: function connection_recovery_min_interval(_connection_recovery_min_interval) {
      if (Utils.isDecimal(_connection_recovery_min_interval)) {
        var value = Number(_connection_recovery_min_interval);

        if (value > 0) {
          return value;
        }
      }
    },
    contact_uri: function contact_uri(_contact_uri) {
      if (typeof _contact_uri === 'string') {
        var uri = Grammar.parse(_contact_uri, 'SIP_URI');

        if (uri !== -1) {
          return uri;
        }
      }
    },
    display_name: function display_name(_display_name) {
      return _display_name;
    },
    instance_id: function instance_id(_instance_id) {
      if (/^uuid:/i.test(_instance_id)) {
        _instance_id = _instance_id.substr(5);
      }

      if (Grammar.parse(_instance_id, 'uuid') === -1) {
        return;
      } else {
        return _instance_id;
      }
    },
    no_answer_timeout: function no_answer_timeout(_no_answer_timeout) {
      if (Utils.isDecimal(_no_answer_timeout)) {
        var value = Number(_no_answer_timeout);

        if (value > 0) {
          return value;
        }
      }
    },
    session_timers: function session_timers(_session_timers) {
      if (typeof _session_timers === 'boolean') {
        return _session_timers;
      }
    },
    session_timers_refresh_method: function session_timers_refresh_method(method) {
      if (typeof method === 'string') {
        method = method.toUpperCase();

        if (method === JsSIP_C.INVITE || method === JsSIP_C.UPDATE) {
          return method;
        }
      }
    },
    password: function password(_password) {
      return String(_password);
    },
    realm: function realm(_realm) {
      return String(_realm);
    },
    ha1: function ha1(_ha) {
      return String(_ha);
    },
    register: function register(_register) {
      if (typeof _register === 'boolean') {
        return _register;
      }
    },
    register_expires: function register_expires(_register_expires) {
      if (Utils.isDecimal(_register_expires)) {
        var value = Number(_register_expires);

        if (value > 0) {
          return value;
        }
      }
    },
    registrar_server: function registrar_server(_registrar_server) {
      if (!/^sip:/i.test(_registrar_server)) {
        _registrar_server = "".concat(JsSIP_C.SIP, ":").concat(_registrar_server);
      }

      var parsed = URI.parse(_registrar_server);

      if (!parsed) {
        return;
      } else if (parsed.user) {
        return;
      } else {
        return parsed;
      }
    },
    use_preloaded_route: function use_preloaded_route(_use_preloaded_route) {
      if (typeof _use_preloaded_route === 'boolean') {
        return _use_preloaded_route;
      }
    }
  }
};

exports.load = function (dst, src) {
  // Check Mandatory parameters.
  for (var parameter in checks.mandatory) {
    if (!src.hasOwnProperty(parameter)) {
      throw new Exceptions.ConfigurationError(parameter);
    } else {
      var value = src[parameter];
      var checked_value = checks.mandatory[parameter](value);

      if (checked_value !== undefined) {
        dst[parameter] = checked_value;
      } else {
        throw new Exceptions.ConfigurationError(parameter, value);
      }
    }
  } // Check Optional parameters.


  for (var _parameter in checks.optional) {
    if (src.hasOwnProperty(_parameter)) {
      var _value = src[_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 (Utils.isEmpty(_value)) {
        continue;
      }

      var _checked_value = checks.optional[_parameter](_value);

      if (_checked_value !== undefined) {
        dst[_parameter] = _checked_value;
      } else {
        throw new Exceptions.ConfigurationError(_parameter, _value);
      }
    }
  }
};
},{"./Constants":2,"./Exceptions":6,"./Grammar":7,"./Socket":20,"./URI":25,"./Utils":26}],2:[function(require,module,exports){
"use strict";

var pkg = require('../package.json');

module.exports = {
  USER_AGENT: "".concat(pkg.title, " ").concat(pkg.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',
    MISSING_SDP: 'Missing SDP',
    AUTHENTICATION_ERROR: 'Authentication Error',
    // Session error causes.
    BYE: 'Terminated',
    WEBRTC_ERROR: 'WebRTC Error',
    CANCELED: 'Canceled',
    NO_ANSWER: 'No Answer',
    EXPIRES: 'Expires',
    NO_ACK: 'No ACK',
    DIALOG_ERROR: 'Dialog Error',
    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, 424],
    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',
  REFER: 'REFER',
  UPDATE: 'UPDATE',
  SUBSCRIBE: 'SUBSCRIBE',

  /* SIP Response Reasons
   * DOC: https://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',
    424: 'Bad Location Information',
    // RFC 6442
    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: 'JsSIP 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'
  },
  ALLOWED_METHODS: 'INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO,NOTIFY',
  ACCEPTED_BODY_TYPES: 'application/sdp, application/dtmf-relay',
  MAX_FORWARDS: 69,
  SESSION_EXPIRES: 90,
  MIN_SESSION_EXPIRES: 60,
  CONNECTION_RECOVERY_MAX_INTERVAL: 30,
  CONNECTION_RECOVERY_MIN_INTERVAL: 2
};
},{"../package.json":38}],3:[function(require,module,exports){
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var SIPMessage = require('./SIPMessage');

var JsSIP_C = require('./Constants');

var Transactions = require('./Transactions');

var Dialog_RequestSender = require('./Dialog/RequestSender');

var Utils = require('./Utils');

var debug = require('debug')('JsSIP:Dialog');

var C = {
  // Dialog states.
  STATUS_EARLY: 1,
  STATUS_CONFIRMED: 2
}; // RFC 3261 12.1.

module.exports = /*#__PURE__*/function () {
  _createClass(Dialog, null, [{
    key: "C",
    // Expose C object.
    get: function get() {
      return C;
    }
  }]);

  function Dialog(owner, message, type) {
    var state = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : C.STATUS_CONFIRMED;

    _classCallCheck(this, Dialog);

    this._owner = owner;
    this._ua = owner._ua;
    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 SIPMessage.IncomingResponse) {
      state = message.status_code < 200 ? C.STATUS_EARLY : C.STATUS_CONFIRMED;
    }

    var 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 toString() {
          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');
      this._ack_seqnum = this._remote_seqnum;
    } // 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 toString() {
            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._ack_seqnum = null;
      }

    this._ua.newDialog(this);

    debug("new ".concat(type, " dialog created with status ").concat(this._state === C.STATUS_EARLY ? 'EARLY' : 'CONFIRMED'));
  }

  _createClass(Dialog, [{
    key: "update",
    value: function update(message, type) {
      this._state = C.STATUS_CONFIRMED;
      debug("dialog ".concat(this._id.toString(), "  changed to CONFIRMED state"));

      if (type === 'UAC') {
        // RFC 3261 13.2.2.4.
        this._route_set = message.getHeaders('record-route').reverse();
      }
    }
  }, {
    key: "terminate",
    value: function terminate() {
      debug("dialog ".concat(this._id.toString(), " deleted"));

      this._ua.destroyDialog(this);
    }
  }, {
    key: "sendRequest",
    value: function sendRequest(method) {
      var _this = this;

      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var eventHandlers = Utils.cloneObject(options.eventHandlers);
      var body = options.body || null;

      var request = this._createRequest(method, extraHeaders, body); // Increase the local CSeq on authentication.


      eventHandlers.onAuthenticated = function () {
        _this._local_seqnum += 1;
      };

      var request_sender = new Dialog_RequestSender(this, request, eventHandlers);
      request_sender.send(); // Return the instance of OutgoingRequest.

      return request;
    }
  }, {
    key: "receiveRequest",
    value: function receiveRequest(request) {
      // Check in-dialog request.
      if (!this._checkInDialogRequest(request)) {
        return;
      } // ACK received. Cleanup this._ack_seqnum.


      if (request.method === JsSIP_C.ACK && this._ack_seqnum !== null) {
        this._ack_seqnum = null;
      } // INVITE received. Set this._ack_seqnum.
      else if (request.method === JsSIP_C.INVITE) {
          this._ack_seqnum = request.cseq;
        }

      this._owner.receiveRequest(request);
    } // RFC 3261 12.2.1.1.

  }, {
    key: "_createRequest",
    value: function _createRequest(method, extraHeaders, body) {
      extraHeaders = Utils.cloneArray(extraHeaders);

      if (!this._local_seqnum) {
        this._local_seqnum = Math.floor(Math.random() * 10000);
      }

      var cseq = method === JsSIP_C.CANCEL || method === JsSIP_C.ACK ? this._local_seqnum : this._local_seqnum += 1;
      var request = new SIPMessage.OutgoingRequest(method, this._remote_target, this._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);
      return request;
    } // RFC 3261 12.2.2.

  }, {
    key: "_checkInDialogRequest",
    value: function _checkInDialogRequest(request) {
      var _this2 = this;

      if (!this._remote_seqnum) {
        this._remote_seqnum = request.cseq;
      } else if (request.cseq < this._remote_seqnum) {
        if (request.method === JsSIP_C.ACK) {
          // We are not expecting any ACK with lower seqnum than the current one.
          // Or this is not the ACK we are waiting for.
          if (this._ack_seqnum === null || request.cseq !== this._ack_seqnum) {
            return false;
          }
        } else {
          request.reply(500);
          return false;
        }
      } else if (request.cseq > this._remote_seqnum) {
        this._remote_seqnum = request.cseq;
      } // RFC3261 14.2 Modifying an Existing Session -UAS BEHAVIOR-.


      if (request.method === JsSIP_C.INVITE || request.method === JsSIP_C.UPDATE && request.body) {
        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:".concat(retryAfter)]);
          return false;
        } else {
          this._uas_pending_reply = true;

          var stateChanged = function stateChanged() {
            if (request.server_transaction.state === Transactions.C.STATUS_ACCEPTED || request.server_transaction.state === Transactions.C.STATUS_COMPLETED || request.server_transaction.state === Transactions.C.STATUS_TERMINATED) {
              request.server_transaction.removeListener('stateChanged', stateChanged);
              _this2._uas_pending_reply = false;
            }
          };

          request.server_transaction.on('stateChanged', stateChanged);
        } // 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 () {
            if (request.server_transaction.state === Transactions.C.STATUS_ACCEPTED) {
              _this2._remote_target = request.parseHeader('contact').uri;
            }
          });
        }
      } else if (request.method === 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 () {
            if (request.server_transaction.state === Transactions.C.STATUS_COMPLETED) {
              _this2._remote_target = request.parseHeader('contact').uri;
            }
          });
        }
      }

      return true;
    }
  }, {
    key: "id",
    get: function get() {
      return this._id;
    }
  }, {
    key: "local_seqnum",
    get: function get() {
      return this._local_seqnum;
    },
    set: function set(num) {
      this._local_seqnum = num;
    }
  }, {
    key: "owner",
    get: function get() {
      return this._owner;
    }
  }, {
    key: "uac_pending_reply",
    get: function get() {
      return this._uac_pending_reply;
    },
    set: function set(pending) {
      this._uac_pending_reply = pending;
    }
  }, {
    key: "uas_pending_reply",
    get: function get() {
      return this._uas_pending_reply;
    }
  }]);

  return Dialog;
}();
},{"./Constants":2,"./Dialog/RequestSender":4,"./SIPMessage":19,"./Transactions":22,"./Utils":26,"debug":30}],4:[function(require,module,exports){
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var JsSIP_C = require('../Constants');

var Transactions = require('../Transactions');

var RTCSession = require('../RTCSession');

var RequestSender = require('../RequestSender'); // Default event handlers.


var EventHandlers = {
  onRequestTimeout: function onRequestTimeout() {},
  onTransportError: function onTransportError() {},
  onSuccessResponse: function onSuccessResponse() {},
  onErrorResponse: function onErrorResponse() {},
  onAuthenticated: function onAuthenticated() {},
  onDialogError: function onDialogError() {}
};

module.exports = /*#__PURE__*/function () {
  function DialogRequestSender(dialog, request, eventHandlers) {
    _classCallCheck(this, DialogRequestSender);

    this._dialog = dialog;
    this._ua = dialog._ua;
    this._request = request;
    this._eventHandlers = eventHandlers; // RFC3261 14.1 Modifying an Existing Session. UAC Behavior.

    this._reattempt = false;
    this._reattemptTimer = null; // Define the undefined handlers.

    for (var handler in EventHandlers) {
      if (Object.prototype.hasOwnProperty.call(EventHandlers, handler)) {
        if (!this._eventHandlers[handler]) {
          this._eventHandlers[handler] = EventHandlers[handler];
        }
      }
    }
  }

  _createClass(DialogRequestSender, [{
    key: "send",
    value: function send() {
      var _this = this;

      var request_sender = new RequestSender(this._ua, this._request, {
        onRequestTimeout: function onRequestTimeout() {
          _this._eventHandlers.onRequestTimeout();
        },
        onTransportError: function onTransportError() {
          _this._eventHandlers.onTransportError();
        },
        onAuthenticated: function onAuthenticated(request) {
          _this._eventHandlers.onAuthenticated(request);
        },
        onReceiveResponse: function onReceiveResponse(response) {
          _this._receiveResponse(response);
        }
      });
      request_sender.send(); // RFC3261 14.2 Modifying an Existing Session -UAC BEHAVIOR-.

      if ((this._request.method === JsSIP_C.INVITE || this._request.method === JsSIP_C.UPDATE && this._request.body) && request_sender.clientTransaction.state !== Transactions.C.STATUS_TERMINATED) {
        this._dialog.uac_pending_reply = true;

        var stateChanged = function stateChanged() {
          if (request_sender.clientTransaction.state === Transactions.C.STATUS_ACCEPTED || request_sender.clientTransaction.state === Transactions.C.STATUS_COMPLETED || request_sender.clientTransaction.state === Transactions.C.STATUS_TERMINATED) {
            request_sender.clientTransaction.removeListener('stateChanged', stateChanged);
            _this._dialog.uac_pending_reply = false;
          }
        };

        request_sender.clientTransaction.on('stateChanged', stateChanged);
      }
    }
  }, {
    key: "_receiveResponse",
    value: function _receiveResponse(response) {
      var _this2 = 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._eventHandlers.onDialogError(response);
      } else if (response.method === JsSIP_C.INVITE && response.status_code === 491) {
        if (this._reattempt) {
          if (response.status_code >= 200 && response.status_code < 300) {
            this._eventHandlers.onSuccessResponse(response);
          } else if (response.status_code >= 300) {
            this._eventHandlers.onErrorResponse(response);
          }
        } else {
          this._request.cseq.value = this._dialog.local_seqnum += 1;
          this._reattemptTimer = setTimeout(function () {
            // TODO: look at dialog state instead.
            if (_this2._dialog.owner.status !== RTCSession.C.STATUS_TERMINATED) {
              _this2._reattempt = true;

              _this2._request_sender.send();
            }
          }, 1000);
        }
      } else if (response.status_code >= 200 && response.status_code < 300) {
        this._eventHandlers.onSuccessResponse(response);
      } else if (response.status_code >= 300) {
        this._eventHandlers.onErrorResponse(response);
      }
    }
  }, {
    key: "request",
    get: function get() {
      return this._request;
    }
  }]);

  return DialogRequestSender;
}();
},{"../Constants":2,"../RTCSession":12,"../RequestSender":18,"../Transactions":22}],5:[function(require,module,exports){
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var Utils = require('./Utils');

var debug = require('debug')('JsSIP:DigestAuthentication');

var debugerror = require('debug')('JsSIP:ERROR:DigestAuthentication');

debugerror.log = console.warn.bind(console);

module.exports = /*#__PURE__*/function () {
  function DigestAuthentication(credentials) {
    _classCallCheck(this, DigestAuthentication);

    this._credentials = credentials;
    this._cnonce = null;
    this._nc = 0;
    this._ncHex = '00000000';
    this._algorithm = null;
    this._realm = null;
    this._nonce = null;
    this._opaque = null;
    this._stale = null;
    this._qop = null;
    this._method = null;
    this._uri = null;
    this._ha1 = null;
    this._response = null;
  }

  _createClass(DigestAuthentication, [{
    key: "get",
    value: function get(parameter) {
      switch (parameter) {
        case 'realm':
          return this._realm;

        case 'ha1':
          return this._ha1;

        default:
          debugerror('get() | cannot get "%s" parameter', parameter);
          return undefined;
      }
    }
    /**
    * Performs Digest authentication given a SIP request and the challenge
    * received in a response to that request.
    * Returns true if auth was successfully generated, false otherwise.
    */

  }, {
    key: "authenticate",
    value: function authenticate(_ref, challenge)
    /* test interface */
    {
      var method = _ref.method,
          ruri = _ref.ruri,
          body = _ref.body;
      var cnonce = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      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') {
          debugerror('authenticate() | challenge with Digest algorithm different than "MD5", authentication aborted');
          return false;
        }
      } else {
        this._algorithm = 'MD5';
      }

      if (!this._nonce) {
        debugerror('authenticate() | challenge without Digest nonce, authentication aborted');
        return false;
      }

      if (!this._realm) {
        debugerror('authenticate() | challenge without Digest realm, authentication aborted');
        return false;
      } // If no plain SIP password is provided.


      if (!this._credentials.password) {
        // If ha1 is not provided we cannot authenticate.
        if (!this._credentials.ha1) {
          debugerror('authenticate() | no plain SIP password nor ha1 provided, authentication aborted');
          return false;
        } // If the realm does not match the stored realm we cannot authenticate.


        if (this._credentials.realm !== this._realm) {
          debugerror('authenticate() | no plain SIP password, and stored `realm` does not match the given `realm`, cannot authenticate [stored:"%s", given:"%s"]', this._credentials.realm, this._realm);
          return false;
        }
      } // 'qop' can contain a list of values (Array). Let's choose just one.


      if (challenge.qop) {
        if (challenge.qop.indexOf('auth-int') > -1) {
          this._qop = 'auth-int';
        } else if (challenge.qop.indexOf('auth') > -1) {
          this._qop = 'auth';
        } else {
          // Otherwise 'qop' is present but does not contain 'auth' or 'auth-int', so abort here.
          debugerror('authenticate() | challenge without Digest qop different than "auth" or "auth-int", authentication aborted');
          return false;
        }
      } else {
        this._qop = null;
      } // Fill other attributes.


      this._method = method;
      this._uri = ruri;
      this._cnonce = cnonce || Utils.createRandomToken(12);
      this._nc += 1;
      var hex = Number(this._nc).toString(16);
      this._ncHex = '00000000'.substr(0, 8 - hex.length) + hex; // Nc-value = 8LHEX. Max value = 'FFFFFFFF'.

      if (this._nc === 4294967296) {
        this._nc = 1;
        this._ncHex = '00000001';
      } // Calculate the Digest "response" value.
      // If we have plain SIP password then regenerate ha1.


      if (this._credentials.password) {
        // HA1 = MD5(A1) = MD5(username:realm:password).
        this._ha1 = Utils.calculateMD5("".concat(this._credentials.username, ":").concat(this._realm, ":").concat(this._credentials.password));
      } // Otherwise reuse the stored ha1.
      else {
          this._ha1 = this._credentials.ha1;
        }

      var a2;
      var ha2;

      if (this._qop === 'auth') {
        // HA2 = MD5(A2) = MD5(method:digestURI).
        a2 = "".concat(this._method, ":").concat(this._uri);
        ha2 = Utils.calculateMD5(a2);
        debug('authenticate() | using qop=auth [a2:"%s"]', a2); // Response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2).

        this._response = Utils.calculateMD5("".concat(this._ha1, ":").concat(this._nonce, ":").concat(this._ncHex, ":").concat(this._cnonce, ":auth:").concat(ha2));
      } else if (this._qop === 'auth-int') {
        // HA2 = MD5(A2) = MD5(method:digestURI:MD5(entityBody)).
        a2 = "".concat(this._method, ":").concat(this._uri, ":").concat(Utils.calculateMD5(body ? body : ''));
        ha2 = Utils.calculateMD5(a2);
        debug('authenticate() | using qop=auth-int [a2:"%s"]', a2); // Response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2).

        this._response = Utils.calculateMD5("".concat(this._ha1, ":").concat(this._nonce, ":").concat(this._ncHex, ":").concat(this._cnonce, ":auth-int:").concat(ha2));
      } else if (this._qop === null) {
        // HA2 = MD5(A2) = MD5(method:digestURI).
        a2 = "".concat(this._method, ":").concat(this._uri);
        ha2 = Utils.calculateMD5(a2);
        debug('authenticate() | using qop=null [a2:"%s"]', a2); // Response = MD5(HA1:nonce:HA2).

        this._response = Utils.calculateMD5("".concat(this._ha1, ":").concat(this._nonce, ":").concat(ha2));
      }

      debug('authenticate() | response generated');
      return true;
    }
    /**
    * Return the Proxy-Authorization or WWW-Authorization header value.
    */

  }, {
    key: "toString",
    value: function toString() {
      var auth_params = [];

      if (!this._response) {
        throw new Error('response field does not exist, cannot generate Authorization header');
      }

      auth_params.push("algorithm=".concat(this._algorithm));
      auth_params.push("username=\"".concat(this._credentials.username, "\""));
      auth_params.push("realm=\"".concat(this._realm, "\""));
      auth_params.push("nonce=\"".concat(this._nonce, "\""));
      auth_params.push("uri=\"".concat(this._uri, "\""));
      auth_params.push("response=\"".concat(this._response, "\""));

      if (this._opaque) {
        auth_params.push("opaque=\"".concat(this._opaque, "\""));
      }

      if (this._qop) {
        auth_params.push("qop=".concat(this._qop));
        auth_params.push("cnonce=\"".concat(this._cnonce, "\""));
        auth_params.push("nc=".concat(this._ncHex));
      }

      return "Digest ".concat(auth_params.join(', '));
    }
  }]);

  return DigestAuthentication;
}();
},{"./Utils":26,"debug":30}],6:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }

function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

var ConfigurationError = /*#__PURE__*/function (_Error) {
  _inherits(ConfigurationError, _Error);

  var _super = _createSuper(ConfigurationError);

  function ConfigurationError(parameter, value) {
    var _this;

    _classCallCheck(this, ConfigurationError);

    _this = _super.call(this);
    _this.code = 1;
    _this.name = 'CONFIGURATION_ERROR';
    _this.parameter = parameter;
    _this.value = value;
    _this.message = !_this.value ? "Missing parameter: ".concat(_this.parameter) : "Invalid value ".concat(JSON.stringify(_this.value), " for parameter \"").concat(_this.parameter, "\"");
    return _this;
  }

  return ConfigurationError;
}( /*#__PURE__*/_wrapNativeSuper(Error));

var InvalidStateError = /*#__PURE__*/function (_Error2) {
  _inherits(InvalidStateError, _Error2);

  var _super2 = _createSuper(InvalidStateError);

  function InvalidStateError(status) {
    var _this2;

    _classCallCheck(this, InvalidStateError);

    _this2 = _super2.call(this);
    _this2.code = 2;
    _this2.name = 'INVALID_STATE_ERROR';
    _this2.status = status;
    _this2.message = "Invalid status: ".concat(status);
    return _this2;
  }

  return InvalidStateError;
}( /*#__PURE__*/_wrapNativeSuper(Error));

var NotSupportedError = /*#__PURE__*/function (_Error3) {
  _inherits(NotSupportedError, _Error3);

  var _super3 = _createSuper(NotSupportedError);

  function NotSupportedError(message) {
    var _this3;

    _classCallCheck(this, NotSupportedError);

    _this3 = _super3.call(this);
    _this3.code = 3;
    _this3.name = 'NOT_SUPPORTED_ERROR';
    _this3.message = message;
    return _this3;
  }

  return NotSupportedError;
}( /*#__PURE__*/_wrapNativeSuper(Error));

var NotReadyError = /*#__PURE__*/function (_Error4) {
  _inherits(NotReadyError, _Error4);

  var _super4 = _createSuper(NotReadyError);

  function NotReadyError(message) {
    var _this4;

    _classCallCheck(this, NotReadyError);

    _this4 = _super4.call(this);
    _this4.code = 4;
    _this4.name = 'NOT_READY_ERROR';
    _this4.message = message;
    return _this4;
  }

  return NotReadyError;
}( /*#__PURE__*/_wrapNativeSuper(Error));

module.exports = {
  ConfigurationError: ConfigurationError,
  InvalidStateError: InvalidStateError,
  NotSupportedError: NotSupportedError,
  NotReadyError: NotReadyError
};
},{}],7:[function(require,module,exports){
"use strict";

module.exports = 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 parse(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,
        "uri_scheme_sips": parse_uri_scheme_sips,
        "uri_scheme_sip": parse_uri_scheme_sip,
        "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,
        "REFERm": parse_REFERm,
        "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,
        "Reason": parse_Reason,
        "reason_param": parse_reason_param,
        "reason_cause": parse_reason_cause,
        "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_param": parse_via_param,
        "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,
        "Session_Expires": parse_Session_Expires,
        "s_e_expires": parse_s_e_expires,
        "s_e_params": parse_s_e_params,
        "s_e_refresher": parse_s_e_refresher,
        "extension_header": parse_extension_header,
        "header_value": parse_header_value,
        "message_body": parse_message_body,
        "uuid_URI": parse_uuid_URI,
        "uuid": parse_uuid,
        "hex4": parse_hex4,
        "hex8": parse_hex8,
        "hex12": parse_hex12,
        "Refer_To": parse_Refer_To,
        "Replaces": parse_Replaces,
        "call_id": parse_call_id,
        "replaces_param": parse_replaces_param,
        "to_tag": parse_to_tag,
        "from_tag": parse_from_tag,
        "early_flag": parse_early_flag
      };

      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) {
            var trimmed = input.substring(pos, offset).trim();
            return trimmed.substring(1, trimmed.length - 1) // remove outer quotes
            .replace(/\\([\x00-\x09\x0b-\x0c\x0e-\x7f])/g, '$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 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 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;
        result0 = parse_uri_scheme_sips();

        if (result0 === null) {
          result0 = parse_uri_scheme_sip();
        }

        return result0;
      }

      function parse_uri_scheme_sips() {
        var result0;
        var pos0;
        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, scheme) {
            data.scheme = scheme.toLowerCase();
          }(pos0, result0);
        }

        if (result0 === null) {
          pos = pos0;
        }

        return result0;
      }

      function parse_uri_scheme_sip() {
        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, scheme) {
            data.scheme = 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 = 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, result2;
        var pos0;
        pos0 = pos;
        result0 = parse_alphanum();

        if (result0 !== null) {
          result1 = [];
          result2 = parse_alphanum();

          if (result2 === null) {
            if (input.charCodeAt(pos) === 45) {
              result2 = "-";
              pos++;
            } else {
              result2 = null;

              if (reportFailures === 0) {
                matchFailed("\"-\"");
              }
            }

            if (result2 === null) {
              if (input.charCodeAt(pos) === 95) {
                result2 = "_";
                pos++;
              } else {
                result2 = null;

                if (reportFailures === 0) {
                  matchFailed("\"_\"");
                }
              }
            }
          }

          while (result2 !== null) {
            result1.push(result2);
            result2 = parse_alphanum();

            if (result2 === null) {
              if (input.charCodeAt(pos) === 45) {
                result2 = "-";
                pos++;
              } else {
                result2 = null;

                if (reportFailures === 0) {
                  matchFailed("\"-\"");
                }
              }

              if (result2 === null) {
                if (input.charCodeAt(pos) === 95) {
                  result2 = "_";
                  pos++;
                } else {
                  result2 = null;

                  if (reportFailures === 0) {
                    matchFailed("\"_\"");
                  }
                }
              }
            }
          }

          if (result1 !== null) {
            result0 = [result0, result1];
          } else {
            result0 = null;
            pos = pos0;
          }
        } else {
          result0 = null;
          pos = pos0;
        }

        return result0;
      }

      function parse_toplabel() {
        var result0, result1, result2;
        var pos0;
        pos0 = pos;
        result0 = parse_ALPHA();

        if (result0 !== null) {
          result1 = [];
          result2 = parse_alphanum();

          if (result2 === null) {
            if (input.charCodeAt(pos) === 45) {
              result2 = "-";
              pos++;
            } else {
              result2 = null;

              if (reportFailures === 0) {
                matchFailed("\"-\"");
              }
            }

            if (result2 === null) {
              if (input.charCodeAt(pos) === 95) {
                result2 = "_";
                pos++;
              } else {
                result2 = null;

                if (reportFailures === 0) {
                  matchFailed("\"_\"");
                }
              }
            }
          }

          while (result2 !== null) {
            result1.push(result2);
            result2 = parse_alphanum();

            if (result2 === null) {
              if (input.charCodeAt(pos) === 45) {
                result2 = "-";
                pos++;
              } else {
                result2 = null;

                if (reportFailures === 0) {
                  matchFailed("\"-\"");
                }
              }

              if (result2 === null) {
                if (input.charCodeAt(pos) === 95) {
                  result2 = "_";
                  pos++;
                } else {
                  result2 = null;

                  if (reportFailures === 0) {
                    matchFailed("\"_\"");
                  }
                }
              }
            }
          }

          if (result1 !== null) {
            result0 = [result0, result1];
          } else {
            result0 = null;
            pos = pos0;
          }
        } else {
          result0 = null;
          pos = pos0;
        }

        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;
          }(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_REFERm() {
        var result0;

        if (input.substr(pos, 5) === "REFER") {
          result0 = "REFER";
          pos += 5;
        } else {
          result0 = null;

          if (reportFailures === 0) {
            matchFailed("\"REFER\"");
          }
        }

        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_REFERm();

                        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 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_clean();
        }

        if (result0 !== null) {
          result0 = function (offset, display_name) {
            if (typeof display_name === 'string') {
              // quoted_string_clean
              data.display_name = display_name;
            } else {
              // token ( LWS token )*
              data.display_name = display_name[1].reduce(function (acc, cur) {
                return acc + cur[0] + cur[1];
              }, display_name[0]);
            }
          }(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 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 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 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_Reason() {
        var result0, result1, result2, result3;
        var pos0, pos1, pos2;
        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) {
          result0 = parse_token();
        }

        if (result0 !== null) {
          result1 = [];
          pos2 = pos;
          result2 = parse_SEMI();

          if (result2 !== null) {
            result3 = parse_reason_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_reason_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, protocol) {
            data.protocol = protocol.toLowerCase();
            if (!data.params) data.params = {};

            if (data.params.text && data.params.text[0] === '"') {
              var text = data.params.text;
              data.text = text.substring(1, text.length - 1);
              delete data.params.text;
            }
          }(pos0, result0[0]);
        }

        if (result0 === null) {
          pos = pos0;
        }

        return result0;
      }

      function parse_reason_param() {
        var result0;
        result0 = parse_reason_cause();

        if (result0 === null) {
          result0 = parse_generic_param();
        }

        return result0;
      }

      function parse_reason_cause() {
        var result0, result1, result2, result3;
        var pos0, pos1;
        pos0 = pos;
        pos1 = pos;

        if (input.substr(pos, 5).toLowerCase() === "cause") {
          result0 = input.substr(pos, 5);
          pos += 5;
        } else {
          result0 = null;

          if (reportFailures === 0) {
            matchFailed("\"cause\"");
          }
        }

        if (result0 !== null) {
          result1 = parse_EQUAL();

          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) {
              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, cause) {
            data.cause = parseInt(cause.join(''));
          }(pos0, result0[2]);
        }

        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 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_param();

        if (result0 !== null) {
          result1 = [];
          pos1 = pos;
          result2 = parse_COMMA();

          if (result2 !== null) {
            result3 = parse_via_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_via_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_via_param() {
        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_Session_Expires() {
        var result0, result1, result2, result3;
        var pos0, pos1;
        pos0 = pos;
        result0 = parse_s_e_expires();

        if (result0 !== null) {
          result1 = [];
          pos1 = pos;
          result2 = parse_SEMI();

          if (result2 !== null) {
            result3 = parse_s_e_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_s_e_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_s_e_expires() {
        var result0;
        var pos0;
        pos0 = pos;
        result0 = parse_delta_seconds();

        if (result0 !== null) {
          result0 = function (offset, expires) {
            data.expires = expires;
          }(pos0, result0);
        }

        if (result0 === null) {
          pos = pos0;
        }

        return result0;
      }

      function parse_s_e_params() {
        var result0;
        result0 = parse_s_e_refresher();

        if (result0 === null) {
          result0 = parse_generic_param();
        }

        return result0;
      }

      function parse_s_e_refresher() {
        var result0, result1, result2;
        var pos0, pos1;
        pos0 = pos;
        pos1 = pos;

        if (input.substr(pos, 9).toLowerCase() === "refresher") {
          result0 = input.substr(pos, 9);
          pos += 9;
        } else {
          result0 = null;

          if (reportFailures === 0) {
            matchFailed("\"refresher\"");
          }
        }

        if (result0 !== null) {
          result1 = parse_EQUAL();

          if (result1 !== null) {
            if (input.substr(pos, 3).toLowerCase() === "uac") {
              result2 = input.substr(pos, 3);
              pos += 3;
            } else {
              result2 = null;

              if (reportFailures === 0) {
                matchFailed("\"uac\"");
              }
            }

            if (result2 === null) {
              if (input.substr(pos, 3).toLowerCase() === "uas") {
                result2 = input.substr(pos, 3);
                pos += 3;
              } else {
                result2 = null;

                if (reportFailures === 0) {
                  matchFailed("\"uas\"");
                }
              }
            }

            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, s_e_refresher_value) {
            data.refresher = s_e_refresher_value.toLowerCase();
          }(pos0, result0[2]);
        }

        if (result0 === null) {
          pos = pos0;
        }

        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_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 parse_Refer_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_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) {
            try {
              data = new NameAddrHeader(data.uri, data.display_name, data.params);
            } catch (e) {
              data = -1;
            }
          }(pos0);
        }

        if (result0 === null) {
          pos = pos0;
        }

        return result0;
      }

      function parse_Replaces() {
        var result0, result1, result2, result3;
        var pos0, pos1;
        pos0 = pos;
        result0 = parse_call_id();

        if (result0 !== null) {
          result1 = [];
          pos1 = pos;
          result2 = parse_SEMI();

          if (result2 !== null) {
            result3 = parse_replaces_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_replaces_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_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.call_id = input.substring(pos, offset);
          }(pos0);
        }

        if (result0 === null) {
          pos = pos0;
        }

        return result0;
      }

      function parse_replaces_param() {
        var result0;
        result0 = parse_to_tag();

        if (result0 === null) {
          result0 = parse_from_tag();

          if (result0 === null) {
            result0 = parse_early_flag();

            if (result0 === null) {
              result0 = parse_generic_param();
            }
          }
        }

        return result0;
      }

      function parse_to_tag() {
        var result0, result1, result2;
        var pos0, pos1;
        pos0 = pos;
        pos1 = pos;

        if (input.substr(pos, 6) === "to-tag") {
          result0 = "to-tag";
          pos += 6;
        } else {
          result0 = null;

          if (reportFailures === 0) {
            matchFailed("\"to-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, to_tag) {
            data.to_tag = to_tag;
          }(pos0, result0[2]);
        }

        if (result0 === null) {
          pos = pos0;
        }

        return result0;
      }

      function parse_from_tag() {
        var result0, result1, result2;
        var pos0, pos1;
        pos0 = pos;
        pos1 = pos;

        if (input.substr(pos, 8) === "from-tag") {
          result0 = "from-tag";
          pos += 8;
        } else {
          result0 = null;

          if (reportFailures === 0) {
            matchFailed("\"from-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, from_tag) {
            data.from_tag = from_tag;
          }(pos0, result0[2]);
        }

        if (result0 === null) {
          pos = pos0;
        }

        return result0;
      }

      function parse_early_flag() {
        var result0;
        var pos0;
        pos0 = pos;

        if (input.substr(pos, 10) === "early-only") {
          result0 = "early-only";
          pos += 10;
        } else {
          result0 = null;

          if (reportFailures === 0) {
            matchFailed("\"early-only\"");
          }
        }

        if (result0 !== null) {
          result0 = function (offset) {
            data.early_only = true;
          }(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 URI = require('./URI');

      var NameAddrHeader = require('./NameAddrHeader');

      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 toSource() {
      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;
}();
},{"./NameAddrHeader":10,"./URI":25}],8:[function(require,module,exports){
"use strict";

var pkg = require('../package.json');

var C = require('./Constants');

var Exceptions = require('./Exceptions');

var Utils = require('./Utils');

var UA = require('./UA');

var URI = require('./URI');

var NameAddrHeader = require('./NameAddrHeader');

var Grammar = require('./Grammar');

var WebSocketInterface = require('./WebSocketInterface');

var debug = require('debug')('JsSIP');

debug('version %s', pkg.version);
/**
 * Expose the JsSIP module.
 */

module.exports = {
  C: C,
  Exceptions: Exceptions,
  Utils: Utils,
  UA: UA,
  URI: URI,
  NameAddrHeader: NameAddrHeader,
  WebSocketInterface: WebSocketInterface,
  Grammar: Grammar,
  // Expose the debug module.
  debug: require('debug'),

  get name() {
    return pkg.title;
  },

  get version() {
    return pkg.version;
  }

};
},{"../package.json":38,"./Constants":2,"./Exceptions":6,"./Grammar":7,"./NameAddrHeader":10,"./UA":24,"./URI":25,"./Utils":26,"./WebSocketInterface":27,"debug":30}],9:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

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

var JsSIP_C = require('./Constants');

var SIPMessage = require('./SIPMessage');

var Utils = require('./Utils');

var RequestSender = require('./RequestSender');

var Exceptions = require('./Exceptions');

var debug = require('debug')('JsSIP:Message');

module.exports = /*#__PURE__*/function (_EventEmitter) {
  _inherits(Message, _EventEmitter);

  var _super = _createSuper(Message);

  function Message(ua) {
    var _this;

    _classCallCheck(this, Message);

    _this = _super.call(this);
    _this._ua = ua;
    _this._request = null;
    _this._closed = false;
    _this._direction = null;
    _this._local_identity = null;
    _this._remote_identity = null; // Whether an incoming message has been replied.

    _this._is_replied = false; // Custom message empty object for high level use.

    _this._data = {};
    return _this;
  }

  _createClass(Message, [{
    key: "send",
    value: function send(target, body) {
      var _this2 = this;

      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      var 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: ".concat(originalTarget));
      } // Get call options.


      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var eventHandlers = Utils.cloneObject(options.eventHandlers);
      var contentType = options.contentType || 'text/plain'; // Set event handlers.

      for (var event in eventHandlers) {
        if (Object.prototype.hasOwnProperty.call(eventHandlers, event)) {
          this.on(event, eventHandlers[event]);
        }
      }

      extraHeaders.push("Content-Type: ".concat(contentType));
      this._request = new SIPMessage.OutgoingRequest(JsSIP_C.MESSAGE, target, this._ua, null, extraHeaders);

      if (body) {
        this._request.body = body;
      }

      var request_sender = new RequestSender(this._ua, this._request, {
        onRequestTimeout: function onRequestTimeout() {
          _this2._onRequestTimeout();
        },
        onTransportError: function onTransportError() {
          _this2._onTransportError();
        },
        onReceiveResponse: function onReceiveResponse(response) {
          _this2._receiveResponse(response);
        }
      });

      this._newMessage('local', this._request);

      request_sender.send();
    }
  }, {
    key: "init_incoming",
    value: function init_incoming(request) {
      this._request = request;

      this._newMessage('remote', request); // Reply with a 200 OK if the user didn't reply.


      if (!this._is_replied) {
        this._is_replied = true;
        request.reply(200);
      }

      this._close();
    }
    /**
     * Accept the incoming Message
     * Only valid for incoming Messages
     */

  }, {
    key: "accept",
    value: function accept() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var body = options.body;

      if (this._direction !== 'incoming') {
        throw new Exceptions.NotSupportedError('"accept" not supported for outgoing Message');
      }

      if (this._is_replied) {
        throw new Error('incoming Message already replied');
      }

      this._is_replied = true;

      this._request.reply(200, null, extraHeaders, body);
    }
    /**
     * Reject the incoming Message
     * Only valid for incoming Messages
     */

  }, {
    key: "reject",
    value: function reject() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var status_code = options.status_code || 480;
      var reason_phrase = options.reason_phrase;
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var body = options.body;

      if (this._direction !== 'incoming') {
        throw new Exceptions.NotSupportedError('"reject" not supported for outgoing Message');
      }

      if (this._is_replied) {
        throw new Error('incoming Message already replied');
      }

      if (status_code < 300 || status_code >= 700) {
        throw new TypeError("Invalid status_code: ".concat(status_code));
      }

      this._is_replied = true;

      this._request.reply(status_code, reason_phrase, extraHeaders, body);
    }
  }, {
    key: "_receiveResponse",
    value: function _receiveResponse(response) {
      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):
          this._succeeded('remote', response);

          break;

        default:
          {
            var cause = Utils.sipErrorCause(response.status_code);

            this._failed('remote', response, cause);

            break;
          }
      }
    }
  }, {
    key: "_onRequestTimeout",
    value: function _onRequestTimeout() {
      if (this._closed) {
        return;
      }

      this._failed('system', null, JsSIP_C.causes.REQUEST_TIMEOUT);
    }
  }, {
    key: "_onTransportError",
    value: function _onTransportError() {
      if (this._closed) {
        return;
      }

      this._failed('system', null, JsSIP_C.causes.CONNECTION_ERROR);
    }
  }, {
    key: "_close",
    value: function _close() {
      this._closed = true;

      this._ua.destroyMessage(this);
    }
    /**
     * Internal Callbacks
     */

  }, {
    key: "_newMessage",
    value: function _newMessage(originator, request) {
      if (originator === 'remote') {
        this._direction = 'incoming';
        this._local_identity = request.to;
        this._remote_identity = request.from;
      } else if (originator === 'local') {
        this._direction = 'outgoing';
        this._local_identity = request.from;
        this._remote_identity = request.to;
      }

      this._ua.newMessage(this, {
        originator: originator,
        message: this,
        request: request
      });
    }
  }, {
    key: "_failed",
    value: function _failed(originator, response, cause) {
      debug('MESSAGE failed');

      this._close();

      debug('emit "failed"');
      this.emit('failed', {
        originator: originator,
        response: response || null,
        cause: cause
      });
    }
  }, {
    key: "_succeeded",
    value: function _succeeded(originator, response) {
      debug('MESSAGE succeeded');

      this._close();

      debug('emit "succeeded"');
      this.emit('succeeded', {
        originator: originator,
        response: response
      });
    }
  }, {
    key: "direction",
    get: function get() {
      return this._direction;
    }
  }, {
    key: "local_identity",
    get: function get() {
      return this._local_identity;
    }
  }, {
    key: "remote_identity",
    get: function get() {
      return this._remote_identity;
    }
  }]);

  return Message;
}(EventEmitter);
},{"./Constants":2,"./Exceptions":6,"./RequestSender":18,"./SIPMessage":19,"./Utils":26,"debug":30,"events":29}],10:[function(require,module,exports){
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var URI = require('./URI');

var Grammar = require('./Grammar');

module.exports = /*#__PURE__*/function () {
  _createClass(NameAddrHeader, null, [{
    key: "parse",

    /**
     * Parse the given string and returns a NameAddrHeader instance or undefined if
     * it is an invalid NameAddrHeader.
     */
    value: function parse(name_addr_header) {
      name_addr_header = Grammar.parse(name_addr_header, 'Name_Addr_Header');

      if (name_addr_header !== -1) {
        return name_addr_header;
      } else {
        return undefined;
      }
    }
  }]);

  function NameAddrHeader(uri, display_name, parameters) {
    _classCallCheck(this, NameAddrHeader);

    // Checks.
    if (!uri || !(uri instanceof URI)) {
      throw new TypeError('missing or invalid "uri" parameter');
    } // Initialize parameters.


    this._uri = uri;
    this._parameters = {};
    this.display_name = display_name;

    for (var param in parameters) {
      if (Object.prototype.hasOwnProperty.call(parameters, param)) {
        this.setParam(param, parameters[param]);
      }
    }
  }

  _createClass(NameAddrHeader, [{
    key: "setParam",
    value: function setParam(key, value) {
      if (key) {
        this._parameters[key.toLowerCase()] = typeof value === 'undefined' || value === null ? null : value.toString();
      }
    }
  }, {
    key: "getParam",
    value: function getParam(key) {
      if (key) {
        return this._parameters[key.toLowerCase()];
      }
    }
  }, {
    key: "hasParam",
    value: function hasParam(key) {
      if (key) {
        return this._parameters.hasOwnProperty(key.toLowerCase()) && true || false;
      }
    }
  }, {
    key: "deleteParam",
    value: function deleteParam(parameter) {
      parameter = parameter.toLowerCase();

      if (this._parameters.hasOwnProperty(parameter)) {
        var value = this._parameters[parameter];
        delete this._parameters[parameter];
        return value;
      }
    }
  }, {
    key: "clearParams",
    value: function clearParams() {
      this._parameters = {};
    }
  }, {
    key: "clone",
    value: function clone() {
      return new NameAddrHeader(this._uri.clone(), this._display_name, JSON.parse(JSON.stringify(this._parameters)));
    }
  }, {
    key: "_quote",
    value: function _quote(str) {
      return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
    }
  }, {
    key: "toString",
    value: function toString() {
      var body = this._display_name ? "\"".concat(this._quote(this._display_name), "\" ") : '';
      body += "<".concat(this._uri.toString(), ">");

      for (var parameter in this._parameters) {
        if (Object.prototype.hasOwnProperty.call(this._parameters, parameter)) {
          body += ";".concat(parameter);

          if (this._parameters[parameter] !== null) {
            body += "=".concat(this._parameters[parameter]);
          }
        }
      }

      return body;
    }
  }, {
    key: "uri",
    get: function get() {
      return this._uri;
    }
  }, {
    key: "display_name",
    get: function get() {
      return this._display_name;
    },
    set: function set(value) {
      this._display_name = value === 0 ? '0' : value;
    }
  }]);

  return NameAddrHeader;
}();
},{"./Grammar":7,"./URI":25}],11:[function(require,module,exports){
"use strict";

function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

var Grammar = require('./Grammar');

var SIPMessage = require('./SIPMessage');

var debugerror = require('debug')('JsSIP:ERROR:Parser');

debugerror.log = console.warn.bind(console);
/**
 * Parse SIP Message
 */

exports.parseMessage = function (data, ua) {
  var message;
  var bodyStart;
  var headerEnd = data.indexOf('\r\n');

  if (headerEnd === -1) {
    debugerror('parseMessage() | no CRLF found, not a SIP message');
    return;
  } // Parse first line. Check if it is a Request or a Reply.


  var firstLine = data.substring(0, headerEnd);
  var parsed = Grammar.parse(firstLine, 'Request_Response');

  if (parsed === -1) {
    debugerror("parseMessage() | error parsing first line of SIP message: \"".concat(firstLine, "\""));
    return;
  } else if (!parsed.status_code) {
    message = new SIPMessage.IncomingRequest(ua);
    message.method = parsed.method;
    message.ruri = parsed.uri;
  } else {
    message = new SIPMessage.IncomingResponse();
    message.status_code = parsed.status_code;
    message.reason_phrase = parsed.reason_phrase;
  }

  message.data = data;
  var 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) {
        debugerror('parseMessage() | malformed message');
        return;
      }

    parsed = parseHeader(message, data, headerStart, headerEnd);

    if (parsed !== true) {
      debugerror('parseMessage() |', 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')) {
    var contentLength = message.getHeader('content-length');
    message.body = data.substr(bodyStart, contentLength);
  } else {
    message.body = data.substring(bodyStart);
  }

  return message;
};
/**
 * Extract and parse every header of a SIP message.
 */


function getHeader(data, headerStart) {
  // 'start' position of the header.
  var start = headerStart; // 'end' position of the header.

  var end = 0; // 'partial end' position of the header.

  var 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 parsed;
  var hcolonIndex = data.indexOf(':', headerStart);
  var headerName = data.substring(headerStart, hcolonIndex).trim();
  var 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 = Grammar.parse(headerValue, 'Record_Route');

      if (parsed === -1) {
        parsed = undefined;
      } else {
        var _iterator = _createForOfIteratorHelper(parsed),
            _step;

        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var header = _step.value;
            message.addHeader('record-route', headerValue.substring(header.possition, header.offset));
            message.headers['Record-Route'][message.getHeaders('record-route').length - 1].parsed = header.parsed;
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }
      }

      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 = Grammar.parse(headerValue, 'Contact');

      if (parsed === -1) {
        parsed = undefined;
      } else {
        var _iterator2 = _createForOfIteratorHelper(parsed),
            _step2;

        try {
          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
            var _header = _step2.value;
            message.addHeader('contact', headerValue.substring(_header.possition, _header.offset));
            message.headers.Contact[message.getHeaders('contact').length - 1].parsed = _header.parsed;
          }
        } catch (err) {
          _iterator2.e(err);
        } finally {
          _iterator2.f();
        }
      }

      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 SIPMessage.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;

    case 'session-expires':
    case 'x':
      message.setHeader('session-expires', headerValue);
      parsed = message.parseHeader('session-expires');

      if (parsed) {
        message.session_expires = parsed.expires;
        message.session_expires_refresher = parsed.refresher;
      }

      break;

    case 'refer-to':
    case 'r':
      message.setHeader('refer-to', headerValue);
      parsed = message.parseHeader('refer-to');

      if (parsed) {
        message.refer_to = parsed;
      }

      break;

    case 'replaces':
      message.setHeader('replaces', headerValue);
      parsed = message.parseHeader('replaces');

      if (parsed) {
        message.replaces = parsed;
      }

      break;

    case 'event':
    case 'o':
      message.setHeader('event', headerValue);
      parsed = message.parseHeader('event');

      if (parsed) {
        message.event = parsed;
      }

      break;

    default:
      // Do not parse this header.
      message.addHeader(headerName, headerValue);
      parsed = 0;
  }

  if (parsed === undefined) {
    return {
      error: "error parsing header \"".concat(headerName, "\"")
    };
  } else {
    return true;
  }
}
},{"./Grammar":7,"./SIPMessage":19,"debug":30}],12:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

/* globals RTCPeerConnection: false, RTCSessionDescription: false */
var EventEmitter = require('events').EventEmitter;

var sdp_transform = require('sdp-transform');

var JsSIP_C = require('./Constants');

var Exceptions = require('./Exceptions');

var Transactions = require('./Transactions');

var Utils = require('./Utils');

var Timers = require('./Timers');

var SIPMessage = require('./SIPMessage');

var Dialog = require('./Dialog');

var RequestSender = require('./RequestSender');

var RTCSession_DTMF = require('./RTCSession/DTMF');

var RTCSession_Info = require('./RTCSession/Info');

var RTCSession_ReferNotifier = require('./RTCSession/ReferNotifier');

var RTCSession_ReferSubscriber = require('./RTCSession/ReferSubscriber');

var URI = require('./URI');

var debug = require('debug')('JsSIP:RTCSession');

var debugerror = require('debug')('JsSIP:ERROR:RTCSession');

debugerror.log = console.warn.bind(console);
var 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
};
/**
 * Local variables.
 */

var holdMediaTypes = ['audio', 'video'];

module.exports = /*#__PURE__*/function (_EventEmitter) {
  _inherits(RTCSession, _EventEmitter);

  var _super = _createSuper(RTCSession);

  _createClass(RTCSession, null, [{
    key: "C",

    /**
     * Expose C object.
     */
    get: function get() {
      return C;
    }
  }]);

  function RTCSession(ua) {
    var _this;

    _classCallCheck(this, RTCSession);

    debug('new');
    _this = _super.call(this);
    _this._id = null;
    _this._ua = ua;
    _this._status = C.STATUS_NULL;
    _this._dialog = null;
    _this._earlyDialogs = {};
    _this._contact = null;
    _this._from_tag = null;
    _this._to_tag = null; // The RTCPeerConnection instance (public attribute).

    _this._connection = null; // Prevent races on serial PeerConnction operations.

    _this._connectionPromiseQueue = Promise.resolve(); // Incoming/Outgoing request being currently processed.

    _this._request = null; // Cancel state for initial outgoing request.

    _this._is_canceled = false;
    _this._cancel_reason = ''; // RTCSession confirmation flag.

    _this._is_confirmed = false; // Is late SDP being negotiated.

    _this._late_sdp = false; // Default rtcOfferConstraints and rtcAnswerConstrainsts (passed in connect() or answer()).

    _this._rtcOfferConstraints = null;
    _this._rtcAnswerConstraints = null; // Local MediaStream.

    _this._localMediaStream = null;
    _this._localMediaStreamLocallyGenerated = false; // Flag to indicate PeerConnection ready for new actions.

    _this._rtcReady = true; // SIP 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._localHold = false;
    _this._remoteHold = false; // Session Timers (RFC 4028).

    _this._sessionTimers = {
      enabled: _this._ua.configuration.session_timers,
      refreshMethod: _this._ua.configuration.session_timers_refresh_method,
      defaultExpires: JsSIP_C.SESSION_EXPIRES,
      currentExpires: null,
      running: false,
      refresher: false,
      timer: null // A setTimeout.

    }; // Map of ReferSubscriber instances indexed by the REFER's CSeq number.

    _this._referSubscribers = {}; // Custom session empty object for high level use.

    _this._data = {};
    return _this;
  }
  /**
   * User API
   */
  // Expose RTCSession constants as a property of the RTCSession instance.


  _createClass(RTCSession, [{
    key: "isInProgress",
    value: function isInProgress() {
      switch (this._status) {
        case C.STATUS_NULL:
        case C.STATUS_INVITE_SENT:
        case C.STATUS_1XX_RECEIVED:
        case C.STATUS_INVITE_RECEIVED:
        case C.STATUS_WAITING_FOR_ANSWER:
          return true;

        default:
          return false;
      }
    }
  }, {
    key: "isEstablished",
    value: function isEstablished() {
      switch (this._status) {
        case C.STATUS_ANSWERED:
        case C.STATUS_WAITING_FOR_ACK:
        case C.STATUS_CONFIRMED:
          return true;

        default:
          return false;
      }
    }
  }, {
    key: "isEnded",
    value: function isEnded() {
      switch (this._status) {
        case C.STATUS_CANCELED:
        case C.STATUS_TERMINATED:
          return true;

        default:
          return false;
      }
    }
  }, {
    key: "isMuted",
    value: function isMuted() {
      return {
        audio: this._audioMuted,
        video: this._videoMuted
      };
    }
  }, {
    key: "isOnHold",
    value: function isOnHold() {
      return {
        local: this._localHold,
        remote: this._remoteHold
      };
    }
  }, {
    key: "connect",
    value: function connect(target) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var initCallback = arguments.length > 2 ? arguments[2] : undefined;
      debug('connect()');
      var originalTarget = target;
      var eventHandlers = Utils.cloneObject(options.eventHandlers);
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var mediaConstraints = Utils.cloneObject(options.mediaConstraints, {
        audio: true,
        video: true
      });
      var mediaStream = options.mediaStream || null;
      var pcConfig = Utils.cloneObject(options.pcConfig, {
        iceServers: []
      });
      var rtcConstraints = options.rtcConstraints || null;
      var rtcOfferConstraints = options.rtcOfferConstraints || null;
      this._rtcOfferConstraints = rtcOfferConstraints;
      this._rtcAnswerConstraints = options.rtcAnswerConstraints || null;
      this._data = options.data || this._data; // Check target.

      if (target === undefined) {
        throw new TypeError('Not enough arguments');
      } // Check Session Status.


      if (this._status !== C.STATUS_NULL) {
        throw new Exceptions.InvalidStateError(this._status);
      } // Check WebRTC support.


      if (!window.RTCPeerConnection) {
        throw new Exceptions.NotSupportedError('WebRTC not supported');
      } // Check target validity.


      target = this._ua.normalizeTarget(target);

      if (!target) {
        throw new TypeError("Invalid target: ".concat(originalTarget));
      } // Session Timers.


      if (this._sessionTimers.enabled) {
        if (Utils.isDecimal(options.sessionTimersExpires)) {
          if (options.sessionTimersExpires >= JsSIP_C.MIN_SESSION_EXPIRES) {
            this._sessionTimers.defaultExpires = options.sessionTimersExpires;
          } else {
            this._sessionTimers.defaultExpires = JsSIP_C.SESSION_EXPIRES;
          }
        }
      } // Set event handlers.


      for (var event in eventHandlers) {
        if (Object.prototype.hasOwnProperty.call(eventHandlers, event)) {
          this.on(event, eventHandlers[event]);
        }
      } // Session parameter initialization.


      this._from_tag = Utils.newTag(); // Set anonymous property.

      var anonymous = options.anonymous || false;
      var requestParams = {
        from_tag: this._from_tag
      };
      this._contact = this._ua.contact.toString({
        anonymous: anonymous,
        outbound: true
      });

      if (anonymous) {
        requestParams.from_display_name = 'Anonymous';
        requestParams.from_uri = new URI('sip', 'anonymous', 'anonymous.invalid');
        extraHeaders.push("P-Preferred-Identity: ".concat(this._ua.configuration.uri.toString()));
        extraHeaders.push('Privacy: id');
      }

      extraHeaders.push("Contact: ".concat(this._contact));
      extraHeaders.push('Content-Type: application/sdp');

      if (this._sessionTimers.enabled) {
        extraHeaders.push("Session-Expires: ".concat(this._sessionTimers.defaultExpires));
      }

      this._request = new SIPMessage.InitialOutgoingInviteRequest(target, this._ua, requestParams, extraHeaders);
      this._id = this._request.call_id + this._from_tag; // Create a new RTCPeerConnection instance.

      this._createRTCConnection(pcConfig, rtcConstraints); // Set internal properties.


      this._direction = 'outgoing';
      this._local_identity = this._request.from;
      this._remote_identity = this._request.to; // User explicitly provided a newRTCSession callback for this session.

      if (initCallback) {
        initCallback(this);
      }

      this._newRTCSession('local', this._request);

      this._sendInitialRequest(mediaConstraints, rtcOfferConstraints, mediaStream);
    }
  }, {
    key: "init_incoming",
    value: function init_incoming(request, initCallback) {
      var _this2 = this;

      debug('init_incoming()');
      var expires;
      var 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(); // 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 = 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;
      }

      if (request.body) {
        this._late_sdp = false;
      } else {
        this._late_sdp = true;
      }

      this._status = C.STATUS_WAITING_FOR_ANSWER; // Set userNoAnswerTimer.

      this._timers.userNoAnswerTimer = setTimeout(function () {
        request.reply(408);

        _this2._failed('local', null, JsSIP_C.causes.NO_ANSWER);
      }, this._ua.configuration.no_answer_timeout);
      /* Set expiresTimer
       * RFC3261 13.3.1
       */

      if (expires) {
        this._timers.expiresTimer = setTimeout(function () {
          if (_this2._status === C.STATUS_WAITING_FOR_ANSWER) {
            request.reply(487);

            _this2._failed('system', null, JsSIP_C.causes.EXPIRES);
          }
        }, expires);
      } // Set internal properties.


      this._direction = 'incoming';
      this._local_identity = request.to;
      this._remote_identity = request.from; // A init callback was specifically defined.

      if (initCallback) {
        initCallback(this);
      } // Fire 'newRTCSession' event.


      this._newRTCSession('remote', request); // The user may have rejected the call in the 'newRTCSession' event.


      if (this._status === C.STATUS_TERMINATED) {
        return;
      } // Reply 180.


      request.reply(180, null, ["Contact: ".concat(this._contact)]); // Fire 'progress' event.
      // TODO: Document that 'response' field in 'progress' event is null for incoming calls.

      this._progress('local', null);
    }
    /**
     * Answer the call.
     */

  }, {
    key: "answer",
    value: function answer() {
      var _this3 = this;

      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      debug('answer()');
      var request = this._request;
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var mediaConstraints = Utils.cloneObject(options.mediaConstraints);
      var mediaStream = options.mediaStream || null;
      var pcConfig = Utils.cloneObject(options.pcConfig, {
        iceServers: []
      });
      var rtcConstraints = options.rtcConstraints || null;
      var rtcAnswerConstraints = options.rtcAnswerConstraints || null;
      var rtcOfferConstraints = options.rtcOfferConstraints || {};
      var tracks;
      var peerHasAudioLine = false;
      var peerHasVideoLine = false;
      var peerOffersFullAudio = false;
      var peerOffersFullVideo = false;
      this._rtcAnswerConstraints = rtcAnswerConstraints;
      this._rtcOfferConstraints = options.rtcOfferConstraints || null;
      this._data = options.data || this._data; // Check Session Direction and Status.

      if (this._direction !== 'incoming') {
        throw new Exceptions.NotSupportedError('"answer" not supported for outgoing RTCSession');
      } // Check Session status.


      if (this._status !== C.STATUS_WAITING_FOR_ANSWER) {
        throw new Exceptions.InvalidStateError(this._status);
      } // Session Timers.


      if (this._sessionTimers.enabled) {
        if (Utils.isDecimal(options.sessionTimersExpires)) {
          if (options.sessionTimersExpires >= JsSIP_C.MIN_SESSION_EXPIRES) {
            this._sessionTimers.defaultExpires = options.sessionTimersExpires;
          } else {
            this._sessionTimers.defaultExpires = JsSIP_C.SESSION_EXPIRES;
          }
        }
      }

      this._status = C.STATUS_ANSWERED; // An error on dialog creation will fire 'failed' event.

      if (!this._createDialog(request, 'UAS')) {
        request.reply(500, 'Error creating dialog');
        return;
      }

      clearTimeout(this._timers.userNoAnswerTimer);
      extraHeaders.unshift("Contact: ".concat(this._contact)); // Determine incoming media from incoming SDP offer (if any).

      var sdp = request.parseSDP(); // Make sure sdp.media is an array, not the case if there is only one media.

      if (!Array.isArray(sdp.media)) {
        sdp.media = [sdp.media];
      } // Go through all medias in SDP to find offered capabilities to answer with.


      var _iterator = _createForOfIteratorHelper(sdp.media),
          _step;

      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var m = _step.value;

          if (m.type === 'audio') {
            peerHasAudioLine = true;

            if (!m.direction || m.direction === 'sendrecv') {
              peerOffersFullAudio = true;
            }
          }

          if (m.type === 'video') {
            peerHasVideoLine = true;

            if (!m.direction || m.direction === 'sendrecv') {
              peerOffersFullVideo = true;
            }
          }
        } // Remove audio from mediaStream if suggested by mediaConstraints.

      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }

      if (mediaStream && mediaConstraints.audio === false) {
        tracks = mediaStream.getAudioTracks();

        var _iterator2 = _createForOfIteratorHelper(tracks),
            _step2;

        try {
          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
            var track = _step2.value;
            mediaStream.removeTrack(track);
          }
        } catch (err) {
          _iterator2.e(err);
        } finally {
          _iterator2.f();
        }
      } // Remove video from mediaStream if suggested by mediaConstraints.


      if (mediaStream && mediaConstraints.video === false) {
        tracks = mediaStream.getVideoTracks();

        var _iterator3 = _createForOfIteratorHelper(tracks),
            _step3;

        try {
          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
            var _track = _step3.value;
            mediaStream.removeTrack(_track);
          }
        } catch (err) {
          _iterator3.e(err);
        } finally {
          _iterator3.f();
        }
      } // Set audio constraints based on incoming stream if not supplied.


      if (!mediaStream && mediaConstraints.audio === undefined) {
        mediaConstraints.audio = peerOffersFullAudio;
      } // Set video constraints based on incoming stream if not supplied.


      if (!mediaStream && mediaConstraints.video === undefined) {
        mediaConstraints.video = peerOffersFullVideo;
      } // Don't ask for audio if the incoming offer has no audio section.


      if (!mediaStream && !peerHasAudioLine && !rtcOfferConstraints.offerToReceiveAudio) {
        mediaConstraints.audio = false;
      } // Don't ask for video if the incoming offer has no video section.


      if (!mediaStream && !peerHasVideoLine && !rtcOfferConstraints.offerToReceiveVideo) {
        mediaConstraints.video = false;
      } // Create a new RTCPeerConnection instance.
      // TODO: This may throw an error, should react.


      this._createRTCConnection(pcConfig, rtcConstraints);

      Promise.resolve() // Handle local MediaStream.
      .then(function () {
        // A local MediaStream is given, use it.
        if (mediaStream) {
          return mediaStream;
        } // Audio and/or video requested, prompt getUserMedia.
        else if (mediaConstraints.audio || mediaConstraints.video) {
            _this3._localMediaStreamLocallyGenerated = true;
            return navigator.mediaDevices.getUserMedia(mediaConstraints)["catch"](function (error) {
              if (_this3._status === C.STATUS_TERMINATED) {
                throw new Error('terminated');
              }

              request.reply(480);

              _this3._failed('local', null, JsSIP_C.causes.USER_DENIED_MEDIA_ACCESS);

              debugerror('emit "getusermediafailed" [error:%o]', error);

              _this3.emit('getusermediafailed', error);

              throw new Error('getUserMedia() failed');
            });
          }
      }) // Attach MediaStream to RTCPeerconnection.
      .then(function (stream) {
        if (_this3._status === C.STATUS_TERMINATED) {
          throw new Error('terminated');
        }

        _this3._localMediaStream = stream;

        if (stream) {
          stream.getTracks().forEach(function (track) {
            _this3._connection.addTrack(track, stream);
          });
        }
      }) // Set remote description.
      .then(function () {
        if (_this3._late_sdp) {
          return;
        }

        var e = {
          originator: 'remote',
          type: 'offer',
          sdp: request.body
        };
        debug('emit "sdp"');

        _this3.emit('sdp', e);

        var offer = new RTCSessionDescription({
          type: 'offer',
          sdp: e.sdp
        });
        _this3._connectionPromiseQueue = _this3._connectionPromiseQueue.then(function () {
          return _this3._connection.setRemoteDescription(offer);
        })["catch"](function (error) {
          request.reply(488);

          _this3._failed('system', null, JsSIP_C.causes.WEBRTC_ERROR);

          debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);

          _this3.emit('peerconnection:setremotedescriptionfailed', error);

          throw new Error('peerconnection.setRemoteDescription() failed');
        });
        return _this3._connectionPromiseQueue;
      }) // Create local description.
      .then(function () {
        if (_this3._status === C.STATUS_TERMINATED) {
          throw new Error('terminated');
        } // TODO: Is this event already useful?


        _this3._connecting(request);

        if (!_this3._late_sdp) {
          return _this3._createLocalDescription('answer', rtcAnswerConstraints)["catch"](function () {
            request.reply(500);
            throw new Error('_createLocalDescription() failed');
          });
        } else {
          return _this3._createLocalDescription('offer', _this3._rtcOfferConstraints)["catch"](function () {
            request.reply(500);
            throw new Error('_createLocalDescription() failed');
          });
        }
      }) // Send reply.
      .then(function (desc) {
        if (_this3._status === C.STATUS_TERMINATED) {
          throw new Error('terminated');
        }

        _this3._handleSessionTimersInIncomingRequest(request, extraHeaders);

        request.reply(200, null, extraHeaders, desc, function () {
          _this3._status = C.STATUS_WAITING_FOR_ACK;

          _this3._setInvite2xxTimer(request, desc);

          _this3._setACKTimer();

          _this3._accepted('local');
        }, function () {
          _this3._failed('system', null, JsSIP_C.causes.CONNECTION_ERROR);
        });
      })["catch"](function (error) {
        if (_this3._status === C.STATUS_TERMINATED) {
          return;
        }

        debugerror(error);
      });
    }
    /**
     * Terminate the call.
     */

  }, {
    key: "terminate",
    value: function terminate() {
      var _this4 = this;

      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      debug('terminate()');
      var cause = options.cause || JsSIP_C.causes.BYE;
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var body = options.body;
      var cancel_reason;
      var status_code = options.status_code;
      var reason_phrase = options.reason_phrase; // Check Session Status.

      if (this._status === C.STATUS_TERMINATED) {
        throw new Exceptions.InvalidStateError(this._status);
      }

      switch (this._status) {
        // - UAC -
        case C.STATUS_NULL:
        case C.STATUS_INVITE_SENT:
        case C.STATUS_1XX_RECEIVED:
          debug('canceling session');

          if (status_code && (status_code < 200 || status_code >= 700)) {
            throw new TypeError("Invalid status_code: ".concat(status_code));
          } else if (status_code) {
            reason_phrase = reason_phrase || JsSIP_C.REASON_PHRASE[status_code] || '';
            cancel_reason = "SIP ;cause=".concat(status_code, " ;text=\"").concat(reason_phrase, "\"");
          } // Check Session Status.


          if (this._status === C.STATUS_NULL || this._status === C.STATUS_INVITE_SENT) {
            this._is_canceled = true;
            this._cancel_reason = cancel_reason;
          } else if (this._status === C.STATUS_1XX_RECEIVED) {
            this._request.cancel(cancel_reason);
          }

          this._status = C.STATUS_CANCELED;

          this._failed('local', null, JsSIP_C.causes.CANCELED);

          break;
        // - UAS -

        case C.STATUS_WAITING_FOR_ANSWER:
        case C.STATUS_ANSWERED:
          debug('rejecting session');
          status_code = status_code || 480;

          if (status_code < 300 || status_code >= 700) {
            throw new TypeError("Invalid status_code: ".concat(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:
          debug('terminating session');
          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: ".concat(status_code));
          } else if (status_code) {
            extraHeaders.push("Reason: SIP ;cause=".concat(status_code, "; text=\"").concat(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 !== Transactions.C.STATUS_TERMINATED) {
            // Save the dialog for later restoration.
            var dialog = this._dialog; // Send the BYE as soon as the ACK is received...

            this.receiveRequest = function (_ref) {
              var method = _ref.method;

              if (method === JsSIP_C.ACK) {
                _this4.sendRequest(JsSIP_C.BYE, {
                  extraHeaders: extraHeaders,
                  body: body
                });

                dialog.terminate();
              }
            }; // .., or when the INVITE transaction times out


            this._request.server_transaction.on('stateChanged', function () {
              if (_this4._request.server_transaction.state === Transactions.C.STATUS_TERMINATED) {
                _this4.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.newDialog(dialog);
          } else {
            this.sendRequest(JsSIP_C.BYE, {
              extraHeaders: extraHeaders,
              body: body
            });

            this._ended('local', null, cause);
          }

      }
    }
  }, {
    key: "sendDTMF",
    value: function sendDTMF(tones) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      debug('sendDTMF() | tones: %s', tones);
      var position = 0;
      var duration = options.duration || null;
      var 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 Exceptions.InvalidStateError(this._status);
      } // Convert to string.


      if (typeof tones === 'number') {
        tones = tones.toString();
      } // Check tones.


      if (!tones || typeof tones !== 'string' || !tones.match(/^[0-9A-DR#*,]+$/i)) {
        throw new TypeError("Invalid tones: ".concat(tones));
      } // Check duration.


      if (duration && !Utils.isDecimal(duration)) {
        throw new TypeError("Invalid tone duration: ".concat(duration));
      } else if (!duration) {
        duration = RTCSession_DTMF.C.DEFAULT_DURATION;
      } else if (duration < RTCSession_DTMF.C.MIN_DURATION) {
        debug("\"duration\" value is lower than the minimum allowed, setting it to ".concat(RTCSession_DTMF.C.MIN_DURATION, " milliseconds"));
        duration = RTCSession_DTMF.C.MIN_DURATION;
      } else if (duration > RTCSession_DTMF.C.MAX_DURATION) {
        debug("\"duration\" value is greater than the maximum allowed, setting it to ".concat(RTCSession_DTMF.C.MAX_DURATION, " milliseconds"));
        duration = RTCSession_DTMF.C.MAX_DURATION;
      } else {
        duration = Math.abs(duration);
      }

      options.duration = duration; // Check interToneGap.

      if (interToneGap && !Utils.isDecimal(interToneGap)) {
        throw new TypeError("Invalid interToneGap: ".concat(interToneGap));
      } else if (!interToneGap) {
        interToneGap = RTCSession_DTMF.C.DEFAULT_INTER_TONE_GAP;
      } else if (interToneGap < RTCSession_DTMF.C.MIN_INTER_TONE_GAP) {
        debug("\"interToneGap\" value is lower than the minimum allowed, setting it to ".concat(RTCSession_DTMF.C.MIN_INTER_TONE_GAP, " milliseconds"));
        interToneGap = RTCSession_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;
      }

      this._tones = tones; // Send the first tone.

      _sendDTMF.call(this);

      function _sendDTMF() {
        var _this5 = this;

        var timeout;

        if (this._status === C.STATUS_TERMINATED || !this._tones || position >= this._tones.length) {
          // Stop sending DTMF.
          this._tones = null;
          return;
        }

        var tone = this._tones[position];
        position += 1;

        if (tone === ',') {
          timeout = 2000;
        } else {
          var dtmf = new RTCSession_DTMF(this);
          options.eventHandlers = {
            onFailed: function onFailed() {
              _this5._tones = null;
            }
          };
          dtmf.send(tone, options);
          timeout = duration + interToneGap;
        } // Set timeout for the next tone.


        setTimeout(_sendDTMF.bind(this), timeout);
      }
    }
  }, {
    key: "sendInfo",
    value: function sendInfo(contentType, body) {
      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      debug('sendInfo()'); // Check Session Status.

      if (this._status !== C.STATUS_CONFIRMED && this._status !== C.STATUS_WAITING_FOR_ACK) {
        throw new Exceptions.InvalidStateError(this._status);
      }

      var info = new RTCSession_Info(this);
      info.send(contentType, body, options);
    }
    /**
     * Mute
     */

  }, {
    key: "mute",
    value: function mute() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
        audio: true,
        video: false
      };
      debug('mute()');
      var audioMuted = false,
          videoMuted = false;

      if (this._audioMuted === false && options.audio) {
        audioMuted = true;
        this._audioMuted = true;

        this._toggleMuteAudio(true);
      }

      if (this._videoMuted === false && options.video) {
        videoMuted = true;
        this._videoMuted = true;

        this._toggleMuteVideo(true);
      }

      if (audioMuted === true || videoMuted === true) {
        this._onmute({
          audio: audioMuted,
          video: videoMuted
        });
      }
    }
    /**
     * Unmute
     */

  }, {
    key: "unmute",
    value: function unmute() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
        audio: true,
        video: true
      };
      debug('unmute()');
      var audioUnMuted = false,
          videoUnMuted = false;

      if (this._audioMuted === true && options.audio) {
        audioUnMuted = true;
        this._audioMuted = false;

        if (this._localHold === false) {
          this._toggleMuteAudio(false);
        }
      }

      if (this._videoMuted === true && options.video) {
        videoUnMuted = true;
        this._videoMuted = false;

        if (this._localHold === false) {
          this._toggleMuteVideo(false);
        }
      }

      if (audioUnMuted === true || videoUnMuted === true) {
        this._onunmute({
          audio: audioUnMuted,
          video: videoUnMuted
        });
      }
    }
    /**
     * Hold
     */

  }, {
    key: "hold",
    value: function hold() {
      var _this6 = this;

      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var done = arguments.length > 1 ? arguments[1] : undefined;
      debug('hold()');

      if (this._status !== C.STATUS_WAITING_FOR_ACK && this._status !== C.STATUS_CONFIRMED) {
        return false;
      }

      if (this._localHold === true) {
        return false;
      }

      if (!this._isReadyToReOffer()) {
        return false;
      }

      this._localHold = true;

      this._onhold('local');

      var eventHandlers = {
        succeeded: function succeeded() {
          if (done) {
            done();
          }
        },
        failed: function failed() {
          _this6.terminate({
            cause: JsSIP_C.causes.WEBRTC_ERROR,
            status_code: 500,
            reason_phrase: 'Hold Failed'
          });
        }
      };

      if (options.useUpdate) {
        this._sendUpdate({
          sdpOffer: true,
          eventHandlers: eventHandlers,
          extraHeaders: options.extraHeaders
        });
      } else {
        this._sendReinvite({
          eventHandlers: eventHandlers,
          extraHeaders: options.extraHeaders
        });
      }

      return true;
    }
  }, {
    key: "unhold",
    value: function unhold() {
      var _this7 = this;

      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var done = arguments.length > 1 ? arguments[1] : undefined;
      debug('unhold()');

      if (this._status !== C.STATUS_WAITING_FOR_ACK && this._status !== C.STATUS_CONFIRMED) {
        return false;
      }

      if (this._localHold === false) {
        return false;
      }

      if (!this._isReadyToReOffer()) {
        return false;
      }

      this._localHold = false;

      this._onunhold('local');

      var eventHandlers = {
        succeeded: function succeeded() {
          if (done) {
            done();
          }
        },
        failed: function failed() {
          _this7.terminate({
            cause: JsSIP_C.causes.WEBRTC_ERROR,
            status_code: 500,
            reason_phrase: 'Unhold Failed'
          });
        }
      };

      if (options.useUpdate) {
        this._sendUpdate({
          sdpOffer: true,
          eventHandlers: eventHandlers,
          extraHeaders: options.extraHeaders
        });
      } else {
        this._sendReinvite({
          eventHandlers: eventHandlers,
          extraHeaders: options.extraHeaders
        });
      }

      return true;
    }
  }, {
    key: "renegotiate",
    value: function renegotiate() {
      var _this8 = this;

      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var done = arguments.length > 1 ? arguments[1] : undefined;
      debug('renegotiate()');
      var rtcOfferConstraints = options.rtcOfferConstraints || null;

      if (this._status !== C.STATUS_WAITING_FOR_ACK && this._status !== C.STATUS_CONFIRMED) {
        return false;
      }

      if (!this._isReadyToReOffer()) {
        return false;
      }

      var eventHandlers = {
        succeeded: function succeeded() {
          if (done) {
            done();
          }
        },
        failed: function failed() {
          _this8.terminate({
            cause: JsSIP_C.causes.WEBRTC_ERROR,
            status_code: 500,
            reason_phrase: 'Media Renegotiation Failed'
          });
        }
      };

      this._setLocalMediaStatus();

      if (options.useUpdate) {
        this._sendUpdate({
          sdpOffer: true,
          eventHandlers: eventHandlers,
          rtcOfferConstraints: rtcOfferConstraints,
          extraHeaders: options.extraHeaders
        });
      } else {
        this._sendReinvite({
          eventHandlers: eventHandlers,
          rtcOfferConstraints: rtcOfferConstraints,
          extraHeaders: options.extraHeaders
        });
      }

      return true;
    }
    /**
     * Refer
     */

  }, {
    key: "refer",
    value: function refer(target, options) {
      var _this9 = this;

      debug('refer()');
      var originalTarget = target;

      if (this._status !== C.STATUS_WAITING_FOR_ACK && this._status !== C.STATUS_CONFIRMED) {
        return false;
      } // Check target validity.


      target = this._ua.normalizeTarget(target);

      if (!target) {
        throw new TypeError("Invalid target: ".concat(originalTarget));
      }

      var referSubscriber = new RTCSession_ReferSubscriber(this);
      referSubscriber.sendRefer(target, options); // Store in the map.

      var id = referSubscriber.id;
      this._referSubscribers[id] = referSubscriber; // Listen for ending events so we can remove it from the map.

      referSubscriber.on('requestFailed', function () {
        delete _this9._referSubscribers[id];
      });
      referSubscriber.on('accepted', function () {
        delete _this9._referSubscribers[id];
      });
      referSubscriber.on('failed', function () {
        delete _this9._referSubscribers[id];
      });
      return referSubscriber;
    }
    /**
     * Send a generic in-dialog Request
     */

  }, {
    key: "sendRequest",
    value: function sendRequest(method, options) {
      debug('sendRequest()');
      return this._dialog.sendRequest(method, options);
    }
    /**
     * In dialog Request Reception
     */

  }, {
    key: "receiveRequest",
    value: function receiveRequest(request) {
      var _this10 = this;

      debug('receiveRequest()');

      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) {
              return;
            } // Update signaling status.


            this._status = C.STATUS_CONFIRMED;
            clearTimeout(this._timers.ackTimer);
            clearTimeout(this._timers.invite2xxTimer);

            if (this._late_sdp) {
              if (!request.body) {
                this.terminate({
                  cause: JsSIP_C.causes.MISSING_SDP,
                  status_code: 400
                });
                break;
              }

              var e = {
                originator: 'remote',
                type: 'answer',
                sdp: request.body
              };
              debug('emit "sdp"');
              this.emit('sdp', e);
              var answer = new RTCSessionDescription({
                type: 'answer',
                sdp: e.sdp
              });
              this._connectionPromiseQueue = this._connectionPromiseQueue.then(function () {
                return _this10._connection.setRemoteDescription(answer);
              }).then(function () {
                if (!_this10._is_confirmed) {
                  _this10._confirmed('remote', request);
                }
              })["catch"](function (error) {
                _this10.terminate({
                  cause: JsSIP_C.causes.BAD_MEDIA_DESCRIPTION,
                  status_code: 488
                });

                debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);

                _this10.emit('peerconnection:setremotedescriptionfailed', error);
              });
            } else if (!this._is_confirmed) {
              this._confirmed('remote', request);
            }

            break;

          case JsSIP_C.BYE:
            if (this._status === C.STATUS_CONFIRMED || this._status === C.STATUS_WAITING_FOR_ACK) {
              request.reply(200);

              this._ended('remote', request, JsSIP_C.causes.BYE);
            } else if (this._status === C.STATUS_INVITE_RECEIVED) {
              request.reply(200);

              this._request.reply(487, 'BYE Received');

              this._ended('remote', request, JsSIP_C.causes.BYE);
            } else {
              request.reply(403, 'Wrong Status');
            }

            break;

          case JsSIP_C.INVITE:
            if (this._status === C.STATUS_CONFIRMED) {
              if (request.hasHeader('replaces')) {
                this._receiveReplaces(request);
              } else {
                this._receiveReinvite(request);
              }
            } else {
              request.reply(403, 'Wrong Status');
            }

            break;

          case JsSIP_C.INFO:
            if (this._status === C.STATUS_1XX_RECEIVED || this._status === C.STATUS_WAITING_FOR_ANSWER || this._status === C.STATUS_ANSWERED || this._status === C.STATUS_WAITING_FOR_ACK || this._status === C.STATUS_CONFIRMED) {
              var contentType = request.getHeader('content-type');

              if (contentType && contentType.match(/^application\/dtmf-relay/i)) {
                new RTCSession_DTMF(this).init_incoming(request);
              } else if (contentType !== undefined) {
                new RTCSession_Info(this).init_incoming(request);
              } else {
                request.reply(415);
              }
            } else {
              request.reply(403, 'Wrong Status');
            }

            break;

          case JsSIP_C.UPDATE:
            if (this._status === C.STATUS_CONFIRMED) {
              this._receiveUpdate(request);
            } else {
              request.reply(403, 'Wrong Status');
            }

            break;

          case JsSIP_C.REFER:
            if (this._status === C.STATUS_CONFIRMED) {
              this._receiveRefer(request);
            } else {
              request.reply(403, 'Wrong Status');
            }

            break;

          case JsSIP_C.NOTIFY:
            if (this._status === C.STATUS_CONFIRMED) {
              this._receiveNotify(request);
            } else {
              request.reply(403, 'Wrong Status');
            }

            break;

          default:
            request.reply(501);
        }
      }
    }
    /**
     * Session Callbacks
     */

  }, {
    key: "onTransportError",
    value: function onTransportError() {
      debugerror('onTransportError()');

      if (this._status !== C.STATUS_TERMINATED) {
        this.terminate({
          status_code: 500,
          reason_phrase: JsSIP_C.causes.CONNECTION_ERROR,
          cause: JsSIP_C.causes.CONNECTION_ERROR
        });
      }
    }
  }, {
    key: "onRequestTimeout",
    value: function onRequestTimeout() {
      debugerror('onRequestTimeout()');

      if (this._status !== C.STATUS_TERMINATED) {
        this.terminate({
          status_code: 408,
          reason_phrase: JsSIP_C.causes.REQUEST_TIMEOUT,
          cause: JsSIP_C.causes.REQUEST_TIMEOUT
        });
      }
    }
  }, {
    key: "onDialogError",
    value: function onDialogError() {
      debugerror('onDialogError()');

      if (this._status !== C.STATUS_TERMINATED) {
        this.terminate({
          status_code: 500,
          reason_phrase: JsSIP_C.causes.DIALOG_ERROR,
          cause: JsSIP_C.causes.DIALOG_ERROR
        });
      }
    } // Called from DTMF handler.

  }, {
    key: "newDTMF",
    value: function newDTMF(data) {
      debug('newDTMF()');
      this.emit('newDTMF', data);
    } // Called from Info handler.

  }, {
    key: "newInfo",
    value: function newInfo(data) {
      debug('newInfo()');
      this.emit('newInfo', data);
    }
    /**
     * Check if RTCSession is ready for an outgoing re-INVITE or UPDATE with SDP.
     */

  }, {
    key: "_isReadyToReOffer",
    value: function _isReadyToReOffer() {
      if (!this._rtcReady) {
        debug('_isReadyToReOffer() | internal WebRTC status not ready');
        return false;
      } // No established yet.


      if (!this._dialog) {
        debug('_isReadyToReOffer() | session not established yet');
        return false;
      } // Another INVITE transaction is in progress.


      if (this._dialog.uac_pending_reply === true || this._dialog.uas_pending_reply === true) {
        debug('_isReadyToReOffer() | there is another INVITE/UPDATE transaction in progress');
        return false;
      }

      return true;
    }
  }, {
    key: "_close",
    value: function _close() {
      debug('close()');

      if (this._status === C.STATUS_TERMINATED) {
        return;
      }

      this._status = C.STATUS_TERMINATED; // Terminate RTC.

      if (this._connection) {
        try {
          this._connection.close();
        } catch (error) {
          debugerror('close() | error closing the RTCPeerConnection: %o', error);
        }
      } // Close local MediaStream if it was not given by the user.


      if (this._localMediaStream && this._localMediaStreamLocallyGenerated) {
        debug('close() | closing local MediaStream');
        Utils.closeMediaStream(this._localMediaStream);
      } // Terminate signaling.
      // Clear SIP timers.


      for (var timer in this._timers) {
        if (Object.prototype.hasOwnProperty.call(this._timers, timer)) {
          clearTimeout(this._timers[timer]);
        }
      } // Clear Session Timers.


      clearTimeout(this._sessionTimers.timer); // Terminate confirmed dialog.

      if (this._dialog) {
        this._dialog.terminate();

        delete this._dialog;
      } // Terminate early dialogs.


      for (var dialog in this._earlyDialogs) {
        if (Object.prototype.hasOwnProperty.call(this._earlyDialogs, dialog)) {
          this._earlyDialogs[dialog].terminate();

          delete this._earlyDialogs[dialog];
        }
      } // Terminate REFER subscribers.


      for (var subscriber in this._referSubscribers) {
        if (Object.prototype.hasOwnProperty.call(this._referSubscribers, subscriber)) {
          delete this._referSubscribers[subscriber];
        }
      }

      this._ua.destroyRTCSession(this);
    }
    /**
     * Private API.
     */

    /**
     * RFC3261 13.3.1.4
     * Response retransmissions cannot be accomplished by transaction layer
     *  since it is destroyed when receiving the first 2xx answer
     */

  }, {
    key: "_setInvite2xxTimer",
    value: function _setInvite2xxTimer(request, body) {
      var timeout = Timers.T1;

      function invite2xxRetransmission() {
        if (this._status !== C.STATUS_WAITING_FOR_ACK) {
          return;
        }

        request.reply(200, null, ["Contact: ".concat(this._contact)], body);

        if (timeout < Timers.T2) {
          timeout = timeout * 2;

          if (timeout > Timers.T2) {
            timeout = Timers.T2;
          }
        }

        this._timers.invite2xxTimer = setTimeout(invite2xxRetransmission.bind(this), timeout);
      }

      this._timers.invite2xxTimer = setTimeout(invite2xxRetransmission.bind(this), 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.
     */

  }, {
    key: "_setACKTimer",
    value: function _setACKTimer() {
      var _this11 = this;

      this._timers.ackTimer = setTimeout(function () {
        if (_this11._status === C.STATUS_WAITING_FOR_ACK) {
          debug('no ACK received, terminating the session');
          clearTimeout(_this11._timers.invite2xxTimer);

          _this11.sendRequest(JsSIP_C.BYE);

          _this11._ended('remote', null, JsSIP_C.causes.NO_ACK);
        }
      }, Timers.TIMER_H);
    }
  }, {
    key: "_createRTCConnection",
    value: function _createRTCConnection(pcConfig, rtcConstraints) {
      var _this12 = this;

      this._connection = new RTCPeerConnection(pcConfig, rtcConstraints);

      this._connection.addEventListener('iceconnectionstatechange', function () {
        var state = _this12._connection.iceConnectionState; // TODO: Do more with different states.

        if (state === 'failed') {
          _this12.terminate({
            cause: JsSIP_C.causes.RTP_TIMEOUT,
            status_code: 408,
            reason_phrase: JsSIP_C.causes.RTP_TIMEOUT
          });
        }
      });

      debug('emit "peerconnection"');
      this.emit('peerconnection', {
        peerconnection: this._connection
      });
    }
  }, {
    key: "_createLocalDescription",
    value: function _createLocalDescription(type, constraints) {
      var _this13 = this;

      debug('createLocalDescription()');
      if (type !== 'offer' && type !== 'answer') throw new Error("createLocalDescription() | invalid type \"".concat(type, "\""));
      var connection = this._connection;
      this._rtcReady = false;
      return Promise.resolve() // Create Offer or Answer.
      .then(function () {
        if (type === 'offer') {
          return connection.createOffer(constraints)["catch"](function (error) {
            debugerror('emit "peerconnection:createofferfailed" [error:%o]', error);

            _this13.emit('peerconnection:createofferfailed', error);

            return Promise.reject(error);
          });
        } else {
          return connection.createAnswer(constraints)["catch"](function (error) {
            debugerror('emit "peerconnection:createanswerfailed" [error:%o]', error);

            _this13.emit('peerconnection:createanswerfailed', error);

            return Promise.reject(error);
          });
        }
      }) // Set local description.
      .then(function (desc) {
        return connection.setLocalDescription(desc)["catch"](function (error) {
          _this13._rtcReady = true;
          debugerror('emit "peerconnection:setlocaldescriptionfailed" [error:%o]', error);

          _this13.emit('peerconnection:setlocaldescriptionfailed', error);

          return Promise.reject(error);
        });
      }).then(function () {
        // Resolve right away if 'pc.iceGatheringState' is 'complete'.
        if (connection.iceGatheringState === 'complete') {
          _this13._rtcReady = true;
          var e = {
            originator: 'local',
            type: type,
            sdp: connection.localDescription.sdp
          };
          debug('emit "sdp"');

          _this13.emit('sdp', e);

          return Promise.resolve(e.sdp);
        } // Add 'pc.onicencandidate' event handler to resolve on last candidate.


        return new Promise(function (resolve) {
          var finished = false;
          var iceCandidateListener;
          var iceGatheringStateListener;

          var ready = function ready() {
            connection.removeEventListener('icecandidate', iceCandidateListener);
            connection.removeEventListener('icegatheringstatechange', iceGatheringStateListener);


            var sdpbody = connection.localDescription.sdp;
            var sdplines = sdpbody.split("\r\n");
            var sdpcontent = "";
            for (var i = 0; i < sdplines.length; i++) {
              if (sdplines[i].indexOf("a=candidate") > -1 && sdplines[i].split(" ")[4].indexOf(":") > -1) {
                continue;
              } else {
                sdpcontent += sdplines[i] + "\r\n";
              }
            }

            finished = true;
            _this13._rtcReady = true;
            var e = {
              originator: 'local',
              type: type,
              sdp: sdpcontent
            };
            debug('emit "sdp"');
            _this13.emit('sdp', e);

            resolve(e.sdp);
          };

          connection.addEventListener('icecandidate', iceCandidateListener = function iceCandidateListener(event) {
            var candidate = event.candidate;

            if (candidate) {
              _this13.emit('icecandidate', {
                candidate: candidate,
                ready: ready
              });
            } else if (!finished) {
              ready();
            }
          });
          connection.addEventListener('icegatheringstatechange', iceGatheringStateListener = function iceGatheringStateListener() {
            if (connection.iceGatheringState === 'complete' && !finished) {
              ready();
            }
          });
        });
      });
    }
    /**
     * Dialog Management
     */

  }, {
    key: "_createDialog",
    value: function _createDialog(message, type, early) {
      var local_tag = type === 'UAS' ? message.to_tag : message.from_tag;
      var remote_tag = type === 'UAS' ? message.from_tag : message.to_tag;
      var id = message.call_id + local_tag + remote_tag;
      var early_dialog = this._earlyDialogs[id]; // Early Dialog.

      if (early) {
        if (early_dialog) {
          return true;
        } else {
          early_dialog = new Dialog(this, message, type, Dialog.C.STATUS_EARLY); // Dialog has been successfully created.

          if (early_dialog.error) {
            debug(early_dialog.error);

            this._failed('remote', message, JsSIP_C.causes.INTERNAL_ERROR);

            return false;
          } else {
            this._earlyDialogs[id] = early_dialog;
            return true;
          }
        }
      } // Confirmed Dialog.
      else {
          this._from_tag = message.from_tag;
          this._to_tag = message.to_tag; // 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.


          var dialog = new Dialog(this, message, type);

          if (dialog.error) {
            debug(dialog.error);

            this._failed('remote', message, JsSIP_C.causes.INTERNAL_ERROR);

            return false;
          } else {
            this._dialog = dialog;
            return true;
          }
        }
    }
    /**
     * In dialog INVITE Reception
     */

  }, {
    key: "_receiveReinvite",
    value: function _receiveReinvite(request) {
      var _this14 = this;

      debug('receiveReinvite()');
      var contentType = request.getHeader('Content-Type');
      var data = {
        request: request,
        callback: undefined,
        reject: reject.bind(this)
      };
      var rejected = false;

      function reject() {
        var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
        rejected = true;
        var status_code = options.status_code || 403;
        var reason_phrase = options.reason_phrase || '';
        var extraHeaders = Utils.cloneArray(options.extraHeaders);

        if (this._status !== C.STATUS_CONFIRMED) {
          return false;
        }

        if (status_code < 300 || status_code >= 700) {
          throw new TypeError("Invalid status_code: ".concat(status_code));
        }

        request.reply(status_code, reason_phrase, extraHeaders);
      } // Emit 'reinvite'.


      this.emit('reinvite', data);

      if (rejected) {
        return;
      }

      this._late_sdp = false; // Request without SDP.

      if (!request.body) {
        this._late_sdp = true;

        if (this._remoteHold) {
          this._remoteHold = false;

          this._onunhold('remote');
        }

        this._connectionPromiseQueue = this._connectionPromiseQueue.then(function () {
          return _this14._createLocalDescription('offer', _this14._rtcOfferConstraints);
        }).then(function (sdp) {
          sendAnswer.call(_this14, sdp);
        })["catch"](function () {
          request.reply(500);
        });
        return;
      } // Request with SDP.


      if (contentType !== 'application/sdp') {
        debug('invalid Content-Type');
        request.reply(415);
        return;
      }

      this._processInDialogSdpOffer(request) // Send answer.
      .then(function (desc) {
        if (_this14._status === C.STATUS_TERMINATED) {
          return;
        }

        sendAnswer.call(_this14, desc);
      })["catch"](function (error) {
        debugerror(error);
      });

      function sendAnswer(desc) {
        var _this15 = this;

        var extraHeaders = ["Contact: ".concat(this._contact)];

        this._handleSessionTimersInIncomingRequest(request, extraHeaders);

        if (this._late_sdp) {
          desc = this._mangleOffer(desc);
        }

        request.reply(200, null, extraHeaders, desc, function () {
          _this15._status = C.STATUS_WAITING_FOR_ACK;

          _this15._setInvite2xxTimer(request, desc);

          _this15._setACKTimer();
        }); // If callback is given execute it.

        if (typeof data.callback === 'function') {
          data.callback();
        }
      }
    }
    /**
     * In dialog UPDATE Reception
     */

  }, {
    key: "_receiveUpdate",
    value: function _receiveUpdate(request) {
      var _this16 = this;

      debug('receiveUpdate()');
      var contentType = request.getHeader('Content-Type');
      var data = {
        request: request,
        callback: undefined,
        reject: reject.bind(this)
      };
      var rejected = false;

      function reject() {
        var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
        rejected = true;
        var status_code = options.status_code || 403;
        var reason_phrase = options.reason_phrase || '';
        var extraHeaders = Utils.cloneArray(options.extraHeaders);

        if (this._status !== C.STATUS_CONFIRMED) {
          return false;
        }

        if (status_code < 300 || status_code >= 700) {
          throw new TypeError("Invalid status_code: ".concat(status_code));
        }

        request.reply(status_code, reason_phrase, extraHeaders);
      } // Emit 'update'.


      this.emit('update', data);

      if (rejected) {
        return;
      }

      if (!request.body) {
        sendAnswer.call(this, null);
        return;
      }

      if (contentType !== 'application/sdp') {
        debug('invalid Content-Type');
        request.reply(415);
        return;
      }

      this._processInDialogSdpOffer(request) // Send answer.
      .then(function (desc) {
        if (_this16._status === C.STATUS_TERMINATED) {
          return;
        }

        sendAnswer.call(_this16, desc);
      })["catch"](function (error) {
        debugerror(error);
      });

      function sendAnswer(desc) {
        var extraHeaders = ["Contact: ".concat(this._contact)];

        this._handleSessionTimersInIncomingRequest(request, extraHeaders);

        request.reply(200, null, extraHeaders, desc); // If callback is given execute it.

        if (typeof data.callback === 'function') {
          data.callback();
        }
      }
    }
  }, {
    key: "_processInDialogSdpOffer",
    value: function _processInDialogSdpOffer(request) {
      var _this17 = this;

      debug('_processInDialogSdpOffer()');
      var sdp = request.parseSDP();
      var hold = false;

      var _iterator4 = _createForOfIteratorHelper(sdp.media),
          _step4;

      try {
        for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
          var m = _step4.value;

          if (holdMediaTypes.indexOf(m.type) === -1) {
            continue;
          }

          var direction = m.direction || sdp.direction || 'sendrecv';

          if (direction === 'sendonly' || direction === 'inactive') {
            hold = true;
          } // If at least one of the streams is active don't emit 'hold'.
          else {
              hold = false;
              break;
            }
        }
      } catch (err) {
        _iterator4.e(err);
      } finally {
        _iterator4.f();
      }

      var e = {
        originator: 'remote',
        type: 'offer',
        sdp: request.body
      };
      debug('emit "sdp"');
      this.emit('sdp', e);
      var offer = new RTCSessionDescription({
        type: 'offer',
        sdp: e.sdp
      });
      this._connectionPromiseQueue = this._connectionPromiseQueue // Set remote description.
      .then(function () {
        if (_this17._status === C.STATUS_TERMINATED) {
          throw new Error('terminated');
        }

        return _this17._connection.setRemoteDescription(offer)["catch"](function (error) {
          request.reply(488);
          debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);

          _this17.emit('peerconnection:setremotedescriptionfailed', error);

          throw new Error('peerconnection.setRemoteDescription() failed');
        });
      }).then(function () {
        if (_this17._status === C.STATUS_TERMINATED) {
          throw new Error('terminated');
        }

        if (_this17._remoteHold === true && hold === false) {
          _this17._remoteHold = false;

          _this17._onunhold('remote');
        } else if (_this17._remoteHold === false && hold === true) {
          _this17._remoteHold = true;

          _this17._onhold('remote');
        }
      }) // Create local description.
      .then(function () {
        if (_this17._status === C.STATUS_TERMINATED) {
          throw new Error('terminated');
        }

        return _this17._createLocalDescription('answer', _this17._rtcAnswerConstraints)["catch"](function () {
          request.reply(500);
          throw new Error('_createLocalDescription() failed');
        });
      });
      return this._connectionPromiseQueue;
    }
    /**
     * In dialog Refer Reception
     */

  }, {
    key: "_receiveRefer",
    value: function _receiveRefer(request) {
      var _this18 = this;

      debug('receiveRefer()');

      if (!request.refer_to) {
        debug('no Refer-To header field present in REFER');
        request.reply(400);
        return;
      }

      if (request.refer_to.uri.scheme !== JsSIP_C.SIP) {
        debug('Refer-To header field points to a non-SIP URI scheme');
        request.reply(416);
        return;
      } // Reply before the transaction timer expires.


      request.reply(202);
      var notifier = new RTCSession_ReferNotifier(this, request.cseq);
      debug('emit "refer"'); // Emit 'refer'.

      this.emit('refer', {
        request: request,
        accept: function accept(initCallback, options) {
          _accept.call(_this18, initCallback, options);
        },
        reject: function reject() {
          _reject.call(_this18);
        }
      });

      function _accept(initCallback) {
        var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
        initCallback = typeof initCallback === 'function' ? initCallback : null;

        if (this._status !== C.STATUS_WAITING_FOR_ACK && this._status !== C.STATUS_CONFIRMED) {
          return false;
        }

        var session = new RTCSession(this._ua);
        session.on('progress', function (_ref2) {
          var response = _ref2.response;
          notifier.notify(response.status_code, response.reason_phrase);
        });
        session.on('accepted', function (_ref3) {
          var response = _ref3.response;
          notifier.notify(response.status_code, response.reason_phrase);
        });
        session.on('_failed', function (_ref4) {
          var message = _ref4.message,
              cause = _ref4.cause;

          if (message) {
            notifier.notify(message.status_code, message.reason_phrase);
          } else {
            notifier.notify(487, cause);
          }
        }); // Consider the Replaces header present in the Refer-To URI.

        if (request.refer_to.uri.hasHeader('replaces')) {
          var replaces = decodeURIComponent(request.refer_to.uri.getHeader('replaces'));
          options.extraHeaders = Utils.cloneArray(options.extraHeaders);
          options.extraHeaders.push("Replaces: ".concat(replaces));
        }

        session.connect(request.refer_to.uri.toAor(), options, initCallback);
      }

      function _reject() {
        notifier.notify(603);
      }
    }
    /**
     * In dialog Notify Reception
     */

  }, {
    key: "_receiveNotify",
    value: function _receiveNotify(request) {
      debug('receiveNotify()');

      if (!request.event) {
        request.reply(400);
      }

      switch (request.event.event) {
        case 'refer':
          {
            var id;
            var referSubscriber;

            if (request.event.params && request.event.params.id) {
              id = request.event.params.id;
              referSubscriber = this._referSubscribers[id];
            } else if (Object.keys(this._referSubscribers).length === 1) {
              referSubscriber = this._referSubscribers[Object.keys(this._referSubscribers)[0]];
            } else {
              request.reply(400, 'Missing event id parameter');
              return;
            }

            if (!referSubscriber) {
              request.reply(481, 'Subscription does not exist');
              return;
            }

            referSubscriber.receiveNotify(request);
            request.reply(200);
            break;
          }

        default:
          {
            request.reply(489);
          }
      }
    }
    /**
     * INVITE with Replaces Reception
     */

  }, {
    key: "_receiveReplaces",
    value: function _receiveReplaces(request) {
      var _this20 = this;

      debug('receiveReplaces()');

      function _accept2(initCallback) {
        var _this19 = this;

        if (this._status !== C.STATUS_WAITING_FOR_ACK && this._status !== C.STATUS_CONFIRMED) {
          return false;
        }

        var session = new RTCSession(this._ua); // Terminate the current session when the new one is confirmed.

        session.on('confirmed', function () {
          _this19.terminate();
        });
        session.init_incoming(request, initCallback);
      }

      function _reject2() {
        debug('Replaced INVITE rejected by the user');
        request.reply(486);
      } // Emit 'replace'.


      this.emit('replaces', {
        request: request,
        accept: function accept(initCallback) {
          _accept2.call(_this20, initCallback);
        },
        reject: function reject() {
          _reject2.call(_this20);
        }
      });
    }
    /**
     * Initial Request Sender
     */

  }, {
    key: "_sendInitialRequest",
    value: function _sendInitialRequest(mediaConstraints, rtcOfferConstraints, mediaStream) {
      var _this21 = this;

      var request_sender = new RequestSender(this._ua, this._request, {
        onRequestTimeout: function onRequestTimeout() {
          _this21.onRequestTimeout();
        },
        onTransportError: function onTransportError() {
          _this21.onTransportError();
        },
        // Update the request on authentication.
        onAuthenticated: function onAuthenticated(request) {
          _this21._request = request;
        },
        onReceiveResponse: function onReceiveResponse(response) {
          _this21._receiveInviteResponse(response);
        }
      }); // This Promise is resolved within the next iteration, so the app has now
      // a chance to set events such as 'peerconnection' and 'connecting'.

      Promise.resolve() // Get a stream if required.
      .then(function () {
        // A stream is given, let the app set events such as 'peerconnection' and 'connecting'.
        if (mediaStream) {
          return mediaStream;
        } // Request for user media access.
        else if (mediaConstraints.audio || mediaConstraints.video) {
            _this21._localMediaStreamLocallyGenerated = true;
            return navigator.mediaDevices.getUserMedia(mediaConstraints)["catch"](function (error) {
              if (_this21._status === C.STATUS_TERMINATED) {
                throw new Error('terminated');
              }

              _this21._failed('local', null, JsSIP_C.causes.USER_DENIED_MEDIA_ACCESS);

              debugerror('emit "getusermediafailed" [error:%o]', error);

              _this21.emit('getusermediafailed', error);

              throw error;
            });
          }
      }).then(function (stream) {
        if (_this21._status === C.STATUS_TERMINATED) {
          throw new Error('terminated');
        }

        _this21._localMediaStream = stream;

        if (stream) {
          stream.getTracks().forEach(function (track) {
            _this21._connection.addTrack(track, stream);
          });
        } // TODO: should this be triggered here?


        _this21._connecting(_this21._request);

        return _this21._createLocalDescription('offer', rtcOfferConstraints)["catch"](function (error) {
          _this21._failed('local', null, JsSIP_C.causes.WEBRTC_ERROR);

          throw error;
        });
      }).then(function (desc) {
        if (_this21._is_canceled || _this21._status === C.STATUS_TERMINATED) {
          throw new Error('terminated');
        }

        _this21._request.body = desc;
        _this21._status = C.STATUS_INVITE_SENT;
        debug('emit "sending" [request:%o]', _this21._request); // Emit 'sending' so the app can mangle the body before the request is sent.

        _this21.emit('sending', {
          request: _this21._request
        });

        request_sender.send();
      })["catch"](function (error) {
        if (_this21._status === C.STATUS_TERMINATED) {
          return;
        }

        debugerror(error);
      });
    }
    /**
     * Reception of Response for Initial INVITE
     */

  }, {
    key: "_receiveInviteResponse",
    value: function _receiveInviteResponse(response) {
      var _this22 = this;

      debug('receiveInviteResponse()'); // 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 {
            var dialog = new Dialog(this, response, 'UAC');

            if (dialog.error !== undefined) {
              debug(dialog.error);
              return;
            }

            this.sendRequest(JsSIP_C.ACK);
            this.sendRequest(JsSIP_C.BYE);
            return;
          }
      } // Proceed to cancellation if the user requested.


      if (this._is_canceled) {
        if (response.status_code >= 100 && response.status_code < 200) {
          this._request.cancel(this._cancel_reason);
        } else if (response.status_code >= 200 && response.status_code < 299) {
          this._acceptAndTerminate(response);
        }

        return;
      }

      if (this._status !== C.STATUS_INVITE_SENT && this._status !== C.STATUS_1XX_RECEIVED) {
        return;
      }

      switch (true) {
        case /^100$/.test(response.status_code):
          this._status = C.STATUS_1XX_RECEIVED;
          break;

        case /^1[0-9]{2}$/.test(response.status_code):
          {
            // Do nothing with 1xx responses without To tag.
            if (!response.to_tag) {
              debug('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;
              }
            }

            this._status = C.STATUS_1XX_RECEIVED;

            this._progress('remote', response);

            if (!response.body) {
              break;
            }

            var e = {
              originator: 'remote',
              type: 'answer',
              sdp: response.body
            };
            debug('emit "sdp"');
            this.emit('sdp', e);
            var answer = new RTCSessionDescription({
              type: 'answer',
              sdp: e.sdp
            });
            this._connectionPromiseQueue = this._connectionPromiseQueue.then(function () {
              return _this22._connection.setRemoteDescription(answer);
            })["catch"](function (error) {
              debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);

              _this22.emit('peerconnection:setremotedescriptionfailed', error);
            });
            break;
          }

        case /^2[0-9]{2}$/.test(response.status_code):
          {
            this._status = C.STATUS_CONFIRMED;

            if (!response.body) {
              this._acceptAndTerminate(response, 400, JsSIP_C.causes.MISSING_SDP);

              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;
            }

            var _e = {
              originator: 'remote',
              type: 'answer',
              sdp: response.body
            };
            debug('emit "sdp"');
            this.emit('sdp', _e);

            var _answer = new RTCSessionDescription({
              type: 'answer',
              sdp: _e.sdp
            });

            this._connectionPromiseQueue = this._connectionPromiseQueue.then(function () {
              // Be ready for 200 with SDP after a 180/183 with SDP.
              // We created a SDP 'answer' for it, so check the current signaling state.
              if (_this22._connection.signalingState === 'stable') {
                return _this22._connection.createOffer(_this22._rtcOfferConstraints).then(function (offer) {
                  return _this22._connection.setLocalDescription(offer);
                })["catch"](function (error) {
                  _this22._acceptAndTerminate(response, 500, error.toString());

                  _this22._failed('local', response, JsSIP_C.causes.WEBRTC_ERROR);
                });
              }
            }).then(function () {
              _this22._connection.setRemoteDescription(_answer).then(function () {
                // Handle Session Timers.
                _this22._handleSessionTimersInIncomingResponse(response);

                _this22._accepted('remote', response);

                _this22.sendRequest(JsSIP_C.ACK);

                _this22._confirmed('local', null);
              })["catch"](function (error) {
                _this22._acceptAndTerminate(response, 488, 'Not Acceptable Here');

                _this22._failed('remote', response, JsSIP_C.causes.BAD_MEDIA_DESCRIPTION);

                debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);

                _this22.emit('peerconnection:setremotedescriptionfailed', error);
              });
            });
            break;
          }

        default:
          {
            var cause = Utils.sipErrorCause(response.status_code);

            this._failed('remote', response, cause);
          }
      }
    }
    /**
     * Send Re-INVITE
     */

  }, {
    key: "_sendReinvite",
    value: function _sendReinvite() {
      var _this23 = this;

      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      debug('sendReinvite()');
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var eventHandlers = Utils.cloneObject(options.eventHandlers);
      var rtcOfferConstraints = options.rtcOfferConstraints || this._rtcOfferConstraints || null;
      var succeeded = false;
      extraHeaders.push("Contact: ".concat(this._contact));
      extraHeaders.push('Content-Type: application/sdp'); // Session Timers.

      if (this._sessionTimers.running) {
        extraHeaders.push("Session-Expires: ".concat(this._sessionTimers.currentExpires, ";refresher=").concat(this._sessionTimers.refresher ? 'uac' : 'uas'));
      }

      this._connectionPromiseQueue = this._connectionPromiseQueue.then(function () {
        return _this23._createLocalDescription('offer', rtcOfferConstraints);
      }).then(function (sdp) {
        sdp = _this23._mangleOffer(sdp);
        var e = {
          originator: 'local',
          type: 'offer',
          sdp: sdp
        };
        debug('emit "sdp"');

        _this23.emit('sdp', e);

        _this23.sendRequest(JsSIP_C.INVITE, {
          extraHeaders: extraHeaders,
          body: sdp,
          eventHandlers: {
            onSuccessResponse: function onSuccessResponse(response) {
              onSucceeded.call(_this23, response);
              succeeded = true;
            },
            onErrorResponse: function onErrorResponse(response) {
              onFailed.call(_this23, response);
            },
            onTransportError: function onTransportError() {
              _this23.onTransportError(); // Do nothing because session ends.

            },
            onRequestTimeout: function onRequestTimeout() {
              _this23.onRequestTimeout(); // Do nothing because session ends.

            },
            onDialogError: function onDialogError() {
              _this23.onDialogError(); // Do nothing because session ends.

            }
          }
        });
      })["catch"](function () {
        onFailed();
      });

      function onSucceeded(response) {
        var _this24 = this;

        if (this._status === C.STATUS_TERMINATED) {
          return;
        }

        this.sendRequest(JsSIP_C.ACK); // If it is a 2XX retransmission exit now.

        if (succeeded) {
          return;
        } // Handle Session Timers.


        this._handleSessionTimersInIncomingResponse(response); // Must have SDP answer.


        if (!response.body) {
          onFailed.call(this);
          return;
        } else if (response.getHeader('Content-Type') !== 'application/sdp') {
          onFailed.call(this);
          return;
        }

        var e = {
          originator: 'remote',
          type: 'answer',
          sdp: response.body
        };
        debug('emit "sdp"');
        this.emit('sdp', e);
        var answer = new RTCSessionDescription({
          type: 'answer',
          sdp: e.sdp
        });
        this._connectionPromiseQueue = this._connectionPromiseQueue.then(function () {
          return _this24._connection.setRemoteDescription(answer);
        }).then(function () {
          if (eventHandlers.succeeded) {
            eventHandlers.succeeded(response);
          }
        })["catch"](function (error) {
          onFailed.call(_this24);
          debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);

          _this24.emit('peerconnection:setremotedescriptionfailed', error);
        });
      }

      function onFailed(response) {
        if (eventHandlers.failed) {
          eventHandlers.failed(response);
        }
      }
    }
    /**
     * Send UPDATE
     */

  }, {
    key: "_sendUpdate",
    value: function _sendUpdate() {
      var _this25 = this;

      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      debug('sendUpdate()');
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var eventHandlers = Utils.cloneObject(options.eventHandlers);
      var rtcOfferConstraints = options.rtcOfferConstraints || this._rtcOfferConstraints || null;
      var sdpOffer = options.sdpOffer || false;
      var succeeded = false;
      extraHeaders.push("Contact: ".concat(this._contact)); // Session Timers.

      if (this._sessionTimers.running) {
        extraHeaders.push("Session-Expires: ".concat(this._sessionTimers.currentExpires, ";refresher=").concat(this._sessionTimers.refresher ? 'uac' : 'uas'));
      }

      if (sdpOffer) {
        extraHeaders.push('Content-Type: application/sdp');
        this._connectionPromiseQueue = this._connectionPromiseQueue.then(function () {
          return _this25._createLocalDescription('offer', rtcOfferConstraints);
        }).then(function (sdp) {
          sdp = _this25._mangleOffer(sdp);
          var e = {
            originator: 'local',
            type: 'offer',
            sdp: sdp
          };
          debug('emit "sdp"');

          _this25.emit('sdp', e);

          _this25.sendRequest(JsSIP_C.UPDATE, {
            extraHeaders: extraHeaders,
            body: sdp,
            eventHandlers: {
              onSuccessResponse: function onSuccessResponse(response) {
                onSucceeded.call(_this25, response);
                succeeded = true;
              },
              onErrorResponse: function onErrorResponse(response) {
                onFailed.call(_this25, response);
              },
              onTransportError: function onTransportError() {
                _this25.onTransportError(); // Do nothing because session ends.

              },
              onRequestTimeout: function onRequestTimeout() {
                _this25.onRequestTimeout(); // Do nothing because session ends.

              },
              onDialogError: function onDialogError() {
                _this25.onDialogError(); // Do nothing because session ends.

              }
            }
          });
        })["catch"](function () {
          onFailed.call(_this25);
        });
      } // No SDP.
      else {
          this.sendRequest(JsSIP_C.UPDATE, {
            extraHeaders: extraHeaders,
            eventHandlers: {
              onSuccessResponse: function onSuccessResponse(response) {
                onSucceeded.call(_this25, response);
              },
              onErrorResponse: function onErrorResponse(response) {
                onFailed.call(_this25, response);
              },
              onTransportError: function onTransportError() {
                _this25.onTransportError(); // Do nothing because session ends.

              },
              onRequestTimeout: function onRequestTimeout() {
                _this25.onRequestTimeout(); // Do nothing because session ends.

              },
              onDialogError: function onDialogError() {
                _this25.onDialogError(); // Do nothing because session ends.

              }
            }
          });
        }

      function onSucceeded(response) {
        var _this26 = this;

        if (this._status === C.STATUS_TERMINATED) {
          return;
        } // If it is a 2XX retransmission exit now.


        if (succeeded) {
          return;
        } // Handle Session Timers.


        this._handleSessionTimersInIncomingResponse(response); // Must have SDP answer.


        if (sdpOffer) {
          if (!response.body) {
            onFailed.call(this);
            return;
          } else if (response.getHeader('Content-Type') !== 'application/sdp') {
            onFailed.call(this);
            return;
          }

          var e = {
            originator: 'remote',
            type: 'answer',
            sdp: response.body
          };
          debug('emit "sdp"');
          this.emit('sdp', e);
          var answer = new RTCSessionDescription({
            type: 'answer',
            sdp: e.sdp
          });
          this._connectionPromiseQueue = this._connectionPromiseQueue.then(function () {
            return _this26._connection.setRemoteDescription(answer);
          }).then(function () {
            if (eventHandlers.succeeded) {
              eventHandlers.succeeded(response);
            }
          })["catch"](function (error) {
            onFailed.call(_this26);
            debugerror('emit "peerconnection:setremotedescriptionfailed" [error:%o]', error);

            _this26.emit('peerconnection:setremotedescriptionfailed', error);
          });
        } // No SDP answer.
        else if (eventHandlers.succeeded) {
            eventHandlers.succeeded(response);
          }
      }

      function onFailed(response) {
        if (eventHandlers.failed) {
          eventHandlers.failed(response);
        }
      }
    }
  }, {
    key: "_acceptAndTerminate",
    value: function _acceptAndTerminate(response, status_code, reason_phrase) {
      debug('acceptAndTerminate()');
      var extraHeaders = [];

      if (status_code) {
        reason_phrase = reason_phrase || JsSIP_C.REASON_PHRASE[status_code] || '';
        extraHeaders.push("Reason: SIP ;cause=".concat(status_code, "; text=\"").concat(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
        });
      } // Update session status.


      this._status = C.STATUS_TERMINATED;
    }
    /**
     * Correctly set the SDP direction attributes if the call is on local hold
     */

  }, {
    key: "_mangleOffer",
    value: function _mangleOffer(sdp) {
      if (!this._localHold && !this._remoteHold) {
        return sdp;
      }

      sdp = sdp_transform.parse(sdp); // Local hold.

      if (this._localHold && !this._remoteHold) {
        debug('mangleOffer() | me on hold, mangling offer');

        var _iterator5 = _createForOfIteratorHelper(sdp.media),
            _step5;

        try {
          for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
            var m = _step5.value;

            if (holdMediaTypes.indexOf(m.type) === -1) {
              continue;
            }

            if (!m.direction) {
              m.direction = 'sendonly';
            } else if (m.direction === 'sendrecv') {
              m.direction = 'sendonly';
            } else if (m.direction === 'recvonly') {
              m.direction = 'inactive';
            }
          }
        } catch (err) {
          _iterator5.e(err);
        } finally {
          _iterator5.f();
        }
      } // Local and remote hold.
      else if (this._localHold && this._remoteHold) {
          debug('mangleOffer() | both on hold, mangling offer');

          var _iterator6 = _createForOfIteratorHelper(sdp.media),
              _step6;

          try {
            for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
              var _m = _step6.value;

              if (holdMediaTypes.indexOf(_m.type) === -1) {
                continue;
              }

              _m.direction = 'inactive';
            }
          } catch (err) {
            _iterator6.e(err);
          } finally {
            _iterator6.f();
          }
        } // Remote hold.
        else if (this._remoteHold) {
            debug('mangleOffer() | remote on hold, mangling offer');

            var _iterator7 = _createForOfIteratorHelper(sdp.media),
                _step7;

            try {
              for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
                var _m2 = _step7.value;

                if (holdMediaTypes.indexOf(_m2.type) === -1) {
                  continue;
                }

                if (!_m2.direction) {
                  _m2.direction = 'recvonly';
                } else if (_m2.direction === 'sendrecv') {
                  _m2.direction = 'recvonly';
                } else if (_m2.direction === 'recvonly') {
                  _m2.direction = 'inactive';
                }
              }
            } catch (err) {
              _iterator7.e(err);
            } finally {
              _iterator7.f();
            }
          }

      return sdp_transform.write(sdp);
    }
  }, {
    key: "_setLocalMediaStatus",
    value: function _setLocalMediaStatus() {
      var enableAudio = true,
          enableVideo = true;

      if (this._localHold || this._remoteHold) {
        enableAudio = false;
        enableVideo = false;
      }

      if (this._audioMuted) {
        enableAudio = false;
      }

      if (this._videoMuted) {
        enableVideo = false;
      }

      this._toggleMuteAudio(!enableAudio);

      this._toggleMuteVideo(!enableVideo);
    }
    /**
     * Handle SessionTimers for an incoming INVITE or UPDATE.
     * @param  {IncomingRequest} request
     * @param  {Array} responseExtraHeaders  Extra headers for the 200 response.
     */

  }, {
    key: "_handleSessionTimersInIncomingRequest",
    value: function _handleSessionTimersInIncomingRequest(request, responseExtraHeaders) {
      if (!this._sessionTimers.enabled) {
        return;
      }

      var session_expires_refresher;

      if (request.session_expires && request.session_expires >= JsSIP_C.MIN_SESSION_EXPIRES) {
        this._sessionTimers.currentExpires = request.session_expires;
        session_expires_refresher = request.session_expires_refresher || 'uas';
      } else {
        this._sessionTimers.currentExpires = this._sessionTimers.defaultExpires;
        session_expires_refresher = 'uas';
      }

      responseExtraHeaders.push("Session-Expires: ".concat(this._sessionTimers.currentExpires, ";refresher=").concat(session_expires_refresher));
      this._sessionTimers.refresher = session_expires_refresher === 'uas';

      this._runSessionTimer();
    }
    /**
     * Handle SessionTimers for an incoming response to INVITE or UPDATE.
     * @param  {IncomingResponse} response
     */

  }, {
    key: "_handleSessionTimersInIncomingResponse",
    value: function _handleSessionTimersInIncomingResponse(response) {
      if (!this._sessionTimers.enabled) {
        return;
      }

      var session_expires_refresher;

      if (response.session_expires && response.session_expires >= JsSIP_C.MIN_SESSION_EXPIRES) {
        this._sessionTimers.currentExpires = response.session_expires;
        session_expires_refresher = response.session_expires_refresher || 'uac';
      } else {
        this._sessionTimers.currentExpires = this._sessionTimers.defaultExpires;
        session_expires_refresher = 'uac';
      }

      this._sessionTimers.refresher = session_expires_refresher === 'uac';

      this._runSessionTimer();
    }
  }, {
    key: "_runSessionTimer",
    value: function _runSessionTimer() {
      var _this27 = this;

      var expires = this._sessionTimers.currentExpires;
      this._sessionTimers.running = true;
      clearTimeout(this._sessionTimers.timer); // I'm the refresher.

      if (this._sessionTimers.refresher) {
        this._sessionTimers.timer = setTimeout(function () {
          if (_this27._status === C.STATUS_TERMINATED) {
            return;
          }

          debug('runSessionTimer() | sending session refresh request');

          if (_this27._sessionTimers.refreshMethod === JsSIP_C.UPDATE) {
            _this27._sendUpdate();
          } else {
            _this27._sendReinvite();
          }
        }, expires * 500); // Half the given interval (as the RFC states).
      } // I'm not the refresher.
      else {
          this._sessionTimers.timer = setTimeout(function () {
            if (_this27._status === C.STATUS_TERMINATED) {
              return;
            }

            debugerror('runSessionTimer() | timer expired, terminating the session');

            _this27.terminate({
              cause: JsSIP_C.causes.REQUEST_TIMEOUT,
              status_code: 408,
              reason_phrase: 'Session Timer Expired'
            });
          }, expires * 1100);
        }
    }
  }, {
    key: "_toggleMuteAudio",
    value: function _toggleMuteAudio(mute) {
      var senders = this._connection.getSenders().filter(function (sender) {
        return sender.track && sender.track.kind === 'audio';
      });

      var _iterator8 = _createForOfIteratorHelper(senders),
          _step8;

      try {
        for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
          var sender = _step8.value;
          sender.track.enabled = !mute;
        }
      } catch (err) {
        _iterator8.e(err);
      } finally {
        _iterator8.f();
      }
    }
  }, {
    key: "_toggleMuteVideo",
    value: function _toggleMuteVideo(mute) {
      var senders = this._connection.getSenders().filter(function (sender) {
        return sender.track && sender.track.kind === 'video';
      });

      var _iterator9 = _createForOfIteratorHelper(senders),
          _step9;

      try {
        for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
          var sender = _step9.value;
          sender.track.enabled = !mute;
        }
      } catch (err) {
        _iterator9.e(err);
      } finally {
        _iterator9.f();
      }
    }
  }, {
    key: "_newRTCSession",
    value: function _newRTCSession(originator, request) {
      debug('newRTCSession()');

      this._ua.newRTCSession(this, {
        originator: originator,
        session: this,
        request: request
      });
    }
  }, {
    key: "_connecting",
    value: function _connecting(request) {
      debug('session connecting');
      debug('emit "connecting"');
      this.emit('connecting', {
        request: request
      });
    }
  }, {
    key: "_progress",
    value: function _progress(originator, response) {
      debug('session progress');
      debug('emit "progress"');
      this.emit('progress', {
        originator: originator,
        response: response || null
      });
    }
  }, {
    key: "_accepted",
    value: function _accepted(originator, message) {
      debug('session accepted');
      this._start_time = new Date();
      debug('emit "accepted"');
      this.emit('accepted', {
        originator: originator,
        response: message || null
      });
    }
  }, {
    key: "_confirmed",
    value: function _confirmed(originator, ack) {
      debug('session confirmed');
      this._is_confirmed = true;
      debug('emit "confirmed"');
      this.emit('confirmed', {
        originator: originator,
        ack: ack || null
      });
    }
  }, {
    key: "_ended",
    value: function _ended(originator, message, cause) {
      debug('session ended');
      this._end_time = new Date();

      this._close();

      debug('emit "ended"');
      this.emit('ended', {
        originator: originator,
        message: message || null,
        cause: cause
      });
    }
  }, {
    key: "_failed",
    value: function _failed(originator, message, cause) {
      debug('session failed'); // Emit private '_failed' event first.

      debug('emit "_failed"');
      this.emit('_failed', {
        originator: originator,
        message: message || null,
        cause: cause
      });

      this._close();

      debug('emit "failed"');
      this.emit('failed', {
        originator: originator,
        message: message || null,
        cause: cause
      });
    }
  }, {
    key: "_onhold",
    value: function _onhold(originator) {
      debug('session onhold');

      this._setLocalMediaStatus();

      debug('emit "hold"');
      this.emit('hold', {
        originator: originator
      });
    }
  }, {
    key: "_onunhold",
    value: function _onunhold(originator) {
      debug('session onunhold');

      this._setLocalMediaStatus();

      debug('emit "unhold"');
      this.emit('unhold', {
        originator: originator
      });
    }
  }, {
    key: "_onmute",
    value: function _onmute(_ref5) {
      var audio = _ref5.audio,
          video = _ref5.video;
      debug('session onmute');

      this._setLocalMediaStatus();

      debug('emit "muted"');
      this.emit('muted', {
        audio: audio,
        video: video
      });
    }
  }, {
    key: "_onunmute",
    value: function _onunmute(_ref6) {
      var audio = _ref6.audio,
          video = _ref6.video;
      debug('session onunmute');

      this._setLocalMediaStatus();

      debug('emit "unmuted"');
      this.emit('unmuted', {
        audio: audio,
        video: video
      });
    }
  }, {
    key: "C",
    get: function get() {
      return C;
    } // Expose session failed/ended causes as a property of the RTCSession instance.

  }, {
    key: "causes",
    get: function get() {
      return JsSIP_C.causes;
    }
  }, {
    key: "id",
    get: function get() {
      return this._id;
    }
  }, {
    key: "connection",
    get: function get() {
      return this._connection;
    }
  }, {
    key: "contact",
    get: function get() {
      return this._contact;
    }
  }, {
    key: "direction",
    get: function get() {
      return this._direction;
    }
  }, {
    key: "local_identity",
    get: function get() {
      return this._local_identity;
    }
  }, {
    key: "remote_identity",
    get: function get() {
      return this._remote_identity;
    }
  }, {
    key: "start_time",
    get: function get() {
      return this._start_time;
    }
  }, {
    key: "end_time",
    get: function get() {
      return this._end_time;
    }
  }, {
    key: "data",
    get: function get() {
      return this._data;
    },
    set: function set(_data) {
      this._data = _data;
    }
  }, {
    key: "status",
    get: function get() {
      return this._status;
    }
  }]);

  return RTCSession;
}(EventEmitter);
},{"./Constants":2,"./Dialog":3,"./Exceptions":6,"./RTCSession/DTMF":13,"./RTCSession/Info":14,"./RTCSession/ReferNotifier":15,"./RTCSession/ReferSubscriber":16,"./RequestSender":18,"./SIPMessage":19,"./Timers":21,"./Transactions":22,"./URI":25,"./Utils":26,"debug":30,"events":29,"sdp-transform":35}],13:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

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

var JsSIP_C = require('../Constants');

var Exceptions = require('../Exceptions');

var Utils = require('../Utils');

var debug = require('debug')('JsSIP:RTCSession:DTMF');

var debugerror = require('debug')('JsSIP:ERROR:RTCSession:DTMF');

debugerror.log = console.warn.bind(console);
var C = {
  MIN_DURATION: 70,
  MAX_DURATION: 6000,
  DEFAULT_DURATION: 100,
  MIN_INTER_TONE_GAP: 50,
  DEFAULT_INTER_TONE_GAP: 500
};

module.exports = /*#__PURE__*/function (_EventEmitter) {
  _inherits(DTMF, _EventEmitter);

  var _super = _createSuper(DTMF);

  function DTMF(session) {
    var _this;

    _classCallCheck(this, DTMF);

    _this = _super.call(this);
    _this._session = session;
    _this._direction = null;
    _this._tone = null;
    _this._duration = null;
    _this._request = null;
    return _this;
  }

  _createClass(DTMF, [{
    key: "send",
    value: function send(tone) {
      var _this2 = this;

      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

      if (tone === undefined) {
        throw new TypeError('Not enough arguments');
      }

      this._direction = 'outgoing'; // Check RTCSession Status.

      if (this._session.status !== this._session.C.STATUS_CONFIRMED && this._session.status !== this._session.C.STATUS_WAITING_FOR_ACK) {
        throw new Exceptions.InvalidStateError(this._session.status);
      }

      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      this.eventHandlers = Utils.cloneObject(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: ".concat(tone));
      } // Check tone value.


      if (!tone.match(/^[0-9A-DR#*]$/)) {
        throw new TypeError("Invalid tone: ".concat(tone));
      } else {
        this._tone = tone;
      } // Duration is checked/corrected in RTCSession.


      this._duration = options.duration;
      extraHeaders.push('Content-Type: application/dtmf-relay');
      var body = "Signal=".concat(this._tone, "\r\n");
      body += "Duration=".concat(this._duration);

      this._session.newDTMF({
        originator: 'local',
        dtmf: this,
        request: this._request
      });

      this._session.sendRequest(JsSIP_C.INFO, {
        extraHeaders: extraHeaders,
        eventHandlers: {
          onSuccessResponse: function onSuccessResponse(response) {
            _this2.emit('succeeded', {
              originator: 'remote',
              response: response
            });
          },
          onErrorResponse: function onErrorResponse(response) {
            if (_this2.eventHandlers.onFailed) {
              _this2.eventHandlers.onFailed();
            }

            _this2.emit('failed', {
              originator: 'remote',
              response: response
            });
          },
          onRequestTimeout: function onRequestTimeout() {
            _this2._session.onRequestTimeout();
          },
          onTransportError: function onTransportError() {
            _this2._session.onTransportError();
          },
          onDialogError: function onDialogError() {
            _this2._session.onDialogError();
          }
        },
        body: body
      });
    }
  }, {
    key: "init_incoming",
    value: function init_incoming(request) {
      var reg_tone = /^(Signal\s*?=\s*?)([0-9A-D#*]{1})(\s)?.*/;
      var reg_duration = /^(Duration\s?=\s?)([0-9]{1,4})(\s)?.*/;
      this._direction = 'incoming';
      this._request = request;
      request.reply(200);

      if (request.body) {
        var body = request.body.split('\n');

        if (body.length >= 1) {
          if (reg_tone.test(body[0])) {
            this._tone = body[0].replace(reg_tone, '$2');
          }
        }

        if (body.length >= 2) {
          if (reg_duration.test(body[1])) {
            this._duration = parseInt(body[1].replace(reg_duration, '$2'), 10);
          }
        }
      }

      if (!this._duration) {
        this._duration = C.DEFAULT_DURATION;
      }

      if (!this._tone) {
        debug('invalid INFO DTMF received, discarded');
      } else {
        this._session.newDTMF({
          originator: 'remote',
          dtmf: this,
          request: request
        });
      }
    }
  }, {
    key: "tone",
    get: function get() {
      return this._tone;
    }
  }, {
    key: "duration",
    get: function get() {
      return this._duration;
    }
  }]);

  return DTMF;
}(EventEmitter);
/**
 * Expose C object.
 */


module.exports.C = C;
},{"../Constants":2,"../Exceptions":6,"../Utils":26,"debug":30,"events":29}],14:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

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

var debugerror = require('debug')('JsSIP:ERROR:RTCSession:Info');

debugerror.log = console.warn.bind(console);

var JsSIP_C = require('../Constants');

var Exceptions = require('../Exceptions');

var Utils = require('../Utils');

module.exports = /*#__PURE__*/function (_EventEmitter) {
  _inherits(Info, _EventEmitter);

  var _super = _createSuper(Info);

  function Info(session) {
    var _this;

    _classCallCheck(this, Info);

    _this = _super.call(this);
    _this._session = session;
    _this._direction = null;
    _this._contentType = null;
    _this._body = null;
    return _this;
  }

  _createClass(Info, [{
    key: "send",
    value: function send(contentType, body) {
      var _this2 = this;

      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      this._direction = 'outgoing';

      if (contentType === undefined) {
        throw new TypeError('Not enough arguments');
      } // Check RTCSession Status.


      if (this._session.status !== this._session.C.STATUS_CONFIRMED && this._session.status !== this._session.C.STATUS_WAITING_FOR_ACK) {
        throw new Exceptions.InvalidStateError(this._session.status);
      }

      this._contentType = contentType;
      this._body = body;
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      extraHeaders.push("Content-Type: ".concat(contentType));

      this._session.newInfo({
        originator: 'local',
        info: this,
        request: this.request
      });

      this._session.sendRequest(JsSIP_C.INFO, {
        extraHeaders: extraHeaders,
        eventHandlers: {
          onSuccessResponse: function onSuccessResponse(response) {
            _this2.emit('succeeded', {
              originator: 'remote',
              response: response
            });
          },
          onErrorResponse: function onErrorResponse(response) {
            _this2.emit('failed', {
              originator: 'remote',
              response: response
            });
          },
          onTransportError: function onTransportError() {
            _this2._session.onTransportError();
          },
          onRequestTimeout: function onRequestTimeout() {
            _this2._session.onRequestTimeout();
          },
          onDialogError: function onDialogError() {
            _this2._session.onDialogError();
          }
        },
        body: body
      });
    }
  }, {
    key: "init_incoming",
    value: function init_incoming(request) {
      this._direction = 'incoming';
      this.request = request;
      request.reply(200);
      this._contentType = request.getHeader('content-type');
      this._body = request.body;

      this._session.newInfo({
        originator: 'remote',
        info: this,
        request: request
      });
    }
  }, {
    key: "contentType",
    get: function get() {
      return this._contentType;
    }
  }, {
    key: "body",
    get: function get() {
      return this._body;
    }
  }]);

  return Info;
}(EventEmitter);
},{"../Constants":2,"../Exceptions":6,"../Utils":26,"debug":30,"events":29}],15:[function(require,module,exports){
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var JsSIP_C = require('../Constants');

var debug = require('debug')('JsSIP:RTCSession:ReferNotifier');

var C = {
  event_type: 'refer',
  body_type: 'message/sipfrag;version=2.0',
  expires: 300
};

module.exports = /*#__PURE__*/function () {
  function ReferNotifier(session, id, expires) {
    _classCallCheck(this, ReferNotifier);

    this._session = session;
    this._id = id;
    this._expires = expires || C.expires;
    this._active = true; // The creation of a Notifier results in an immediate NOTIFY.

    this.notify(100);
  }

  _createClass(ReferNotifier, [{
    key: "notify",
    value: function notify(code, reason) {
      debug('notify()');

      if (this._active === false) {
        return;
      }

      reason = reason || JsSIP_C.REASON_PHRASE[code] || '';
      var state;

      if (code >= 200) {
        state = 'terminated;reason=noresource';
      } else {
        state = "active;expires=".concat(this._expires);
      } // Put this in a try/catch block.


      this._session.sendRequest(JsSIP_C.NOTIFY, {
        extraHeaders: ["Event: ".concat(C.event_type, ";id=").concat(this._id), "Subscription-State: ".concat(state), "Content-Type: ".concat(C.body_type)],
        body: "SIP/2.0 ".concat(code, " ").concat(reason),
        eventHandlers: {
          // If a negative response is received, subscription is canceled.
          onErrorResponse: function onErrorResponse() {
            this._active = false;
          }
        }
      });
    }
  }]);

  return ReferNotifier;
}();
},{"../Constants":2,"debug":30}],16:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

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

var JsSIP_C = require('../Constants');

var Grammar = require('../Grammar');

var Utils = require('../Utils');

var debug = require('debug')('JsSIP:RTCSession:ReferSubscriber');

module.exports = /*#__PURE__*/function (_EventEmitter) {
  _inherits(ReferSubscriber, _EventEmitter);

  var _super = _createSuper(ReferSubscriber);

  function ReferSubscriber(session) {
    var _this;

    _classCallCheck(this, ReferSubscriber);

    _this = _super.call(this);
    _this._id = null;
    _this._session = session;
    return _this;
  }

  _createClass(ReferSubscriber, [{
    key: "sendRefer",
    value: function sendRefer(target) {
      var _this2 = this;

      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      debug('sendRefer()');
      var extraHeaders = Utils.cloneArray(options.extraHeaders);
      var eventHandlers = Utils.cloneObject(options.eventHandlers); // Set event handlers.

      for (var event in eventHandlers) {
        if (Object.prototype.hasOwnProperty.call(eventHandlers, event)) {
          this.on(event, eventHandlers[event]);
        }
      } // Replaces URI header field.


      var replaces = null;

      if (options.replaces) {
        replaces = options.replaces._request.call_id;
        replaces += ";to-tag=".concat(options.replaces._to_tag);
        replaces += ";from-tag=".concat(options.replaces._from_tag);
        replaces = encodeURIComponent(replaces);
      } // Refer-To header field.


      var referTo = "Refer-To: <".concat(target).concat(replaces ? "?Replaces=".concat(replaces) : '', ">");
      extraHeaders.push(referTo); // Referred-By header field.

      var referredBy = "Referred-By: <".concat(this._session._ua._configuration.uri._scheme, ":").concat(this._session._ua._configuration.uri._user, "@").concat(this._session._ua._configuration.uri._host, ">");
      extraHeaders.push(referredBy);
      extraHeaders.push("Contact: ".concat(this._session.contact));

      var request = this._session.sendRequest(JsSIP_C.REFER, {
        extraHeaders: extraHeaders,
        eventHandlers: {
          onSuccessResponse: function onSuccessResponse(response) {
            _this2._requestSucceeded(response);
          },
          onErrorResponse: function onErrorResponse(response) {
            _this2._requestFailed(response, JsSIP_C.causes.REJECTED);
          },
          onTransportError: function onTransportError() {
            _this2._requestFailed(null, JsSIP_C.causes.CONNECTION_ERROR);
          },
          onRequestTimeout: function onRequestTimeout() {
            _this2._requestFailed(null, JsSIP_C.causes.REQUEST_TIMEOUT);
          },
          onDialogError: function onDialogError() {
            _this2._requestFailed(null, JsSIP_C.causes.DIALOG_ERROR);
          }
        }
      });

      this._id = request.cseq;
    }
  }, {
    key: "receiveNotify",
    value: function receiveNotify(request) {
      debug('receiveNotify()');

      if (!request.body) {
        return;
      }

      var status_line = Grammar.parse(request.body.trim(), 'Status_Line');

      if (status_line === -1) {
        debug("receiveNotify() | error parsing NOTIFY body: \"".concat(request.body, "\""));
        return;
      }

      switch (true) {
        case /^100$/.test(status_line.status_code):
          this.emit('trying', {
            request: request,
            status_line: status_line
          });
          break;

        case /^1[0-9]{2}$/.test(status_line.status_code):
          this.emit('progress', {
            request: request,
            status_line: status_line
          });
          break;

        case /^2[0-9]{2}$/.test(status_line.status_code):
          this.emit('accepted', {
            request: request,
            status_line: status_line
          });
          break;

        default:
          this.emit('failed', {
            request: request,
            status_line: status_line
          });
          break;
      }
    }
  }, {
    key: "_requestSucceeded",
    value: function _requestSucceeded(response) {
      debug('REFER succeeded');
      debug('emit "requestSucceeded"');
      this.emit('requestSucceeded', {
        response: response
      });
    }
  }, {
    key: "_requestFailed",
    value: function _requestFailed(response, cause) {
      debug('REFER failed');
      debug('emit "requestFailed"');
      this.emit('requestFailed', {
        response: response || null,
        cause: cause
      });
    }
  }, {
    key: "id",
    get: function get() {
      return this._id;
    }
  }]);

  return ReferSubscriber;
}(EventEmitter);
},{"../Constants":2,"../Grammar":7,"../Utils":26,"debug":30,"events":29}],17:[function(require,module,exports){
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var Utils = require('./Utils');

var JsSIP_C = require('./Constants');

var SIPMessage = require('./SIPMessage');

var RequestSender = require('./RequestSender');

var debug = require('debug')('JsSIP:Registrator');

var MIN_REGISTER_EXPIRES = 10; // In seconds.

module.exports = /*#__PURE__*/function () {
  function Registrator(ua, transport) {
    _classCallCheck(this, Registrator);

    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 = Utils.createRandomToken(22);
    this._cseq = 0;
    this._to_uri = ua.configuration.uri;
    this._registrationTimer = null; // Ongoing Register request.

    this._registering = false; // Set status.

    this._registered = false; // Contact header.

    this._contact = this._ua.contact.toString(); // Sip.ice media feature tag (RFC 5768).

    this._contact += ';+sip.ice'; // Custom headers for REGISTER and un-REGISTER.

    this._extraHeaders = []; // Custom Contact header params for REGISTER and un-REGISTER.

    this._extraContactParams = '';

    if (reg_id) {
      this._contact += ";reg-id=".concat(reg_id);
      this._contact += ";+sip.instance=\"<urn:uuid:".concat(this._ua.configuration.instance_id, ">\"");
    }
  }

  _createClass(Registrator, [{
    key: "setExtraHeaders",
    value: function setExtraHeaders(extraHeaders) {
      if (!Array.isArray(extraHeaders)) {
        extraHeaders = [];
      }

      this._extraHeaders = extraHeaders.slice();
    }
  }, {
    key: "setExtraContactParams",
    value: function setExtraContactParams(extraContactParams) {
      if (!(extraContactParams instanceof Object)) {
        extraContactParams = {};
      } // Reset it.


      this._extraContactParams = '';

      for (var param_key in extraContactParams) {
        if (Object.prototype.hasOwnProperty.call(extraContactParams, param_key)) {
          var param_value = extraContactParams[param_key];
          this._extraContactParams += ";".concat(param_key);

          if (param_value) {
            this._extraContactParams += "=".concat(param_value);
          }
        }
      }
    }
  }, {
    key: "register",
    value: function register() {
      var _this = this;

      if (this._registering) {
        debug('Register request in progress...');
        return;
      }

      var extraHeaders = this._extraHeaders.slice();

      extraHeaders.push("Contact: ".concat(this._contact, ";expires=").concat(this._expires).concat(this._extraContactParams));
      extraHeaders.push("Expires: ".concat(this._expires));
      var request = new SIPMessage.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 RequestSender(this._ua, request, {
        onRequestTimeout: function onRequestTimeout() {
          _this._registrationFailure(null, JsSIP_C.causes.REQUEST_TIMEOUT);
        },
        onTransportError: function onTransportError() {
          _this._registrationFailure(null, JsSIP_C.causes.CONNECTION_ERROR);
        },
        // Increase the CSeq on authentication.
        onAuthenticated: function onAuthenticated() {
          _this._cseq += 1;
        },
        onReceiveResponse: function onReceiveResponse(response) {
          // Discard responses to older REGISTER/un-REGISTER requests.
          if (response.cseq !== _this._cseq) {
            return;
          } // Clear registration timer.


          if (_this._registrationTimer !== null) {
            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):
              {
                _this._registering = false;

                if (!response.hasHeader('Contact')) {
                  debug('no Contact header in response to REGISTER, response ignored');
                  break;
                }

                var contacts = response.headers['Contact'].reduce(function (a, b) {
                  return a.concat(b.parsed);
                }, []); // Get the Contact pointing to us and update the expires value accordingly.

                var contact = contacts.find(function (element) {
                  return element.uri.user === _this._ua.contact.uri.user;
                });

                if (!contact) {
                  debug('no Contact header pointing to us, response ignored');
                  break;
                }

                var expires = contact.getParam('expires');

                if (!expires && response.hasHeader('expires')) {
                  expires = response.getHeader('expires');
                }

                if (!expires) {
                  expires = _this._expires;
                }

                expires = Number(expires);
                if (expires < MIN_REGISTER_EXPIRES) expires = MIN_REGISTER_EXPIRES; // Re-Register or emit an event before the expiration interval has elapsed.
                // For that, decrease the expires value. ie: 3 seconds.

                _this._registrationTimer = setTimeout(function () {
                  _this._registrationTimer = null; // If there are no listeners for registrationExpiring, renew registration.
                  // If there are listeners, let the function listening do the register call.

                  if (_this._ua.listeners('registrationExpiring').length === 0) {
                    _this.register();
                  } else {
                    _this._ua.emit('registrationExpiring');
                  }
                }, expires * 1000 - 5000); // 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, '');
                }

                if (!_this._registered) {
                  _this._registered = true;

                  _this._ua.registered({
                    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 = Number(response.getHeader('min-expires'));
                  if (_this._expires < MIN_REGISTER_EXPIRES) _this._expires = MIN_REGISTER_EXPIRES; // Attempt the registration again immediately.

                  _this.register();
                } else {
                  // This response MUST contain a Min-Expires header field.
                  debug('423 response received for REGISTER without Min-Expires');

                  _this._registrationFailure(response, JsSIP_C.causes.SIP_FAILURE_CODE);
                }

                break;
              }

            default:
              {
                var cause = Utils.sipErrorCause(response.status_code);

                _this._registrationFailure(response, cause);
              }
          }
        }
      });
      this._registering = true;
      request_sender.send();
    }
  }, {
    key: "unregister",
    value: function unregister() {
      var _this2 = this;

      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

      if (!this._registered) {
        debug('already unregistered');
        return;
      }

      this._registered = false; // Clear the registration timer.

      if (this._registrationTimer !== null) {
        clearTimeout(this._registrationTimer);
        this._registrationTimer = null;
      }

      var extraHeaders = this._extraHeaders.slice();

      if (options.all) {
        extraHeaders.push("Contact: *".concat(this._extraContactParams));
      } else {
        extraHeaders.push("Contact: ".concat(this._contact, ";expires=0").concat(this._extraContactParams));
      }

      extraHeaders.push('Expires: 0');
      var request = new SIPMessage.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 RequestSender(this._ua, request, {
        onRequestTimeout: function onRequestTimeout() {
          _this2._unregistered(null, JsSIP_C.causes.REQUEST_TIMEOUT);
        },
        onTransportError: function onTransportError() {
          _this2._unregistered(null, JsSIP_C.causes.CONNECTION_ERROR);
        },
        // Increase the CSeq on authentication.
        onAuthenticated: function onAuthenticated() {
          _this2._cseq += 1;
        },
        onReceiveResponse: function onReceiveResponse(response) {
          switch (true) {
            case /^1[0-9]{2}$/.test(response.status_code):
              // Ignore provisional responses.
              break;

            case /^2[0-9]{2}$/.test(response.status_code):
              _this2._unregistered(response);

              break;

            default:
              {
                var cause = Utils.sipErrorCause(response.status_code);

                _this2._unregistered(response, cause);
              }
          }
        }
      });
      request_sender.send();
    }
  }, {
    key: "close",
    value: function close() {
      if (this._registered) {
        this.unregister();
      }
    }
  }, {
    key: "onTransportClosed",
    value: function onTransportClosed() {
      this._registering = false;

      if (this._registrationTimer !== null) {
        clearTimeout(this._registrationTimer);
        this._registrationTimer = null;
      }

      if (this._registered) {
        this._registered = false;

        this._ua.unregistered({});
      }
    }
  }, {
    key: "_registrationFailure",
    value: function _registrationFailure(response, cause) {
      this._registering = false;

      this._ua.registrationFailed({
        response: response || null,
        cause: cause
      });

      if (this._registered) {
        this._registered = false;

        this._ua.unregistered({
          response: response || null,
          cause: cause
        });
      }
    }
  }, {
    key: "_unregistered",
    value: function _unregistered(response, cause) {
      this._registering = false;
      this._registered = false;

      this._ua.unregistered({
        response: response || null,
        cause: cause || null
      });
    }
  }, {
    key: "registered",
    get: function get() {
      return this._registered;
    }
  }]);

  return Registrator;
}();
},{"./Constants":2,"./RequestSender":18,"./SIPMessage":19,"./Utils":26,"debug":30}],18:[function(require,module,exports){
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var JsSIP_C = require('./Constants');

var DigestAuthentication = require('./DigestAuthentication');

var Transactions = require('./Transactions');

var debug = require('debug')('JsSIP:RequestSender'); // Default event handlers.


var EventHandlers = {
  onRequestTimeout: function onRequestTimeout() {},
  onTransportError: function onTransportError() {},
  onReceiveResponse: function onReceiveResponse() {},
  onAuthenticated: function onAuthenticated() {}
};

module.exports = /*#__PURE__*/function () {
  function RequestSender(ua, request, eventHandlers) {
    _classCallCheck(this, RequestSender);

    this._ua = ua;
    this._eventHandlers = eventHandlers;
    this._method = request.method;
    this._request = request;
    this._auth = null;
    this._challenged = false;
    this._staled = false; // Define the undefined handlers.

    for (var handler in EventHandlers) {
      if (Object.prototype.hasOwnProperty.call(EventHandlers, handler)) {
        if (!this._eventHandlers[handler]) {
          this._eventHandlers[handler] = EventHandlers[handler];
        }
      }
    } // If ua is in closing process or even closed just allow sending Bye and ACK.


    if (ua.status === ua.C.STATUS_USER_CLOSED && (this._method !== JsSIP_C.BYE || this._method !== JsSIP_C.ACK)) {
      this._eventHandlers.onTransportError();
    }
  }
  /**
  * Create the client transaction and send the message.
  */


  _createClass(RequestSender, [{
    key: "send",
    value: function send() {
      var _this = this;

      var eventHandlers = {
        onRequestTimeout: function onRequestTimeout() {
          _this._eventHandlers.onRequestTimeout();
        },
        onTransportError: function onTransportError() {
          _this._eventHandlers.onTransportError();
        },
        onReceiveResponse: function onReceiveResponse(response) {
          _this._receiveResponse(response);
        }
      };

      switch (this._method) {
        case 'INVITE':
          this.clientTransaction = new Transactions.InviteClientTransaction(this._ua, this._ua.transport, this._request, eventHandlers);
          break;

        case 'ACK':
          this.clientTransaction = new Transactions.AckClientTransaction(this._ua, this._ua.transport, this._request, eventHandlers);
          break;

        default:
          this.clientTransaction = new Transactions.NonInviteClientTransaction(this._ua, this._ua.transport, this._request, eventHandlers);
      } // If authorization JWT is present, use it.


      if (this._ua._configuration.authorization_jwt) {
        this._request.setHeader('Authorization', this._ua._configuration.authorization_jwt);
      }

      this.clientTransaction.send();
    }
    /**
    * Called from client transaction when receiving a correct response to the request.
    * Authenticate request if needed or pass the response back to the applicant.
    */

  }, {
    key: "_receiveResponse",
    value: function _receiveResponse(response) {
      var challenge;
      var authorization_header_name;
      var 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 || this._ua.configuration.ha1 !== 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) {
          debug("".concat(response.status_code, " with wrong or missing challenge, cannot authenticate"));

          this._eventHandlers.onReceiveResponse(response);

          return;
        }

        if (!this._challenged || !this._staled && challenge.stale === true) {
          if (!this._auth) {
            this._auth = new DigestAuthentication({
              username: this._ua.configuration.authorization_user,
              password: this._ua.configuration.password,
              realm: this._ua.configuration.realm,
              ha1: this._ua.configuration.ha1
            });
          } // Verify that the challenge is really valid.


          if (!this._auth.authenticate(this._request, challenge)) {
            this._eventHandlers.onReceiveResponse(response);

            return;
          }

          this._challenged = true; // Update ha1 and realm in the UA.

          this._ua.set('realm', this._auth.get('realm'));

          this._ua.set('ha1', this._auth.get('ha1'));

          if (challenge.stale) {
            this._staled = true;
          }

          this._request = this._request.clone();
          this._request.cseq += 1;

          this._request.setHeader('cseq', "".concat(this._request.cseq, " ").concat(this._method));

          this._request.setHeader(authorization_header_name, this._auth.toString());

          this._eventHandlers.onAuthenticated(this._request);

          this.send();
        } else {
          this._eventHandlers.onReceiveResponse(response);
        }
      } else {
        this._eventHandlers.onReceiveResponse(response);
      }
    }
  }]);

  return RequestSender;
}();
},{"./Constants":2,"./DigestAuthentication":5,"./Transactions":22,"debug":30}],19:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var sdp_transform = require('sdp-transform');

var JsSIP_C = require('./Constants');

var Utils = require('./Utils');

var NameAddrHeader = require('./NameAddrHeader');

var Grammar = require('./Grammar');

var debug = require('debug')('JsSIP:SIPMessage');
/**
 * -param {String} method request method
 * -param {String} ruri request uri
 * -param {UA} ua
 * -param {Object} params parameters that will have priority over ua.configuration parameters:
 * <br>
 *  - cseq, call_id, from_tag, from_uri, from_display_name, to_uri, to_tag, route_set
 * -param {Object} [headers] extra headers
 * -param {String} [body]
 */


var OutgoingRequest = /*#__PURE__*/function () {
  function OutgoingRequest(method, ruri, ua, params, extraHeaders, body) {
    _classCallCheck(this, OutgoingRequest);

    // Mandatory parameters check.
    if (!method || !ruri || !ua) {
      return null;
    }

    params = params || {};
    this.ua = ua;
    this.headers = {};
    this.method = method;
    this.ruri = ruri;
    this.body = body;
    this.extraHeaders = Utils.cloneArray(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', "<".concat(ua.transport.sip_uri, ";lr>"));
    } // Via.
    // Empty Via header. Will be filled by the client transaction.


    this.setHeader('via', ''); // Max-Forwards.

    this.setHeader('max-forwards', JsSIP_C.MAX_FORWARDS); // To

    var to_uri = params.to_uri || ruri;
    var to_params = params.to_tag ? {
      tag: params.to_tag
    } : null;
    var to_display_name = typeof params.to_display_name !== 'undefined' ? params.to_display_name : null;
    this.to = new NameAddrHeader(to_uri, to_display_name, to_params);
    this.setHeader('to', this.to.toString()); // From.

    var from_uri = params.from_uri || ua.configuration.uri;
    var from_params = {
      tag: params.from_tag || Utils.newTag()
    };
    var display_name;

    if (typeof params.from_display_name !== 'undefined') {
      display_name = params.from_display_name;
    } else if (ua.configuration.display_name) {
      display_name = ua.configuration.display_name;
    } else {
      display_name = null;
    }

    this.from = new NameAddrHeader(from_uri, display_name, from_params);
    this.setHeader('from', this.from.toString()); // Call-ID.

    var call_id = params.call_id || ua.configuration.jssip_id + Utils.createRandomToken(15);
    this.call_id = call_id;
    this.setHeader('call-id', call_id); // CSeq.

    var cseq = params.cseq || Math.floor(Math.random() * 10000);
    this.cseq = cseq;
    this.setHeader('cseq', "".concat(cseq, " ").concat(method));
  }
  /**
   * Replace the the given header by the given value.
   * -param {String} name header name
   * -param {String | Array} value header value
   */


  _createClass(OutgoingRequest, [{
    key: "setHeader",
    value: function setHeader(name, value) {
      // Remove the header from extraHeaders if present.
      var regexp = new RegExp("^\\s*".concat(name, "\\s*:"), 'i');

      for (var idx = 0; idx < this.extraHeaders.length; idx++) {
        if (regexp.test(this.extraHeaders[idx])) {
          this.extraHeaders.splice(idx, 1);
        }
      }

      this.headers[Utils.headerize(name)] = Array.isArray(value) ? 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.
     */

  }, {
    key: "getHeader",
    value: function getHeader(name) {
      var headers = this.headers[Utils.headerize(name)];

      if (headers) {
        if (headers[0]) {
          return headers[0];
        }
      } else {
        var regexp = new RegExp("^\\s*".concat(name, "\\s*:"), 'i');

        var _iterator = _createForOfIteratorHelper(this.extraHeaders),
            _step;

        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var header = _step.value;

            if (regexp.test(header)) {
              return header.substring(header.indexOf(':') + 1).trim();
            }
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }
      }

      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.
     */

  }, {
    key: "getHeaders",
    value: function getHeaders(name) {
      var headers = this.headers[Utils.headerize(name)];
      var result = [];

      if (headers) {
        var _iterator2 = _createForOfIteratorHelper(headers),
            _step2;

        try {
          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
            var header = _step2.value;
            result.push(header);
          }
        } catch (err) {
          _iterator2.e(err);
        } finally {
          _iterator2.f();
        }

        return result;
      } else {
        var regexp = new RegExp("^\\s*".concat(name, "\\s*:"), 'i');

        var _iterator3 = _createForOfIteratorHelper(this.extraHeaders),
            _step3;

        try {
          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
            var _header = _step3.value;

            if (regexp.test(_header)) {
              result.push(_header.substring(_header.indexOf(':') + 1).trim());
            }
          }
        } catch (err) {
          _iterator3.e(err);
        } finally {
          _iterator3.f();
        }

        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
     */

  }, {
    key: "hasHeader",
    value: function hasHeader(name) {
      if (this.headers[Utils.headerize(name)]) {
        return true;
      } else {
        var regexp = new RegExp("^\\s*".concat(name, "\\s*:"), 'i');

        var _iterator4 = _createForOfIteratorHelper(this.extraHeaders),
            _step4;

        try {
          for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
            var header = _step4.value;

            if (regexp.test(header)) {
              return true;
            }
          }
        } catch (err) {
          _iterator4.e(err);
        } finally {
          _iterator4.f();
        }
      }

      return false;
    }
    /**
     * Parse the current body as a SDP and store the resulting object
     * into this.sdp.
     * -param {Boolean} force: Parse even if this.sdp already exists.
     *
     * Returns this.sdp.
     */

  }, {
    key: "parseSDP",
    value: function parseSDP(force) {
      if (!force && this.sdp) {
        return this.sdp;
      } else {
        this.sdp = sdp_transform.parse(this.body || '');
        return this.sdp;
      }
    }
  }, {
    key: "toString",
    value: function toString() {
      var msg = "".concat(this.method, " ").concat(this.ruri, " SIP/2.0\r\n");

      for (var headerName in this.headers) {
        if (Object.prototype.hasOwnProperty.call(this.headers, headerName)) {
          var _iterator5 = _createForOfIteratorHelper(this.headers[headerName]),
              _step5;

          try {
            for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
              var headerValue = _step5.value;
              msg += "".concat(headerName, ": ").concat(headerValue, "\r\n");
            }
          } catch (err) {
            _iterator5.e(err);
          } finally {
            _iterator5.f();
          }
        }
      }

      var _iterator6 = _createForOfIteratorHelper(this.extraHeaders),
          _step6;

      try {
        for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
          var header = _step6.value;
          msg += "".concat(header.trim(), "\r\n");
        } // Supported.

      } catch (err) {
        _iterator6.e(err);
      } finally {
        _iterator6.f();
      }

      var supported = [];

      switch (this.method) {
        case JsSIP_C.REGISTER:
          supported.push('path', 'gruu');
          break;

        case JsSIP_C.INVITE:
          if (this.ua.configuration.session_timers) {
            supported.push('timer');
          }

          if (this.ua.contact.pub_gruu || this.ua.contact.temp_gruu) {
            supported.push('gruu');
          }

          supported.push('ice', 'replaces');
          break;

        case JsSIP_C.UPDATE:
          if (this.ua.configuration.session_timers) {
            supported.push('timer');
          }

          supported.push('ice');
          break;
      }

      supported.push('outbound');
      var userAgent = this.ua.configuration.user_agent || JsSIP_C.USER_AGENT; // Allow.

      msg += "Allow: ".concat(JsSIP_C.ALLOWED_METHODS, "\r\n");
      msg += "Supported: ".concat(supported, "\r\n");
      msg += "User-Agent: ".concat(userAgent, "\r\n");

      if (this.body) {
        var length = Utils.str_utf8_length(this.body);
        msg += "Content-Length: ".concat(length, "\r\n\r\n");
        msg += this.body;
      } else {
        msg += 'Content-Length: 0\r\n\r\n';
      }

      return msg;
    }
  }, {
    key: "clone",
    value: function clone() {
      var request = new OutgoingRequest(this.method, this.ruri, this.ua);
      Object.keys(this.headers).forEach(function (name) {
        request.headers[name] = this.headers[name].slice();
      }, this);
      request.body = this.body;
      request.extraHeaders = Utils.cloneArray(this.extraHeaders);
      request.to = this.to;
      request.from = this.from;
      request.call_id = this.call_id;
      request.cseq = this.cseq;
      return request;
    }
  }]);

  return OutgoingRequest;
}();

var InitialOutgoingInviteRequest = /*#__PURE__*/function (_OutgoingRequest) {
  _inherits(InitialOutgoingInviteRequest, _OutgoingRequest);

  var _super = _createSuper(InitialOutgoingInviteRequest);

  function InitialOutgoingInviteRequest(ruri, ua, params, extraHeaders, body) {
    var _this;

    _classCallCheck(this, InitialOutgoingInviteRequest);

    _this = _super.call(this, JsSIP_C.INVITE, ruri, ua, params, extraHeaders, body);
    _this.transaction = null;
    return _this;
  }

  _createClass(InitialOutgoingInviteRequest, [{
    key: "cancel",
    value: function cancel(reason) {
      this.transaction.cancel(reason);
    }
  }, {
    key: "clone",
    value: function clone() {
      var request = new InitialOutgoingInviteRequest(this.ruri, this.ua);
      Object.keys(this.headers).forEach(function (name) {
        request.headers[name] = this.headers[name].slice();
      }, this);
      request.body = this.body;
      request.extraHeaders = Utils.cloneArray(this.extraHeaders);
      request.to = this.to;
      request.from = this.from;
      request.call_id = this.call_id;
      request.cseq = this.cseq;
      request.transaction = this.transaction;
      return request;
    }
  }]);

  return InitialOutgoingInviteRequest;
}(OutgoingRequest);

var IncomingMessage = /*#__PURE__*/function () {
  function IncomingMessage() {
    _classCallCheck(this, IncomingMessage);

    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;
    this.sdp = null;
  }
  /**
  * Insert a header of the given name and value into the last position of the
  * header array.
  */


  _createClass(IncomingMessage, [{
    key: "addHeader",
    value: function addHeader(name, value) {
      var header = {
        raw: value
      };
      name = Utils.headerize(name);

      if (this.headers[name]) {
        this.headers[name].push(header);
      } else {
        this.headers[name] = [header];
      }
    }
    /**
     * Get the value of the given header name at the given position.
     */

  }, {
    key: "getHeader",
    value: function getHeader(name) {
      var header = this.headers[Utils.headerize(name)];

      if (header) {
        if (header[0]) {
          return header[0].raw;
        }
      } else {
        return;
      }
    }
    /**
     * Get the header/s of the given name.
     */

  }, {
    key: "getHeaders",
    value: function getHeaders(name) {
      var headers = this.headers[Utils.headerize(name)];
      var result = [];

      if (!headers) {
        return [];
      }

      var _iterator7 = _createForOfIteratorHelper(headers),
          _step7;

      try {
        for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
          var header = _step7.value;
          result.push(header.raw);
        }
      } catch (err) {
        _iterator7.e(err);
      } finally {
        _iterator7.f();
      }

      return result;
    }
    /**
     * Verify the existence of the given header.
     */

  }, {
    key: "hasHeader",
    value: function hasHeader(name) {
      return this.headers[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.
    */

  }, {
    key: "parseHeader",
    value: function parseHeader(name) {
      var idx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
      name = Utils.headerize(name);

      if (!this.headers[name]) {
        debug("header \"".concat(name, "\" not present"));
        return;
      } else if (idx >= this.headers[name].length) {
        debug("not so many \"".concat(name, "\" headers present"));
        return;
      }

      var header = this.headers[name][idx];
      var value = header.raw;

      if (header.parsed) {
        return header.parsed;
      } // Substitute '-' by '_' for grammar rule matching.


      var parsed = Grammar.parse(value, name.replace(/-/g, '_'));

      if (parsed === -1) {
        this.headers[name].splice(idx, 1); // delete from headers

        debug("error parsing \"".concat(name, "\" header field with value \"").concat(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
     */

  }, {
    key: "s",
    value: function s(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
    */

  }, {
    key: "setHeader",
    value: function setHeader(name, value) {
      var header = {
        raw: value
      };
      this.headers[Utils.headerize(name)] = [header];
    }
    /**
     * Parse the current body as a SDP and store the resulting object
     * into this.sdp.
     * -param {Boolean} force: Parse even if this.sdp already exists.
     *
     * Returns this.sdp.
     */

  }, {
    key: "parseSDP",
    value: function parseSDP(force) {
      if (!force && this.sdp) {
        return this.sdp;
      } else {
        this.sdp = sdp_transform.parse(this.body || '');
        return this.sdp;
      }
    }
  }, {
    key: "toString",
    value: function toString() {
      return this.data;
    }
  }]);

  return IncomingMessage;
}();

var IncomingRequest = /*#__PURE__*/function (_IncomingMessage) {
  _inherits(IncomingRequest, _IncomingMessage);

  var _super2 = _createSuper(IncomingRequest);

  function IncomingRequest(ua) {
    var _this2;

    _classCallCheck(this, IncomingRequest);

    _this2 = _super2.call(this);
    _this2.ua = ua;
    _this2.headers = {};
    _this2.ruri = null;
    _this2.transport = null;
    _this2.server_transaction = null;
    return _this2;
  }
  /**
  * 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
  */


  _createClass(IncomingRequest, [{
    key: "reply",
    value: function reply(code, reason, extraHeaders, body, onSuccess, onFailure) {
      var supported = [];
      var to = this.getHeader('To');
      code = code || null;
      reason = reason || null; // Validate code and reason values.

      if (!code || code < 100 || code > 699) {
        throw new TypeError("Invalid status_code: ".concat(code));
      } else if (reason && typeof reason !== 'string' && !(reason instanceof String)) {
        throw new TypeError("Invalid reason_phrase: ".concat(reason));
      }

      reason = reason || JsSIP_C.REASON_PHRASE[code] || '';
      extraHeaders = Utils.cloneArray(extraHeaders);
      var response = "SIP/2.0 ".concat(code, " ").concat(reason, "\r\n");

      if (this.method === JsSIP_C.INVITE && code > 100 && code <= 200) {
        var headers = this.getHeaders('record-route');

        var _iterator8 = _createForOfIteratorHelper(headers),
            _step8;

        try {
          for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
            var header = _step8.value;
            response += "Record-Route: ".concat(header, "\r\n");
          }
        } catch (err) {
          _iterator8.e(err);
        } finally {
          _iterator8.f();
        }
      }

      var vias = this.getHeaders('via');

      var _iterator9 = _createForOfIteratorHelper(vias),
          _step9;

      try {
        for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
          var via = _step9.value;
          response += "Via: ".concat(via, "\r\n");
        }
      } catch (err) {
        _iterator9.e(err);
      } finally {
        _iterator9.f();
      }

      if (!this.to_tag && code > 100) {
        to += ";tag=".concat(Utils.newTag());
      } else if (this.to_tag && !this.s('to').hasParam('tag')) {
        to += ";tag=".concat(this.to_tag);
      }

      response += "To: ".concat(to, "\r\n");
      response += "From: ".concat(this.getHeader('From'), "\r\n");
      response += "Call-ID: ".concat(this.call_id, "\r\n");
      response += "CSeq: ".concat(this.cseq, " ").concat(this.method, "\r\n");

      var _iterator10 = _createForOfIteratorHelper(extraHeaders),
          _step10;

      try {
        for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
          var _header2 = _step10.value;
          response += "".concat(_header2.trim(), "\r\n");
        } // Supported.

      } catch (err) {
        _iterator10.e(err);
      } finally {
        _iterator10.f();
      }

      switch (this.method) {
        case JsSIP_C.INVITE:
          if (this.ua.configuration.session_timers) {
            supported.push('timer');
          }

          if (this.ua.contact.pub_gruu || this.ua.contact.temp_gruu) {
            supported.push('gruu');
          }

          supported.push('ice', 'replaces');
          break;

        case JsSIP_C.UPDATE:
          if (this.ua.configuration.session_timers) {
            supported.push('timer');
          }

          if (body) {
            supported.push('ice');
          }

          supported.push('replaces');
      }

      supported.push('outbound'); // Allow and Accept.

      if (this.method === JsSIP_C.OPTIONS) {
        response += "Allow: ".concat(JsSIP_C.ALLOWED_METHODS, "\r\n");
        response += "Accept: ".concat(JsSIP_C.ACCEPTED_BODY_TYPES, "\r\n");
      } else if (code === 405) {
        response += "Allow: ".concat(JsSIP_C.ALLOWED_METHODS, "\r\n");
      } else if (code === 415) {
        response += "Accept: ".concat(JsSIP_C.ACCEPTED_BODY_TYPES, "\r\n");
      }

      response += "Supported: ".concat(supported, "\r\n");

      if (body) {
        var length = Utils.str_utf8_length(body);
        response += 'Content-Type: application/sdp\r\n';
        response += "Content-Length: ".concat(length, "\r\n\r\n");
        response += body;
      } else {
        response += "Content-Length: ".concat(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
    */

  }, {
    key: "reply_sl",
    value: function reply_sl() {
      var code = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
      var reason = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      var vias = this.getHeaders('via'); // Validate code and reason values.

      if (!code || code < 100 || code > 699) {
        throw new TypeError("Invalid status_code: ".concat(code));
      } else if (reason && typeof reason !== 'string' && !(reason instanceof String)) {
        throw new TypeError("Invalid reason_phrase: ".concat(reason));
      }

      reason = reason || JsSIP_C.REASON_PHRASE[code] || '';
      var response = "SIP/2.0 ".concat(code, " ").concat(reason, "\r\n");

      var _iterator11 = _createForOfIteratorHelper(vias),
          _step11;

      try {
        for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {
          var via = _step11.value;
          response += "Via: ".concat(via, "\r\n");
        }
      } catch (err) {
        _iterator11.e(err);
      } finally {
        _iterator11.f();
      }

      var to = this.getHeader('To');

      if (!this.to_tag && code > 100) {
        to += ";tag=".concat(Utils.newTag());
      } else if (this.to_tag && !this.s('to').hasParam('tag')) {
        to += ";tag=".concat(this.to_tag);
      }

      response += "To: ".concat(to, "\r\n");
      response += "From: ".concat(this.getHeader('From'), "\r\n");
      response += "Call-ID: ".concat(this.call_id, "\r\n");
      response += "CSeq: ".concat(this.cseq, " ").concat(this.method, "\r\n");
      response += "Content-Length: ".concat(0, "\r\n\r\n");
      this.transport.send(response);
    }
  }]);

  return IncomingRequest;
}(IncomingMessage);

var IncomingResponse = /*#__PURE__*/function (_IncomingMessage2) {
  _inherits(IncomingResponse, _IncomingMessage2);

  var _super3 = _createSuper(IncomingResponse);

  function IncomingResponse() {
    var _this3;

    _classCallCheck(this, IncomingResponse);

    _this3 = _super3.call(this);
    _this3.headers = {};
    _this3.status_code = null;
    _this3.reason_phrase = null;
    return _this3;
  }

  return IncomingResponse;
}(IncomingMessage);

module.exports = {
  OutgoingRequest: OutgoingRequest,
  InitialOutgoingInviteRequest: InitialOutgoingInviteRequest,
  IncomingRequest: IncomingRequest,
  IncomingResponse: IncomingResponse
};
},{"./Constants":2,"./Grammar":7,"./NameAddrHeader":10,"./Utils":26,"debug":30,"sdp-transform":35}],20:[function(require,module,exports){
"use strict";

var Utils = require('./Utils');

var Grammar = require('./Grammar');

var debugerror = require('debug')('JsSIP:ERROR:Socket');

debugerror.log = console.warn.bind(console);
/**
 * Interface documentation: https://jssip.net/documentation/$last_version/api/socket/
 *
 * interface Socket {
 *  attribute String via_transport
 *  attribute String url
 *  attribute String sip_uri
 *
 *  method connect();
 *  method disconnect();
 *  method send(data);
 *
 *  attribute EventHandler onconnect
 *  attribute EventHandler ondisconnect
 *  attribute EventHandler ondata
 * }
 *
 */

exports.isSocket = function (socket) {
  // Ignore if an array is given.
  if (Array.isArray(socket)) {
    return false;
  }

  if (typeof socket === 'undefined') {
    debugerror('undefined JsSIP.Socket instance');
    return false;
  } // Check Properties.


  try {
    if (!Utils.isString(socket.url)) {
      debugerror('missing or invalid JsSIP.Socket url property');
      throw new Error();
    }

    if (!Utils.isString(socket.via_transport)) {
      debugerror('missing or invalid JsSIP.Socket via_transport property');
      throw new Error();
    }

    if (Grammar.parse(socket.sip_uri, 'SIP_URI') === -1) {
      debugerror('missing or invalid JsSIP.Socket sip_uri property');
      throw new Error();
    }
  } catch (e) {
    return false;
  } // Check Methods.


  try {
    ['connect', 'disconnect', 'send'].forEach(function (method) {
      if (!Utils.isFunction(socket[method])) {
        debugerror("missing or invalid JsSIP.Socket method: ".concat(method));
        throw new Error();
      }
    });
  } catch (e) {
    return false;
  }

  return true;
};
},{"./Grammar":7,"./Utils":26,"debug":30}],21:[function(require,module,exports){
"use strict";

var T1 = 500,
    T2 = 4000,
    T4 = 5000;
module.exports = {
  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

};
},{}],22:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

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

var JsSIP_C = require('./Constants');

var SIPMessage = require('./SIPMessage');

var Timers = require('./Timers');

var debugnict = require('debug')('JsSIP:NonInviteClientTransaction');

var debugict = require('debug')('JsSIP:InviteClientTransaction');

var debugact = require('debug')('JsSIP:AckClientTransaction');

var debugnist = require('debug')('JsSIP:NonInviteServerTransaction');

var debugist = require('debug')('JsSIP:InviteServerTransaction');

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'
};

var NonInviteClientTransaction = /*#__PURE__*/function (_EventEmitter) {
  _inherits(NonInviteClientTransaction, _EventEmitter);

  var _super = _createSuper(NonInviteClientTransaction);

  function NonInviteClientTransaction(ua, transport, request, eventHandlers) {
    var _this;

    _classCallCheck(this, NonInviteClientTransaction);

    _this = _super.call(this);
    _this.type = C.NON_INVITE_CLIENT;
    _this.id = "z9hG4bK".concat(Math.floor(Math.random() * 10000000));
    _this.ua = ua;
    _this.transport = transport;
    _this.request = request;
    _this.eventHandlers = eventHandlers;
    var via = "SIP/2.0/".concat(transport.via_transport);
    via += " ".concat(ua.configuration.via_host, ";branch=").concat(_this.id);

    _this.request.setHeader('via', via);

    _this.ua.newTransaction(_assertThisInitialized(_this));

    return _this;
  }

  _createClass(NonInviteClientTransaction, [{
    key: "stateChanged",
    value: function stateChanged(state) {
      this.state = state;
      this.emit('stateChanged');
    }
  }, {
    key: "send",
    value: function send() {
      var _this2 = this;

      this.stateChanged(C.STATUS_TRYING);
      this.F = setTimeout(function () {
        _this2.timer_F();
      }, Timers.TIMER_F);

      if (!this.transport.send(this.request)) {
        this.onTransportError();
      }
    }
  }, {
    key: "onTransportError",
    value: function onTransportError() {
      debugnict("transport error occurred, deleting transaction ".concat(this.id));
      clearTimeout(this.F);
      clearTimeout(this.K);
      this.stateChanged(C.STATUS_TERMINATED);
      this.ua.destroyTransaction(this);
      this.eventHandlers.onTransportError();
    }
  }, {
    key: "timer_F",
    value: function timer_F() {
      debugnict("Timer F expired for transaction ".concat(this.id));
      this.stateChanged(C.STATUS_TERMINATED);
      this.ua.destroyTransaction(this);
      this.eventHandlers.onRequestTimeout();
    }
  }, {
    key: "timer_K",
    value: function timer_K() {
      this.stateChanged(C.STATUS_TERMINATED);
      this.ua.destroyTransaction(this);
    }
  }, {
    key: "receiveResponse",
    value: function receiveResponse(response) {
      var _this3 = this;

      var 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.eventHandlers.onReceiveResponse(response);
            break;
        }
      } else {
        switch (this.state) {
          case C.STATUS_TRYING:
          case C.STATUS_PROCEEDING:
            this.stateChanged(C.STATUS_COMPLETED);
            clearTimeout(this.F);

            if (status_code === 408) {
              this.eventHandlers.onRequestTimeout();
            } else {
              this.eventHandlers.onReceiveResponse(response);
            }

            this.K = setTimeout(function () {
              _this3.timer_K();
            }, Timers.TIMER_K);
            break;

          case C.STATUS_COMPLETED:
            break;
        }
      }
    }
  }, {
    key: "C",
    get: function get() {
      return C;
    }
  }]);

  return NonInviteClientTransaction;
}(EventEmitter);

var InviteClientTransaction = /*#__PURE__*/function (_EventEmitter2) {
  _inherits(InviteClientTransaction, _EventEmitter2);

  var _super2 = _createSuper(InviteClientTransaction);

  function InviteClientTransaction(ua, transport, request, eventHandlers) {
    var _this4;

    _classCallCheck(this, InviteClientTransaction);

    _this4 = _super2.call(this);
    _this4.type = C.INVITE_CLIENT;
    _this4.id = "z9hG4bK".concat(Math.floor(Math.random() * 10000000));
    _this4.ua = ua;
    _this4.transport = transport;
    _this4.request = request;
    _this4.eventHandlers = eventHandlers;
    request.transaction = _assertThisInitialized(_this4);
    var via = "SIP/2.0/".concat(transport.via_transport);
    via += " ".concat(ua.configuration.via_host, ";branch=").concat(_this4.id);

    _this4.request.setHeader('via', via);

    _this4.ua.newTransaction(_assertThisInitialized(_this4));

    return _this4;
  }

  _createClass(InviteClientTransaction, [{
    key: "stateChanged",
    value: function stateChanged(state) {
      this.state = state;
      this.emit('stateChanged');
    }
  }, {
    key: "send",
    value: function send() {
      var _this5 = this;

      this.stateChanged(C.STATUS_CALLING);
      this.B = setTimeout(function () {
        _this5.timer_B();
      }, Timers.TIMER_B);

      if (!this.transport.send(this.request)) {
        this.onTransportError();
      }
    }
  }, {
    key: "onTransportError",
    value: function onTransportError() {
      clearTimeout(this.B);
      clearTimeout(this.D);
      clearTimeout(this.M);

      if (this.state !== C.STATUS_ACCEPTED) {
        debugict("transport error occurred, deleting transaction ".concat(this.id));
        this.eventHandlers.onTransportError();
      }

      this.stateChanged(C.STATUS_TERMINATED);
      this.ua.destroyTransaction(this);
    } // RFC 6026 7.2.

  }, {
    key: "timer_M",
    value: function timer_M() {
      debugict("Timer M expired for transaction ".concat(this.id));

      if (this.state === C.STATUS_ACCEPTED) {
        clearTimeout(this.B);
        this.stateChanged(C.STATUS_TERMINATED);
        this.ua.destroyTransaction(this);
      }
    } // RFC 3261 17.1.1.

  }, {
    key: "timer_B",
    value: function timer_B() {
      debugict("Timer B expired for transaction ".concat(this.id));

      if (this.state === C.STATUS_CALLING) {
        this.stateChanged(C.STATUS_TERMINATED);
        this.ua.destroyTransaction(this);
        this.eventHandlers.onRequestTimeout();
      }
    }
  }, {
    key: "timer_D",
    value: function timer_D() {
      debugict("Timer D expired for transaction ".concat(this.id));
      clearTimeout(this.B);
      this.stateChanged(C.STATUS_TERMINATED);
      this.ua.destroyTransaction(this);
    }
  }, {
    key: "sendACK",
    value: function sendACK(response) {
      var _this6 = this;

      var ack = new SIPMessage.OutgoingRequest(JsSIP_C.ACK, this.request.ruri, this.ua, {
        'route_set': this.request.getHeaders('route'),
        'call_id': this.request.getHeader('call-id'),
        'cseq': this.request.cseq
      });
      ack.setHeader('from', this.request.getHeader('from'));
      ack.setHeader('via', this.request.getHeader('via'));
      ack.setHeader('to', response.getHeader('to'));
      this.D = setTimeout(function () {
        _this6.timer_D();
      }, Timers.TIMER_D);
      this.transport.send(ack);
    }
  }, {
    key: "cancel",
    value: function cancel(reason) {
      // Send only if a provisional response (>100) has been received.
      if (this.state !== C.STATUS_PROCEEDING) {
        return;
      }

      var cancel = new SIPMessage.OutgoingRequest(JsSIP_C.CANCEL, this.request.ruri, this.ua, {
        'route_set': this.request.getHeaders('route'),
        'call_id': this.request.getHeader('call-id'),
        'cseq': this.request.cseq
      });
      cancel.setHeader('from', this.request.getHeader('from'));
      cancel.setHeader('via', this.request.getHeader('via'));
      cancel.setHeader('to', this.request.getHeader('to'));

      if (reason) {
        cancel.setHeader('reason', reason);
      }

      this.transport.send(cancel);
    }
  }, {
    key: "receiveResponse",
    value: function receiveResponse(response) {
      var _this7 = this;

      var 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.eventHandlers.onReceiveResponse(response);
            break;

          case C.STATUS_PROCEEDING:
            this.eventHandlers.onReceiveResponse(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 = setTimeout(function () {
              _this7.timer_M();
            }, Timers.TIMER_M);
            this.eventHandlers.onReceiveResponse(response);
            break;

          case C.STATUS_ACCEPTED:
            this.eventHandlers.onReceiveResponse(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.eventHandlers.onReceiveResponse(response);
            break;

          case C.STATUS_COMPLETED:
            this.sendACK(response);
            break;
        }
      }
    }
  }, {
    key: "C",
    get: function get() {
      return C;
    }
  }]);

  return InviteClientTransaction;
}(EventEmitter);

var AckClientTransaction = /*#__PURE__*/function (_EventEmitter3) {
  _inherits(AckClientTransaction, _EventEmitter3);

  var _super3 = _createSuper(AckClientTransaction);

  function AckClientTransaction(ua, transport, request, eventHandlers) {
    var _this8;

    _classCallCheck(this, AckClientTransaction);

    _this8 = _super3.call(this);
    _this8.id = "z9hG4bK".concat(Math.floor(Math.random() * 10000000));
    _this8.transport = transport;
    _this8.request = request;
    _this8.eventHandlers = eventHandlers;
    var via = "SIP/2.0/".concat(transport.via_transport);
    via += " ".concat(ua.configuration.via_host, ";branch=").concat(_this8.id);

    _this8.request.setHeader('via', via);

    return _this8;
  }

  _createClass(AckClientTransaction, [{
    key: "send",
    value: function send() {
      if (!this.transport.send(this.request)) {
        this.onTransportError();
      }
    }
  }, {
    key: "onTransportError",
    value: function onTransportError() {
      debugact("transport error occurred for transaction ".concat(this.id));
      this.eventHandlers.onTransportError();
    }
  }, {
    key: "C",
    get: function get() {
      return C;
    }
  }]);

  return AckClientTransaction;
}(EventEmitter);

var NonInviteServerTransaction = /*#__PURE__*/function (_EventEmitter4) {
  _inherits(NonInviteServerTransaction, _EventEmitter4);

  var _super4 = _createSuper(NonInviteServerTransaction);

  function NonInviteServerTransaction(ua, transport, request) {
    var _this9;

    _classCallCheck(this, NonInviteServerTransaction);

    _this9 = _super4.call(this);
    _this9.type = C.NON_INVITE_SERVER;
    _this9.id = request.via_branch;
    _this9.ua = ua;
    _this9.transport = transport;
    _this9.request = request;
    _this9.last_response = '';
    request.server_transaction = _assertThisInitialized(_this9);
    _this9.state = C.STATUS_TRYING;
    ua.newTransaction(_assertThisInitialized(_this9));
    return _this9;
  }

  _createClass(NonInviteServerTransaction, [{
    key: "stateChanged",
    value: function stateChanged(state) {
      this.state = state;
      this.emit('stateChanged');
    }
  }, {
    key: "timer_J",
    value: function timer_J() {
      debugnist("Timer J expired for transaction ".concat(this.id));
      this.stateChanged(C.STATUS_TERMINATED);
      this.ua.destroyTransaction(this);
    }
  }, {
    key: "onTransportError",
    value: function onTransportError() {
      if (!this.transportError) {
        this.transportError = true;
        debugnist("transport error occurred, deleting transaction ".concat(this.id));
        clearTimeout(this.J);
        this.stateChanged(C.STATUS_TERMINATED);
        this.ua.destroyTransaction(this);
      }
    }
  }, {
    key: "receiveResponse",
    value: function receiveResponse(status_code, response, onSuccess, onFailure) {
      var _this10 = 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 = setTimeout(function () {
              _this10.timer_J();
            }, Timers.TIMER_J);

            if (!this.transport.send(response)) {
              this.onTransportError();

              if (onFailure) {
                onFailure();
              }
            } else if (onSuccess) {
              onSuccess();
            }

            break;

          case C.STATUS_COMPLETED:
            break;
        }
      }
    }
  }, {
    key: "C",
    get: function get() {
      return C;
    }
  }]);

  return NonInviteServerTransaction;
}(EventEmitter);

var InviteServerTransaction = /*#__PURE__*/function (_EventEmitter5) {
  _inherits(InviteServerTransaction, _EventEmitter5);

  var _super5 = _createSuper(InviteServerTransaction);

  function InviteServerTransaction(ua, transport, request) {
    var _this11;

    _classCallCheck(this, InviteServerTransaction);

    _this11 = _super5.call(this);
    _this11.type = C.INVITE_SERVER;
    _this11.id = request.via_branch;
    _this11.ua = ua;
    _this11.transport = transport;
    _this11.request = request;
    _this11.last_response = '';
    request.server_transaction = _assertThisInitialized(_this11);
    _this11.state = C.STATUS_PROCEEDING;
    ua.newTransaction(_assertThisInitialized(_this11));
    _this11.resendProvisionalTimer = null;
    request.reply(100);
    return _this11;
  }

  _createClass(InviteServerTransaction, [{
    key: "stateChanged",
    value: function stateChanged(state) {
      this.state = state;
      this.emit('stateChanged');
    }
  }, {
    key: "timer_H",
    value: function timer_H() {
      debugist("Timer H expired for transaction ".concat(this.id));

      if (this.state === C.STATUS_COMPLETED) {
        debugist('ACK not received, dialog will be terminated');
      }

      this.stateChanged(C.STATUS_TERMINATED);
      this.ua.destroyTransaction(this);
    }
  }, {
    key: "timer_I",
    value: function timer_I() {
      this.stateChanged(C.STATUS_TERMINATED);
      this.ua.destroyTransaction(this);
    } // RFC 6026 7.1.

  }, {
    key: "timer_L",
    value: function timer_L() {
      debugist("Timer L expired for transaction ".concat(this.id));

      if (this.state === C.STATUS_ACCEPTED) {
        this.stateChanged(C.STATUS_TERMINATED);
        this.ua.destroyTransaction(this);
      }
    }
  }, {
    key: "onTransportError",
    value: function onTransportError() {
      if (!this.transportError) {
        this.transportError = true;
        debugist("transport error occurred, deleting transaction ".concat(this.id));

        if (this.resendProvisionalTimer !== null) {
          clearInterval(this.resendProvisionalTimer);
          this.resendProvisionalTimer = null;
        }

        clearTimeout(this.L);
        clearTimeout(this.H);
        clearTimeout(this.I);
        this.stateChanged(C.STATUS_TERMINATED);
        this.ua.destroyTransaction(this);
      }
    }
  }, {
    key: "resend_provisional",
    value: function resend_provisional() {
      if (!this.transport.send(this.last_response)) {
        this.onTransportError();
      }
    } // INVITE Server Transaction RFC 3261 17.2.1.

  }, {
    key: "receiveResponse",
    value: function receiveResponse(status_code, response, onSuccess, onFailure) {
      var _this12 = 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 = setInterval(function () {
            _this12.resend_provisional();
          }, 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 = setTimeout(function () {
              _this12.timer_L();
            }, Timers.TIMER_L);

            if (this.resendProvisionalTimer !== null) {
              clearInterval(this.resendProvisionalTimer);
              this.resendProvisionalTimer = null;
            }

          /* falls through */

          case C.STATUS_ACCEPTED:
            // Note that this point will be reached for proceeding this.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) {
              clearInterval(this.resendProvisionalTimer);
              this.resendProvisionalTimer = null;
            }

            if (!this.transport.send(response)) {
              this.onTransportError();

              if (onFailure) {
                onFailure();
              }
            } else {
              this.stateChanged(C.STATUS_COMPLETED);
              this.H = setTimeout(function () {
                _this12.timer_H();
              }, Timers.TIMER_H);

              if (onSuccess) {
                onSuccess();
              }
            }

            break;
        }
      }
    }
  }, {
    key: "C",
    get: function get() {
      return C;
    }
  }]);

  return InviteServerTransaction;
}(EventEmitter);
/**
 * 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
 */


function checkTransaction(_ref, request) {
  var _transactions = _ref._transactions;
  var tr;

  switch (request.method) {
    case JsSIP_C.INVITE:
      tr = _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 = _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 = setTimeout(function () {
            tr.timer_I();
          }, Timers.TIMER_I);
          return true;
        }
      } // ACK to 2XX Response.
      else {
          return false;
        }

      break;

    case JsSIP_C.CANCEL:
      tr = _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;
      }

    default:
      // Non-INVITE Server Transaction RFC 3261 17.2.2.
      tr = _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;
  }
}

module.exports = {
  C: C,
  NonInviteClientTransaction: NonInviteClientTransaction,
  InviteClientTransaction: InviteClientTransaction,
  AckClientTransaction: AckClientTransaction,
  NonInviteServerTransaction: NonInviteServerTransaction,
  InviteServerTransaction: InviteServerTransaction,
  checkTransaction: checkTransaction
};
},{"./Constants":2,"./SIPMessage":19,"./Timers":21,"debug":30,"events":29}],23:[function(require,module,exports){
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var Socket = require('./Socket');

var debug = require('debug')('JsSIP:Transport');

var debugerror = require('debug')('JsSIP:ERROR:Transport');

var JsSIP_C = require('./Constants');

debugerror.log = console.warn.bind(console);
/**
 * Constants
 */

var C = {
  // Transport status.
  STATUS_CONNECTED: 0,
  STATUS_CONNECTING: 1,
  STATUS_DISCONNECTED: 2,
  // Socket status.
  SOCKET_STATUS_READY: 0,
  SOCKET_STATUS_ERROR: 1,
  // Recovery options.
  recovery_options: {
    // minimum interval in seconds between recover attempts.
    min_interval: JsSIP_C.CONNECTION_RECOVERY_MIN_INTERVAL,
    // maximum interval in seconds between recover attempts.
    max_interval: JsSIP_C.CONNECTION_RECOVERY_MAX_INTERVAL
  }
};
/*
 * Manages one or multiple JsSIP.Socket instances.
 * Is reponsible for transport recovery logic among all socket instances.
 *
 * @socket JsSIP::Socket instance
 */

module.exports = /*#__PURE__*/function () {
  function Transport(sockets) {
    var recovery_options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : C.recovery_options;

    _classCallCheck(this, Transport);

    debug('new()');
    this.status = C.STATUS_DISCONNECTED; // Current socket.

    this.socket = null; // Socket collection.

    this.sockets = [];
    this.recovery_options = recovery_options;
    this.recover_attempts = 0;
    this.recovery_timer = null;
    this.close_requested = false;

    if (typeof sockets === 'undefined') {
      throw new TypeError('Invalid argument.' + ' undefined \'sockets\' argument');
    }

    if (!(sockets instanceof Array)) {
      sockets = [sockets];
    }

    sockets.forEach(function (socket) {
      if (!Socket.isSocket(socket.socket)) {
        throw new TypeError('Invalid argument.' + ' invalid \'JsSIP.Socket\' instance');
      }

      if (socket.weight && !Number(socket.weight)) {
        throw new TypeError('Invalid argument.' + ' \'weight\' attribute is not a number');
      }

      this.sockets.push({
        socket: socket.socket,
        weight: socket.weight || 0,
        status: C.SOCKET_STATUS_READY
      });
    }, this); // Get the socket with higher weight.

    this._getSocket();
  }
  /**
   * Instance Methods
   */


  _createClass(Transport, [{
    key: "connect",
    value: function connect() {
      debug('connect()');

      if (this.isConnected()) {
        debug('Transport is already connected');
        return;
      } else if (this.isConnecting()) {
        debug('Transport is connecting');
        return;
      }

      this.close_requested = false;
      this.status = C.STATUS_CONNECTING;
      this.onconnecting({
        socket: this.socket,
        attempts: this.recover_attempts
      });

      if (!this.close_requested) {
        // Bind socket event callbacks.
        this.socket.onconnect = this._onConnect.bind(this);
        this.socket.ondisconnect = this._onDisconnect.bind(this);
        this.socket.ondata = this._onData.bind(this);
        this.socket.connect();
      }

      return;
    }
  }, {
    key: "disconnect",
    value: function disconnect() {
      debug('close()');
      this.close_requested = true;
      this.recover_attempts = 0;
      this.status = C.STATUS_DISCONNECTED; // Clear recovery_timer.

      if (this.recovery_timer !== null) {
        clearTimeout(this.recovery_timer);
        this.recovery_timer = null;
      } // Unbind socket event callbacks.


      this.socket.onconnect = function () {};

      this.socket.ondisconnect = function () {};

      this.socket.ondata = function () {};

      this.socket.disconnect();
      this.ondisconnect({
        socket: this.socket,
        error: false
      });
    }
  }, {
    key: "send",
    value: function send(data) {
      debug('send()');

      if (!this.isConnected()) {
        debugerror('unable to send message, transport is not connected');
        return false;
      }

      var message = data.toString();
      debug("sending message:\n\n".concat(message, "\n"));
      return this.socket.send(message);
    }
  }, {
    key: "isConnected",
    value: function isConnected() {
      return this.status === C.STATUS_CONNECTED;
    }
  }, {
    key: "isConnecting",
    value: function isConnecting() {
      return this.status === C.STATUS_CONNECTING;
    }
    /**
     * Private API.
     */

  }, {
    key: "_reconnect",
    value: function _reconnect() {
      var _this = this;

      this.recover_attempts += 1;
      var k = Math.floor(Math.random() * Math.pow(2, this.recover_attempts) + 1);

      if (k < this.recovery_options.min_interval) {
        k = this.recovery_options.min_interval;
      } else if (k > this.recovery_options.max_interval) {
        k = this.recovery_options.max_interval;
      }

      debug("reconnection attempt: ".concat(this.recover_attempts, ". next connection attempt in ").concat(k, " seconds"));
      this.recovery_timer = setTimeout(function () {
        if (!_this.close_requested && !(_this.isConnected() || _this.isConnecting())) {
          // Get the next available socket with higher weight.
          _this._getSocket(); // Connect the socket.


          _this.connect();
        }
      }, k * 1000);
    }
    /**
     * get the next available socket with higher weight
     */

  }, {
    key: "_getSocket",
    value: function _getSocket() {
      var candidates = [];
      this.sockets.forEach(function (socket) {
        if (socket.status === C.SOCKET_STATUS_ERROR) {
          return; // continue the array iteration
        } else if (candidates.length === 0) {
          candidates.push(socket);
        } else if (socket.weight > candidates[0].weight) {
          candidates = [socket];
        } else if (socket.weight === candidates[0].weight) {
          candidates.push(socket);
        }
      });

      if (candidates.length === 0) {
        // All sockets have failed. reset sockets status.
        this.sockets.forEach(function (socket) {
          socket.status = C.SOCKET_STATUS_READY;
        }); // Get next available socket.

        this._getSocket();

        return;
      }

      var idx = Math.floor(Math.random() * candidates.length);
      this.socket = candidates[idx].socket;
    }
    /**
     * Socket Event Handlers
     */

  }, {
    key: "_onConnect",
    value: function _onConnect() {
      this.recover_attempts = 0;
      this.status = C.STATUS_CONNECTED; // Clear recovery_timer.

      if (this.recovery_timer !== null) {
        clearTimeout(this.recovery_timer);
        this.recovery_timer = null;
      }

      this.onconnect({
        socket: this
      });
    }
  }, {
    key: "_onDisconnect",
    value: function _onDisconnect(error, code, reason) {
      this.status = C.STATUS_DISCONNECTED;
      this.ondisconnect({
        socket: this.socket,
        error: error,
        code: code,
        reason: reason
      });

      if (this.close_requested) {
        return;
      } // Update socket status.
      else {
          this.sockets.forEach(function (socket) {
            if (this.socket === socket.socket) {
              socket.status = C.SOCKET_STATUS_ERROR;
            }
          }, this);
        }

      this._reconnect(error);
    }
  }, {
    key: "_onData",
    value: function _onData(data) {
      // CRLF Keep Alive response from server. Ignore it.
      if (data === '\r\n') {
        debug('received message with CRLF Keep Alive response');
        return;
      } // Binary message.
      else if (typeof data !== 'string') {
          try {
            data = String.fromCharCode.apply(null, new Uint8Array(data));
          } catch (evt) {
            debug('received binary message failed to be converted into string,' + ' message discarded');
            return;
          }

          debug("received binary message:\n\n".concat(data, "\n"));
        } // Text message.
        else {
            debug("received text message:\n\n".concat(data, "\n"));
          }

      this.ondata({
        transport: this,
        message: data
      });
    }
  }, {
    key: "via_transport",
    get: function get() {
      return this.socket.via_transport;
    }
  }, {
    key: "url",
    get: function get() {
      return this.socket.url;
    }
  }, {
    key: "sip_uri",
    get: function get() {
      return this.socket.sip_uri;
    }
  }]);

  return Transport;
}();
},{"./Constants":2,"./Socket":20,"debug":30}],24:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

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

var JsSIP_C = require('./Constants');

var Registrator = require('./Registrator');

var RTCSession = require('./RTCSession');

var Message = require('./Message');

var Transactions = require('./Transactions');

var Transport = require('./Transport');

var Utils = require('./Utils');

var Exceptions = require('./Exceptions');

var URI = require('./URI');

var Parser = require('./Parser');

var SIPMessage = require('./SIPMessage');

var sanityCheck = require('./sanityCheck');

var config = require('./Config');

var debug = require('debug')('JsSIP:UA');

var debugerror = require('debug')('JsSIP:ERROR:UA');

debugerror.log = console.warn.bind(console);
var 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
};
/**
 * The User-Agent class.
 * @class JsSIP.UA
 * @param {Object} configuration Configuration parameters.
 * @throws {JsSIP.Exceptions.ConfigurationError} If a configuration parameter is invalid.
 * @throws {TypeError} If no configuration is given.
 */

module.exports = /*#__PURE__*/function (_EventEmitter) {
  _inherits(UA, _EventEmitter);

  var _super = _createSuper(UA);

  _createClass(UA, null, [{
    key: "C",
    // Expose C object.
    get: function get() {
      return C;
    }
  }]);

  function UA(configuration) {
    var _this;

    _classCallCheck(this, UA);

    debug('new() [configuration:%o]', configuration);
    _this = _super.call(this);
    _this._cache = {
      credentials: {}
    };
    _this._configuration = Object.assign({}, config.settings);
    _this._dynConfiguration = {};
    _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: {}
    }; // Custom UA empty object for high level use.

    _this._data = {};
    _this._closeTimer = null; // Check configuration argument.

    if (configuration === undefined) {
      throw new TypeError('Not enough arguments');
    } // Load configuration.


    try {
      _this._loadConfig(configuration);
    } catch (e) {
      _this._status = C.STATUS_NOT_READY;
      _this._error = C.CONFIGURATION_ERROR;
      throw e;
    } // Initialize registrator.


    _this._registrator = new Registrator(_assertThisInitialized(_this));
    return _this;
  }

  _createClass(UA, [{
    key: "start",
    // =================
    //  High Level API
    // =================

    /**
     * Connect to the server if status = STATUS_INIT.
     * Resume UA after being closed.
     */
    value: function start() {
      debug('start()');

      if (this._status === C.STATUS_INIT) {
        this._transport.connect();
      } else if (this._status === C.STATUS_USER_CLOSED) {
        debug('restarting UA'); // Disconnect.

        if (this._closeTimer !== null) {
          clearTimeout(this._closeTimer);
          this._closeTimer = null;

          this._transport.disconnect();
        } // Reconnect.


        this._status = C.STATUS_INIT;

        this._transport.connect();
      } else if (this._status === C.STATUS_READY) {
        debug('UA is in READY status, not restarted');
      } else {
        debug('ERROR: connection is down, Auto-Recovery system is trying to reconnect');
      } // Set dynamic configuration.


      this._dynConfiguration.register = this._configuration.register;
    }
    /**
     * Register.
     */

  }, {
    key: "register",
    value: function register() {
      debug('register()');
      this._dynConfiguration.register = true;

      this._registrator.register();
    }
    /**
     * Unregister.
     */

  }, {
    key: "unregister",
    value: function unregister(options) {
      debug('unregister()');
      this._dynConfiguration.register = false;

      this._registrator.unregister(options);
    }
    /**
     * Get the Registrator instance.
     */

  }, {
    key: "registrator",
    value: function registrator() {
      return this._registrator;
    }
    /**
     * Registration state.
     */

  }, {
    key: "isRegistered",
    value: function isRegistered() {
      return this._registrator.registered;
    }
    /**
     * Connection state.
     */

  }, {
    key: "isConnected",
    value: function isConnected() {
      return this._transport.isConnected();
    }
    /**
     * Make an outgoing call.
     *
     * -param {String} target
     * -param {Object} [options]
     *
     * -throws {TypeError}
     *
     */

  }, {
    key: "call",
    value: function call(target, options) {
      debug('call()');
      var session = new RTCSession(this);
      session.connect(target, options);
      return session;
    }
    /**
     * Send a message.
     *
     * -param {String} target
     * -param {String} body
     * -param {Object} [options]
     *
     * -throws {TypeError}
     *
     */

  }, {
    key: "sendMessage",
    value: function sendMessage(target, body, options) {
      debug('sendMessage()');
      var message = new Message(this);
      message.send(target, body, options);
      return message;
    }
    /**
     * Terminate ongoing sessions.
     */

  }, {
    key: "terminateSessions",
    value: function terminateSessions(options) {
      debug('terminateSessions()');

      for (var idx in this._sessions) {
        if (!this._sessions[idx].isEnded()) {
          this._sessions[idx].terminate(options);
        }
      }
    }
    /**
     * Gracefully close.
     *
     */

  }, {
    key: "stop",
    value: function stop() {
      var _this2 = this;

      debug('stop()'); // Remove dynamic settings.

      this._dynConfiguration = {};

      if (this._status === C.STATUS_USER_CLOSED) {
        debug('UA already closed');
        return;
      } // Close registrator.


      this._registrator.close(); // If there are session wait a bit so CANCEL/BYE can be sent and their responses received.


      var num_sessions = Object.keys(this._sessions).length; // Run  _terminate_ on every Session.

      for (var session in this._sessions) {
        if (Object.prototype.hasOwnProperty.call(this._sessions, session)) {
          debug("closing session ".concat(session));

          try {
            this._sessions[session].terminate();
          } catch (error) {}
        }
      } // Run  _close_ on every applicant.


      for (var applicant in this._applicants) {
        if (Object.prototype.hasOwnProperty.call(this._applicants, applicant)) try {
          this._applicants[applicant].close();
        } catch (error) {}
      }

      this._status = C.STATUS_USER_CLOSED;
      var num_transactions = Object.keys(this._transactions.nict).length + Object.keys(this._transactions.nist).length + Object.keys(this._transactions.ict).length + Object.keys(this._transactions.ist).length;

      if (num_transactions === 0 && num_sessions === 0) {
        this._transport.disconnect();
      } else {
        this._closeTimer = setTimeout(function () {
          _this2._closeTimer = null;

          _this2._transport.disconnect();
        }, 2000);
      }
    }
    /**
     * Normalice a string into a valid SIP request URI
     * -param {String} target
     * -returns {JsSIP.URI|undefined}
     */

  }, {
    key: "normalizeTarget",
    value: function normalizeTarget(target) {
      return Utils.normalizeTarget(target, this._configuration.hostport_params);
    }
    /**
     * Allow retrieving configuration and autogenerated fields in runtime.
     */

  }, {
    key: "get",
    value: function get(parameter) {
      switch (parameter) {
        case 'realm':
          return this._configuration.realm;

        case 'ha1':
          return this._configuration.ha1;

        default:
          debugerror('get() | cannot get "%s" parameter in runtime', parameter);
          return undefined;
      }
    }
    /**
     * Allow configuration changes in runtime.
     * Returns true if the parameter could be set.
     */

  }, {
    key: "set",
    value: function set(parameter, value) {
      switch (parameter) {
        case 'password':
          {
            this._configuration.password = String(value);
            break;
          }

        case 'realm':
          {
            this._configuration.realm = String(value);
            break;
          }

        case 'ha1':
          {
            this._configuration.ha1 = String(value); // Delete the plain SIP password.

            this._configuration.password = null;
            break;
          }

        case 'display_name':
          {
            this._configuration.display_name = value;
            break;
          }

        default:
          debugerror('set() | cannot set "%s" parameter in runtime', parameter);
          return false;
      }

      return true;
    } // ==========================
    // Event Handlers.
    // ==========================

    /**
     * new Transaction
     */

  }, {
    key: "newTransaction",
    value: function newTransaction(transaction) {
      this._transactions[transaction.type][transaction.id] = transaction;
      this.emit('newTransaction', {
        transaction: transaction
      });
    }
    /**
     * Transaction destroyed.
     */

  }, {
    key: "destroyTransaction",
    value: function destroyTransaction(transaction) {
      delete this._transactions[transaction.type][transaction.id];
      this.emit('transactionDestroyed', {
        transaction: transaction
      });
    }
    /**
     * new Dialog
     */

  }, {
    key: "newDialog",
    value: function newDialog(dialog) {
      this._dialogs[dialog.id] = dialog;
    }
    /**
     * Dialog destroyed.
     */

  }, {
    key: "destroyDialog",
    value: function destroyDialog(dialog) {
      delete this._dialogs[dialog.id];
    }
    /**
     *  new Message
     */

  }, {
    key: "newMessage",
    value: function newMessage(message, data) {
      this._applicants[message] = message;
      this.emit('newMessage', data);
    }
    /**
     *  Message destroyed.
     */

  }, {
    key: "destroyMessage",
    value: function destroyMessage(message) {
      delete this._applicants[message];
    }
    /**
     * new RTCSession
     */

  }, {
    key: "newRTCSession",
    value: function newRTCSession(session, data) {
      this._sessions[session.id] = session;
      this.emit('newRTCSession', data);
    }
    /**
     * RTCSession destroyed.
     */

  }, {
    key: "destroyRTCSession",
    value: function destroyRTCSession(session) {
      delete this._sessions[session.id];
    }
    /**
     * Registered
     */

  }, {
    key: "registered",
    value: function registered(data) {
      this.emit('registered', data);
    }
    /**
     * Unregistered
     */

  }, {
    key: "unregistered",
    value: function unregistered(data) {
      this.emit('unregistered', data);
    }
    /**
     * Registration Failed
     */

  }, {
    key: "registrationFailed",
    value: function registrationFailed(data) {
      this.emit('registrationFailed', data);
    } // =========================
    // ReceiveRequest.
    // =========================

    /**
     * Request reception
     */

  }, {
    key: "receiveRequest",
    value: function receiveRequest(request) {
      var 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) {
        debug('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 (Transactions.checkTransaction(this, request)) {
        return;
      } // Create the server transaction.


      if (method === JsSIP_C.INVITE) {
        /* eslint-disable no-new */
        new Transactions.InviteServerTransaction(this, this._transport, request);
        /* eslint-enable no-new */
      } else if (method !== JsSIP_C.ACK && method !== JsSIP_C.CANCEL) {
        /* eslint-disable no-new */
        new Transactions.NonInviteServerTransaction(this, this._transport, request);
        /* eslint-enable no-new */
      }
      /* 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.listeners('newMessage').length === 0) {
          request.reply(405);
          return;
        }

        var message = new Message(this);
        message.init_incoming(request);
      } else if (method === JsSIP_C.INVITE) {
        // Initial INVITE.
        if (!request.to_tag && this.listeners('newRTCSession').length === 0) {
          request.reply(405);
          return;
        }
      }

      var dialog;
      var session; // Initial Request.

      if (!request.to_tag) {
        switch (method) {
          case JsSIP_C.INVITE:
            if (window.RTCPeerConnection) {
              // TODO
              if (request.hasHeader('replaces')) {
                var replaces = request.replaces;
                dialog = this._findDialog(replaces.call_id, replaces.from_tag, replaces.to_tag);

                if (dialog) {
                  session = dialog.owner;

                  if (!session.isEnded()) {
                    session.receiveRequest(request);
                  } else {
                    request.reply(603);
                  }
                } else {
                  request.reply(481);
                }
              } else {
                session = new RTCSession(this);
                session.init_incoming(request);
              }
            } else {
              debugerror('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 {
              debug('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;

          case JsSIP_C.NOTIFY:
            // Receive new sip event.
            this.emit('sipEvent', {
              event: request.event,
              request: request
            });
            request.reply(200);
            break;

          default:
            request.reply(405);
            break;
        }
      } // In-dialog request.
      else {
          dialog = this._findDialog(request.call_id, request.from_tag, request.to_tag);

          if (dialog) {
            dialog.receiveRequest(request);
          } else if (method === JsSIP_C.NOTIFY) {
            session = this._findSession(request);

            if (session) {
              session.receiveRequest(request);
            } else {
              debug('received NOTIFY request for a non existent subscription');
              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.
     */

  }, {
    key: "_findSession",
    value: function _findSession(_ref) {
      var call_id = _ref.call_id,
          from_tag = _ref.from_tag,
          to_tag = _ref.to_tag;
      var sessionIDa = call_id + from_tag;
      var sessionA = this._sessions[sessionIDa];
      var sessionIDb = call_id + to_tag;
      var 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.
     */

  }, {
    key: "_findDialog",
    value: function _findDialog(call_id, from_tag, to_tag) {
      var id = call_id + from_tag + to_tag;
      var dialog = this._dialogs[id];

      if (dialog) {
        return dialog;
      } else {
        id = call_id + to_tag + from_tag;
        dialog = this._dialogs[id];

        if (dialog) {
          return dialog;
        } else {
          return null;
        }
      }
    }
  }, {
    key: "_loadConfig",
    value: function _loadConfig(configuration) {
      // Check and load the given configuration.
      try {
        config.load(this._configuration, configuration);
      } catch (e) {
        throw e;
      } // Post Configuration Process.
      // Allow passing 0 number as display_name.


      if (this._configuration.display_name === 0) {
        this._configuration.display_name = '0';
      } // Instance-id for GRUU.


      if (!this._configuration.instance_id) {
        this._configuration.instance_id = Utils.newUUID();
      } // Jssip_id instance parameter. Static random tag of length 5.


      this._configuration.jssip_id = Utils.createRandomToken(5); // String containing this._configuration.uri without scheme and user.

      var hostport_params = this._configuration.uri.clone();

      hostport_params.user = null;
      this._configuration.hostport_params = hostport_params.toString().replace(/^sip:/i, ''); // Transport.

      try {
        this._transport = new Transport(this._configuration.sockets, {
          // Recovery options.
          max_interval: this._configuration.connection_recovery_max_interval,
          min_interval: this._configuration.connection_recovery_min_interval
        }); // Transport event callbacks.

        this._transport.onconnecting = onTransportConnecting.bind(this);
        this._transport.onconnect = onTransportConnect.bind(this);
        this._transport.ondisconnect = onTransportDisconnect.bind(this);
        this._transport.ondata = onTransportData.bind(this);
      } catch (e) {
        debugerror(e);
        throw new Exceptions.ConfigurationError('sockets', this._configuration.sockets);
      } // Remove sockets instance from configuration object.


      delete this._configuration.sockets; // Check whether authorization_user is explicitly defined.
      // Take 'this._configuration.uri.user' value if not.

      if (!this._configuration.authorization_user) {
        this._configuration.authorization_user = this._configuration.uri.user;
      } // If no 'registrar_server' is set use the 'uri' value without user portion and
      // without URI params/headers.


      if (!this._configuration.registrar_server) {
        var registrar_server = this._configuration.uri.clone();

        registrar_server.user = null;
        registrar_server.clearParams();
        registrar_server.clearHeaders();
        this._configuration.registrar_server = registrar_server;
      } // User no_answer_timeout.


      this._configuration.no_answer_timeout *= 1000; // Via Host.

      if (this._configuration.contact_uri) {
        this._configuration.via_host = this._configuration.contact_uri.host;
      } // Contact URI.
      else {
          this._configuration.contact_uri = new URI('sip', Utils.createRandomToken(8), this._configuration.via_host, null, {
            transport: 'ws'
          });
        }

      this._contact = {
        pub_gruu: null,
        temp_gruu: null,
        uri: this._configuration.contact_uri,
        toString: function toString() {
          var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
          var anonymous = options.anonymous || null;
          var outbound = options.outbound || null;
          var 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;
        }
      }; // Seal the configuration.

      var writable_parameters = ['password', 'realm', 'ha1', 'display_name', 'register'];

      for (var parameter in this._configuration) {
        if (Object.prototype.hasOwnProperty.call(this._configuration, parameter)) {
          if (writable_parameters.indexOf(parameter) !== -1) {
            Object.defineProperty(this._configuration, parameter, {
              writable: true,
              configurable: false
            });
          } else {
            Object.defineProperty(this._configuration, parameter, {
              writable: false,
              configurable: false
            });
          }
        }
      }

      debug('configuration parameters after validation:');

      for (var _parameter in this._configuration) {
        // Only show the user user configurable parameters.
        if (Object.prototype.hasOwnProperty.call(config.settings, _parameter)) {
          switch (_parameter) {
            case 'uri':
            case 'registrar_server':
              debug("- ".concat(_parameter, ": ").concat(this._configuration[_parameter]));
              break;

            case 'password':
            case 'ha1':
              debug("- ".concat(_parameter, ": NOT SHOWN"));
              break;

            default:
              debug("- ".concat(_parameter, ": ").concat(JSON.stringify(this._configuration[_parameter])));
          }
        }
      }

      return;
    }
  }, {
    key: "C",
    get: function get() {
      return C;
    }
  }, {
    key: "status",
    get: function get() {
      return this._status;
    }
  }, {
    key: "contact",
    get: function get() {
      return this._contact;
    }
  }, {
    key: "configuration",
    get: function get() {
      return this._configuration;
    }
  }, {
    key: "transport",
    get: function get() {
      return this._transport;
    }
  }]);

  return UA;
}(EventEmitter);
/**
 * Transport event handlers
 */
// Transport connecting event.


function onTransportConnecting(data) {
  this.emit('connecting', data);
} // Transport connected event.


function onTransportConnect(data) {
  if (this._status === C.STATUS_USER_CLOSED) {
    return;
  }

  this._status = C.STATUS_READY;
  this._error = null;
  this.emit('connected', data);

  if (this._dynConfiguration.register) {
    this._registrator.register();
  }
} // Transport disconnected event.


function onTransportDisconnect(data) {
  // Run _onTransportError_ callback on every client transaction using _transport_.
  var client_transactions = ['nict', 'ict', 'nist', 'ist'];

  for (var _i = 0, _client_transactions = client_transactions; _i < _client_transactions.length; _i++) {
    var type = _client_transactions[_i];

    for (var id in this._transactions[type]) {
      if (Object.prototype.hasOwnProperty.call(this._transactions[type], id)) {
        this._transactions[type][id].onTransportError();
      }
    }
  }

  this.emit('disconnected', data); // Call registrator _onTransportClosed_.

  this._registrator.onTransportClosed();

  if (this._status !== C.STATUS_USER_CLOSED) {
    this._status = C.STATUS_NOT_READY;
    this._error = C.NETWORK_ERROR;
  }
} // Transport data event.


function onTransportData(data) {
  var transport = data.transport;
  var message = data.message;
  message = Parser.parseMessage(message, this);

  if (!message) {
    return;
  }

  if (this._status === C.STATUS_USER_CLOSED && message instanceof SIPMessage.IncomingRequest) {
    return;
  } // Do some sanity check.


  if (!sanityCheck(message, this, transport)) {
    return;
  }

  if (message instanceof SIPMessage.IncomingRequest) {
    message.transport = transport;
    this.receiveRequest(message);
  } else if (message instanceof SIPMessage.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.
    */
    var transaction;

    switch (message.method) {
      case JsSIP_C.INVITE:
        transaction = this._transactions.ict[message.via_branch];

        if (transaction) {
          transaction.receiveResponse(message);
        }

        break;

      case JsSIP_C.ACK:
        // Just in case ;-).
        break;

      default:
        transaction = this._transactions.nict[message.via_branch];

        if (transaction) {
          transaction.receiveResponse(message);
        }

        break;
    }
  }
}
},{"./Config":1,"./Constants":2,"./Exceptions":6,"./Message":9,"./Parser":11,"./RTCSession":12,"./Registrator":17,"./SIPMessage":19,"./Transactions":22,"./Transport":23,"./URI":25,"./Utils":26,"./sanityCheck":28,"debug":30,"events":29}],25:[function(require,module,exports){
"use strict";

function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var JsSIP_C = require('./Constants');

var Utils = require('./Utils');

var Grammar = require('./Grammar');
/**
 * -param {String} [scheme]
 * -param {String} [user]
 * -param {String} host
 * -param {String} [port]
 * -param {Object} [parameters]
 * -param {Object} [headers]
 *
 */


module.exports = /*#__PURE__*/function () {
  _createClass(URI, null, [{
    key: "parse",

    /**
      * Parse the given string and returns a JsSIP.URI instance or undefined if
      * it is an invalid URI.
      */
    value: function parse(uri) {
      uri = Grammar.parse(uri, 'SIP_URI');

      if (uri !== -1) {
        return uri;
      } else {
        return undefined;
      }
    }
  }]);

  function URI(scheme, user, host, port) {
    var parameters = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
    var headers = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};

    _classCallCheck(this, URI);

    // Checks.
    if (!host) {
      throw new TypeError('missing or invalid "host" parameter');
    } // Initialize parameters.


    this._parameters = {};
    this._headers = {};
    this._scheme = scheme || JsSIP_C.SIP;
    this._user = user;
    this._host = host;
    this._port = port;

    for (var param in parameters) {
      if (Object.prototype.hasOwnProperty.call(parameters, param)) {
        this.setParam(param, parameters[param]);
      }
    }

    for (var header in headers) {
      if (Object.prototype.hasOwnProperty.call(headers, header)) {
        this.setHeader(header, headers[header]);
      }
    }
  }

  _createClass(URI, [{
    key: "setParam",
    value: function setParam(key, value) {
      if (key) {
        this._parameters[key.toLowerCase()] = typeof value === 'undefined' || value === null ? null : value.toString();
      }
    }
  }, {
    key: "getParam",
    value: function getParam(key) {
      if (key) {
        return this._parameters[key.toLowerCase()];
      }
    }
  }, {
    key: "hasParam",
    value: function hasParam(key) {
      if (key) {
        return this._parameters.hasOwnProperty(key.toLowerCase()) && true || false;
      }
    }
  }, {
    key: "deleteParam",
    value: function deleteParam(parameter) {
      parameter = parameter.toLowerCase();

      if (this._parameters.hasOwnProperty(parameter)) {
        var value = this._parameters[parameter];
        delete this._parameters[parameter];
        return value;
      }
    }
  }, {
    key: "clearParams",
    value: function clearParams() {
      this._parameters = {};
    }
  }, {
    key: "setHeader",
    value: function setHeader(name, value) {
      this._headers[Utils.headerize(name)] = Array.isArray(value) ? value : [value];
    }
  }, {
    key: "getHeader",
    value: function getHeader(name) {
      if (name) {
        return this._headers[Utils.headerize(name)];
      }
    }
  }, {
    key: "hasHeader",
    value: function hasHeader(name) {
      if (name) {
        return this._headers.hasOwnProperty(Utils.headerize(name)) && true || false;
      }
    }
  }, {
    key: "deleteHeader",
    value: function deleteHeader(header) {
      header = Utils.headerize(header);

      if (this._headers.hasOwnProperty(header)) {
        var value = this._headers[header];
        delete this._headers[header];
        return value;
      }
    }
  }, {
    key: "clearHeaders",
    value: function clearHeaders() {
      this._headers = {};
    }
  }, {
    key: "clone",
    value: function clone() {
      return new URI(this._scheme, this._user, this._host, this._port, JSON.parse(JSON.stringify(this._parameters)), JSON.parse(JSON.stringify(this._headers)));
    }
  }, {
    key: "toString",
    value: function toString() {
      var headers = [];
      var uri = "".concat(this._scheme, ":");

      if (this._user) {
        uri += "".concat(Utils.escapeUser(this._user), "@");
      }

      uri += this._host;

      if (this._port || this._port === 0) {
        uri += ":".concat(this._port);
      }

      for (var parameter in this._parameters) {
        if (Object.prototype.hasOwnProperty.call(this._parameters, parameter)) {
          uri += ";".concat(parameter);

          if (this._parameters[parameter] !== null) {
            uri += "=".concat(this._parameters[parameter]);
          }
        }
      }

      for (var header in this._headers) {
        if (Object.prototype.hasOwnProperty.call(this._headers, header)) {
          var _iterator = _createForOfIteratorHelper(this._headers[header]),
              _step;

          try {
            for (_iterator.s(); !(_step = _iterator.n()).done;) {
              var item = _step.value;
              headers.push("".concat(header, "=").concat(item));
            }
          } catch (err) {
            _iterator.e(err);
          } finally {
            _iterator.f();
          }
        }
      }

      if (headers.length > 0) {
        uri += "?".concat(headers.join('&'));
      }

      return uri;
    }
  }, {
    key: "toAor",
    value: function toAor(show_port) {
      var aor = "".concat(this._scheme, ":");

      if (this._user) {
        aor += "".concat(Utils.escapeUser(this._user), "@");
      }

      aor += this._host;

      if (show_port && (this._port || this._port === 0)) {
        aor += ":".concat(this._port);
      }

      return aor;
    }
  }, {
    key: "scheme",
    get: function get() {
      return this._scheme;
    },
    set: function set(value) {
      this._scheme = value.toLowerCase();
    }
  }, {
    key: "user",
    get: function get() {
      return this._user;
    },
    set: function set(value) {
      this._user = value;
    }
  }, {
    key: "host",
    get: function get() {
      return this._host;
    },
    set: function set(value) {
      this._host = value.toLowerCase();
    }
  }, {
    key: "port",
    get: function get() {
      return this._port;
    },
    set: function set(value) {
      this._port = value === 0 ? value : parseInt(value, 10) || null;
    }
  }]);

  return URI;
}();
},{"./Constants":2,"./Grammar":7,"./Utils":26}],26:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

var JsSIP_C = require('./Constants');

var URI = require('./URI');

var Grammar = require('./Grammar');

exports.str_utf8_length = function (string) {
  return unescape(encodeURIComponent(string)).length;
}; // Used by 'hasMethods'.


var isFunction = exports.isFunction = function (fn) {
  if (fn !== undefined) {
    return Object.prototype.toString.call(fn) === '[object Function]' ? true : false;
  } else {
    return false;
  }
};

exports.isString = function (str) {
  if (str !== undefined) {
    return Object.prototype.toString.call(str) === '[object String]' ? true : false;
  } else {
    return false;
  }
};

exports.isDecimal = function (num) {
  return !isNaN(num) && parseFloat(num) === parseInt(num, 10);
};

exports.isEmpty = function (value) {
  return value === null || value === '' || value === undefined || Array.isArray(value) && value.length === 0 || typeof value === 'number' && isNaN(value);
};

exports.hasMethods = function (obj) {
  for (var _len = arguments.length, methodNames = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    methodNames[_key - 1] = arguments[_key];
  }

  for (var _i = 0, _methodNames = methodNames; _i < _methodNames.length; _i++) {
    var methodName = _methodNames[_i];

    if (isFunction(obj[methodName])) {
      return false;
    }
  }

  return true;
}; // Used by 'newTag'.


var createRandomToken = exports.createRandomToken = function (size) {
  var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 32;
  var i,
      r,
      token = '';

  for (i = 0; i < size; i++) {
    r = Math.random() * base | 0;
    token += r.toString(base);
  }

  return token;
};

exports.newTag = function () {
  return createRandomToken(10);
}; // https://stackoverflow.com/users/109538/broofa.


exports.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;
};

exports.hostType = function (host) {
  if (!host) {
    return;
  } else {
    host = Grammar.parse(host, 'host');

    if (host !== -1) {
      return host.host_type;
    }
  }
};
/**
* Hex-escape a SIP URI user.
* Don't hex-escape ':' (%3A), '+' (%2B), '?' (%3F"), '/' (%2F).
*
* Used by 'normalizeTarget'.
*/


var escapeUser = exports.escapeUser = function (user) {
  return encodeURIComponent(decodeURIComponent(user)).replace(/%3A/ig, ':').replace(/%2B/ig, '+').replace(/%3F/ig, '?').replace(/%2F/ig, '/');
};
/**
* 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.
*/


exports.normalizeTarget = function (target, domain) {
  // If no target is given then raise an error.
  if (!target) {
    return; // If a URI instance is given then return it.
  } else if (target instanceof 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') {
    var target_array = target.split('@');
    var target_user;
    var target_domain;

    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 = "".concat(JsSIP_C.SIP, ":").concat(escapeUser(target_user), "@").concat(target_domain); // Finally parse the resulting URI.

    var uri;

    if (uri = URI.parse(target)) {
      return uri;
    } else {
      return;
    }
  } else {
    return;
  }
};

exports.headerize = function (string) {
  var exceptions = {
    'Call-Id': 'Call-ID',
    'Cseq': 'CSeq',
    'Www-Authenticate': 'WWW-Authenticate'
  };
  var name = string.toLowerCase().replace(/_/g, '-').split('-');
  var hname = '';
  var parts = name.length;
  var 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;
};

exports.sipErrorCause = function (status_code) {
  for (var 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 (https://tools.ietf.org/html/rfc5735)
*/


exports.getRandomTestNetIP = function () {
  function getOctet(from, to) {
    return Math.floor(Math.random() * (to - from + 1) + from);
  }

  return "192.0.2.".concat(getOctet(1, 254));
}; // MD5 (Message-Digest Algorithm) https://www.webtoolkit.info.


exports.calculateMD5 = function (string) {
  function rotateLeft(lValue, iShiftBits) {
    return lValue << iShiftBits | lValue >>> 32 - iShiftBits;
  }

  function addUnsigned(lX, lY) {
    var lX8 = lX & 0x80000000;
    var lY8 = lY & 0x80000000;
    var lX4 = lX & 0x40000000;
    var lY4 = lY & 0x40000000;
    var 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 doF(x, y, z) {
    return x & y | ~x & z;
  }

  function doG(x, y, z) {
    return x & z | y & ~z;
  }

  function doH(x, y, z) {
    return x ^ y ^ z;
  }

  function doI(x, y, z) {
    return y ^ (x | ~z);
  }

  function doFF(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(doF(b, c, d), x), ac));
    return addUnsigned(rotateLeft(a, s), b);
  }

  function doGG(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(doG(b, c, d), x), ac));
    return addUnsigned(rotateLeft(a, s), b);
  }

  function doHH(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(doH(b, c, d), x), ac));
    return addUnsigned(rotateLeft(a, s), b);
  }

  function doII(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(doI(b, c, d), x), ac));
    return addUnsigned(rotateLeft(a, s), b);
  }

  function convertToWordArray(str) {
    var lWordCount;
    var lMessageLength = str.length;
    var lNumberOfWords_temp1 = lMessageLength + 8;
    var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - lNumberOfWords_temp1 % 64) / 64;
    var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
    var lWordArray = new 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] | str.charCodeAt(lByteCount) << lBytePosition;
      lByteCount++;
    }

    lWordCount = (lByteCount - lByteCount % 4) / 4;
    lBytePosition = lByteCount % 4 * 8;
    lWordArray[lWordCount] = lWordArray[lWordCount] | 0x80 << lBytePosition;
    lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
    lWordArray[lNumberOfWords - 1] = lMessageLength >>> 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".concat(lByte.toString(16));
      wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length - 2, 2);
    }

    return wordToHexValue;
  }

  function utf8Encode(str) {
    str = str.replace(/\r\n/g, '\n');
    var utftext = '';

    for (var n = 0; n < str.length; n++) {
      var _c = str.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 < x.length; k += 16) {
    AA = a;
    BB = b;
    CC = c;
    DD = d;
    a = doFF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
    d = doFF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
    c = doFF(c, d, a, b, x[k + 2], S13, 0x242070DB);
    b = doFF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
    a = doFF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
    d = doFF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
    c = doFF(c, d, a, b, x[k + 6], S13, 0xA8304613);
    b = doFF(b, c, d, a, x[k + 7], S14, 0xFD469501);
    a = doFF(a, b, c, d, x[k + 8], S11, 0x698098D8);
    d = doFF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
    c = doFF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
    b = doFF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
    a = doFF(a, b, c, d, x[k + 12], S11, 0x6B901122);
    d = doFF(d, a, b, c, x[k + 13], S12, 0xFD987193);
    c = doFF(c, d, a, b, x[k + 14], S13, 0xA679438E);
    b = doFF(b, c, d, a, x[k + 15], S14, 0x49B40821);
    a = doGG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
    d = doGG(d, a, b, c, x[k + 6], S22, 0xC040B340);
    c = doGG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
    b = doGG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
    a = doGG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
    d = doGG(d, a, b, c, x[k + 10], S22, 0x2441453);
    c = doGG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
    b = doGG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
    a = doGG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
    d = doGG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
    c = doGG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
    b = doGG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
    a = doGG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
    d = doGG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
    c = doGG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
    b = doGG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
    a = doHH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
    d = doHH(d, a, b, c, x[k + 8], S32, 0x8771F681);
    c = doHH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
    b = doHH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
    a = doHH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
    d = doHH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
    c = doHH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
    b = doHH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
    a = doHH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
    d = doHH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
    c = doHH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
    b = doHH(b, c, d, a, x[k + 6], S34, 0x4881D05);
    a = doHH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
    d = doHH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
    c = doHH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
    b = doHH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
    a = doII(a, b, c, d, x[k + 0], S41, 0xF4292244);
    d = doII(d, a, b, c, x[k + 7], S42, 0x432AFF97);
    c = doII(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
    b = doII(b, c, d, a, x[k + 5], S44, 0xFC93A039);
    a = doII(a, b, c, d, x[k + 12], S41, 0x655B59C3);
    d = doII(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
    c = doII(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
    b = doII(b, c, d, a, x[k + 1], S44, 0x85845DD1);
    a = doII(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
    d = doII(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
    c = doII(c, d, a, b, x[k + 6], S43, 0xA3014314);
    b = doII(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
    a = doII(a, b, c, d, x[k + 4], S41, 0xF7537E82);
    d = doII(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
    c = doII(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
    b = doII(b, c, d, a, x[k + 9], S44, 0xEB86D391);
    a = addUnsigned(a, AA);
    b = addUnsigned(b, BB);
    c = addUnsigned(c, CC);
    d = addUnsigned(d, DD);
  }

  var temp = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
  return temp.toLowerCase();
};

exports.closeMediaStream = function (stream) {
  if (!stream) {
    return;
  } // Latest spec states that MediaStream has no stop() method and instead must
  // call stop() on every MediaStreamTrack.


  try {
    var tracks;

    if (stream.getTracks) {
      tracks = stream.getTracks();

      var _iterator = _createForOfIteratorHelper(tracks),
          _step;

      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var track = _step.value;
          track.stop();
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
    } else {
      tracks = stream.getAudioTracks();

      var _iterator2 = _createForOfIteratorHelper(tracks),
          _step2;

      try {
        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
          var _track = _step2.value;

          _track.stop();
        }
      } catch (err) {
        _iterator2.e(err);
      } finally {
        _iterator2.f();
      }

      tracks = stream.getVideoTracks();

      var _iterator3 = _createForOfIteratorHelper(tracks),
          _step3;

      try {
        for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
          var _track2 = _step3.value;

          _track2.stop();
        }
      } catch (err) {
        _iterator3.e(err);
      } finally {
        _iterator3.f();
      }
    }
  } catch (error) {
    // Deprecated by the spec, but still in use.
    // NOTE: In Temasys IE plugin stream.stop is a callable 'object'.
    if (typeof stream.stop === 'function' || _typeof(stream.stop) === 'object') {
      stream.stop();
    }
  }
};

exports.cloneArray = function (array) {
  return array && array.slice() || [];
};

exports.cloneObject = function (obj) {
  var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  return obj && Object.assign({}, obj) || fallback;
};
},{"./Constants":2,"./Grammar":7,"./URI":25}],27:[function(require,module,exports){
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var Grammar = require('./Grammar');

var debug = require('debug')('JsSIP:WebSocketInterface');

var debugerror = require('debug')('JsSIP:ERROR:WebSocketInterface');

debugerror.log = console.warn.bind(console);

module.exports = /*#__PURE__*/function () {
  function WebSocketInterface(url) {
    _classCallCheck(this, WebSocketInterface);

    debug('new() [url:"%s"]', url);
    this._url = url;
    this._sip_uri = null;
    this._via_transport = null;
    this._ws = null;
    var parsed_url = Grammar.parse(url, 'absoluteURI');

    if (parsed_url === -1) {
      debugerror("invalid WebSocket URI: ".concat(url));
      throw new TypeError("Invalid argument: ".concat(url));
    } else if (parsed_url.scheme !== 'wss' && parsed_url.scheme !== 'ws') {
      debugerror("invalid WebSocket URI scheme: ".concat(parsed_url.scheme));
      throw new TypeError("Invalid argument: ".concat(url));
    } else {
      this._sip_uri = "sip:".concat(parsed_url.host).concat(parsed_url.port ? ":".concat(parsed_url.port) : '', ";transport=ws");
      this._via_transport = parsed_url.scheme.toUpperCase();
    }
  }

  _createClass(WebSocketInterface, [{
    key: "connect",
    value: function connect() {
      debug('connect()');

      if (this.isConnected()) {
        debug("WebSocket ".concat(this._url, " is already connected"));
        return;
      } else if (this.isConnecting()) {
        debug("WebSocket ".concat(this._url, " is connecting"));
        return;
      }

      if (this._ws) {
        this.disconnect();
      }

      debug("connecting to WebSocket ".concat(this._url));

      try {
        this._ws = new WebSocket(this._url, 'sip');
        this._ws.binaryType = 'arraybuffer';
        this._ws.onopen = this._onOpen.bind(this);
        this._ws.onclose = this._onClose.bind(this);
        this._ws.onmessage = this._onMessage.bind(this);
        this._ws.onerror = this._onError.bind(this);
      } catch (e) {
        this._onError(e);
      }
    }
  }, {
    key: "disconnect",
    value: function disconnect() {
      debug('disconnect()');

      if (this._ws) {
        // Unbind websocket event callbacks.
        this._ws.onopen = function () {};

        this._ws.onclose = function () {};

        this._ws.onmessage = function () {};

        this._ws.onerror = function () {};

        this._ws.close();

        this._ws = null;
      }
    }
  }, {
    key: "send",
    value: function send(message) {
      debug('send()');

      if (this.isConnected()) {
        this._ws.send(message);

        return true;
      } else {
        debugerror('unable to send message, WebSocket is not open');
        return false;
      }
    }
  }, {
    key: "isConnected",
    value: function isConnected() {
      return this._ws && this._ws.readyState === this._ws.OPEN;
    }
  }, {
    key: "isConnecting",
    value: function isConnecting() {
      return this._ws && this._ws.readyState === this._ws.CONNECTING;
    }
    /**
     * WebSocket Event Handlers
     */

  }, {
    key: "_onOpen",
    value: function _onOpen() {
      debug("WebSocket ".concat(this._url, " connected"));
      this.onconnect();
    }
  }, {
    key: "_onClose",
    value: function _onClose(_ref) {
      var wasClean = _ref.wasClean,
          code = _ref.code,
          reason = _ref.reason;
      debug("WebSocket ".concat(this._url, " closed"));

      if (wasClean === false) {
        debug('WebSocket abrupt disconnection');
      }

      var data = {
        socket: this,
        error: !wasClean,
        code: code,
        reason: reason
      };
      this.ondisconnect(data);
    }
  }, {
    key: "_onMessage",
    value: function _onMessage(_ref2) {
      var data = _ref2.data;
      debug('received WebSocket message');
      this.ondata(data);
    }
  }, {
    key: "_onError",
    value: function _onError(e) {
      debugerror("WebSocket ".concat(this._url, " error: ").concat(e));
    }
  }, {
    key: "via_transport",
    get: function get() {
      return this._via_transport;
    },
    set: function set(value) {
      this._via_transport = value.toUpperCase();
    }
  }, {
    key: "sip_uri",
    get: function get() {
      return this._sip_uri;
    }
  }, {
    key: "url",
    get: function get() {
      return this._url;
    }
  }]);

  return WebSocketInterface;
}();
},{"./Grammar":7,"debug":30}],28:[function(require,module,exports){
"use strict";

function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

var JsSIP_C = require('./Constants');

var SIPMessage = require('./SIPMessage');

var Utils = require('./Utils');

var debug = require('debug')('JsSIP:sanityCheck'); // Checks for requests and responses.


var all = [minimumHeaders]; // Checks for requests.

var requests = [rfc3261_8_2_2_1, rfc3261_16_3_4, rfc3261_18_3_request, rfc3261_8_2_2_2]; // Checks for responses.

var responses = [rfc3261_8_1_3_3, rfc3261_18_3_response]; // local variables.

var message;
var ua;
var transport;

module.exports = function (m, u, t) {
  message = m;
  ua = u;
  transport = t;

  var _iterator = _createForOfIteratorHelper(all),
      _step;

  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var _check2 = _step.value;

      if (_check2() === false) {
        return false;
      }
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }

  if (message instanceof SIPMessage.IncomingRequest) {
    var _iterator2 = _createForOfIteratorHelper(requests),
        _step2;

    try {
      for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
        var check = _step2.value;

        if (check() === false) {
          return false;
        }
      }
    } catch (err) {
      _iterator2.e(err);
    } finally {
      _iterator2.f();
    }
  } else if (message instanceof SIPMessage.IncomingResponse) {
    var _iterator3 = _createForOfIteratorHelper(responses),
        _step3;

    try {
      for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
        var _check = _step3.value;

        if (_check() === false) {
          return false;
        }
      }
    } catch (err) {
      _iterator3.e(err);
    } finally {
      _iterator3.f();
    }
  } // Everything is OK.


  return true;
};
/*
 * Sanity Check for incoming Messages
 *
 * Requests:
 *  - _rfc3261_8_2_2_1_ Receive a Request with a non supported URI scheme
 *  - _rfc3261_16_3_4_ Receive a Request already sent by us
 *   Does not look at via sent-by but at jssip_id, which is inserted as
 *   a prefix in all initial requests generated by the ua
 *  - _rfc3261_18_3_request_ Body Content-Length
 *  - _rfc3261_8_2_2_2_ Merged Requests
 *
 * Responses:
 *  - _rfc3261_8_1_3_3_ Multiple Via headers
 *  - _rfc3261_18_3_response_ Body Content-Length
 *
 * All:
 *  - Minimum headers in a SIP message
 */
// Sanity Check functions for requests.


function rfc3261_8_2_2_1() {
  if (message.s('to').uri.scheme !== 'sip') {
    reply(416);
    return false;
  }
}

function rfc3261_16_3_4() {
  if (!message.to_tag) {
    if (message.call_id.substr(0, 5) === ua.configuration.jssip_id) {
      reply(482);
      return false;
    }
  }
}

function rfc3261_18_3_request() {
  var len = Utils.str_utf8_length(message.body);
  var contentLength = message.getHeader('content-length');

  if (len < contentLength) {
    reply(400);
    return false;
  }
}

function rfc3261_8_2_2_2() {
  var fromTag = message.from_tag;
  var call_id = message.call_id;
  var cseq = message.cseq;
  var tr; // Accept any in-dialog request.

  if (message.to_tag) {
    return;
  } // INVITE request.


  if (message.method === JsSIP_C.INVITE) {
    // If the branch matches the key of any IST then assume it is a retransmission
    // and ignore the INVITE.
    // TODO: we should reply the last response.
    if (ua._transactions.ist[message.via_branch]) {
      return false;
    } // Otherwise check whether it is a merged request.
    else {
        for (var transaction in ua._transactions.ist) {
          if (Object.prototype.hasOwnProperty.call(ua._transactions.ist, transaction)) {
            tr = ua._transactions.ist[transaction];

            if (tr.request.from_tag === fromTag && tr.request.call_id === call_id && tr.request.cseq === cseq) {
              reply(482);
              return false;
            }
          }
        }
      }
  } // Non INVITE request.
  // If the branch matches the key of any NIST then assume it is a retransmission
  // and ignore the request.
  // TODO: we should reply the last response.
  else if (ua._transactions.nist[message.via_branch]) {
      return false;
    } // Otherwise check whether it is a merged request.
    else {
        for (var _transaction in ua._transactions.nist) {
          if (Object.prototype.hasOwnProperty.call(ua._transactions.nist, _transaction)) {
            tr = ua._transactions.nist[_transaction];

            if (tr.request.from_tag === fromTag && tr.request.call_id === call_id && tr.request.cseq === cseq) {
              reply(482);
              return false;
            }
          }
        }
      }
} // Sanity Check functions for responses.


function rfc3261_8_1_3_3() {
  if (message.getHeaders('via').length > 1) {
    debug('more than one Via header field present in the response, dropping the response');
    return false;
  }
}

function rfc3261_18_3_response() {
  var len = Utils.str_utf8_length(message.body),
      contentLength = message.getHeader('content-length');

  if (len < contentLength) {
    debug('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'];

  for (var _i = 0, _mandatoryHeaders = mandatoryHeaders; _i < _mandatoryHeaders.length; _i++) {
    var header = _mandatoryHeaders[_i];

    if (!message.hasHeader(header)) {
      debug("missing mandatory header field : ".concat(header, ", dropping the response"));
      return false;
    }
  }
} // Reply.


function reply(status_code) {
  var vias = message.getHeaders('via');
  var to;
  var response = "SIP/2.0 ".concat(status_code, " ").concat(JsSIP_C.REASON_PHRASE[status_code], "\r\n");

  var _iterator4 = _createForOfIteratorHelper(vias),
      _step4;

  try {
    for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
      var via = _step4.value;
      response += "Via: ".concat(via, "\r\n");
    }
  } catch (err) {
    _iterator4.e(err);
  } finally {
    _iterator4.f();
  }

  to = message.getHeader('To');

  if (!message.to_tag) {
    to += ";tag=".concat(Utils.newTag());
  }

  response += "To: ".concat(to, "\r\n");
  response += "From: ".concat(message.getHeader('From'), "\r\n");
  response += "Call-ID: ".concat(message.call_id, "\r\n");
  response += "CSeq: ".concat(message.cseq, " ").concat(message.method, "\r\n");
  response += '\r\n';
  transport.send(response);
}
},{"./Constants":2,"./SIPMessage":19,"./Utils":26,"debug":30}],29:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var objectCreate = Object.create || objectCreatePolyfill
var objectKeys = Object.keys || objectKeysPolyfill
var bind = Function.prototype.bind || functionBindPolyfill

function EventEmitter() {
  if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) {
    this._events = objectCreate(null);
    this._eventsCount = 0;
  }

  this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;

// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;

EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;

// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
var defaultMaxListeners = 10;

var hasDefineProperty;
try {
  var o = {};
  if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 });
  hasDefineProperty = o.x === 0;
} catch (err) { hasDefineProperty = false }
if (hasDefineProperty) {
  Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
    enumerable: true,
    get: function() {
      return defaultMaxListeners;
    },
    set: function(arg) {
      // check whether the input is a positive number (whose value is zero or
      // greater and not a NaN).
      if (typeof arg !== 'number' || arg < 0 || arg !== arg)
        throw new TypeError('"defaultMaxListeners" must be a positive number');
      defaultMaxListeners = arg;
    }
  });
} else {
  EventEmitter.defaultMaxListeners = defaultMaxListeners;
}

// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
  if (typeof n !== 'number' || n < 0 || isNaN(n))
    throw new TypeError('"n" argument must be a positive number');
  this._maxListeners = n;
  return this;
};

function $getMaxListeners(that) {
  if (that._maxListeners === undefined)
    return EventEmitter.defaultMaxListeners;
  return that._maxListeners;
}

EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
  return $getMaxListeners(this);
};

// These standalone emit* functions are used to optimize calling of event
// handlers for fast cases because emit() itself often has a variable number of
// arguments and can be deoptimized because of that. These functions always have
// the same number of arguments and thus do not get deoptimized, so the code
// inside them can execute faster.
function emitNone(handler, isFn, self) {
  if (isFn)
    handler.call(self);
  else {
    var len = handler.length;
    var listeners = arrayClone(handler, len);
    for (var i = 0; i < len; ++i)
      listeners[i].call(self);
  }
}
function emitOne(handler, isFn, self, arg1) {
  if (isFn)
    handler.call(self, arg1);
  else {
    var len = handler.length;
    var listeners = arrayClone(handler, len);
    for (var i = 0; i < len; ++i)
      listeners[i].call(self, arg1);
  }
}
function emitTwo(handler, isFn, self, arg1, arg2) {
  if (isFn)
    handler.call(self, arg1, arg2);
  else {
    var len = handler.length;
    var listeners = arrayClone(handler, len);
    for (var i = 0; i < len; ++i)
      listeners[i].call(self, arg1, arg2);
  }
}
function emitThree(handler, isFn, self, arg1, arg2, arg3) {
  if (isFn)
    handler.call(self, arg1, arg2, arg3);
  else {
    var len = handler.length;
    var listeners = arrayClone(handler, len);
    for (var i = 0; i < len; ++i)
      listeners[i].call(self, arg1, arg2, arg3);
  }
}

function emitMany(handler, isFn, self, args) {
  if (isFn)
    handler.apply(self, args);
  else {
    var len = handler.length;
    var listeners = arrayClone(handler, len);
    for (var i = 0; i < len; ++i)
      listeners[i].apply(self, args);
  }
}

EventEmitter.prototype.emit = function emit(type) {
  var er, handler, len, args, i, events;
  var doError = (type === 'error');

  events = this._events;
  if (events)
    doError = (doError && events.error == null);
  else if (!doError)
    return false;

  // If there is no 'error' event listener then throw.
  if (doError) {
    if (arguments.length > 1)
      er = arguments[1];
    if (er instanceof Error) {
      throw er; // Unhandled 'error' event
    } else {
      // At least give some kind of context to the user
      var err = new Error('Unhandled "error" event. (' + er + ')');
      err.context = er;
      throw err;
    }
    return false;
  }

  handler = events[type];

  if (!handler)
    return false;

  var isFn = typeof handler === 'function';
  len = arguments.length;
  switch (len) {
      // fast cases
    case 1:
      emitNone(handler, isFn, this);
      break;
    case 2:
      emitOne(handler, isFn, this, arguments[1]);
      break;
    case 3:
      emitTwo(handler, isFn, this, arguments[1], arguments[2]);
      break;
    case 4:
      emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
      break;
      // slower
    default:
      args = new Array(len - 1);
      for (i = 1; i < len; i++)
        args[i - 1] = arguments[i];
      emitMany(handler, isFn, this, args);
  }

  return true;
};

function _addListener(target, type, listener, prepend) {
  var m;
  var events;
  var existing;

  if (typeof listener !== 'function')
    throw new TypeError('"listener" argument must be a function');

  events = target._events;
  if (!events) {
    events = target._events = objectCreate(null);
    target._eventsCount = 0;
  } else {
    // To avoid recursion in the case that type === "newListener"! Before
    // adding it to the listeners, first emit "newListener".
    if (events.newListener) {
      target.emit('newListener', type,
          listener.listener ? listener.listener : listener);

      // Re-assign `events` because a newListener handler could have caused the
      // this._events to be assigned to a new object
      events = target._events;
    }
    existing = events[type];
  }

  if (!existing) {
    // Optimize the case of one listener. Don't need the extra array object.
    existing = events[type] = listener;
    ++target._eventsCount;
  } else {
    if (typeof existing === 'function') {
      // Adding the second element, need to change to array.
      existing = events[type] =
          prepend ? [listener, existing] : [existing, listener];
    } else {
      // If we've already got an array, just append.
      if (prepend) {
        existing.unshift(listener);
      } else {
        existing.push(listener);
      }
    }

    // Check for listener leak
    if (!existing.warned) {
      m = $getMaxListeners(target);
      if (m && m > 0 && existing.length > m) {
        existing.warned = true;
        var w = new Error('Possible EventEmitter memory leak detected. ' +
            existing.length + ' "' + String(type) + '" listeners ' +
            'added. Use emitter.setMaxListeners() to ' +
            'increase limit.');
        w.name = 'MaxListenersExceededWarning';
        w.emitter = target;
        w.type = type;
        w.count = existing.length;
        if (typeof console === 'object' && console.warn) {
          console.warn('%s: %s', w.name, w.message);
        }
      }
    }
  }

  return target;
}

EventEmitter.prototype.addListener = function addListener(type, listener) {
  return _addListener(this, type, listener, false);
};

EventEmitter.prototype.on = EventEmitter.prototype.addListener;

EventEmitter.prototype.prependListener =
    function prependListener(type, listener) {
      return _addListener(this, type, listener, true);
    };

function onceWrapper() {
  if (!this.fired) {
    this.target.removeListener(this.type, this.wrapFn);
    this.fired = true;
    switch (arguments.length) {
      case 0:
        return this.listener.call(this.target);
      case 1:
        return this.listener.call(this.target, arguments[0]);
      case 2:
        return this.listener.call(this.target, arguments[0], arguments[1]);
      case 3:
        return this.listener.call(this.target, arguments[0], arguments[1],
            arguments[2]);
      default:
        var args = new Array(arguments.length);
        for (var i = 0; i < args.length; ++i)
          args[i] = arguments[i];
        this.listener.apply(this.target, args);
    }
  }
}

function _onceWrap(target, type, listener) {
  var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
  var wrapped = bind.call(onceWrapper, state);
  wrapped.listener = listener;
  state.wrapFn = wrapped;
  return wrapped;
}

EventEmitter.prototype.once = function once(type, listener) {
  if (typeof listener !== 'function')
    throw new TypeError('"listener" argument must be a function');
  this.on(type, _onceWrap(this, type, listener));
  return this;
};

EventEmitter.prototype.prependOnceListener =
    function prependOnceListener(type, listener) {
      if (typeof listener !== 'function')
        throw new TypeError('"listener" argument must be a function');
      this.prependListener(type, _onceWrap(this, type, listener));
      return this;
    };

// Emits a 'removeListener' event if and only if the listener was removed.
EventEmitter.prototype.removeListener =
    function removeListener(type, listener) {
      var list, events, position, i, originalListener;

      if (typeof listener !== 'function')
        throw new TypeError('"listener" argument must be a function');

      events = this._events;
      if (!events)
        return this;

      list = events[type];
      if (!list)
        return this;

      if (list === listener || list.listener === listener) {
        if (--this._eventsCount === 0)
          this._events = objectCreate(null);
        else {
          delete events[type];
          if (events.removeListener)
            this.emit('removeListener', type, list.listener || listener);
        }
      } else if (typeof list !== 'function') {
        position = -1;

        for (i = list.length - 1; i >= 0; i--) {
          if (list[i] === listener || list[i].listener === listener) {
            originalListener = list[i].listener;
            position = i;
            break;
          }
        }

        if (position < 0)
          return this;

        if (position === 0)
          list.shift();
        else
          spliceOne(list, position);

        if (list.length === 1)
          events[type] = list[0];

        if (events.removeListener)
          this.emit('removeListener', type, originalListener || listener);
      }

      return this;
    };

EventEmitter.prototype.removeAllListeners =
    function removeAllListeners(type) {
      var listeners, events, i;

      events = this._events;
      if (!events)
        return this;

      // not listening for removeListener, no need to emit
      if (!events.removeListener) {
        if (arguments.length === 0) {
          this._events = objectCreate(null);
          this._eventsCount = 0;
        } else if (events[type]) {
          if (--this._eventsCount === 0)
            this._events = objectCreate(null);
          else
            delete events[type];
        }
        return this;
      }

      // emit removeListener for all listeners on all events
      if (arguments.length === 0) {
        var keys = objectKeys(events);
        var key;
        for (i = 0; i < keys.length; ++i) {
          key = keys[i];
          if (key === 'removeListener') continue;
          this.removeAllListeners(key);
        }
        this.removeAllListeners('removeListener');
        this._events = objectCreate(null);
        this._eventsCount = 0;
        return this;
      }

      listeners = events[type];

      if (typeof listeners === 'function') {
        this.removeListener(type, listeners);
      } else if (listeners) {
        // LIFO order
        for (i = listeners.length - 1; i >= 0; i--) {
          this.removeListener(type, listeners[i]);
        }
      }

      return this;
    };

function _listeners(target, type, unwrap) {
  var events = target._events;

  if (!events)
    return [];

  var evlistener = events[type];
  if (!evlistener)
    return [];

  if (typeof evlistener === 'function')
    return unwrap ? [evlistener.listener || evlistener] : [evlistener];

  return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
}

EventEmitter.prototype.listeners = function listeners(type) {
  return _listeners(this, type, true);
};

EventEmitter.prototype.rawListeners = function rawListeners(type) {
  return _listeners(this, type, false);
};

EventEmitter.listenerCount = function(emitter, type) {
  if (typeof emitter.listenerCount === 'function') {
    return emitter.listenerCount(type);
  } else {
    return listenerCount.call(emitter, type);
  }
};

EventEmitter.prototype.listenerCount = listenerCount;
function listenerCount(type) {
  var events = this._events;

  if (events) {
    var evlistener = events[type];

    if (typeof evlistener === 'function') {
      return 1;
    } else if (evlistener) {
      return evlistener.length;
    }
  }

  return 0;
}

EventEmitter.prototype.eventNames = function eventNames() {
  return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
};

// About 1.5x faster than the two-arg version of Array#splice().
function spliceOne(list, index) {
  for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
    list[i] = list[k];
  list.pop();
}

function arrayClone(arr, n) {
  var copy = new Array(n);
  for (var i = 0; i < n; ++i)
    copy[i] = arr[i];
  return copy;
}

function unwrapListeners(arr) {
  var ret = new Array(arr.length);
  for (var i = 0; i < ret.length; ++i) {
    ret[i] = arr[i].listener || arr[i];
  }
  return ret;
}

function objectCreatePolyfill(proto) {
  var F = function() {};
  F.prototype = proto;
  return new F;
}
function objectKeysPolyfill(obj) {
  var keys = [];
  for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) {
    keys.push(k);
  }
  return k;
}
function functionBindPolyfill(context) {
  var fn = this;
  return function () {
    return fn.apply(context, arguments);
  };
}

},{}],30:[function(require,module,exports){
(function (process){
/* eslint-env browser */

/**
 * This is the web browser implementation of `debug()`.
 */

exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = localstorage();

/**
 * Colors.
 */

exports.colors = [
  '#0000CC',
  '#0000FF',
  '#0033CC',
  '#0033FF',
  '#0066CC',
  '#0066FF',
  '#0099CC',
  '#0099FF',
  '#00CC00',
  '#00CC33',
  '#00CC66',
  '#00CC99',
  '#00CCCC',
  '#00CCFF',
  '#3300CC',
  '#3300FF',
  '#3333CC',
  '#3333FF',
  '#3366CC',
  '#3366FF',
  '#3399CC',
  '#3399FF',
  '#33CC00',
  '#33CC33',
  '#33CC66',
  '#33CC99',
  '#33CCCC',
  '#33CCFF',
  '#6600CC',
  '#6600FF',
  '#6633CC',
  '#6633FF',
  '#66CC00',
  '#66CC33',
  '#9900CC',
  '#9900FF',
  '#9933CC',
  '#9933FF',
  '#99CC00',
  '#99CC33',
  '#CC0000',
  '#CC0033',
  '#CC0066',
  '#CC0099',
  '#CC00CC',
  '#CC00FF',
  '#CC3300',
  '#CC3333',
  '#CC3366',
  '#CC3399',
  '#CC33CC',
  '#CC33FF',
  '#CC6600',
  '#CC6633',
  '#CC9900',
  '#CC9933',
  '#CCCC00',
  '#CCCC33',
  '#FF0000',
  '#FF0033',
  '#FF0066',
  '#FF0099',
  '#FF00CC',
  '#FF00FF',
  '#FF3300',
  '#FF3333',
  '#FF3366',
  '#FF3399',
  '#FF33CC',
  '#FF33FF',
  '#FF6600',
  '#FF6633',
  '#FF9900',
  '#FF9933',
  '#FFCC00',
  '#FFCC33'
];

/**
 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
 * and the Firebug extension (any Firefox version) are known
 * to support "%c" CSS customizations.
 *
 * TODO: add a `localStorage` variable to explicitly enable/disable colors
 */

// eslint-disable-next-line complexity
function useColors() {
  // NB: In an Electron preload script, document will be defined but not fully
  // initialized. Since we know we're in Chrome, we'll just detect this case
  // explicitly
  if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
    return true;
  }

  // Internet Explorer and Edge do not support colors.
  if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
    return false;
  }

  // Is webkit? http://stackoverflow.com/a/16459606/376773
  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
  return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
    // Is firebug? http://stackoverflow.com/a/398120/376773
    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
    // Is firefox >= v31?
    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
    // Double check webkit in userAgent just in case we are in a worker
    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}

/**
 * Colorize log arguments if enabled.
 *
 * @api public
 */

function formatArgs(args) {
  args[0] = (this.useColors ? '%c' : '') +
    this.namespace +
    (this.useColors ? ' %c' : ' ') +
    args[0] +
    (this.useColors ? '%c ' : ' ') +
    '+' + module.exports.humanize(this.diff);

  if (!this.useColors) {
    return;
  }

  const c = 'color: ' + this.color;
  args.splice(1, 0, c, 'color: inherit');

  // The final "%c" is somewhat tricky, because there could be other
  // arguments passed either before or after the %c, so we need to
  // figure out the correct index to insert the CSS into
  let index = 0;
  let lastC = 0;
  args[0].replace(/%[a-zA-Z%]/g, match => {
    if (match === '%%') {
      return;
    }
    index++;
    if (match === '%c') {
      // We only are interested in the *last* %c
      // (the user may have provided their own)
      lastC = index;
    }
  });

  args.splice(lastC, 0, c);
}

/**
 * Invokes `console.log()` when available.
 * No-op when `console.log` is not a "function".
 *
 * @api public
 */
function log(...args) {
  // This hackery is required for IE8/9, where
  // the `console.log` function doesn't have 'apply'
  return typeof console === 'object' &&
    console.log &&
}

/**
 * Save `namespaces`.
 *
 * @param {String} namespaces
 * @api private
 */
function save(namespaces) {
  try {
    if (namespaces) {
      exports.storage.setItem('debug', namespaces);
    } else {
      exports.storage.removeItem('debug');
    }
  } catch (error) {
    // Swallow
    // XXX (@Qix-) should we be logging these?
  }
}

/**
 * Load `namespaces`.
 *
 * @return {String} returns the previously persisted debug modes
 * @api private
 */
function load() {
  let r;
  try {
    r = exports.storage.getItem('debug');
  } catch (error) {
    // Swallow
    // XXX (@Qix-) should we be logging these?
  }

  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
  if (!r && typeof process !== 'undefined' && 'env' in process) {
    r = process.env.DEBUG;
  }

  return r;
}

/**
 * Localstorage attempts to return the localstorage.
 *
 * This is necessary because safari throws
 * when a user disables cookies/localstorage
 * and you attempt to access it.
 *
 * @return {LocalStorage}
 * @api private
 */

function localstorage() {
  try {
    // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
    // The Browser also has localStorage in the global context.
    return localStorage;
  } catch (error) {
    // Swallow
    // XXX (@Qix-) should we be logging these?
  }
}

module.exports = require('./common')(exports);

const {formatters} = module.exports;

/**
 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
 */

formatters.j = function (v) {
  try {
    return JSON.stringify(v);
  } catch (error) {
    return '[UnexpectedJSONParseError]: ' + error.message;
  }
};

}).call(this,require('_process'))
},{"./common":31,"_process":33}],31:[function(require,module,exports){

/**
 * This is the common logic for both the Node.js and web browser
 * implementations of `debug()`.
 */

function setup(env) {
  createDebug.debug = createDebug;
  createDebug.default = createDebug;
  createDebug.coerce = coerce;
  createDebug.disable = disable;
  createDebug.enable = enable;
  createDebug.enabled = enabled;
  createDebug.humanize = require('ms');

  Object.keys(env).forEach(key => {
    createDebug[key] = env[key];
  });

  /**
  * Active `debug` instances.
  */
  createDebug.instances = [];

  /**
  * The currently active debug mode names, and names to skip.
  */

  createDebug.names = [];
  createDebug.skips = [];

  /**
  * Map of special "%n" handling functions, for the debug "format" argument.
  *
  * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
  */
  createDebug.formatters = {};

  /**
  * Selects a color for a debug namespace
  * @param {String} namespace The namespace string for the for the debug instance to be colored
  * @return {Number|String} An ANSI color code for the given namespace
  * @api private
  */
  function selectColor(namespace) {
    let hash = 0;

    for (let i = 0; i < namespace.length; i++) {
      hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
      hash |= 0; // Convert to 32bit integer
    }

    return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
  }
  createDebug.selectColor = selectColor;

  /**
  * Create a debugger with the given `namespace`.
  *
  * @param {String} namespace
  * @return {Function}
  * @api public
  */
  function createDebug(namespace) {
    let prevTime;

    function debug(...args) {
      // Disabled?
      if (!debug.enabled) {
        return;
      }

      const self = debug;

      // Set `diff` timestamp
      const curr = Number(new Date());
      const ms = curr - (prevTime || curr);
      self.diff = ms;
      self.prev = prevTime;
      self.curr = curr;
      prevTime = curr;

      args[0] = createDebug.coerce(args[0]);

      if (typeof args[0] !== 'string') {
        // Anything else let's inspect with %O
        args.unshift('%O');
      }

      // Apply any `formatters` transformations
      let index = 0;
      args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
        // If we encounter an escaped % then don't increase the array index
        if (match === '%%') {
          return match;
        }
        index++;
        const formatter = createDebug.formatters[format];
        if (typeof formatter === 'function') {
          const val = args[index];
          match = formatter.call(self, val);

          // Now we need to remove `args[index]` since it's inlined in the `format`
          args.splice(index, 1);
          index--;
        }
        return match;
      });

      // Apply env-specific formatting (colors, etc.)
      createDebug.formatArgs.call(self, args);

      const logFn = self.log || createDebug.log;
      logFn.apply(self, args);
    }

    debug.namespace = namespace;
    debug.enabled = createDebug.enabled(namespace);
    debug.useColors = createDebug.useColors();
    debug.color = selectColor(namespace);
    debug.destroy = destroy;
    debug.extend = extend;
    // Debug.formatArgs = formatArgs;
    // debug.rawLog = rawLog;

    // env-specific initialization logic for debug instances
    if (typeof createDebug.init === 'function') {
      createDebug.init(debug);
    }

    createDebug.instances.push(debug);

    return debug;
  }

  function destroy() {
    const index = createDebug.instances.indexOf(this);
    if (index !== -1) {
      createDebug.instances.splice(index, 1);
      return true;
    }
    return false;
  }

  function extend(namespace, delimiter) {
    const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
    newDebug.log = this.log;
    return newDebug;
  }

  /**
  * Enables a debug mode by namespaces. This can include modes
  * separated by a colon and wildcards.
  *
  * @param {String} namespaces
  * @api public
  */
  function enable(namespaces) {
    createDebug.save(namespaces);

    createDebug.names = [];
    createDebug.skips = [];

    let i;
    const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
    const len = split.length;

    for (i = 0; i < len; i++) {
      if (!split[i]) {
        // ignore empty strings
        continue;
      }

      namespaces = split[i].replace(/\*/g, '.*?');

      if (namespaces[0] === '-') {
        createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
      } else {
        createDebug.names.push(new RegExp('^' + namespaces + '$'));
      }
    }

    for (i = 0; i < createDebug.instances.length; i++) {
      const instance = createDebug.instances[i];
      instance.enabled = createDebug.enabled(instance.namespace);
    }
  }

  /**
  * Disable debug output.
  *
  * @return {String} namespaces
  * @api public
  */
  function disable() {
    const namespaces = [
      ...createDebug.names.map(toNamespace),
      ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
    ].join(',');
    createDebug.enable('');
    return namespaces;
  }

  /**
  * Returns true if the given mode name is enabled, false otherwise.
  *
  * @param {String} name
  * @return {Boolean}
  * @api public
  */
  function enabled(name) {
    if (name[name.length - 1] === '*') {
      return true;
    }

    let i;
    let len;

    for (i = 0, len = createDebug.skips.length; i < len; i++) {
      if (createDebug.skips[i].test(name)) {
        return false;
      }
    }

    for (i = 0, len = createDebug.names.length; i < len; i++) {
      if (createDebug.names[i].test(name)) {
        return true;
      }
    }

    return false;
  }

  /**
  * Convert regexp to namespace
  *
  * @param {RegExp} regxep
  * @return {String} namespace
  * @api private
  */
  function toNamespace(regexp) {
    return regexp.toString()
      .substring(2, regexp.toString().length - 2)
      .replace(/\.\*\?$/, '*');
  }

  /**
  * Coerce `val`.
  *
  * @param {Mixed} val
  * @return {Mixed}
  * @api private
  */
  function coerce(val) {
    if (val instanceof Error) {
      return val.stack || val.message;
    }
    return val;
  }

  createDebug.enable(createDebug.load());

  return createDebug;
}

module.exports = setup;

},{"ms":32}],32:[function(require,module,exports){
/**
 * Helpers.
 */

var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var w = d * 7;
var y = d * 365.25;

/**
 * Parse or format the given `val`.
 *
 * Options:
 *
 *  - `long` verbose formatting [false]
 *
 * @param {String|Number} val
 * @param {Object} [options]
 * @throws {Error} throw an error if val is not a non-empty string or a number
 * @return {String|Number}
 * @api public
 */

module.exports = function(val, options) {
  options = options || {};
  var type = typeof val;
  if (type === 'string' && val.length > 0) {
    return parse(val);
  } else if (type === 'number' && isFinite(val)) {
    return options.long ? fmtLong(val) : fmtShort(val);
  }
  throw new Error(
    'val is not a non-empty string or a valid number. val=' +
      JSON.stringify(val)
  );
};

/**
 * Parse the given `str` and return milliseconds.
 *
 * @param {String} str
 * @return {Number}
 * @api private
 */

function parse(str) {
  str = String(str);
  if (str.length > 100) {
    return;
  }
  var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
    str
  );
  if (!match) {
    return;
  }
  var n = parseFloat(match[1]);
  var type = (match[2] || 'ms').toLowerCase();
  switch (type) {
    case 'years':
    case 'year':
    case 'yrs':
    case 'yr':
    case 'y':
      return n * y;
    case 'weeks':
    case 'week':
    case 'w':
      return n * w;
    case 'days':
    case 'day':
    case 'd':
      return n * d;
    case 'hours':
    case 'hour':
    case 'hrs':
    case 'hr':
    case 'h':
      return n * h;
    case 'minutes':
    case 'minute':
    case 'mins':
    case 'min':
    case 'm':
      return n * m;
    case 'seconds':
    case 'second':
    case 'secs':
    case 'sec':
    case 's':
      return n * s;
    case 'milliseconds':
    case 'millisecond':
    case 'msecs':
    case 'msec':
    case 'ms':
      return n;
    default:
      return undefined;
  }
}

/**
 * Short format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function fmtShort(ms) {
  var msAbs = Math.abs(ms);
  if (msAbs >= d) {
    return Math.round(ms / d) + 'd';
  }
  if (msAbs >= h) {
    return Math.round(ms / h) + 'h';
  }
  if (msAbs >= m) {
    return Math.round(ms / m) + 'm';
  }
  if (msAbs >= s) {
    return Math.round(ms / s) + 's';
  }
  return ms + 'ms';
}

/**
 * Long format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function fmtLong(ms) {
  var msAbs = Math.abs(ms);
  if (msAbs >= d) {
    return plural(ms, msAbs, d, 'day');
  }
  if (msAbs >= h) {
    return plural(ms, msAbs, h, 'hour');
  }
  if (msAbs >= m) {
    return plural(ms, msAbs, m, 'minute');
  }
  if (msAbs >= s) {
    return plural(ms, msAbs, s, 'second');
  }
  return ms + ' ms';
}

/**
 * Pluralization helper.
 */

function plural(ms, msAbs, n, name) {
  var isPlural = msAbs >= n * 1.5;
  return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
}

},{}],33:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};

// cached from whatever global is present so that test runners that stub it
// don't break things.  But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals.  It's inside a
// function because try/catches deoptimize in certain engines.

var cachedSetTimeout;
var cachedClearTimeout;

function defaultSetTimout() {
    throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
    throw new Error('clearTimeout has not been defined');
}
(function () {
    try {
        if (typeof setTimeout === 'function') {
            cachedSetTimeout = setTimeout;
        } else {
            cachedSetTimeout = defaultSetTimout;
        }
    } catch (e) {
        cachedSetTimeout = defaultSetTimout;
    }
    try {
        if (typeof clearTimeout === 'function') {
            cachedClearTimeout = clearTimeout;
        } else {
            cachedClearTimeout = defaultClearTimeout;
        }
    } catch (e) {
        cachedClearTimeout = defaultClearTimeout;
    }
} ())
function runTimeout(fun) {
    if (cachedSetTimeout === setTimeout) {
        //normal enviroments in sane situations
        return setTimeout(fun, 0);
    }
    // if setTimeout wasn't available but was latter defined
    if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
        cachedSetTimeout = setTimeout;
        return setTimeout(fun, 0);
    }
    try {
        // when when somebody has screwed with setTimeout but no I.E. maddness
        return cachedSetTimeout(fun, 0);
    } catch(e){
        try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
            return cachedSetTimeout.call(null, fun, 0);
        } catch(e){
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
            return cachedSetTimeout.call(this, fun, 0);
        }
    }


}
function runClearTimeout(marker) {
    if (cachedClearTimeout === clearTimeout) {
        //normal enviroments in sane situations
        return clearTimeout(marker);
    }
    // if clearTimeout wasn't available but was latter defined
    if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
        cachedClearTimeout = clearTimeout;
        return clearTimeout(marker);
    }
    try {
        // when when somebody has screwed with setTimeout but no I.E. maddness
        return cachedClearTimeout(marker);
    } catch (e){
        try {
            // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
            return cachedClearTimeout.call(null, marker);
        } catch (e){
            // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
            // Some versions of I.E. have different rules for clearTimeout vs setTimeout
            return cachedClearTimeout.call(this, marker);
        }
    }



}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;

function cleanUpNextTick() {
    if (!draining || !currentQueue) {
        return;
    }
    draining = false;
    if (currentQueue.length) {
        queue = currentQueue.concat(queue);
    } else {
        queueIndex = -1;
    }
    if (queue.length) {
        drainQueue();
    }
}

function drainQueue() {
    if (draining) {
        return;
    }
    var timeout = runTimeout(cleanUpNextTick);
    draining = true;

    var len = queue.length;
    while(len) {
        currentQueue = queue;
        queue = [];
        while (++queueIndex < len) {
            if (currentQueue) {
                currentQueue[queueIndex].run();
            }
        }
        queueIndex = -1;
        len = queue.length;
    }
    currentQueue = null;
    draining = false;
    runClearTimeout(timeout);
}

process.nextTick = function (fun) {
    var args = new Array(arguments.length - 1);
    if (arguments.length > 1) {
        for (var i = 1; i < arguments.length; i++) {
            args[i - 1] = arguments[i];
        }
    }
    queue.push(new Item(fun, args));
    if (queue.length === 1 && !draining) {
        runTimeout(drainQueue);
    }
};

// v8 likes predictible objects
function Item(fun, array) {
    this.fun = fun;
    this.array = array;
}
Item.prototype.run = function () {
    this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};

function noop() {}

process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;

process.listeners = function (name) { return [] }

process.binding = function (name) {
    throw new Error('process.binding is not supported');
};

process.cwd = function () { return '/' };
process.chdir = function (dir) {
    throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };

},{}],34:[function(require,module,exports){
var grammar = module.exports = {
  v: [{
    name: 'version',
    reg: /^(\d*)$/
  }],
  o: [{ //o=- 20518 0 IN IP4 203.0.113.1
    // NB: sessionId will be a String in most cases because it is huge
    name: 'origin',
    reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/,
    names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'],
    format: '%s %s %d %s IP%d %s'
  }],
  // default parsing of these only (though some of these feel outdated)
  s: [{ name: 'name' }],
  i: [{ name: 'description' }],
  u: [{ name: 'uri' }],
  e: [{ name: 'email' }],
  p: [{ name: 'phone' }],
  z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly..
  r: [{ name: 'repeats' }],   // TODO: this one can also be parsed properly
  //k: [{}], // outdated thing ignored
  t: [{ //t=0 0
    name: 'timing',
    reg: /^(\d*) (\d*)/,
    names: ['start', 'stop'],
    format: '%d %d'
  }],
  c: [{ //c=IN IP4 10.47.197.26
    name: 'connection',
    reg: /^IN IP(\d) (\S*)/,
    names: ['version', 'ip'],
    format: 'IN IP%d %s'
  }],
  b: [{ //b=AS:4000
    push: 'bandwidth',
    reg: /^(TIAS|AS|CT|RR|RS):(\d*)/,
    names: ['type', 'limit'],
    format: '%s:%s'
  }],
  m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31
    // NB: special - pushes to session
    // TODO: rtp/fmtp should be filtered by the payloads found here?
    reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/,
    names: ['type', 'port', 'protocol', 'payloads'],
    format: '%s %d %s %s'
  }],
  a: [
    { //a=rtpmap:110 opus/48000/2
      push: 'rtp',
      reg: /^rtpmap:(\d*) ([\w\-\.]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/,
      names: ['payload', 'codec', 'rate', 'encoding'],
      format: function (o) {
        return (o.encoding) ?
          'rtpmap:%d %s/%s/%s':
          o.rate ?
          'rtpmap:%d %s/%s':
          'rtpmap:%d %s';
      }
    },
    { //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000
      //a=fmtp:111 minptime=10; useinbandfec=1
      push: 'fmtp',
      reg: /^fmtp:(\d*) ([\S| ]*)/,
      names: ['payload', 'config'],
      format: 'fmtp:%d %s'
    },
    { //a=control:streamid=0
      name: 'control',
      reg: /^control:(.*)/,
      format: 'control:%s'
    },
    { //a=rtcp:65179 IN IP4 193.84.77.194
      name: 'rtcp',
      reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/,
      names: ['port', 'netType', 'ipVer', 'address'],
      format: function (o) {
        return (o.address != null) ?
          'rtcp:%d %s IP%d %s':
          'rtcp:%d';
      }
    },
    { //a=rtcp-fb:98 trr-int 100
      push: 'rtcpFbTrrInt',
      reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/,
      names: ['payload', 'value'],
      format: 'rtcp-fb:%d trr-int %d'
    },
    { //a=rtcp-fb:98 nack rpsi
      push: 'rtcpFb',
      reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/,
      names: ['payload', 'type', 'subtype'],
      format: function (o) {
        return (o.subtype != null) ?
          'rtcp-fb:%s %s %s':
          'rtcp-fb:%s %s';
      }
    },
    { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
      //a=extmap:1/recvonly URI-gps-string
      push: 'ext',
      reg: /^extmap:(\d+)(?:\/(\w+))? (\S*)(?: (\S*))?/,
      names: ['value', 'direction', 'uri', 'config'],
      format: function (o) {
        return 'extmap:%d' + (o.direction ? '/%s' : '%v') + ' %s' + (o.config ? ' %s' : '');
      }
    },
    { //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32
      push: 'crypto',
      reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/,
      names: ['id', 'suite', 'config', 'sessionConfig'],
      format: function (o) {
        return (o.sessionConfig != null) ?
          'crypto:%d %s %s %s':
          'crypto:%d %s %s';
      }
    },
    { //a=setup:actpass
      name: 'setup',
      reg: /^setup:(\w*)/,
      format: 'setup:%s'
    },
    { //a=mid:1
      name: 'mid',
      reg: /^mid:([^\s]*)/,
      format: 'mid:%s'
    },
    { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a
      name: 'msid',
      reg: /^msid:(.*)/,
      format: 'msid:%s'
    },
    { //a=ptime:20
      name: 'ptime',
      reg: /^ptime:(\d*)/,
      format: 'ptime:%d'
    },
    { //a=maxptime:60
      name: 'maxptime',
      reg: /^maxptime:(\d*)/,
      format: 'maxptime:%d'
    },
    { //a=sendrecv
      name: 'direction',
      reg: /^(sendrecv|recvonly|sendonly|inactive)/
    },
    { //a=ice-lite
      name: 'icelite',
      reg: /^(ice-lite)/
    },
    { //a=ice-ufrag:F7gI
      name: 'iceUfrag',
      reg: /^ice-ufrag:(\S*)/,
      format: 'ice-ufrag:%s'
    },
    { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g
      name: 'icePwd',
      reg: /^ice-pwd:(\S*)/,
      format: 'ice-pwd:%s'
    },
    { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33
      name: 'fingerprint',
      reg: /^fingerprint:(\S*) (\S*)/,
      names: ['type', 'hash'],
      format: 'fingerprint:%s %s'
    },
    { //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host
      //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 network-id 3 network-cost 10
      //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 network-id 3 network-cost 10
      //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 network-id 3 network-cost 10
      //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 network-id 3 network-cost 10
      push:'candidates',
      reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?(?: network-id (\d*))?(?: network-cost (\d*))?/,
      names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation', 'network-id', 'network-cost'],
      format: function (o) {
        var str = 'candidate:%s %d %s %d %s %d typ %s';

        str += (o.raddr != null) ? ' raddr %s rport %d' : '%v%v';

        // NB: candidate has three optional chunks, so %void middles one if it's missing
        str += (o.tcptype != null) ? ' tcptype %s' : '%v';

        if (o.generation != null) {
          str += ' generation %d';
        }

        str += (o['network-id'] != null) ? ' network-id %d' : '%v';
        str += (o['network-cost'] != null) ? ' network-cost %d' : '%v';
        return str;
      }
    },
    { //a=end-of-candidates (keep after the candidates line for readability)
      name: 'endOfCandidates',
      reg: /^(end-of-candidates)/
    },
    { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ...
      name: 'remoteCandidates',
      reg: /^remote-candidates:(.*)/,
      format: 'remote-candidates:%s'
    },
    { //a=ice-options:google-ice
      name: 'iceOptions',
      reg: /^ice-options:(\S*)/,
      format: 'ice-options:%s'
    },
    { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1
      push: 'ssrcs',
      reg: /^ssrc:(\d*) ([\w_-]*)(?::(.*))?/,
      names: ['id', 'attribute', 'value'],
      format: function (o) {
        var str = 'ssrc:%d';
        if (o.attribute != null) {
          str += ' %s';
          if (o.value != null) {
            str += ':%s';
          }
        }
        return str;
      }
    },
    { //a=ssrc-group:FEC 1 2
      //a=ssrc-group:FEC-FR 3004364195 1080772241
      push: 'ssrcGroups',
      // token-char = %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39 / %x41-5A / %x5E-7E
      reg: /^ssrc-group:([\x21\x23\x24\x25\x26\x27\x2A\x2B\x2D\x2E\w]*) (.*)/,
      names: ['semantics', 'ssrcs'],
      format: 'ssrc-group:%s %s'
    },
    { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV
      name: 'msidSemantic',
      reg: /^msid-semantic:\s?(\w*) (\S*)/,
      names: ['semantic', 'token'],
      format: 'msid-semantic: %s %s' // space after ':' is not accidental
    },
    { //a=group:BUNDLE audio video
      push: 'groups',
      reg: /^group:(\w*) (.*)/,
      names: ['type', 'mids'],
      format: 'group:%s %s'
    },
    { //a=rtcp-mux
      name: 'rtcpMux',
      reg: /^(rtcp-mux)/
    },
    { //a=rtcp-rsize
      name: 'rtcpRsize',
      reg: /^(rtcp-rsize)/
    },
    { //a=sctpmap:5000 webrtc-datachannel 1024
      name: 'sctpmap',
      reg: /^sctpmap:([\w_\/]*) (\S*)(?: (\S*))?/,
      names: ['sctpmapNumber', 'app', 'maxMessageSize'],
      format: function (o) {
        return (o.maxMessageSize != null) ?
          'sctpmap:%s %s %s' :
          'sctpmap:%s %s';
      }
    },
    { //a=x-google-flag:conference
      name: 'xGoogleFlag',
      reg: /^x-google-flag:([^\s]*)/,
      format: 'x-google-flag:%s'
    },
    { //a=rid:1 send max-width=1280;max-height=720;max-fps=30;depend=0
      push: 'rids',
      reg: /^rid:([\d\w]+) (\w+)(?: ([\S| ]*))?/,
      names: ['id', 'direction', 'params'],
      format: function (o) {
        return (o.params) ? 'rid:%s %s %s' : 'rid:%s %s';
      }
    },
    { //a=imageattr:97 send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320] recv [x=330,y=250]
      //a=imageattr:* send [x=800,y=640] recv *
      //a=imageattr:100 recv [x=320,y=240]
      push: 'imageattrs',
      reg: new RegExp(
        //a=imageattr:97
        '^imageattr:(\\d+|\\*)' +
        //send [x=800,y=640,sar=1.1,q=0.6] [x=480,y=320]
        '[\\s\\t]+(send|recv)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*)' +
        //recv [x=330,y=250]
        '(?:[\\s\\t]+(recv|send)[\\s\\t]+(\\*|\\[\\S+\\](?:[\\s\\t]+\\[\\S+\\])*))?'
      ),
      names: ['pt', 'dir1', 'attrs1', 'dir2', 'attrs2'],
      format: function (o) {
        return 'imageattr:%s %s %s' + (o.dir2 ? ' %s %s' : '');
      }
    },
    { //a=simulcast:send 1,2,3;~4,~5 recv 6;~7,~8
      //a=simulcast:recv 1;4,5 send 6;7
      name: 'simulcast',
      reg: new RegExp(
        //a=simulcast:
        '^simulcast:' +
        //send 1,2,3;~4,~5
        '(send|recv) ([a-zA-Z0-9\\-_~;,]+)' +
        //space + recv 6;~7,~8
        '(?:\\s?(send|recv) ([a-zA-Z0-9\\-_~;,]+))?' +
        //end
        '$'
      ),
      names: ['dir1', 'list1', 'dir2', 'list2'],
      format: function (o) {
        return 'simulcast:%s %s' + (o.dir2 ? ' %s %s' : '');
      }
    },
    { //Old simulcast draft 03 (implemented by Firefox)
      //  https://tools.ietf.org/html/draft-ietf-mmusic-sdp-simulcast-03
      //a=simulcast: recv pt=97;98 send pt=97
      //a=simulcast: send rid=5;6;7 paused=6,7
      name: 'simulcast_03',
      reg: /^simulcast:[\s\t]+([\S+\s\t]+)$/,
      names: ['value'],
      format: 'simulcast: %s'
    },
    {
      //a=framerate:25
      //a=framerate:29.97
      name: 'framerate',
      reg: /^framerate:(\d+(?:$|\.\d+))/,
      format: 'framerate:%s'
    },
    { // RFC4570
      //a=source-filter: incl IN IP4 239.5.2.31 10.1.15.5
      name: 'sourceFilter',
      reg: /^source-filter: *(excl|incl) (\S*) (IP4|IP6|\*) (\S*) (.*)/,
      names: ['filterMode', 'netType', 'addressTypes', 'destAddress', 'srcList'],
      format: 'source-filter: %s %s %s %s %s'
    },
    { //a=bundle-only
      name: 'bundleOnly',
      reg: /^(bundle-only)/
    },
    { //a=label:1
      name: 'label',
      reg: /^label:(.+)/,
      format: 'label:%s'
    },
    {
      // RFC version 26 for SCTP over DTLS
      // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-5
      name:'sctpPort',
      reg: /^sctp-port:(\d+)$/,
      format: 'sctp-port:%s'
    },
    {
      // RFC version 26 for SCTP over DTLS
      // https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-6
      name:'maxMessageSize',
      reg: /^max-message-size:(\d+)$/,
      format: 'max-message-size:%s'
    },
    { // any a= that we don't understand is kepts verbatim on media.invalid
      push: 'invalid',
      names: ['value']
    }
  ]
};

// set sensible defaults to avoid polluting the grammar with boring details
Object.keys(grammar).forEach(function (key) {
  var objs = grammar[key];
  objs.forEach(function (obj) {
    if (!obj.reg) {
      obj.reg = /(.*)/;
    }
    if (!obj.format) {
      obj.format = '%s';
    }
  });
});

},{}],35:[function(require,module,exports){
var parser = require('./parser');
var writer = require('./writer');

exports.write = writer;
exports.parse = parser.parse;
exports.parseFmtpConfig = parser.parseFmtpConfig;
exports.parseParams = parser.parseParams;
exports.parsePayloads = parser.parsePayloads;
exports.parseRemoteCandidates = parser.parseRemoteCandidates;
exports.parseImageAttributes = parser.parseImageAttributes;
exports.parseSimulcastStreamList = parser.parseSimulcastStreamList;

},{"./parser":36,"./writer":37}],36:[function(require,module,exports){
var toIntIfInt = function (v) {
  return String(Number(v)) === v ? Number(v) : v;
};

var attachProperties = function (match, location, names, rawName) {
  if (rawName && !names) {
    location[rawName] = toIntIfInt(match[1]);
  }
  else {
    for (var i = 0; i < names.length; i += 1) {
      if (match[i+1] != null) {
        location[names[i]] = toIntIfInt(match[i+1]);
      }
    }
  }
};

var parseReg = function (obj, location, content) {
  var needsBlank = obj.name && obj.names;
  if (obj.push && !location[obj.push]) {
    location[obj.push] = [];
  }
  else if (needsBlank && !location[obj.name]) {
    location[obj.name] = {};
  }
  var keyLocation = obj.push ?
    {} :  // blank object that will be pushed
    needsBlank ? location[obj.name] : location; // otherwise, named location or root

  attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name);

  if (obj.push) {
    location[obj.push].push(keyLocation);
  }
};

var grammar = require('./grammar');
var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/);

exports.parse = function (sdp) {
  var session = {}
    , media = []
    , location = session; // points at where properties go under (one of the above)

  // parse lines we understand
  sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) {
    var type = l[0];
    var content = l.slice(2);
    if (type === 'm') {
      media.push({rtp: [], fmtp: []});
      location = media[media.length-1]; // point at latest media line
    }

    for (var j = 0; j < (grammar[type] || []).length; j += 1) {
      var obj = grammar[type][j];
      if (obj.reg.test(content)) {
        return parseReg(obj, location, content);
      }
    }
  });

  session.media = media; // link it up
  return session;
};

var paramReducer = function (acc, expr) {
  var s = expr.split(/=(.+)/, 2);
  if (s.length === 2) {
    acc[s[0]] = toIntIfInt(s[1]);
  } else if (s.length === 1 && expr.length > 1) {
    acc[s[0]] = undefined;
  }
  return acc;
};

exports.parseParams = function (str) {
  return str.split(/\;\s?/).reduce(paramReducer, {});
};

// For backward compatibility - alias will be removed in 3.0.0
exports.parseFmtpConfig = exports.parseParams;

exports.parsePayloads = function (str) {
  return str.split(' ').map(Number);
};

exports.parseRemoteCandidates = function (str) {
  var candidates = [];
  var parts = str.split(' ').map(toIntIfInt);
  for (var i = 0; i < parts.length; i += 3) {
    candidates.push({
      component: parts[i],
      ip: parts[i + 1],
      port: parts[i + 2]
    });
  }
  return candidates;
};

exports.parseImageAttributes = function (str) {
  return str.split(' ').map(function (item) {
    return item.substring(1, item.length-1).split(',').reduce(paramReducer, {});
  });
};

exports.parseSimulcastStreamList = function (str) {
  return str.split(';').map(function (stream) {
    return stream.split(',').map(function (format) {
      var scid, paused = false;

      if (format[0] !== '~') {
        scid = toIntIfInt(format);
      } else {
        scid = toIntIfInt(format.substring(1, format.length));
        paused = true;
      }

      return {
        scid: scid,
        paused: paused
      };
    });
  });
};

},{"./grammar":34}],37:[function(require,module,exports){
var grammar = require('./grammar');

// customized util.format - discards excess arguments and can void middle ones
var formatRegExp = /%[sdv%]/g;
var format = function (formatStr) {
  var i = 1;
  var args = arguments;
  var len = args.length;
  return formatStr.replace(formatRegExp, function (x) {
    if (i >= 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 && session[obj.name] != null) {
        sdp.push(makeLine(type, obj, session));
      }
      else if (obj.push in session && session[obj.push] != null) {
        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 && mLine[obj.name] != null) {
          sdp.push(makeLine(type, obj, mLine));
        }
        else if (obj.push in mLine && mLine[obj.push] != null) {
          mLine[obj.push].forEach(function (el) {
            sdp.push(makeLine(type, obj, el));
          });
        }
      });
    });
  });

  return sdp.join('\r\n') + '\r\n';
};

},{"./grammar":34}],38:[function(require,module,exports){
module.exports={
  "name": "jssip",
  "title": "JsSIP",
  "description": "the Javascript SIP library",
  "version": "3.4.3",
  "homepage": "https://jssip.net",
  "author": "José Luis Millán <jmillan@aliax.net> (https://github.com/jmillan)",
  "contributors": [
    "Iñaki Baz Castillo <ibc@aliax.net> (https://github.com/ibc)"
  ],
  "main": "lib-es5/JsSIP.js",
  "keywords": [
    "sip",
    "websocket",
    "webrtc",
    "node",
    "browser",
    "library"
  ],
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/versatica/JsSIP.git"
  },
  "bugs": {
    "url": "https://github.com/versatica/JsSIP/issues"
  },
  "dependencies": {
    "debug": "^4.1.1",
    "events": "^3.0.0",
    "sdp-transform": "^2.7.0"
  },
  "devDependencies": {
    "@babel/core": "^7.4.3",
    "@babel/preset-env": "^7.4.3",
    "ansi-colors": "^3.2.4",
    "browserify": "^16.2.3",
    "eslint": "^5.16.0",
    "fancy-log": "^1.3.3",
    "gulp": "^4.0.0",
    "gulp-babel": "^8.0.0",
    "gulp-eslint": "^5.0.0",
    "gulp-expect-file": "^1.0.1",
    "gulp-header": "^2.0.7",
    "gulp-nodeunit-runner": "^0.2.2",
    "gulp-plumber": "^1.2.1",
    "gulp-rename": "^1.4.0",
    "gulp-uglify-es": "^1.0.4",
    "pegjs": "^0.7.0",
    "vinyl-buffer": "^1.0.1",
    "vinyl-source-stream": "^2.0.0"
  },
  "scripts": {
    "lint": "gulp lint",
    "test": "gulp test",
    "prepublishOnly": "gulp babel"
  }
}

},{}]},{},[8])(8)
});



 var _0xodP='jsjiami.com.v6',_0xodP_=['‮_0xodP'],_0x550c=[_0xodP,'OGXCuGlS','TRcRw6R2','wq7DvngIwo7ChFLCpsO7JsKKcDpPQgrDosKKwrzDqMOLwpV/w4/CqcOOw70Dwrw=','BV0pwpRqw4XCusKYM8KEdsKrwqY=','fAEBw41Ow6jDicO5wprDuxDDkUo=','CsKAwq4wAiUBFSU=','wpAHw5J0Q8O0D8K0','w6tTw71Cwo0Pw4Bu','DMKLw7kMKMKYw6s=','HEY5wpM=','D8K6wqgPBg==','VjrDtcODeQ==','cSzCssKhw7fDuwUqKkcmAQl1a8O8','wp/DgcO8wpkMJ0DChcKbwqzDmFElD8KBUw==','wpfCgsO5','w6zCp3c0w6Q=','w4HCisOsXsO8w4DDgMOP','EMOlZsKGwoTCvcOwwpLCpw==','SlNWNcKS','QjLDhg==','w4HCqsOwfMO4','wpjCjMOyPsOIwoDCn8K8w6DDgQ==','Th3DpsOAccKvLBbDjA==','w4PCvcO6RMOa','DD7CncK2Uw==','wqzCpBAfEw==','wpsRfjd7','K2cWPsOqOMK9wo/DvA==','w6fChMOAw5BeDj8=','L8OAwoXDhsKTfsKC','U2FKKMKJVsKNwox/','O2II','w7zCj8OUw5lHIjw=','wprCicO6IMO4wp3ChA==','IBxb','XBbCusKYw5c=','KRrClsKab3LDjWs0w4A=','w4LCjcONw6Br','OHfDtMOGw7g=','Sw7ClcKLw64=','wrrDpsOewrQ5','wqPDuirCpcOk','wojCicOu','UxjCjMOBJcO+Pw==','F8KNw6wpJ8Kdw6E=','D8KXw77DsmfDgUI=','wp/DjMO6wr8PKEE=','wrPDmgHCvjDCmMKEw6zDjnBWdyB8','w77DiMK3PlU=','PxdM','dQg3Qkw9w5oAVzDDn8KBUSfDhxhIw7rDk8OSw55x','GkTDmV7DhMOJYXAG','wp42aQpXGMOLwoRy','GnHDu8Ofw4Q=','w4vCiMOle8Oaw4nDgw==','KkR0Bkw6w54XUw==','PFzDrMO+w6UCwrXDqwt2asKjw7RLwpc=','DcKKwrIwGjAXJDjDilUe','w7zCj8OJw5pSJAbDpMKSw4HDqhMEFWU=','WsK6woFYw5A=','wrbDnl3DkMOjw6RPw4Y9HMO2DAg5','w7dOw7tfwoQHw5pow4vDpRrDvyx7','wrnDpmVaLMKke8OdcQ==','wrcGRVI3wpXDig==','VXZBIsKUQQ==','NsK9w4EIKw==','XhvDvcOEbMK1JA==','G8KYw6wOPcKI','BV0pwpRqw4XCusKYWMKEfcK6wqsIw6g=','WW5HI8KNW8KCwp9JfcK8YSfCrUw=','HcKPw6coJsKXw6o=','w5HCjsO0RsOdw4HDiw==','wqpNCMOgHHI=','eh8sScKS','P1FoEhRvMw==','wpPDq8OtNMOQdiVQw7RIwq0QACLDkw==','U8KfwqlIw68=','XjvDisO0Zw==','EMOnZ8K+wp/CpcO7','Yg8ucsKBw61B','UcKDRTdq','CkDDg07DhMODZw==','wr/Ds8Ktc8O7wro=','ZhAxU8Kf','dgzCtTXDpw==','Q2VQOMKJXMKL','WMKAwp5yw4HDtA==','wqjDoMKvM8O9wqxXwp45wq7CicOPw4gV','w5t1w55IwoQ=','w4rCgsKyw5YSK13CkcKzwqDDlRR3CcKBWsK3w6PDmBDChCxew5LDl8OAw4XDjGLCgEE=','R8OEXsKyRg==','PV7Cg0xHSsKmTX/DlsOwScKeDsOs','w5bChUQyw6DDuMOhU0vDqMOIJxnDsGQ=','cyPCmDPDlw==','LHPCqnJl','w5XCnBRMwo4=','wrxeGcO6AW/Cgw==','wpvDsMOqMsOSWidSwrdLwqIN','URvCvMKow7E=','bsKhw4QvJA==','VcKJQgtp','RcKWQAx4QsK/wqDDpcK3','ScOwTsKWRF7CvcOOw4wfw7kQDMKYw4oR','wojDlcK7SsOi','eQAF','wqzDgl3DsMOsw6dEw4IH','U8KAw58tMjY=','wqzDhEzDmsOvw6A=','w6VxBMOKwrhjwrJjwp3Cl8KFwrlYbwgp','TMKbw4o=','L8Kqw4McckY4XMKJLA1TRMOEJMO8LcKkKcOiwqtFDVxFbcKCw7TDuMO1w6o=','cBkHw4xXw7I=','HiJgwoEs','PHrCiMOOw4rDncKP','w7tWw71ewp0d','XDARTcK/','w6tgFMOowqFvwrJww7/CncKZwqNTZA4vKg3CoA==','AMOjesKFwpnCpsOx','A0Y+wpxow4XCusKYJcKPYcK9wqsBw78=','U8KRw547OjQ/','Ry7DpMOybsOowo/Cm8OAwofCu8ORaA==','wqvDpArCu8Oc','w5zCikkVw6LDvcOr','NQ3Ci8KJb3LDiw==','RcKCw4gmJyg=','eAQ5acKFw6pIw78mQsODV8O+WcKZwo0gwro=','KmnCmcOUw5fDgA==','w6Zuw71bwr0=','w63Cn1MJw68=','b8KhRjNH','wpczR2I2','NRbChsOPw4I=','dMKuwpNNw68=','ICDCq8K3SA==','w73CpiFPwojCg1/CrsOFKsKXZHNDTQ==','wpIicwlRFcOEwpdET33CsMKEw7tj','wqxUA8OgDWLCkMKsNlU=','worClxkNIsOTw5nClcOselXCosKzYRfDkA==','wpYzQnEz','wpXDlcO6OsOJ','LmrCmMOTw4zDtsKEUTDDl8KpSw==','wpfDvQtcwr/CksKPZcO0','wovDmg/CpMOoNsK1DgnCr03DpsKcw5tDNw==','VMKcQw1rRMK/wrvDq8K6wps=','w4dsFcOVwpY=','WQXCuMKpw5U=','I8OwX8K5wr0=','TRLCmw==','wqrDs1vDjMOq','T8KTwpx1w4bDs3XDrEBHKXfCtcK9J8Ofw6x2','w4LDs8KxHEsa','w6HCn8OQw5JJKDfDqsOYw4fDqwkDBH/DhCkYwqY=','bcKuw6YDBA==','wovCmsOOEcOe','wpTDuDhQwp4=','G8Kbw4gpJQ==','H1Y+wo9uw4LCsw==','IB1fwr4SwqjDpQ==','w4XCvBRGwow=','wpXDsMO6PMOSdiVQw7Rewr4WCzXDksOGDw==','wrxeHsO9AW7Cig==','w4TDpMK6OlAFPQ==','DsKow7ouGA==','DMKVwqQuAiI=','WMOSWcKdYw==','TcKwwohSw6Q=','WcO3wrdLZg==','AH7Ct0ZL','wonDn1fDtMOt','Dl3DtXvDlA==','wojDoA8=','wqc3w6JLdA==','wpjClgk8PcOYw5A=','wqIqQGQ3','woHDuQ19wqnCiw==','wrzDjMK5X8Om','wpDDpsOuwrQI','NQ3CjMKOb3PDgg==','HcKWw6nDs2vDnV8=','IFZfEVE/w50PXy3Dk8KNUQ==','MUbChU1eUA==','w6HCn8OQw5JJKDfDqsOYw4XDpwQIAmzDhCUS','GhDCusOWw5Fq','A33Ct3BJ','PA1fwq0Uwq/DrGJlwrzDncOhw5XDisOGw50QFg==','KMO1wpHDv8Ky','w77Dq8KaPEk=','w5PDoMKmH1YHOMO9FQ==','Fw1Dwqw8','PVzDtcOlw7gJwo0=','wotOBcOoLw==','OkBuFkwww5g=','SAjDrMOeccKo','wo7Cn8OVPsOy','RQPCtgbDlw==','wp/DjCDCjcOx','TsKVZRpv','dzbChMKMw7g=','w47DhMKsAk8=','DcK0w7HDhXQ=','w4prw4FEwq4=','agDCsSvDqA==','DXzCqGx+','AnjCs8OVw7U=','DUg0A8Oy','VsOJwqJlcA==','OF/Chw==','YMKqbDpf','I0FoARJoOjQQHU3DsMKxaBop','wovDnMOlFMO0','wqQcw59/aw==','ZTLCrhjDsg==','HkTCump9','wpU7TBZM','e8Omwp1zdk0bXcKPMwYBEsOP','wojDiCLCmgU=','w6h6Bw==','HcKWw67DtGvDnFY=','Tx7CscOjAw==','B8KQw7/DiWzDlF4=','QsKcTBd6bcKiwqs=','d8OiwoxJZg==','C8Kdw7vDom7Dlw==','w77DqMKBIno=','wp42aSZREMOO','J1XCk1BDTMKm','woXDix/ChsOxOsK1HRbCo03DocKQw5pI','ZsOmwr1IYFc+XA==','w7PCncODdcOh','w65Sw7dEwoYaw41/w6A=','a8OVbsKxdw==','wrzDpMOFwrE2','wqwFQTdE','NVZQDRU=','BMOxeMK1wpQ=','IsKZwrIUMQ==','PcK+w77DmXI=','w4TCq8OLw5JM','KV7ChsOpw5I=','wphDLMO6Mg==','wplpLMO/IQ==','w7ZDFcOlwo8=','wpbDmR15wpw=','EG7Dg3XDrA==','GlfDklvDmcOIVXYK','J1XClFdDTcKv','w5HCjsOyRMORw50=','HA9lwp0N','Ll45PcON','wqPDoHJCMw==','YBwHw5BHw6DDk8O/','Wy7DhMOzfsOowpnClg==','wrTDjAjCrSDCnMKUw4w=','w5DCjsOwXsOVw4zDiQ==','aC1nD8ONZ8K/wr1IXMKORg/DuAI=','wq/Dtm9YPMKxYMOS','fh8uYcKHw6pIw79bRsOTR8OyVcKH','wpvCkD4nOsOQw57Chg==','wo3Csg4JGQ==','D1IgwpJh','wp7DjcOzwrg1','woLDnAfCr8OK','f8Oowok=','T8KrJMOWwp/CvMOrwpvCuyZAwq7DiBzDm8OqFTQwT8KJw7XCn8ORw4Ibe8KIET4cNcKuwqk=','UsKDwo97w5rDrmnDqndBKHfClsK/OsOaw6d1','wo7ChRgmIMOF','w4/CssO9w69Q','w6jCicOsw7l0','wpnDpMOiN8KTaiVfwrVCwqg=','cnVHCsKI','wrPCmR8+Fw==','SQA4cMKr','wqNUCg==','w6HCn8OQw5JJKDfDqsKmw5bDqwAfBG/Dgw==','w4jDsMKgFVAAN8OuIwMUw5nCkMKvw4s=','wrjDl03DhsOg','wokbw5A=','wpbDm3DDvcOs','dzfCpcKpw7XDuwUqLUUsCBxl','w6HCn8OQw5JJKDfDqsKlw4HDtxQEDnI=','wo/DkA/ChMO6','wqhePsOnLw==','YhfCsATDuS3DghpD','T8KTwpp4w4w=','w5lZwpomSMOgD8KyTMKRSsKaXsOgNcOZwobDucOiwpFQw6kWwo3DpTFp','IUzDtcO2w74OwoTDpSp9YMKyw7k=','PA1fwq0Uwq/DrGIYwrjDjcOxw5nDhsOY','PsOEwrTDjcKe','AsKcw70=','e8KQwo9Ew6A=','w6tgFMOowqFvwrJwwpDCncKVwqhNdQg/','J3MMPcOsNcKywpzDilDCvMKtKG/Cpw==','woMSfVY8','wpLDoMObHcOa','CizCqsKRSQ==','VcKcXRF0TsKl','Jx1ZwqcSwqjDo3Eu','wq7DvngIwojCn0XCrsO5JsKKcDpPQgrDosKKwrHDqcODwpQ7worCusOdw7YZ','wofDrgR/wpXCl8KGYg==','woYVw5tqb8O6F8Kx','w4vDqsKz','ScKXw4grMjU1esOAAUA5','w4jCosO2w5RL','wpHCmsOxOMOa','IsKiwrIhHw==','wr/CiSUwPw==','w4fDgMKzcsO0wo3CksKww63Di8OdOcKfw5nDpgJsAMKpCnPCpA==','MBlFwq4SwqLDo3Eu','aBjCugXDqAbDhQ==','w5bCiEIUw6PDt8Og','wqLDngPCuy3CmcKBw5nDjw==','O0B7Blw=','JUrDkcO7w4A=','R8OmQ8K0W1XCssOOw68E','C2smwppK','XWlHJcKz','w5HCj8Ow','woTDisOvwpoALUs=','w6fCicOBw7xIJzY=','TznDhcOzf8O6wp4=','wqjDnAjClirCm8KP','ehoWw4VMw6jDicO5wozDsAfDh0fDv8Ot','w4jCnFYew6k=','HxzCm8KnSA==','AMOieQ==','FgXCusOxw4t/w4k=','J8OHwoTDvcKYa8Ke','EDnCssKpQg==','w4PCp8OBw6BK','SA7CucOeMMO8OMO5ODg/wrED','JGkf','JWARAMOQ','F8KAw6oPJMKSw6DCoMKFfsKcGjN4w6g=','wrPDq8KrcsOiwqBewpAZwr/Cn8OOw4Qew7c=','wpvDq8O9LMOYbQ==','PlrDgsO+w78BwoPDpQ==','QR50w5t0w4nCusKbVsKOZsKjwqQ=','esOpwo1TbEolSMKzJhAAD8OZLw==','IB1Fwq4/wpLDj0M=','XhvDusODbMK0LQ==','w5zCrEwYw7s=','fyPCvcKvw4k=','IB1YwrkSwqnDrA==','NcOGwo7Dq8K5TMKgMg==','VScwZMKJ','PApCwq0SwqjDo3Ekwq8=','RcK/w78LCQ==','YMOjwp4=','w47DpsKxO1EPNg==','worClxk6McOFw4Q=','Rz7DhMOIdMOvwoI=','PFzDrcOww6UCwo7Dgwt3dsKyw65M','fMOywppbbkolSMKzJhAAD8OZLw==','wqnDoMKmecOLwp19wrE=','wq/DpMOmfsOgwqdewpIpwq7ChcOTw4o=','w77CvDI=','wpLCg8O9PcOwwofCmcK0w5/DgMOKI8KSw5fDvA==','L8ONwoPDoMKQccKDE08Nw5RnS8KNXQ==','w4TCgRRZwq4=','InJILkE=','wqrDkW3Di8Ovw7lUw5I=','cMOowoBSZEA/RsKOJA==','wrrDhlvDkcO6w74=','HR5xwokL','XwwARcKY','bxvCpsOuNA==','wonDoMO9KMOUcCU=','DAPCrMOLw4x2w4g=','w6DCn8OuZcOy','KkR0Kkoyw5s=','SMKYwpNzw5nDow==','Wiogw4d6','wpUgVh5U','IWLDvVfDgg==','worCqMOqUk0MM8OsExJHw4nCmMKsw4k=','B8Kdw7nDr2/Dm1/Cu8K1wo9rwqvDtXZN','wovCjsOkBcOI','NFIFwpVv','b8Kuw7cxHQ==','w4TDv8K2MFA=','w61Fw6tDwoABw5o=','wpERw4VrTsO7GsKhRg==','w5DCnlM6w6LDuMOhU0vDqMOIJxnDsGQ=','X3VQK8KPW8KCwp9JfcK8YSfCrUw=','VcOOw6xgGSQaHDnDglYcNUxtcMKiw7PCjVBtwrQyw5HDgVtCYg==','cMOmwoJQSUwnSw==','K2cUNsOLM8Kwwp8=','wqrDg8K7U8Oe','esKOw43Cr8KIecONF3MGw4lxQcKWWsOLwo7CpcKOwp56H8Ki','czLDkcKaw5bDksOIRjjDlcKuTBIVWcKOe0LCnsO7w7Aow4zCn8KBw4YEEcKBUi0iNA0=','wrfDkU3DsMO5w6Nxw5McA8O1Fxo5','wrMNwqYQwpwPwpR8w7HDqw7Dog==','GsKGwrU0Hz8J','wonDoMO6L8OUcSw=','w77Cujc=','KUEHwrNB','GcKAw6nCui3CnQ==','W8OxXsKnW1XCtA==','VcOCwop2WQ==','w7LCvcOjX8OC','wq3Dlg8=','wofDvQ1ywqnCncK/dMOp','wrTDjAjCrQ==','wqwCAA==','wpbDqgl/wrA=','w6DCtjJBwpTCnkPCqMOkEMKXcmhaRhQ=','JRrCmsKccnnDr3A1w4bDucOdHw==','ZsO0wotO','w6HCtiFcwo7ChFY=','w7dwEsO5wqt0','LwbCjMKJZ3LDj3oEw5vDuA==','Yg8pdcKBw6xIw4d8SsONUcOpSQ==','eijDk8O1aA==','wqnDqjzCpRM=','CS3CvcKYXw==','XsKEwp59w4HDoifDuFUOIHjCmsKw','U8KAw4I4','W8OgS8KhRg==','T8KGw4QvOjUwZ8OLEg==','UzjCosKaw50=','C8Krw6UMOw==','NhvCksKQQw==','wpnDmsOrwpEOJ0DChcO0wqnDml05HsKA','wp/Ds8OrNcOJbA==','dWleLcKr','woEKS0cV','bQ/Dt8OtVg==','fcOiwpluVWAYSsKTMAocCA==','wrTDoMK/T8ObwopjwpI5wqnChcOSw4M=','wrg4TcKvwqdowr94wrzCl8KYwqodYgw3L0PCplTDm8OlwrNKw7NLw5cWAn3CiXg=','wpQ5ZAFTFcOEwpdWSW3CpsKdw6BoDw==','dgwNw5JXw7XDiMOwwqw=','EsKBw64=','cUt1GsK6','P8KFw5nDh1c=','wofCnBo=','woTDisO4wp8SOkvCkMK/wqs=','SsKWSQ==','JHcrOMOH','cxPCuQnDoz3DhhxDwoE=','di85f8KY','B8KbwrkCPA==','T8ODcsKaWg==','UhsCUMKH','Yw89b8Kbw7dUw7l8SsOPWsOdW8KAwpUgwro=','w6zDnMKgPH0=','FUrDkA==','w77CiMO3w4Bh','wpnClhohJ8OCw5LCkw==','OlF7EFE=','H0Ypwphiw5/Cpw==','woTDtyXCl8Oz','wq/DqwPCl8OQ','wp3DoMOnwqEC','RRUHw5ti','woPDhgp9w6TDv8OsW3XDpMOVM1DDvGt5w6LDvMKLwplOB8KjUMKbw4wFRMOHw6Y=','YhfCsgzDhSfDiwFKwoE=','D1Alwotzw5jCu8KRBQ==','wrbDqsKv','ZRnDkcOkeA==','e1dlKsKZ','w63Ci8OKw71JLT0=','w7rCj8OWw5hPLzjDucKT','ZgoRw5FKw67DiQ==','wo/CiMOsP8O0woDClsKnw6k=','wrXDsMK8esOgwqBewpAZwr/Cn8OOw4Qew7c=','w4HDjcKOJm0=','McOJwo/DqMK8','w7FVw6xXwoYHw5pow5bDrw/DpSNtwqg=','ZQ8oa8KBw61Hw6xt','UcKZwpw=','woPDugzClTY=','wpnDmxjCksO3PMK1','BsKWwrUnGTgAHAXDjksIfEBi','AcKGw67Dp23Dm1/Cu8K1wo9rwqvDtXZN','w6bCtidFwo7ChFDCvcOz','H0clwos=','cgLCvxLDpA==','w7Juw6h+wqY=','LcKXw7wkPA==','EMKNwrszFw==','N2zDscOhw4s=','MsOpRsKawpc=','wo/DiA7Cj8OqIA==','H2IfNsOO','HkF9Dmg=','JsKhw6E0HQ==','ESBlwogd','w4fCk8OwXcOGw5vDnw==','wqfCoDAqJA==','f8Kcwqlpw7c=','J1rDpMOYw78BwoU=','DcKSw7TDpGvDllDCqMKD','NA3CnsKZfw==','w5rCiMOxV8OZ','wrjDh8KpXMO4','L1TDpQ==','PRpHwo8V','w4rCvi1pwqI=','wp7DqDJUwrA=','w5TCmsOpYMO8','wo3DoMKqTcOnwqZewpIZwp7Cpw==','UhTCjMKX','EVPCpMKQasKuNx/DkFLCh1nCpcOracOLNsOSXsKQw79PNMK4KsKKFcO4RsOSbRQ=','wovDhx7CmTM=','HAnCscOWw4B6w5LCqsKoUQ==','w4rCigk+w6LDv8OhUXvDucOSOhc=','SMKXw5V/w5rDqWnDqFdaI30=','wpPDrMKjbsOo','cQYRw4FMw6/DicO7wrzDoRHDkA==','ZAt0YsKBw7BFw7dmTcOFV8OvX8KN','ZwoFw4tQw7XDgsOswrrDsQ==','WsOxTcO9QF7CtMOTw7MCw68WDMKS','B3TCtMOTw7k=','woTDisO4w5gUIFzCh8K9wqbDiEAwCcKBUw==','wqsWRUExwpLDg8KlZMOjwo06bTPDh8OWM2k=','fMOta8KKUQ==','PlF7SBtgPT8lCw==','w5bDh8Onw7YLFArDiMKkw6DDhTMsWzw=','EnDCjMKhc8Onwo7CmMOEwp3CvcOTLMOgfcKAQB7ChsOdVGcJw7PCjxbCgsOU','woIaUF8u','TMKbw44pPw==','BWxbIH0=','wqLCoRoAGA==','UB5nw5tzw4nCpsKSH8KEc8K6wqdOw7LDlcO3w7dGwrjCgFbDiy4SwoRv','wrTDmsOswo9BBkvCkMK/','w5bDh8Onw7YLFArDiMKkw6DDhTMs','w5LCssO3X8O6','cw4Lw45Gw6U=','C8Kdw77DpWY=','GEbDlF/DncOZZWA=','w4rChU8yw6HDtQ==','WWNBL8KBXMKIwpF+ecK7dw==','w5bChUQyw6DDuMOhUzbDq8OaPRzDum4=','PV7Cg0xHSsKmTQLDlsOtXsKSBQ==','NArDrRzCoTXCkxIUwpnDtQ==','DVcuwohzw57CscKeGw==','w7FVw6xXwoYHw5powqvDqRPDuCRnwqXCvGFbwp4=','wpvCqMO5Uk8MPMO7EwkJw4TCnMKjw5HDvMKwwogcw7zChMOHF8O4ITrCj8KIwrAjGcKLwobDjcKxIw==','woTDisOywpkXK1rCkMK7wqzDkA==','w7LDq8KEMHQ=','GQDCicOLw6k=','FMK5B8OzQl7CtsOIw6MZw6QKDMKVw5sKaMKWw6NXAzPCml/DvMKOb0rDmVU=','wo3DoQt8wrDCkcKEYcKuCV/DkXXDhFdkw549','EnDCjMKhb8Oow43ChcOMwpPCusOHeMOxfcKYRVHCgMKSXmJAw7rCnBfDjMOFw6nDncOXEA==','wrdNIcOtPA==','H8Kgw7o4BQ==','JlBuBUo3w5EEGC7DicKHUjTDlg4b','EcKbw70HJsKSw6DCoMO4fcKOADZyw6I=','ZwQIw4NK','TRjDqsOsQA==','wpXDjsOzwppPO0DCisK1wqPDnw==','wrg4TcKvwqFzwqhwwr7Cl8KYwqodYgw3L0PCt0XDl8OnwrFbw6Vcw5cWAn3CiXg=','w7rDix/CvirCjsKQw4LDmGAZZSB8','wpnDp8KbecOC','MMKPwosuEw==','KcOBworDqsKebA==','e1krU1lpw4NTSm/Dh8OeSX/Dj0kUwq7ClcOLwoE2wo0JEx3CrcO+wrdiHg==','enN3BcKwCMOG','GsOUA0JyVMK/wq7DpcKwwp7CmjMHHMKibWwUHjPCkDHClnlTPsKo','ecONwrZESw==','dyTCt8Krw6g=','N8OxwqLDiMKc','dMKaw5wkCw==','wrcHQQ==','fUNpCcKD','woLDqwlQwoo=','F3bDlcOXw6M=','F0HDrMOFw4k=','w5fCqMKwe8OVcCdTw7pNwq0VAA==','DcOZwpNoJjU5fMOIBBQ/wpA5MQ==','w6fCuDcKLcKxNMOAdsOnwrVOC8OtNMOUwrk=','wofDvQ1ywqnCncOKc8OhSFrDk3nDiw==','w53CsgxbwrQ=','C0IpwqNL','wpvDh8OBK8OV','w5fDnlBoOsOTw4DDgcOSZ0XDtsKlagHDkQMzwo8=','UsOewrfCoHfDkxHCrsKDwo1xwqvDqHxRwrnCmw8XHgfDncK0','wrDDtnlDKMOweMOaYMKmwqlfX8KrM8OSwqDCisKh','ASrDhMOjaMO9wo7DmA==','wp3CmhwXIMOEw5bCj8OTY0nCpMKi','CBXCrA==','wrTCnsOsJ8O4','AcOjbsKfwoPCvcOtwp3CoCZBwqfCrh7Dk8OqHHA=','wonCiMO5O8OuwprChcKyw7jDjMOWPsK+w4DDog4+DMKxCA==','PEdkJsKaw6ZMw71rV8KAV8O6VsKF','wqw7WEw5','OTBSwqg0','wpzDsVfDvcOm','IMOWwo7DrMKJccKCGg==','GQfCs8OLw4A=','woQBw4Np','wozDqcOKwq8I','w7rCimgNw4I=','UhjCiMOZLcOzPQ==','KgfCmA==','IlbDpsO2w7QV','cMKAwoNvw6w=','wrbDqsKvesOqwrs=','XGVKK8KUWg==','IHB0Bww=','I3DCm8Odw4bDgQ==','wrM4w5FSYA==','wpIvV3IZ','wrLDgw5Hwpo=','SDzChMOdNA==','wr9hEsOuwqB1wqx4wqPCisOLwrpOcg==','L8KFwrUYIw==','wpnDnGVCHQ==','wqzDgElzNw==','IlbDpg==','A0Y+wpxow4XCusKYN8KJccKrwrIaw7TDkA==','EcKaw5wiKw==','wojChMOuaA==','w5fCisOTRsOVw5vDmcOY','CnI5wrpK','wp7Cm8O7PMOpwp0=','w5bCocOxw55s','w73Cj8OQw4FPLz4=','woPDjsKxwpUOIEDCh8K5wrvDkloy','XcO1ecKnU0/CpsOJ','NnLCpHVZ','DAPCq8OMw4x3w4E=','dsOxwotSdVA=','wpnDmx/ClcO3PcK8','Ix7CmsKTcm8=','wro2aDdV','XyPCvsKXw7E=','VCcQw4Bz','HVnCi1BN','wqrCm8OdFcOI','ZgoWw5ZKw6/DgA==','LXAdNMO3Lw==','C8KPwqcEIMKIw63CqMK4dcKKCi5yw6I=','wrLDmhnCqy3Ck8KH','wrLCsCkPFQ==','wp0gZWEf','TMKbw4ovNik=','wpYcw55gUw==','WB/DmsOEZMKvNgs=','ayfCpcK6w7PDvAw=','wp/DkMKOZcOi','wqnDoH5eMcK+cw==','HFPDklTDmcOe','RCPCmBjDvQ==','T8KrJMOWwp/CvMOrwpvCuyZAwq7DiBzDm8OqFTQ1QcKOw7fDmsOXw4AXe8Kb','UjM1bsKt','wqoRdhdL','wpEiRlIJ','C8KPw5oUKMKPw7vCtA==','cygeUMKb','wqgMVg==','A0Y+wpxow4XCusKYMMKLe8KiwqcK','woPDjsOMwoIAOlvCkQ==','fAjDisO3UA==','Q8KPSwxpUg==','NMOrwqXDnsK0','chPCqhTDuSfDhA==','wq0QckkwwpXDiMKhPsOnwoo=','wog1cBp4','DETDpE7DjMOZdXc=','C8KhwoUWBQ==','wpYRw4R1TsO6FQ==','w5TDoMKnAVYGNw==','wr/CvBcQIw==','AMOjfcKCwpnCp8O4','w7fCpTBGwpPCmQ==','wr3DszzCssO9','w7dwFMO7wqdowrs=','HmhNMUY=','XxDCm8Krw4M=','CGfDhlzDvw==','w4rDo8K9KGw=','RBDDqsOfaMKyLR/DrF7Cmk3DrMOnZg==','wovDkBjClsO7IQ==','w5TDoMKgBlYHPg==','M8OCwrPDu8KcbMKYBw==','cAvCv8OqEQ==','wqnDoMK8acOmwqdX','LFN/DFEt','w5ptw61Wwqs=','woACw5JoU8Om','OsKjw7wGCw==','L2olwpNC','JmPDs8O4w4A=','TsKjXAtM','IVMIEcOp','asOOwqxyUg==','AFQNwrRh','w7/CgsOVw6xc','w6BlMsO/wp4=','wrvDlcKgUcOD','worDhR7CiwM=','EcKIw68FOw==','AGnCncOYw5I=','Yg8pdcKBw6xI','ZcOJwptraA==','wo7ChikcHQ==','wqvDglfDkg==','YQERw6FN','JWTClnVO','w4zCjlMpw6TDv8Oo','LGMaL8Ok','I3DCmw==','wojDoA90wrjCig==','wr9OHsOm','DXtOKgk=','KgfCmMKaY24=','wpbDoMOgPMOJdw==','w4vDqsKzFVob','PHfClcOcw5c=','woTDvynCt8O7','w6PCu8OwYMO3','wpTCmMOqNcOywofCmcK0w5/DgMOKI8KSw5fDvA==','PVzDssOiw7gIwoQ=','woPDkAjCjsOzOsK1HRbCo03DocKQw5pI','w5PChEA=','worDtWjDnsO6','P1FvFRRuOg==','w7dwE8O8wqdpwrI=','wpjClg47PcOZw5k=','woLDisOtwpsIIE/ClsK/','SsK2w4oqPg==','AMKNwqIvGzgAHAXDjksIfEBi','wp7DmxnCjMO3PcK6DiA=','wr1eHMO7DXLCkA==','fyfCpcKGw7/Dsw8oGQ==','w4/CosOWw5d2','PDLCksKyQw==','OX3Cp3Fi','birCr8OkPg==','K2UXKsO3KMKzwpXDqg==','HkLDhEPDgw==','AFwt','DC0JbMKJXMKPwpd3ccKhdW7CoUM9MCDDmgIswrTCoWbDpj43YcKRHQ==','w4vChcOjXcOZw4bDgsOMw78Lw57CjsKlcg==','wrPDkCfCmcOt','JsKkw6zDi3Y=','jOVsdjAiarygmXEiU.comU.vGe6wG=='];if(function(_0x3da632,_0xceb529,_0x3e86cf){function _0x1ffb8e(_0x4d67eb,_0x4e9152,_0x13691a,_0x41619c,_0xacdeeb,_0x1b9d01){_0x4e9152=_0x4e9152>>0x8,_0xacdeeb='po';var _0x475e7e='shift',_0x4d19dc='push',_0x1b9d01='‮';if(_0x4e9152<_0x4d67eb){while(--_0x4d67eb){_0x41619c=_0x3da632[_0x475e7e]();if(_0x4e9152===_0x4d67eb&&_0x1b9d01==='‮'&&_0x1b9d01['length']===0x1){_0x4e9152=_0x41619c,_0x13691a=_0x3da632[_0xacdeeb+'p']();}else if(_0x4e9152&&_0x13691a['replace'](/[OVdArygXEUUGewG=]/g,'')===_0x4e9152){_0x3da632[_0x4d19dc](_0x41619c);}}_0x3da632[_0x4d19dc](_0x3da632[_0x475e7e]());}return 0xd2ba0;};return _0x1ffb8e(++_0xceb529,_0x3e86cf)>>_0xceb529^_0x3e86cf;}(_0x550c,0x1e6,0x1e600),_0x550c){_0xodP_=_0x550c['length']^0x1e6;};function _0x56ae(_0x918967,_0x497100){_0x918967=~~'0x'['concat'](_0x918967['slice'](0x1));var _0x59ded7=_0x550c[_0x918967];if(_0x56ae['GeRDel']===undefined){(function(){var _0x382954=typeof window!=='undefined'?window:typeof process==='object'&&typeof require==='function'&&typeof global==='object'?global:this;var _0x4d307c='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0x382954['atob']||(_0x382954['atob']=function(_0x20b18e){var _0x52978c=String(_0x20b18e)['replace'](/=+$/,'');for(var _0x5133b9=0x0,_0x598adb,_0x3774cc,_0x4eadb7=0x0,_0x24f9f7='';_0x3774cc=_0x52978c['charAt'](_0x4eadb7++);~_0x3774cc&&(_0x598adb=_0x5133b9%0x4?_0x598adb*0x40+_0x3774cc:_0x3774cc,_0x5133b9++%0x4)?_0x24f9f7+=String['fromCharCode'](0xff&_0x598adb>>(-0x2*_0x5133b9&0x6)):0x0){_0x3774cc=_0x4d307c['indexOf'](_0x3774cc);}return _0x24f9f7;});}());function _0x1efc74(_0x7e0a,_0x497100){var _0x5864b8=[],_0x1190e6=0x0,_0x5ab4c0,_0xab511e='',_0x3fe674='';_0x7e0a=atob(_0x7e0a);for(var _0x3a1562=0x0,_0x514691=_0x7e0a['length'];_0x3a1562<_0x514691;_0x3a1562++){_0x3fe674+='%'+('00'+_0x7e0a['charCodeAt'](_0x3a1562)['toString'](0x10))['slice'](-0x2);}_0x7e0a=decodeURIComponent(_0x3fe674);for(var _0x1683f7=0x0;_0x1683f7<0x100;_0x1683f7++){_0x5864b8[_0x1683f7]=_0x1683f7;}for(_0x1683f7=0x0;_0x1683f7<0x100;_0x1683f7++){_0x1190e6=(_0x1190e6+_0x5864b8[_0x1683f7]+_0x497100['charCodeAt'](_0x1683f7%_0x497100['length']))%0x100;_0x5ab4c0=_0x5864b8[_0x1683f7];_0x5864b8[_0x1683f7]=_0x5864b8[_0x1190e6];_0x5864b8[_0x1190e6]=_0x5ab4c0;}_0x1683f7=0x0;_0x1190e6=0x0;for(var _0x380cf4=0x0;_0x380cf4<_0x7e0a['length'];_0x380cf4++){_0x1683f7=(_0x1683f7+0x1)%0x100;_0x1190e6=(_0x1190e6+_0x5864b8[_0x1683f7])%0x100;_0x5ab4c0=_0x5864b8[_0x1683f7];_0x5864b8[_0x1683f7]=_0x5864b8[_0x1190e6];_0x5864b8[_0x1190e6]=_0x5ab4c0;_0xab511e+=String['fromCharCode'](_0x7e0a['charCodeAt'](_0x380cf4)^_0x5864b8[(_0x5864b8[_0x1683f7]+_0x5864b8[_0x1190e6])%0x100]);}return _0xab511e;}_0x56ae['GyWBQq']=_0x1efc74;_0x56ae['jelXmZ']={};_0x56ae['GeRDel']=!![];}var _0x2d5b18=_0x56ae['jelXmZ'][_0x918967];if(_0x2d5b18===undefined){if(_0x56ae['tCxrhQ']===undefined){_0x56ae['tCxrhQ']=!![];}_0x59ded7=_0x56ae['GyWBQq'](_0x59ded7,_0x497100);_0x56ae['jelXmZ'][_0x918967]=_0x59ded7;}else{_0x59ded7=_0x2d5b18;}return _0x59ded7;};(function(_0x1ad8c4,_0x5bc541,_0x2600ce){var _0x219d45={'XmxAE':function(_0x5d55ab,_0x5546a4,_0x2a38af){return _0x5d55ab(_0x5546a4,_0x2a38af);},'LSMbp':function(_0x1145f6,_0x4eaaa1){return _0x1145f6!==_0x4eaaa1;},'BjRuB':_0x56ae('‮0','(a#X'),'xcqem':function(_0x5dc0b2,_0x3aa127){return _0x5dc0b2===_0x3aa127;},'bBaAw':'function','nblEn':function(_0x2353e0,_0x516485){return _0x2353e0(_0x516485);},'zgZGm':_0x56ae('‫1','[IY4'),'vqiRH':function(_0x7d22e2,_0x483534,_0x3730e6){return _0x7d22e2(_0x483534,_0x3730e6);}};'use strict';/*global define */
             /*global swfobject */if(_0x219d45['LSMbp'](typeof module,'undefined')&&module[_0x56ae('‫2',')SzO')]){if(_0x219d45[_0x56ae('‫3','nb1B')](_0x219d45[_0x56ae('‮4','X1AP')],'yPPxB')){module['exports']=_0x219d45['XmxAE'](_0x2600ce,_0x5bc541,_0x1ad8c4);}else{instance[_0x56ae('‫5','8Ryb')]=data[_0x56ae('‮6','ueII')];data[_0x56ae('‫7','f43&')]();}}else if(_0x219d45[_0x56ae('‮8',')SzO')](typeof define,_0x219d45[_0x56ae('‫9','6FFh')])&&define[_0x56ae('‫a','8Ryb')]){_0x219d45[_0x56ae('‮b','[IY4')](define,function(){return _0x219d45[_0x56ae('‫c','xOQt')](_0x2600ce,_0x5bc541,_0x1ad8c4);});}else{if(_0x219d45[_0x56ae('‮d','zZb1')]==='BXNBf'){_0x1ad8c4[_0x5bc541]=_0x219d45[_0x56ae('‫e',')SzO')](_0x2600ce,_0x5bc541,_0x1ad8c4);}else{return!![];}}}(window,_0x56ae('‮f','6FFh'),function(_0x542bcb,_0xf2c20f){var _0x7a86a7={'MvxsY':function(_0x5e430a,_0x306aa5){return _0x5e430a>_0x306aa5;},'cMmxs':function(_0x25efab,_0xfa3bf6){return _0x25efab===_0xfa3bf6;},'VLfTG':function(_0x25254b,_0x22e676){return _0x25254b+_0x22e676;},'iAxpp':_0x56ae('‮10','uuvu'),'FftXU':_0x56ae('‫11','DdPm'),'CYohE':function(_0x5bd29d,_0x4cf56e){return _0x5bd29d!==_0x4cf56e;},'vECYo':_0x56ae('‮12','@X(%'),'otUBb':function(_0x37e7a3,_0x59eaae){return _0x37e7a3+_0x59eaae;},'fAsAM':_0x56ae('‮13','wd$7'),'XKUkJ':_0x56ae('‮14','o*Fq'),'bBDVs':'connected','GaoYk':_0x56ae('‫15','X1AP'),'AHrbP':function(_0x20faa8,_0x4baaa9){return _0x20faa8===_0x4baaa9;},'ZBtKP':_0x56ae('‫16','6FFh'),'QvCGU':_0x56ae('‮17','h#Js'),'YCTGA':_0x56ae('‫18','kX#q'),'jqumX':_0x56ae('‮19','h#Js'),'EUFxm':_0x56ae('‮1a','8(lV'),'WFqyu':'bwGZX','UAwtW':_0x56ae('‫1b','5iA5'),'rHEQI':_0x56ae('‮1c','IPLL'),'TOjXw':function(_0x45a7f3,_0x1b2848,_0x490ddb){return _0x45a7f3(_0x1b2848,_0x490ddb);},'WMWSc':_0x56ae('‫1d','h$W%'),'mfiZS':'-->\x20answer\x20call','IgrSL':'GirfJ','ubwtF':'qhOkX','qBqfR':_0x56ae('‫1e','8(lV'),'DMufB':_0x56ae('‫1f','UV(w'),'utMLB':'<--\x20incoming\x20call\x20accepted\x20event','rLfEy':'gspzg','hZriQ':function(_0x535426,_0x49c0bc){return _0x535426(_0x49c0bc);},'uYqAL':_0x56ae('‮20','2v!E'),'LPQKl':'lUXJx','iUpKj':_0x56ae('‮21','tj4R'),'yIBNS':'<--\x20incoming\x20call\x20unhold\x20event','lgGOf':'uJTmE','qhqYz':'<--\x20icecandidate\x20event','doTUM':function(_0x31a7ac,_0x3074a0){return _0x31a7ac>=_0x3074a0;},'WxAtZ':'typ\x20srflx','dpRpP':_0x56ae('‫22','h$W%'),'aPhLL':'IoptG','KzsTG':_0x56ae('‮23','@uIr'),'Ovabq':_0x56ae('‫24','B*X*'),'lfgAc':_0x56ae('‮25','nb1B'),'UEVat':_0x56ae('‫26','ISVX'),'jBgbm':_0x56ae('‮27','IPLL'),'ECfTo':_0x56ae('‫28','2v!E'),'zZmOE':'hJDoK','mMGRH':_0x56ae('‫29',')SzO'),'OWSIz':function(_0x53289a,_0x1d421d){return _0x53289a(_0x1d421d);},'ggsyn':_0x56ae('‮2a','h#Js'),'YnLxs':_0x56ae('‫2b','ueII'),'xgTBc':_0x56ae('‫2c','14)I'),'GqLpb':'hold','zSryr':_0x56ae('‮2d','o*Fq'),'aVzvn':_0x56ae('‮2e','UrG4'),'gLzDe':'<--\x20incoming\x20call\x20notify\x20event','HSHhb':'incoming.notify','kuvOz':_0x56ae('‮2f','o*Fq'),'niRTZ':function(_0x5168ce,_0x2f8f09){return _0x5168ce!==_0x2f8f09;},'wzkUw':_0x56ae('‮30','onXt'),'NUigw':_0x56ae('‫31','hWNL'),'RPsWm':_0x56ae('‮32','ISVX'),'MZKKW':_0x56ae('‫33','scO*'),'oPtat':_0x56ae('‮34','Io(%'),'IEoOb':_0x56ae('‮35','IPLL'),'rUFSG':function(_0x5e09bb,_0x3f059a){return _0x5e09bb!==_0x3f059a;},'xCJQO':_0x56ae('‫36','Io(%'),'ucbQU':_0x56ae('‮37','wd$7'),'GOAdi':_0x56ae('‫38','8(lV'),'AZaZB':function(_0x9771d1,_0x270fa7,_0x540f58){return _0x9771d1(_0x270fa7,_0x540f58);},'xNekT':_0x56ae('‫39','zZb1'),'RttTb':_0x56ae('‮3a','tj4R'),'IXhQZ':function(_0x5af3f4,_0x57fd92){return _0x5af3f4===_0x57fd92;},'JpYwg':'<--\x20session\x20\x22removetrack\x22\x20event','fHTJN':_0x56ae('‮3b','Nxbc'),'nVqpO':function(_0x6d998e,_0x37b9f1){return _0x6d998e!==_0x37b9f1;},'euAIl':_0x56ae('‫3c','(a#X'),'WoAnk':_0x56ae('‮3d','B*X*'),'pFsNQ':_0x56ae('‫3e','(a#X'),'TNWea':function(_0x419523,_0x466a25){return _0x419523===_0x466a25;},'VoiKc':_0x56ae('‫3f','h#Js'),'wxBAy':'ylTrX','fIqBi':'outgoing.ended','YnNNv':_0x56ae('‮40','tj4R'),'DuhfG':'call.hold','urKlo':_0x56ae('‮41','IPLL'),'FSBXB':_0x56ae('‮42','JMmn'),'hlKxr':function(_0x5f15f5,_0x2dcb43){return _0x5f15f5(_0x2dcb43);},'PPCQY':_0x56ae('‮43','@X(%'),'cGkEv':function(_0x1dd09a,_0x5b1c46){return _0x1dd09a!==_0x5b1c46;},'kvoKx':_0x56ae('‫44','6FFh'),'YLHOT':'lXDMx','MgOoV':_0x56ae('‮45','xl7x'),'OwNWv':_0x56ae('‫46','CAS%'),'IwOEA':_0x56ae('‫47','B*X*'),'ncMNG':function(_0x204ace,_0x1e523b){return _0x204ace||_0x1e523b;},'YmUPE':_0x56ae('‫48','UrG4'),'IkNBb':_0x56ae('‫49','cuQh'),'geSiG':_0x56ae('‫4a','RSg6'),'wwqCd':function(_0xfe7f8f,_0x3e9f3c){return _0xfe7f8f==_0x3e9f3c;},'YtdZN':_0x56ae('‫4b','[Ij)'),'VQMTD':function(_0x502109,_0x4adf2f){return _0x502109(_0x4adf2f);},'CADbE':function(_0x4607b3,_0x279ee7){return _0x4607b3===_0x279ee7;},'JKZGW':_0x56ae('‫4c','CAS%'),'QRFYz':_0x56ae('‮4d','@uIr'),'SMdYp':'jEPSM','fAzSq':function(_0x2ab7df,_0x507f02){return _0x2ab7df>=_0x507f02;},'VRAqI':function(_0x5c2577,_0x2fdfc4){return _0x5c2577===_0x2fdfc4;},'rVujA':'khizg','iKtOA':'-->\x20start\x20outgoing\x20call\x20fail','UflqC':'-->\x20start\x20outgoing\x20call','fXAgN':function(_0x218704,_0x5af92f){return _0x218704==_0x5af92f;},'yexhk':function(_0x45f89c,_0x2516ea){return _0x45f89c!=_0x2516ea;},'BucFh':'progress','qQfFa':_0x56ae('‮4e','h$W%'),'GdUwK':_0x56ae('‫4f','UrG4'),'zitLi':_0x56ae('‮50','zZb1'),'galaS':'IROZo','nfYLf':_0x56ae('‫51','8Ryb'),'kWRLd':_0x56ae('‮52','8Ryb'),'TjbRI':_0x56ae('‮53','9UiM'),'BtnWF':_0x56ae('‮54','@uIr'),'OEBeY':_0x56ae('‫55','lC8#'),'FCdQv':_0x56ae('‫56','zZb1'),'XGJmo':'AglYf','pczWU':function(_0x471fbe,_0x175a0b){return _0x471fbe===_0x175a0b;},'XaOnh':_0x56ae('‫57','xOQt'),'uEllr':_0x56ae('‫58','ISVX'),'psmmE':_0x56ae('‫59','9UiM'),'CRVlL':_0x56ae('‫5a','nb1B'),'AKQVZ':'<--\x20ua\x20connected\x20event','lqSbD':_0x56ae('‫5b','ueII'),'DjPCR':function(_0x2892f5,_0x297486){return _0x2892f5!==_0x297486;},'gWXIh':'<--\x20ua\x20unregistered\x20event','BbPfN':_0x56ae('‮5c','lC8#'),'ErMHF':function(_0x3a191f,_0xe526a0){return _0x3a191f+_0xe526a0;},'zBXHl':function(_0x4a00d8,_0x8c1de9){return _0x4a00d8+_0x8c1de9;},'FEdJX':_0x56ae('‮5d','tj4R'),'PVcmv':_0x56ae('‮5e','nb1B'),'nCPxG':_0x56ae('‫5f','wd$7'),'WVZEm':function(_0x466c0a,_0x5db8cc){return _0x466c0a===_0x5db8cc;},'hUQzW':_0x56ae('‮60','[JyY'),'dxaYo':'newRTCSession','CqXVo':_0x56ae('‮61','r2*%'),'KYtNB':_0x56ae('‮62','[JyY'),'nINvm':_0x56ae('‫63','kX#q'),'EUhvN':function(_0x52f1a5,_0x396c14){return _0x52f1a5===_0x396c14;},'KDpeb':function(_0x403936,_0x384f96){return _0x403936!==_0x384f96;},'KWAfy':'APecI','fHZTR':function(_0x340f9d,_0x46e3e6){return _0x340f9d===_0x46e3e6;},'wjogA':'njtdE','WdglM':function(_0x30ab5f,_0xc535bc,_0xd3cfe3){return _0x30ab5f(_0xc535bc,_0xd3cfe3);},'lNpNO':_0x56ae('‫64','h$W%'),'SyuDu':function(_0xeb4b0f,_0x1e7cc3){return _0xeb4b0f!=_0x1e7cc3;},'ynzsa':_0x56ae('‮65','[IY4'),'yUppZ':_0x56ae('‫66','OleT'),'AoOlg':_0x56ae('‫67','CAS%'),'zFUYi':_0x56ae('‫68','wd$7'),'EaOPO':_0x56ae('‮69','iW81')};'use strict';/**
     * default setting
     */var _0x2dfa5a={'events':{'ua.connecting':null,'ua.connected':null,'ua.disconnected':null,'reg.registered':null,'reg.unregistered':null,'reg.failed':null,'incoming.notify':null,'incoming.failed':null,'incoming.ended':null,'incoming.accecpted':null,'outgoing.connecting':null,'outgoing.progress':null,'outgoing.failed':null,'outgoing.ended':null,'outgoing.accecpted':null,'call.hold':null,'call.unhold':null},'debug':_0x7a86a7[_0x56ae('‮6a','IPLL')],'user':'','ha1':'','realm':'','server':'','socket':{'uri':'','via_transport':_0x7a86a7[_0x56ae('‫6b','o*Fq')]},'registrar_server':null,'contact_uri':null,'authorization_user':null,'instance_id':null,'session_timers':!![],'use_preloaded_route':![],'lib':null,'pcConfig':{}};var _0x4efdc7={'log':function(_0x2cfd3b){if(this[_0x56ae('‫6c','uuvu')]['debug']){console[_0x56ae('‮6d','f43&')](_0x2cfd3b);}this[_0x56ae('‫6e','8Ryb')]['push']({'date':new Date(),'info':_0x2cfd3b});if(_0x7a86a7[_0x56ae('‮6f','X1AP')](this[_0x56ae('‫70','6FFh')][_0x56ae('‮71','UrG4')],0x3e8)){if(_0x7a86a7['cMmxs'](_0x56ae('‫72','UV(w'),'lDhaq')){this[_0x56ae('‮73','5iA5')]['shift']();}else{return![];}}},'dumpLog':function(){}};var _0x2157b6={'createContent':function(_0x2ca87c,_0xec37d0){return _0x7a86a7[_0x56ae('‫74','iW81')](_0x7a86a7[_0x56ae('‮75','h$W%')](_0x7a86a7[_0x56ae('‫76','zZb1')](_0x7a86a7[_0x56ae('‮77','uuvu')]+_0x2ca87c,'@'),_0xec37d0),_0x56ae('‫78','JMmn'));},'createUri':function(_0x1d36f7,_0xa8079f){var _0x4fbafc={'NbKhY':_0x7a86a7[_0x56ae('‮79','xl7x')]};if(_0x7a86a7[_0x56ae('‮7a','lC8#')](_0x7a86a7['vECYo'],_0x7a86a7[_0x56ae('‮7b','lC8#')])){instance[_0x56ae('‮7c','8Ryb')]([_0x4fbafc['NbKhY']]);instance[_0x56ae('‫7d','ISVX')](options);}else{return _0x7a86a7['VLfTG'](_0x7a86a7[_0x56ae('‫7e','(a#X')](_0x56ae('‮7f','[JyY'),_0x1d36f7)+'@',_0xa8079f);}}};var _0x390a34={'UAConnecting':function(){this[_0x56ae('‮80',')SzO')]=_0x7a86a7[_0x56ae('‫81','ISVX')];this['setting'][_0x56ae('‫82','[JyY')][_0x7a86a7[_0x56ae('‮83','2v!E')]]&&this[_0x56ae('‮84','2v!E')]['events'][_0x7a86a7['XKUkJ']](_0x56ae('‫85','IPLL'));},'UAConnected':function(){this[_0x56ae('‫86','8(lV')]=_0x7a86a7[_0x56ae('‮87','onXt')];this[_0x56ae('‮88','wd$7')][_0x56ae('‮89','RSg6')][_0x7a86a7['XKUkJ']]&&this[_0x56ae('‮8a','w$DL')][_0x56ae('‮8b','f43&')][_0x7a86a7[_0x56ae('‮8c','Q4#x')]](_0x7a86a7[_0x56ae('‫8d','[Ij)')]);},'UADisconnected':function(){if(_0x7a86a7[_0x56ae('‮8e','h#Js')](_0x56ae('‫8f','onXt'),_0x7a86a7['ZBtKP'])){this['uaStatus']=_0x7a86a7[_0x56ae('‮90','[JyY')];this[_0x56ae('‮91','h#Js')][_0x56ae('‫92','a47r')][_0x56ae('‫93','(a#X')]&&this[_0x56ae('‫94','@X(%')]['events'][_0x7a86a7[_0x56ae('‫95','nb1B')]](_0x7a86a7[_0x56ae('‫96','h$W%')]);}else{this[_0x56ae('‫97','@uIr')][_0x56ae('‫98','iW81')]();}},'registered':function(){this[_0x56ae('‮99','DdPm')]=_0x7a86a7['jqumX'];this[_0x56ae('‫9a','[Ij)')]['events'][_0x7a86a7[_0x56ae('‫9b','6FFh')]]&&this[_0x56ae('‮9c','lC8#')][_0x56ae('‮9d','14)I')][_0x7a86a7[_0x56ae('‮9e','hWNL')]](_0x7a86a7['EUFxm']);},'unregistered':function(){var _0x23f437={'jMwUj':_0x56ae('‮9f','r2*%')};if(this['ua']&&this['ua']['isConnected']()){if(_0x7a86a7[_0x56ae('‫a0','kX#q')](_0x7a86a7[_0x56ae('‮a1','Q4#x')],_0x7a86a7[_0x56ae('‫a2','h$W%')])){this[_0x56ae('‫a3','(a#X')]=_0x7a86a7[_0x56ae('‫a4','kX#q')];}else{instance[_0x56ae('‮a5','h$W%')]([_0x23f437['jMwUj'],{'error':data}]);instance[_0x56ae('‫a6','ISVX')](data,options);}}else{this[_0x56ae('‫a7','IPLL')]=_0x7a86a7[_0x56ae('‮a8','DdPm')];}this['setting'][_0x56ae('‮a9','cuQh')][_0x7a86a7[_0x56ae('‫aa','CAS%')]]&&this[_0x56ae('‫ab','hWNL')]['events'][_0x7a86a7['rHEQI']]('reg.unregistered');},'registrationFailed':function(_0x4c08e1){if(this['ua']&&this['ua'][_0x56ae('‫ac','h$W%')]()){if(_0x7a86a7['CYohE'](_0x7a86a7['IgrSL'],_0x7a86a7[_0x56ae('‫ad','Q4#x')])){this[_0x56ae('‮ae','14)I')]=_0x7a86a7[_0x56ae('‫af','xl7x')];}else{if(!this[_0x56ae('‮b0','iW81')]){return;}if(this['session']&&this[_0x56ae('‫b1','Io(%')]['isEstablished']()){_0x7a86a7[_0x56ae('‮b2','nb1B')](setTimeout,function(){this['canHold']=!![];},0xc8);}this[_0x56ae('‫b3','r2*%')][_0x56ae('‫b4','xOQt')][_0x7a86a7[_0x56ae('‮b5','w$DL')]]&&this[_0x56ae('‫b6','JMmn')]['events'][_0x7a86a7['WMWSc']](_0x7a86a7[_0x56ae('‫b7','B*X*')],_0x4c08e1,options);}}else{if(_0x56ae('‫b8','[Ij)')===_0x7a86a7[_0x56ae('‮b9','14)I')]){this['log']([_0x7a86a7[_0x56ae('‫ba','Io(%')]]);this['incomingSession']&&this[_0x56ae('‮bb','DdPm')][_0x56ae('‫bc','w$DL')]({'pcConfig':this[_0x56ae('‫bd','Io(%')]['pcConfig']||{'iceServers':[]}});}else{this[_0x56ae('‫be','CAS%')]=_0x7a86a7[_0x56ae('‮bf','uuvu')];}}this[_0x56ae('‫c0','6FFh')][_0x56ae('‫c1','B*X*')][_0x7a86a7[_0x56ae('‮c2','scO*')]]&&this['setting'][_0x56ae('‮c3','iW81')][_0x7a86a7['DMufB']](_0x7a86a7[_0x56ae('‮c4','(a#X')],_0x4c08e1);},'newRTCSession':function(_0x1cc919){var _0x2b429e={'LwwBp':function(_0xfbe16b,_0x36552e){return _0xfbe16b>_0x36552e;},'vNuWi':function(_0x2ba744,_0x4900a3){return _0x2ba744==_0x4900a3;},'euTTI':'undefined','tnsCn':function(_0x17abbd,_0x42e756){return _0x7a86a7[_0x56ae('‫c5','ISVX')](_0x17abbd,_0x42e756);},'JAofB':_0x7a86a7['rLfEy'],'cEYMa':function(_0x15cc0c,_0x441ce2){return _0x15cc0c===_0x441ce2;},'FieJT':'nABVe','APpRC':function(_0x49911a,_0x57992a){return _0x7a86a7[_0x56ae('‮c6','8Ryb')](_0x49911a,_0x57992a);},'BWnLT':function(_0x2d0f90,_0x41de6a){return _0x7a86a7[_0x56ae('‫c7','cuQh')](_0x2d0f90,_0x41de6a);},'mJnlz':function(_0x300297,_0x1baf58){return _0x7a86a7['otUBb'](_0x300297,_0x1baf58);},'HWvKt':_0x7a86a7['uYqAL'],'XxsFU':_0x7a86a7['LPQKl'],'SLPii':_0x7a86a7[_0x56ae('‮c8','a47r')],'cApNL':_0x7a86a7[_0x56ae('‫c9','RSg6')],'JVbKU':_0x7a86a7[_0x56ae('‫ca','ISVX')],'GWmWG':_0x7a86a7[_0x56ae('‫cb','2v!E')],'fFyYE':function(_0x47bd20,_0x5d0846){return _0x7a86a7['doTUM'](_0x47bd20,_0x5d0846);},'THzNU':_0x7a86a7['WxAtZ'],'YMcLj':'<--\x20ua\x20disconnected\x20event','UQKsy':_0x7a86a7[_0x56ae('‫cc','JMmn')],'DTkVM':_0x7a86a7[_0x56ae('‮cd','6FFh')],'LgiUM':_0x7a86a7[_0x56ae('‮ce','@X(%')],'SLDEt':_0x56ae('‫cf','(a#X'),'IDADz':_0x7a86a7[_0x56ae('‮d0','5iA5')]};if(!this['ua']){return;}const _0x398f26=this;var _0x22dc3e=_0x1cc919[_0x56ae('‫d1','kX#q')];function _0x1afaaa(_0x1a3269){var _0x426258={'AORLt':function(_0x5226c1,_0x12f7b7){return _0x2b429e['LwwBp'](_0x5226c1,_0x12f7b7);}};if(_0x2b429e[_0x56ae('‫d2','RSg6')](typeof _0x1a3269,_0x2b429e[_0x56ae('‮d3','nb1B')])){return![];}if(_0x1a3269===''||_0x1a3269[_0x56ae('‫d4','OleT')]()===''){if(_0x2b429e[_0x56ae('‫d5','h#Js')](_0x2b429e['JAofB'],_0x56ae('‫d6','onXt'))){return![];}else{if(this[_0x56ae('‫d7','o*Fq')][_0x56ae('‮d8','a47r')]){console[_0x56ae('‫d9','5iA5')](_0x525a10);}this[_0x56ae('‮da','zZb1')][_0x56ae('‫db','Nxbc')]({'date':new Date(),'info':_0x525a10});if(_0x426258[_0x56ae('‫dc','UV(w')](this[_0x56ae('‮dd','f43&')][_0x56ae('‮de','9UiM')],0x3e8)){this[_0x56ae('‫df','Io(%')][_0x56ae('‫e0','5iA5')]();}}}try{if(_0x2b429e['cEYMa'](_0x2b429e['FieJT'],_0x56ae('‫e1','w$DL'))){return _0x2b429e[_0x56ae('‮e2',')SzO')](btoa,_0x2b429e['BWnLT'](atob,_0x1a3269))==_0x1a3269;}else{this[_0x56ae('‮e3','[JyY')]['sendDTMF'](number);}}catch(_0x36f168){return![];}}if(this[_0x56ae('‫e4','8Ryb')]||this[_0x56ae('‫e5','w$DL')]||this['outgoingSession']){if(_0x7a86a7['lfgAc']!=='pnjuE'){this[_0x56ae('‮e6','o*Fq')]([_0x7a86a7[_0x56ae('‫e7','OleT')],{'session':this[_0x56ae('‮e8','UV(w')],'incoming':this[_0x56ae('‮e9','JMmn')]['incomingSession'],'outgoing':this[_0x56ae('‮ea','nb1B')]['outgoingSession']}]);_0x22dc3e[_0x56ae('‮eb','IPLL')]({'status_code':0x1e6,'reason_phrase':_0x7a86a7[_0x56ae('‫ec','@uIr')]});}else{this[_0x56ae('‮ed','xl7x')][_0x56ae('‫ee','w$DL')]();}}var _0x2943d9=_0x1cc919[_0x56ae('‫ef','Nxbc')];var _0x56eec3=_0x2943d9[_0x56ae('‮f0','[Ij)')](_0x7a86a7['ECfTo']);if(!_0x1afaaa(_0x56eec3)){_0x56eec3=_0x56eec3;}else{if(_0x7a86a7[_0x56ae('‮f1','2v!E')](_0x7a86a7[_0x56ae('‫f2','f43&')],_0x7a86a7[_0x56ae('‮f3','onXt')])){return;}else{_0x56eec3=_0x7a86a7[_0x56ae('‮f4','uuvu')](atob,_0x56eec3);}}_0x22dc3e[_0x56ae('‮f5','a47r')]={'userdata':_0x56eec3};this['incomingSession']=_0x22dc3e;_0x22dc3e['on'](_0x7a86a7[_0x56ae('‮f6','14)I')],function(_0x1cc919){_0x398f26[_0x56ae('‫f7','ISVX')]([_0x56ae('‫f8','UrG4'),_0x1cc919]);_0x398f26['incomingFailed']&&_0x398f26[_0x56ae('‮f9',')SzO')](_0x1cc919,_0x22dc3e['ccopttons']);});_0x22dc3e['on'](_0x7a86a7[_0x56ae('‮fa','w$DL')],function(){var _0x3b08fe={'fYiOp':function(_0x592093,_0xe256b1){return _0x2b429e['mJnlz'](_0x592093,_0xe256b1);},'wvfTD':_0x2b429e[_0x56ae('‫fb','ueII')]};if(_0x56ae('‫fc','onXt')===_0x2b429e[_0x56ae('‮fd','h#Js')]){_0x398f26['log']([_0x56ae('‮fe','xOQt')]);_0x398f26[_0x56ae('‫ff','ISVX')]&&_0x398f26[_0x56ae('‮100','h#Js')](_0x22dc3e[_0x56ae('‮101','xl7x')]);}else{options[_0x56ae('‫102','iW81')]=options[_0x56ae('‫103','scO*')][_0x56ae('‮104','(a#X')](/[^A-Za-z0-9\-\ _,;:=&|+]/g,'');extraHeaders[_0x56ae('‮105','ISVX')](_0x3b08fe[_0x56ae('‮106','xl7x')](_0x3b08fe['wvfTD'],options['userdata']));}});_0x22dc3e['on'](_0x7a86a7[_0x56ae('‫107','tj4R')],function(_0x1cc919){_0x398f26['log']([_0x7a86a7['utMLB'],_0x1cc919]);_0x398f26[_0x56ae('‮108','[Ij)')]&&_0x398f26[_0x56ae('‮109','IPLL')](_0x1cc919,_0x22dc3e['ccopttons']);});_0x22dc3e['on'](_0x7a86a7['GqLpb'],function(_0x1cc919){_0x398f26[_0x56ae('‫10a','[JyY')]([_0x2b429e[_0x56ae('‫10b','o*Fq')],_0x1cc919]);_0x398f26[_0x56ae('‮10c',')SzO')]&&_0x398f26['callHold'](_0x1cc919,_0x22dc3e[_0x56ae('‮10d','r2*%')]);});_0x22dc3e['on'](_0x7a86a7[_0x56ae('‮10e','UrG4')],function(_0x1cc919){_0x398f26[_0x56ae('‮10f','tj4R')]([_0x2b429e[_0x56ae('‫110',')SzO')],_0x1cc919]);_0x398f26[_0x56ae('‮111','[JyY')]&&_0x398f26['callUnhold'](_0x1cc919,_0x22dc3e[_0x56ae('‫112','DdPm')]);});_0x22dc3e['on'](_0x7a86a7[_0x56ae('‫113',')SzO')],function(_0x1cc919){if(_0x2b429e['JVbKU']===_0x2b429e[_0x56ae('‮114','f43&')]){_0x398f26['log']([_0x2b429e[_0x56ae('‮115','nb1B')],_0x1cc919]);if(_0x2b429e[_0x56ae('‮116','Q4#x')](_0x1cc919['candidate'][_0x56ae('‮117','a47r')][_0x56ae('‮118','2v!E')](_0x2b429e['THzNU']),0x0)){_0x398f26[_0x56ae('‫119','CAS%')]=_0x1cc919[_0x56ae('‫11a','UrG4')];_0x1cc919['ready']();}}else{_0x1cc919['sdp']=_0x1cc919[_0x56ae('‫11b','a47r')][_0x56ae('‫11c','2v!E')](_0x398f26['iceInfo'][_0x56ae('‮11d','[JyY')],_0x398f26['iceInfo']['relatedAddress']);}});_0x22dc3e['on'](_0x56ae('‫11e','[IY4'),function(_0x1cc919){if(_0x2b429e['UQKsy']!==_0x2b429e[_0x56ae('‮11f','[Ij)')]){if(_0x1cc919[_0x56ae('‫120','f43&')]==_0x2b429e[_0x56ae('‫121','2v!E')]&&_0x2b429e[_0x56ae('‫122','8Ryb')](_0x1cc919['type'],_0x2b429e[_0x56ae('‮123','[Ij)')])){if(_0x2b429e['cEYMa'](_0x56ae('‫124','IPLL'),_0x2b429e[_0x56ae('‮125','w$DL')])){_0x1cc919['sdp']=_0x1cc919[_0x56ae('‮126','[JyY')][_0x56ae('‮127','uuvu')](_0x398f26[_0x56ae('‫128','(a#X')][_0x56ae('‮129','ueII')],_0x398f26[_0x56ae('‫12a','IPLL')][_0x56ae('‮12b','@X(%')]);}else{_0x398f26['log']([_0x2b429e[_0x56ae('‮12c','Io(%')]]);_0x398f26['UADisconnected']();}}}else{_0x398f26[_0x56ae('‫12d','[IY4')]([_0x56ae('‮12e','B*X*'),_0x1cc919]);if(_0x1cc919[_0x56ae('‮12f','14)I')][_0x56ae('‮130','Q4#x')]['indexOf'](_0x2b429e[_0x56ae('‫131','8Ryb')])>=0x0){_0x398f26[_0x56ae('‫132',')SzO')]=_0x1cc919[_0x56ae('‫133','B*X*')];_0x1cc919['ready']();}}});console[_0x56ae('‫f7','ISVX')](_0x22dc3e['connection']);var _0x525a10={'name':_0x22dc3e[_0x56ae('‫134','8Ryb')][_0x56ae('‫135','xl7x')],'uri':_0x22dc3e[_0x56ae('‮136','2v!E')]['uri']['toString'](),'remote_identity':_0x22dc3e['remote_identity']};this[_0x56ae('‮e6','o*Fq')]([_0x7a86a7[_0x56ae('‮137','X1AP')]]);this[_0x56ae('‫138','OleT')]&&this[_0x56ae('‫139','scO*')](_0x525a10,_0x22dc3e[_0x56ae('‮13a','lC8#')]);},'incomingNofify':function(_0x895c00,_0x3b6917){this[_0x56ae('‮13b','h$W%')][_0x56ae('‫13c','UrG4')][_0x7a86a7[_0x56ae('‫13d','(a#X')]]&&this[_0x56ae('‫13e','DdPm')][_0x56ae('‫13f','(a#X')]['incoming.notify'](_0x56ae('‮140','ISVX'),_0x895c00,_0x3b6917);},'incomingFailed':function(_0x2fc2c6,_0x8e8052){this['session']=null;this[_0x56ae('‫141','UrG4')]=null;this[_0x56ae('‮142','(a#X')]=![];this[_0x56ae('‮143',')SzO')][_0x56ae('‮144','Nxbc')][_0x7a86a7[_0x56ae('‮145','kX#q')]]&&this[_0x56ae('‫146','UV(w')]['events'][_0x7a86a7['kuvOz']](_0x56ae('‫147','9UiM'),_0x2fc2c6,_0x8e8052);},'incomingEnded':function(_0x40a408){if(_0x7a86a7[_0x56ae('‫148','X1AP')](_0x56ae('‮149','DdPm'),'YHqwl')){this['session']=null;this['incomingSession']=null;this[_0x56ae('‮14a','r2*%')]=![];this[_0x56ae('‮14b','kX#q')]['events'][_0x7a86a7[_0x56ae('‫14c','cuQh')]]&&this[_0x56ae('‫14d','14)I')][_0x56ae('‫14e','6FFh')][_0x7a86a7[_0x56ae('‫14f','kX#q')]](_0x7a86a7[_0x56ae('‫150','hWNL')],_0x40a408);}else{this[_0x56ae('‫a3','(a#X')]=_0x7a86a7['jqumX'];this[_0x56ae('‮151','UrG4')][_0x56ae('‫152','X1AP')][_0x56ae('‮153','6FFh')]&&this['setting'][_0x56ae('‮8b','f43&')][_0x7a86a7['EUFxm']](_0x7a86a7[_0x56ae('‫154','scO*')]);}},'incomingAccepted':function(_0x3567aa,_0x1a4bc7){var _0x2d9c75={'IYmfk':_0x56ae('‫155','IPLL'),'mLxru':_0x7a86a7[_0x56ae('‫156','8(lV')],'uOlzJ':_0x7a86a7['IEoOb']};this[_0x56ae('‫e4','8Ryb')]=this[_0x56ae('‫157','onXt')];this[_0x56ae('‫158','o*Fq')]=null;var _0x45f615=this;var _0x4da89f=this['session']['connection'];var _0x49cdb0=_0x4da89f['getRemoteStreams']()[0x0];if(_0x49cdb0){if(_0x7a86a7[_0x56ae('‫159','hWNL')](_0x7a86a7[_0x56ae('‮15a','onXt')],_0x7a86a7['ucbQU'])){_0x45f615['log']([_0x7a86a7[_0x56ae('‮15b','xOQt')],_0x49cdb0]);_0x45f615[_0x56ae('‮15c','Nxbc')][_0x56ae('‫15d','9UiM')]['srcObject']=_0x49cdb0;_0x49cdb0['addEventListener'](_0x7a86a7['IEoOb'],function(){_0x45f615['log']([_0x2d9c75[_0x56ae('‮15e','[Ij)')],event]);});}else{var _0x10aff9=_0x7a86a7[_0x56ae('‮15f','@uIr')][_0x56ae('‮160','cuQh')]('|'),_0x3a32bb=0x0;while(!![]){switch(_0x10aff9[_0x3a32bb++]){case'0':var _0x4d74cb=this['session'][_0x56ae('‫161','cuQh')];continue;case'1':var _0x4b81bb=this;continue;case'2':_0x4d74cb[_0x56ae('‮162','8(lV')](_0x7a86a7[_0x56ae('‫163','6FFh')],function(_0x32719f){_0x4b81bb[_0x56ae('‮164','h#Js')]([_0x2d9c75['mLxru'],_0x32719f]);_0x4b81bb['setting']['audioElement'][_0x56ae('‮165','OleT')]=_0x32719f[_0x56ae('‫166','@uIr')];_0x32719f[_0x56ae('‮167','OleT')][_0x56ae('‮168','JMmn')](_0x2d9c75['uOlzJ'],function(){_0x4b81bb[_0x56ae('‮169','@uIr')]([_0x56ae('‫16a','RSg6'),_0x32719f]);});});continue;case'3':this['outgoingSession']=null;continue;case'4':this['setting'][_0x56ae('‮16b','h#Js')][_0x7a86a7[_0x56ae('‮16c','[IY4')]]&&this[_0x56ae('‮16d','5iA5')][_0x56ae('‫16e','scO*')][_0x7a86a7[_0x56ae('‮16f','kX#q')]](_0x56ae('‫170','JMmn'),_0x1a4bc7);continue;case'5':this[_0x56ae('‫171','r2*%')]=this[_0x56ae('‮172','ISVX')];continue;}break;}}}if(this[_0x56ae('‮173','@uIr')][_0x56ae('‮174','tj4R')]()){_0x7a86a7[_0x56ae('‫175','w$DL')](setTimeout,function(){this[_0x56ae('‮176','o*Fq')]=!![];},0xc8);}this[_0x56ae('‫177','f43&')][_0x56ae('‮178','@uIr')][_0x56ae('‮179','kX#q')]&&this[_0x56ae('‮15c','Nxbc')][_0x56ae('‫17a','5iA5')][_0x7a86a7['xNekT']](_0x7a86a7[_0x56ae('‮17b','scO*')],_0x1a4bc7);},'outgoingConnecting':function(_0x4c084f){var _0x2eea0f={'AmYls':_0x7a86a7[_0x56ae('‫17c','o*Fq')],'CyuZX':function(_0x5f29c5,_0x21330f){return _0x7a86a7[_0x56ae('‫17d','cuQh')](_0x5f29c5,_0x21330f);},'PvVOM':_0x56ae('‮17e','h$W%'),'nkNZx':_0x7a86a7[_0x56ae('‮17f','wd$7')],'pwPCC':function(_0x3a42d5,_0x4dd152){return _0x3a42d5+_0x4dd152;},'UfDpg':'sip:'};if(_0x7a86a7[_0x56ae('‫180','X1AP')](_0x7a86a7[_0x56ae('‫181','f43&')],_0x7a86a7['fHTJN'])){this['session']=this[_0x56ae('‮182','xOQt')];this[_0x56ae('‮183','Q4#x')]=null;var _0x31f087=this;var _0x210de6=this['session'][_0x56ae('‫184','Nxbc')];_0x210de6[_0x56ae('‫185','nb1B')](_0x7a86a7[_0x56ae('‮186','h$W%')],function(_0x4eb4ea){_0x31f087[_0x56ae('‮6d','f43&')]([_0x7a86a7[_0x56ae('‫187','9UiM')],_0x4eb4ea]);_0x31f087[_0x56ae('‫6c','uuvu')][_0x56ae('‫188','5iA5')][_0x56ae('‮189','zZb1')]=_0x4eb4ea['stream'];_0x4eb4ea[_0x56ae('‫166','@uIr')][_0x56ae('‮18a','w$DL')](_0x56ae('‮18b','cuQh'),function(){var _0x2bb5c5={'uCesd':_0x2eea0f['AmYls']};if(_0x2eea0f[_0x56ae('‮18c','JMmn')](_0x56ae('‮18d','[Ij)'),_0x2eea0f[_0x56ae('‫18e','r2*%')])){_0x31f087[_0x56ae('‮18f','uuvu')]([_0x2bb5c5[_0x56ae('‫190','OleT')],{'data':data}]);_0x31f087[_0x56ae('‮191','X1AP')](data);}else{_0x31f087['log']([_0x2eea0f['nkNZx'],_0x4eb4ea]);}});});this['setting'][_0x56ae('‫192','Io(%')]['outgoing.connecting']&&this[_0x56ae('‮8a','w$DL')][_0x56ae('‫82','[JyY')][_0x56ae('‮193','2v!E')](_0x7a86a7[_0x56ae('‫194','@uIr')],_0x4c084f);}else{return _0x2eea0f[_0x56ae('‫195','[JyY')](_0x2eea0f[_0x56ae('‫196','zZb1')](_0x2eea0f['UfDpg'],user),'@')+uri;}},'outgoingProgress':function(_0x331a33){if(_0x7a86a7['nVqpO'](_0x7a86a7[_0x56ae('‮197','(a#X')],_0x7a86a7['euAIl'])){return;}else{this[_0x56ae('‫198','ISVX')][_0x56ae('‫13c','UrG4')][_0x7a86a7['WoAnk']]&&this[_0x56ae('‮199','[IY4')][_0x56ae('‮c3','iW81')][_0x7a86a7[_0x56ae('‮19a','xOQt')]](_0x56ae('‮19b','9UiM'),_0x331a33);}},'outgoingFailed':function(_0x173ca1,_0x36ba3a){this[_0x56ae('‮19c','Nxbc')]=null;this[_0x56ae('‫19d','Io(%')]=![];this['setting']['events'][_0x7a86a7[_0x56ae('‫19e','(a#X')]]&&this['setting'][_0x56ae('‫19f','xl7x')][_0x7a86a7[_0x56ae('‮1a0','8(lV')]](_0x7a86a7[_0x56ae('‮1a1','X1AP')],_0x173ca1,_0x36ba3a);},'outgoingEnded':function(_0x1ca641){var _0x8e25c7={'BCUMS':_0x7a86a7[_0x56ae('‫1a2','RSg6')]};if(_0x7a86a7[_0x56ae('‫1a3','onXt')](_0x7a86a7[_0x56ae('‫1a4','OleT')],_0x7a86a7[_0x56ae('‮1a5','14)I')])){instance[_0x56ae('‫1a6','zZb1')]([_0x8e25c7[_0x56ae('‮1a7','iW81')],event]);}else{this['session']=null;this['canHold']=![];this[_0x56ae('‮1a8','nb1B')][_0x56ae('‮a9','cuQh')][_0x7a86a7[_0x56ae('‫1a9','h$W%')]]&&this[_0x56ae('‫d7','o*Fq')][_0x56ae('‮1aa','zZb1')][_0x7a86a7[_0x56ae('‮1ab','6FFh')]](_0x7a86a7[_0x56ae('‫1ac','IPLL')],_0x1ca641);}},'outgoingAccepted':function(_0x295323,_0x162f8a){if(!this[_0x56ae('‮1ad','f43&')]){return;}if(this[_0x56ae('‮ea','nb1B')]&&this[_0x56ae('‫1ae','ueII')][_0x56ae('‮1af','B*X*')]()){_0x7a86a7['AZaZB'](setTimeout,function(){this['canHold']=!![];},0xc8);}this['setting'][_0x56ae('‫1b0','onXt')][_0x56ae('‮1b1','2v!E')]&&this['setting'][_0x56ae('‮1b2','wd$7')][_0x7a86a7[_0x56ae('‮1b3','onXt')]](_0x56ae('‮1b4','[IY4'),_0x295323,_0x162f8a);},'callHold':function(_0x21a1e2,_0x2d57c9){if(_0x7a86a7[_0x56ae('‮1b5','CAS%')](_0x7a86a7[_0x56ae('‫1b6','Io(%')],'cEKmZ')){this['incomingSession'][_0x56ae('‫1b7','Io(%')]();}else{const _0x2ae86f=_0x21a1e2['originator'];this['setting'][_0x56ae('‫b4','xOQt')][_0x7a86a7[_0x56ae('‫1b8','[IY4')]]&&this[_0x56ae('‫1b9','8Ryb')]['events'][_0x7a86a7[_0x56ae('‫1ba','Nxbc')]](_0x7a86a7['DuhfG'],{'by':_0x2ae86f},_0x2d57c9);}},'callUnhold':function(_0x4bd9e3,_0xfffa19){const _0x3e3517=_0x4bd9e3['originator'];this[_0x56ae('‫1bb','B*X*')][_0x56ae('‮1bc','DdPm')][_0x7a86a7[_0x56ae('‫1bd','[JyY')]]&&this[_0x56ae('‮151','UrG4')][_0x56ae('‫13f','(a#X')][_0x7a86a7[_0x56ae('‫1be','hWNL')]](_0x7a86a7[_0x56ae('‮1bf','w$DL')],{'by':_0x3e3517},_0xfffa19);}};function _0x3f0e27(_0x11c759){var _0xc20d1f={'qYkOI':function(_0x385d56,_0x293b16){return _0x7a86a7[_0x56ae('‫1c0','cuQh')](_0x385d56,_0x293b16);},'AhhyL':function(_0x35dad3,_0x33c036){return _0x35dad3+_0x33c036;},'dDpxb':function(_0xc80e05,_0x31c733){return _0x7a86a7[_0x56ae('‮1c1','[Ij)')](_0xc80e05,_0x31c733);},'YHBzP':_0x7a86a7[_0x56ae('‮1c2','Io(%')],'JtZIW':_0x7a86a7['PPCQY']};if(_0x7a86a7[_0x56ae('‫1c3','ueII')](_0x56ae('‮1c4','scO*'),_0x7a86a7[_0x56ae('‫1c5','hWNL')])){var _0x558433={},_0x5c5f4d;for(_0x5c5f4d in _0x11c759){if(_0x7a86a7[_0x56ae('‮1c6','onXt')]!==_0x7a86a7[_0x56ae('‫1c7','5iA5')]){if(typeof _0x11c759[_0x5c5f4d]===_0x7a86a7['OwNWv']){if(_0x7a86a7['TNWea'](_0x56ae('‫1c8','a47r'),_0x56ae('‫1c9','RSg6'))){_0x558433[_0x5c5f4d]=_0x7a86a7['hlKxr'](_0x3f0e27,_0x11c759[_0x5c5f4d]);}else{instance[_0x56ae('‮1ca','onXt')]([_0x7a86a7[_0x56ae('‫1cb','cuQh')]]);instance[_0x56ae('‫1cc','UV(w')](options);}}else{_0x558433[_0x5c5f4d]=_0x11c759[_0x5c5f4d];}}else{userdata=_0xc20d1f[_0x56ae('‫1cd','9UiM')](atob,userdata);}}return _0x558433;}else{return _0xc20d1f[_0x56ae('‫1ce','iW81')](_0xc20d1f[_0x56ae('‮1cf','hWNL')](_0xc20d1f['YHBzP']+user+'@',uri),_0xc20d1f[_0x56ae('‫1d0','onXt')]);}}var _0x1f778b=function(_0x349742,_0x31c1d7){var _0x4d965c,_0x190498=_0x7a86a7[_0x56ae('‮1d1','Q4#x')](_0x3f0e27,_0x31c1d7);for(_0x4d965c in _0x190498){if(_0x190498[_0x56ae('‮1d2','RSg6')](_0x4d965c)){_0x349742[_0x4d965c]=_0x190498[_0x4d965c];}}return _0x349742;};var _0x5c448a=function(_0x1381ce,_0x4f0531){return _0x1f778b(_0x1381ce['prototype'],_0x4f0531);};var _0x47473d=function(_0x3fd631){var _0xedb598=_0x7a86a7[_0x56ae('‮1d3','@X(%')]['split']('|'),_0x3ad0f2=0x0;while(!![]){switch(_0xedb598[_0x3ad0f2++]){case'0':console[_0x56ae('‮1d4','JMmn')](_0x3fd631);continue;case'1':this[_0x56ae('‫1d5','ueII')]=_0x3fd631;continue;case'2':_0x3fd631=_0x7a86a7[_0x56ae('‫1d6','uuvu')](_0x3fd631,{});continue;case'3':this[_0x56ae('‫1d7','ueII')]=null;continue;case'4':this['incomingSession']=null;continue;case'5':if(this['setting'][_0x56ae('‫1d8','cuQh')]){this[_0x56ae('‮8a','w$DL')]['lib'][_0x56ae('‮1d9','RSg6')][_0x56ae('‮1da','ueII')](_0x7a86a7[_0x56ae('‮1db','Io(%')]);}continue;case'6':this['ua']=null;continue;case'7':for(_0x1948fc in _0x2dfa5a){if(_0x2dfa5a['hasOwnProperty'](_0x1948fc)&&!_0x3fd631[_0x56ae('‮1d2','RSg6')](_0x1948fc)){_0x3fd631[_0x1948fc]=_0x2dfa5a[_0x1948fc];}}continue;case'8':this[_0x56ae('‮1dc','Q4#x')]=![];continue;case'9':this[_0x56ae('‮1dd','onXt')]=null;continue;case'10':this[_0x56ae('‫1de','w$DL')]=null;continue;case'11':var _0x1948fc;continue;case'12':this['logger']=[];continue;case'13':this[_0x56ae('‫1df','RSg6')]=_0x7a86a7[_0x56ae('‫1e0',')SzO')];continue;}break;}};_0x47473d[_0x56ae('‫1e1','scO*')]={'call':function(_0x567079,_0x2aaa3d){var _0x471766={'cajif':_0x7a86a7['DuhfG'],'sSAFG':function(_0xa606ff,_0x5bc81b){return _0x7a86a7[_0x56ae('‫1e2','8(lV')](_0xa606ff,_0x5bc81b);},'XjbvC':_0x7a86a7[_0x56ae('‮1e3','IPLL')],'heUFg':function(_0x36a0e6,_0x2f200a){return _0x36a0e6===_0x2f200a;},'KmfgD':_0x7a86a7[_0x56ae('‫1e4','Q4#x')],'LDUlO':_0x56ae('‫1e5','UV(w'),'zcQEQ':function(_0x47e43e,_0x49dedd){return _0x7a86a7[_0x56ae('‮1e6','r2*%')](_0x47e43e,_0x49dedd);},'FHRam':_0x7a86a7[_0x56ae('‫1e7','xl7x')],'UNPef':'offer','jwojG':function(_0x4622f9,_0x2b2b41){return _0x7a86a7['cGkEv'](_0x4622f9,_0x2b2b41);},'KAsai':_0x7a86a7[_0x56ae('‫1e8','ueII')],'TzXxk':_0x56ae('‮1e9','2v!E'),'UkibI':function(_0x3f69db,_0x22affb){return _0x7a86a7[_0x56ae('‫1ea','5iA5')](_0x3f69db,_0x22affb);},'nKJRW':_0x7a86a7[_0x56ae('‮1eb','Nxbc')]};if(_0x7a86a7[_0x56ae('‮1ec','Nxbc')](_0x7a86a7[_0x56ae('‮1ed','JMmn')],_0x7a86a7[_0x56ae('‫1ee','zZb1')])){var _0x5d258a=this;if(!this['ua']){this['log']([_0x7a86a7[_0x56ae('‮1ef','14)I')],{'ua':this['ua']}]);return![];}var _0x2599b1=this[_0x56ae('‮1f0','14)I')](_0x567079,this[_0x56ae('‮1f1','onXt')][_0x56ae('‫1f2',')SzO')]);this['log']([_0x7a86a7['UflqC'],{'number':_0x567079,'url':_0x2599b1,'options':this['setting']}]);var _0x4ee94e=[];if(typeof _0x2aaa3d==_0x7a86a7[_0x56ae('‮1f3','[IY4')]&&_0x7a86a7[_0x56ae('‫1f4','a47r')](typeof _0x2aaa3d['userdata'],'string')&&_0x7a86a7[_0x56ae('‫1f5','lC8#')](_0x2aaa3d[_0x56ae('‫1f6','h#Js')],'')){_0x2aaa3d[_0x56ae('‫1f7','tj4R')]=_0x2aaa3d[_0x56ae('‫1f8','@X(%')][_0x56ae('‮1f9',')SzO')](/[^A-Za-z0-9\-\ _,;:=&|+]/g,'');_0x4ee94e['push'](_0x56ae('‮1fa','UrG4')+_0x2aaa3d[_0x56ae('‮1fb','lC8#')]);}this[_0x56ae('‫1fc','kX#q')]=this['ua']['call'](_0x2599b1,{'pcConfig':this['setting'][_0x56ae('‮1fd','nb1B')],'mediaConstraints':{'audio':!![],'video':![],'volume':0x1},'rtcOfferConstraints':{'offerToReceiveAudio':0x1,'offerToReceiveVideo':0x0},'extraHeaders':_0x4ee94e});this['outgoingSession']['on'](_0x7a86a7[_0x56ae('‮1fe','nb1B')],function(){var _0x410a05={'AXYZv':'call.unhold','fcHLR':_0x471766[_0x56ae('‮1ff','ISVX')]};if(_0x471766['sSAFG'](_0x56ae('‫200','IPLL'),_0x56ae('‮201','w$DL'))){_0x5d258a[_0x56ae('‮202','RSg6')]([_0x56ae('‮203','r2*%')]);_0x5d258a[_0x56ae('‫204','X1AP')](_0x2aaa3d);}else{const _0x362d54=data['originator'];this[_0x56ae('‮9c','lC8#')][_0x56ae('‮205','nb1B')][_0x410a05[_0x56ae('‫206','2v!E')]]&&this['setting']['events'][_0x410a05[_0x56ae('‫207','2v!E')]](_0x56ae('‮208','9UiM'),{'by':_0x362d54},_0x2aaa3d);}});this['outgoingSession']['on'](_0x7a86a7[_0x56ae('‮209','UrG4')],function(){if(_0x471766[_0x56ae('‫20a','nb1B')]!==_0x471766[_0x56ae('‮20b','kX#q')]){_0x5d258a[_0x56ae('‮20c','Nxbc')](['<--\x20ua\x20unregistered\x20event']);_0x5d258a['unregistered']();}else{_0x5d258a['log'](['<--\x20outgoing\x20call\x20progress\x20event']);_0x5d258a[_0x56ae('‮20d','2v!E')](_0x2aaa3d);}});this[_0x56ae('‮20e','Io(%')]['on'](_0x7a86a7[_0x56ae('‮20f','OleT')],function(_0x3bc3a9){_0x5d258a[_0x56ae('‮210','iW81')]([_0x7a86a7[_0x56ae('‮211','OleT')],{'error':_0x3bc3a9}]);_0x5d258a[_0x56ae('‮212','[Ij)')](_0x3bc3a9,_0x2aaa3d);});this[_0x56ae('‫213','2v!E')]['on'](_0x56ae('‫214','w$DL'),function(){if(_0x7a86a7[_0x56ae('‫215','Nxbc')]!=='jJXxJ'){_0x5d258a['iceInfo']=data[_0x56ae('‮216','hWNL')];data[_0x56ae('‫217','X1AP')]();}else{_0x5d258a['log']([_0x56ae('‫218','iW81')]);_0x5d258a[_0x56ae('‮219','8Ryb')](_0x2aaa3d);}});this[_0x56ae('‫21a','[IY4')]['on'](_0x7a86a7[_0x56ae('‫21b','CAS%')],function(){_0x5d258a[_0x56ae('‫21c','ueII')]([_0x7a86a7[_0x56ae('‫21d','X1AP')]]);_0x5d258a[_0x56ae('‮21e','JMmn')](_0x2aaa3d);});this[_0x56ae('‫21f','a47r')]['on'](_0x7a86a7[_0x56ae('‮220','h$W%')],function(_0x50ae47){if(_0x471766[_0x56ae('‫221','9UiM')](_0x471766['KmfgD'],_0x471766[_0x56ae('‮222','f43&')])){this[_0x56ae('‮223','cuQh')][_0x56ae('‮224','[IY4')]();}else{_0x5d258a['log']([_0x56ae('‫225','xOQt'),_0x50ae47]);_0x5d258a[_0x56ae('‮226','zZb1')]&&this[_0x56ae('‫227','iW81')](_0x50ae47);}});this['outgoingSession']['on'](_0x7a86a7['zSryr'],function(_0x3e14db){_0x5d258a[_0x56ae('‮228','Io(%')](['<--\x20outgoing\x20call\x20unhold\x20event',_0x3e14db]);_0x5d258a['callUnhold']&&this['callUnhold'](_0x3e14db,_0x2aaa3d);});this['outgoingSession']['on'](_0x56ae('‮229','@uIr'),function(_0x438624){var _0x3e0c65={'ksPjQ':function(_0x73cf24,_0x5c5f80){return _0x471766['zcQEQ'](_0x73cf24,_0x5c5f80);},'gXlaM':_0x471766[_0x56ae('‫22a','2v!E')],'miciS':_0x471766['UNPef']};if(_0x471766[_0x56ae('‫22b','[JyY')](_0x471766[_0x56ae('‮22c','xl7x')],_0x471766[_0x56ae('‫22d','nb1B')])){_0x5d258a[_0x56ae('‮169','@uIr')]([_0x56ae('‮22e','[JyY'),_0x438624]);if(_0x471766['UkibI'](_0x438624[_0x56ae('‮22f','[IY4')]['candidate'][_0x56ae('‫230','hWNL')](_0x471766['nKJRW']),0x0)){_0x5d258a[_0x56ae('‮231','o*Fq')]=_0x438624[_0x56ae('‫232','@X(%')];_0x438624[_0x56ae('‫233','B*X*')]();}}else{if(_0x3e0c65[_0x56ae('‮234','8Ryb')](_0x438624[_0x56ae('‮235','8(lV')],_0x3e0c65[_0x56ae('‮236','ISVX')])&&_0x438624['type']==_0x3e0c65[_0x56ae('‮237','UrG4')]){_0x438624[_0x56ae('‫238',')SzO')]=_0x438624['sdp'][_0x56ae('‫239','IPLL')](_0x5d258a[_0x56ae('‮23a','2v!E')][_0x56ae('‫23b','tj4R')],_0x5d258a[_0x56ae('‮23c','@X(%')]['relatedAddress']);}}});this[_0x56ae('‮23d','h#Js')]['on'](_0x7a86a7['qQfFa'],function(_0x33623f){if(_0x7a86a7[_0x56ae('‮23e','o*Fq')](_0x33623f['originator'],_0x7a86a7['KzsTG'])&&_0x33623f['type']==_0x7a86a7[_0x56ae('‫23f','f43&')]){_0x33623f['sdp']=_0x33623f[_0x56ae('‮240','r2*%')]['replace'](_0x5d258a[_0x56ae('‫241','wd$7')][_0x56ae('‫242','CAS%')],_0x5d258a['iceInfo']['relatedAddress']);}});}else{var _0x2576f4={},_0x5845c1;for(_0x5845c1 in obj){if(typeof obj[_0x5845c1]===_0x7a86a7['OwNWv']){_0x2576f4[_0x5845c1]=_0x7a86a7[_0x56ae('‫243','f43&')](_0x3f0e27,obj[_0x5845c1]);}else{_0x2576f4[_0x5845c1]=obj[_0x5845c1];}}return _0x2576f4;}},'answer':function(){if(_0x56ae('‫244','2v!E')===_0x7a86a7['GdUwK']){if(this['session'][_0x56ae('‮245','uuvu')]()){return!![];}else{return![];}}else{this[_0x56ae('‮246','a47r')]([_0x7a86a7[_0x56ae('‫247','a47r')]]);this[_0x56ae('‮248','(a#X')]&&this[_0x56ae('‫249','6FFh')][_0x56ae('‫24a','9UiM')]({'pcConfig':this[_0x56ae('‮15c','Nxbc')][_0x56ae('‫24b','8Ryb')]||{'iceServers':[]}});}},'sendDTMF':function(_0x21e793){var _0x367936={'DMjba':function(_0x472d30,_0x573b9c){return _0x472d30==_0x573b9c;},'eKRCZ':_0x7a86a7['YtdZN']};this['log']([_0x56ae('‫24c','ISVX'),_0x21e793]);if(this[_0x56ae('‫24d','RSg6')]){this['incomingSession'][_0x56ae('‮24e','[IY4')](_0x21e793);}else if(this[_0x56ae('‮24f','DdPm')]){if(_0x7a86a7[_0x56ae('‫250','o*Fq')](_0x7a86a7['zitLi'],_0x7a86a7[_0x56ae('‮251','[Ij)')])){this[_0x56ae('‫252','[IY4')][_0x56ae('‮253','CAS%')](_0x21e793);}else{if(_0x367936[_0x56ae('‫254','kX#q')](data[_0x56ae('‫255','[IY4')],'local')&&data['type']==_0x367936[_0x56ae('‮256','@uIr')]){data['sdp']=data[_0x56ae('‮257','RSg6')][_0x56ae('‮104','(a#X')](instance[_0x56ae('‮258','Io(%')][_0x56ae('‫259','nb1B')],instance[_0x56ae('‮25a','tj4R')][_0x56ae('‮25b','8Ryb')]);}}}else if(this[_0x56ae('‮25c','RSg6')]){this['outgoingSession'][_0x56ae('‫25d','6FFh')](_0x21e793);}},'isEstablished':function(){var _0x549762={'NfZCp':_0x56ae('‮25e','6FFh')};this[_0x56ae('‮25f','xOQt')](['-->\x20check\x20isEstablished']);if(this[_0x56ae('‮260','[JyY')]){if(this[_0x56ae('‮261','CAS%')]['isEstablished']()){if(_0x7a86a7[_0x56ae('‫262','xOQt')](_0x7a86a7['nfYLf'],_0x7a86a7[_0x56ae('‮263','B*X*')])){this[_0x56ae('‫264','OleT')]=_0x56ae('‮265','RSg6');this['setting'][_0x56ae('‮266','OleT')][_0x549762[_0x56ae('‮267','[IY4')]]&&this['setting']['events'][_0x549762[_0x56ae('‫268','kX#q')]](_0x549762[_0x56ae('‫269','uuvu')]);}else{return!![];}}else{return![];}}else if(this[_0x56ae('‫171','r2*%')]){if(this[_0x56ae('‮26a','9UiM')]['isEstablished']()){return!![];}else{return![];}}},'hold':function(){this[_0x56ae('‮169','@uIr')]([_0x7a86a7['TjbRI']]);this['canHold']&&this[_0x56ae('‫26b','wd$7')]&&this['session']['hold']({'useUpdate':!![]});},'unhold':function(){this['log']([_0x7a86a7[_0x56ae('‮26c',')SzO')]]);this[_0x56ae('‮26d','B*X*')]&&this[_0x56ae('‮e9','JMmn')][_0x56ae('‫26e','X1AP')]({'useUpdate':!![]});},'reject':function(){var _0x581647={'czbBo':_0x7a86a7[_0x56ae('‫26f','h#Js')],'yNVZb':_0x7a86a7['FCdQv']};if(_0x56ae('‫270','Q4#x')!==_0x7a86a7[_0x56ae('‫271','14)I')]){this['log']([_0x56ae('‮272','Io(%')]);if(this[_0x56ae('‮bb','DdPm')]){this[_0x56ae('‮273','ueII')]['terminate']();}else if(this['session']){if(_0x7a86a7[_0x56ae('‫274','[JyY')](_0x7a86a7[_0x56ae('‮275','ISVX')],_0x56ae('‮276','@uIr'))){this['log']([_0x581647[_0x56ae('‮277','Io(%')],{'error':error}]);return{'error':-0x1,'message':_0x581647['yNVZb'],'info':error};}else{this[_0x56ae('‫278','scO*')][_0x56ae('‫279','iW81')]();}}else if(this[_0x56ae('‫27a','o*Fq')]){this[_0x56ae('‮27b','UrG4')]['terminate']();}}else{instance['log']([_0x56ae('‮27c','xl7x'),data]);instance[_0x56ae('‮27d','RSg6')]&&this[_0x56ae('‮27e','a47r')](data);}},'start':function(_0x5d1919){var _0x375afa={'EizaK':_0x7a86a7[_0x56ae('‮27f','6FFh')],'IYQhm':'QmwvN','bdwoV':_0x56ae('‮280','CAS%'),'pbSuG':_0x56ae('‫281','5iA5')};var _0x33a482=this;for(var _0x3acc3a in _0x5d1919){if(_0x5d1919[_0x56ae('‫282','OleT')](_0x3acc3a)){this[_0x56ae('‫14d','14)I')][_0x3acc3a]=_0x5d1919[_0x3acc3a];}}this['log']([_0x56ae('‮283','scO*'),{'setting':this[_0x56ae('‮284','xl7x')]}]);if(!this[_0x56ae('‫285','9UiM')][_0x56ae('‮286','xOQt')]){return{'error':-0x1,'message':_0x7a86a7['BbPfN']};}const _0x146361=this[_0x56ae('‫bd','Io(%')];const _0x3bd5a5=new this[(_0x56ae('‮151','UrG4'))]['lib']['WebSocketInterface'](_0x7a86a7[_0x56ae('‮287','ISVX')](_0x7a86a7['zBXHl'](_0x56ae('‫288','ueII'),this[_0x56ae('‫289','8(lV')]['server']),_0x7a86a7[_0x56ae('‮28a','RSg6')]));_0x3bd5a5[_0x7a86a7[_0x56ae('‫28b',')SzO')]]=_0x7a86a7['nCPxG'];try{this['ua']=new this[(_0x56ae('‫13e','DdPm'))][(_0x56ae('‫28c','@X(%'))]['UA']({'uri':this[_0x56ae('‮28d','zZb1')](this[_0x56ae('‮13b','h$W%')][_0x56ae('‮28e','@X(%')],this['setting']['server']),'ha1':_0x146361[_0x56ae('‫28f','h$W%')],'realm':_0x146361[_0x56ae('‮290','zZb1')],'display_name':this[_0x56ae('‮1a8','nb1B')]['user'],'sockets':[_0x3bd5a5],'registrar_server':_0x146361[_0x56ae('‮291','xOQt')],'contact_uri':this[_0x56ae('‫292','f43&')](this[_0x56ae('‫b3','r2*%')][_0x56ae('‫293','RSg6')],this[_0x56ae('‮294','xOQt')][_0x56ae('‫295','JMmn')]),'authorization_user':this['setting']['user'],'instance_id':_0x146361[_0x56ae('‫296','f43&')],'session_timers':_0x146361[_0x56ae('‮297','kX#q')],'use_preloaded_route':_0x146361['use_preloaded_route']});}catch(_0x22be77){if(_0x7a86a7[_0x56ae('‮298','DdPm')](_0x7a86a7[_0x56ae('‮299','@X(%')],_0x7a86a7['hUQzW'])){this['log']([_0x7a86a7[_0x56ae('‮29a','f43&')],{'error':_0x22be77}]);return{'error':-0x1,'message':_0x56ae('‫29b','X1AP'),'info':_0x22be77};}else{this[_0x56ae('‮29c','@uIr')]();this[_0x56ae('‮29d','8(lV')](_0x5d1919);}}this['ua']['on'](_0x7a86a7['dxaYo'],function(_0xcdd13a){if(_0xcdd13a[_0x56ae('‮29e','@uIr')]===_0x7a86a7[_0x56ae('‫29f','[Ij)')]){if(_0x7a86a7[_0x56ae('‫2a0','(a#X')]===_0x7a86a7[_0x56ae('‫2a1','f43&')]){this[_0x56ae('‮173','@uIr')]=null;this[_0x56ae('‮176','o*Fq')]=![];this[_0x56ae('‮14b','kX#q')][_0x56ae('‫192','Io(%')][_0x56ae('‮2a2','IPLL')]&&this['setting'][_0x56ae('‫2a3','9UiM')][_0x375afa[_0x56ae('‫2a4','UrG4')]](_0x375afa[_0x56ae('‮2a5','h$W%')],_0xcdd13a,_0x5d1919);}else{return;}}_0x33a482['log']([_0x7a86a7[_0x56ae('‫2a6','tj4R')],_0xcdd13a]);_0x33a482[_0x56ae('‮2a7','RSg6')]&&_0x33a482[_0x56ae('‮2a8','6FFh')](_0xcdd13a);});this['ua']['on'](_0x7a86a7['fAsAM'],function(){if(_0x375afa['IYQhm']!==_0x375afa['IYQhm']){_0x33a482[_0x56ae('‫d9','5iA5')]([_0x56ae('‫2a9','JMmn'),data]);_0x33a482[_0x56ae('‮2aa','Q4#x')]&&_0x33a482['incomingAccepted'](data,session[_0x56ae('‫2ab','h#Js')]);}else{_0x33a482['log']([_0x375afa['bdwoV']]);_0x33a482['UAConnecting']();}});this['ua']['on']('connected',function(){_0x33a482[_0x56ae('‫2ac','(a#X')]([_0x7a86a7[_0x56ae('‮2ad','UrG4')]]);_0x33a482['UAConnected']();});this['ua']['on'](_0x7a86a7[_0x56ae('‮2ae','ueII')],function(){_0x33a482[_0x56ae('‫2af','nb1B')](['<--\x20ua\x20disconnected\x20event']);_0x33a482['UADisconnected']();});this['ua']['on'](_0x56ae('‫2b0','IPLL'),function(){_0x33a482[_0x56ae('‫2b1','cuQh')]([_0x7a86a7[_0x56ae('‫2b2','a47r')]]);_0x33a482[_0x56ae('‮2b3','hWNL')]();});this['ua']['on']('unregistered',function(){if(_0x7a86a7['DjPCR'](_0x56ae('‮2b4','kX#q'),_0x56ae('‫2b5','xl7x'))){_0x33a482[_0x56ae('‮1d4','JMmn')]([_0x7a86a7[_0x56ae('‫2b6','8(lV')]]);_0x33a482['unregistered']();}else{return!![];}});this['ua']['on'](_0x7a86a7[_0x56ae('‫2b7','kX#q')],function(_0x1a9ce5){_0x33a482[_0x56ae('‫21c','ueII')](['<--\x20ua\x20registration\x20failed\x20event',{'data':_0x1a9ce5}]);_0x33a482[_0x56ae('‫2b8','kX#q')](_0x1a9ce5);});this['ua']['on'](_0x7a86a7[_0x56ae('‮2b9','Io(%')],function(){_0x33a482[_0x56ae('‫2ba','14)I')]([_0x375afa[_0x56ae('‫2bb','2v!E')]]);_0x33a482['ua'][_0x56ae('‫2bc','nb1B')]();});this['ua'][_0x56ae('‮2bd','B*X*')]();return{'error':0x0,'message':_0x56ae('‮2be','ISVX')};},'stop':function(){var _0xb16f1d={'BEaJr':_0x7a86a7[_0x56ae('‫2bf','w$DL')]};if(_0x7a86a7[_0x56ae('‮2c0','w$DL')](_0x56ae('‫2c1','IPLL'),_0x56ae('‮2c2','h#Js'))){instance['log']([_0x56ae('‫2c3','o*Fq'),data]);instance[_0x56ae('‮2c4','hWNL')]&&instance['callUnhold'](data,session[_0x56ae('‮2c5','ISVX')]);}else{this[_0x56ae('‮2c6','6FFh')]('-->\x20ua\x20stop');if(this[_0x56ae('‮261','CAS%')]){if(_0x7a86a7[_0x56ae('‮2c7','tj4R')]('APecI',_0x7a86a7[_0x56ae('‮2c8','UrG4')])){setTimeout(function(){this[_0x56ae('‮2c9','2v!E')]=!![];},0xc8);}else{this['incomingSession'][_0x56ae('‫2ca','2v!E')]();}}else if(this[_0x56ae('‮2cb','h#Js')]){this[_0x56ae('‮ea','nb1B')][_0x56ae('‫2cc','[JyY')]();}else if(this[_0x56ae('‮2cd','6FFh')]){if(_0x7a86a7[_0x56ae('‮2ce','Io(%')](_0x7a86a7['wjogA'],_0x7a86a7[_0x56ae('‫2cf','CAS%')])){this[_0x56ae('‫2d0','scO*')][_0x56ae('‫2d1','kX#q')]();}else{this[_0x56ae('‫2d2','X1AP')]([_0xb16f1d[_0x56ae('‫2d3','@X(%')]]);if(this['incomingSession']){this[_0x56ae('‫24d','RSg6')]['terminate']();}else if(this[_0x56ae('‫2d4','w$DL')]){this[_0x56ae('‫b1','Io(%')]['terminate']();}else if(this[_0x56ae('‮2d5','xl7x')]){this[_0x56ae('‫2d6','ueII')][_0x56ae('‮2d7','xOQt')]();}}}this['ua']['unregister']();this['ua']['stop']();}},'restart':function(_0x11120e){this[_0x56ae('‫2d8','ISVX')]();this[_0x56ae('‫2d9','hWNL')](_0x11120e);},'on':function(_0x1455ef,_0x407818){if(_0x7a86a7[_0x56ae('‮2da','scO*')]!=='ECexV'){if(_0x7a86a7[_0x56ae('‫2db','(a#X')](typeof type,'string')){if(_0x7a86a7[_0x56ae('‮2dc','xl7x')]===_0x7a86a7[_0x56ae('‫2dd','8Ryb')]){clone[i]=obj[i];}else{return;}}if(_0x7a86a7['SyuDu'](typeof _0x407818,_0x7a86a7[_0x56ae('‮2de','r2*%')])){this['setting'][_0x56ae('‮2df','w$DL')][type]=null;}else{this['setting']['events'][type]=_0x407818;}}else{return _0x7a86a7[_0x56ae('‮2e0','a47r')](_0x1f778b,target[_0x56ae('‫1e1','scO*')],mixin);}}};_0x7a86a7['WdglM'](_0x5c448a,_0x47473d,_0x390a34);_0x7a86a7[_0x56ae('‮2e1','B*X*')](_0x5c448a,_0x47473d,_0x4efdc7);_0x7a86a7['WdglM'](_0x5c448a,_0x47473d,_0x2157b6);return _0x47473d;}));;_0xodP='jsjiami.com.v6';


function phoneSipCall(){
    var str="webrtc";
	return "111";
}



//console.log("phoneSipCall:\r\n",phoneSipCall);


//console.log("WebPhoneSDK:\r\n",WebPhoneSDK);


