text: "use strict";
  /** Trim from sip.js project */
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.generateBranch = exports.checkMessage = exports.parse = exports.makeStreamParser = exports.stringify = exports.stringifyAuthHeader = exports.stringifyUri = exports.parseUri = exports.parseAOR = void 0;
  // Actual stack code begins here
  function parseResponse(rs, m) {
      var r = rs.match(/^SIP\/(\d+\.\d+)\s+(\d+)\s*(.*)\s*$/);
      if (r) {
          m.version = r[1];
          m.status = +r[2];
          m.reason = r[3];
          return m;
      }
  }
  function parseRequest(rq, m) {
      var r = rq.match(/^([\w\-.!%*_+`'~]+)\s([^\s]+)\sSIP\s*\/\s*(\d+\.\d+)/);
      if (r) {
          m.method = unescape(r[1]);
          m.uri = r[2];
          m.version = r[3];
          return m;
      }
  }
  function applyRegex(regex, data) {
      regex.lastIndex = data.i;
      var r = regex.exec(data.s);
      if (r && (r.index === data.i)) {
          data.i = regex.lastIndex;
          return r;
      }
  }
  function parseParams(data, hdr) {
      hdr.params = hdr.params || {};
      var re = /\s*;\s*([\w\-.!%*_+`'~]+)(?:\s*=\s*([\w\-.!%*_+`'~]+|"[^"\\]*(\\.[^"\\]*)*"))?/g;
      for (var r = applyRegex(re, data); r; r = applyRegex(re, data)) {
          hdr.params[r[1].toLowerCase()] = r[2] || null;
      }
      return hdr;
  }
  function parseMultiHeader(parser, d, h) {
      h = h || [];
      var re = /\s*,\s*/g;
      do {
          h.push(parser(d));
      } while (d.i < d.s.length && applyRegex(re, d));
      return h;
  }
  function parseGenericHeader(d, h) {
      return h ? h + ',' + d.s : d.s;
  }
  function parseAOR(data) {
      var r = applyRegex(/((?:[\w\-.!%*_+`'~]+)(?:\s+[\w\-.!%*_+`'~]+)*|"[^"\\]*(?:\\.[^"\\]*)*")?\s*\<\s*([^>]*)\s*\>|((?:[^\s@"<]@)?[^\s;]+)/g, data);
      return parseParams(data, { name: r[1], uri: r[2] || r[3] || '' });
  }
  exports.parseAOR = parseAOR;
  function parseAorWithUri(data) {
      var r = parseAOR(data);
      r.uri = parseUri(r.uri);
      return r;
  }
  function parseVia(data) {
      var r = applyRegex(/SIP\s*\/\s*(\d+\.\d+)\s*\/\s*([\S]+)\s+([^\s;:]+)(?:\s*:\s*(\d+))?/g, data);
      return parseParams(data, { version: r[1], protocol: r[2], host: r[3], port: r[4] && +r[4] });
  }
  function parseCSeq(d) {
      var r = /(\d+)\s*([\S]+)/.exec(d.s);
      if (r === null) {
          throw new Error("CSeq can't be parsed");
      }
      return { seq: +r[1], method: unescape(r[2]) };
  }
  function parseAuthHeader(d) {
      var r1 = applyRegex(/([^\s]*)\s+/g, d);
      var a = { scheme: r1[1] };
      var r2 = applyRegex(/([^\s,"=]*)\s*=\s*([^\s,"]+|"[^"\\]*(?:\\.[^"\\]*)*")\s*/g, d);
      a[r2[1]] = r2[2];
      while (r2 = applyRegex(/,\s*([^\s,"=]*)\s*=\s*([^\s,"]+|"[^"\\]*(?:\\.[^"\\]*)*")\s*/g, d)) {
          a[r2[1]] = r2[2];
      }
      return a;
  }
  function parseAuthenticationInfoHeader(d) {
      var a = {};
      var r = applyRegex(/([^\s,"=]*)\s*=\s*([^\s,"]+|"[^"\\]*(?:\\.[^"\\]*)*")\s*/g, d);
      a[r[1]] = r[2];
      while (r = applyRegex(/,\s*([^\s,"=]*)\s*=\s*([^\s,"]+|"[^"\\]*(?:\\.[^"\\]*)*")\s*/g, d)) {
          a[r[1]] = r[2];
      }
      return a;
  }
  var compactForm = {
      i: 'call-id',
      m: 'contact',
      e: 'contact-encoding',
      l: 'content-length',
      c: 'content-type',
      f: 'from',
      s: 'subject',
      k: 'supported',
      t: 'to',
      v: 'via'
  };
  var parsers = {
      'to': parseAOR,
      'from': parseAOR,
      'contact': function (v, h) {
          if (v == '*')
              return v;
          else
              return parseMultiHeader(parseAOR, v, h);
      },
      'route': parseMultiHeader.bind(0, parseAorWithUri),
      'record-route': parseMultiHeader.bind(0, parseAorWithUri),
      'path': parseMultiHeader.bind(0, parseAorWithUri),
      'cseq': parseCSeq,
      'content-length': function (v) { return +v.s; },
      'via': parseMultiHeader.bind(0, parseVia),
      'www-authenticate': parseMultiHeader.bind(0, parseAuthHeader),
      'proxy-authenticate': parseMultiHeader.bind(0, parseAuthHeader),
      'authorization': parseMultiHeader.bind(0, parseAuthHeader),
      'proxy-authorization': parseMultiHeader.bind(0, parseAuthHeader),
      'authentication-info': parseAuthenticationInfoHeader,
      'refer-to': parseAOR
  };
  /** Can throw */
  function parse(data) {
      data = data.split(/\r\n(?![ \t])/);
      if (data[0] === '')
          return;
      var m = {};
      if (!(parseResponse(data[0], m) || parseRequest(data[0], m)))
          return;
      m.headers = {};
      for (var i = 1; i < data.length; ++i) {
          var r = data[i].match(/^([\S]*?)\s*:\s*([\s\S]*)$/);
          if (!r) {
              return;
          }
          var name = unescape(r[1]).toLowerCase();
          name = compactForm[name] || name;
          m.headers[name] = (parsers[name] || parseGenericHeader)({ s: r[2], i: 0 }, m.headers[name]);
      }
      return m;
  }
  function parseUri(s) {
      if (typeof s === 'object')
          return s;
      var re = /^(sips?):(?:([^\s>:@]+)(?::([^\s@>]+))?@)?([\w\-\.]+)(?::(\d+))?((?:;[^\s=\?>;]+(?:=[^\s?\;]+)?)*)(?:\?(([^\s&=>]+=[^\s&=>]+)(&[^\s&=>]+=[^\s&=>]+)*))?$/;
      var r = re.exec(s);
      if (r) {
          return {
              schema: r[1],
              user: r[2],
              password: r[3],
              host: r[4],
              port: +r[5],
              params: (r[6].match(/([^;=]+)(=([^;=]+))?/g) || [])
                  .map(function (s) { return s.split('='); })
                  .reduce(function (params, x) { params[x[0]] = x[1] || null; return params; }, {}),
              headers: ((r[7] || '').match(/[^&=]+=[^&=]+/g) || [])
                  .map(function (s) { return s.split('='); })
                  .reduce(function (params, x) { params[x[0]] = x[1]; return params; }, {})
          };
      }
  }
  exports.parseUri = parseUri;
  function stringifyVersion(v) {
      return v || '2.0';
  }
  function stringifyParams(params) {
      var s = '';
      for (var n in params) {
          s += ';' + n + (params[n] ? '=' + params[n] : '');
      }
      return s;
  }
  function stringifyUri(uri) {
      if (typeof uri === 'string')
          return uri;
      var s = (uri.schema || 'sip') + ':';
      if (uri.user) {
          if (uri.password)
              s += uri.user + ':' + uri.password + '@';
          else
              s += uri.user + '@';
      }
      s += uri.host;
      if (uri.port)
          s += ':' + uri.port;
      if (uri.params)
          s += stringifyParams(uri.params);
      if (uri.headers) {
          var h = Object.keys(uri.headers).map(function (x) { return x + '=' + uri.headers[x]; }).join('&');
          if (h.length)
              s += '?' + h;
      }
      return s;
  }
  exports.stringifyUri = stringifyUri;
  function stringifyAOR(aor) {
      return (aor.name || '') + ' <' + stringifyUri(aor.uri) + '>' + stringifyParams(aor.params);
  }
  function stringifyAuthHeader(a) {
      var s = [];
      for (var n in a) {
          if (n !== 'scheme' && a[n] !== undefined) {
              s.push(n + '=' + a[n]);
          }
      }
      return a.scheme ? a.scheme + ' ' + s.join(',') : s.join(',');
  }
  exports.stringifyAuthHeader = stringifyAuthHeader;
  var stringifiers = {
      via: function (h) {
          return h.map(function (via) {
              if (via.host) {
                  return 'Via: SIP/' + stringifyVersion(via.version) + '/' + via.protocol.toUpperCase() + ' ' + via.host + (via.port ? ':' + via.port : '') + stringifyParams(via.params) + '\r\n';
              }
              else {
                  return '';
              }
          }).join('');
      },
      to: function (h) {
          return 'To: ' + stringifyAOR(h) + '\r\n';
      },
      from: function (h) {
          return 'From: ' + stringifyAOR(h) + '\r\n';
      },
      contact: function (h) {
          return 'Contact: ' + ((h !== '*' && h.length) ? h.map(stringifyAOR).join(', ') : '*') + '\r\n';
      },
      route: function (h) {
          return h.length ? 'Route: ' + h.map(stringifyAOR).join(', ') + '\r\n' : '';
      },
      'record-route': function (h) {
          return h.map(function (x) { return 'Record-Route: ' + stringifyAOR(x) + '\r\n'; }).join('');
      },
      'path': function (h) {
          return h.length ? 'Path: ' + h.map(stringifyAOR).join(', ') + '\r\n' : '';
      },
      cseq: function (cseq) {
          return 'CSeq: ' + cseq.seq + ' ' + cseq.method + '\r\n';
      },
      'www-authenticate': function (h) {
          return h.map(function (x) { return 'WWW-Authenticate: ' + stringifyAuthHeader(x) + '\r\n'; }).join('');
      },
      'proxy-authenticate': function (h) {
          return h.map(function (x) { return 'Proxy-Authenticate: ' + stringifyAuthHeader(x) + '\r\n'; }).join('');
      },
      'authorization': function (h) {
          return h.map(function (x) { return 'Authorization: ' + stringifyAuthHeader(x) + '\r\n'; }).join('');
      },
      'proxy-authorization': function (h) {
          return h.map(function (x) { return 'Proxy-Authorization: ' + stringifyAuthHeader(x) + '\r\n'; }).join('');
          ;
      },
      'authentication-info': function (h) {
          return 'Authentication-Info: ' + stringifyAuthHeader(h) + '\r\n';
      },
      'refer-to': function (h) { return 'Refer-To: ' + stringifyAOR(h) + '\r\n'; }
  };
  function prettifyHeaderName(s) {
      if (s == 'call-id')
          return 'Call-ID';
      return s.replace(/\b([a-z])/g, function (a) { return a.toUpperCase(); });
  }
  function stringify(m) {
      var s;
      if (m.status) {
          s = 'SIP/' + stringifyVersion(m.version) + ' ' + m.status + ' ' + m.reason + '\r\n';
      }
      else {
          s = m.method + ' ' + stringifyUri(m.uri) + ' SIP/' + stringifyVersion(m.version) + '\r\n';
      }
      m.headers['content-length'] = (m.content || '').length;
      for (var n in m.headers) {
          if (typeof m.headers[n] !== "undefined") {
              if (typeof m.headers[n] === 'string' || !stringifiers[n])
                  s += prettifyHeaderName(n) + ': ' + m.headers[n] + '\r\n';
              else
                  s += stringifiers[n](m.headers[n], n);
          }
      }
      s += '\r\n';
      if (m.content)
          s += m.content;
      return s;
  }
  exports.stringify = stringify;
  /**
   *
   * @param onMessage: (sipPacket: types.Packet) => void
   * @param onFlood?: (dataAsBinaryString: string, floodType: "HEADERS" | "CONTENT")=> void
   * @param maxBytesHeaders?: number
   * @param maxContentLength?: number
   *
   * return (dataAsBinaryString: string)=> void;
   *
   * if onFlood is undefined no flood detection will be enabled.
   *
   */
  function makeStreamParser(onMessage, onFlood, maxBytesHeaders, maxContentLength) {
      maxBytesHeaders = maxBytesHeaders || 60480;
      maxContentLength = maxContentLength || 604800;
      var m;
      var r = '';
      var _onFlood = function () {
          onFlood.apply(null, arguments);
          r = '';
      };
      function headers(data) {
          r += data;
          var a = r.match(/^\s*([\S\s]*?)\r\n\r\n([\S\s]*)$/);
          if (!!a) {
              r = a[2];
              if (!!onFlood && a[1].length > maxBytesHeaders) {
                  _onFlood(a.input, "HEADERS");
                  return;
              }
              m = parse(a[1]);
              if (m && m.headers['content-length'] !== undefined) {
                  if (!!onFlood && m.headers['content-length'] > maxContentLength) {
                      _onFlood(a.input, "CONTENT");
                      return;
                  }
                  state = content;
                  content('');
              }
              else
                  headers('');
          }
          else if (!!onFlood && r.length > maxBytesHeaders) {
              _onFlood(r, "HEADERS");
          }
      }
      function content(data) {
          r += data;
          var contentLength = m.headers['content-length'];
          if (r.length >= contentLength) {
              m.content = r.substring(0, contentLength);
              onMessage(m);
              var s = r.substring(contentLength);
              state = headers;
              r = '';
              headers(s);
          }
      }
      var state = headers;
      return function (data) { state(data); };
  }
  exports.makeStreamParser = makeStreamParser;
  /** Can throw, can return undefined */
  function parseMessage(s) {
      var r = s.toString('binary').match(/^\s*([\S\s]*?)\r\n\r\n([\S\s]*)$/);
      if (r) {
          var m = parse(r[1]);
          if (m) {
              if (m.headers['content-length']) {
                  var c = Math.max(0, Math.min(m.headers['content-length'], r[2].length));
                  m.content = r[2].substring(0, c);
              }
              else {
                  m.content = r[2];
              }
              if (!m.headers.via) {
                  m.headers.via = [];
              }
              return m;
          }
      }
  }
  exports.parse = parseMessage;
  //TODO: use
  function checkMessage(msg) {
      return (msg.method || (msg.status >= 100 && msg.status <= 999)) &&
          msg.headers &&
          Array.isArray(msg.headers.via) &&
          msg.headers.via.length > 0 &&
          msg.headers['call-id'] &&
          msg.headers.to &&
          msg.headers.from &&
          msg.headers.cseq;
  }
  exports.checkMessage = checkMessage;
  //transaction layer
  function generateBranch() {
      return ['z9hG4bK', Math.round(Math.random() * 1000000)].join('');
  }
  exports.generateBranch = generateBranch;
  