Fork of FusionPBX but with LDAP kinda working
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

21552 lines
930 KiB

  1. /*!
  2. *
  3. * SIP version 0.15.6
  4. * Copyright (c) 2014-2019 Junction Networks, Inc <http://www.onsip.com>
  5. * Homepage: https://sipjs.com
  6. * License: https://sipjs.com/license/
  7. *
  8. *
  9. * ~~~SIP.js contains substantial portions of JsSIP under the following license~~~
  10. * Homepage: http://jssip.net
  11. * Copyright (c) 2012-2013 José Luis Millán - Versatica <http://www.versatica.com>
  12. *
  13. * Permission is hereby granted, free of charge, to any person obtaining
  14. * a copy of this software and associated documentation files (the
  15. * "Software"), to deal in the Software without restriction, including
  16. * without limitation the rights to use, copy, modify, merge, publish,
  17. * distribute, sublicense, and/or sell copies of the Software, and to
  18. * permit persons to whom the Software is furnished to do so, subject to
  19. * the following conditions:
  20. *
  21. * The above copyright notice and this permission notice shall be
  22. * included in all copies or substantial portions of the Software.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  28. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  29. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  30. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  31. *
  32. * ~~~ end JsSIP license ~~~
  33. *
  34. *
  35. *
  36. *
  37. */
  38. (function webpackUniversalModuleDefinition(root, factory) {
  39. if(typeof exports === 'object' && typeof module === 'object')
  40. module.exports = factory();
  41. else if(typeof define === 'function' && define.amd)
  42. define([], factory);
  43. else if(typeof exports === 'object')
  44. exports["SIP"] = factory();
  45. else
  46. root["SIP"] = factory();
  47. })(this, function() {
  48. return /******/ (function(modules) { // webpackBootstrap
  49. /******/ // The module cache
  50. /******/ var installedModules = {};
  51. /******/
  52. /******/ // The require function
  53. /******/ function __webpack_require__(moduleId) {
  54. /******/
  55. /******/ // Check if module is in cache
  56. /******/ if(installedModules[moduleId]) {
  57. /******/ return installedModules[moduleId].exports;
  58. /******/ }
  59. /******/ // Create a new module (and put it into the cache)
  60. /******/ var module = installedModules[moduleId] = {
  61. /******/ i: moduleId,
  62. /******/ l: false,
  63. /******/ exports: {}
  64. /******/ };
  65. /******/
  66. /******/ // Execute the module function
  67. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  68. /******/
  69. /******/ // Flag the module as loaded
  70. /******/ module.l = true;
  71. /******/
  72. /******/ // Return the exports of the module
  73. /******/ return module.exports;
  74. /******/ }
  75. /******/
  76. /******/
  77. /******/ // expose the modules object (__webpack_modules__)
  78. /******/ __webpack_require__.m = modules;
  79. /******/
  80. /******/ // expose the module cache
  81. /******/ __webpack_require__.c = installedModules;
  82. /******/
  83. /******/ // define getter function for harmony exports
  84. /******/ __webpack_require__.d = function(exports, name, getter) {
  85. /******/ if(!__webpack_require__.o(exports, name)) {
  86. /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
  87. /******/ }
  88. /******/ };
  89. /******/
  90. /******/ // define __esModule on exports
  91. /******/ __webpack_require__.r = function(exports) {
  92. /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  93. /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  94. /******/ }
  95. /******/ Object.defineProperty(exports, '__esModule', { value: true });
  96. /******/ };
  97. /******/
  98. /******/ // create a fake namespace object
  99. /******/ // mode & 1: value is a module id, require it
  100. /******/ // mode & 2: merge all properties of value into the ns
  101. /******/ // mode & 4: return value when already ns object
  102. /******/ // mode & 8|1: behave like require
  103. /******/ __webpack_require__.t = function(value, mode) {
  104. /******/ if(mode & 1) value = __webpack_require__(value);
  105. /******/ if(mode & 8) return value;
  106. /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
  107. /******/ var ns = Object.create(null);
  108. /******/ __webpack_require__.r(ns);
  109. /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
  110. /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
  111. /******/ return ns;
  112. /******/ };
  113. /******/
  114. /******/ // getDefaultExport function for compatibility with non-harmony modules
  115. /******/ __webpack_require__.n = function(module) {
  116. /******/ var getter = module && module.__esModule ?
  117. /******/ function getDefault() { return module['default']; } :
  118. /******/ function getModuleExports() { return module; };
  119. /******/ __webpack_require__.d(getter, 'a', getter);
  120. /******/ return getter;
  121. /******/ };
  122. /******/
  123. /******/ // Object.prototype.hasOwnProperty.call
  124. /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  125. /******/
  126. /******/ // __webpack_public_path__
  127. /******/ __webpack_require__.p = "";
  128. /******/
  129. /******/
  130. /******/ // Load entry module and return exports
  131. /******/ return __webpack_require__(__webpack_require__.s = 0);
  132. /******/ })
  133. /************************************************************************/
  134. /******/ ([
  135. /* 0 */
  136. /***/ (function(module, exports, __webpack_require__) {
  137. "use strict";
  138. Object.defineProperty(exports, "__esModule", { value: true });
  139. var tslib_1 = __webpack_require__(1);
  140. var core_1 = __webpack_require__(2);
  141. exports.DigestAuthentication = core_1.DigestAuthentication;
  142. exports.Grammar = core_1.Grammar;
  143. exports.IncomingRequest = core_1.IncomingRequestMessage;
  144. exports.IncomingResponse = core_1.IncomingResponseMessage;
  145. exports.LoggerFactory = core_1.LoggerFactory;
  146. exports.NameAddrHeader = core_1.NameAddrHeader;
  147. exports.OutgoingRequest = core_1.OutgoingRequestMessage;
  148. exports.Timers = core_1.Timers;
  149. exports.Transport = core_1.Transport;
  150. exports.URI = core_1.URI;
  151. var ClientContext_1 = __webpack_require__(79);
  152. exports.ClientContext = ClientContext_1.ClientContext;
  153. var Constants_1 = __webpack_require__(80);
  154. exports.C = Constants_1.C;
  155. var Enums_1 = __webpack_require__(82);
  156. exports.DialogStatus = Enums_1.DialogStatus;
  157. exports.SessionStatus = Enums_1.SessionStatus;
  158. exports.TypeStrings = Enums_1.TypeStrings;
  159. exports.UAStatus = Enums_1.UAStatus;
  160. var Exceptions_1 = __webpack_require__(84);
  161. exports.Exceptions = Exceptions_1.Exceptions;
  162. var Parser_1 = __webpack_require__(85);
  163. exports.Parser = Parser_1.Parser;
  164. var PublishContext_1 = __webpack_require__(86);
  165. exports.PublishContext = PublishContext_1.PublishContext;
  166. var ReferContext_1 = __webpack_require__(87);
  167. exports.ReferClientContext = ReferContext_1.ReferClientContext;
  168. exports.ReferServerContext = ReferContext_1.ReferServerContext;
  169. var RegisterContext_1 = __webpack_require__(89);
  170. exports.RegisterContext = RegisterContext_1.RegisterContext;
  171. var ServerContext_1 = __webpack_require__(88);
  172. exports.ServerContext = ServerContext_1.ServerContext;
  173. var Session_1 = __webpack_require__(90);
  174. exports.InviteClientContext = Session_1.InviteClientContext;
  175. exports.InviteServerContext = Session_1.InviteServerContext;
  176. exports.Session = Session_1.Session;
  177. var Subscription_1 = __webpack_require__(92);
  178. exports.Subscription = Subscription_1.Subscription;
  179. var transactions_1 = __webpack_require__(27);
  180. var Transactions = {
  181. InviteClientTransaction: transactions_1.InviteClientTransaction,
  182. InviteServerTransaction: transactions_1.InviteServerTransaction,
  183. NonInviteClientTransaction: transactions_1.NonInviteClientTransaction,
  184. NonInviteServerTransaction: transactions_1.NonInviteServerTransaction
  185. };
  186. exports.Transactions = Transactions;
  187. var UA_1 = __webpack_require__(93);
  188. exports.makeUserAgentCoreConfigurationFromUA = UA_1.makeUserAgentCoreConfigurationFromUA;
  189. exports.UA = UA_1.UA;
  190. var Utils_1 = __webpack_require__(83);
  191. exports.Utils = Utils_1.Utils;
  192. var Web = tslib_1.__importStar(__webpack_require__(104));
  193. exports.Web = Web;
  194. var version = Constants_1.C.version;
  195. exports.version = version;
  196. var name = "sip.js";
  197. exports.name = name;
  198. var Core = tslib_1.__importStar(__webpack_require__(2));
  199. exports.Core = Core;
  200. /***/ }),
  201. /* 1 */
  202. /***/ (function(module, __webpack_exports__, __webpack_require__) {
  203. "use strict";
  204. __webpack_require__.r(__webpack_exports__);
  205. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__extends", function() { return __extends; });
  206. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__assign", function() { return __assign; });
  207. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__rest", function() { return __rest; });
  208. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__decorate", function() { return __decorate; });
  209. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__param", function() { return __param; });
  210. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__metadata", function() { return __metadata; });
  211. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__awaiter", function() { return __awaiter; });
  212. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__generator", function() { return __generator; });
  213. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__exportStar", function() { return __exportStar; });
  214. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__values", function() { return __values; });
  215. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__read", function() { return __read; });
  216. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__spread", function() { return __spread; });
  217. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__spreadArrays", function() { return __spreadArrays; });
  218. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__await", function() { return __await; });
  219. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncGenerator", function() { return __asyncGenerator; });
  220. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncDelegator", function() { return __asyncDelegator; });
  221. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncValues", function() { return __asyncValues; });
  222. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__makeTemplateObject", function() { return __makeTemplateObject; });
  223. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__importStar", function() { return __importStar; });
  224. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__importDefault", function() { return __importDefault; });
  225. /*! *****************************************************************************
  226. Copyright (c) Microsoft Corporation. All rights reserved.
  227. Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  228. this file except in compliance with the License. You may obtain a copy of the
  229. License at http://www.apache.org/licenses/LICENSE-2.0
  230. THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  231. KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  232. WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  233. MERCHANTABLITY OR NON-INFRINGEMENT.
  234. See the Apache Version 2.0 License for specific language governing permissions
  235. and limitations under the License.
  236. ***************************************************************************** */
  237. /* global Reflect, Promise */
  238. var extendStatics = function(d, b) {
  239. extendStatics = Object.setPrototypeOf ||
  240. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  241. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  242. return extendStatics(d, b);
  243. };
  244. function __extends(d, b) {
  245. extendStatics(d, b);
  246. function __() { this.constructor = d; }
  247. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  248. }
  249. var __assign = function() {
  250. __assign = Object.assign || function __assign(t) {
  251. for (var s, i = 1, n = arguments.length; i < n; i++) {
  252. s = arguments[i];
  253. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
  254. }
  255. return t;
  256. }
  257. return __assign.apply(this, arguments);
  258. }
  259. function __rest(s, e) {
  260. var t = {};
  261. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  262. t[p] = s[p];
  263. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  264. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  265. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  266. t[p[i]] = s[p[i]];
  267. }
  268. return t;
  269. }
  270. function __decorate(decorators, target, key, desc) {
  271. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  272. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  273. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  274. return c > 3 && r && Object.defineProperty(target, key, r), r;
  275. }
  276. function __param(paramIndex, decorator) {
  277. return function (target, key) { decorator(target, key, paramIndex); }
  278. }
  279. function __metadata(metadataKey, metadataValue) {
  280. if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
  281. }
  282. function __awaiter(thisArg, _arguments, P, generator) {
  283. return new (P || (P = Promise))(function (resolve, reject) {
  284. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  285. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  286. function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
  287. step((generator = generator.apply(thisArg, _arguments || [])).next());
  288. });
  289. }
  290. function __generator(thisArg, body) {
  291. var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
  292. return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
  293. function verb(n) { return function (v) { return step([n, v]); }; }
  294. function step(op) {
  295. if (f) throw new TypeError("Generator is already executing.");
  296. while (_) try {
  297. if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
  298. if (y = 0, t) op = [op[0] & 2, t.value];
  299. switch (op[0]) {
  300. case 0: case 1: t = op; break;
  301. case 4: _.label++; return { value: op[1], done: false };
  302. case 5: _.label++; y = op[1]; op = [0]; continue;
  303. case 7: op = _.ops.pop(); _.trys.pop(); continue;
  304. default:
  305. if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
  306. if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
  307. if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
  308. if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
  309. if (t[2]) _.ops.pop();
  310. _.trys.pop(); continue;
  311. }
  312. op = body.call(thisArg, _);
  313. } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
  314. if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
  315. }
  316. }
  317. function __exportStar(m, exports) {
  318. for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
  319. }
  320. function __values(o) {
  321. var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
  322. if (m) return m.call(o);
  323. return {
  324. next: function () {
  325. if (o && i >= o.length) o = void 0;
  326. return { value: o && o[i++], done: !o };
  327. }
  328. };
  329. }
  330. function __read(o, n) {
  331. var m = typeof Symbol === "function" && o[Symbol.iterator];
  332. if (!m) return o;
  333. var i = m.call(o), r, ar = [], e;
  334. try {
  335. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
  336. }
  337. catch (error) { e = { error: error }; }
  338. finally {
  339. try {
  340. if (r && !r.done && (m = i["return"])) m.call(i);
  341. }
  342. finally { if (e) throw e.error; }
  343. }
  344. return ar;
  345. }
  346. function __spread() {
  347. for (var ar = [], i = 0; i < arguments.length; i++)
  348. ar = ar.concat(__read(arguments[i]));
  349. return ar;
  350. }
  351. function __spreadArrays() {
  352. for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
  353. for (var r = Array(s), k = 0, i = 0; i < il; i++)
  354. for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
  355. r[k] = a[j];
  356. return r;
  357. };
  358. function __await(v) {
  359. return this instanceof __await ? (this.v = v, this) : new __await(v);
  360. }
  361. function __asyncGenerator(thisArg, _arguments, generator) {
  362. if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
  363. var g = generator.apply(thisArg, _arguments || []), i, q = [];
  364. return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
  365. function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
  366. function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
  367. function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
  368. function fulfill(value) { resume("next", value); }
  369. function reject(value) { resume("throw", value); }
  370. function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
  371. }
  372. function __asyncDelegator(o) {
  373. var i, p;
  374. return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
  375. function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
  376. }
  377. function __asyncValues(o) {
  378. if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
  379. var m = o[Symbol.asyncIterator], i;
  380. return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
  381. function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
  382. function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
  383. }
  384. function __makeTemplateObject(cooked, raw) {
  385. if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
  386. return cooked;
  387. };
  388. function __importStar(mod) {
  389. if (mod && mod.__esModule) return mod;
  390. var result = {};
  391. if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
  392. result.default = mod;
  393. return result;
  394. }
  395. function __importDefault(mod) {
  396. return (mod && mod.__esModule) ? mod : { default: mod };
  397. }
  398. /***/ }),
  399. /* 2 */
  400. /***/ (function(module, exports, __webpack_require__) {
  401. "use strict";
  402. /**
  403. * A core library implementing low level SIP protocol elements.
  404. * @packageDocumentation
  405. */
  406. Object.defineProperty(exports, "__esModule", { value: true });
  407. var tslib_1 = __webpack_require__(1);
  408. // Directories
  409. tslib_1.__exportStar(__webpack_require__(3), exports);
  410. tslib_1.__exportStar(__webpack_require__(31), exports);
  411. tslib_1.__exportStar(__webpack_require__(60), exports);
  412. tslib_1.__exportStar(__webpack_require__(5), exports);
  413. tslib_1.__exportStar(__webpack_require__(24), exports);
  414. tslib_1.__exportStar(__webpack_require__(56), exports);
  415. tslib_1.__exportStar(__webpack_require__(27), exports);
  416. tslib_1.__exportStar(__webpack_require__(64), exports);
  417. tslib_1.__exportStar(__webpack_require__(66), exports);
  418. // Files
  419. tslib_1.__exportStar(__webpack_require__(26), exports);
  420. tslib_1.__exportStar(__webpack_require__(78), exports);
  421. /***/ }),
  422. /* 3 */
  423. /***/ (function(module, exports, __webpack_require__) {
  424. "use strict";
  425. Object.defineProperty(exports, "__esModule", { value: true });
  426. var tslib_1 = __webpack_require__(1);
  427. tslib_1.__exportStar(__webpack_require__(4), exports);
  428. tslib_1.__exportStar(__webpack_require__(23), exports);
  429. tslib_1.__exportStar(__webpack_require__(55), exports);
  430. /***/ }),
  431. /* 4 */
  432. /***/ (function(module, exports, __webpack_require__) {
  433. "use strict";
  434. Object.defineProperty(exports, "__esModule", { value: true });
  435. var messages_1 = __webpack_require__(5);
  436. /**
  437. * Dialog.
  438. * @remarks
  439. * A key concept for a user agent is that of a dialog. A dialog
  440. * represents a peer-to-peer SIP relationship between two user agents
  441. * that persists for some time. The dialog facilitates sequencing of
  442. * messages between the user agents and proper routing of requests
  443. * between both of them. The dialog represents a context in which to
  444. * interpret SIP messages.
  445. * https://tools.ietf.org/html/rfc3261#section-12
  446. * @public
  447. */
  448. var Dialog = /** @class */ (function () {
  449. /**
  450. * Dialog constructor.
  451. * @param core - User agent core.
  452. * @param dialogState - Initial dialog state.
  453. */
  454. function Dialog(core, dialogState) {
  455. this.core = core;
  456. this.dialogState = dialogState;
  457. this.core.dialogs.set(this.id, this);
  458. }
  459. /**
  460. * When a UAC receives a response that establishes a dialog, it
  461. * constructs the state of the dialog. This state MUST be maintained
  462. * for the duration of the dialog.
  463. * https://tools.ietf.org/html/rfc3261#section-12.1.2
  464. * @param outgoingRequestMessage - Outgoing request message for dialog.
  465. * @param incomingResponseMessage - Incoming response message creating dialog.
  466. */
  467. Dialog.initialDialogStateForUserAgentClient = function (outgoingRequestMessage, incomingResponseMessage) {
  468. // If the request was sent over TLS, and the Request-URI contained a
  469. // SIPS URI, the "secure" flag is set to TRUE.
  470. // https://tools.ietf.org/html/rfc3261#section-12.1.2
  471. var secure = false; // FIXME: Currently no support for TLS.
  472. // The route set MUST be set to the list of URIs in the Record-Route
  473. // header field from the response, taken in reverse order and preserving
  474. // all URI parameters. If no Record-Route header field is present in
  475. // the response, the route set MUST be set to the empty set. This route
  476. // set, even if empty, overrides any pre-existing route set for future
  477. // requests in this dialog. The remote target MUST be set to the URI
  478. // from the Contact header field of the response.
  479. // https://tools.ietf.org/html/rfc3261#section-12.1.2
  480. var routeSet = incomingResponseMessage.getHeaders("record-route").reverse();
  481. var contact = incomingResponseMessage.parseHeader("contact");
  482. if (!contact) { // TODO: Review to make sure this will never happen
  483. throw new Error("Contact undefined.");
  484. }
  485. if (!(contact instanceof messages_1.NameAddrHeader)) {
  486. throw new Error("Contact not instance of NameAddrHeader.");
  487. }
  488. var remoteTarget = contact.uri;
  489. // The local sequence number MUST be set to the value of the sequence
  490. // number in the CSeq header field of the request. The remote sequence
  491. // number MUST be empty (it is established when the remote UA sends a
  492. // request within the dialog). The call identifier component of the
  493. // dialog ID MUST be set to the value of the Call-ID in the request.
  494. // The local tag component of the dialog ID MUST be set to the tag in
  495. // the From field in the request, and the remote tag component of the
  496. // dialog ID MUST be set to the tag in the To field of the response. A
  497. // UAC MUST be prepared to receive a response without a tag in the To
  498. // field, in which case the tag is considered to have a value of null.
  499. //
  500. // This is to maintain backwards compatibility with RFC 2543, which
  501. // did not mandate To tags.
  502. //
  503. // https://tools.ietf.org/html/rfc3261#section-12.1.2
  504. var localSequenceNumber = outgoingRequestMessage.cseq;
  505. var remoteSequenceNumber = undefined;
  506. var callId = outgoingRequestMessage.callId;
  507. var localTag = outgoingRequestMessage.fromTag;
  508. var remoteTag = incomingResponseMessage.toTag;
  509. if (!callId) { // TODO: Review to make sure this will never happen
  510. throw new Error("Call id undefined.");
  511. }
  512. if (!localTag) { // TODO: Review to make sure this will never happen
  513. throw new Error("From tag undefined.");
  514. }
  515. if (!remoteTag) { // TODO: Review to make sure this will never happen
  516. throw new Error("To tag undefined."); // FIXME: No backwards compatibility with RFC 2543
  517. }
  518. // The remote URI MUST be set to the URI in the To field, and the local
  519. // URI MUST be set to the URI in the From field.
  520. // https://tools.ietf.org/html/rfc3261#section-12.1.2
  521. if (!outgoingRequestMessage.from) { // TODO: Review to make sure this will never happen
  522. throw new Error("From undefined.");
  523. }
  524. if (!outgoingRequestMessage.to) { // TODO: Review to make sure this will never happen
  525. throw new Error("To undefined.");
  526. }
  527. var localURI = outgoingRequestMessage.from.uri;
  528. var remoteURI = outgoingRequestMessage.to.uri;
  529. // A dialog can also be in the "early" state, which occurs when it is
  530. // created with a provisional response, and then transition to the
  531. // "confirmed" state when a 2xx final response arrives.
  532. // https://tools.ietf.org/html/rfc3261#section-12
  533. if (!incomingResponseMessage.statusCode) {
  534. throw new Error("Incoming response status code undefined.");
  535. }
  536. var early = incomingResponseMessage.statusCode < 200 ? true : false;
  537. var dialogState = {
  538. id: callId + localTag + remoteTag,
  539. early: early,
  540. callId: callId,
  541. localTag: localTag,
  542. remoteTag: remoteTag,
  543. localSequenceNumber: localSequenceNumber,
  544. remoteSequenceNumber: remoteSequenceNumber,
  545. localURI: localURI,
  546. remoteURI: remoteURI,
  547. remoteTarget: remoteTarget,
  548. routeSet: routeSet,
  549. secure: secure
  550. };
  551. return dialogState;
  552. };
  553. /**
  554. * The UAS then constructs the state of the dialog. This state MUST be
  555. * maintained for the duration of the dialog.
  556. * https://tools.ietf.org/html/rfc3261#section-12.1.1
  557. * @param incomingRequestMessage - Incoming request message creating dialog.
  558. * @param toTag - Tag in the To field in the response to the incoming request.
  559. */
  560. Dialog.initialDialogStateForUserAgentServer = function (incomingRequestMessage, toTag, early) {
  561. if (early === void 0) { early = false; }
  562. // If the request arrived over TLS, and the Request-URI contained a SIPS
  563. // URI, the "secure" flag is set to TRUE.
  564. // https://tools.ietf.org/html/rfc3261#section-12.1.1
  565. var secure = false; // FIXME: Currently no support for TLS.
  566. // The route set MUST be set to the list of URIs in the Record-Route
  567. // header field from the request, taken in order and preserving all URI
  568. // parameters. If no Record-Route header field is present in the
  569. // request, the route set MUST be set to the empty set. This route set,
  570. // even if empty, overrides any pre-existing route set for future
  571. // requests in this dialog. The remote target MUST be set to the URI
  572. // from the Contact header field of the request.
  573. // https://tools.ietf.org/html/rfc3261#section-12.1.1
  574. var routeSet = incomingRequestMessage.getHeaders("record-route");
  575. var contact = incomingRequestMessage.parseHeader("contact");
  576. if (!contact) { // TODO: Review to make sure this will never happen
  577. throw new Error("Contact undefined.");
  578. }
  579. if (!(contact instanceof messages_1.NameAddrHeader)) {
  580. throw new Error("Contact not instance of NameAddrHeader.");
  581. }
  582. var remoteTarget = contact.uri;
  583. // The remote sequence number MUST be set to the value of the sequence
  584. // number in the CSeq header field of the request. The local sequence
  585. // number MUST be empty. The call identifier component of the dialog ID
  586. // MUST be set to the value of the Call-ID in the request. The local
  587. // tag component of the dialog ID MUST be set to the tag in the To field
  588. // in the response to the request (which always includes a tag), and the
  589. // remote tag component of the dialog ID MUST be set to the tag from the
  590. // From field in the request. A UAS MUST be prepared to receive a
  591. // request without a tag in the From field, in which case the tag is
  592. // considered to have a value of null.
  593. //
  594. // This is to maintain backwards compatibility with RFC 2543, which
  595. // did not mandate From tags.
  596. //
  597. // https://tools.ietf.org/html/rfc3261#section-12.1.1
  598. var remoteSequenceNumber = incomingRequestMessage.cseq;
  599. var localSequenceNumber = undefined;
  600. var callId = incomingRequestMessage.callId;
  601. var localTag = toTag;
  602. var remoteTag = incomingRequestMessage.fromTag;
  603. // The remote URI MUST be set to the URI in the From field, and the
  604. // local URI MUST be set to the URI in the To field.
  605. // https://tools.ietf.org/html/rfc3261#section-12.1.1
  606. var remoteURI = incomingRequestMessage.from.uri;
  607. var localURI = incomingRequestMessage.to.uri;
  608. var dialogState = {
  609. id: callId + localTag + remoteTag,
  610. early: early,
  611. callId: callId,
  612. localTag: localTag,
  613. remoteTag: remoteTag,
  614. localSequenceNumber: localSequenceNumber,
  615. remoteSequenceNumber: remoteSequenceNumber,
  616. localURI: localURI,
  617. remoteURI: remoteURI,
  618. remoteTarget: remoteTarget,
  619. routeSet: routeSet,
  620. secure: secure
  621. };
  622. return dialogState;
  623. };
  624. /** Destructor. */
  625. Dialog.prototype.dispose = function () {
  626. this.core.dialogs.delete(this.id);
  627. };
  628. Object.defineProperty(Dialog.prototype, "id", {
  629. /**
  630. * A dialog is identified at each UA with a dialog ID, which consists of
  631. * a Call-ID value, a local tag and a remote tag. The dialog ID at each
  632. * UA involved in the dialog is not the same. Specifically, the local
  633. * tag at one UA is identical to the remote tag at the peer UA. The
  634. * tags are opaque tokens that facilitate the generation of unique
  635. * dialog IDs.
  636. * https://tools.ietf.org/html/rfc3261#section-12
  637. */
  638. get: function () {
  639. return this.dialogState.id;
  640. },
  641. enumerable: true,
  642. configurable: true
  643. });
  644. Object.defineProperty(Dialog.prototype, "early", {
  645. /**
  646. * A dialog can also be in the "early" state, which occurs when it is
  647. * created with a provisional response, and then it transition to the
  648. * "confirmed" state when a 2xx final response received or is sent.
  649. *
  650. * Note: RFC 3261 is concise on when a dialog is "confirmed", but it
  651. * can be a point of confusion if an INVITE dialog is "confirmed" after
  652. * a 2xx is sent or after receiving the ACK for the 2xx response.
  653. * With careful reading it can be inferred a dialog is always is
  654. * "confirmed" when the 2xx is sent (regardless of type of dialog).
  655. * However a INVITE dialog does have additional considerations
  656. * when it is confirmed but an ACK has not yet been received (in
  657. * particular with regard to a callee sending BYE requests).
  658. */
  659. get: function () {
  660. return this.dialogState.early;
  661. },
  662. enumerable: true,
  663. configurable: true
  664. });
  665. Object.defineProperty(Dialog.prototype, "callId", {
  666. /** Call identifier component of the dialog id. */
  667. get: function () {
  668. return this.dialogState.callId;
  669. },
  670. enumerable: true,
  671. configurable: true
  672. });
  673. Object.defineProperty(Dialog.prototype, "localTag", {
  674. /** Local tag component of the dialog id. */
  675. get: function () {
  676. return this.dialogState.localTag;
  677. },
  678. enumerable: true,
  679. configurable: true
  680. });
  681. Object.defineProperty(Dialog.prototype, "remoteTag", {
  682. /** Remote tag component of the dialog id. */
  683. get: function () {
  684. return this.dialogState.remoteTag;
  685. },
  686. enumerable: true,
  687. configurable: true
  688. });
  689. Object.defineProperty(Dialog.prototype, "localSequenceNumber", {
  690. /** Local sequence number (used to order requests from the UA to its peer). */
  691. get: function () {
  692. return this.dialogState.localSequenceNumber;
  693. },
  694. enumerable: true,
  695. configurable: true
  696. });
  697. Object.defineProperty(Dialog.prototype, "remoteSequenceNumber", {
  698. /** Remote sequence number (used to order requests from its peer to the UA). */
  699. get: function () {
  700. return this.dialogState.remoteSequenceNumber;
  701. },
  702. enumerable: true,
  703. configurable: true
  704. });
  705. Object.defineProperty(Dialog.prototype, "localURI", {
  706. /** Local URI. */
  707. get: function () {
  708. return this.dialogState.localURI;
  709. },
  710. enumerable: true,
  711. configurable: true
  712. });
  713. Object.defineProperty(Dialog.prototype, "remoteURI", {
  714. /** Remote URI. */
  715. get: function () {
  716. return this.dialogState.remoteURI;
  717. },
  718. enumerable: true,
  719. configurable: true
  720. });
  721. Object.defineProperty(Dialog.prototype, "remoteTarget", {
  722. /** Remote target. */
  723. get: function () {
  724. return this.dialogState.remoteTarget;
  725. },
  726. enumerable: true,
  727. configurable: true
  728. });
  729. Object.defineProperty(Dialog.prototype, "routeSet", {
  730. /**
  731. * Route set, which is an ordered list of URIs. The route set is the
  732. * list of servers that need to be traversed to send a request to the peer.
  733. */
  734. get: function () {
  735. return this.dialogState.routeSet;
  736. },
  737. enumerable: true,
  738. configurable: true
  739. });
  740. Object.defineProperty(Dialog.prototype, "secure", {
  741. /**
  742. * If the request was sent over TLS, and the Request-URI contained
  743. * a SIPS URI, the "secure" flag is set to true. *NOT IMPLEMENTED*
  744. */
  745. get: function () {
  746. return this.dialogState.secure;
  747. },
  748. enumerable: true,
  749. configurable: true
  750. });
  751. Object.defineProperty(Dialog.prototype, "userAgentCore", {
  752. /** The user agent core servicing this dialog. */
  753. get: function () {
  754. return this.core;
  755. },
  756. enumerable: true,
  757. configurable: true
  758. });
  759. /** Confirm the dialog. Only matters if dialog is currently early. */
  760. Dialog.prototype.confirm = function () {
  761. this.dialogState.early = false;
  762. };
  763. /**
  764. * Requests sent within a dialog, as any other requests, are atomic. If
  765. * a particular request is accepted by the UAS, all the state changes
  766. * associated with it are performed. If the request is rejected, none
  767. * of the state changes are performed.
  768. *
  769. * Note that some requests, such as INVITEs, affect several pieces of
  770. * state.
  771. *
  772. * https://tools.ietf.org/html/rfc3261#section-12.2.2
  773. * @param message - Incoming request message within this dialog.
  774. */
  775. Dialog.prototype.receiveRequest = function (message) {
  776. // ACK guard.
  777. // By convention, the handling of ACKs is the responsibility
  778. // the particular dialog implementation. For example, see SessionDialog.
  779. // Furthermore, ACKs have same sequence number as the associated INVITE.
  780. if (message.method === messages_1.C.ACK) {
  781. return;
  782. }
  783. // If the remote sequence number was not empty, but the sequence number
  784. // of the request is lower than the remote sequence number, the request
  785. // is out of order and MUST be rejected with a 500 (Server Internal
  786. // Error) response. If the remote sequence number was not empty, and
  787. // the sequence number of the request is greater than the remote
  788. // sequence number, the request is in order. It is possible for the
  789. // CSeq sequence number to be higher than the remote sequence number by
  790. // more than one. This is not an error condition, and a UAS SHOULD be
  791. // prepared to receive and process requests with CSeq values more than
  792. // one higher than the previous received request. The UAS MUST then set
  793. // the remote sequence number to the value of the sequence number in the
  794. // CSeq header field value in the request.
  795. //
  796. // If a proxy challenges a request generated by the UAC, the UAC has
  797. // to resubmit the request with credentials. The resubmitted request
  798. // will have a new CSeq number. The UAS will never see the first
  799. // request, and thus, it will notice a gap in the CSeq number space.
  800. // Such a gap does not represent any error condition.
  801. //
  802. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  803. if (this.remoteSequenceNumber) {
  804. if (message.cseq <= this.remoteSequenceNumber) {
  805. throw new Error("Out of sequence in dialog request. Did you forget to call sequenceGuard()?");
  806. }
  807. this.dialogState.remoteSequenceNumber = message.cseq;
  808. }
  809. // If the remote sequence number is empty, it MUST be set to the value
  810. // of the sequence number in the CSeq header field value in the request.
  811. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  812. if (!this.remoteSequenceNumber) {
  813. this.dialogState.remoteSequenceNumber = message.cseq;
  814. }
  815. // When a UAS receives a target refresh request, it MUST replace the
  816. // dialog's remote target URI with the URI from the Contact header field
  817. // in that request, if present.
  818. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  819. // Note: "target refresh request" processing delegated to sub-class.
  820. };
  821. /**
  822. * If the dialog identifier in the 2xx response matches the dialog
  823. * identifier of an existing dialog, the dialog MUST be transitioned to
  824. * the "confirmed" state, and the route set for the dialog MUST be
  825. * recomputed based on the 2xx response using the procedures of Section
  826. * 12.2.1.2. Otherwise, a new dialog in the "confirmed" state MUST be
  827. * constructed using the procedures of Section 12.1.2.
  828. *
  829. * Note that the only piece of state that is recomputed is the route
  830. * set. Other pieces of state such as the highest sequence numbers
  831. * (remote and local) sent within the dialog are not recomputed. The
  832. * route set only is recomputed for backwards compatibility. RFC
  833. * 2543 did not mandate mirroring of the Record-Route header field in
  834. * a 1xx, only 2xx. However, we cannot update the entire state of
  835. * the dialog, since mid-dialog requests may have been sent within
  836. * the early dialog, modifying the sequence numbers, for example.
  837. *
  838. * https://tools.ietf.org/html/rfc3261#section-13.2.2.4
  839. */
  840. Dialog.prototype.recomputeRouteSet = function (message) {
  841. this.dialogState.routeSet = message.getHeaders("record-route").reverse();
  842. };
  843. /**
  844. * A request within a dialog is constructed by using many of the
  845. * components of the state stored as part of the dialog.
  846. * https://tools.ietf.org/html/rfc3261#section-12.2.1.1
  847. * @param method - Outgoing request method.
  848. */
  849. Dialog.prototype.createOutgoingRequestMessage = function (method, options) {
  850. // The URI in the To field of the request MUST be set to the remote URI
  851. // from the dialog state. The tag in the To header field of the request
  852. // MUST be set to the remote tag of the dialog ID. The From URI of the
  853. // request MUST be set to the local URI from the dialog state. The tag
  854. // in the From header field of the request MUST be set to the local tag
  855. // of the dialog ID. If the value of the remote or local tags is null,
  856. // the tag parameter MUST be omitted from the To or From header fields,
  857. // respectively.
  858. //
  859. // Usage of the URI from the To and From fields in the original
  860. // request within subsequent requests is done for backwards
  861. // compatibility with RFC 2543, which used the URI for dialog
  862. // identification. In this specification, only the tags are used for
  863. // dialog identification. It is expected that mandatory reflection
  864. // of the original To and From URI in mid-dialog requests will be
  865. // deprecated in a subsequent revision of this specification.
  866. // https://tools.ietf.org/html/rfc3261#section-12.2.1.1
  867. var toUri = this.remoteURI;
  868. var toTag = this.remoteTag;
  869. var fromUri = this.localURI;
  870. var fromTag = this.localTag;
  871. // The Call-ID of the request MUST be set to the Call-ID of the dialog.
  872. // Requests within a dialog MUST contain strictly monotonically
  873. // increasing and contiguous CSeq sequence numbers (increasing-by-one)
  874. // in each direction (excepting ACK and CANCEL of course, whose numbers
  875. // equal the requests being acknowledged or cancelled). Therefore, if
  876. // the local sequence number is not empty, the value of the local
  877. // sequence number MUST be incremented by one, and this value MUST be
  878. // placed into the CSeq header field. If the local sequence number is
  879. // empty, an initial value MUST be chosen using the guidelines of
  880. // Section 8.1.1.5. The method field in the CSeq header field value
  881. // MUST match the method of the request.
  882. // https://tools.ietf.org/html/rfc3261#section-12.2.1.1
  883. var callId = this.callId;
  884. var cseq;
  885. if (options && options.cseq) {
  886. cseq = options.cseq;
  887. }
  888. else if (!this.dialogState.localSequenceNumber) {
  889. cseq = this.dialogState.localSequenceNumber = 1; // https://tools.ietf.org/html/rfc3261#section-8.1.1.5
  890. }
  891. else {
  892. cseq = this.dialogState.localSequenceNumber += 1;
  893. }
  894. // The UAC uses the remote target and route set to build the Request-URI
  895. // and Route header field of the request.
  896. //
  897. // If the route set is empty, the UAC MUST place the remote target URI
  898. // into the Request-URI. The UAC MUST NOT add a Route header field to
  899. // the request.
  900. //
  901. // If the route set is not empty, and the first URI in the route set
  902. // contains the lr parameter (see Section 19.1.1), the UAC MUST place
  903. // the remote target URI into the Request-URI and MUST include a Route
  904. // header field containing the route set values in order, including all
  905. // parameters.
  906. //
  907. // If the route set is not empty, and its first URI does not contain the
  908. // lr parameter, the UAC MUST place the first URI from the route set
  909. // into the Request-URI, stripping any parameters that are not allowed
  910. // in a Request-URI. The UAC MUST add a Route header field containing
  911. // the remainder of the route set values in order, including all
  912. // parameters. The UAC MUST then place the remote target URI into the
  913. // Route header field as the last value.
  914. // https://tools.ietf.org/html/rfc3261#section-12.2.1.1
  915. // The lr parameter, when present, indicates that the element
  916. // responsible for this resource implements the routing mechanisms
  917. // specified in this document. This parameter will be used in the
  918. // URIs proxies place into Record-Route header field values, and
  919. // may appear in the URIs in a pre-existing route set.
  920. //
  921. // This parameter is used to achieve backwards compatibility with
  922. // systems implementing the strict-routing mechanisms of RFC 2543
  923. // and the rfc2543bis drafts up to bis-05. An element preparing
  924. // to send a request based on a URI not containing this parameter
  925. // can assume the receiving element implements strict-routing and
  926. // reformat the message to preserve the information in the
  927. // Request-URI.
  928. // https://tools.ietf.org/html/rfc3261#section-19.1.1
  929. // NOTE: Not backwards compatible with RFC 2543 (no support for strict-routing).
  930. var ruri = this.remoteTarget;
  931. var routeSet = this.routeSet;
  932. var extraHeaders = options && options.extraHeaders;
  933. var body = options && options.body;
  934. // The relative order of header fields with different field names is not
  935. // significant. However, it is RECOMMENDED that header fields which are
  936. // needed for proxy processing (Via, Route, Record-Route, Proxy-Require,
  937. // Max-Forwards, and Proxy-Authorization, for example) appear towards
  938. // the top of the message to facilitate rapid parsing.
  939. // https://tools.ietf.org/html/rfc3261#section-7.3.1
  940. var message = this.userAgentCore.makeOutgoingRequestMessage(method, ruri, fromUri, toUri, {
  941. callId: callId,
  942. cseq: cseq,
  943. fromTag: fromTag,
  944. toTag: toTag,
  945. routeSet: routeSet
  946. }, extraHeaders, body);
  947. return message;
  948. };
  949. /**
  950. * If the remote sequence number was not empty, but the sequence number
  951. * of the request is lower than the remote sequence number, the request
  952. * is out of order and MUST be rejected with a 500 (Server Internal
  953. * Error) response.
  954. * https://tools.ietf.org/html/rfc3261#section-12.2.2
  955. * @param request - Incoming request to guard.
  956. * @returns True if the program execution is to continue in the branch in question.
  957. * Otherwise a 500 Server Internal Error was stateless sent and request processing must stop.
  958. */
  959. Dialog.prototype.sequenceGuard = function (message) {
  960. // ACK guard.
  961. // By convention, handling of unexpected ACKs is responsibility
  962. // the particular dialog implementation. For example, see SessionDialog.
  963. // Furthermore, we cannot reply to an "out of sequence" ACK.
  964. if (message.method === messages_1.C.ACK) {
  965. return true;
  966. }
  967. // Note: We are rejecting on "less than or equal to" the remote
  968. // sequence number (excepting ACK whose numbers equal the requests
  969. // being acknowledged or cancelled), which is the correct thing to
  970. // do in our case. The only time a request with the same sequence number
  971. // will show up here if is a) it is a very late retransmission of a
  972. // request we already handled or b) it is a different request with the
  973. // same sequence number which would be violation of the standard.
  974. // Request retransmissions are absorbed by the transaction layer,
  975. // so any request with a duplicate sequence number getting here
  976. // would have to be a retransmission after the transaction terminated
  977. // or a broken request (with unique via branch value).
  978. // Requests within a dialog MUST contain strictly monotonically
  979. // increasing and contiguous CSeq sequence numbers (increasing-by-one)
  980. // in each direction (excepting ACK and CANCEL of course, whose numbers
  981. // equal the requests being acknowledged or cancelled). Therefore, if
  982. // the local sequence number is not empty, the value of the local
  983. // sequence number MUST be incremented by one, and this value MUST be
  984. // placed into the CSeq header field.
  985. // https://tools.ietf.org/html/rfc3261#section-12.2.1.1
  986. if (this.remoteSequenceNumber && message.cseq <= this.remoteSequenceNumber) {
  987. this.core.replyStateless(message, { statusCode: 500 });
  988. return false;
  989. }
  990. return true;
  991. };
  992. return Dialog;
  993. }());
  994. exports.Dialog = Dialog;
  995. /***/ }),
  996. /* 5 */
  997. /***/ (function(module, exports, __webpack_require__) {
  998. "use strict";
  999. Object.defineProperty(exports, "__esModule", { value: true });
  1000. var tslib_1 = __webpack_require__(1);
  1001. // Directories
  1002. tslib_1.__exportStar(__webpack_require__(6), exports);
  1003. // Files
  1004. tslib_1.__exportStar(__webpack_require__(8), exports);
  1005. tslib_1.__exportStar(__webpack_require__(19), exports);
  1006. tslib_1.__exportStar(__webpack_require__(11), exports);
  1007. tslib_1.__exportStar(__webpack_require__(10), exports);
  1008. tslib_1.__exportStar(__webpack_require__(9), exports);
  1009. tslib_1.__exportStar(__webpack_require__(17), exports);
  1010. tslib_1.__exportStar(__webpack_require__(13), exports);
  1011. tslib_1.__exportStar(__webpack_require__(18), exports);
  1012. tslib_1.__exportStar(__webpack_require__(22), exports);
  1013. tslib_1.__exportStar(__webpack_require__(14), exports);
  1014. tslib_1.__exportStar(__webpack_require__(15), exports);
  1015. /***/ }),
  1016. /* 6 */
  1017. /***/ (function(module, exports, __webpack_require__) {
  1018. "use strict";
  1019. Object.defineProperty(exports, "__esModule", { value: true });
  1020. var tslib_1 = __webpack_require__(1);
  1021. tslib_1.__exportStar(__webpack_require__(7), exports);
  1022. /***/ }),
  1023. /* 7 */
  1024. /***/ (function(module, exports, __webpack_require__) {
  1025. "use strict";
  1026. Object.defineProperty(exports, "__esModule", { value: true });
  1027. /**
  1028. * SIP Methods
  1029. * @internal
  1030. */
  1031. var C;
  1032. (function (C) {
  1033. C.ACK = "ACK";
  1034. C.BYE = "BYE";
  1035. C.CANCEL = "CANCEL";
  1036. C.INFO = "INFO";
  1037. C.INVITE = "INVITE";
  1038. C.MESSAGE = "MESSAGE";
  1039. C.NOTIFY = "NOTIFY";
  1040. C.OPTIONS = "OPTIONS";
  1041. C.REGISTER = "REGISTER";
  1042. C.UPDATE = "UPDATE";
  1043. C.SUBSCRIBE = "SUBSCRIBE";
  1044. C.PUBLISH = "PUBLISH";
  1045. C.REFER = "REFER";
  1046. C.PRACK = "PRACK";
  1047. })(C = exports.C || (exports.C = {}));
  1048. /***/ }),
  1049. /* 8 */
  1050. /***/ (function(module, exports, __webpack_require__) {
  1051. "use strict";
  1052. Object.defineProperty(exports, "__esModule", { value: true });
  1053. var incoming_request_message_1 = __webpack_require__(9);
  1054. var incoming_response_message_1 = __webpack_require__(17);
  1055. var outgoing_request_message_1 = __webpack_require__(18);
  1056. /**
  1057. * Create a Body given a legacy body type.
  1058. * @param bodyLegacy - Body Object
  1059. * @internal
  1060. */
  1061. function fromBodyLegacy(bodyLegacy) {
  1062. var content = (typeof bodyLegacy === "string") ? bodyLegacy : bodyLegacy.body;
  1063. var contentType = (typeof bodyLegacy === "string") ? "application/sdp" : bodyLegacy.contentType;
  1064. var contentDisposition = contentTypeToContentDisposition(contentType);
  1065. var body = { contentDisposition: contentDisposition, contentType: contentType, content: content };
  1066. return body;
  1067. }
  1068. exports.fromBodyLegacy = fromBodyLegacy;
  1069. /**
  1070. * Given a message, get a normalized body.
  1071. * The content disposition is inferred if not set.
  1072. * @param message - The message.
  1073. * @internal
  1074. */
  1075. function getBody(message) {
  1076. var contentDisposition;
  1077. var contentType;
  1078. var content;
  1079. // We're in UAS role, receiving incoming request
  1080. if (message instanceof incoming_request_message_1.IncomingRequestMessage) {
  1081. if (message.body) {
  1082. // FIXME: Parsing needs typing
  1083. var parse = message.parseHeader("Content-Disposition");
  1084. contentDisposition = parse ? parse.type : undefined;
  1085. contentType = message.parseHeader("Content-Type");
  1086. content = message.body;
  1087. }
  1088. }
  1089. // We're in UAC role, receiving incoming response
  1090. if (message instanceof incoming_response_message_1.IncomingResponseMessage) {
  1091. if (message.body) {
  1092. // FIXME: Parsing needs typing
  1093. var parse = message.parseHeader("Content-Disposition");
  1094. contentDisposition = parse ? parse.type : undefined;
  1095. contentType = message.parseHeader("Content-Type");
  1096. content = message.body;
  1097. }
  1098. }
  1099. // We're in UAC role, sending outgoing request
  1100. if (message instanceof outgoing_request_message_1.OutgoingRequestMessage) {
  1101. if (message.body) {
  1102. contentDisposition = message.getHeader("Content-Disposition");
  1103. contentType = message.getHeader("Content-Type");
  1104. if (typeof message.body === "string") {
  1105. // FIXME: OutgoingRequest should not allow a "string" body without a "Content-Type" header.
  1106. if (!contentType) {
  1107. throw new Error("Header content type header does not equal body content type.");
  1108. }
  1109. content = message.body;
  1110. }
  1111. else {
  1112. // FIXME: OutgoingRequest should not allow the "Content-Type" header not to match th body content type
  1113. if (contentType && contentType !== message.body.contentType) {
  1114. throw new Error("Header content type header does not equal body content type.");
  1115. }
  1116. contentType = message.body.contentType;
  1117. content = message.body.body;
  1118. }
  1119. }
  1120. }
  1121. // We're in UAS role, sending outgoing response
  1122. if (isBody(message)) {
  1123. contentDisposition = message.contentDisposition;
  1124. contentType = message.contentType;
  1125. content = message.content;
  1126. }
  1127. // No content, no body.
  1128. if (!content) {
  1129. return undefined;
  1130. }
  1131. if (contentType && !contentDisposition) {
  1132. contentDisposition = contentTypeToContentDisposition(contentType);
  1133. }
  1134. if (!contentDisposition) {
  1135. throw new Error("Content disposition undefined.");
  1136. }
  1137. if (!contentType) {
  1138. throw new Error("Content type undefined.");
  1139. }
  1140. return {
  1141. contentDisposition: contentDisposition,
  1142. contentType: contentType,
  1143. content: content
  1144. };
  1145. }
  1146. exports.getBody = getBody;
  1147. /**
  1148. * User-Defined Type Guard for Body.
  1149. * @param body - Body to check.
  1150. * @internal
  1151. */
  1152. function isBody(body) {
  1153. return body &&
  1154. typeof body.content === "string" &&
  1155. typeof body.contentType === "string" &&
  1156. body.contentDisposition === undefined ? true : typeof body.contentDisposition === "string";
  1157. }
  1158. exports.isBody = isBody;
  1159. // If the Content-Disposition header field is missing, bodies of
  1160. // Content-Type application/sdp imply the disposition "session", while
  1161. // other content types imply "render".
  1162. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  1163. function contentTypeToContentDisposition(contentType) {
  1164. if (contentType === "application/sdp") {
  1165. return "session";
  1166. }
  1167. else {
  1168. return "render";
  1169. }
  1170. }
  1171. /***/ }),
  1172. /* 9 */
  1173. /***/ (function(module, exports, __webpack_require__) {
  1174. "use strict";
  1175. Object.defineProperty(exports, "__esModule", { value: true });
  1176. var tslib_1 = __webpack_require__(1);
  1177. var incoming_message_1 = __webpack_require__(10);
  1178. /**
  1179. * Incoming request message.
  1180. * @public
  1181. */
  1182. var IncomingRequestMessage = /** @class */ (function (_super) {
  1183. tslib_1.__extends(IncomingRequestMessage, _super);
  1184. function IncomingRequestMessage() {
  1185. return _super.call(this) || this;
  1186. }
  1187. return IncomingRequestMessage;
  1188. }(incoming_message_1.IncomingMessage));
  1189. exports.IncomingRequestMessage = IncomingRequestMessage;
  1190. /***/ }),
  1191. /* 10 */
  1192. /***/ (function(module, exports, __webpack_require__) {
  1193. "use strict";
  1194. Object.defineProperty(exports, "__esModule", { value: true });
  1195. var grammar_1 = __webpack_require__(11);
  1196. var utils_1 = __webpack_require__(16);
  1197. /**
  1198. * Incoming message.
  1199. * @public
  1200. */
  1201. var IncomingMessage = /** @class */ (function () {
  1202. function IncomingMessage() {
  1203. this.headers = {};
  1204. }
  1205. /**
  1206. * Insert a header of the given name and value into the last position of the
  1207. * header array.
  1208. * @param name - header name
  1209. * @param value - header value
  1210. */
  1211. IncomingMessage.prototype.addHeader = function (name, value) {
  1212. var header = { raw: value };
  1213. name = utils_1.headerize(name);
  1214. if (this.headers[name]) {
  1215. this.headers[name].push(header);
  1216. }
  1217. else {
  1218. this.headers[name] = [header];
  1219. }
  1220. };
  1221. /**
  1222. * Get the value of the given header name at the given position.
  1223. * @param name - header name
  1224. * @returns Returns the specified header, undefined if header doesn't exist.
  1225. */
  1226. IncomingMessage.prototype.getHeader = function (name) {
  1227. var header = this.headers[utils_1.headerize(name)];
  1228. if (header) {
  1229. if (header[0]) {
  1230. return header[0].raw;
  1231. }
  1232. }
  1233. else {
  1234. return;
  1235. }
  1236. };
  1237. /**
  1238. * Get the header/s of the given name.
  1239. * @param name - header name
  1240. * @returns Array - with all the headers of the specified name.
  1241. */
  1242. IncomingMessage.prototype.getHeaders = function (name) {
  1243. var header = this.headers[utils_1.headerize(name)];
  1244. var result = [];
  1245. if (!header) {
  1246. return [];
  1247. }
  1248. for (var _i = 0, header_1 = header; _i < header_1.length; _i++) {
  1249. var headerPart = header_1[_i];
  1250. result.push(headerPart.raw);
  1251. }
  1252. return result;
  1253. };
  1254. /**
  1255. * Verify the existence of the given header.
  1256. * @param name - header name
  1257. * @returns true if header with given name exists, false otherwise
  1258. */
  1259. IncomingMessage.prototype.hasHeader = function (name) {
  1260. return !!this.headers[utils_1.headerize(name)];
  1261. };
  1262. /**
  1263. * Parse the given header on the given index.
  1264. * @param name - header name
  1265. * @param idx - header index
  1266. * @returns Parsed header object, undefined if the
  1267. * header is not present or in case of a parsing error.
  1268. */
  1269. IncomingMessage.prototype.parseHeader = function (name, idx) {
  1270. if (idx === void 0) { idx = 0; }
  1271. name = utils_1.headerize(name);
  1272. if (!this.headers[name]) {
  1273. // this.logger.log("header '" + name + "' not present");
  1274. return;
  1275. }
  1276. else if (idx >= this.headers[name].length) {
  1277. // this.logger.log("not so many '" + name + "' headers present");
  1278. return;
  1279. }
  1280. var header = this.headers[name][idx];
  1281. var value = header.raw;
  1282. if (header.parsed) {
  1283. return header.parsed;
  1284. }
  1285. // substitute '-' by '_' for grammar rule matching.
  1286. var parsed = grammar_1.Grammar.parse(value, name.replace(/-/g, "_"));
  1287. if (parsed === -1) {
  1288. this.headers[name].splice(idx, 1); // delete from headers
  1289. // this.logger.warn('error parsing "' + name + '" header field with value "' + value + '"');
  1290. return;
  1291. }
  1292. else {
  1293. header.parsed = parsed;
  1294. return parsed;
  1295. }
  1296. };
  1297. /**
  1298. * Message Header attribute selector. Alias of parseHeader.
  1299. * @param name - header name
  1300. * @param idx - header index
  1301. * @returns Parsed header object, undefined if the
  1302. * header is not present or in case of a parsing error.
  1303. *
  1304. * @example
  1305. * message.s('via',3).port
  1306. */
  1307. IncomingMessage.prototype.s = function (name, idx) {
  1308. if (idx === void 0) { idx = 0; }
  1309. return this.parseHeader(name, idx);
  1310. };
  1311. /**
  1312. * Replace the value of the given header by the value.
  1313. * @param name - header name
  1314. * @param value - header value
  1315. */
  1316. IncomingMessage.prototype.setHeader = function (name, value) {
  1317. this.headers[utils_1.headerize(name)] = [{ raw: value }];
  1318. };
  1319. IncomingMessage.prototype.toString = function () {
  1320. return this.data;
  1321. };
  1322. return IncomingMessage;
  1323. }());
  1324. exports.IncomingMessage = IncomingMessage;
  1325. /***/ }),
  1326. /* 11 */
  1327. /***/ (function(module, exports, __webpack_require__) {
  1328. "use strict";
  1329. Object.defineProperty(exports, "__esModule", { value: true });
  1330. var tslib_1 = __webpack_require__(1);
  1331. var pegGrammar = tslib_1.__importStar(__webpack_require__(12));
  1332. /**
  1333. * Grammar.
  1334. * @internal
  1335. */
  1336. var Grammar;
  1337. (function (Grammar) {
  1338. /**
  1339. * Parse.
  1340. * @param input -
  1341. * @param startRule -
  1342. */
  1343. function parse(input, startRule) {
  1344. var options = { startRule: startRule };
  1345. try {
  1346. pegGrammar.parse(input, options);
  1347. }
  1348. catch (e) {
  1349. options.data = -1;
  1350. }
  1351. return options.data;
  1352. }
  1353. Grammar.parse = parse;
  1354. /**
  1355. * Parse the given string and returns a SIP.NameAddrHeader instance or undefined if
  1356. * it is an invalid NameAddrHeader.
  1357. * @param name_addr_header -
  1358. */
  1359. function nameAddrHeaderParse(nameAddrHeader) {
  1360. var parsedNameAddrHeader = Grammar.parse(nameAddrHeader, "Name_Addr_Header");
  1361. return parsedNameAddrHeader !== -1 ? parsedNameAddrHeader : undefined;
  1362. }
  1363. Grammar.nameAddrHeaderParse = nameAddrHeaderParse;
  1364. /**
  1365. * Parse the given string and returns a SIP.URI instance or undefined if
  1366. * it is an invalid URI.
  1367. * @param uri -
  1368. */
  1369. function URIParse(uri) {
  1370. var parsedUri = Grammar.parse(uri, "SIP_URI");
  1371. return parsedUri !== -1 ? parsedUri : undefined;
  1372. }
  1373. Grammar.URIParse = URIParse;
  1374. })(Grammar = exports.Grammar || (exports.Grammar = {}));
  1375. /***/ }),
  1376. /* 12 */
  1377. /***/ (function(module, exports, __webpack_require__) {
  1378. "use strict";
  1379. // tslint:disable:interface-name
  1380. // tslint:disable: trailing-comma
  1381. // tslint:disable: object-literal-sort-keys
  1382. // tslint:disable: max-line-length
  1383. // tslint:disable: only-arrow-functions
  1384. // tslint:disable: one-variable-per-declaration
  1385. // tslint:disable: no-consecutive-blank-lines
  1386. // tslint:disable: align
  1387. // tslint:disable: radix
  1388. // tslint:disable: quotemark
  1389. // tslint:disable: semicolon
  1390. // tslint:disable: object-literal-shorthand
  1391. // tslint:disable: variable-name
  1392. // tslint:disable: no-var-keyword
  1393. // tslint:disable: whitespace
  1394. // tslint:disable: curly
  1395. // tslint:disable: prefer-const
  1396. // tslint:disable: object-literal-key-quotes
  1397. // tslint:disable: no-string-literal
  1398. // tslint:disable: one-line
  1399. // tslint:disable: no-unused-expression
  1400. // tslint:disable: space-before-function-paren
  1401. // tslint:disable: arrow-return-shorthand
  1402. Object.defineProperty(exports, "__esModule", { value: true });
  1403. var tslib_1 = __webpack_require__(1);
  1404. // Generated by PEG.js v. 0.10.0 (ts-pegjs plugin v. 0.2.6 )
  1405. //
  1406. // https://pegjs.org/ https://github.com/metadevpro/ts-pegjs
  1407. var name_addr_header_1 = __webpack_require__(13);
  1408. var uri_1 = __webpack_require__(15);
  1409. var SyntaxError = /** @class */ (function (_super) {
  1410. tslib_1.__extends(SyntaxError, _super);
  1411. function SyntaxError(message, expected, found, location) {
  1412. var _this = _super.call(this) || this;
  1413. _this.message = message;
  1414. _this.expected = expected;
  1415. _this.found = found;
  1416. _this.location = location;
  1417. _this.name = "SyntaxError";
  1418. if (typeof Error.captureStackTrace === "function") {
  1419. Error.captureStackTrace(_this, SyntaxError);
  1420. }
  1421. return _this;
  1422. }
  1423. SyntaxError.buildMessage = function (expected, found) {
  1424. function hex(ch) {
  1425. return ch.charCodeAt(0).toString(16).toUpperCase();
  1426. }
  1427. function literalEscape(s) {
  1428. return s
  1429. .replace(/\\/g, "\\\\")
  1430. .replace(/"/g, "\\\"")
  1431. .replace(/\0/g, "\\0")
  1432. .replace(/\t/g, "\\t")
  1433. .replace(/\n/g, "\\n")
  1434. .replace(/\r/g, "\\r")
  1435. .replace(/[\x00-\x0F]/g, function (ch) { return "\\x0" + hex(ch); })
  1436. .replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) { return "\\x" + hex(ch); });
  1437. }
  1438. function classEscape(s) {
  1439. return s
  1440. .replace(/\\/g, "\\\\")
  1441. .replace(/\]/g, "\\]")
  1442. .replace(/\^/g, "\\^")
  1443. .replace(/-/g, "\\-")
  1444. .replace(/\0/g, "\\0")
  1445. .replace(/\t/g, "\\t")
  1446. .replace(/\n/g, "\\n")
  1447. .replace(/\r/g, "\\r")
  1448. .replace(/[\x00-\x0F]/g, function (ch) { return "\\x0" + hex(ch); })
  1449. .replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) { return "\\x" + hex(ch); });
  1450. }
  1451. function describeExpectation(expectation) {
  1452. switch (expectation.type) {
  1453. case "literal":
  1454. return "\"" + literalEscape(expectation.text) + "\"";
  1455. case "class":
  1456. var escapedParts = expectation.parts.map(function (part) {
  1457. return Array.isArray(part)
  1458. ? classEscape(part[0]) + "-" + classEscape(part[1])
  1459. : classEscape(part);
  1460. });
  1461. return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
  1462. case "any":
  1463. return "any character";
  1464. case "end":
  1465. return "end of input";
  1466. case "other":
  1467. return expectation.description;
  1468. }
  1469. }
  1470. function describeExpected(expected1) {
  1471. var descriptions = expected1.map(describeExpectation);
  1472. var i;
  1473. var j;
  1474. descriptions.sort();
  1475. if (descriptions.length > 0) {
  1476. for (i = 1, j = 1; i < descriptions.length; i++) {
  1477. if (descriptions[i - 1] !== descriptions[i]) {
  1478. descriptions[j] = descriptions[i];
  1479. j++;
  1480. }
  1481. }
  1482. descriptions.length = j;
  1483. }
  1484. switch (descriptions.length) {
  1485. case 1:
  1486. return descriptions[0];
  1487. case 2:
  1488. return descriptions[0] + " or " + descriptions[1];
  1489. default:
  1490. return descriptions.slice(0, -1).join(", ")
  1491. + ", or "
  1492. + descriptions[descriptions.length - 1];
  1493. }
  1494. }
  1495. function describeFound(found1) {
  1496. return found1 ? "\"" + literalEscape(found1) + "\"" : "end of input";
  1497. }
  1498. return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
  1499. };
  1500. return SyntaxError;
  1501. }(Error));
  1502. exports.SyntaxError = SyntaxError;
  1503. function peg$parse(input, options) {
  1504. options = options !== undefined ? options : {};
  1505. var peg$FAILED = {};
  1506. var peg$startRuleIndices = { Contact: 119, Name_Addr_Header: 156, Record_Route: 176, Request_Response: 81, SIP_URI: 45, Subscription_State: 186, Supported: 191, Require: 182, Via: 194, absoluteURI: 84, Call_ID: 118, Content_Disposition: 130, Content_Length: 135, Content_Type: 136, CSeq: 146, displayName: 122, Event: 149, From: 151, host: 52, Max_Forwards: 154, Min_SE: 213, Proxy_Authenticate: 157, quoted_string: 40, Refer_To: 178, Replaces: 179, Session_Expires: 210, stun_URI: 217, To: 192, turn_URI: 223, uuid: 226, WWW_Authenticate: 209, challenge: 158, sipfrag: 230, Referred_By: 231 };
  1507. var peg$startRuleIndex = 119;
  1508. var peg$consts = [
  1509. "\r\n",
  1510. peg$literalExpectation("\r\n", false),
  1511. /^[0-9]/,
  1512. peg$classExpectation([["0", "9"]], false, false),
  1513. /^[a-zA-Z]/,
  1514. peg$classExpectation([["a", "z"], ["A", "Z"]], false, false),
  1515. /^[0-9a-fA-F]/,
  1516. peg$classExpectation([["0", "9"], ["a", "f"], ["A", "F"]], false, false),
  1517. /^[\0-\xFF]/,
  1518. peg$classExpectation([["\0", "\xFF"]], false, false),
  1519. /^["]/,
  1520. peg$classExpectation(["\""], false, false),
  1521. " ",
  1522. peg$literalExpectation(" ", false),
  1523. "\t",
  1524. peg$literalExpectation("\t", false),
  1525. /^[a-zA-Z0-9]/,
  1526. peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"]], false, false),
  1527. ";",
  1528. peg$literalExpectation(";", false),
  1529. "/",
  1530. peg$literalExpectation("/", false),
  1531. "?",
  1532. peg$literalExpectation("?", false),
  1533. ":",
  1534. peg$literalExpectation(":", false),
  1535. "@",
  1536. peg$literalExpectation("@", false),
  1537. "&",
  1538. peg$literalExpectation("&", false),
  1539. "=",
  1540. peg$literalExpectation("=", false),
  1541. "+",
  1542. peg$literalExpectation("+", false),
  1543. "$",
  1544. peg$literalExpectation("$", false),
  1545. ",",
  1546. peg$literalExpectation(",", false),
  1547. "-",
  1548. peg$literalExpectation("-", false),
  1549. "_",
  1550. peg$literalExpectation("_", false),
  1551. ".",
  1552. peg$literalExpectation(".", false),
  1553. "!",
  1554. peg$literalExpectation("!", false),
  1555. "~",
  1556. peg$literalExpectation("~", false),
  1557. "*",
  1558. peg$literalExpectation("*", false),
  1559. "'",
  1560. peg$literalExpectation("'", false),
  1561. "(",
  1562. peg$literalExpectation("(", false),
  1563. ")",
  1564. peg$literalExpectation(")", false),
  1565. "%",
  1566. peg$literalExpectation("%", false),
  1567. function () { return " "; },
  1568. function () { return ':'; },
  1569. /^[!-~]/,
  1570. peg$classExpectation([["!", "~"]], false, false),
  1571. /^[\x80-\uFFFF]/,
  1572. peg$classExpectation([["\x80", "\uFFFF"]], false, false),
  1573. /^[\x80-\xBF]/,
  1574. peg$classExpectation([["\x80", "\xBF"]], false, false),
  1575. /^[a-f]/,
  1576. peg$classExpectation([["a", "f"]], false, false),
  1577. "`",
  1578. peg$literalExpectation("`", false),
  1579. "<",
  1580. peg$literalExpectation("<", false),
  1581. ">",
  1582. peg$literalExpectation(">", false),
  1583. "\\",
  1584. peg$literalExpectation("\\", false),
  1585. "[",
  1586. peg$literalExpectation("[", false),
  1587. "]",
  1588. peg$literalExpectation("]", false),
  1589. "{",
  1590. peg$literalExpectation("{", false),
  1591. "}",
  1592. peg$literalExpectation("}", false),
  1593. function () { return "*"; },
  1594. function () { return "/"; },
  1595. function () { return "="; },
  1596. function () { return "("; },
  1597. function () { return ")"; },
  1598. function () { return ">"; },
  1599. function () { return "<"; },
  1600. function () { return ","; },
  1601. function () { return ";"; },
  1602. function () { return ":"; },
  1603. function () { return "\""; },
  1604. /^[!-']/,
  1605. peg$classExpectation([["!", "'"]], false, false),
  1606. /^[*-[]/,
  1607. peg$classExpectation([["*", "["]], false, false),
  1608. /^[\]-~]/,
  1609. peg$classExpectation([["]", "~"]], false, false),
  1610. function (contents) {
  1611. return contents;
  1612. },
  1613. /^[#-[]/,
  1614. peg$classExpectation([["#", "["]], false, false),
  1615. /^[\0-\t]/,
  1616. peg$classExpectation([["\0", "\t"]], false, false),
  1617. /^[\x0B-\f]/,
  1618. peg$classExpectation([["\x0B", "\f"]], false, false),
  1619. /^[\x0E-\x7F]/,
  1620. peg$classExpectation([["\x0E", "\x7F"]], false, false),
  1621. function () {
  1622. options = options || { data: {} };
  1623. options.data.uri = new uri_1.URI(options.data.scheme, options.data.user, options.data.host, options.data.port);
  1624. delete options.data.scheme;
  1625. delete options.data.user;
  1626. delete options.data.host;
  1627. delete options.data.host_type;
  1628. delete options.data.port;
  1629. },
  1630. function () {
  1631. options = options || { data: {} };
  1632. options.data.uri = new uri_1.URI(options.data.scheme, options.data.user, options.data.host, options.data.port, options.data.uri_params, options.data.uri_headers);
  1633. delete options.data.scheme;
  1634. delete options.data.user;
  1635. delete options.data.host;
  1636. delete options.data.host_type;
  1637. delete options.data.port;
  1638. delete options.data.uri_params;
  1639. if (options.startRule === 'SIP_URI') {
  1640. options.data = options.data.uri;
  1641. }
  1642. },
  1643. "sips",
  1644. peg$literalExpectation("sips", true),
  1645. "sip",
  1646. peg$literalExpectation("sip", true),
  1647. function (uri_scheme) {
  1648. options = options || { data: {} };
  1649. options.data.scheme = uri_scheme;
  1650. },
  1651. function () {
  1652. options = options || { data: {} };
  1653. options.data.user = decodeURIComponent(text().slice(0, -1));
  1654. },
  1655. function () {
  1656. options = options || { data: {} };
  1657. options.data.password = text();
  1658. },
  1659. function () {
  1660. options = options || { data: {} };
  1661. options.data.host = text();
  1662. return options.data.host;
  1663. },
  1664. function () {
  1665. options = options || { data: {} };
  1666. options.data.host_type = 'domain';
  1667. return text();
  1668. },
  1669. /^[a-zA-Z0-9_\-]/,
  1670. peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"], "_", "-"], false, false),
  1671. /^[a-zA-Z0-9\-]/,
  1672. peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"], "-"], false, false),
  1673. function () {
  1674. options = options || { data: {} };
  1675. options.data.host_type = 'IPv6';
  1676. return text();
  1677. },
  1678. "::",
  1679. peg$literalExpectation("::", false),
  1680. function () {
  1681. options = options || { data: {} };
  1682. options.data.host_type = 'IPv6';
  1683. return text();
  1684. },
  1685. function () {
  1686. options = options || { data: {} };
  1687. options.data.host_type = 'IPv4';
  1688. return text();
  1689. },
  1690. "25",
  1691. peg$literalExpectation("25", false),
  1692. /^[0-5]/,
  1693. peg$classExpectation([["0", "5"]], false, false),
  1694. "2",
  1695. peg$literalExpectation("2", false),
  1696. /^[0-4]/,
  1697. peg$classExpectation([["0", "4"]], false, false),
  1698. "1",
  1699. peg$literalExpectation("1", false),
  1700. /^[1-9]/,
  1701. peg$classExpectation([["1", "9"]], false, false),
  1702. function (port) {
  1703. options = options || { data: {} };
  1704. port = parseInt(port.join(''));
  1705. options.data.port = port;
  1706. return port;
  1707. },
  1708. "transport=",
  1709. peg$literalExpectation("transport=", true),
  1710. "udp",
  1711. peg$literalExpectation("udp", true),
  1712. "tcp",
  1713. peg$literalExpectation("tcp", true),
  1714. "sctp",
  1715. peg$literalExpectation("sctp", true),
  1716. "tls",
  1717. peg$literalExpectation("tls", true),
  1718. function (transport) {
  1719. options = options || { data: {} };
  1720. if (!options.data.uri_params)
  1721. options.data.uri_params = {};
  1722. options.data.uri_params['transport'] = transport.toLowerCase();
  1723. },
  1724. "user=",
  1725. peg$literalExpectation("user=", true),
  1726. "phone",
  1727. peg$literalExpectation("phone", true),
  1728. "ip",
  1729. peg$literalExpectation("ip", true),
  1730. function (user) {
  1731. options = options || { data: {} };
  1732. if (!options.data.uri_params)
  1733. options.data.uri_params = {};
  1734. options.data.uri_params['user'] = user.toLowerCase();
  1735. },
  1736. "method=",
  1737. peg$literalExpectation("method=", true),
  1738. function (method) {
  1739. options = options || { data: {} };
  1740. if (!options.data.uri_params)
  1741. options.data.uri_params = {};
  1742. options.data.uri_params['method'] = method;
  1743. },
  1744. "ttl=",
  1745. peg$literalExpectation("ttl=", true),
  1746. function (ttl) {
  1747. options = options || { data: {} };
  1748. if (!options.data.params)
  1749. options.data.params = {};
  1750. options.data.params['ttl'] = ttl;
  1751. },
  1752. "maddr=",
  1753. peg$literalExpectation("maddr=", true),
  1754. function (maddr) {
  1755. options = options || { data: {} };
  1756. if (!options.data.uri_params)
  1757. options.data.uri_params = {};
  1758. options.data.uri_params['maddr'] = maddr;
  1759. },
  1760. "lr",
  1761. peg$literalExpectation("lr", true),
  1762. function () {
  1763. options = options || { data: {} };
  1764. if (!options.data.uri_params)
  1765. options.data.uri_params = {};
  1766. options.data.uri_params['lr'] = undefined;
  1767. },
  1768. function (param, value) {
  1769. options = options || { data: {} };
  1770. if (!options.data.uri_params)
  1771. options.data.uri_params = {};
  1772. if (value === null) {
  1773. value = undefined;
  1774. }
  1775. else {
  1776. value = value[1];
  1777. }
  1778. options.data.uri_params[param.toLowerCase()] = value;
  1779. },
  1780. function (hname, hvalue) {
  1781. hname = hname.join('').toLowerCase();
  1782. hvalue = hvalue.join('');
  1783. options = options || { data: {} };
  1784. if (!options.data.uri_headers)
  1785. options.data.uri_headers = {};
  1786. if (!options.data.uri_headers[hname]) {
  1787. options.data.uri_headers[hname] = [hvalue];
  1788. }
  1789. else {
  1790. options.data.uri_headers[hname].push(hvalue);
  1791. }
  1792. },
  1793. function () {
  1794. options = options || { data: {} };
  1795. // lots of tests fail if this isn't guarded...
  1796. if (options.startRule === 'Refer_To') {
  1797. options.data.uri = new uri_1.URI(options.data.scheme, options.data.user, options.data.host, options.data.port, options.data.uri_params, options.data.uri_headers);
  1798. delete options.data.scheme;
  1799. delete options.data.user;
  1800. delete options.data.host;
  1801. delete options.data.host_type;
  1802. delete options.data.port;
  1803. delete options.data.uri_params;
  1804. }
  1805. },
  1806. "//",
  1807. peg$literalExpectation("//", false),
  1808. function () {
  1809. options = options || { data: {} };
  1810. options.data.scheme = text();
  1811. },
  1812. peg$literalExpectation("SIP", true),
  1813. function () {
  1814. options = options || { data: {} };
  1815. options.data.sip_version = text();
  1816. },
  1817. "INVITE",
  1818. peg$literalExpectation("INVITE", false),
  1819. "ACK",
  1820. peg$literalExpectation("ACK", false),
  1821. "VXACH",
  1822. peg$literalExpectation("VXACH", false),
  1823. "OPTIONS",
  1824. peg$literalExpectation("OPTIONS", false),
  1825. "BYE",
  1826. peg$literalExpectation("BYE", false),
  1827. "CANCEL",
  1828. peg$literalExpectation("CANCEL", false),
  1829. "REGISTER",
  1830. peg$literalExpectation("REGISTER", false),
  1831. "SUBSCRIBE",
  1832. peg$literalExpectation("SUBSCRIBE", false),
  1833. "NOTIFY",
  1834. peg$literalExpectation("NOTIFY", false),
  1835. "REFER",
  1836. peg$literalExpectation("REFER", false),
  1837. "PUBLISH",
  1838. peg$literalExpectation("PUBLISH", false),
  1839. function () {
  1840. options = options || { data: {} };
  1841. options.data.method = text();
  1842. return options.data.method;
  1843. },
  1844. function (status_code) {
  1845. options = options || { data: {} };
  1846. options.data.status_code = parseInt(status_code.join(''));
  1847. },
  1848. function () {
  1849. options = options || { data: {} };
  1850. options.data.reason_phrase = text();
  1851. },
  1852. function () {
  1853. options = options || { data: {} };
  1854. options.data = text();
  1855. },
  1856. function () {
  1857. var idx, length;
  1858. options = options || { data: {} };
  1859. length = options.data.multi_header.length;
  1860. for (idx = 0; idx < length; idx++) {
  1861. if (options.data.multi_header[idx].parsed === null) {
  1862. options.data = null;
  1863. break;
  1864. }
  1865. }
  1866. if (options.data !== null) {
  1867. options.data = options.data.multi_header;
  1868. }
  1869. else {
  1870. options.data = -1;
  1871. }
  1872. },
  1873. function () {
  1874. var header;
  1875. options = options || { data: {} };
  1876. if (!options.data.multi_header)
  1877. options.data.multi_header = [];
  1878. try {
  1879. header = new name_addr_header_1.NameAddrHeader(options.data.uri, options.data.displayName, options.data.params);
  1880. delete options.data.uri;
  1881. delete options.data.displayName;
  1882. delete options.data.params;
  1883. }
  1884. catch (e) {
  1885. header = null;
  1886. }
  1887. options.data.multi_header.push({ 'position': peg$currPos,
  1888. 'offset': location().start.offset,
  1889. 'parsed': header
  1890. });
  1891. },
  1892. function (displayName) {
  1893. displayName = text().trim();
  1894. if (displayName[0] === '\"') {
  1895. displayName = displayName.substring(1, displayName.length - 1);
  1896. }
  1897. options = options || { data: {} };
  1898. options.data.displayName = displayName;
  1899. },
  1900. "q",
  1901. peg$literalExpectation("q", true),
  1902. function (q) {
  1903. options = options || { data: {} };
  1904. if (!options.data.params)
  1905. options.data.params = {};
  1906. options.data.params['q'] = q;
  1907. },
  1908. "expires",
  1909. peg$literalExpectation("expires", true),
  1910. function (expires) {
  1911. options = options || { data: {} };
  1912. if (!options.data.params)
  1913. options.data.params = {};
  1914. options.data.params['expires'] = expires;
  1915. },
  1916. function (delta_seconds) {
  1917. return parseInt(delta_seconds.join(''));
  1918. },
  1919. "0",
  1920. peg$literalExpectation("0", false),
  1921. function () {
  1922. return parseFloat(text());
  1923. },
  1924. function (param, value) {
  1925. options = options || { data: {} };
  1926. if (!options.data.params)
  1927. options.data.params = {};
  1928. if (value === null) {
  1929. value = undefined;
  1930. }
  1931. else {
  1932. value = value[1];
  1933. }
  1934. options.data.params[param.toLowerCase()] = value;
  1935. },
  1936. "render",
  1937. peg$literalExpectation("render", true),
  1938. "session",
  1939. peg$literalExpectation("session", true),
  1940. "icon",
  1941. peg$literalExpectation("icon", true),
  1942. "alert",
  1943. peg$literalExpectation("alert", true),
  1944. function () {
  1945. options = options || { data: {} };
  1946. if (options.startRule === 'Content_Disposition') {
  1947. options.data.type = text().toLowerCase();
  1948. }
  1949. },
  1950. "handling",
  1951. peg$literalExpectation("handling", true),
  1952. "optional",
  1953. peg$literalExpectation("optional", true),
  1954. "required",
  1955. peg$literalExpectation("required", true),
  1956. function (length) {
  1957. options = options || { data: {} };
  1958. options.data = parseInt(length.join(''));
  1959. },
  1960. function () {
  1961. options = options || { data: {} };
  1962. options.data = text();
  1963. },
  1964. "text",
  1965. peg$literalExpectation("text", true),
  1966. "image",
  1967. peg$literalExpectation("image", true),
  1968. "audio",
  1969. peg$literalExpectation("audio", true),
  1970. "video",
  1971. peg$literalExpectation("video", true),
  1972. "application",
  1973. peg$literalExpectation("application", true),
  1974. "message",
  1975. peg$literalExpectation("message", true),
  1976. "multipart",
  1977. peg$literalExpectation("multipart", true),
  1978. "x-",
  1979. peg$literalExpectation("x-", true),
  1980. function (cseq_value) {
  1981. options = options || { data: {} };
  1982. options.data.value = parseInt(cseq_value.join(''));
  1983. },
  1984. function (expires) { options = options || { data: {} }; options.data = expires; },
  1985. function (event_type) {
  1986. options = options || { data: {} };
  1987. options.data.event = event_type.toLowerCase();
  1988. },
  1989. function () {
  1990. options = options || { data: {} };
  1991. var tag = options.data.tag;
  1992. options.data = new name_addr_header_1.NameAddrHeader(options.data.uri, options.data.displayName, options.data.params);
  1993. if (tag) {
  1994. options.data.setParam('tag', tag);
  1995. }
  1996. },
  1997. "tag",
  1998. peg$literalExpectation("tag", true),
  1999. function (tag) { options = options || { data: {} }; options.data.tag = tag; },
  2000. function (forwards) {
  2001. options = options || { data: {} };
  2002. options.data = parseInt(forwards.join(''));
  2003. },
  2004. function (min_expires) { options = options || { data: {} }; options.data = min_expires; },
  2005. function () {
  2006. options = options || { data: {} };
  2007. options.data = new name_addr_header_1.NameAddrHeader(options.data.uri, options.data.displayName, options.data.params);
  2008. },
  2009. "digest",
  2010. peg$literalExpectation("Digest", true),
  2011. "realm",
  2012. peg$literalExpectation("realm", true),
  2013. function (realm) { options = options || { data: {} }; options.data.realm = realm; },
  2014. "domain",
  2015. peg$literalExpectation("domain", true),
  2016. "nonce",
  2017. peg$literalExpectation("nonce", true),
  2018. function (nonce) { options = options || { data: {} }; options.data.nonce = nonce; },
  2019. "opaque",
  2020. peg$literalExpectation("opaque", true),
  2021. function (opaque) { options = options || { data: {} }; options.data.opaque = opaque; },
  2022. "stale",
  2023. peg$literalExpectation("stale", true),
  2024. "true",
  2025. peg$literalExpectation("true", true),
  2026. function () { options = options || { data: {} }; options.data.stale = true; },
  2027. "false",
  2028. peg$literalExpectation("false", true),
  2029. function () { options = options || { data: {} }; options.data.stale = false; },
  2030. "algorithm",
  2031. peg$literalExpectation("algorithm", true),
  2032. "md5",
  2033. peg$literalExpectation("MD5", true),
  2034. "md5-sess",
  2035. peg$literalExpectation("MD5-sess", true),
  2036. function (algorithm) {
  2037. options = options || { data: {} };
  2038. options.data.algorithm = algorithm.toUpperCase();
  2039. },
  2040. "qop",
  2041. peg$literalExpectation("qop", true),
  2042. "auth-int",
  2043. peg$literalExpectation("auth-int", true),
  2044. "auth",
  2045. peg$literalExpectation("auth", true),
  2046. function (qop_value) {
  2047. options = options || { data: {} };
  2048. options.data.qop || (options.data.qop = []);
  2049. options.data.qop.push(qop_value.toLowerCase());
  2050. },
  2051. function (rack_value) {
  2052. options = options || { data: {} };
  2053. options.data.value = parseInt(rack_value.join(''));
  2054. },
  2055. function () {
  2056. var idx, length;
  2057. options = options || { data: {} };
  2058. length = options.data.multi_header.length;
  2059. for (idx = 0; idx < length; idx++) {
  2060. if (options.data.multi_header[idx].parsed === null) {
  2061. options.data = null;
  2062. break;
  2063. }
  2064. }
  2065. if (options.data !== null) {
  2066. options.data = options.data.multi_header;
  2067. }
  2068. else {
  2069. options.data = -1;
  2070. }
  2071. },
  2072. function () {
  2073. var header;
  2074. options = options || { data: {} };
  2075. if (!options.data.multi_header)
  2076. options.data.multi_header = [];
  2077. try {
  2078. header = new name_addr_header_1.NameAddrHeader(options.data.uri, options.data.displayName, options.data.params);
  2079. delete options.data.uri;
  2080. delete options.data.displayName;
  2081. delete options.data.params;
  2082. }
  2083. catch (e) {
  2084. header = null;
  2085. }
  2086. options.data.multi_header.push({ 'position': peg$currPos,
  2087. 'offset': location().start.offset,
  2088. 'parsed': header
  2089. });
  2090. },
  2091. function () {
  2092. options = options || { data: {} };
  2093. options.data = new name_addr_header_1.NameAddrHeader(options.data.uri, options.data.displayName, options.data.params);
  2094. },
  2095. function () {
  2096. options = options || { data: {} };
  2097. if (!(options.data.replaces_from_tag && options.data.replaces_to_tag)) {
  2098. options.data = -1;
  2099. }
  2100. },
  2101. function () {
  2102. options = options || { data: {} };
  2103. options.data = {
  2104. call_id: options.data
  2105. };
  2106. },
  2107. "from-tag",
  2108. peg$literalExpectation("from-tag", true),
  2109. function (from_tag) {
  2110. options = options || { data: {} };
  2111. options.data.replaces_from_tag = from_tag;
  2112. },
  2113. "to-tag",
  2114. peg$literalExpectation("to-tag", true),
  2115. function (to_tag) {
  2116. options = options || { data: {} };
  2117. options.data.replaces_to_tag = to_tag;
  2118. },
  2119. "early-only",
  2120. peg$literalExpectation("early-only", true),
  2121. function () {
  2122. options = options || { data: {} };
  2123. options.data.early_only = true;
  2124. },
  2125. function (head, r) { return r; },
  2126. function (head, tail) { return list(head, tail); },
  2127. function (value) {
  2128. options = options || { data: {} };
  2129. if (options.startRule === 'Require') {
  2130. options.data = value || [];
  2131. }
  2132. },
  2133. function (rseq_value) {
  2134. options = options || { data: {} };
  2135. options.data.value = parseInt(rseq_value.join(''));
  2136. },
  2137. "active",
  2138. peg$literalExpectation("active", true),
  2139. "pending",
  2140. peg$literalExpectation("pending", true),
  2141. "terminated",
  2142. peg$literalExpectation("terminated", true),
  2143. function () {
  2144. options = options || { data: {} };
  2145. options.data.state = text();
  2146. },
  2147. "reason",
  2148. peg$literalExpectation("reason", true),
  2149. function (reason) {
  2150. options = options || { data: {} };
  2151. if (typeof reason !== 'undefined')
  2152. options.data.reason = reason;
  2153. },
  2154. function (expires) {
  2155. options = options || { data: {} };
  2156. if (typeof expires !== 'undefined')
  2157. options.data.expires = expires;
  2158. },
  2159. "retry_after",
  2160. peg$literalExpectation("retry_after", true),
  2161. function (retry_after) {
  2162. options = options || { data: {} };
  2163. if (typeof retry_after !== 'undefined')
  2164. options.data.retry_after = retry_after;
  2165. },
  2166. "deactivated",
  2167. peg$literalExpectation("deactivated", true),
  2168. "probation",
  2169. peg$literalExpectation("probation", true),
  2170. "rejected",
  2171. peg$literalExpectation("rejected", true),
  2172. "timeout",
  2173. peg$literalExpectation("timeout", true),
  2174. "giveup",
  2175. peg$literalExpectation("giveup", true),
  2176. "noresource",
  2177. peg$literalExpectation("noresource", true),
  2178. "invariant",
  2179. peg$literalExpectation("invariant", true),
  2180. function (value) {
  2181. options = options || { data: {} };
  2182. if (options.startRule === 'Supported') {
  2183. options.data = value || [];
  2184. }
  2185. },
  2186. function () {
  2187. options = options || { data: {} };
  2188. var tag = options.data.tag;
  2189. options.data = new name_addr_header_1.NameAddrHeader(options.data.uri, options.data.displayName, options.data.params);
  2190. if (tag) {
  2191. options.data.setParam('tag', tag);
  2192. }
  2193. },
  2194. "ttl",
  2195. peg$literalExpectation("ttl", true),
  2196. function (via_ttl_value) {
  2197. options = options || { data: {} };
  2198. options.data.ttl = via_ttl_value;
  2199. },
  2200. "maddr",
  2201. peg$literalExpectation("maddr", true),
  2202. function (via_maddr) {
  2203. options = options || { data: {} };
  2204. options.data.maddr = via_maddr;
  2205. },
  2206. "received",
  2207. peg$literalExpectation("received", true),
  2208. function (via_received) {
  2209. options = options || { data: {} };
  2210. options.data.received = via_received;
  2211. },
  2212. "branch",
  2213. peg$literalExpectation("branch", true),
  2214. function (via_branch) {
  2215. options = options || { data: {} };
  2216. options.data.branch = via_branch;
  2217. },
  2218. "rport",
  2219. peg$literalExpectation("rport", true),
  2220. function (response_port) {
  2221. options = options || { data: {} };
  2222. if (typeof response_port !== 'undefined')
  2223. options.data.rport = response_port.join('');
  2224. },
  2225. function (via_protocol) {
  2226. options = options || { data: {} };
  2227. options.data.protocol = via_protocol;
  2228. },
  2229. peg$literalExpectation("UDP", true),
  2230. peg$literalExpectation("TCP", true),
  2231. peg$literalExpectation("TLS", true),
  2232. peg$literalExpectation("SCTP", true),
  2233. function (via_transport) {
  2234. options = options || { data: {} };
  2235. options.data.transport = via_transport;
  2236. },
  2237. function () {
  2238. options = options || { data: {} };
  2239. options.data.host = text();
  2240. },
  2241. function (via_sent_by_port) {
  2242. options = options || { data: {} };
  2243. options.data.port = parseInt(via_sent_by_port.join(''));
  2244. },
  2245. function (ttl) {
  2246. return parseInt(ttl.join(''));
  2247. },
  2248. function (deltaSeconds) {
  2249. options = options || { data: {} };
  2250. if (options.startRule === 'Session_Expires') {
  2251. options.data.deltaSeconds = deltaSeconds;
  2252. }
  2253. },
  2254. "refresher",
  2255. peg$literalExpectation("refresher", false),
  2256. "uas",
  2257. peg$literalExpectation("uas", false),
  2258. "uac",
  2259. peg$literalExpectation("uac", false),
  2260. function (endpoint) {
  2261. options = options || { data: {} };
  2262. if (options.startRule === 'Session_Expires') {
  2263. options.data.refresher = endpoint;
  2264. }
  2265. },
  2266. function (deltaSeconds) {
  2267. options = options || { data: {} };
  2268. if (options.startRule === 'Min_SE') {
  2269. options.data = deltaSeconds;
  2270. }
  2271. },
  2272. "stuns",
  2273. peg$literalExpectation("stuns", true),
  2274. "stun",
  2275. peg$literalExpectation("stun", true),
  2276. function (scheme) {
  2277. options = options || { data: {} };
  2278. options.data.scheme = scheme;
  2279. },
  2280. function (host) {
  2281. options = options || { data: {} };
  2282. options.data.host = host;
  2283. },
  2284. "?transport=",
  2285. peg$literalExpectation("?transport=", false),
  2286. "turns",
  2287. peg$literalExpectation("turns", true),
  2288. "turn",
  2289. peg$literalExpectation("turn", true),
  2290. function (transport) {
  2291. options = options || { data: {} };
  2292. options.data.transport = transport;
  2293. },
  2294. function () {
  2295. options = options || { data: {} };
  2296. options.data = text();
  2297. },
  2298. "Referred-By",
  2299. peg$literalExpectation("Referred-By", false),
  2300. "b",
  2301. peg$literalExpectation("b", false),
  2302. "cid",
  2303. peg$literalExpectation("cid", false)
  2304. ];
  2305. var peg$bytecode = [
  2306. peg$decode("2 \"\"6 7!"),
  2307. peg$decode("4\"\"\"5!7#"),
  2308. peg$decode("4$\"\"5!7%"),
  2309. peg$decode("4&\"\"5!7'"),
  2310. peg$decode(";'.# &;("),
  2311. peg$decode("4(\"\"5!7)"),
  2312. peg$decode("4*\"\"5!7+"),
  2313. peg$decode("2,\"\"6,7-"),
  2314. peg$decode("2.\"\"6.7/"),
  2315. peg$decode("40\"\"5!71"),
  2316. peg$decode("22\"\"6273.\x89 &24\"\"6475.} &26\"\"6677.q &28\"\"6879.e &2:\"\"6:7;.Y &2<\"\"6<7=.M &2>\"\"6>7?.A &2@\"\"6@7A.5 &2B\"\"6B7C.) &2D\"\"6D7E"),
  2317. peg$decode(";).# &;,"),
  2318. peg$decode("2F\"\"6F7G.} &2H\"\"6H7I.q &2J\"\"6J7K.e &2L\"\"6L7M.Y &2N\"\"6N7O.M &2P\"\"6P7Q.A &2R\"\"6R7S.5 &2T\"\"6T7U.) &2V\"\"6V7W"),
  2319. peg$decode("%%2X\"\"6X7Y/5#;#/,$;#/#$+#)(#'#(\"'#&'#/\"!&,)"),
  2320. peg$decode("%%$;$0#*;$&/,#; /#$+\")(\"'#&'#.\" &\"/=#$;$/&#0#*;$&&&#/'$8\":Z\" )(\"'#&'#"),
  2321. peg$decode(";..\" &\""),
  2322. peg$decode("%$;'.# &;(0)*;'.# &;(&/?#28\"\"6879/0$;//'$8#:[# )(#'#(\"'#&'#"),
  2323. peg$decode("%%$;2/&#0#*;2&&&#/g#$%$;.0#*;.&/,#;2/#$+\")(\"'#&'#0=*%$;.0#*;.&/,#;2/#$+\")(\"'#&'#&/#$+\")(\"'#&'#/\"!&,)"),
  2324. peg$decode("4\\\"\"5!7].# &;3"),
  2325. peg$decode("4^\"\"5!7_"),
  2326. peg$decode("4`\"\"5!7a"),
  2327. peg$decode(";!.) &4b\"\"5!7c"),
  2328. peg$decode("%$;).\x95 &2F\"\"6F7G.\x89 &2J\"\"6J7K.} &2L\"\"6L7M.q &2X\"\"6X7Y.e &2P\"\"6P7Q.Y &2H\"\"6H7I.M &2@\"\"6@7A.A &2d\"\"6d7e.5 &2R\"\"6R7S.) &2N\"\"6N7O/\x9E#0\x9B*;).\x95 &2F\"\"6F7G.\x89 &2J\"\"6J7K.} &2L\"\"6L7M.q &2X\"\"6X7Y.e &2P\"\"6P7Q.Y &2H\"\"6H7I.M &2@\"\"6@7A.A &2d\"\"6d7e.5 &2R\"\"6R7S.) &2N\"\"6N7O&&&#/\"!&,)"),
  2329. peg$decode("%$;).\x89 &2F\"\"6F7G.} &2L\"\"6L7M.q &2X\"\"6X7Y.e &2P\"\"6P7Q.Y &2H\"\"6H7I.M &2@\"\"6@7A.A &2d\"\"6d7e.5 &2R\"\"6R7S.) &2N\"\"6N7O/\x92#0\x8F*;).\x89 &2F\"\"6F7G.} &2L\"\"6L7M.q &2X\"\"6X7Y.e &2P\"\"6P7Q.Y &2H\"\"6H7I.M &2@\"\"6@7A.A &2d\"\"6d7e.5 &2R\"\"6R7S.) &2N\"\"6N7O&&&#/\"!&,)"),
  2330. peg$decode("2T\"\"6T7U.\xE3 &2V\"\"6V7W.\xD7 &2f\"\"6f7g.\xCB &2h\"\"6h7i.\xBF &2:\"\"6:7;.\xB3 &2D\"\"6D7E.\xA7 &22\"\"6273.\x9B &28\"\"6879.\x8F &2j\"\"6j7k.\x83 &;&.} &24\"\"6475.q &2l\"\"6l7m.e &2n\"\"6n7o.Y &26\"\"6677.M &2>\"\"6>7?.A &2p\"\"6p7q.5 &2r\"\"6r7s.) &;'.# &;("),
  2331. peg$decode("%$;).\u012B &2F\"\"6F7G.\u011F &2J\"\"6J7K.\u0113 &2L\"\"6L7M.\u0107 &2X\"\"6X7Y.\xFB &2P\"\"6P7Q.\xEF &2H\"\"6H7I.\xE3 &2@\"\"6@7A.\xD7 &2d\"\"6d7e.\xCB &2R\"\"6R7S.\xBF &2N\"\"6N7O.\xB3 &2T\"\"6T7U.\xA7 &2V\"\"6V7W.\x9B &2f\"\"6f7g.\x8F &2h\"\"6h7i.\x83 &28\"\"6879.w &2j\"\"6j7k.k &;&.e &24\"\"6475.Y &2l\"\"6l7m.M &2n\"\"6n7o.A &26\"\"6677.5 &2p\"\"6p7q.) &2r\"\"6r7s/\u0134#0\u0131*;).\u012B &2F\"\"6F7G.\u011F &2J\"\"6J7K.\u0113 &2L\"\"6L7M.\u0107 &2X\"\"6X7Y.\xFB &2P\"\"6P7Q.\xEF &2H\"\"6H7I.\xE3 &2@\"\"6@7A.\xD7 &2d\"\"6d7e.\xCB &2R\"\"6R7S.\xBF &2N\"\"6N7O.\xB3 &2T\"\"6T7U.\xA7 &2V\"\"6V7W.\x9B &2f\"\"6f7g.\x8F &2h\"\"6h7i.\x83 &28\"\"6879.w &2j\"\"6j7k.k &;&.e &24\"\"6475.Y &2l\"\"6l7m.M &2n\"\"6n7o.A &26\"\"6677.5 &2p\"\"6p7q.) &2r\"\"6r7s&&&#/\"!&,)"),
  2332. peg$decode("%;//?#2P\"\"6P7Q/0$;//'$8#:t# )(#'#(\"'#&'#"),
  2333. peg$decode("%;//?#24\"\"6475/0$;//'$8#:u# )(#'#(\"'#&'#"),
  2334. peg$decode("%;//?#2>\"\"6>7?/0$;//'$8#:v# )(#'#(\"'#&'#"),
  2335. peg$decode("%;//?#2T\"\"6T7U/0$;//'$8#:w# )(#'#(\"'#&'#"),
  2336. peg$decode("%;//?#2V\"\"6V7W/0$;//'$8#:x# )(#'#(\"'#&'#"),
  2337. peg$decode("%2h\"\"6h7i/0#;//'$8\":y\" )(\"'#&'#"),
  2338. peg$decode("%;//6#2f\"\"6f7g/'$8\":z\" )(\"'#&'#"),
  2339. peg$decode("%;//?#2D\"\"6D7E/0$;//'$8#:{# )(#'#(\"'#&'#"),
  2340. peg$decode("%;//?#22\"\"6273/0$;//'$8#:|# )(#'#(\"'#&'#"),
  2341. peg$decode("%;//?#28\"\"6879/0$;//'$8#:}# )(#'#(\"'#&'#"),
  2342. peg$decode("%;//0#;&/'$8\":~\" )(\"'#&'#"),
  2343. peg$decode("%;&/0#;//'$8\":~\" )(\"'#&'#"),
  2344. peg$decode("%;=/T#$;G.) &;K.# &;F0/*;G.) &;K.# &;F&/,$;>/#$+#)(#'#(\"'#&'#"),
  2345. peg$decode("4\x7F\"\"5!7\x80.A &4\x81\"\"5!7\x82.5 &4\x83\"\"5!7\x84.) &;3.# &;."),
  2346. peg$decode("%%;//Q#;&/H$$;J.# &;K0)*;J.# &;K&/,$;&/#$+$)($'#(#'#(\"'#&'#/\"!&,)"),
  2347. peg$decode("%;//]#;&/T$%$;J.# &;K0)*;J.# &;K&/\"!&,)/1$;&/($8$:\x85$!!)($'#(#'#(\"'#&'#"),
  2348. peg$decode(";..G &2L\"\"6L7M.; &4\x86\"\"5!7\x87./ &4\x83\"\"5!7\x84.# &;3"),
  2349. peg$decode("%2j\"\"6j7k/J#4\x88\"\"5!7\x89.5 &4\x8A\"\"5!7\x8B.) &4\x8C\"\"5!7\x8D/#$+\")(\"'#&'#"),
  2350. peg$decode("%;N/M#28\"\"6879/>$;O.\" &\"/0$;S/'$8$:\x8E$ )($'#(#'#(\"'#&'#"),
  2351. peg$decode("%;N/d#28\"\"6879/U$;O.\" &\"/G$;S/>$;_/5$;l.\" &\"/'$8&:\x8F& )(&'#(%'#($'#(#'#(\"'#&'#"),
  2352. peg$decode("%3\x90\"\"5$7\x91.) &3\x92\"\"5#7\x93/' 8!:\x94!! )"),
  2353. peg$decode("%;P/]#%28\"\"6879/,#;R/#$+\")(\"'#&'#.\" &\"/6$2:\"\"6:7;/'$8#:\x95# )(#'#(\"'#&'#"),
  2354. peg$decode("$;+.) &;-.# &;Q/2#0/*;+.) &;-.# &;Q&&&#"),
  2355. peg$decode("2<\"\"6<7=.q &2>\"\"6>7?.e &2@\"\"6@7A.Y &2B\"\"6B7C.M &2D\"\"6D7E.A &22\"\"6273.5 &26\"\"6677.) &24\"\"6475"),
  2356. peg$decode("%$;+._ &;-.Y &2<\"\"6<7=.M &2>\"\"6>7?.A &2@\"\"6@7A.5 &2B\"\"6B7C.) &2D\"\"6D7E0e*;+._ &;-.Y &2<\"\"6<7=.M &2>\"\"6>7?.A &2@\"\"6@7A.5 &2B\"\"6B7C.) &2D\"\"6D7E&/& 8!:\x96! )"),
  2357. peg$decode("%;T/J#%28\"\"6879/,#;^/#$+\")(\"'#&'#.\" &\"/#$+\")(\"'#&'#"),
  2358. peg$decode("%;U.) &;\\.# &;X/& 8!:\x97! )"),
  2359. peg$decode("%$%;V/2#2J\"\"6J7K/#$+\")(\"'#&'#0<*%;V/2#2J\"\"6J7K/#$+\")(\"'#&'#&/D#;W/;$2J\"\"6J7K.\" &\"/'$8#:\x98# )(#'#(\"'#&'#"),
  2360. peg$decode("$4\x99\"\"5!7\x9A/,#0)*4\x99\"\"5!7\x9A&&&#"),
  2361. peg$decode("%4$\"\"5!7%/?#$4\x9B\"\"5!7\x9C0)*4\x9B\"\"5!7\x9C&/#$+\")(\"'#&'#"),
  2362. peg$decode("%2l\"\"6l7m/?#;Y/6$2n\"\"6n7o/'$8#:\x9D# )(#'#(\"'#&'#"),
  2363. peg$decode("%%;Z/\xB3#28\"\"6879/\xA4$;Z/\x9B$28\"\"6879/\x8C$;Z/\x83$28\"\"6879/t$;Z/k$28\"\"6879/\\$;Z/S$28\"\"6879/D$;Z/;$28\"\"6879/,$;[/#$+-)(-'#(,'#(+'#(*'#()'#(('#(''#(&'#(%'#($'#(#'#(\"'#&'#.\u0790 &%2\x9E\"\"6\x9E7\x9F/\xA4#;Z/\x9B$28\"\"6879/\x8C$;Z/\x83$28\"\"6879/t$;Z/k$28\"\"6879/\\$;Z/S$28\"\"6879/D$;Z/;$28\"\"6879/,$;[/#$+,)(,'#(+'#(*'#()'#(('#(''#(&'#(%'#($'#(#'#(\"'#&'#.\u06F9 &%2\x9E\"\"6\x9E7\x9F/\x8C#;Z/\x83$28\"\"6879/t$;Z/k$28\"\"6879/\\$;Z/S$28\"\"6879/D$;Z/;$28\"\"6879/,$;[/#$+*)(*'#()'#(('#(''#(&'#(%'#($'#(#'#(\"'#&'#.\u067A &%2\x9E\"\"6\x9E7\x9F/t#;Z/k$28\"\"6879/\\$;Z/S$28\"\"6879/D$;Z/;$28\"\"6879/,$;[/#$+()(('#(''#(&'#(%'#($'#(#'#(\"'#&'#.\u0613 &%2\x9E\"\"6\x9E7\x9F/\\#;Z/S$28\"\"6879/D$;Z/;$28\"\"6879/,$;[/#$+&)(&'#(%'#($'#(#'#(\"'#&'#.\u05C4 &%2\x9E\"\"6\x9E7\x9F/D#;Z/;$28\"\"6879/,$;[/#$+$)($'#(#'#(\"'#&'#.\u058D &%2\x9E\"\"6\x9E7\x9F/,#;[/#$+\")(\"'#&'#.\u056E &%2\x9E\"\"6\x9E7\x9F/,#;Z/#$+\")(\"'#&'#.\u054F &%;Z/\x9B#2\x9E\"\"6\x9E7\x9F/\x8C$;Z/\x83$28\"\"6879/t$;Z/k$28\"\"6879/\\$;Z/S$28\"\"6879/D$;Z/;$28\"\"6879/,$;[/#$++)(+'#(*'#()'#(('#(''#(&'#(%'#($'#(#'#(\"'#&'#.\u04C7 &%;Z/\xAA#%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\x83$2\x9E\"\"6\x9E7\x9F/t$;Z/k$28\"\"6879/\\$;Z/S$28\"\"6879/D$;Z/;$28\"\"6879/,$;[/#$+*)(*'#()'#(('#(''#(&'#(%'#($'#(#'#(\"'#&'#.\u0430 &%;Z/\xB9#%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\x92$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/k$2\x9E\"\"6\x9E7\x9F/\\$;Z/S$28\"\"6879/D$;Z/;$28\"\"6879/,$;[/#$+))()'#(('#(''#(&'#(%'#($'#(#'#(\"'#&'#.\u038A &%;Z/\xC8#%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\xA1$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/z$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/S$2\x9E\"\"6\x9E7\x9F/D$;Z/;$28\"\"6879/,$;[/#$+()(('#(''#(&'#(%'#($'#(#'#(\"'#&'#.\u02D5 &%;Z/\xD7#%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\xB0$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\x89$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/b$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/;$2\x9E\"\"6\x9E7\x9F/,$;[/#$+')(''#(&'#(%'#($'#(#'#(\"'#&'#.\u0211 &%;Z/\xFE#%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\xD7$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\xB0$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\x89$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/b$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/;$2\x9E\"\"6\x9E7\x9F/,$;Z/#$+()(('#(''#(&'#(%'#($'#(#'#(\"'#&'#.\u0126 &%;Z/\u011C#%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\xF5$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\xCE$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\xA7$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/\x80$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/Y$%28\"\"6879/,#;Z/#$+\")(\"'#&'#.\" &\"/2$2\x9E\"\"6\x9E7\x9F/#$+()(('#(''#(&'#(%'#($'#(#'#(\"'#&'#/& 8!:\xA0! )"),
  2364. peg$decode("%;#/M#;#.\" &\"/?$;#.\" &\"/1$;#.\" &\"/#$+$)($'#(#'#(\"'#&'#"),
  2365. peg$decode("%;Z/;#28\"\"6879/,$;Z/#$+#)(#'#(\"'#&'#.# &;\\"),
  2366. peg$decode("%;]/o#2J\"\"6J7K/`$;]/W$2J\"\"6J7K/H$;]/?$2J\"\"6J7K/0$;]/'$8':\xA1' )(''#(&'#(%'#($'#(#'#(\"'#&'#"),
  2367. peg$decode("%2\xA2\"\"6\xA27\xA3/2#4\xA4\"\"5!7\xA5/#$+\")(\"'#&'#.\x98 &%2\xA6\"\"6\xA67\xA7/;#4\xA8\"\"5!7\xA9/,$;!/#$+#)(#'#(\"'#&'#.j &%2\xAA\"\"6\xAA7\xAB/5#;!/,$;!/#$+#)(#'#(\"'#&'#.B &%4\xAC\"\"5!7\xAD/,#;!/#$+\")(\"'#&'#.# &;!"),
  2368. peg$decode("%%;!.\" &\"/[#;!.\" &\"/M$;!.\" &\"/?$;!.\" &\"/1$;!.\" &\"/#$+%)(%'#($'#(#'#(\"'#&'#/' 8!:\xAE!! )"),
  2369. peg$decode("$%22\"\"6273/,#;`/#$+\")(\"'#&'#0<*%22\"\"6273/,#;`/#$+\")(\"'#&'#&"),
  2370. peg$decode(";a.A &;b.; &;c.5 &;d./ &;e.) &;f.# &;g"),
  2371. peg$decode("%3\xAF\"\"5*7\xB0/a#3\xB1\"\"5#7\xB2.G &3\xB3\"\"5#7\xB4.; &3\xB5\"\"5$7\xB6./ &3\xB7\"\"5#7\xB8.# &;6/($8\":\xB9\"! )(\"'#&'#"),
  2372. peg$decode("%3\xBA\"\"5%7\xBB/I#3\xBC\"\"5%7\xBD./ &3\xBE\"\"5\"7\xBF.# &;6/($8\":\xC0\"! )(\"'#&'#"),
  2373. peg$decode("%3\xC1\"\"5'7\xC2/1#;\x90/($8\":\xC3\"! )(\"'#&'#"),
  2374. peg$decode("%3\xC4\"\"5$7\xC5/1#;\xF0/($8\":\xC6\"! )(\"'#&'#"),
  2375. peg$decode("%3\xC7\"\"5&7\xC8/1#;T/($8\":\xC9\"! )(\"'#&'#"),
  2376. peg$decode("%3\xCA\"\"5\"7\xCB/N#%2>\"\"6>7?/,#;6/#$+\")(\"'#&'#.\" &\"/'$8\":\xCC\" )(\"'#&'#"),
  2377. peg$decode("%;h/P#%2>\"\"6>7?/,#;i/#$+\")(\"'#&'#.\" &\"/)$8\":\xCD\"\"! )(\"'#&'#"),
  2378. peg$decode("%$;j/&#0#*;j&&&#/\"!&,)"),
  2379. peg$decode("%$;j/&#0#*;j&&&#/\"!&,)"),
  2380. peg$decode(";k.) &;+.# &;-"),
  2381. peg$decode("2l\"\"6l7m.e &2n\"\"6n7o.Y &24\"\"6475.M &28\"\"6879.A &2<\"\"6<7=.5 &2@\"\"6@7A.) &2B\"\"6B7C"),
  2382. peg$decode("%26\"\"6677/n#;m/e$$%2<\"\"6<7=/,#;m/#$+\")(\"'#&'#0<*%2<\"\"6<7=/,#;m/#$+\")(\"'#&'#&/#$+#)(#'#(\"'#&'#"),
  2383. peg$decode("%;n/A#2>\"\"6>7?/2$;o/)$8#:\xCE#\"\" )(#'#(\"'#&'#"),
  2384. peg$decode("$;p.) &;+.# &;-/2#0/*;p.) &;+.# &;-&&&#"),
  2385. peg$decode("$;p.) &;+.# &;-0/*;p.) &;+.# &;-&"),
  2386. peg$decode("2l\"\"6l7m.e &2n\"\"6n7o.Y &24\"\"6475.M &26\"\"6677.A &28\"\"6879.5 &2@\"\"6@7A.) &2B\"\"6B7C"),
  2387. peg$decode(";\x91.# &;r"),
  2388. peg$decode("%;\x90/G#;'/>$;s/5$;'/,$;\x84/#$+%)(%'#($'#(#'#(\"'#&'#"),
  2389. peg$decode(";M.# &;t"),
  2390. peg$decode("%;\x7F/E#28\"\"6879/6$;u.# &;x/'$8#:\xCF# )(#'#(\"'#&'#"),
  2391. peg$decode("%;v.# &;w/J#%26\"\"6677/,#;\x83/#$+\")(\"'#&'#.\" &\"/#$+\")(\"'#&'#"),
  2392. peg$decode("%2\xD0\"\"6\xD07\xD1/:#;\x80/1$;w.\" &\"/#$+#)(#'#(\"'#&'#"),
  2393. peg$decode("%24\"\"6475/,#;{/#$+\")(\"'#&'#"),
  2394. peg$decode("%;z/3#$;y0#*;y&/#$+\")(\"'#&'#"),
  2395. peg$decode(";*.) &;+.# &;-"),
  2396. peg$decode(";+.\x8F &;-.\x89 &22\"\"6273.} &26\"\"6677.q &28\"\"6879.e &2:\"\"6:7;.Y &2<\"\"6<7=.M &2>\"\"6>7?.A &2@\"\"6@7A.5 &2B\"\"6B7C.) &2D\"\"6D7E"),
  2397. peg$decode("%;|/e#$%24\"\"6475/,#;|/#$+\")(\"'#&'#0<*%24\"\"6475/,#;|/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2398. peg$decode("%$;~0#*;~&/e#$%22\"\"6273/,#;}/#$+\")(\"'#&'#0<*%22\"\"6273/,#;}/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2399. peg$decode("$;~0#*;~&"),
  2400. peg$decode(";+.w &;-.q &28\"\"6879.e &2:\"\"6:7;.Y &2<\"\"6<7=.M &2>\"\"6>7?.A &2@\"\"6@7A.5 &2B\"\"6B7C.) &2D\"\"6D7E"),
  2401. peg$decode("%%;\"/\x87#$;\".G &;!.A &2@\"\"6@7A.5 &2F\"\"6F7G.) &2J\"\"6J7K0M*;\".G &;!.A &2@\"\"6@7A.5 &2F\"\"6F7G.) &2J\"\"6J7K&/#$+\")(\"'#&'#/& 8!:\xD2! )"),
  2402. peg$decode(";\x81.# &;\x82"),
  2403. peg$decode("%%;O/2#2:\"\"6:7;/#$+\")(\"'#&'#.\" &\"/,#;S/#$+\")(\"'#&'#.\" &\""),
  2404. peg$decode("$;+.\x83 &;-.} &2B\"\"6B7C.q &2D\"\"6D7E.e &22\"\"6273.Y &28\"\"6879.M &2:\"\"6:7;.A &2<\"\"6<7=.5 &2>\"\"6>7?.) &2@\"\"6@7A/\x8C#0\x89*;+.\x83 &;-.} &2B\"\"6B7C.q &2D\"\"6D7E.e &22\"\"6273.Y &28\"\"6879.M &2:\"\"6:7;.A &2<\"\"6<7=.5 &2>\"\"6>7?.) &2@\"\"6@7A&&&#"),
  2405. peg$decode("$;y0#*;y&"),
  2406. peg$decode("%3\x92\"\"5#7\xD3/q#24\"\"6475/b$$;!/&#0#*;!&&&#/L$2J\"\"6J7K/=$$;!/&#0#*;!&&&#/'$8%:\xD4% )(%'#($'#(#'#(\"'#&'#"),
  2407. peg$decode("2\xD5\"\"6\xD57\xD6"),
  2408. peg$decode("2\xD7\"\"6\xD77\xD8"),
  2409. peg$decode("2\xD9\"\"6\xD97\xDA"),
  2410. peg$decode("2\xDB\"\"6\xDB7\xDC"),
  2411. peg$decode("2\xDD\"\"6\xDD7\xDE"),
  2412. peg$decode("2\xDF\"\"6\xDF7\xE0"),
  2413. peg$decode("2\xE1\"\"6\xE17\xE2"),
  2414. peg$decode("2\xE3\"\"6\xE37\xE4"),
  2415. peg$decode("2\xE5\"\"6\xE57\xE6"),
  2416. peg$decode("2\xE7\"\"6\xE77\xE8"),
  2417. peg$decode("2\xE9\"\"6\xE97\xEA"),
  2418. peg$decode("%;\x85.Y &;\x86.S &;\x88.M &;\x89.G &;\x8A.A &;\x8B.; &;\x8C.5 &;\x8F./ &;\x8D.) &;\x8E.# &;6/& 8!:\xEB! )"),
  2419. peg$decode("%;\x84/G#;'/>$;\x92/5$;'/,$;\x94/#$+%)(%'#($'#(#'#(\"'#&'#"),
  2420. peg$decode("%;\x93/' 8!:\xEC!! )"),
  2421. peg$decode("%;!/5#;!/,$;!/#$+#)(#'#(\"'#&'#"),
  2422. peg$decode("%$;*.A &;+.; &;-.5 &;3./ &;4.) &;'.# &;(0G*;*.A &;+.; &;-.5 &;3./ &;4.) &;'.# &;(&/& 8!:\xED! )"),
  2423. peg$decode("%;\xB6/Y#$%;A/,#;\xB6/#$+\")(\"'#&'#06*%;A/,#;\xB6/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2424. peg$decode("%;9/N#%2:\"\"6:7;/,#;9/#$+\")(\"'#&'#.\" &\"/'$8\":\xEE\" )(\"'#&'#"),
  2425. peg$decode("%;:.c &%;\x98/Y#$%;A/,#;\x98/#$+\")(\"'#&'#06*%;A/,#;\x98/#$+\")(\"'#&'#&/#$+\")(\"'#&'#/& 8!:\xEF! )"),
  2426. peg$decode("%;L.# &;\x99/]#$%;B/,#;\x9B/#$+\")(\"'#&'#06*%;B/,#;\x9B/#$+\")(\"'#&'#&/'$8\":\xF0\" )(\"'#&'#"),
  2427. peg$decode("%;\x9A.\" &\"/>#;@/5$;M/,$;?/#$+$)($'#(#'#(\"'#&'#"),
  2428. peg$decode("%%;6/Y#$%;./,#;6/#$+\")(\"'#&'#06*%;./,#;6/#$+\")(\"'#&'#&/#$+\")(\"'#&'#.# &;H/' 8!:\xF1!! )"),
  2429. peg$decode(";\x9C.) &;\x9D.# &;\xA0"),
  2430. peg$decode("%3\xF2\"\"5!7\xF3/:#;</1$;\x9F/($8#:\xF4#! )(#'#(\"'#&'#"),
  2431. peg$decode("%3\xF5\"\"5'7\xF6/:#;</1$;\x9E/($8#:\xF7#! )(#'#(\"'#&'#"),
  2432. peg$decode("%$;!/&#0#*;!&&&#/' 8!:\xF8!! )"),
  2433. peg$decode("%2\xF9\"\"6\xF97\xFA/o#%2J\"\"6J7K/M#;!.\" &\"/?$;!.\" &\"/1$;!.\" &\"/#$+$)($'#(#'#(\"'#&'#.\" &\"/'$8\":\xFB\" )(\"'#&'#"),
  2434. peg$decode("%;6/J#%;</,#;\xA1/#$+\")(\"'#&'#.\" &\"/)$8\":\xFC\"\"! )(\"'#&'#"),
  2435. peg$decode(";6.) &;T.# &;H"),
  2436. peg$decode("%;\xA3/Y#$%;B/,#;\xA4/#$+\")(\"'#&'#06*%;B/,#;\xA4/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2437. peg$decode("%3\xFD\"\"5&7\xFE.G &3\xFF\"\"5'7\u0100.; &3\u0101\"\"5$7\u0102./ &3\u0103\"\"5%7\u0104.# &;6/& 8!:\u0105! )"),
  2438. peg$decode(";\xA5.# &;\xA0"),
  2439. peg$decode("%3\u0106\"\"5(7\u0107/M#;</D$3\u0108\"\"5(7\u0109./ &3\u010A\"\"5(7\u010B.# &;6/#$+#)(#'#(\"'#&'#"),
  2440. peg$decode("%;6/Y#$%;A/,#;6/#$+\")(\"'#&'#06*%;A/,#;6/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2441. peg$decode("%$;!/&#0#*;!&&&#/' 8!:\u010C!! )"),
  2442. peg$decode("%;\xA9/& 8!:\u010D! )"),
  2443. peg$decode("%;\xAA/k#;;/b$;\xAF/Y$$%;B/,#;\xB0/#$+\")(\"'#&'#06*%;B/,#;\xB0/#$+\")(\"'#&'#&/#$+$)($'#(#'#(\"'#&'#"),
  2444. peg$decode(";\xAB.# &;\xAC"),
  2445. peg$decode("3\u010E\"\"5$7\u010F.S &3\u0110\"\"5%7\u0111.G &3\u0112\"\"5%7\u0113.; &3\u0114\"\"5%7\u0115./ &3\u0116\"\"5+7\u0117.# &;\xAD"),
  2446. peg$decode("3\u0118\"\"5'7\u0119./ &3\u011A\"\"5)7\u011B.# &;\xAD"),
  2447. peg$decode(";6.# &;\xAE"),
  2448. peg$decode("%3\u011C\"\"5\"7\u011D/,#;6/#$+\")(\"'#&'#"),
  2449. peg$decode(";\xAD.# &;6"),
  2450. peg$decode("%;6/5#;</,$;\xB1/#$+#)(#'#(\"'#&'#"),
  2451. peg$decode(";6.# &;H"),
  2452. peg$decode("%;\xB3/5#;./,$;\x90/#$+#)(#'#(\"'#&'#"),
  2453. peg$decode("%$;!/&#0#*;!&&&#/' 8!:\u011E!! )"),
  2454. peg$decode("%;\x9E/' 8!:\u011F!! )"),
  2455. peg$decode("%;\xB6/^#$%;B/,#;\xA0/#$+\")(\"'#&'#06*%;B/,#;\xA0/#$+\")(\"'#&'#&/($8\":\u0120\"!!)(\"'#&'#"),
  2456. peg$decode("%%;7/e#$%2J\"\"6J7K/,#;7/#$+\")(\"'#&'#0<*%2J\"\"6J7K/,#;7/#$+\")(\"'#&'#&/#$+\")(\"'#&'#/\"!&,)"),
  2457. peg$decode("%;L.# &;\x99/]#$%;B/,#;\xB8/#$+\")(\"'#&'#06*%;B/,#;\xB8/#$+\")(\"'#&'#&/'$8\":\u0121\" )(\"'#&'#"),
  2458. peg$decode(";\xB9.# &;\xA0"),
  2459. peg$decode("%3\u0122\"\"5#7\u0123/:#;</1$;6/($8#:\u0124#! )(#'#(\"'#&'#"),
  2460. peg$decode("%$;!/&#0#*;!&&&#/' 8!:\u0125!! )"),
  2461. peg$decode("%;\x9E/' 8!:\u0126!! )"),
  2462. peg$decode("%$;\x9A0#*;\x9A&/x#;@/o$;M/f$;?/]$$%;B/,#;\xA0/#$+\")(\"'#&'#06*%;B/,#;\xA0/#$+\")(\"'#&'#&/'$8%:\u0127% )(%'#($'#(#'#(\"'#&'#"),
  2463. peg$decode(";\xBE"),
  2464. peg$decode("%3\u0128\"\"5&7\u0129/k#;./b$;\xC1/Y$$%;A/,#;\xC1/#$+\")(\"'#&'#06*%;A/,#;\xC1/#$+\")(\"'#&'#&/#$+$)($'#(#'#(\"'#&'#.# &;\xBF"),
  2465. peg$decode("%;6/k#;./b$;\xC0/Y$$%;A/,#;\xC0/#$+\")(\"'#&'#06*%;A/,#;\xC0/#$+\")(\"'#&'#&/#$+$)($'#(#'#(\"'#&'#"),
  2466. peg$decode("%;6/;#;</2$;6.# &;H/#$+#)(#'#(\"'#&'#"),
  2467. peg$decode(";\xC2.G &;\xC4.A &;\xC6.; &;\xC8.5 &;\xC9./ &;\xCA.) &;\xCB.# &;\xC0"),
  2468. peg$decode("%3\u012A\"\"5%7\u012B/5#;</,$;\xC3/#$+#)(#'#(\"'#&'#"),
  2469. peg$decode("%;I/' 8!:\u012C!! )"),
  2470. peg$decode("%3\u012D\"\"5&7\u012E/\x97#;</\x8E$;D/\x85$;\xC5/|$$%$;'/&#0#*;'&&&#/,#;\xC5/#$+\")(\"'#&'#0C*%$;'/&#0#*;'&&&#/,#;\xC5/#$+\")(\"'#&'#&/,$;E/#$+&)(&'#(%'#($'#(#'#(\"'#&'#"),
  2471. peg$decode(";t.# &;w"),
  2472. peg$decode("%3\u012F\"\"5%7\u0130/5#;</,$;\xC7/#$+#)(#'#(\"'#&'#"),
  2473. peg$decode("%;I/' 8!:\u0131!! )"),
  2474. peg$decode("%3\u0132\"\"5&7\u0133/:#;</1$;I/($8#:\u0134#! )(#'#(\"'#&'#"),
  2475. peg$decode("%3\u0135\"\"5%7\u0136/]#;</T$%3\u0137\"\"5$7\u0138/& 8!:\u0139! ).4 &%3\u013A\"\"5%7\u013B/& 8!:\u013C! )/#$+#)(#'#(\"'#&'#"),
  2476. peg$decode("%3\u013D\"\"5)7\u013E/R#;</I$3\u013F\"\"5#7\u0140./ &3\u0141\"\"5(7\u0142.# &;6/($8#:\u0143#! )(#'#(\"'#&'#"),
  2477. peg$decode("%3\u0144\"\"5#7\u0145/\x93#;</\x8A$;D/\x81$%;\xCC/e#$%2D\"\"6D7E/,#;\xCC/#$+\")(\"'#&'#0<*%2D\"\"6D7E/,#;\xCC/#$+\")(\"'#&'#&/#$+\")(\"'#&'#/,$;E/#$+%)(%'#($'#(#'#(\"'#&'#"),
  2478. peg$decode("%3\u0146\"\"5(7\u0147./ &3\u0148\"\"5$7\u0149.# &;6/' 8!:\u014A!! )"),
  2479. peg$decode("%;6/Y#$%;A/,#;6/#$+\")(\"'#&'#06*%;A/,#;6/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2480. peg$decode("%;\xCF/G#;./>$;\xCF/5$;./,$;\x90/#$+%)(%'#($'#(#'#(\"'#&'#"),
  2481. peg$decode("%$;!/&#0#*;!&&&#/' 8!:\u014B!! )"),
  2482. peg$decode("%;\xD1/]#$%;A/,#;\xD1/#$+\")(\"'#&'#06*%;A/,#;\xD1/#$+\")(\"'#&'#&/'$8\":\u014C\" )(\"'#&'#"),
  2483. peg$decode("%;\x99/]#$%;B/,#;\xA0/#$+\")(\"'#&'#06*%;B/,#;\xA0/#$+\")(\"'#&'#&/'$8\":\u014D\" )(\"'#&'#"),
  2484. peg$decode("%;L.O &;\x99.I &%;@.\" &\"/:#;t/1$;?.\" &\"/#$+#)(#'#(\"'#&'#/]#$%;B/,#;\xA0/#$+\")(\"'#&'#06*%;B/,#;\xA0/#$+\")(\"'#&'#&/'$8\":\u014E\" )(\"'#&'#"),
  2485. peg$decode("%;\xD4/]#$%;B/,#;\xD5/#$+\")(\"'#&'#06*%;B/,#;\xD5/#$+\")(\"'#&'#&/'$8\":\u014F\" )(\"'#&'#"),
  2486. peg$decode("%;\x96/& 8!:\u0150! )"),
  2487. peg$decode("%3\u0151\"\"5(7\u0152/:#;</1$;6/($8#:\u0153#! )(#'#(\"'#&'#.g &%3\u0154\"\"5&7\u0155/:#;</1$;6/($8#:\u0156#! )(#'#(\"'#&'#.: &%3\u0157\"\"5*7\u0158/& 8!:\u0159! ).# &;\xA0"),
  2488. peg$decode("%%;6/k#$%;A/2#;6/)$8\":\u015A\"\"$ )(\"'#&'#0<*%;A/2#;6/)$8\":\u015A\"\"$ )(\"'#&'#&/)$8\":\u015B\"\"! )(\"'#&'#.\" &\"/' 8!:\u015C!! )"),
  2489. peg$decode("%;\xD8/Y#$%;A/,#;\xD8/#$+\")(\"'#&'#06*%;A/,#;\xD8/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2490. peg$decode("%;\x99/Y#$%;B/,#;\xA0/#$+\")(\"'#&'#06*%;B/,#;\xA0/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2491. peg$decode("%$;!/&#0#*;!&&&#/' 8!:\u015D!! )"),
  2492. peg$decode("%;\xDB/Y#$%;B/,#;\xDC/#$+\")(\"'#&'#06*%;B/,#;\xDC/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2493. peg$decode("%3\u015E\"\"5&7\u015F.; &3\u0160\"\"5'7\u0161./ &3\u0162\"\"5*7\u0163.# &;6/& 8!:\u0164! )"),
  2494. peg$decode("%3\u0165\"\"5&7\u0166/:#;</1$;\xDD/($8#:\u0167#! )(#'#(\"'#&'#.} &%3\xF5\"\"5'7\xF6/:#;</1$;\x9E/($8#:\u0168#! )(#'#(\"'#&'#.P &%3\u0169\"\"5+7\u016A/:#;</1$;\x9E/($8#:\u016B#! )(#'#(\"'#&'#.# &;\xA0"),
  2495. peg$decode("3\u016C\"\"5+7\u016D.k &3\u016E\"\"5)7\u016F._ &3\u0170\"\"5(7\u0171.S &3\u0172\"\"5'7\u0173.G &3\u0174\"\"5&7\u0175.; &3\u0176\"\"5*7\u0177./ &3\u0178\"\"5)7\u0179.# &;6"),
  2496. peg$decode(";1.\" &\""),
  2497. peg$decode("%%;6/k#$%;A/2#;6/)$8\":\u015A\"\"$ )(\"'#&'#0<*%;A/2#;6/)$8\":\u015A\"\"$ )(\"'#&'#&/)$8\":\u015B\"\"! )(\"'#&'#.\" &\"/' 8!:\u017A!! )"),
  2498. peg$decode("%;L.# &;\x99/]#$%;B/,#;\xE1/#$+\")(\"'#&'#06*%;B/,#;\xE1/#$+\")(\"'#&'#&/'$8\":\u017B\" )(\"'#&'#"),
  2499. peg$decode(";\xB9.# &;\xA0"),
  2500. peg$decode("%;\xE3/Y#$%;A/,#;\xE3/#$+\")(\"'#&'#06*%;A/,#;\xE3/#$+\")(\"'#&'#&/#$+\")(\"'#&'#"),
  2501. peg$decode("%;\xEA/k#;./b$;\xED/Y$$%;B/,#;\xE4/#$+\")(\"'#&'#06*%;B/,#;\xE4/#$+\")(\"'#&'#&/#$+$)($'#(#'#(\"'#&'#"),
  2502. peg$decode(";\xE5.; &;\xE6.5 &;\xE7./ &;\xE8.) &;\xE9.# &;\xA0"),
  2503. peg$decode("%3\u017C\"\"5#7\u017D/:#;</1$;\xF0/($8#:\u017E#! )(#'#(\"'#&'#"),
  2504. peg$decode("%3\u017F\"\"5%7\u0180/:#;</1$;T/($8#:\u0181#! )(#'#(\"'#&'#"),
  2505. peg$decode("%3\u0182\"\"5(7\u0183/F#;</=$;\\.) &;Y.# &;X/($8#:\u0184#! )(#'#(\"'#&'#"),
  2506. peg$decode("%3\u0185\"\"5&7\u0186/:#;</1$;6/($8#:\u0187#! )(#'#(\"'#&'#"),
  2507. peg$decode("%3\u0188\"\"5%7\u0189/A#;</8$$;!0#*;!&/($8#:\u018A#! )(#'#(\"'#&'#"),
  2508. peg$decode("%;\xEB/G#;;/>$;6/5$;;/,$;\xEC/#$+%)(%'#($'#(#'#(\"'#&'#"),
  2509. peg$decode("%3\x92\"\"5#7\xD3.# &;6/' 8!:\u018B!! )"),
  2510. peg$decode("%3\xB1\"\"5#7\u018C.G &3\xB3\"\"5#7\u018D.; &3\xB7\"\"5#7\u018E./ &3\xB5\"\"5$7\u018F.# &;6/' 8!:\u0190!! )"),
  2511. peg$decode("%;\xEE/D#%;C/,#;\xEF/#$+\")(\"'#&'#.\" &\"/#$+\")(\"'#&'#"),
  2512. peg$decode("%;U.) &;\\.# &;X/& 8!:\u0191! )"),
  2513. peg$decode("%%;!.\" &\"/[#;!.\" &\"/M$;!.\" &\"/?$;!.\" &\"/1$;!.\" &\"/#$+%)(%'#($'#(#'#(\"'#&'#/' 8!:\u0192!! )"),
  2514. peg$decode("%%;!/?#;!.\" &\"/1$;!.\" &\"/#$+#)(#'#(\"'#&'#/' 8!:\u0193!! )"),
  2515. peg$decode(";\xBE"),
  2516. peg$decode("%;\x9E/^#$%;B/,#;\xF3/#$+\")(\"'#&'#06*%;B/,#;\xF3/#$+\")(\"'#&'#&/($8\":\u0194\"!!)(\"'#&'#"),
  2517. peg$decode(";\xF4.# &;\xA0"),
  2518. peg$decode("%2\u0195\"\"6\u01957\u0196/L#;</C$2\u0197\"\"6\u01977\u0198.) &2\u0199\"\"6\u01997\u019A/($8#:\u019B#! )(#'#(\"'#&'#"),
  2519. peg$decode("%;\x9E/^#$%;B/,#;\xA0/#$+\")(\"'#&'#06*%;B/,#;\xA0/#$+\")(\"'#&'#&/($8\":\u019C\"!!)(\"'#&'#"),
  2520. peg$decode("%;6/5#;0/,$;\xF7/#$+#)(#'#(\"'#&'#"),
  2521. peg$decode("$;2.) &;4.# &;.0/*;2.) &;4.# &;.&"),
  2522. peg$decode("$;%0#*;%&"),
  2523. peg$decode("%;\xFA/;#28\"\"6879/,$;\xFB/#$+#)(#'#(\"'#&'#"),
  2524. peg$decode("%3\u019D\"\"5%7\u019E.) &3\u019F\"\"5$7\u01A0/' 8!:\u01A1!! )"),
  2525. peg$decode("%;\xFC/J#%28\"\"6879/,#;^/#$+\")(\"'#&'#.\" &\"/#$+\")(\"'#&'#"),
  2526. peg$decode("%;\\.) &;X.# &;\x82/' 8!:\u01A2!! )"),
  2527. peg$decode(";\".S &;!.M &2F\"\"6F7G.A &2J\"\"6J7K.5 &2H\"\"6H7I.) &2N\"\"6N7O"),
  2528. peg$decode("2L\"\"6L7M.\x95 &2B\"\"6B7C.\x89 &2<\"\"6<7=.} &2R\"\"6R7S.q &2T\"\"6T7U.e &2V\"\"6V7W.Y &2P\"\"6P7Q.M &2@\"\"6@7A.A &2D\"\"6D7E.5 &22\"\"6273.) &2>\"\"6>7?"),
  2529. peg$decode("%;\u0100/b#28\"\"6879/S$;\xFB/J$%2\u01A3\"\"6\u01A37\u01A4/,#;\xEC/#$+\")(\"'#&'#.\" &\"/#$+$)($'#(#'#(\"'#&'#"),
  2530. peg$decode("%3\u01A5\"\"5%7\u01A6.) &3\u01A7\"\"5$7\u01A8/' 8!:\u01A1!! )"),
  2531. peg$decode("%3\xB1\"\"5#7\xB2.6 &3\xB3\"\"5#7\xB4.* &$;+0#*;+&/' 8!:\u01A9!! )"),
  2532. peg$decode("%;\u0104/\x87#2F\"\"6F7G/x$;\u0103/o$2F\"\"6F7G/`$;\u0103/W$2F\"\"6F7G/H$;\u0103/?$2F\"\"6F7G/0$;\u0105/'$8):\u01AA) )()'#(('#(''#(&'#(%'#($'#(#'#(\"'#&'#"),
  2533. peg$decode("%;#/>#;#/5$;#/,$;#/#$+$)($'#(#'#(\"'#&'#"),
  2534. peg$decode("%;\u0103/,#;\u0103/#$+\")(\"'#&'#"),
  2535. peg$decode("%;\u0103/5#;\u0103/,$;\u0103/#$+#)(#'#(\"'#&'#"),
  2536. peg$decode("%;q/T#$;m0#*;m&/D$%; /,#;\xF8/#$+\")(\"'#&'#.\" &\"/#$+#)(#'#(\"'#&'#"),
  2537. peg$decode("%2\u01AB\"\"6\u01AB7\u01AC.) &2\u01AD\"\"6\u01AD7\u01AE/w#;0/n$;\u0108/e$$%;B/2#;\u0109.# &;\xA0/#$+\")(\"'#&'#0<*%;B/2#;\u0109.# &;\xA0/#$+\")(\"'#&'#&/#$+$)($'#(#'#(\"'#&'#"),
  2538. peg$decode(";\x99.# &;L"),
  2539. peg$decode("%2\u01AF\"\"6\u01AF7\u01B0/5#;</,$;\u010A/#$+#)(#'#(\"'#&'#"),
  2540. peg$decode("%;D/S#;,/J$2:\"\"6:7;/;$;,.# &;T/,$;E/#$+%)(%'#($'#(#'#(\"'#&'#")
  2541. ];
  2542. var peg$currPos = 0;
  2543. var peg$savedPos = 0;
  2544. var peg$posDetailsCache = [{ line: 1, column: 1 }];
  2545. var peg$maxFailPos = 0;
  2546. var peg$maxFailExpected = [];
  2547. var peg$silentFails = 0;
  2548. var peg$result;
  2549. if (options.startRule !== undefined) {
  2550. if (!(options.startRule in peg$startRuleIndices)) {
  2551. throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
  2552. }
  2553. peg$startRuleIndex = peg$startRuleIndices[options.startRule];
  2554. }
  2555. function text() {
  2556. return input.substring(peg$savedPos, peg$currPos);
  2557. }
  2558. function location() {
  2559. return peg$computeLocation(peg$savedPos, peg$currPos);
  2560. }
  2561. function expected(description, location1) {
  2562. location1 = location1 !== undefined
  2563. ? location1
  2564. : peg$computeLocation(peg$savedPos, peg$currPos);
  2565. throw peg$buildStructuredError([peg$otherExpectation(description)], input.substring(peg$savedPos, peg$currPos), location1);
  2566. }
  2567. function error(message, location1) {
  2568. location1 = location1 !== undefined
  2569. ? location1
  2570. : peg$computeLocation(peg$savedPos, peg$currPos);
  2571. throw peg$buildSimpleError(message, location1);
  2572. }
  2573. function peg$literalExpectation(text1, ignoreCase) {
  2574. return { type: "literal", text: text1, ignoreCase: ignoreCase };
  2575. }
  2576. function peg$classExpectation(parts, inverted, ignoreCase) {
  2577. return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
  2578. }
  2579. function peg$anyExpectation() {
  2580. return { type: "any" };
  2581. }
  2582. function peg$endExpectation() {
  2583. return { type: "end" };
  2584. }
  2585. function peg$otherExpectation(description) {
  2586. return { type: "other", description: description };
  2587. }
  2588. function peg$computePosDetails(pos) {
  2589. var details = peg$posDetailsCache[pos];
  2590. var p;
  2591. if (details) {
  2592. return details;
  2593. }
  2594. else {
  2595. p = pos - 1;
  2596. while (!peg$posDetailsCache[p]) {
  2597. p--;
  2598. }
  2599. details = peg$posDetailsCache[p];
  2600. details = {
  2601. line: details.line,
  2602. column: details.column
  2603. };
  2604. while (p < pos) {
  2605. if (input.charCodeAt(p) === 10) {
  2606. details.line++;
  2607. details.column = 1;
  2608. }
  2609. else {
  2610. details.column++;
  2611. }
  2612. p++;
  2613. }
  2614. peg$posDetailsCache[pos] = details;
  2615. return details;
  2616. }
  2617. }
  2618. function peg$computeLocation(startPos, endPos) {
  2619. var startPosDetails = peg$computePosDetails(startPos);
  2620. var endPosDetails = peg$computePosDetails(endPos);
  2621. return {
  2622. start: {
  2623. offset: startPos,
  2624. line: startPosDetails.line,
  2625. column: startPosDetails.column
  2626. },
  2627. end: {
  2628. offset: endPos,
  2629. line: endPosDetails.line,
  2630. column: endPosDetails.column
  2631. }
  2632. };
  2633. }
  2634. function peg$fail(expected1) {
  2635. if (peg$currPos < peg$maxFailPos) {
  2636. return;
  2637. }
  2638. if (peg$currPos > peg$maxFailPos) {
  2639. peg$maxFailPos = peg$currPos;
  2640. peg$maxFailExpected = [];
  2641. }
  2642. peg$maxFailExpected.push(expected1);
  2643. }
  2644. function peg$buildSimpleError(message, location1) {
  2645. return new SyntaxError(message, [], "", location1);
  2646. }
  2647. function peg$buildStructuredError(expected1, found, location1) {
  2648. return new SyntaxError(SyntaxError.buildMessage(expected1, found), expected1, found, location1);
  2649. }
  2650. function peg$decode(s) {
  2651. return s.split("").map(function (ch) { return ch.charCodeAt(0) - 32; });
  2652. }
  2653. function peg$parseRule(index) {
  2654. var bc = peg$bytecode[index];
  2655. var ip = 0;
  2656. var ips = [];
  2657. var end = bc.length;
  2658. var ends = [];
  2659. var stack = [];
  2660. var params;
  2661. while (true) {
  2662. while (ip < end) {
  2663. switch (bc[ip]) {
  2664. case 0:
  2665. stack.push(peg$consts[bc[ip + 1]]);
  2666. ip += 2;
  2667. break;
  2668. case 1:
  2669. stack.push(undefined);
  2670. ip++;
  2671. break;
  2672. case 2:
  2673. stack.push(null);
  2674. ip++;
  2675. break;
  2676. case 3:
  2677. stack.push(peg$FAILED);
  2678. ip++;
  2679. break;
  2680. case 4:
  2681. stack.push([]);
  2682. ip++;
  2683. break;
  2684. case 5:
  2685. stack.push(peg$currPos);
  2686. ip++;
  2687. break;
  2688. case 6:
  2689. stack.pop();
  2690. ip++;
  2691. break;
  2692. case 7:
  2693. peg$currPos = stack.pop();
  2694. ip++;
  2695. break;
  2696. case 8:
  2697. stack.length -= bc[ip + 1];
  2698. ip += 2;
  2699. break;
  2700. case 9:
  2701. stack.splice(-2, 1);
  2702. ip++;
  2703. break;
  2704. case 10:
  2705. stack[stack.length - 2].push(stack.pop());
  2706. ip++;
  2707. break;
  2708. case 11:
  2709. stack.push(stack.splice(stack.length - bc[ip + 1], bc[ip + 1]));
  2710. ip += 2;
  2711. break;
  2712. case 12:
  2713. stack.push(input.substring(stack.pop(), peg$currPos));
  2714. ip++;
  2715. break;
  2716. case 13:
  2717. ends.push(end);
  2718. ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);
  2719. if (stack[stack.length - 1]) {
  2720. end = ip + 3 + bc[ip + 1];
  2721. ip += 3;
  2722. }
  2723. else {
  2724. end = ip + 3 + bc[ip + 1] + bc[ip + 2];
  2725. ip += 3 + bc[ip + 1];
  2726. }
  2727. break;
  2728. case 14:
  2729. ends.push(end);
  2730. ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);
  2731. if (stack[stack.length - 1] === peg$FAILED) {
  2732. end = ip + 3 + bc[ip + 1];
  2733. ip += 3;
  2734. }
  2735. else {
  2736. end = ip + 3 + bc[ip + 1] + bc[ip + 2];
  2737. ip += 3 + bc[ip + 1];
  2738. }
  2739. break;
  2740. case 15:
  2741. ends.push(end);
  2742. ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);
  2743. if (stack[stack.length - 1] !== peg$FAILED) {
  2744. end = ip + 3 + bc[ip + 1];
  2745. ip += 3;
  2746. }
  2747. else {
  2748. end = ip + 3 + bc[ip + 1] + bc[ip + 2];
  2749. ip += 3 + bc[ip + 1];
  2750. }
  2751. break;
  2752. case 16:
  2753. if (stack[stack.length - 1] !== peg$FAILED) {
  2754. ends.push(end);
  2755. ips.push(ip);
  2756. end = ip + 2 + bc[ip + 1];
  2757. ip += 2;
  2758. }
  2759. else {
  2760. ip += 2 + bc[ip + 1];
  2761. }
  2762. break;
  2763. case 17:
  2764. ends.push(end);
  2765. ips.push(ip + 3 + bc[ip + 1] + bc[ip + 2]);
  2766. if (input.length > peg$currPos) {
  2767. end = ip + 3 + bc[ip + 1];
  2768. ip += 3;
  2769. }
  2770. else {
  2771. end = ip + 3 + bc[ip + 1] + bc[ip + 2];
  2772. ip += 3 + bc[ip + 1];
  2773. }
  2774. break;
  2775. case 18:
  2776. ends.push(end);
  2777. ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]);
  2778. if (input.substr(peg$currPos, peg$consts[bc[ip + 1]].length) === peg$consts[bc[ip + 1]]) {
  2779. end = ip + 4 + bc[ip + 2];
  2780. ip += 4;
  2781. }
  2782. else {
  2783. end = ip + 4 + bc[ip + 2] + bc[ip + 3];
  2784. ip += 4 + bc[ip + 2];
  2785. }
  2786. break;
  2787. case 19:
  2788. ends.push(end);
  2789. ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]);
  2790. if (input.substr(peg$currPos, peg$consts[bc[ip + 1]].length).toLowerCase() === peg$consts[bc[ip + 1]]) {
  2791. end = ip + 4 + bc[ip + 2];
  2792. ip += 4;
  2793. }
  2794. else {
  2795. end = ip + 4 + bc[ip + 2] + bc[ip + 3];
  2796. ip += 4 + bc[ip + 2];
  2797. }
  2798. break;
  2799. case 20:
  2800. ends.push(end);
  2801. ips.push(ip + 4 + bc[ip + 2] + bc[ip + 3]);
  2802. if (peg$consts[bc[ip + 1]].test(input.charAt(peg$currPos))) {
  2803. end = ip + 4 + bc[ip + 2];
  2804. ip += 4;
  2805. }
  2806. else {
  2807. end = ip + 4 + bc[ip + 2] + bc[ip + 3];
  2808. ip += 4 + bc[ip + 2];
  2809. }
  2810. break;
  2811. case 21:
  2812. stack.push(input.substr(peg$currPos, bc[ip + 1]));
  2813. peg$currPos += bc[ip + 1];
  2814. ip += 2;
  2815. break;
  2816. case 22:
  2817. stack.push(peg$consts[bc[ip + 1]]);
  2818. peg$currPos += peg$consts[bc[ip + 1]].length;
  2819. ip += 2;
  2820. break;
  2821. case 23:
  2822. stack.push(peg$FAILED);
  2823. if (peg$silentFails === 0) {
  2824. peg$fail(peg$consts[bc[ip + 1]]);
  2825. }
  2826. ip += 2;
  2827. break;
  2828. case 24:
  2829. peg$savedPos = stack[stack.length - 1 - bc[ip + 1]];
  2830. ip += 2;
  2831. break;
  2832. case 25:
  2833. peg$savedPos = peg$currPos;
  2834. ip++;
  2835. break;
  2836. case 26:
  2837. params = bc.slice(ip + 4, ip + 4 + bc[ip + 3])
  2838. .map(function (p) { return stack[stack.length - 1 - p]; });
  2839. stack.splice(stack.length - bc[ip + 2], bc[ip + 2], peg$consts[bc[ip + 1]].apply(null, params));
  2840. ip += 4 + bc[ip + 3];
  2841. break;
  2842. case 27:
  2843. stack.push(peg$parseRule(bc[ip + 1]));
  2844. ip += 2;
  2845. break;
  2846. case 28:
  2847. peg$silentFails++;
  2848. ip++;
  2849. break;
  2850. case 29:
  2851. peg$silentFails--;
  2852. ip++;
  2853. break;
  2854. default:
  2855. throw new Error("Invalid opcode: " + bc[ip] + ".");
  2856. }
  2857. }
  2858. if (ends.length > 0) {
  2859. end = ends.pop();
  2860. ip = ips.pop();
  2861. }
  2862. else {
  2863. break;
  2864. }
  2865. }
  2866. return stack[0];
  2867. }
  2868. options.data = {}; // Object to which header attributes will be assigned during parsing
  2869. function list(head, tail) {
  2870. return [head].concat(tail);
  2871. }
  2872. peg$result = peg$parseRule(peg$startRuleIndex);
  2873. if (peg$result !== peg$FAILED && peg$currPos === input.length) {
  2874. return peg$result;
  2875. }
  2876. else {
  2877. if (peg$result !== peg$FAILED && peg$currPos < input.length) {
  2878. peg$fail(peg$endExpectation());
  2879. }
  2880. throw peg$buildStructuredError(peg$maxFailExpected, peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, peg$maxFailPos < input.length
  2881. ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
  2882. : peg$computeLocation(peg$maxFailPos, peg$maxFailPos));
  2883. }
  2884. }
  2885. exports.parse = peg$parse;
  2886. /***/ }),
  2887. /* 13 */
  2888. /***/ (function(module, exports, __webpack_require__) {
  2889. "use strict";
  2890. Object.defineProperty(exports, "__esModule", { value: true });
  2891. var tslib_1 = __webpack_require__(1);
  2892. var parameters_1 = __webpack_require__(14);
  2893. /**
  2894. * Name Address SIP header.
  2895. * @public
  2896. */
  2897. var NameAddrHeader = /** @class */ (function (_super) {
  2898. tslib_1.__extends(NameAddrHeader, _super);
  2899. /**
  2900. * Constructor
  2901. * @param uri -
  2902. * @param displayName -
  2903. * @param parameters -
  2904. */
  2905. function NameAddrHeader(uri, displayName, parameters) {
  2906. var _this = _super.call(this, parameters) || this;
  2907. _this.uri = uri;
  2908. _this._displayName = displayName;
  2909. return _this;
  2910. }
  2911. Object.defineProperty(NameAddrHeader.prototype, "friendlyName", {
  2912. get: function () {
  2913. return this.displayName || this.uri.aor;
  2914. },
  2915. enumerable: true,
  2916. configurable: true
  2917. });
  2918. Object.defineProperty(NameAddrHeader.prototype, "displayName", {
  2919. get: function () { return this._displayName; },
  2920. set: function (value) {
  2921. this._displayName = value;
  2922. },
  2923. enumerable: true,
  2924. configurable: true
  2925. });
  2926. NameAddrHeader.prototype.clone = function () {
  2927. return new NameAddrHeader(this.uri.clone(), this._displayName, JSON.parse(JSON.stringify(this.parameters)));
  2928. };
  2929. NameAddrHeader.prototype.toString = function () {
  2930. var body = (this.displayName || this.displayName === "0") ? '"' + this.displayName + '" ' : "";
  2931. body += "<" + this.uri.toString() + ">";
  2932. for (var parameter in this.parameters) {
  2933. if (this.parameters.hasOwnProperty(parameter)) {
  2934. body += ";" + parameter;
  2935. if (this.parameters[parameter] !== null) {
  2936. body += "=" + this.parameters[parameter];
  2937. }
  2938. }
  2939. }
  2940. return body;
  2941. };
  2942. return NameAddrHeader;
  2943. }(parameters_1.Parameters));
  2944. exports.NameAddrHeader = NameAddrHeader;
  2945. /***/ }),
  2946. /* 14 */
  2947. /***/ (function(module, exports, __webpack_require__) {
  2948. "use strict";
  2949. Object.defineProperty(exports, "__esModule", { value: true });
  2950. /**
  2951. * @internal
  2952. */
  2953. var Parameters = /** @class */ (function () {
  2954. function Parameters(parameters) {
  2955. this.parameters = {};
  2956. for (var param in parameters) {
  2957. if (parameters.hasOwnProperty(param)) {
  2958. this.setParam(param, parameters[param]);
  2959. }
  2960. }
  2961. }
  2962. Parameters.prototype.setParam = function (key, value) {
  2963. if (key) {
  2964. this.parameters[key.toLowerCase()] = (typeof value === "undefined" || value === null) ? null : value.toString();
  2965. }
  2966. };
  2967. Parameters.prototype.getParam = function (key) {
  2968. if (key) {
  2969. return this.parameters[key.toLowerCase()];
  2970. }
  2971. };
  2972. Parameters.prototype.hasParam = function (key) {
  2973. if (key) {
  2974. return !!this.parameters.hasOwnProperty(key.toLowerCase());
  2975. }
  2976. return false;
  2977. };
  2978. Parameters.prototype.deleteParam = function (parameter) {
  2979. parameter = parameter.toLowerCase();
  2980. if (this.parameters.hasOwnProperty(parameter)) {
  2981. var value = this.parameters[parameter];
  2982. delete this.parameters[parameter];
  2983. return value;
  2984. }
  2985. };
  2986. Parameters.prototype.clearParams = function () {
  2987. this.parameters = {};
  2988. };
  2989. return Parameters;
  2990. }());
  2991. exports.Parameters = Parameters;
  2992. /***/ }),
  2993. /* 15 */
  2994. /***/ (function(module, exports, __webpack_require__) {
  2995. "use strict";
  2996. Object.defineProperty(exports, "__esModule", { value: true });
  2997. var tslib_1 = __webpack_require__(1);
  2998. var parameters_1 = __webpack_require__(14);
  2999. /**
  3000. * URI.
  3001. * @public
  3002. */
  3003. var URI = /** @class */ (function (_super) {
  3004. tslib_1.__extends(URI, _super);
  3005. /**
  3006. * Constructor
  3007. * @param scheme -
  3008. * @param user -
  3009. * @param host -
  3010. * @param port -
  3011. * @param parameters -
  3012. * @param headers -
  3013. */
  3014. function URI(scheme, user, host, port, parameters, headers) {
  3015. var _this = _super.call(this, parameters) || this;
  3016. _this.headers = {};
  3017. // Checks
  3018. if (!host) {
  3019. throw new TypeError('missing or invalid "host" parameter');
  3020. }
  3021. // Initialize parameters
  3022. scheme = scheme || "sip";
  3023. for (var header in headers) {
  3024. if (headers.hasOwnProperty(header)) {
  3025. _this.setHeader(header, headers[header]);
  3026. }
  3027. }
  3028. // Raw URI
  3029. _this.raw = {
  3030. scheme: scheme,
  3031. user: user,
  3032. host: host,
  3033. port: port
  3034. };
  3035. // Normalized URI
  3036. _this.normal = {
  3037. scheme: scheme.toLowerCase(),
  3038. user: user,
  3039. host: host.toLowerCase(),
  3040. port: port
  3041. };
  3042. return _this;
  3043. }
  3044. Object.defineProperty(URI.prototype, "scheme", {
  3045. get: function () { return this.normal.scheme; },
  3046. set: function (value) {
  3047. this.raw.scheme = value;
  3048. this.normal.scheme = value.toLowerCase();
  3049. },
  3050. enumerable: true,
  3051. configurable: true
  3052. });
  3053. Object.defineProperty(URI.prototype, "user", {
  3054. get: function () { return this.normal.user; },
  3055. set: function (value) {
  3056. this.normal.user = this.raw.user = value;
  3057. },
  3058. enumerable: true,
  3059. configurable: true
  3060. });
  3061. Object.defineProperty(URI.prototype, "host", {
  3062. get: function () { return this.normal.host; },
  3063. set: function (value) {
  3064. this.raw.host = value;
  3065. this.normal.host = value.toLowerCase();
  3066. },
  3067. enumerable: true,
  3068. configurable: true
  3069. });
  3070. Object.defineProperty(URI.prototype, "aor", {
  3071. get: function () { return this.normal.user + "@" + this.normal.host; },
  3072. enumerable: true,
  3073. configurable: true
  3074. });
  3075. Object.defineProperty(URI.prototype, "port", {
  3076. get: function () { return this.normal.port; },
  3077. set: function (value) {
  3078. this.normal.port = this.raw.port = value === 0 ? value : value;
  3079. },
  3080. enumerable: true,
  3081. configurable: true
  3082. });
  3083. URI.prototype.setHeader = function (name, value) {
  3084. this.headers[this.headerize(name)] = (value instanceof Array) ? value : [value];
  3085. };
  3086. URI.prototype.getHeader = function (name) {
  3087. if (name) {
  3088. return this.headers[this.headerize(name)];
  3089. }
  3090. };
  3091. URI.prototype.hasHeader = function (name) {
  3092. return !!name && !!this.headers.hasOwnProperty(this.headerize(name));
  3093. };
  3094. URI.prototype.deleteHeader = function (header) {
  3095. header = this.headerize(header);
  3096. if (this.headers.hasOwnProperty(header)) {
  3097. var value = this.headers[header];
  3098. delete this.headers[header];
  3099. return value;
  3100. }
  3101. };
  3102. URI.prototype.clearHeaders = function () {
  3103. this.headers = {};
  3104. };
  3105. URI.prototype.clone = function () {
  3106. return new URI(this._raw.scheme, this._raw.user || "", this._raw.host, this._raw.port, JSON.parse(JSON.stringify(this.parameters)), JSON.parse(JSON.stringify(this.headers)));
  3107. };
  3108. URI.prototype.toRaw = function () {
  3109. return this._toString(this._raw);
  3110. };
  3111. URI.prototype.toString = function () {
  3112. return this._toString(this._normal);
  3113. };
  3114. Object.defineProperty(URI.prototype, "_normal", {
  3115. get: function () { return this.normal; },
  3116. enumerable: true,
  3117. configurable: true
  3118. });
  3119. Object.defineProperty(URI.prototype, "_raw", {
  3120. get: function () { return this.raw; },
  3121. enumerable: true,
  3122. configurable: true
  3123. });
  3124. URI.prototype._toString = function (uri) {
  3125. var uriString = uri.scheme + ":";
  3126. // add slashes if it's not a sip(s) URI
  3127. if (!uri.scheme.toLowerCase().match("^sips?$")) {
  3128. uriString += "//";
  3129. }
  3130. if (uri.user) {
  3131. uriString += this.escapeUser(uri.user) + "@";
  3132. }
  3133. uriString += uri.host;
  3134. if (uri.port || uri.port === 0) {
  3135. uriString += ":" + uri.port;
  3136. }
  3137. for (var parameter in this.parameters) {
  3138. if (this.parameters.hasOwnProperty(parameter)) {
  3139. uriString += ";" + parameter;
  3140. if (this.parameters[parameter] !== null) {
  3141. uriString += "=" + this.parameters[parameter];
  3142. }
  3143. }
  3144. }
  3145. var headers = [];
  3146. for (var header in this.headers) {
  3147. if (this.headers.hasOwnProperty(header)) {
  3148. for (var idx in this.headers[header]) {
  3149. if (this.headers[header].hasOwnProperty(idx)) {
  3150. headers.push(header + "=" + this.headers[header][idx]);
  3151. }
  3152. }
  3153. }
  3154. }
  3155. if (headers.length > 0) {
  3156. uriString += "?" + headers.join("&");
  3157. }
  3158. return uriString;
  3159. };
  3160. /*
  3161. * Hex-escape a SIP URI user.
  3162. * @private
  3163. * @param {String} user
  3164. */
  3165. URI.prototype.escapeUser = function (user) {
  3166. var decodedUser;
  3167. // FIXME: This is called by toString above which should never throw, but
  3168. // decodeURIComponent can throw and I've seen one case in production where
  3169. // it did throw resulting in a cascading failure. This class should be
  3170. // fixed so that decodeURIComponent is not called at this point (in toString).
  3171. // The user should be decoded when the URI is constructor or some other
  3172. // place where we can catch the error before the URI is created or somesuch.
  3173. try {
  3174. decodedUser = decodeURIComponent(user);
  3175. }
  3176. catch (error) {
  3177. throw error;
  3178. }
  3179. // Don't hex-escape ':' (%3A), '+' (%2B), '?' (%3F"), '/' (%2F).
  3180. return encodeURIComponent(decodedUser)
  3181. .replace(/%3A/ig, ":")
  3182. .replace(/%2B/ig, "+")
  3183. .replace(/%3F/ig, "?")
  3184. .replace(/%2F/ig, "/");
  3185. };
  3186. URI.prototype.headerize = function (str) {
  3187. var exceptions = {
  3188. "Call-Id": "Call-ID",
  3189. "Cseq": "CSeq",
  3190. "Min-Se": "Min-SE",
  3191. "Rack": "RAck",
  3192. "Rseq": "RSeq",
  3193. "Www-Authenticate": "WWW-Authenticate",
  3194. };
  3195. var name = str.toLowerCase().replace(/_/g, "-").split("-");
  3196. var parts = name.length;
  3197. var hname = "";
  3198. for (var part = 0; part < parts; part++) {
  3199. if (part !== 0) {
  3200. hname += "-";
  3201. }
  3202. hname += name[part].charAt(0).toUpperCase() + name[part].substring(1);
  3203. }
  3204. if (exceptions[hname]) {
  3205. hname = exceptions[hname];
  3206. }
  3207. return hname;
  3208. };
  3209. return URI;
  3210. }(parameters_1.Parameters));
  3211. exports.URI = URI;
  3212. /***/ }),
  3213. /* 16 */
  3214. /***/ (function(module, exports, __webpack_require__) {
  3215. "use strict";
  3216. Object.defineProperty(exports, "__esModule", { value: true });
  3217. /**
  3218. * @param size -
  3219. * @param base -
  3220. * @internal
  3221. */
  3222. function createRandomToken(size, base) {
  3223. if (base === void 0) { base = 32; }
  3224. var token = "";
  3225. for (var i = 0; i < size; i++) {
  3226. var r = Math.floor(Math.random() * base);
  3227. token += r.toString(base);
  3228. }
  3229. return token;
  3230. }
  3231. exports.createRandomToken = createRandomToken;
  3232. /**
  3233. * @internal
  3234. */
  3235. function getReasonPhrase(code) {
  3236. return REASON_PHRASE[code] || "";
  3237. }
  3238. exports.getReasonPhrase = getReasonPhrase;
  3239. /**
  3240. * @internal
  3241. */
  3242. function newTag() {
  3243. return createRandomToken(10);
  3244. }
  3245. exports.newTag = newTag;
  3246. /**
  3247. * @param str -
  3248. * @internal
  3249. */
  3250. function headerize(str) {
  3251. var exceptions = {
  3252. "Call-Id": "Call-ID",
  3253. "Cseq": "CSeq",
  3254. "Min-Se": "Min-SE",
  3255. "Rack": "RAck",
  3256. "Rseq": "RSeq",
  3257. "Www-Authenticate": "WWW-Authenticate",
  3258. };
  3259. var name = str.toLowerCase().replace(/_/g, "-").split("-");
  3260. var parts = name.length;
  3261. var hname = "";
  3262. for (var part = 0; part < parts; part++) {
  3263. if (part !== 0) {
  3264. hname += "-";
  3265. }
  3266. hname += name[part].charAt(0).toUpperCase() + name[part].substring(1);
  3267. }
  3268. if (exceptions[hname]) {
  3269. hname = exceptions[hname];
  3270. }
  3271. return hname;
  3272. }
  3273. exports.headerize = headerize;
  3274. /**
  3275. * @param str -
  3276. * @internal
  3277. */
  3278. function str_utf8_length(str) {
  3279. return encodeURIComponent(str).replace(/%[A-F\d]{2}/g, "U").length;
  3280. }
  3281. exports.str_utf8_length = str_utf8_length;
  3282. /**
  3283. * SIP Response Reasons
  3284. * DOC: http://www.iana.org/assignments/sip-parameters
  3285. * @internal
  3286. */
  3287. var REASON_PHRASE = {
  3288. 100: "Trying",
  3289. 180: "Ringing",
  3290. 181: "Call Is Being Forwarded",
  3291. 182: "Queued",
  3292. 183: "Session Progress",
  3293. 199: "Early Dialog Terminated",
  3294. 200: "OK",
  3295. 202: "Accepted",
  3296. 204: "No Notification",
  3297. 300: "Multiple Choices",
  3298. 301: "Moved Permanently",
  3299. 302: "Moved Temporarily",
  3300. 305: "Use Proxy",
  3301. 380: "Alternative Service",
  3302. 400: "Bad Request",
  3303. 401: "Unauthorized",
  3304. 402: "Payment Required",
  3305. 403: "Forbidden",
  3306. 404: "Not Found",
  3307. 405: "Method Not Allowed",
  3308. 406: "Not Acceptable",
  3309. 407: "Proxy Authentication Required",
  3310. 408: "Request Timeout",
  3311. 410: "Gone",
  3312. 412: "Conditional Request Failed",
  3313. 413: "Request Entity Too Large",
  3314. 414: "Request-URI Too Long",
  3315. 415: "Unsupported Media Type",
  3316. 416: "Unsupported URI Scheme",
  3317. 417: "Unknown Resource-Priority",
  3318. 420: "Bad Extension",
  3319. 421: "Extension Required",
  3320. 422: "Session Interval Too Small",
  3321. 423: "Interval Too Brief",
  3322. 428: "Use Identity Header",
  3323. 429: "Provide Referrer Identity",
  3324. 430: "Flow Failed",
  3325. 433: "Anonymity Disallowed",
  3326. 436: "Bad Identity-Info",
  3327. 437: "Unsupported Certificate",
  3328. 438: "Invalid Identity Header",
  3329. 439: "First Hop Lacks Outbound Support",
  3330. 440: "Max-Breadth Exceeded",
  3331. 469: "Bad Info Package",
  3332. 470: "Consent Needed",
  3333. 478: "Unresolvable Destination",
  3334. 480: "Temporarily Unavailable",
  3335. 481: "Call/Transaction Does Not Exist",
  3336. 482: "Loop Detected",
  3337. 483: "Too Many Hops",
  3338. 484: "Address Incomplete",
  3339. 485: "Ambiguous",
  3340. 486: "Busy Here",
  3341. 487: "Request Terminated",
  3342. 488: "Not Acceptable Here",
  3343. 489: "Bad Event",
  3344. 491: "Request Pending",
  3345. 493: "Undecipherable",
  3346. 494: "Security Agreement Required",
  3347. 500: "Internal Server Error",
  3348. 501: "Not Implemented",
  3349. 502: "Bad Gateway",
  3350. 503: "Service Unavailable",
  3351. 504: "Server Time-out",
  3352. 505: "Version Not Supported",
  3353. 513: "Message Too Large",
  3354. 580: "Precondition Failure",
  3355. 600: "Busy Everywhere",
  3356. 603: "Decline",
  3357. 604: "Does Not Exist Anywhere",
  3358. 606: "Not Acceptable"
  3359. };
  3360. /***/ }),
  3361. /* 17 */
  3362. /***/ (function(module, exports, __webpack_require__) {
  3363. "use strict";
  3364. Object.defineProperty(exports, "__esModule", { value: true });
  3365. var tslib_1 = __webpack_require__(1);
  3366. var incoming_message_1 = __webpack_require__(10);
  3367. /**
  3368. * Incoming response message.
  3369. * @public
  3370. */
  3371. var IncomingResponseMessage = /** @class */ (function (_super) {
  3372. tslib_1.__extends(IncomingResponseMessage, _super);
  3373. function IncomingResponseMessage() {
  3374. return _super.call(this) || this;
  3375. }
  3376. return IncomingResponseMessage;
  3377. }(incoming_message_1.IncomingMessage));
  3378. exports.IncomingResponseMessage = IncomingResponseMessage;
  3379. /***/ }),
  3380. /* 18 */
  3381. /***/ (function(module, exports, __webpack_require__) {
  3382. "use strict";
  3383. Object.defineProperty(exports, "__esModule", { value: true });
  3384. var tslib_1 = __webpack_require__(1);
  3385. var name_addr_header_1 = __webpack_require__(13);
  3386. var utils_1 = __webpack_require__(16);
  3387. /**
  3388. * Outgoing SIP request message.
  3389. * @public
  3390. */
  3391. var OutgoingRequestMessage = /** @class */ (function () {
  3392. function OutgoingRequestMessage(method, ruri, fromURI, toURI, options, extraHeaders, body) {
  3393. this.headers = {};
  3394. this.extraHeaders = [];
  3395. this.options = OutgoingRequestMessage.getDefaultOptions();
  3396. // Options - merge a deep copy
  3397. if (options) {
  3398. this.options = tslib_1.__assign(tslib_1.__assign({}, this.options), options);
  3399. if (this.options.optionTags && this.options.optionTags.length) {
  3400. this.options.optionTags = this.options.optionTags.slice();
  3401. }
  3402. if (this.options.routeSet && this.options.routeSet.length) {
  3403. this.options.routeSet = this.options.routeSet.slice();
  3404. }
  3405. }
  3406. // Extra headers - deep copy
  3407. if (extraHeaders && extraHeaders.length) {
  3408. this.extraHeaders = extraHeaders.slice();
  3409. }
  3410. // Body - deep copy
  3411. if (body) {
  3412. // TODO: internal representation should be Body
  3413. // this.body = { ...body };
  3414. this.body = {
  3415. body: body.content,
  3416. contentType: body.contentType
  3417. };
  3418. }
  3419. // Method
  3420. this.method = method;
  3421. // RURI
  3422. this.ruri = ruri.clone();
  3423. // From
  3424. this.fromURI = fromURI.clone();
  3425. this.fromTag = this.options.fromTag ? this.options.fromTag : utils_1.newTag();
  3426. this.from = OutgoingRequestMessage.makeNameAddrHeader(this.fromURI, this.options.fromDisplayName, this.fromTag);
  3427. // To
  3428. this.toURI = toURI.clone();
  3429. this.toTag = this.options.toTag;
  3430. this.to = OutgoingRequestMessage.makeNameAddrHeader(this.toURI, this.options.toDisplayName, this.toTag);
  3431. // Call-ID
  3432. this.callId = this.options.callId ? this.options.callId : this.options.callIdPrefix + utils_1.createRandomToken(15);
  3433. // CSeq
  3434. this.cseq = this.options.cseq;
  3435. // The relative order of header fields with different field names is not
  3436. // significant. However, it is RECOMMENDED that header fields which are
  3437. // needed for proxy processing (Via, Route, Record-Route, Proxy-Require,
  3438. // Max-Forwards, and Proxy-Authorization, for example) appear towards
  3439. // the top of the message to facilitate rapid parsing.
  3440. // https://tools.ietf.org/html/rfc3261#section-7.3.1
  3441. this.setHeader("route", this.options.routeSet);
  3442. this.setHeader("via", "");
  3443. this.setHeader("to", this.to.toString());
  3444. this.setHeader("from", this.from.toString());
  3445. this.setHeader("cseq", this.cseq + " " + this.method);
  3446. this.setHeader("call-id", this.callId);
  3447. this.setHeader("max-forwards", "70");
  3448. }
  3449. /** Get a copy of the default options. */
  3450. OutgoingRequestMessage.getDefaultOptions = function () {
  3451. return {
  3452. callId: "",
  3453. callIdPrefix: "",
  3454. cseq: 1,
  3455. toDisplayName: "",
  3456. toTag: "",
  3457. fromDisplayName: "",
  3458. fromTag: "",
  3459. forceRport: false,
  3460. hackViaTcp: false,
  3461. optionTags: ["outbound"],
  3462. routeSet: [],
  3463. userAgentString: "sip.js",
  3464. viaHost: ""
  3465. };
  3466. };
  3467. OutgoingRequestMessage.makeNameAddrHeader = function (uri, displayName, tag) {
  3468. var parameters = {};
  3469. if (tag) {
  3470. parameters.tag = tag;
  3471. }
  3472. return new name_addr_header_1.NameAddrHeader(uri, displayName, parameters);
  3473. };
  3474. /**
  3475. * Get the value of the given header name at the given position.
  3476. * @param name - header name
  3477. * @returns Returns the specified header, undefined if header doesn't exist.
  3478. */
  3479. OutgoingRequestMessage.prototype.getHeader = function (name) {
  3480. var header = this.headers[utils_1.headerize(name)];
  3481. if (header) {
  3482. if (header[0]) {
  3483. return header[0];
  3484. }
  3485. }
  3486. else {
  3487. var regexp = new RegExp("^\\s*" + name + "\\s*:", "i");
  3488. for (var _i = 0, _a = this.extraHeaders; _i < _a.length; _i++) {
  3489. var exHeader = _a[_i];
  3490. if (regexp.test(exHeader)) {
  3491. return exHeader.substring(exHeader.indexOf(":") + 1).trim();
  3492. }
  3493. }
  3494. }
  3495. return;
  3496. };
  3497. /**
  3498. * Get the header/s of the given name.
  3499. * @param name - header name
  3500. * @returns Array with all the headers of the specified name.
  3501. */
  3502. OutgoingRequestMessage.prototype.getHeaders = function (name) {
  3503. var result = [];
  3504. var headerArray = this.headers[utils_1.headerize(name)];
  3505. if (headerArray) {
  3506. for (var _i = 0, headerArray_1 = headerArray; _i < headerArray_1.length; _i++) {
  3507. var headerPart = headerArray_1[_i];
  3508. result.push(headerPart);
  3509. }
  3510. }
  3511. else {
  3512. var regexp = new RegExp("^\\s*" + name + "\\s*:", "i");
  3513. for (var _a = 0, _b = this.extraHeaders; _a < _b.length; _a++) {
  3514. var exHeader = _b[_a];
  3515. if (regexp.test(exHeader)) {
  3516. result.push(exHeader.substring(exHeader.indexOf(":") + 1).trim());
  3517. }
  3518. }
  3519. }
  3520. return result;
  3521. };
  3522. /**
  3523. * Verify the existence of the given header.
  3524. * @param name - header name
  3525. * @returns true if header with given name exists, false otherwise
  3526. */
  3527. OutgoingRequestMessage.prototype.hasHeader = function (name) {
  3528. if (this.headers[utils_1.headerize(name)]) {
  3529. return true;
  3530. }
  3531. else {
  3532. var regexp = new RegExp("^\\s*" + name + "\\s*:", "i");
  3533. for (var _i = 0, _a = this.extraHeaders; _i < _a.length; _i++) {
  3534. var extraHeader = _a[_i];
  3535. if (regexp.test(extraHeader)) {
  3536. return true;
  3537. }
  3538. }
  3539. }
  3540. return false;
  3541. };
  3542. /**
  3543. * Replace the the given header by the given value.
  3544. * @param name - header name
  3545. * @param value - header value
  3546. */
  3547. OutgoingRequestMessage.prototype.setHeader = function (name, value) {
  3548. this.headers[utils_1.headerize(name)] = (value instanceof Array) ? value : [value];
  3549. };
  3550. /**
  3551. * The Via header field indicates the transport used for the transaction
  3552. * and identifies the location where the response is to be sent. A Via
  3553. * header field value is added only after the transport that will be
  3554. * used to reach the next hop has been selected (which may involve the
  3555. * usage of the procedures in [4]).
  3556. *
  3557. * When the UAC creates a request, it MUST insert a Via into that
  3558. * request. The protocol name and protocol version in the header field
  3559. * MUST be SIP and 2.0, respectively. The Via header field value MUST
  3560. * contain a branch parameter. This parameter is used to identify the
  3561. * transaction created by that request. This parameter is used by both
  3562. * the client and the server.
  3563. * https://tools.ietf.org/html/rfc3261#section-8.1.1.7
  3564. * @param branchParameter - The branch parameter.
  3565. * @param scheme - The scheme.
  3566. */
  3567. OutgoingRequestMessage.prototype.setViaHeader = function (branch, scheme) {
  3568. if (scheme === void 0) { scheme = "WSS"; }
  3569. // FIXME: Hack
  3570. if (this.options.hackViaTcp) {
  3571. scheme = "TCP";
  3572. }
  3573. var via = "SIP/2.0/" + scheme;
  3574. via += " " + this.options.viaHost + ";branch=" + branch;
  3575. if (this.options.forceRport) {
  3576. via += ";rport";
  3577. }
  3578. this.setHeader("via", via);
  3579. this.branch = branch;
  3580. };
  3581. OutgoingRequestMessage.prototype.toString = function () {
  3582. var msg = "";
  3583. msg += this.method + " " + this.ruri.toRaw() + " SIP/2.0\r\n";
  3584. for (var header in this.headers) {
  3585. if (this.headers[header]) {
  3586. for (var _i = 0, _a = this.headers[header]; _i < _a.length; _i++) {
  3587. var headerPart = _a[_i];
  3588. msg += header + ": " + headerPart + "\r\n";
  3589. }
  3590. }
  3591. }
  3592. for (var _b = 0, _c = this.extraHeaders; _b < _c.length; _b++) {
  3593. var header = _c[_b];
  3594. msg += header.trim() + "\r\n";
  3595. }
  3596. msg += "Supported: " + this.options.optionTags.join(", ") + "\r\n";
  3597. msg += "User-Agent: " + this.options.userAgentString + "\r\n";
  3598. if (this.body) {
  3599. if (typeof this.body === "string") {
  3600. msg += "Content-Length: " + utils_1.str_utf8_length(this.body) + "\r\n\r\n";
  3601. msg += this.body;
  3602. }
  3603. else {
  3604. if (this.body.body && this.body.contentType) {
  3605. msg += "Content-Type: " + this.body.contentType + "\r\n";
  3606. msg += "Content-Length: " + utils_1.str_utf8_length(this.body.body) + "\r\n\r\n";
  3607. msg += this.body.body;
  3608. }
  3609. else {
  3610. msg += "Content-Length: " + 0 + "\r\n\r\n";
  3611. }
  3612. }
  3613. }
  3614. else {
  3615. msg += "Content-Length: " + 0 + "\r\n\r\n";
  3616. }
  3617. return msg;
  3618. };
  3619. return OutgoingRequestMessage;
  3620. }());
  3621. exports.OutgoingRequestMessage = OutgoingRequestMessage;
  3622. /***/ }),
  3623. /* 19 */
  3624. /***/ (function(module, exports, __webpack_require__) {
  3625. "use strict";
  3626. Object.defineProperty(exports, "__esModule", { value: true });
  3627. var tslib_1 = __webpack_require__(1);
  3628. var md5_1 = tslib_1.__importDefault(__webpack_require__(20));
  3629. var utils_1 = __webpack_require__(16);
  3630. /**
  3631. * Digest Authentication.
  3632. * @internal
  3633. */
  3634. var DigestAuthentication = /** @class */ (function () {
  3635. /**
  3636. * Constructor.
  3637. * @param loggerFactory - LoggerFactory.
  3638. * @param username - Username.
  3639. * @param password - Password.
  3640. */
  3641. function DigestAuthentication(loggerFactory, username, password) {
  3642. this.logger = loggerFactory.getLogger("sipjs.digestauthentication");
  3643. this.username = username;
  3644. this.password = password;
  3645. this.nc = 0;
  3646. this.ncHex = "00000000";
  3647. }
  3648. /**
  3649. * Performs Digest authentication given a SIP request and the challenge
  3650. * received in a response to that request.
  3651. * @param request -
  3652. * @param challenge -
  3653. * @returns true if credentials were successfully generated, false otherwise.
  3654. */
  3655. DigestAuthentication.prototype.authenticate = function (request, challenge, body) {
  3656. // Inspect and validate the challenge.
  3657. this.algorithm = challenge.algorithm;
  3658. this.realm = challenge.realm;
  3659. this.nonce = challenge.nonce;
  3660. this.opaque = challenge.opaque;
  3661. this.stale = challenge.stale;
  3662. if (this.algorithm) {
  3663. if (this.algorithm !== "MD5") {
  3664. this.logger.warn("challenge with Digest algorithm different than 'MD5', authentication aborted");
  3665. return false;
  3666. }
  3667. }
  3668. else {
  3669. this.algorithm = "MD5";
  3670. }
  3671. if (!this.realm) {
  3672. this.logger.warn("challenge without Digest realm, authentication aborted");
  3673. return false;
  3674. }
  3675. if (!this.nonce) {
  3676. this.logger.warn("challenge without Digest nonce, authentication aborted");
  3677. return false;
  3678. }
  3679. // 'qop' can contain a list of values (Array). Let's choose just one.
  3680. if (challenge.qop) {
  3681. if (challenge.qop.indexOf("auth") > -1) {
  3682. this.qop = "auth";
  3683. }
  3684. else if (challenge.qop.indexOf("auth-int") > -1) {
  3685. this.qop = "auth-int";
  3686. }
  3687. else {
  3688. // Otherwise 'qop' is present but does not contain 'auth' or 'auth-int', so abort here.
  3689. this.logger.warn("challenge without Digest qop different than 'auth' or 'auth-int', authentication aborted");
  3690. return false;
  3691. }
  3692. }
  3693. else {
  3694. this.qop = undefined;
  3695. }
  3696. // Fill other attributes.
  3697. this.method = request.method;
  3698. this.uri = request.ruri;
  3699. this.cnonce = utils_1.createRandomToken(12);
  3700. this.nc += 1;
  3701. this.updateNcHex();
  3702. // nc-value = 8LHEX. Max value = 'FFFFFFFF'.
  3703. if (this.nc === 4294967296) {
  3704. this.nc = 1;
  3705. this.ncHex = "00000001";
  3706. }
  3707. // Calculate the Digest "response" value.
  3708. this.calculateResponse(body);
  3709. return true;
  3710. };
  3711. /**
  3712. * Return the Proxy-Authorization or WWW-Authorization header value.
  3713. */
  3714. DigestAuthentication.prototype.toString = function () {
  3715. var authParams = [];
  3716. if (!this.response) {
  3717. throw new Error("response field does not exist, cannot generate Authorization header");
  3718. }
  3719. authParams.push("algorithm=" + this.algorithm);
  3720. authParams.push('username="' + this.username + '"');
  3721. authParams.push('realm="' + this.realm + '"');
  3722. authParams.push('nonce="' + this.nonce + '"');
  3723. authParams.push('uri="' + this.uri + '"');
  3724. authParams.push('response="' + this.response + '"');
  3725. if (this.opaque) {
  3726. authParams.push('opaque="' + this.opaque + '"');
  3727. }
  3728. if (this.qop) {
  3729. authParams.push("qop=" + this.qop);
  3730. authParams.push('cnonce="' + this.cnonce + '"');
  3731. authParams.push("nc=" + this.ncHex);
  3732. }
  3733. return "Digest " + authParams.join(", ");
  3734. };
  3735. /**
  3736. * Generate the 'nc' value as required by Digest in this.ncHex by reading this.nc.
  3737. */
  3738. DigestAuthentication.prototype.updateNcHex = function () {
  3739. var hex = Number(this.nc).toString(16);
  3740. this.ncHex = "00000000".substr(0, 8 - hex.length) + hex;
  3741. };
  3742. /**
  3743. * Generate Digest 'response' value.
  3744. */
  3745. DigestAuthentication.prototype.calculateResponse = function (body) {
  3746. var ha2;
  3747. // HA1 = MD5(A1) = MD5(username:realm:password)
  3748. var ha1 = md5_1.default(this.username + ":" + this.realm + ":" + this.password);
  3749. if (this.qop === "auth") {
  3750. // HA2 = MD5(A2) = MD5(method:digestURI)
  3751. ha2 = md5_1.default(this.method + ":" + this.uri);
  3752. // response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2)
  3753. this.response = md5_1.default(ha1 + ":" + this.nonce + ":" + this.ncHex + ":" + this.cnonce + ":auth:" + ha2);
  3754. }
  3755. else if (this.qop === "auth-int") {
  3756. // HA2 = MD5(A2) = MD5(method:digestURI:MD5(entityBody))
  3757. ha2 = md5_1.default(this.method + ":" + this.uri + ":" + md5_1.default(body ? body : ""));
  3758. // response = MD5(HA1:nonce:nonceCount:credentialsNonce:qop:HA2)
  3759. this.response = md5_1.default(ha1 + ":" + this.nonce + ":" + this.ncHex + ":" + this.cnonce + ":auth-int:" + ha2);
  3760. }
  3761. else if (this.qop === undefined) {
  3762. // HA2 = MD5(A2) = MD5(method:digestURI)
  3763. ha2 = md5_1.default(this.method + ":" + this.uri);
  3764. // response = MD5(HA1:nonce:HA2)
  3765. this.response = md5_1.default(ha1 + ":" + this.nonce + ":" + ha2);
  3766. }
  3767. };
  3768. return DigestAuthentication;
  3769. }());
  3770. exports.DigestAuthentication = DigestAuthentication;
  3771. /***/ }),
  3772. /* 20 */
  3773. /***/ (function(module, exports, __webpack_require__) {
  3774. ;(function (root, factory) {
  3775. if (true) {
  3776. // CommonJS
  3777. module.exports = exports = factory(__webpack_require__(21));
  3778. }
  3779. else {}
  3780. }(this, function (CryptoJS) {
  3781. (function (Math) {
  3782. // Shortcuts
  3783. var C = CryptoJS;
  3784. var C_lib = C.lib;
  3785. var WordArray = C_lib.WordArray;
  3786. var Hasher = C_lib.Hasher;
  3787. var C_algo = C.algo;
  3788. // Constants table
  3789. var T = [];
  3790. // Compute constants
  3791. (function () {
  3792. for (var i = 0; i < 64; i++) {
  3793. T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
  3794. }
  3795. }());
  3796. /**
  3797. * MD5 hash algorithm.
  3798. */
  3799. var MD5 = C_algo.MD5 = Hasher.extend({
  3800. _doReset: function () {
  3801. this._hash = new WordArray.init([
  3802. 0x67452301, 0xefcdab89,
  3803. 0x98badcfe, 0x10325476
  3804. ]);
  3805. },
  3806. _doProcessBlock: function (M, offset) {
  3807. // Swap endian
  3808. for (var i = 0; i < 16; i++) {
  3809. // Shortcuts
  3810. var offset_i = offset + i;
  3811. var M_offset_i = M[offset_i];
  3812. M[offset_i] = (
  3813. (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
  3814. (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
  3815. );
  3816. }
  3817. // Shortcuts
  3818. var H = this._hash.words;
  3819. var M_offset_0 = M[offset + 0];
  3820. var M_offset_1 = M[offset + 1];
  3821. var M_offset_2 = M[offset + 2];
  3822. var M_offset_3 = M[offset + 3];
  3823. var M_offset_4 = M[offset + 4];
  3824. var M_offset_5 = M[offset + 5];
  3825. var M_offset_6 = M[offset + 6];
  3826. var M_offset_7 = M[offset + 7];
  3827. var M_offset_8 = M[offset + 8];
  3828. var M_offset_9 = M[offset + 9];
  3829. var M_offset_10 = M[offset + 10];
  3830. var M_offset_11 = M[offset + 11];
  3831. var M_offset_12 = M[offset + 12];
  3832. var M_offset_13 = M[offset + 13];
  3833. var M_offset_14 = M[offset + 14];
  3834. var M_offset_15 = M[offset + 15];
  3835. // Working varialbes
  3836. var a = H[0];
  3837. var b = H[1];
  3838. var c = H[2];
  3839. var d = H[3];
  3840. // Computation
  3841. a = FF(a, b, c, d, M_offset_0, 7, T[0]);
  3842. d = FF(d, a, b, c, M_offset_1, 12, T[1]);
  3843. c = FF(c, d, a, b, M_offset_2, 17, T[2]);
  3844. b = FF(b, c, d, a, M_offset_3, 22, T[3]);
  3845. a = FF(a, b, c, d, M_offset_4, 7, T[4]);
  3846. d = FF(d, a, b, c, M_offset_5, 12, T[5]);
  3847. c = FF(c, d, a, b, M_offset_6, 17, T[6]);
  3848. b = FF(b, c, d, a, M_offset_7, 22, T[7]);
  3849. a = FF(a, b, c, d, M_offset_8, 7, T[8]);
  3850. d = FF(d, a, b, c, M_offset_9, 12, T[9]);
  3851. c = FF(c, d, a, b, M_offset_10, 17, T[10]);
  3852. b = FF(b, c, d, a, M_offset_11, 22, T[11]);
  3853. a = FF(a, b, c, d, M_offset_12, 7, T[12]);
  3854. d = FF(d, a, b, c, M_offset_13, 12, T[13]);
  3855. c = FF(c, d, a, b, M_offset_14, 17, T[14]);
  3856. b = FF(b, c, d, a, M_offset_15, 22, T[15]);
  3857. a = GG(a, b, c, d, M_offset_1, 5, T[16]);
  3858. d = GG(d, a, b, c, M_offset_6, 9, T[17]);
  3859. c = GG(c, d, a, b, M_offset_11, 14, T[18]);
  3860. b = GG(b, c, d, a, M_offset_0, 20, T[19]);
  3861. a = GG(a, b, c, d, M_offset_5, 5, T[20]);
  3862. d = GG(d, a, b, c, M_offset_10, 9, T[21]);
  3863. c = GG(c, d, a, b, M_offset_15, 14, T[22]);
  3864. b = GG(b, c, d, a, M_offset_4, 20, T[23]);
  3865. a = GG(a, b, c, d, M_offset_9, 5, T[24]);
  3866. d = GG(d, a, b, c, M_offset_14, 9, T[25]);
  3867. c = GG(c, d, a, b, M_offset_3, 14, T[26]);
  3868. b = GG(b, c, d, a, M_offset_8, 20, T[27]);
  3869. a = GG(a, b, c, d, M_offset_13, 5, T[28]);
  3870. d = GG(d, a, b, c, M_offset_2, 9, T[29]);
  3871. c = GG(c, d, a, b, M_offset_7, 14, T[30]);
  3872. b = GG(b, c, d, a, M_offset_12, 20, T[31]);
  3873. a = HH(a, b, c, d, M_offset_5, 4, T[32]);
  3874. d = HH(d, a, b, c, M_offset_8, 11, T[33]);
  3875. c = HH(c, d, a, b, M_offset_11, 16, T[34]);
  3876. b = HH(b, c, d, a, M_offset_14, 23, T[35]);
  3877. a = HH(a, b, c, d, M_offset_1, 4, T[36]);
  3878. d = HH(d, a, b, c, M_offset_4, 11, T[37]);
  3879. c = HH(c, d, a, b, M_offset_7, 16, T[38]);
  3880. b = HH(b, c, d, a, M_offset_10, 23, T[39]);
  3881. a = HH(a, b, c, d, M_offset_13, 4, T[40]);
  3882. d = HH(d, a, b, c, M_offset_0, 11, T[41]);
  3883. c = HH(c, d, a, b, M_offset_3, 16, T[42]);
  3884. b = HH(b, c, d, a, M_offset_6, 23, T[43]);
  3885. a = HH(a, b, c, d, M_offset_9, 4, T[44]);
  3886. d = HH(d, a, b, c, M_offset_12, 11, T[45]);
  3887. c = HH(c, d, a, b, M_offset_15, 16, T[46]);
  3888. b = HH(b, c, d, a, M_offset_2, 23, T[47]);
  3889. a = II(a, b, c, d, M_offset_0, 6, T[48]);
  3890. d = II(d, a, b, c, M_offset_7, 10, T[49]);
  3891. c = II(c, d, a, b, M_offset_14, 15, T[50]);
  3892. b = II(b, c, d, a, M_offset_5, 21, T[51]);
  3893. a = II(a, b, c, d, M_offset_12, 6, T[52]);
  3894. d = II(d, a, b, c, M_offset_3, 10, T[53]);
  3895. c = II(c, d, a, b, M_offset_10, 15, T[54]);
  3896. b = II(b, c, d, a, M_offset_1, 21, T[55]);
  3897. a = II(a, b, c, d, M_offset_8, 6, T[56]);
  3898. d = II(d, a, b, c, M_offset_15, 10, T[57]);
  3899. c = II(c, d, a, b, M_offset_6, 15, T[58]);
  3900. b = II(b, c, d, a, M_offset_13, 21, T[59]);
  3901. a = II(a, b, c, d, M_offset_4, 6, T[60]);
  3902. d = II(d, a, b, c, M_offset_11, 10, T[61]);
  3903. c = II(c, d, a, b, M_offset_2, 15, T[62]);
  3904. b = II(b, c, d, a, M_offset_9, 21, T[63]);
  3905. // Intermediate hash value
  3906. H[0] = (H[0] + a) | 0;
  3907. H[1] = (H[1] + b) | 0;
  3908. H[2] = (H[2] + c) | 0;
  3909. H[3] = (H[3] + d) | 0;
  3910. },
  3911. _doFinalize: function () {
  3912. // Shortcuts
  3913. var data = this._data;
  3914. var dataWords = data.words;
  3915. var nBitsTotal = this._nDataBytes * 8;
  3916. var nBitsLeft = data.sigBytes * 8;
  3917. // Add padding
  3918. dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
  3919. var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
  3920. var nBitsTotalL = nBitsTotal;
  3921. dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
  3922. (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
  3923. (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00)
  3924. );
  3925. dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
  3926. (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
  3927. (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00)
  3928. );
  3929. data.sigBytes = (dataWords.length + 1) * 4;
  3930. // Hash final blocks
  3931. this._process();
  3932. // Shortcuts
  3933. var hash = this._hash;
  3934. var H = hash.words;
  3935. // Swap endian
  3936. for (var i = 0; i < 4; i++) {
  3937. // Shortcut
  3938. var H_i = H[i];
  3939. H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) |
  3940. (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
  3941. }
  3942. // Return final computed hash
  3943. return hash;
  3944. },
  3945. clone: function () {
  3946. var clone = Hasher.clone.call(this);
  3947. clone._hash = this._hash.clone();
  3948. return clone;
  3949. }
  3950. });
  3951. function FF(a, b, c, d, x, s, t) {
  3952. var n = a + ((b & c) | (~b & d)) + x + t;
  3953. return ((n << s) | (n >>> (32 - s))) + b;
  3954. }
  3955. function GG(a, b, c, d, x, s, t) {
  3956. var n = a + ((b & d) | (c & ~d)) + x + t;
  3957. return ((n << s) | (n >>> (32 - s))) + b;
  3958. }
  3959. function HH(a, b, c, d, x, s, t) {
  3960. var n = a + (b ^ c ^ d) + x + t;
  3961. return ((n << s) | (n >>> (32 - s))) + b;
  3962. }
  3963. function II(a, b, c, d, x, s, t) {
  3964. var n = a + (c ^ (b | ~d)) + x + t;
  3965. return ((n << s) | (n >>> (32 - s))) + b;
  3966. }
  3967. /**
  3968. * Shortcut function to the hasher's object interface.
  3969. *
  3970. * @param {WordArray|string} message The message to hash.
  3971. *
  3972. * @return {WordArray} The hash.
  3973. *
  3974. * @static
  3975. *
  3976. * @example
  3977. *
  3978. * var hash = CryptoJS.MD5('message');
  3979. * var hash = CryptoJS.MD5(wordArray);
  3980. */
  3981. C.MD5 = Hasher._createHelper(MD5);
  3982. /**
  3983. * Shortcut function to the HMAC's object interface.
  3984. *
  3985. * @param {WordArray|string} message The message to hash.
  3986. * @param {WordArray|string} key The secret key.
  3987. *
  3988. * @return {WordArray} The HMAC.
  3989. *
  3990. * @static
  3991. *
  3992. * @example
  3993. *
  3994. * var hmac = CryptoJS.HmacMD5(message, key);
  3995. */
  3996. C.HmacMD5 = Hasher._createHmacHelper(MD5);
  3997. }(Math));
  3998. return CryptoJS.MD5;
  3999. }));
  4000. /***/ }),
  4001. /* 21 */
  4002. /***/ (function(module, exports, __webpack_require__) {
  4003. ;(function (root, factory) {
  4004. if (true) {
  4005. // CommonJS
  4006. module.exports = exports = factory();
  4007. }
  4008. else {}
  4009. }(this, function () {
  4010. /**
  4011. * CryptoJS core components.
  4012. */
  4013. var CryptoJS = CryptoJS || (function (Math, undefined) {
  4014. /*
  4015. * Local polyfil of Object.create
  4016. */
  4017. var create = Object.create || (function () {
  4018. function F() {};
  4019. return function (obj) {
  4020. var subtype;
  4021. F.prototype = obj;
  4022. subtype = new F();
  4023. F.prototype = null;
  4024. return subtype;
  4025. };
  4026. }())
  4027. /**
  4028. * CryptoJS namespace.
  4029. */
  4030. var C = {};
  4031. /**
  4032. * Library namespace.
  4033. */
  4034. var C_lib = C.lib = {};
  4035. /**
  4036. * Base object for prototypal inheritance.
  4037. */
  4038. var Base = C_lib.Base = (function () {
  4039. return {
  4040. /**
  4041. * Creates a new object that inherits from this object.
  4042. *
  4043. * @param {Object} overrides Properties to copy into the new object.
  4044. *
  4045. * @return {Object} The new object.
  4046. *
  4047. * @static
  4048. *
  4049. * @example
  4050. *
  4051. * var MyType = CryptoJS.lib.Base.extend({
  4052. * field: 'value',
  4053. *
  4054. * method: function () {
  4055. * }
  4056. * });
  4057. */
  4058. extend: function (overrides) {
  4059. // Spawn
  4060. var subtype = create(this);
  4061. // Augment
  4062. if (overrides) {
  4063. subtype.mixIn(overrides);
  4064. }
  4065. // Create default initializer
  4066. if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
  4067. subtype.init = function () {
  4068. subtype.$super.init.apply(this, arguments);
  4069. };
  4070. }
  4071. // Initializer's prototype is the subtype object
  4072. subtype.init.prototype = subtype;
  4073. // Reference supertype
  4074. subtype.$super = this;
  4075. return subtype;
  4076. },
  4077. /**
  4078. * Extends this object and runs the init method.
  4079. * Arguments to create() will be passed to init().
  4080. *
  4081. * @return {Object} The new object.
  4082. *
  4083. * @static
  4084. *
  4085. * @example
  4086. *
  4087. * var instance = MyType.create();
  4088. */
  4089. create: function () {
  4090. var instance = this.extend();
  4091. instance.init.apply(instance, arguments);
  4092. return instance;
  4093. },
  4094. /**
  4095. * Initializes a newly created object.
  4096. * Override this method to add some logic when your objects are created.
  4097. *
  4098. * @example
  4099. *
  4100. * var MyType = CryptoJS.lib.Base.extend({
  4101. * init: function () {
  4102. * // ...
  4103. * }
  4104. * });
  4105. */
  4106. init: function () {
  4107. },
  4108. /**
  4109. * Copies properties into this object.
  4110. *
  4111. * @param {Object} properties The properties to mix in.
  4112. *
  4113. * @example
  4114. *
  4115. * MyType.mixIn({
  4116. * field: 'value'
  4117. * });
  4118. */
  4119. mixIn: function (properties) {
  4120. for (var propertyName in properties) {
  4121. if (properties.hasOwnProperty(propertyName)) {
  4122. this[propertyName] = properties[propertyName];
  4123. }
  4124. }
  4125. // IE won't copy toString using the loop above
  4126. if (properties.hasOwnProperty('toString')) {
  4127. this.toString = properties.toString;
  4128. }
  4129. },
  4130. /**
  4131. * Creates a copy of this object.
  4132. *
  4133. * @return {Object} The clone.
  4134. *
  4135. * @example
  4136. *
  4137. * var clone = instance.clone();
  4138. */
  4139. clone: function () {
  4140. return this.init.prototype.extend(this);
  4141. }
  4142. };
  4143. }());
  4144. /**
  4145. * An array of 32-bit words.
  4146. *
  4147. * @property {Array} words The array of 32-bit words.
  4148. * @property {number} sigBytes The number of significant bytes in this word array.
  4149. */
  4150. var WordArray = C_lib.WordArray = Base.extend({
  4151. /**
  4152. * Initializes a newly created word array.
  4153. *
  4154. * @param {Array} words (Optional) An array of 32-bit words.
  4155. * @param {number} sigBytes (Optional) The number of significant bytes in the words.
  4156. *
  4157. * @example
  4158. *
  4159. * var wordArray = CryptoJS.lib.WordArray.create();
  4160. * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
  4161. * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
  4162. */
  4163. init: function (words, sigBytes) {
  4164. words = this.words = words || [];
  4165. if (sigBytes != undefined) {
  4166. this.sigBytes = sigBytes;
  4167. } else {
  4168. this.sigBytes = words.length * 4;
  4169. }
  4170. },
  4171. /**
  4172. * Converts this word array to a string.
  4173. *
  4174. * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
  4175. *
  4176. * @return {string} The stringified word array.
  4177. *
  4178. * @example
  4179. *
  4180. * var string = wordArray + '';
  4181. * var string = wordArray.toString();
  4182. * var string = wordArray.toString(CryptoJS.enc.Utf8);
  4183. */
  4184. toString: function (encoder) {
  4185. return (encoder || Hex).stringify(this);
  4186. },
  4187. /**
  4188. * Concatenates a word array to this word array.
  4189. *
  4190. * @param {WordArray} wordArray The word array to append.
  4191. *
  4192. * @return {WordArray} This word array.
  4193. *
  4194. * @example
  4195. *
  4196. * wordArray1.concat(wordArray2);
  4197. */
  4198. concat: function (wordArray) {
  4199. // Shortcuts
  4200. var thisWords = this.words;
  4201. var thatWords = wordArray.words;
  4202. var thisSigBytes = this.sigBytes;
  4203. var thatSigBytes = wordArray.sigBytes;
  4204. // Clamp excess bits
  4205. this.clamp();
  4206. // Concat
  4207. if (thisSigBytes % 4) {
  4208. // Copy one byte at a time
  4209. for (var i = 0; i < thatSigBytes; i++) {
  4210. var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
  4211. thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
  4212. }
  4213. } else {
  4214. // Copy one word at a time
  4215. for (var i = 0; i < thatSigBytes; i += 4) {
  4216. thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
  4217. }
  4218. }
  4219. this.sigBytes += thatSigBytes;
  4220. // Chainable
  4221. return this;
  4222. },
  4223. /**
  4224. * Removes insignificant bits.
  4225. *
  4226. * @example
  4227. *
  4228. * wordArray.clamp();
  4229. */
  4230. clamp: function () {
  4231. // Shortcuts
  4232. var words = this.words;
  4233. var sigBytes = this.sigBytes;
  4234. // Clamp
  4235. words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
  4236. words.length = Math.ceil(sigBytes / 4);
  4237. },
  4238. /**
  4239. * Creates a copy of this word array.
  4240. *
  4241. * @return {WordArray} The clone.
  4242. *
  4243. * @example
  4244. *
  4245. * var clone = wordArray.clone();
  4246. */
  4247. clone: function () {
  4248. var clone = Base.clone.call(this);
  4249. clone.words = this.words.slice(0);
  4250. return clone;
  4251. },
  4252. /**
  4253. * Creates a word array filled with random bytes.
  4254. *
  4255. * @param {number} nBytes The number of random bytes to generate.
  4256. *
  4257. * @return {WordArray} The random word array.
  4258. *
  4259. * @static
  4260. *
  4261. * @example
  4262. *
  4263. * var wordArray = CryptoJS.lib.WordArray.random(16);
  4264. */
  4265. random: function (nBytes) {
  4266. var words = [];
  4267. var r = (function (m_w) {
  4268. var m_w = m_w;
  4269. var m_z = 0x3ade68b1;
  4270. var mask = 0xffffffff;
  4271. return function () {
  4272. m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask;
  4273. m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask;
  4274. var result = ((m_z << 0x10) + m_w) & mask;
  4275. result /= 0x100000000;
  4276. result += 0.5;
  4277. return result * (Math.random() > .5 ? 1 : -1);
  4278. }
  4279. });
  4280. for (var i = 0, rcache; i < nBytes; i += 4) {
  4281. var _r = r((rcache || Math.random()) * 0x100000000);
  4282. rcache = _r() * 0x3ade67b7;
  4283. words.push((_r() * 0x100000000) | 0);
  4284. }
  4285. return new WordArray.init(words, nBytes);
  4286. }
  4287. });
  4288. /**
  4289. * Encoder namespace.
  4290. */
  4291. var C_enc = C.enc = {};
  4292. /**
  4293. * Hex encoding strategy.
  4294. */
  4295. var Hex = C_enc.Hex = {
  4296. /**
  4297. * Converts a word array to a hex string.
  4298. *
  4299. * @param {WordArray} wordArray The word array.
  4300. *
  4301. * @return {string} The hex string.
  4302. *
  4303. * @static
  4304. *
  4305. * @example
  4306. *
  4307. * var hexString = CryptoJS.enc.Hex.stringify(wordArray);
  4308. */
  4309. stringify: function (wordArray) {
  4310. // Shortcuts
  4311. var words = wordArray.words;
  4312. var sigBytes = wordArray.sigBytes;
  4313. // Convert
  4314. var hexChars = [];
  4315. for (var i = 0; i < sigBytes; i++) {
  4316. var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
  4317. hexChars.push((bite >>> 4).toString(16));
  4318. hexChars.push((bite & 0x0f).toString(16));
  4319. }
  4320. return hexChars.join('');
  4321. },
  4322. /**
  4323. * Converts a hex string to a word array.
  4324. *
  4325. * @param {string} hexStr The hex string.
  4326. *
  4327. * @return {WordArray} The word array.
  4328. *
  4329. * @static
  4330. *
  4331. * @example
  4332. *
  4333. * var wordArray = CryptoJS.enc.Hex.parse(hexString);
  4334. */
  4335. parse: function (hexStr) {
  4336. // Shortcut
  4337. var hexStrLength = hexStr.length;
  4338. // Convert
  4339. var words = [];
  4340. for (var i = 0; i < hexStrLength; i += 2) {
  4341. words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
  4342. }
  4343. return new WordArray.init(words, hexStrLength / 2);
  4344. }
  4345. };
  4346. /**
  4347. * Latin1 encoding strategy.
  4348. */
  4349. var Latin1 = C_enc.Latin1 = {
  4350. /**
  4351. * Converts a word array to a Latin1 string.
  4352. *
  4353. * @param {WordArray} wordArray The word array.
  4354. *
  4355. * @return {string} The Latin1 string.
  4356. *
  4357. * @static
  4358. *
  4359. * @example
  4360. *
  4361. * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
  4362. */
  4363. stringify: function (wordArray) {
  4364. // Shortcuts
  4365. var words = wordArray.words;
  4366. var sigBytes = wordArray.sigBytes;
  4367. // Convert
  4368. var latin1Chars = [];
  4369. for (var i = 0; i < sigBytes; i++) {
  4370. var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
  4371. latin1Chars.push(String.fromCharCode(bite));
  4372. }
  4373. return latin1Chars.join('');
  4374. },
  4375. /**
  4376. * Converts a Latin1 string to a word array.
  4377. *
  4378. * @param {string} latin1Str The Latin1 string.
  4379. *
  4380. * @return {WordArray} The word array.
  4381. *
  4382. * @static
  4383. *
  4384. * @example
  4385. *
  4386. * var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
  4387. */
  4388. parse: function (latin1Str) {
  4389. // Shortcut
  4390. var latin1StrLength = latin1Str.length;
  4391. // Convert
  4392. var words = [];
  4393. for (var i = 0; i < latin1StrLength; i++) {
  4394. words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
  4395. }
  4396. return new WordArray.init(words, latin1StrLength);
  4397. }
  4398. };
  4399. /**
  4400. * UTF-8 encoding strategy.
  4401. */
  4402. var Utf8 = C_enc.Utf8 = {
  4403. /**
  4404. * Converts a word array to a UTF-8 string.
  4405. *
  4406. * @param {WordArray} wordArray The word array.
  4407. *
  4408. * @return {string} The UTF-8 string.
  4409. *
  4410. * @static
  4411. *
  4412. * @example
  4413. *
  4414. * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
  4415. */
  4416. stringify: function (wordArray) {
  4417. try {
  4418. return decodeURIComponent(escape(Latin1.stringify(wordArray)));
  4419. } catch (e) {
  4420. throw new Error('Malformed UTF-8 data');
  4421. }
  4422. },
  4423. /**
  4424. * Converts a UTF-8 string to a word array.
  4425. *
  4426. * @param {string} utf8Str The UTF-8 string.
  4427. *
  4428. * @return {WordArray} The word array.
  4429. *
  4430. * @static
  4431. *
  4432. * @example
  4433. *
  4434. * var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
  4435. */
  4436. parse: function (utf8Str) {
  4437. return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
  4438. }
  4439. };
  4440. /**
  4441. * Abstract buffered block algorithm template.
  4442. *
  4443. * The property blockSize must be implemented in a concrete subtype.
  4444. *
  4445. * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
  4446. */
  4447. var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
  4448. /**
  4449. * Resets this block algorithm's data buffer to its initial state.
  4450. *
  4451. * @example
  4452. *
  4453. * bufferedBlockAlgorithm.reset();
  4454. */
  4455. reset: function () {
  4456. // Initial values
  4457. this._data = new WordArray.init();
  4458. this._nDataBytes = 0;
  4459. },
  4460. /**
  4461. * Adds new data to this block algorithm's buffer.
  4462. *
  4463. * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
  4464. *
  4465. * @example
  4466. *
  4467. * bufferedBlockAlgorithm._append('data');
  4468. * bufferedBlockAlgorithm._append(wordArray);
  4469. */
  4470. _append: function (data) {
  4471. // Convert string to WordArray, else assume WordArray already
  4472. if (typeof data == 'string') {
  4473. data = Utf8.parse(data);
  4474. }
  4475. // Append
  4476. this._data.concat(data);
  4477. this._nDataBytes += data.sigBytes;
  4478. },
  4479. /**
  4480. * Processes available data blocks.
  4481. *
  4482. * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
  4483. *
  4484. * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
  4485. *
  4486. * @return {WordArray} The processed data.
  4487. *
  4488. * @example
  4489. *
  4490. * var processedData = bufferedBlockAlgorithm._process();
  4491. * var processedData = bufferedBlockAlgorithm._process(!!'flush');
  4492. */
  4493. _process: function (doFlush) {
  4494. // Shortcuts
  4495. var data = this._data;
  4496. var dataWords = data.words;
  4497. var dataSigBytes = data.sigBytes;
  4498. var blockSize = this.blockSize;
  4499. var blockSizeBytes = blockSize * 4;
  4500. // Count blocks ready
  4501. var nBlocksReady = dataSigBytes / blockSizeBytes;
  4502. if (doFlush) {
  4503. // Round up to include partial blocks
  4504. nBlocksReady = Math.ceil(nBlocksReady);
  4505. } else {
  4506. // Round down to include only full blocks,
  4507. // less the number of blocks that must remain in the buffer
  4508. nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
  4509. }
  4510. // Count words ready
  4511. var nWordsReady = nBlocksReady * blockSize;
  4512. // Count bytes ready
  4513. var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
  4514. // Process blocks
  4515. if (nWordsReady) {
  4516. for (var offset = 0; offset < nWordsReady; offset += blockSize) {
  4517. // Perform concrete-algorithm logic
  4518. this._doProcessBlock(dataWords, offset);
  4519. }
  4520. // Remove processed words
  4521. var processedWords = dataWords.splice(0, nWordsReady);
  4522. data.sigBytes -= nBytesReady;
  4523. }
  4524. // Return processed words
  4525. return new WordArray.init(processedWords, nBytesReady);
  4526. },
  4527. /**
  4528. * Creates a copy of this object.
  4529. *
  4530. * @return {Object} The clone.
  4531. *
  4532. * @example
  4533. *
  4534. * var clone = bufferedBlockAlgorithm.clone();
  4535. */
  4536. clone: function () {
  4537. var clone = Base.clone.call(this);
  4538. clone._data = this._data.clone();
  4539. return clone;
  4540. },
  4541. _minBufferSize: 0
  4542. });
  4543. /**
  4544. * Abstract hasher template.
  4545. *
  4546. * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
  4547. */
  4548. var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
  4549. /**
  4550. * Configuration options.
  4551. */
  4552. cfg: Base.extend(),
  4553. /**
  4554. * Initializes a newly created hasher.
  4555. *
  4556. * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
  4557. *
  4558. * @example
  4559. *
  4560. * var hasher = CryptoJS.algo.SHA256.create();
  4561. */
  4562. init: function (cfg) {
  4563. // Apply config defaults
  4564. this.cfg = this.cfg.extend(cfg);
  4565. // Set initial values
  4566. this.reset();
  4567. },
  4568. /**
  4569. * Resets this hasher to its initial state.
  4570. *
  4571. * @example
  4572. *
  4573. * hasher.reset();
  4574. */
  4575. reset: function () {
  4576. // Reset data buffer
  4577. BufferedBlockAlgorithm.reset.call(this);
  4578. // Perform concrete-hasher logic
  4579. this._doReset();
  4580. },
  4581. /**
  4582. * Updates this hasher with a message.
  4583. *
  4584. * @param {WordArray|string} messageUpdate The message to append.
  4585. *
  4586. * @return {Hasher} This hasher.
  4587. *
  4588. * @example
  4589. *
  4590. * hasher.update('message');
  4591. * hasher.update(wordArray);
  4592. */
  4593. update: function (messageUpdate) {
  4594. // Append
  4595. this._append(messageUpdate);
  4596. // Update the hash
  4597. this._process();
  4598. // Chainable
  4599. return this;
  4600. },
  4601. /**
  4602. * Finalizes the hash computation.
  4603. * Note that the finalize operation is effectively a destructive, read-once operation.
  4604. *
  4605. * @param {WordArray|string} messageUpdate (Optional) A final message update.
  4606. *
  4607. * @return {WordArray} The hash.
  4608. *
  4609. * @example
  4610. *
  4611. * var hash = hasher.finalize();
  4612. * var hash = hasher.finalize('message');
  4613. * var hash = hasher.finalize(wordArray);
  4614. */
  4615. finalize: function (messageUpdate) {
  4616. // Final message update
  4617. if (messageUpdate) {
  4618. this._append(messageUpdate);
  4619. }
  4620. // Perform concrete-hasher logic
  4621. var hash = this._doFinalize();
  4622. return hash;
  4623. },
  4624. blockSize: 512/32,
  4625. /**
  4626. * Creates a shortcut function to a hasher's object interface.
  4627. *
  4628. * @param {Hasher} hasher The hasher to create a helper for.
  4629. *
  4630. * @return {Function} The shortcut function.
  4631. *
  4632. * @static
  4633. *
  4634. * @example
  4635. *
  4636. * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
  4637. */
  4638. _createHelper: function (hasher) {
  4639. return function (message, cfg) {
  4640. return new hasher.init(cfg).finalize(message);
  4641. };
  4642. },
  4643. /**
  4644. * Creates a shortcut function to the HMAC's object interface.
  4645. *
  4646. * @param {Hasher} hasher The hasher to use in this HMAC helper.
  4647. *
  4648. * @return {Function} The shortcut function.
  4649. *
  4650. * @static
  4651. *
  4652. * @example
  4653. *
  4654. * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
  4655. */
  4656. _createHmacHelper: function (hasher) {
  4657. return function (message, key) {
  4658. return new C_algo.HMAC.init(hasher, key).finalize(message);
  4659. };
  4660. }
  4661. });
  4662. /**
  4663. * Algorithm namespace.
  4664. */
  4665. var C_algo = C.algo = {};
  4666. return C;
  4667. }(Math));
  4668. return CryptoJS;
  4669. }));
  4670. /***/ }),
  4671. /* 22 */
  4672. /***/ (function(module, exports, __webpack_require__) {
  4673. "use strict";
  4674. Object.defineProperty(exports, "__esModule", { value: true });
  4675. var utils_1 = __webpack_require__(16);
  4676. /**
  4677. * When a UAS wishes to construct a response to a request, it follows
  4678. * the general procedures detailed in the following subsections.
  4679. * Additional behaviors specific to the response code in question, which
  4680. * are not detailed in this section, may also be required.
  4681. * https://tools.ietf.org/html/rfc3261#section-8.2.6
  4682. * @internal
  4683. */
  4684. function constructOutgoingResponse(message, options) {
  4685. var CRLF = "\r\n";
  4686. if (options.statusCode < 100 || options.statusCode > 699) {
  4687. throw new TypeError("Invalid statusCode: " + options.statusCode);
  4688. }
  4689. var reasonPhrase = options.reasonPhrase ? options.reasonPhrase : utils_1.getReasonPhrase(options.statusCode);
  4690. // SIP responses are distinguished from requests by having a Status-Line
  4691. // as their start-line. A Status-Line consists of the protocol version
  4692. // followed by a numeric Status-Code and its associated textual phrase,
  4693. // with each element separated by a single SP character.
  4694. // https://tools.ietf.org/html/rfc3261#section-7.2
  4695. var response = "SIP/2.0 " + options.statusCode + " " + reasonPhrase + CRLF;
  4696. // One largely non-method-specific guideline for the generation of
  4697. // responses is that UASs SHOULD NOT issue a provisional response for a
  4698. // non-INVITE request. Rather, UASs SHOULD generate a final response to
  4699. // a non-INVITE request as soon as possible.
  4700. // https://tools.ietf.org/html/rfc3261#section-8.2.6.1
  4701. if (options.statusCode >= 100 && options.statusCode < 200) {
  4702. // TODO
  4703. }
  4704. // When a 100 (Trying) response is generated, any Timestamp header field
  4705. // present in the request MUST be copied into this 100 (Trying)
  4706. // response. If there is a delay in generating the response, the UAS
  4707. // SHOULD add a delay value into the Timestamp value in the response.
  4708. // This value MUST contain the difference between the time of sending of
  4709. // the response and receipt of the request, measured in seconds.
  4710. // https://tools.ietf.org/html/rfc3261#section-8.2.6.1
  4711. if (options.statusCode === 100) {
  4712. // TODO
  4713. }
  4714. // The From field of the response MUST equal the From header field of
  4715. // the request. The Call-ID header field of the response MUST equal the
  4716. // Call-ID header field of the request. The CSeq header field of the
  4717. // response MUST equal the CSeq field of the request. The Via header
  4718. // field values in the response MUST equal the Via header field values
  4719. // in the request and MUST maintain the same ordering.
  4720. // https://tools.ietf.org/html/rfc3261#section-8.2.6.2
  4721. var fromHeader = "From: " + message.getHeader("From") + CRLF;
  4722. var callIdHeader = "Call-ID: " + message.callId + CRLF;
  4723. var cSeqHeader = "CSeq: " + message.cseq + " " + message.method + CRLF;
  4724. var viaHeaders = message.getHeaders("via").reduce(function (previous, current) {
  4725. return previous + "Via: " + current + CRLF;
  4726. }, "");
  4727. // If a request contained a To tag in the request, the To header field
  4728. // in the response MUST equal that of the request. However, if the To
  4729. // header field in the request did not contain a tag, the URI in the To
  4730. // header field in the response MUST equal the URI in the To header
  4731. // field; additionally, the UAS MUST add a tag to the To header field in
  4732. // the response (with the exception of the 100 (Trying) response, in
  4733. // which a tag MAY be present). This serves to identify the UAS that is
  4734. // responding, possibly resulting in a component of a dialog ID. The
  4735. // same tag MUST be used for all responses to that request, both final
  4736. // and provisional (again excepting the 100 (Trying)).
  4737. // https://tools.ietf.org/html/rfc3261#section-8.2.6.2
  4738. var toHeader = "To: " + message.getHeader("to");
  4739. if (options.statusCode > 100 && !message.parseHeader("to").hasParam("tag")) {
  4740. var toTag = options.toTag;
  4741. if (!toTag) {
  4742. // Stateless UAS Behavior...
  4743. // o To header tags MUST be generated for responses in a stateless
  4744. // manner - in a manner that will generate the same tag for the
  4745. // same request consistently. For information on tag construction
  4746. // see Section 19.3.
  4747. // https://tools.ietf.org/html/rfc3261#section-8.2.7
  4748. toTag = utils_1.newTag(); // FIXME: newTag() currently generates random tags
  4749. }
  4750. toHeader += ";tag=" + toTag;
  4751. }
  4752. toHeader += CRLF;
  4753. // FIXME: TODO: needs review... moved to InviteUserAgentServer (as it is specific to that)
  4754. // let recordRouteHeaders = "";
  4755. // if (request.method === C.INVITE && statusCode > 100 && statusCode <= 200) {
  4756. // recordRouteHeaders = request.getHeaders("record-route").reduce((previous, current) => {
  4757. // return previous + "Record-Route: " + current + CRLF;
  4758. // }, "");
  4759. // }
  4760. // FIXME: TODO: needs review...
  4761. var supportedHeader = "";
  4762. if (options.supported) {
  4763. supportedHeader = "Supported: " + options.supported.join(", ") + CRLF;
  4764. }
  4765. // FIXME: TODO: needs review...
  4766. var userAgentHeader = "";
  4767. if (options.userAgent) {
  4768. userAgentHeader = "User-Agent: " + options.userAgent + CRLF;
  4769. }
  4770. var extensionHeaders = "";
  4771. if (options.extraHeaders) {
  4772. extensionHeaders = options.extraHeaders.reduce(function (previous, current) {
  4773. return previous + current.trim() + CRLF;
  4774. }, "");
  4775. }
  4776. // The relative order of header fields with different field names is not
  4777. // significant. However, it is RECOMMENDED that header fields which are
  4778. // needed for proxy processing (Via, Route, Record-Route, Proxy-Require,
  4779. // Max-Forwards, and Proxy-Authorization, for example) appear towards
  4780. // the top of the message to facilitate rapid parsing.
  4781. // https://tools.ietf.org/html/rfc3261#section-7.3.1
  4782. // response += recordRouteHeaders;
  4783. response += viaHeaders;
  4784. response += fromHeader;
  4785. response += toHeader;
  4786. response += cSeqHeader;
  4787. response += callIdHeader;
  4788. response += supportedHeader;
  4789. response += userAgentHeader;
  4790. response += extensionHeaders;
  4791. if (options.body) {
  4792. response += "Content-Type: " + options.body.contentType + CRLF;
  4793. response += "Content-Length: " + utils_1.str_utf8_length(options.body.content) + CRLF + CRLF;
  4794. response += options.body.content;
  4795. }
  4796. else {
  4797. response += "Content-Length: " + 0 + CRLF + CRLF;
  4798. }
  4799. return { message: response };
  4800. }
  4801. exports.constructOutgoingResponse = constructOutgoingResponse;
  4802. /***/ }),
  4803. /* 23 */
  4804. /***/ (function(module, exports, __webpack_require__) {
  4805. "use strict";
  4806. Object.defineProperty(exports, "__esModule", { value: true });
  4807. var tslib_1 = __webpack_require__(1);
  4808. var messages_1 = __webpack_require__(5);
  4809. var session_1 = __webpack_require__(24);
  4810. var timers_1 = __webpack_require__(26);
  4811. var transactions_1 = __webpack_require__(27);
  4812. var bye_user_agent_client_1 = __webpack_require__(41);
  4813. var bye_user_agent_server_1 = __webpack_require__(43);
  4814. var info_user_agent_client_1 = __webpack_require__(45);
  4815. var info_user_agent_server_1 = __webpack_require__(46);
  4816. var notify_user_agent_client_1 = __webpack_require__(47);
  4817. var notify_user_agent_server_1 = __webpack_require__(48);
  4818. var prack_user_agent_client_1 = __webpack_require__(49);
  4819. var prack_user_agent_server_1 = __webpack_require__(50);
  4820. var re_invite_user_agent_client_1 = __webpack_require__(51);
  4821. var re_invite_user_agent_server_1 = __webpack_require__(52);
  4822. var refer_user_agent_client_1 = __webpack_require__(53);
  4823. var refer_user_agent_server_1 = __webpack_require__(54);
  4824. var dialog_1 = __webpack_require__(4);
  4825. /**
  4826. * Session Dialog.
  4827. * @public
  4828. */
  4829. var SessionDialog = /** @class */ (function (_super) {
  4830. tslib_1.__extends(SessionDialog, _super);
  4831. function SessionDialog(initialTransaction, core, state, delegate) {
  4832. var _this = _super.call(this, core, state) || this;
  4833. _this.initialTransaction = initialTransaction;
  4834. /** The state of the offer/answer exchange. */
  4835. _this._signalingState = session_1.SignalingState.Initial;
  4836. /** True if waiting for an ACK to the initial transaction 2xx (UAS only). */
  4837. _this.ackWait = false;
  4838. _this.delegate = delegate;
  4839. if (initialTransaction instanceof transactions_1.InviteServerTransaction) {
  4840. // If we're created by an invite server transaction, we're
  4841. // going to be waiting for an ACK if are to be confirmed.
  4842. _this.ackWait = true;
  4843. }
  4844. // If we're confirmed upon creation start the retransmitting whatever
  4845. // the 2xx final response was that confirmed us into existence.
  4846. if (!_this.early) {
  4847. _this.start2xxRetransmissionTimer();
  4848. }
  4849. _this.signalingStateTransition(initialTransaction.request);
  4850. _this.logger = core.loggerFactory.getLogger("sip.invite-dialog");
  4851. _this.logger.log("INVITE dialog " + _this.id + " constructed");
  4852. return _this;
  4853. }
  4854. SessionDialog.prototype.dispose = function () {
  4855. _super.prototype.dispose.call(this);
  4856. this._signalingState = session_1.SignalingState.Closed;
  4857. this._offer = undefined;
  4858. this._answer = undefined;
  4859. if (this.invite2xxTimer) {
  4860. clearTimeout(this.invite2xxTimer);
  4861. this.invite2xxTimer = undefined;
  4862. }
  4863. // The UAS MUST still respond to any pending requests received for that
  4864. // dialog. It is RECOMMENDED that a 487 (Request Terminated) response
  4865. // be generated to those pending requests.
  4866. // https://tools.ietf.org/html/rfc3261#section-15.1.2
  4867. // TODO:
  4868. // this.userAgentServers.forEach((uas) => uas.reply(487));
  4869. this.logger.log("INVITE dialog " + this.id + " destroyed");
  4870. };
  4871. Object.defineProperty(SessionDialog.prototype, "sessionState", {
  4872. // FIXME: Need real state machine
  4873. get: function () {
  4874. if (this.early) {
  4875. return session_1.SessionState.Early;
  4876. }
  4877. else if (this.ackWait) {
  4878. return session_1.SessionState.AckWait;
  4879. }
  4880. else if (this._signalingState === session_1.SignalingState.Closed) {
  4881. return session_1.SessionState.Terminated;
  4882. }
  4883. else {
  4884. return session_1.SessionState.Confirmed;
  4885. }
  4886. },
  4887. enumerable: true,
  4888. configurable: true
  4889. });
  4890. Object.defineProperty(SessionDialog.prototype, "signalingState", {
  4891. /** The state of the offer/answer exchange. */
  4892. get: function () {
  4893. return this._signalingState;
  4894. },
  4895. enumerable: true,
  4896. configurable: true
  4897. });
  4898. Object.defineProperty(SessionDialog.prototype, "offer", {
  4899. /** The current offer. Undefined unless signaling state HaveLocalOffer, HaveRemoteOffer, of Stable. */
  4900. get: function () {
  4901. return this._offer;
  4902. },
  4903. enumerable: true,
  4904. configurable: true
  4905. });
  4906. Object.defineProperty(SessionDialog.prototype, "answer", {
  4907. /** The current answer. Undefined unless signaling state Stable. */
  4908. get: function () {
  4909. return this._answer;
  4910. },
  4911. enumerable: true,
  4912. configurable: true
  4913. });
  4914. /** Confirm the dialog. Only matters if dialog is currently early. */
  4915. SessionDialog.prototype.confirm = function () {
  4916. // When we're confirmed start the retransmitting whatever
  4917. // the 2xx final response that may have confirmed us.
  4918. if (this.early) {
  4919. this.start2xxRetransmissionTimer();
  4920. }
  4921. _super.prototype.confirm.call(this);
  4922. };
  4923. /** Re-confirm the dialog. Only matters if handling re-INVITE request. */
  4924. SessionDialog.prototype.reConfirm = function () {
  4925. // When we're confirmed start the retransmitting whatever
  4926. // the 2xx final response that may have confirmed us.
  4927. if (this.reinviteUserAgentServer) {
  4928. this.startReInvite2xxRetransmissionTimer();
  4929. }
  4930. };
  4931. /**
  4932. * The UAC core MUST generate an ACK request for each 2xx received from
  4933. * the transaction layer. The header fields of the ACK are constructed
  4934. * in the same way as for any request sent within a dialog (see Section
  4935. * 12) with the exception of the CSeq and the header fields related to
  4936. * authentication. The sequence number of the CSeq header field MUST be
  4937. * the same as the INVITE being acknowledged, but the CSeq method MUST
  4938. * be ACK. The ACK MUST contain the same credentials as the INVITE. If
  4939. * the 2xx contains an offer (based on the rules above), the ACK MUST
  4940. * carry an answer in its body. If the offer in the 2xx response is not
  4941. * acceptable, the UAC core MUST generate a valid answer in the ACK and
  4942. * then send a BYE immediately.
  4943. * https://tools.ietf.org/html/rfc3261#section-13.2.2.4
  4944. * @param options - ACK options bucket.
  4945. */
  4946. SessionDialog.prototype.ack = function (options) {
  4947. if (options === void 0) { options = {}; }
  4948. this.logger.log("INVITE dialog " + this.id + " sending ACK request");
  4949. var transaction;
  4950. if (this.reinviteUserAgentClient) {
  4951. // We're sending ACK for a re-INVITE
  4952. if (!(this.reinviteUserAgentClient.transaction instanceof transactions_1.InviteClientTransaction)) {
  4953. throw new Error("Transaction not instance of InviteClientTransaction.");
  4954. }
  4955. transaction = this.reinviteUserAgentClient.transaction;
  4956. this.reinviteUserAgentClient = undefined;
  4957. }
  4958. else {
  4959. // We're sending ACK for the initial INVITE
  4960. if (!(this.initialTransaction instanceof transactions_1.InviteClientTransaction)) {
  4961. throw new Error("Initial transaction not instance of InviteClientTransaction.");
  4962. }
  4963. transaction = this.initialTransaction;
  4964. }
  4965. options.cseq = transaction.request.cseq; // ACK cseq is INVITE cseq
  4966. var message = this.createOutgoingRequestMessage(messages_1.C.ACK, options);
  4967. transaction.ackResponse(message); // See InviteClientTransaction for details.
  4968. this.signalingStateTransition(message);
  4969. return { message: message };
  4970. };
  4971. /**
  4972. * Terminating a Session
  4973. *
  4974. * This section describes the procedures for terminating a session
  4975. * established by SIP. The state of the session and the state of the
  4976. * dialog are very closely related. When a session is initiated with an
  4977. * INVITE, each 1xx or 2xx response from a distinct UAS creates a
  4978. * dialog, and if that response completes the offer/answer exchange, it
  4979. * also creates a session. As a result, each session is "associated"
  4980. * with a single dialog - the one which resulted in its creation. If an
  4981. * initial INVITE generates a non-2xx final response, that terminates
  4982. * all sessions (if any) and all dialogs (if any) that were created
  4983. * through responses to the request. By virtue of completing the
  4984. * transaction, a non-2xx final response also prevents further sessions
  4985. * from being created as a result of the INVITE. The BYE request is
  4986. * used to terminate a specific session or attempted session. In this
  4987. * case, the specific session is the one with the peer UA on the other
  4988. * side of the dialog. When a BYE is received on a dialog, any session
  4989. * associated with that dialog SHOULD terminate. A UA MUST NOT send a
  4990. * BYE outside of a dialog. The caller's UA MAY send a BYE for either
  4991. * confirmed or early dialogs, and the callee's UA MAY send a BYE on
  4992. * confirmed dialogs, but MUST NOT send a BYE on early dialogs.
  4993. *
  4994. * However, the callee's UA MUST NOT send a BYE on a confirmed dialog
  4995. * until it has received an ACK for its 2xx response or until the server
  4996. * transaction times out. If no SIP extensions have defined other
  4997. * application layer states associated with the dialog, the BYE also
  4998. * terminates the dialog.
  4999. *
  5000. * https://tools.ietf.org/html/rfc3261#section-15
  5001. * FIXME: Make these proper Exceptions...
  5002. * @param options - BYE options bucket.
  5003. * @returns
  5004. * Throws `Error` if callee's UA attempts a BYE on an early dialog.
  5005. * Throws `Error` if callee's UA attempts a BYE on a confirmed dialog
  5006. * while it's waiting on the ACK for its 2xx response.
  5007. */
  5008. SessionDialog.prototype.bye = function (delegate, options) {
  5009. this.logger.log("INVITE dialog " + this.id + " sending BYE request");
  5010. // The caller's UA MAY send a BYE for either
  5011. // confirmed or early dialogs, and the callee's UA MAY send a BYE on
  5012. // confirmed dialogs, but MUST NOT send a BYE on early dialogs.
  5013. //
  5014. // However, the callee's UA MUST NOT send a BYE on a confirmed dialog
  5015. // until it has received an ACK for its 2xx response or until the server
  5016. // transaction times out.
  5017. // https://tools.ietf.org/html/rfc3261#section-15
  5018. if (this.initialTransaction instanceof transactions_1.InviteServerTransaction) {
  5019. if (this.early) {
  5020. // FIXME: TODO: This should throw a proper exception.
  5021. throw new Error("UAS MUST NOT send a BYE on early dialogs.");
  5022. }
  5023. if (this.ackWait && this.initialTransaction.state !== transactions_1.TransactionState.Terminated) {
  5024. // FIXME: TODO: This should throw a proper exception.
  5025. throw new Error("UAS MUST NOT send a BYE on a confirmed dialog " +
  5026. "until it has received an ACK for its 2xx response " +
  5027. "or until the server transaction times out.");
  5028. }
  5029. }
  5030. // A BYE request is constructed as would any other request within a
  5031. // dialog, as described in Section 12.
  5032. //
  5033. // Once the BYE is constructed, the UAC core creates a new non-INVITE
  5034. // client transaction, and passes it the BYE request. The UAC MUST
  5035. // consider the session terminated (and therefore stop sending or
  5036. // listening for media) as soon as the BYE request is passed to the
  5037. // client transaction. If the response for the BYE is a 481
  5038. // (Call/Transaction Does Not Exist) or a 408 (Request Timeout) or no
  5039. // response at all is received for the BYE (that is, a timeout is
  5040. // returned by the client transaction), the UAC MUST consider the
  5041. // session and the dialog terminated.
  5042. // https://tools.ietf.org/html/rfc3261#section-15.1.1
  5043. return new bye_user_agent_client_1.ByeUserAgentClient(this, delegate, options);
  5044. };
  5045. /**
  5046. * An INFO request can be associated with an Info Package (see
  5047. * Section 5), or associated with a legacy INFO usage (see Section 2).
  5048. *
  5049. * The construction of the INFO request is the same as any other
  5050. * non-target refresh request within an existing invite dialog usage as
  5051. * described in Section 12.2 of RFC 3261.
  5052. * https://tools.ietf.org/html/rfc6086#section-4.2.1
  5053. * @param options - Options bucket.
  5054. */
  5055. SessionDialog.prototype.info = function (delegate, options) {
  5056. this.logger.log("INVITE dialog " + this.id + " sending INFO request");
  5057. if (this.early) {
  5058. // FIXME: TODO: This should throw a proper exception.
  5059. throw new Error("Dialog not confirmed.");
  5060. }
  5061. return new info_user_agent_client_1.InfoUserAgentClient(this, delegate, options);
  5062. };
  5063. /**
  5064. * Modifying an Existing Session
  5065. *
  5066. * A successful INVITE request (see Section 13) establishes both a
  5067. * dialog between two user agents and a session using the offer-answer
  5068. * model. Section 12 explains how to modify an existing dialog using a
  5069. * target refresh request (for example, changing the remote target URI
  5070. * of the dialog). This section describes how to modify the actual
  5071. * session. This modification can involve changing addresses or ports,
  5072. * adding a media stream, deleting a media stream, and so on. This is
  5073. * accomplished by sending a new INVITE request within the same dialog
  5074. * that established the session. An INVITE request sent within an
  5075. * existing dialog is known as a re-INVITE.
  5076. *
  5077. * Note that a single re-INVITE can modify the dialog and the
  5078. * parameters of the session at the same time.
  5079. *
  5080. * Either the caller or callee can modify an existing session.
  5081. * https://tools.ietf.org/html/rfc3261#section-14
  5082. * @param options - Options bucket
  5083. */
  5084. SessionDialog.prototype.invite = function (delegate, options) {
  5085. this.logger.log("INVITE dialog " + this.id + " sending INVITE request");
  5086. if (this.early) {
  5087. // FIXME: TODO: This should throw a proper exception.
  5088. throw new Error("Dialog not confirmed.");
  5089. }
  5090. // Note that a UAC MUST NOT initiate a new INVITE transaction within a
  5091. // dialog while another INVITE transaction is in progress in either
  5092. // direction.
  5093. //
  5094. // 1. If there is an ongoing INVITE client transaction, the TU MUST
  5095. // wait until the transaction reaches the completed or terminated
  5096. // state before initiating the new INVITE.
  5097. //
  5098. // 2. If there is an ongoing INVITE server transaction, the TU MUST
  5099. // wait until the transaction reaches the confirmed or terminated
  5100. // state before initiating the new INVITE.
  5101. //
  5102. // However, a UA MAY initiate a regular transaction while an INVITE
  5103. // transaction is in progress. A UA MAY also initiate an INVITE
  5104. // transaction while a regular transaction is in progress.
  5105. // https://tools.ietf.org/html/rfc3261#section-14.1
  5106. if (this.reinviteUserAgentClient) {
  5107. // FIXME: TODO: This should throw a proper exception.
  5108. throw new Error("There is an ongoing re-INVITE client transaction.");
  5109. }
  5110. if (this.reinviteUserAgentServer) {
  5111. // FIXME: TODO: This should throw a proper exception.
  5112. throw new Error("There is an ongoing re-INVITE server transaction.");
  5113. }
  5114. return new re_invite_user_agent_client_1.ReInviteUserAgentClient(this, delegate, options);
  5115. };
  5116. /**
  5117. * The NOTIFY mechanism defined in [2] MUST be used to inform the agent
  5118. * sending the REFER of the status of the reference.
  5119. * https://tools.ietf.org/html/rfc3515#section-2.4.4
  5120. * @param options - Options bucket.
  5121. */
  5122. SessionDialog.prototype.notify = function (delegate, options) {
  5123. this.logger.log("INVITE dialog " + this.id + " sending NOTIFY request");
  5124. if (this.early) {
  5125. // FIXME: TODO: This should throw a proper exception.
  5126. throw new Error("Dialog not confirmed.");
  5127. }
  5128. return new notify_user_agent_client_1.NotifyUserAgentClient(this, delegate, options);
  5129. };
  5130. /**
  5131. * Assuming the response is to be transmitted reliably, the UAC MUST
  5132. * create a new request with method PRACK. This request is sent within
  5133. * the dialog associated with the provisional response (indeed, the
  5134. * provisional response may have created the dialog). PRACK requests
  5135. * MAY contain bodies, which are interpreted according to their type and
  5136. * disposition.
  5137. * https://tools.ietf.org/html/rfc3262#section-4
  5138. * @param options - Options bucket.
  5139. */
  5140. SessionDialog.prototype.prack = function (delegate, options) {
  5141. this.logger.log("INVITE dialog " + this.id + " sending PRACK request");
  5142. return new prack_user_agent_client_1.PrackUserAgentClient(this, delegate, options);
  5143. };
  5144. /**
  5145. * REFER is a SIP request and is constructed as defined in [1]. A REFER
  5146. * request MUST contain exactly one Refer-To header field value.
  5147. * https://tools.ietf.org/html/rfc3515#section-2.4.1
  5148. * @param options - Options bucket.
  5149. */
  5150. SessionDialog.prototype.refer = function (delegate, options) {
  5151. this.logger.log("INVITE dialog " + this.id + " sending REFER request");
  5152. if (this.early) {
  5153. // FIXME: TODO: This should throw a proper exception.
  5154. throw new Error("Dialog not confirmed.");
  5155. }
  5156. // FIXME: TODO: Validate Refer-To header field value.
  5157. return new refer_user_agent_client_1.ReferUserAgentClient(this, delegate, options);
  5158. };
  5159. /**
  5160. * Requests sent within a dialog, as any other requests, are atomic. If
  5161. * a particular request is accepted by the UAS, all the state changes
  5162. * associated with it are performed. If the request is rejected, none
  5163. * of the state changes are performed.
  5164. * https://tools.ietf.org/html/rfc3261#section-12.2.2
  5165. * @param message - Incoming request message within this dialog.
  5166. */
  5167. SessionDialog.prototype.receiveRequest = function (message) {
  5168. this.logger.log("INVITE dialog " + this.id + " received " + message.method + " request");
  5169. // Response retransmissions cease when an ACK request for the
  5170. // response is received. This is independent of whatever transport
  5171. // protocols are used to send the response.
  5172. // https://tools.ietf.org/html/rfc6026#section-8.1
  5173. if (message.method === messages_1.C.ACK) {
  5174. // If ackWait is true, then this is the ACK to the initial INVITE,
  5175. // otherwise this is an ACK to an in dialog INVITE. In either case,
  5176. // guard to make sure the sequence number of the ACK matches the INVITE.
  5177. if (this.ackWait) {
  5178. if (this.initialTransaction instanceof transactions_1.InviteClientTransaction) {
  5179. this.logger.warn("INVITE dialog " + this.id + " received unexpected " + message.method + " request, dropping.");
  5180. return;
  5181. }
  5182. if (this.initialTransaction.request.cseq !== message.cseq) {
  5183. this.logger.warn("INVITE dialog " + this.id + " received unexpected " + message.method + " request, dropping.");
  5184. return;
  5185. }
  5186. // Update before the delegate has a chance to handle the
  5187. // message as delegate may callback into this dialog.
  5188. this.ackWait = false;
  5189. }
  5190. else {
  5191. if (!this.reinviteUserAgentServer) {
  5192. this.logger.warn("INVITE dialog " + this.id + " received unexpected " + message.method + " request, dropping.");
  5193. return;
  5194. }
  5195. if (this.reinviteUserAgentServer.transaction.request.cseq !== message.cseq) {
  5196. this.logger.warn("INVITE dialog " + this.id + " received unexpected " + message.method + " request, dropping.");
  5197. return;
  5198. }
  5199. this.reinviteUserAgentServer = undefined;
  5200. }
  5201. this.signalingStateTransition(message);
  5202. if (this.delegate && this.delegate.onAck) {
  5203. this.delegate.onAck({ message: message });
  5204. }
  5205. return;
  5206. }
  5207. // Request within a dialog out of sequence guard.
  5208. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  5209. if (!this.sequenceGuard(message)) {
  5210. this.logger.log("INVITE dialog " + this.id + " rejected out of order " + message.method + " request.");
  5211. return;
  5212. }
  5213. if (message.method === messages_1.C.INVITE) {
  5214. // A UAS that receives a second INVITE before it sends the final
  5215. // response to a first INVITE with a lower CSeq sequence number on the
  5216. // same dialog MUST return a 500 (Server Internal Error) response to the
  5217. // second INVITE and MUST include a Retry-After header field with a
  5218. // randomly chosen value of between 0 and 10 seconds.
  5219. // https://tools.ietf.org/html/rfc3261#section-14.2
  5220. if (this.reinviteUserAgentServer) {
  5221. // https://tools.ietf.org/html/rfc3261#section-20.33
  5222. var retryAfter = Math.floor((Math.random() * 10)) + 1;
  5223. var extraHeaders = ["Retry-After: " + retryAfter];
  5224. this.core.replyStateless(message, { statusCode: 500, extraHeaders: extraHeaders });
  5225. return;
  5226. }
  5227. // A UAS that receives an INVITE on a dialog while an INVITE it had sent
  5228. // on that dialog is in progress MUST return a 491 (Request Pending)
  5229. // response to the received INVITE.
  5230. // https://tools.ietf.org/html/rfc3261#section-14.2
  5231. if (this.reinviteUserAgentClient) {
  5232. this.core.replyStateless(message, { statusCode: 491 });
  5233. return;
  5234. }
  5235. }
  5236. // Request within a dialog common processing.
  5237. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  5238. _super.prototype.receiveRequest.call(this, message);
  5239. // Requests within a dialog MAY contain Record-Route and Contact header
  5240. // fields. However, these requests do not cause the dialog's route set
  5241. // to be modified, although they may modify the remote target URI.
  5242. // Specifically, requests that are not target refresh requests do not
  5243. // modify the dialog's remote target URI, and requests that are target
  5244. // refresh requests do. For dialogs that have been established with an
  5245. // INVITE, the only target refresh request defined is re-INVITE (see
  5246. // Section 14). Other extensions may define different target refresh
  5247. // requests for dialogs established in other ways.
  5248. //
  5249. // Note that an ACK is NOT a target refresh request.
  5250. //
  5251. // Target refresh requests only update the dialog's remote target URI,
  5252. // and not the route set formed from the Record-Route. Updating the
  5253. // latter would introduce severe backwards compatibility problems with
  5254. // RFC 2543-compliant systems.
  5255. // https://tools.ietf.org/html/rfc3261#section-15
  5256. if (message.method === messages_1.C.INVITE) {
  5257. // FIXME: parser needs to be typed...
  5258. var contact = message.parseHeader("contact");
  5259. if (!contact) { // TODO: Review to make sure this will never happen
  5260. throw new Error("Contact undefined.");
  5261. }
  5262. if (!(contact instanceof messages_1.NameAddrHeader)) {
  5263. throw new Error("Contact not instance of NameAddrHeader.");
  5264. }
  5265. this.dialogState.remoteTarget = contact.uri;
  5266. }
  5267. // Switch on method and then delegate.
  5268. switch (message.method) {
  5269. case messages_1.C.BYE:
  5270. // A UAS core receiving a BYE request for an existing dialog MUST follow
  5271. // the procedures of Section 12.2.2 to process the request. Once done,
  5272. // the UAS SHOULD terminate the session (and therefore stop sending and
  5273. // listening for media). The only case where it can elect not to are
  5274. // multicast sessions, where participation is possible even if the other
  5275. // participant in the dialog has terminated its involvement in the
  5276. // session. Whether or not it ends its participation on the session,
  5277. // the UAS core MUST generate a 2xx response to the BYE, and MUST pass
  5278. // that to the server transaction for transmission.
  5279. //
  5280. // The UAS MUST still respond to any pending requests received for that
  5281. // dialog. It is RECOMMENDED that a 487 (Request Terminated) response
  5282. // be generated to those pending requests.
  5283. // https://tools.ietf.org/html/rfc3261#section-15.1.2
  5284. {
  5285. var uas = new bye_user_agent_server_1.ByeUserAgentServer(this, message);
  5286. this.delegate && this.delegate.onBye ?
  5287. this.delegate.onBye(uas) :
  5288. uas.accept();
  5289. this.dispose();
  5290. }
  5291. break;
  5292. case messages_1.C.INFO:
  5293. // If a UA receives an INFO request associated with an Info Package that
  5294. // the UA has not indicated willingness to receive, the UA MUST send a
  5295. // 469 (Bad Info Package) response (see Section 11.6), which contains a
  5296. // Recv-Info header field with Info Packages for which the UA is willing
  5297. // to receive INFO requests.
  5298. {
  5299. var uas = new info_user_agent_server_1.InfoUserAgentServer(this, message);
  5300. this.delegate && this.delegate.onInfo ?
  5301. this.delegate.onInfo(uas) :
  5302. uas.reject({
  5303. statusCode: 469,
  5304. extraHeaders: ["Recv-Info :"]
  5305. });
  5306. }
  5307. break;
  5308. case messages_1.C.INVITE:
  5309. // If the new session description is not acceptable, the UAS can reject
  5310. // it by returning a 488 (Not Acceptable Here) response for the re-
  5311. // INVITE. This response SHOULD include a Warning header field.
  5312. // https://tools.ietf.org/html/rfc3261#section-14.2
  5313. {
  5314. var uas = new re_invite_user_agent_server_1.ReInviteUserAgentServer(this, message);
  5315. this.signalingStateTransition(message);
  5316. this.delegate && this.delegate.onInvite ?
  5317. this.delegate.onInvite(uas) :
  5318. uas.reject({ statusCode: 488 }); // TODO: Warning header field.
  5319. }
  5320. break;
  5321. case messages_1.C.NOTIFY:
  5322. // https://tools.ietf.org/html/rfc3515#section-2.4.4
  5323. {
  5324. var uas = new notify_user_agent_server_1.NotifyUserAgentServer(this, message);
  5325. this.delegate && this.delegate.onNotify ?
  5326. this.delegate.onNotify(uas) :
  5327. uas.accept();
  5328. }
  5329. break;
  5330. case messages_1.C.PRACK:
  5331. // https://tools.ietf.org/html/rfc3262#section-4
  5332. {
  5333. var uas = new prack_user_agent_server_1.PrackUserAgentServer(this, message);
  5334. this.delegate && this.delegate.onPrack ?
  5335. this.delegate.onPrack(uas) :
  5336. uas.accept();
  5337. }
  5338. break;
  5339. case messages_1.C.REFER:
  5340. // https://tools.ietf.org/html/rfc3515#section-2.4.2
  5341. {
  5342. var uas = new refer_user_agent_server_1.ReferUserAgentServer(this, message);
  5343. this.delegate && this.delegate.onRefer ?
  5344. this.delegate.onRefer(uas) :
  5345. uas.reject();
  5346. }
  5347. break;
  5348. default:
  5349. {
  5350. this.logger.log("INVITE dialog " + this.id + " received unimplemented " + message.method + " request");
  5351. this.core.replyStateless(message, { statusCode: 501 });
  5352. }
  5353. break;
  5354. }
  5355. };
  5356. SessionDialog.prototype.reliableSequenceGuard = function (message) {
  5357. var statusCode = message.statusCode;
  5358. if (!statusCode) {
  5359. throw new Error("Status code undefined");
  5360. }
  5361. if (statusCode > 100 && statusCode < 200) {
  5362. // If a provisional response is received for an initial request, and
  5363. // that response contains a Require header field containing the option
  5364. // tag 100rel, the response is to be sent reliably. If the response is
  5365. // a 100 (Trying) (as opposed to 101 to 199), this option tag MUST be
  5366. // ignored, and the procedures below MUST NOT be used.
  5367. // https://tools.ietf.org/html/rfc3262#section-4
  5368. var requireHeader = message.getHeader("require");
  5369. var rseqHeader = message.getHeader("rseq");
  5370. var rseq = requireHeader && requireHeader.includes("100rel") && rseqHeader ? Number(rseqHeader) : undefined;
  5371. if (rseq) {
  5372. // Handling of subsequent reliable provisional responses for the same
  5373. // initial request follows the same rules as above, with the following
  5374. // difference: reliable provisional responses are guaranteed to be in
  5375. // order. As a result, if the UAC receives another reliable provisional
  5376. // response to the same request, and its RSeq value is not one higher
  5377. // than the value of the sequence number, that response MUST NOT be
  5378. // acknowledged with a PRACK, and MUST NOT be processed further by the
  5379. // UAC. An implementation MAY discard the response, or MAY cache the
  5380. // response in the hopes of receiving the missing responses.
  5381. // https://tools.ietf.org/html/rfc3262#section-4
  5382. if (this.rseq && this.rseq + 1 !== rseq) {
  5383. return false;
  5384. }
  5385. // Once a reliable provisional response is received, retransmissions of
  5386. // that response MUST be discarded. A response is a retransmission when
  5387. // its dialog ID, CSeq, and RSeq match the original response. The UAC
  5388. // MUST maintain a sequence number that indicates the most recently
  5389. // received in-order reliable provisional response for the initial
  5390. // request. This sequence number MUST be maintained until a final
  5391. // response is received for the initial request. Its value MUST be
  5392. // initialized to the RSeq header field in the first reliable
  5393. // provisional response received for the initial request.
  5394. // https://tools.ietf.org/html/rfc3262#section-4
  5395. if (!this.rseq) {
  5396. this.rseq = rseq;
  5397. }
  5398. }
  5399. }
  5400. return true;
  5401. };
  5402. /**
  5403. * If not in a stable signaling state, rollback to prior stable signaling state.
  5404. */
  5405. SessionDialog.prototype.signalingStateRollback = function () {
  5406. if (this._signalingState === session_1.SignalingState.HaveLocalOffer ||
  5407. this.signalingState === session_1.SignalingState.HaveRemoteOffer) {
  5408. if (this._rollbackOffer && this._rollbackAnswer) {
  5409. this._signalingState = session_1.SignalingState.Stable;
  5410. this._offer = this._rollbackOffer;
  5411. this._answer = this._rollbackAnswer;
  5412. }
  5413. }
  5414. };
  5415. /**
  5416. * Update the signaling state of the dialog.
  5417. * @param message - The message to base the update off of.
  5418. */
  5419. SessionDialog.prototype.signalingStateTransition = function (message) {
  5420. var body = messages_1.getBody(message);
  5421. // No body, no session. No, woman, no cry.
  5422. if (!body || body.contentDisposition !== "session") {
  5423. return;
  5424. }
  5425. // We've got an existing offer and answer which we may wish to rollback to
  5426. if (this._signalingState === session_1.SignalingState.Stable) {
  5427. this._rollbackOffer = this._offer;
  5428. this._rollbackAnswer = this._answer;
  5429. }
  5430. // We're in UAS role, receiving incoming request with session description
  5431. if (message instanceof messages_1.IncomingRequestMessage) {
  5432. switch (this._signalingState) {
  5433. case session_1.SignalingState.Initial:
  5434. case session_1.SignalingState.Stable:
  5435. this._signalingState = session_1.SignalingState.HaveRemoteOffer;
  5436. this._offer = body;
  5437. this._answer = undefined;
  5438. break;
  5439. case session_1.SignalingState.HaveLocalOffer:
  5440. this._signalingState = session_1.SignalingState.Stable;
  5441. this._answer = body;
  5442. break;
  5443. case session_1.SignalingState.HaveRemoteOffer:
  5444. // You cannot make a new offer while one is in progress.
  5445. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  5446. // FIXME: What to do here?
  5447. break;
  5448. case session_1.SignalingState.Closed:
  5449. break;
  5450. default:
  5451. throw new Error("Unexpected signaling state.");
  5452. }
  5453. }
  5454. // We're in UAC role, receiving incoming response with session description
  5455. if (message instanceof messages_1.IncomingResponseMessage) {
  5456. switch (this._signalingState) {
  5457. case session_1.SignalingState.Initial:
  5458. case session_1.SignalingState.Stable:
  5459. this._signalingState = session_1.SignalingState.HaveRemoteOffer;
  5460. this._offer = body;
  5461. this._answer = undefined;
  5462. break;
  5463. case session_1.SignalingState.HaveLocalOffer:
  5464. this._signalingState = session_1.SignalingState.Stable;
  5465. this._answer = body;
  5466. break;
  5467. case session_1.SignalingState.HaveRemoteOffer:
  5468. // You cannot make a new offer while one is in progress.
  5469. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  5470. // FIXME: What to do here?
  5471. break;
  5472. case session_1.SignalingState.Closed:
  5473. break;
  5474. default:
  5475. throw new Error("Unexpected signaling state.");
  5476. }
  5477. }
  5478. // We're in UAC role, sending outgoing request with session description
  5479. if (message instanceof messages_1.OutgoingRequestMessage) {
  5480. switch (this._signalingState) {
  5481. case session_1.SignalingState.Initial:
  5482. case session_1.SignalingState.Stable:
  5483. this._signalingState = session_1.SignalingState.HaveLocalOffer;
  5484. this._offer = body;
  5485. this._answer = undefined;
  5486. break;
  5487. case session_1.SignalingState.HaveLocalOffer:
  5488. // You cannot make a new offer while one is in progress.
  5489. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  5490. // FIXME: What to do here?
  5491. break;
  5492. case session_1.SignalingState.HaveRemoteOffer:
  5493. this._signalingState = session_1.SignalingState.Stable;
  5494. this._answer = body;
  5495. break;
  5496. case session_1.SignalingState.Closed:
  5497. break;
  5498. default:
  5499. throw new Error("Unexpected signaling state.");
  5500. }
  5501. }
  5502. // We're in UAS role, sending outgoing response with session description
  5503. if (messages_1.isBody(message)) {
  5504. switch (this._signalingState) {
  5505. case session_1.SignalingState.Initial:
  5506. case session_1.SignalingState.Stable:
  5507. this._signalingState = session_1.SignalingState.HaveLocalOffer;
  5508. this._offer = body;
  5509. this._answer = undefined;
  5510. break;
  5511. case session_1.SignalingState.HaveLocalOffer:
  5512. // You cannot make a new offer while one is in progress.
  5513. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  5514. // FIXME: What to do here?
  5515. break;
  5516. case session_1.SignalingState.HaveRemoteOffer:
  5517. this._signalingState = session_1.SignalingState.Stable;
  5518. this._answer = body;
  5519. break;
  5520. case session_1.SignalingState.Closed:
  5521. break;
  5522. default:
  5523. throw new Error("Unexpected signaling state.");
  5524. }
  5525. }
  5526. };
  5527. SessionDialog.prototype.start2xxRetransmissionTimer = function () {
  5528. var _this = this;
  5529. if (this.initialTransaction instanceof transactions_1.InviteServerTransaction) {
  5530. var transaction_1 = this.initialTransaction;
  5531. // Once the response has been constructed, it is passed to the INVITE
  5532. // server transaction. In order to ensure reliable end-to-end
  5533. // transport of the response, it is necessary to periodically pass
  5534. // the response directly to the transport until the ACK arrives. The
  5535. // 2xx response is passed to the transport with an interval that
  5536. // starts at T1 seconds and doubles for each retransmission until it
  5537. // reaches T2 seconds (T1 and T2 are defined in Section 17).
  5538. // Response retransmissions cease when an ACK request for the
  5539. // response is received. This is independent of whatever transport
  5540. // protocols are used to send the response.
  5541. // https://tools.ietf.org/html/rfc6026#section-8.1
  5542. var timeout_1 = timers_1.Timers.T1;
  5543. var retransmission_1 = function () {
  5544. if (!_this.ackWait) {
  5545. _this.invite2xxTimer = undefined;
  5546. return;
  5547. }
  5548. _this.logger.log("No ACK for 2xx response received, attempting retransmission");
  5549. transaction_1.retransmitAcceptedResponse();
  5550. timeout_1 = Math.min(timeout_1 * 2, timers_1.Timers.T2);
  5551. _this.invite2xxTimer = setTimeout(retransmission_1, timeout_1);
  5552. };
  5553. this.invite2xxTimer = setTimeout(retransmission_1, timeout_1);
  5554. // If the server retransmits the 2xx response for 64*T1 seconds without
  5555. // receiving an ACK, the dialog is confirmed, but the session SHOULD be
  5556. // terminated. This is accomplished with a BYE, as described in Section 15.
  5557. // https://tools.ietf.org/html/rfc3261#section-13.3.1.4
  5558. var stateChanged_1 = function () {
  5559. if (transaction_1.state === transactions_1.TransactionState.Terminated) {
  5560. transaction_1.removeListener("stateChanged", stateChanged_1);
  5561. if (_this.invite2xxTimer) {
  5562. clearTimeout(_this.invite2xxTimer);
  5563. _this.invite2xxTimer = undefined;
  5564. }
  5565. if (_this.ackWait) {
  5566. if (_this.delegate && _this.delegate.onAckTimeout) {
  5567. _this.delegate.onAckTimeout();
  5568. }
  5569. else {
  5570. _this.bye();
  5571. }
  5572. }
  5573. }
  5574. };
  5575. transaction_1.addListener("stateChanged", stateChanged_1);
  5576. }
  5577. };
  5578. // FIXME: Refactor
  5579. SessionDialog.prototype.startReInvite2xxRetransmissionTimer = function () {
  5580. var _this = this;
  5581. if (this.reinviteUserAgentServer && this.reinviteUserAgentServer.transaction instanceof transactions_1.InviteServerTransaction) {
  5582. var transaction_2 = this.reinviteUserAgentServer.transaction;
  5583. // Once the response has been constructed, it is passed to the INVITE
  5584. // server transaction. In order to ensure reliable end-to-end
  5585. // transport of the response, it is necessary to periodically pass
  5586. // the response directly to the transport until the ACK arrives. The
  5587. // 2xx response is passed to the transport with an interval that
  5588. // starts at T1 seconds and doubles for each retransmission until it
  5589. // reaches T2 seconds (T1 and T2 are defined in Section 17).
  5590. // Response retransmissions cease when an ACK request for the
  5591. // response is received. This is independent of whatever transport
  5592. // protocols are used to send the response.
  5593. // https://tools.ietf.org/html/rfc6026#section-8.1
  5594. var timeout_2 = timers_1.Timers.T1;
  5595. var retransmission_2 = function () {
  5596. if (!_this.reinviteUserAgentServer) {
  5597. _this.invite2xxTimer = undefined;
  5598. return;
  5599. }
  5600. _this.logger.log("No ACK for 2xx response received, attempting retransmission");
  5601. transaction_2.retransmitAcceptedResponse();
  5602. timeout_2 = Math.min(timeout_2 * 2, timers_1.Timers.T2);
  5603. _this.invite2xxTimer = setTimeout(retransmission_2, timeout_2);
  5604. };
  5605. this.invite2xxTimer = setTimeout(retransmission_2, timeout_2);
  5606. // If the server retransmits the 2xx response for 64*T1 seconds without
  5607. // receiving an ACK, the dialog is confirmed, but the session SHOULD be
  5608. // terminated. This is accomplished with a BYE, as described in Section 15.
  5609. // https://tools.ietf.org/html/rfc3261#section-13.3.1.4
  5610. var stateChanged_2 = function () {
  5611. if (transaction_2.state === transactions_1.TransactionState.Terminated) {
  5612. transaction_2.removeListener("stateChanged", stateChanged_2);
  5613. if (_this.invite2xxTimer) {
  5614. clearTimeout(_this.invite2xxTimer);
  5615. _this.invite2xxTimer = undefined;
  5616. }
  5617. if (_this.reinviteUserAgentServer) {
  5618. // FIXME: TODO: What to do here
  5619. }
  5620. }
  5621. };
  5622. transaction_2.addListener("stateChanged", stateChanged_2);
  5623. }
  5624. };
  5625. return SessionDialog;
  5626. }(dialog_1.Dialog));
  5627. exports.SessionDialog = SessionDialog;
  5628. /***/ }),
  5629. /* 24 */
  5630. /***/ (function(module, exports, __webpack_require__) {
  5631. "use strict";
  5632. Object.defineProperty(exports, "__esModule", { value: true });
  5633. var tslib_1 = __webpack_require__(1);
  5634. tslib_1.__exportStar(__webpack_require__(25), exports);
  5635. /***/ }),
  5636. /* 25 */
  5637. /***/ (function(module, exports, __webpack_require__) {
  5638. "use strict";
  5639. Object.defineProperty(exports, "__esModule", { value: true });
  5640. /**
  5641. * Session state.
  5642. * @remarks
  5643. * https://tools.ietf.org/html/rfc3261#section-13
  5644. * @public
  5645. */
  5646. var SessionState;
  5647. (function (SessionState) {
  5648. SessionState["Initial"] = "Initial";
  5649. SessionState["Early"] = "Early";
  5650. SessionState["AckWait"] = "AckWait";
  5651. SessionState["Confirmed"] = "Confirmed";
  5652. SessionState["Terminated"] = "Terminated";
  5653. })(SessionState = exports.SessionState || (exports.SessionState = {}));
  5654. /**
  5655. * Offer/Answer state.
  5656. * @remarks
  5657. * ```txt
  5658. * Offer Answer RFC Ini Est Early
  5659. * -------------------------------------------------------------------
  5660. * 1. INVITE Req. 2xx INVITE Resp. RFC 3261 Y Y N
  5661. * 2. 2xx INVITE Resp. ACK Req. RFC 3261 Y Y N
  5662. * 3. INVITE Req. 1xx-rel INVITE Resp. RFC 3262 Y Y N
  5663. * 4. 1xx-rel INVITE Resp. PRACK Req. RFC 3262 Y Y N
  5664. * 5. PRACK Req. 200 PRACK Resp. RFC 3262 N Y Y
  5665. * 6. UPDATE Req. 2xx UPDATE Resp. RFC 3311 N Y Y
  5666. *
  5667. * Table 1: Summary of SIP Usage of the Offer/Answer Model
  5668. * ```
  5669. * https://tools.ietf.org/html/rfc6337#section-2.2
  5670. * @public
  5671. */
  5672. var SignalingState;
  5673. (function (SignalingState) {
  5674. SignalingState["Initial"] = "Initial";
  5675. SignalingState["HaveLocalOffer"] = "HaveLocalOffer";
  5676. SignalingState["HaveRemoteOffer"] = "HaveRemoteOffer";
  5677. SignalingState["Stable"] = "Stable";
  5678. SignalingState["Closed"] = "Closed";
  5679. })(SignalingState = exports.SignalingState || (exports.SignalingState = {}));
  5680. /***/ }),
  5681. /* 26 */
  5682. /***/ (function(module, exports, __webpack_require__) {
  5683. "use strict";
  5684. Object.defineProperty(exports, "__esModule", { value: true });
  5685. var T1 = 500;
  5686. var T2 = 4000;
  5687. var T4 = 5000;
  5688. /**
  5689. * Timers.
  5690. * @public
  5691. */
  5692. exports.Timers = {
  5693. T1: T1,
  5694. T2: T2,
  5695. T4: T4,
  5696. TIMER_B: 64 * T1,
  5697. TIMER_D: 0 * T1,
  5698. TIMER_F: 64 * T1,
  5699. TIMER_H: 64 * T1,
  5700. TIMER_I: 0 * T4,
  5701. TIMER_J: 0 * T1,
  5702. TIMER_K: 0 * T4,
  5703. TIMER_L: 64 * T1,
  5704. TIMER_M: 64 * T1,
  5705. TIMER_N: 64 * T1,
  5706. PROVISIONAL_RESPONSE_INTERVAL: 60000 // See RFC 3261 Section 13.3.1.1
  5707. };
  5708. /***/ }),
  5709. /* 27 */
  5710. /***/ (function(module, exports, __webpack_require__) {
  5711. "use strict";
  5712. Object.defineProperty(exports, "__esModule", { value: true });
  5713. var tslib_1 = __webpack_require__(1);
  5714. tslib_1.__exportStar(__webpack_require__(28), exports);
  5715. tslib_1.__exportStar(__webpack_require__(35), exports);
  5716. tslib_1.__exportStar(__webpack_require__(37), exports);
  5717. tslib_1.__exportStar(__webpack_require__(39), exports);
  5718. tslib_1.__exportStar(__webpack_require__(40), exports);
  5719. tslib_1.__exportStar(__webpack_require__(35), exports);
  5720. tslib_1.__exportStar(__webpack_require__(38), exports);
  5721. tslib_1.__exportStar(__webpack_require__(36), exports);
  5722. tslib_1.__exportStar(__webpack_require__(29), exports);
  5723. /***/ }),
  5724. /* 28 */
  5725. /***/ (function(module, exports, __webpack_require__) {
  5726. "use strict";
  5727. Object.defineProperty(exports, "__esModule", { value: true });
  5728. var tslib_1 = __webpack_require__(1);
  5729. var transaction_1 = __webpack_require__(29);
  5730. /**
  5731. * Client Transaction.
  5732. * @remarks
  5733. * The client transaction provides its functionality through the
  5734. * maintenance of a state machine.
  5735. *
  5736. * The TU communicates with the client transaction through a simple
  5737. * interface. When the TU wishes to initiate a new transaction, it
  5738. * creates a client transaction and passes it the SIP request to send
  5739. * and an IP address, port, and transport to which to send it. The
  5740. * client transaction begins execution of its state machine. Valid
  5741. * responses are passed up to the TU from the client transaction.
  5742. * https://tools.ietf.org/html/rfc3261#section-17.1
  5743. * @public
  5744. */
  5745. var ClientTransaction = /** @class */ (function (_super) {
  5746. tslib_1.__extends(ClientTransaction, _super);
  5747. function ClientTransaction(_request, transport, user, state, loggerCategory) {
  5748. var _this = _super.call(this, transport, user, ClientTransaction.makeId(_request), state, loggerCategory) || this;
  5749. _this._request = _request;
  5750. _this.user = user;
  5751. // The Via header field indicates the transport used for the transaction
  5752. // and identifies the location where the response is to be sent. A Via
  5753. // header field value is added only after the transport that will be
  5754. // used to reach the next hop has been selected (which may involve the
  5755. // usage of the procedures in [4]).
  5756. // https://tools.ietf.org/html/rfc3261#section-8.1.1.7
  5757. // FIXME: Transport's server property is not typed (as of writing this).
  5758. var scheme = transport.server && transport.server.scheme ? transport.server.scheme : undefined;
  5759. _request.setViaHeader(_this.id, scheme);
  5760. return _this;
  5761. }
  5762. ClientTransaction.makeId = function (request) {
  5763. if (request.method === "CANCEL") {
  5764. if (!request.branch) {
  5765. throw new Error("Outgoing CANCEL request without a branch.");
  5766. }
  5767. return request.branch;
  5768. }
  5769. else {
  5770. return "z9hG4bK" + Math.floor(Math.random() * 10000000);
  5771. }
  5772. };
  5773. Object.defineProperty(ClientTransaction.prototype, "request", {
  5774. /** The outgoing request the transaction handling. */
  5775. get: function () {
  5776. return this._request;
  5777. },
  5778. enumerable: true,
  5779. configurable: true
  5780. });
  5781. /**
  5782. * A 408 to non-INVITE will always arrive too late to be useful ([3]),
  5783. * The client already has full knowledge of the timeout. The only
  5784. * information this message would convey is whether or not the server
  5785. * believed the transaction timed out. However, with the current design
  5786. * of the NIT, a client cannot do anything with this knowledge. Thus,
  5787. * the 408 is simply wasting network resources and contributes to the
  5788. * response bombardment illustrated in [3].
  5789. * https://tools.ietf.org/html/rfc4320#section-4.1
  5790. */
  5791. ClientTransaction.prototype.onRequestTimeout = function () {
  5792. if (this.user.onRequestTimeout) {
  5793. this.user.onRequestTimeout();
  5794. }
  5795. };
  5796. return ClientTransaction;
  5797. }(transaction_1.Transaction));
  5798. exports.ClientTransaction = ClientTransaction;
  5799. /***/ }),
  5800. /* 29 */
  5801. /***/ (function(module, exports, __webpack_require__) {
  5802. "use strict";
  5803. Object.defineProperty(exports, "__esModule", { value: true });
  5804. var tslib_1 = __webpack_require__(1);
  5805. var events_1 = __webpack_require__(30);
  5806. var exceptions_1 = __webpack_require__(31);
  5807. /**
  5808. * Transaction.
  5809. * @remarks
  5810. * SIP is a transactional protocol: interactions between components take
  5811. * place in a series of independent message exchanges. Specifically, a
  5812. * SIP transaction consists of a single request and any responses to
  5813. * that request, which include zero or more provisional responses and
  5814. * one or more final responses. In the case of a transaction where the
  5815. * request was an INVITE (known as an INVITE transaction), the
  5816. * transaction also includes the ACK only if the final response was not
  5817. * a 2xx response. If the response was a 2xx, the ACK is not considered
  5818. * part of the transaction.
  5819. * https://tools.ietf.org/html/rfc3261#section-17
  5820. * @public
  5821. */
  5822. var Transaction = /** @class */ (function (_super) {
  5823. tslib_1.__extends(Transaction, _super);
  5824. function Transaction(_transport, _user, _id, _state, loggerCategory) {
  5825. var _this = _super.call(this) || this;
  5826. _this._transport = _transport;
  5827. _this._user = _user;
  5828. _this._id = _id;
  5829. _this._state = _state;
  5830. _this.logger = _user.loggerFactory.getLogger(loggerCategory, _id);
  5831. _this.logger.debug("Constructing " + _this.typeToString() + " with id " + _this.id + ".");
  5832. return _this;
  5833. }
  5834. /**
  5835. * Destructor.
  5836. * Once the transaction is in the "terminated" state, it is destroyed
  5837. * immediately and there is no need to call `dispose`. However, if a
  5838. * transaction needs to be ended prematurely, the transaction user may
  5839. * do so by calling this method (for example, perhaps the UA is shutting down).
  5840. * No state transition will occur upon calling this method, all outstanding
  5841. * transmission timers will be cancelled, and use of the transaction after
  5842. * calling `dispose` is undefined.
  5843. */
  5844. Transaction.prototype.dispose = function () {
  5845. this.logger.debug("Destroyed " + this.typeToString() + " with id " + this.id + ".");
  5846. };
  5847. Object.defineProperty(Transaction.prototype, "id", {
  5848. /** Transaction id. */
  5849. get: function () {
  5850. return this._id;
  5851. },
  5852. enumerable: true,
  5853. configurable: true
  5854. });
  5855. Object.defineProperty(Transaction.prototype, "kind", {
  5856. /** Transaction kind. Deprecated. */
  5857. get: function () {
  5858. throw new Error("Invalid kind.");
  5859. },
  5860. enumerable: true,
  5861. configurable: true
  5862. });
  5863. Object.defineProperty(Transaction.prototype, "state", {
  5864. /** Transaction state. */
  5865. get: function () {
  5866. return this._state;
  5867. },
  5868. enumerable: true,
  5869. configurable: true
  5870. });
  5871. Object.defineProperty(Transaction.prototype, "transport", {
  5872. /** Transaction transport. */
  5873. get: function () {
  5874. return this._transport;
  5875. },
  5876. enumerable: true,
  5877. configurable: true
  5878. });
  5879. Transaction.prototype.on = function (name, callback) { return _super.prototype.on.call(this, name, callback); };
  5880. Transaction.prototype.logTransportError = function (error, message) {
  5881. this.logger.error(error.message);
  5882. this.logger.error("Transport error occurred in " + this.typeToString() + " with id " + this.id + ".");
  5883. this.logger.error(message);
  5884. };
  5885. /**
  5886. * Pass message to transport for transmission. If transport fails,
  5887. * the transaction user is notified by callback to onTransportError().
  5888. * @returns
  5889. * Rejects with `TransportError` if transport fails.
  5890. */
  5891. Transaction.prototype.send = function (message) {
  5892. var _this = this;
  5893. return this.transport.send(message).catch(function (error) {
  5894. // If the transport rejects, it SHOULD reject with a TransportError.
  5895. // But the transport may be external code, so we are careful
  5896. // make sure we convert it to a TransportError if need be.
  5897. if (error instanceof exceptions_1.TransportError) {
  5898. _this.onTransportError(error);
  5899. throw error;
  5900. }
  5901. var transportError;
  5902. if (error && typeof error.message === "string") {
  5903. transportError = new exceptions_1.TransportError(error.message);
  5904. }
  5905. else {
  5906. transportError = new exceptions_1.TransportError();
  5907. }
  5908. _this.onTransportError(transportError);
  5909. throw transportError;
  5910. });
  5911. };
  5912. Transaction.prototype.setState = function (state) {
  5913. this.logger.debug("State change to \"" + state + "\" on " + this.typeToString() + " with id " + this.id + ".");
  5914. this._state = state;
  5915. if (this._user.onStateChange) {
  5916. this._user.onStateChange(state);
  5917. }
  5918. this.emit("stateChanged");
  5919. };
  5920. Transaction.prototype.typeToString = function () {
  5921. return "UnknownType";
  5922. };
  5923. return Transaction;
  5924. }(events_1.EventEmitter));
  5925. exports.Transaction = Transaction;
  5926. /***/ }),
  5927. /* 30 */
  5928. /***/ (function(module, exports, __webpack_require__) {
  5929. "use strict";
  5930. // Copyright Joyent, Inc. and other Node contributors.
  5931. //
  5932. // Permission is hereby granted, free of charge, to any person obtaining a
  5933. // copy of this software and associated documentation files (the
  5934. // "Software"), to deal in the Software without restriction, including
  5935. // without limitation the rights to use, copy, modify, merge, publish,
  5936. // distribute, sublicense, and/or sell copies of the Software, and to permit
  5937. // persons to whom the Software is furnished to do so, subject to the
  5938. // following conditions:
  5939. //
  5940. // The above copyright notice and this permission notice shall be included
  5941. // in all copies or substantial portions of the Software.
  5942. //
  5943. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  5944. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  5945. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  5946. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  5947. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  5948. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  5949. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  5950. var R = typeof Reflect === 'object' ? Reflect : null
  5951. var ReflectApply = R && typeof R.apply === 'function'
  5952. ? R.apply
  5953. : function ReflectApply(target, receiver, args) {
  5954. return Function.prototype.apply.call(target, receiver, args);
  5955. }
  5956. var ReflectOwnKeys
  5957. if (R && typeof R.ownKeys === 'function') {
  5958. ReflectOwnKeys = R.ownKeys
  5959. } else if (Object.getOwnPropertySymbols) {
  5960. ReflectOwnKeys = function ReflectOwnKeys(target) {
  5961. return Object.getOwnPropertyNames(target)
  5962. .concat(Object.getOwnPropertySymbols(target));
  5963. };
  5964. } else {
  5965. ReflectOwnKeys = function ReflectOwnKeys(target) {
  5966. return Object.getOwnPropertyNames(target);
  5967. };
  5968. }
  5969. function ProcessEmitWarning(warning) {
  5970. if (console && console.warn) console.warn(warning);
  5971. }
  5972. var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
  5973. return value !== value;
  5974. }
  5975. function EventEmitter() {
  5976. EventEmitter.init.call(this);
  5977. }
  5978. module.exports = EventEmitter;
  5979. // Backwards-compat with node 0.10.x
  5980. EventEmitter.EventEmitter = EventEmitter;
  5981. EventEmitter.prototype._events = undefined;
  5982. EventEmitter.prototype._eventsCount = 0;
  5983. EventEmitter.prototype._maxListeners = undefined;
  5984. // By default EventEmitters will print a warning if more than 10 listeners are
  5985. // added to it. This is a useful default which helps finding memory leaks.
  5986. var defaultMaxListeners = 10;
  5987. Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
  5988. enumerable: true,
  5989. get: function() {
  5990. return defaultMaxListeners;
  5991. },
  5992. set: function(arg) {
  5993. if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
  5994. throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
  5995. }
  5996. defaultMaxListeners = arg;
  5997. }
  5998. });
  5999. EventEmitter.init = function() {
  6000. if (this._events === undefined ||
  6001. this._events === Object.getPrototypeOf(this)._events) {
  6002. this._events = Object.create(null);
  6003. this._eventsCount = 0;
  6004. }
  6005. this._maxListeners = this._maxListeners || undefined;
  6006. };
  6007. // Obviously not all Emitters should be limited to 10. This function allows
  6008. // that to be increased. Set to zero for unlimited.
  6009. EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
  6010. if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
  6011. throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
  6012. }
  6013. this._maxListeners = n;
  6014. return this;
  6015. };
  6016. function $getMaxListeners(that) {
  6017. if (that._maxListeners === undefined)
  6018. return EventEmitter.defaultMaxListeners;
  6019. return that._maxListeners;
  6020. }
  6021. EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
  6022. return $getMaxListeners(this);
  6023. };
  6024. EventEmitter.prototype.emit = function emit(type) {
  6025. var args = [];
  6026. for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
  6027. var doError = (type === 'error');
  6028. var events = this._events;
  6029. if (events !== undefined)
  6030. doError = (doError && events.error === undefined);
  6031. else if (!doError)
  6032. return false;
  6033. // If there is no 'error' event listener then throw.
  6034. if (doError) {
  6035. var er;
  6036. if (args.length > 0)
  6037. er = args[0];
  6038. if (er instanceof Error) {
  6039. // Note: The comments on the `throw` lines are intentional, they show
  6040. // up in Node's output if this results in an unhandled exception.
  6041. throw er; // Unhandled 'error' event
  6042. }
  6043. // At least give some kind of context to the user
  6044. var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
  6045. err.context = er;
  6046. throw err; // Unhandled 'error' event
  6047. }
  6048. var handler = events[type];
  6049. if (handler === undefined)
  6050. return false;
  6051. if (typeof handler === 'function') {
  6052. ReflectApply(handler, this, args);
  6053. } else {
  6054. var len = handler.length;
  6055. var listeners = arrayClone(handler, len);
  6056. for (var i = 0; i < len; ++i)
  6057. ReflectApply(listeners[i], this, args);
  6058. }
  6059. return true;
  6060. };
  6061. function _addListener(target, type, listener, prepend) {
  6062. var m;
  6063. var events;
  6064. var existing;
  6065. if (typeof listener !== 'function') {
  6066. throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
  6067. }
  6068. events = target._events;
  6069. if (events === undefined) {
  6070. events = target._events = Object.create(null);
  6071. target._eventsCount = 0;
  6072. } else {
  6073. // To avoid recursion in the case that type === "newListener"! Before
  6074. // adding it to the listeners, first emit "newListener".
  6075. if (events.newListener !== undefined) {
  6076. target.emit('newListener', type,
  6077. listener.listener ? listener.listener : listener);
  6078. // Re-assign `events` because a newListener handler could have caused the
  6079. // this._events to be assigned to a new object
  6080. events = target._events;
  6081. }
  6082. existing = events[type];
  6083. }
  6084. if (existing === undefined) {
  6085. // Optimize the case of one listener. Don't need the extra array object.
  6086. existing = events[type] = listener;
  6087. ++target._eventsCount;
  6088. } else {
  6089. if (typeof existing === 'function') {
  6090. // Adding the second element, need to change to array.
  6091. existing = events[type] =
  6092. prepend ? [listener, existing] : [existing, listener];
  6093. // If we've already got an array, just append.
  6094. } else if (prepend) {
  6095. existing.unshift(listener);
  6096. } else {
  6097. existing.push(listener);
  6098. }
  6099. // Check for listener leak
  6100. m = $getMaxListeners(target);
  6101. if (m > 0 && existing.length > m && !existing.warned) {
  6102. existing.warned = true;
  6103. // No error code for this since it is a Warning
  6104. // eslint-disable-next-line no-restricted-syntax
  6105. var w = new Error('Possible EventEmitter memory leak detected. ' +
  6106. existing.length + ' ' + String(type) + ' listeners ' +
  6107. 'added. Use emitter.setMaxListeners() to ' +
  6108. 'increase limit');
  6109. w.name = 'MaxListenersExceededWarning';
  6110. w.emitter = target;
  6111. w.type = type;
  6112. w.count = existing.length;
  6113. ProcessEmitWarning(w);
  6114. }
  6115. }
  6116. return target;
  6117. }
  6118. EventEmitter.prototype.addListener = function addListener(type, listener) {
  6119. return _addListener(this, type, listener, false);
  6120. };
  6121. EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  6122. EventEmitter.prototype.prependListener =
  6123. function prependListener(type, listener) {
  6124. return _addListener(this, type, listener, true);
  6125. };
  6126. function onceWrapper() {
  6127. var args = [];
  6128. for (var i = 0; i < arguments.length; i++) args.push(arguments[i]);
  6129. if (!this.fired) {
  6130. this.target.removeListener(this.type, this.wrapFn);
  6131. this.fired = true;
  6132. ReflectApply(this.listener, this.target, args);
  6133. }
  6134. }
  6135. function _onceWrap(target, type, listener) {
  6136. var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
  6137. var wrapped = onceWrapper.bind(state);
  6138. wrapped.listener = listener;
  6139. state.wrapFn = wrapped;
  6140. return wrapped;
  6141. }
  6142. EventEmitter.prototype.once = function once(type, listener) {
  6143. if (typeof listener !== 'function') {
  6144. throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
  6145. }
  6146. this.on(type, _onceWrap(this, type, listener));
  6147. return this;
  6148. };
  6149. EventEmitter.prototype.prependOnceListener =
  6150. function prependOnceListener(type, listener) {
  6151. if (typeof listener !== 'function') {
  6152. throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
  6153. }
  6154. this.prependListener(type, _onceWrap(this, type, listener));
  6155. return this;
  6156. };
  6157. // Emits a 'removeListener' event if and only if the listener was removed.
  6158. EventEmitter.prototype.removeListener =
  6159. function removeListener(type, listener) {
  6160. var list, events, position, i, originalListener;
  6161. if (typeof listener !== 'function') {
  6162. throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
  6163. }
  6164. events = this._events;
  6165. if (events === undefined)
  6166. return this;
  6167. list = events[type];
  6168. if (list === undefined)
  6169. return this;
  6170. if (list === listener || list.listener === listener) {
  6171. if (--this._eventsCount === 0)
  6172. this._events = Object.create(null);
  6173. else {
  6174. delete events[type];
  6175. if (events.removeListener)
  6176. this.emit('removeListener', type, list.listener || listener);
  6177. }
  6178. } else if (typeof list !== 'function') {
  6179. position = -1;
  6180. for (i = list.length - 1; i >= 0; i--) {
  6181. if (list[i] === listener || list[i].listener === listener) {
  6182. originalListener = list[i].listener;
  6183. position = i;
  6184. break;
  6185. }
  6186. }
  6187. if (position < 0)
  6188. return this;
  6189. if (position === 0)
  6190. list.shift();
  6191. else {
  6192. spliceOne(list, position);
  6193. }
  6194. if (list.length === 1)
  6195. events[type] = list[0];
  6196. if (events.removeListener !== undefined)
  6197. this.emit('removeListener', type, originalListener || listener);
  6198. }
  6199. return this;
  6200. };
  6201. EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
  6202. EventEmitter.prototype.removeAllListeners =
  6203. function removeAllListeners(type) {
  6204. var listeners, events, i;
  6205. events = this._events;
  6206. if (events === undefined)
  6207. return this;
  6208. // not listening for removeListener, no need to emit
  6209. if (events.removeListener === undefined) {
  6210. if (arguments.length === 0) {
  6211. this._events = Object.create(null);
  6212. this._eventsCount = 0;
  6213. } else if (events[type] !== undefined) {
  6214. if (--this._eventsCount === 0)
  6215. this._events = Object.create(null);
  6216. else
  6217. delete events[type];
  6218. }
  6219. return this;
  6220. }
  6221. // emit removeListener for all listeners on all events
  6222. if (arguments.length === 0) {
  6223. var keys = Object.keys(events);
  6224. var key;
  6225. for (i = 0; i < keys.length; ++i) {
  6226. key = keys[i];
  6227. if (key === 'removeListener') continue;
  6228. this.removeAllListeners(key);
  6229. }
  6230. this.removeAllListeners('removeListener');
  6231. this._events = Object.create(null);
  6232. this._eventsCount = 0;
  6233. return this;
  6234. }
  6235. listeners = events[type];
  6236. if (typeof listeners === 'function') {
  6237. this.removeListener(type, listeners);
  6238. } else if (listeners !== undefined) {
  6239. // LIFO order
  6240. for (i = listeners.length - 1; i >= 0; i--) {
  6241. this.removeListener(type, listeners[i]);
  6242. }
  6243. }
  6244. return this;
  6245. };
  6246. function _listeners(target, type, unwrap) {
  6247. var events = target._events;
  6248. if (events === undefined)
  6249. return [];
  6250. var evlistener = events[type];
  6251. if (evlistener === undefined)
  6252. return [];
  6253. if (typeof evlistener === 'function')
  6254. return unwrap ? [evlistener.listener || evlistener] : [evlistener];
  6255. return unwrap ?
  6256. unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
  6257. }
  6258. EventEmitter.prototype.listeners = function listeners(type) {
  6259. return _listeners(this, type, true);
  6260. };
  6261. EventEmitter.prototype.rawListeners = function rawListeners(type) {
  6262. return _listeners(this, type, false);
  6263. };
  6264. EventEmitter.listenerCount = function(emitter, type) {
  6265. if (typeof emitter.listenerCount === 'function') {
  6266. return emitter.listenerCount(type);
  6267. } else {
  6268. return listenerCount.call(emitter, type);
  6269. }
  6270. };
  6271. EventEmitter.prototype.listenerCount = listenerCount;
  6272. function listenerCount(type) {
  6273. var events = this._events;
  6274. if (events !== undefined) {
  6275. var evlistener = events[type];
  6276. if (typeof evlistener === 'function') {
  6277. return 1;
  6278. } else if (evlistener !== undefined) {
  6279. return evlistener.length;
  6280. }
  6281. }
  6282. return 0;
  6283. }
  6284. EventEmitter.prototype.eventNames = function eventNames() {
  6285. return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
  6286. };
  6287. function arrayClone(arr, n) {
  6288. var copy = new Array(n);
  6289. for (var i = 0; i < n; ++i)
  6290. copy[i] = arr[i];
  6291. return copy;
  6292. }
  6293. function spliceOne(list, index) {
  6294. for (; index + 1 < list.length; index++)
  6295. list[index] = list[index + 1];
  6296. list.pop();
  6297. }
  6298. function unwrapListeners(arr) {
  6299. var ret = new Array(arr.length);
  6300. for (var i = 0; i < ret.length; ++i) {
  6301. ret[i] = arr[i].listener || arr[i];
  6302. }
  6303. return ret;
  6304. }
  6305. /***/ }),
  6306. /* 31 */
  6307. /***/ (function(module, exports, __webpack_require__) {
  6308. "use strict";
  6309. Object.defineProperty(exports, "__esModule", { value: true });
  6310. var tslib_1 = __webpack_require__(1);
  6311. tslib_1.__exportStar(__webpack_require__(32), exports);
  6312. tslib_1.__exportStar(__webpack_require__(33), exports);
  6313. tslib_1.__exportStar(__webpack_require__(34), exports);
  6314. /***/ }),
  6315. /* 32 */
  6316. /***/ (function(module, exports, __webpack_require__) {
  6317. "use strict";
  6318. Object.defineProperty(exports, "__esModule", { value: true });
  6319. var tslib_1 = __webpack_require__(1);
  6320. /**
  6321. * An Exception is considered a condition that a reasonable application may wish to catch.
  6322. * An Error indicates serious problems that a reasonable application should not try to catch.
  6323. * @public
  6324. */
  6325. var Exception = /** @class */ (function (_super) {
  6326. tslib_1.__extends(Exception, _super);
  6327. function Exception(message) {
  6328. var _newTarget = this.constructor;
  6329. var _this = _super.call(this, message) || this;
  6330. Object.setPrototypeOf(_this, _newTarget.prototype); // restore prototype chain
  6331. return _this;
  6332. }
  6333. return Exception;
  6334. }(Error));
  6335. exports.Exception = Exception;
  6336. /***/ }),
  6337. /* 33 */
  6338. /***/ (function(module, exports, __webpack_require__) {
  6339. "use strict";
  6340. Object.defineProperty(exports, "__esModule", { value: true });
  6341. var tslib_1 = __webpack_require__(1);
  6342. var exception_1 = __webpack_require__(32);
  6343. /**
  6344. * Indicates that the operation could not be completed given the current transaction state.
  6345. * @public
  6346. */
  6347. var TransactionStateError = /** @class */ (function (_super) {
  6348. tslib_1.__extends(TransactionStateError, _super);
  6349. function TransactionStateError(message) {
  6350. return _super.call(this, message ? message : "Transaction state error.") || this;
  6351. }
  6352. return TransactionStateError;
  6353. }(exception_1.Exception));
  6354. exports.TransactionStateError = TransactionStateError;
  6355. /***/ }),
  6356. /* 34 */
  6357. /***/ (function(module, exports, __webpack_require__) {
  6358. "use strict";
  6359. Object.defineProperty(exports, "__esModule", { value: true });
  6360. var tslib_1 = __webpack_require__(1);
  6361. var exception_1 = __webpack_require__(32);
  6362. /**
  6363. * Transport error.
  6364. * @public
  6365. */
  6366. var TransportError = /** @class */ (function (_super) {
  6367. tslib_1.__extends(TransportError, _super);
  6368. function TransportError(message) {
  6369. return _super.call(this, message ? message : "Unspecified transport error.") || this;
  6370. }
  6371. return TransportError;
  6372. }(exception_1.Exception));
  6373. exports.TransportError = TransportError;
  6374. /***/ }),
  6375. /* 35 */
  6376. /***/ (function(module, exports, __webpack_require__) {
  6377. "use strict";
  6378. Object.defineProperty(exports, "__esModule", { value: true });
  6379. var tslib_1 = __webpack_require__(1);
  6380. var timers_1 = __webpack_require__(26);
  6381. var client_transaction_1 = __webpack_require__(28);
  6382. var transaction_state_1 = __webpack_require__(36);
  6383. /**
  6384. * INVITE Client Transaction.
  6385. * @remarks
  6386. * The INVITE transaction consists of a three-way handshake. The client
  6387. * transaction sends an INVITE, the server transaction sends responses,
  6388. * and the client transaction sends an ACK.
  6389. * https://tools.ietf.org/html/rfc3261#section-17.1.1
  6390. * @public
  6391. */
  6392. var InviteClientTransaction = /** @class */ (function (_super) {
  6393. tslib_1.__extends(InviteClientTransaction, _super);
  6394. /**
  6395. * Constructor.
  6396. * Upon construction, the outgoing request's Via header is updated by calling `setViaHeader`.
  6397. * Then `toString` is called on the outgoing request and the message is sent via the transport.
  6398. * After construction the transaction will be in the "calling" state and the transaction id
  6399. * will equal the branch parameter set in the Via header of the outgoing request.
  6400. * https://tools.ietf.org/html/rfc3261#section-17.1.1
  6401. * @param request - The outgoing INVITE request.
  6402. * @param transport - The transport.
  6403. * @param user - The transaction user.
  6404. */
  6405. function InviteClientTransaction(request, transport, user) {
  6406. var _this = _super.call(this, request, transport, user, transaction_state_1.TransactionState.Calling, "sip.transaction.ict") || this;
  6407. /**
  6408. * Map of 2xx to-tag to ACK.
  6409. * If value is not undefined, value is the ACK which was sent.
  6410. * If key exists but value is undefined, a 2xx was received but the ACK not yet sent.
  6411. * Otherwise, a 2xx was not (yet) received for this transaction.
  6412. */
  6413. _this.ackRetransmissionCache = new Map();
  6414. // FIXME: Timer A for unreliable transport not implemented
  6415. //
  6416. // If an unreliable transport is being used, the client transaction
  6417. // MUST start timer A with a value of T1. If a reliable transport is being used,
  6418. // the client transaction SHOULD NOT start timer A (Timer A controls request retransmissions).
  6419. // For any transport, the client transaction MUST start timer B with a value
  6420. // of 64*T1 seconds (Timer B controls transaction timeouts).
  6421. // https://tools.ietf.org/html/rfc3261#section-17.1.1.2
  6422. //
  6423. // While not spelled out in the RFC, Timer B is the maximum amount of time that a sender
  6424. // will wait for an INVITE message to be acknowledged (a SIP response message is received).
  6425. // So Timer B should be cleared when the transaction state proceeds from "Calling".
  6426. _this.B = setTimeout(function () { return _this.timer_B(); }, timers_1.Timers.TIMER_B);
  6427. _this.send(request.toString()).catch(function (error) {
  6428. _this.logTransportError(error, "Failed to send initial outgoing request.");
  6429. });
  6430. return _this;
  6431. }
  6432. /**
  6433. * Destructor.
  6434. */
  6435. InviteClientTransaction.prototype.dispose = function () {
  6436. if (this.B) {
  6437. clearTimeout(this.B);
  6438. this.B = undefined;
  6439. }
  6440. if (this.D) {
  6441. clearTimeout(this.D);
  6442. this.D = undefined;
  6443. }
  6444. if (this.M) {
  6445. clearTimeout(this.M);
  6446. this.M = undefined;
  6447. }
  6448. _super.prototype.dispose.call(this);
  6449. };
  6450. Object.defineProperty(InviteClientTransaction.prototype, "kind", {
  6451. /** Transaction kind. Deprecated. */
  6452. get: function () {
  6453. return "ict";
  6454. },
  6455. enumerable: true,
  6456. configurable: true
  6457. });
  6458. /**
  6459. * ACK a 2xx final response.
  6460. *
  6461. * The transaction includes the ACK only if the final response was not a 2xx response (the
  6462. * transaction will generate and send the ACK to the transport automagically). If the
  6463. * final response was a 2xx, the ACK is not considered part of the transaction (the
  6464. * transaction user needs to generate and send the ACK).
  6465. *
  6466. * This library is not strictly RFC compliant with regard to ACK handling for 2xx final
  6467. * responses. Specifically, retransmissions of ACKs to a 2xx final responses is handled
  6468. * by the transaction layer (instead of the UAC core). The "standard" approach is for
  6469. * the UAC core to receive all 2xx responses and manage sending ACK retransmissions to
  6470. * the transport directly. Herein the transaction layer manages sending ACKs to 2xx responses
  6471. * and any retransmissions of those ACKs as needed.
  6472. *
  6473. * @param ack - The outgoing ACK request.
  6474. */
  6475. InviteClientTransaction.prototype.ackResponse = function (ack) {
  6476. var _this = this;
  6477. var toTag = ack.toTag;
  6478. if (!toTag) {
  6479. throw new Error("To tag undefined.");
  6480. }
  6481. var id = "z9hG4bK" + Math.floor(Math.random() * 10000000);
  6482. // FIXME: Transport's server property is not typed (as of writing this).
  6483. var scheme = this.transport.server && this.transport.server.scheme ? this.transport.server.scheme : undefined;
  6484. ack.setViaHeader(id, scheme);
  6485. this.ackRetransmissionCache.set(toTag, ack); // Add to ACK retransmission cache
  6486. this.send(ack.toString()).catch(function (error) {
  6487. _this.logTransportError(error, "Failed to send ACK to 2xx response.");
  6488. });
  6489. };
  6490. /**
  6491. * Handler for incoming responses from the transport which match this transaction.
  6492. * @param response - The incoming response.
  6493. */
  6494. InviteClientTransaction.prototype.receiveResponse = function (response) {
  6495. var _this = this;
  6496. var statusCode = response.statusCode;
  6497. if (!statusCode || statusCode < 100 || statusCode > 699) {
  6498. throw new Error("Invalid status code " + statusCode);
  6499. }
  6500. switch (this.state) {
  6501. case transaction_state_1.TransactionState.Calling:
  6502. // If the client transaction receives a provisional response while in
  6503. // the "Calling" state, it transitions to the "Proceeding" state. In the
  6504. // "Proceeding" state, the client transaction SHOULD NOT retransmit the
  6505. // request any longer. Furthermore, the provisional response MUST be
  6506. // passed to the TU. Any further provisional responses MUST be passed
  6507. // up to the TU while in the "Proceeding" state.
  6508. // https://tools.ietf.org/html/rfc3261#section-17.1.1.2
  6509. if (statusCode >= 100 && statusCode <= 199) {
  6510. this.stateTransition(transaction_state_1.TransactionState.Proceeding);
  6511. if (this.user.receiveResponse) {
  6512. this.user.receiveResponse(response);
  6513. }
  6514. return;
  6515. }
  6516. // When a 2xx response is received while in either the "Calling" or
  6517. // "Proceeding" states, the client transaction MUST transition to
  6518. // the "Accepted" state... The 2xx response MUST be passed up to the TU.
  6519. // The client transaction MUST NOT generate an ACK to the 2xx response -- its
  6520. // handling is delegated to the TU. A UAC core will send an ACK to
  6521. // the 2xx response using a new transaction.
  6522. // https://tools.ietf.org/html/rfc6026#section-8.4
  6523. if (statusCode >= 200 && statusCode <= 299) {
  6524. this.ackRetransmissionCache.set(response.toTag, undefined); // Prime the ACK cache
  6525. this.stateTransition(transaction_state_1.TransactionState.Accepted);
  6526. if (this.user.receiveResponse) {
  6527. this.user.receiveResponse(response);
  6528. }
  6529. return;
  6530. }
  6531. // When in either the "Calling" or "Proceeding" states, reception of
  6532. // a response with status code from 300-699 MUST cause the client
  6533. // transaction to transition to "Completed". The client transaction
  6534. // MUST pass the received response up to the TU, and the client
  6535. // transaction MUST generate an ACK request, even if the transport is
  6536. // reliable (guidelines for constructing the ACK from the response
  6537. // are given in Section 17.1.1.3), and then pass the ACK to the
  6538. // transport layer for transmission. The ACK MUST be sent to the
  6539. // same address, port, and transport to which the original request was sent.
  6540. // https://tools.ietf.org/html/rfc6026#section-8.4
  6541. if (statusCode >= 300 && statusCode <= 699) {
  6542. this.stateTransition(transaction_state_1.TransactionState.Completed);
  6543. this.ack(response);
  6544. if (this.user.receiveResponse) {
  6545. this.user.receiveResponse(response);
  6546. }
  6547. return;
  6548. }
  6549. break;
  6550. case transaction_state_1.TransactionState.Proceeding:
  6551. // In the "Proceeding" state, the client transaction SHOULD NOT retransmit the
  6552. // request any longer. Furthermore, the provisional response MUST be
  6553. // passed to the TU. Any further provisional responses MUST be passed
  6554. // up to the TU while in the "Proceeding" state.
  6555. // https://tools.ietf.org/html/rfc3261#section-17.1.1.2
  6556. if (statusCode >= 100 && statusCode <= 199) {
  6557. if (this.user.receiveResponse) {
  6558. this.user.receiveResponse(response);
  6559. }
  6560. return;
  6561. }
  6562. // When a 2xx response is received while in either the "Calling" or "Proceeding" states,
  6563. // the client transaction MUST transition to the "Accepted" state...
  6564. // The 2xx response MUST be passed up to the TU. The client
  6565. // transaction MUST NOT generate an ACK to the 2xx response -- its
  6566. // handling is delegated to the TU. A UAC core will send an ACK to
  6567. // the 2xx response using a new transaction.
  6568. // https://tools.ietf.org/html/rfc6026#section-8.4
  6569. if (statusCode >= 200 && statusCode <= 299) {
  6570. this.ackRetransmissionCache.set(response.toTag, undefined); // Prime the ACK cache
  6571. this.stateTransition(transaction_state_1.TransactionState.Accepted);
  6572. if (this.user.receiveResponse) {
  6573. this.user.receiveResponse(response);
  6574. }
  6575. return;
  6576. }
  6577. // When in either the "Calling" or "Proceeding" states, reception of
  6578. // a response with status code from 300-699 MUST cause the client
  6579. // transaction to transition to "Completed". The client transaction
  6580. // MUST pass the received response up to the TU, and the client
  6581. // transaction MUST generate an ACK request, even if the transport is
  6582. // reliable (guidelines for constructing the ACK from the response
  6583. // are given in Section 17.1.1.3), and then pass the ACK to the
  6584. // transport layer for transmission. The ACK MUST be sent to the
  6585. // same address, port, and transport to which the original request was sent.
  6586. // https://tools.ietf.org/html/rfc6026#section-8.4
  6587. if (statusCode >= 300 && statusCode <= 699) {
  6588. this.stateTransition(transaction_state_1.TransactionState.Completed);
  6589. this.ack(response);
  6590. if (this.user.receiveResponse) {
  6591. this.user.receiveResponse(response);
  6592. }
  6593. return;
  6594. }
  6595. break;
  6596. case transaction_state_1.TransactionState.Accepted:
  6597. // The purpose of the "Accepted" state is to allow the client
  6598. // transaction to continue to exist to receive, and pass to the TU,
  6599. // any retransmissions of the 2xx response and any additional 2xx
  6600. // responses from other branches of the INVITE if it forked
  6601. // downstream. Timer M reflects the amount of time that the
  6602. // transaction user will wait for such messages.
  6603. //
  6604. // Any 2xx responses that match this client transaction and that are
  6605. // received while in the "Accepted" state MUST be passed up to the
  6606. // TU. The client transaction MUST NOT generate an ACK to the 2xx
  6607. // response. The client transaction takes no further action.
  6608. // https://tools.ietf.org/html/rfc6026#section-8.4
  6609. if (statusCode >= 200 && statusCode <= 299) {
  6610. // NOTE: This implementation herein is intentionally not RFC compliant.
  6611. // While the first 2xx response for a given branch is passed up to the TU,
  6612. // retransmissions of 2xx responses are absorbed and the ACK associated
  6613. // with the original response is resent. This approach is taken because
  6614. // our current transaction users are not currently in a good position to
  6615. // deal with 2xx retransmission. This SHOULD NOT cause any compliance issues - ;)
  6616. //
  6617. // If we don't have a cache hit, pass the response to the TU.
  6618. if (!this.ackRetransmissionCache.has(response.toTag)) {
  6619. this.ackRetransmissionCache.set(response.toTag, undefined); // Prime the ACK cache
  6620. if (this.user.receiveResponse) {
  6621. this.user.receiveResponse(response);
  6622. }
  6623. return;
  6624. }
  6625. // If we have a cache hit, try pulling the ACK from cache and retransmitting it.
  6626. var ack = this.ackRetransmissionCache.get(response.toTag);
  6627. if (ack) {
  6628. this.send(ack.toString()).catch(function (error) {
  6629. _this.logTransportError(error, "Failed to send retransmission of ACK to 2xx response.");
  6630. });
  6631. return;
  6632. }
  6633. // If an ACK was not found in cache then we have received a retransmitted 2xx
  6634. // response before the TU responded to the original response (we don't have an ACK yet).
  6635. // So discard this response under the assumption that the TU will eventually
  6636. // get us a ACK for the original response.
  6637. return;
  6638. }
  6639. break;
  6640. case transaction_state_1.TransactionState.Completed:
  6641. // Any retransmissions of a response with status code 300-699 that
  6642. // are received while in the "Completed" state MUST cause the ACK to
  6643. // be re-passed to the transport layer for retransmission, but the
  6644. // newly received response MUST NOT be passed up to the TU.
  6645. // https://tools.ietf.org/html/rfc6026#section-8.4
  6646. if (statusCode >= 300 && statusCode <= 699) {
  6647. this.ack(response);
  6648. return;
  6649. }
  6650. break;
  6651. case transaction_state_1.TransactionState.Terminated:
  6652. break;
  6653. default:
  6654. throw new Error("Invalid state " + this.state);
  6655. }
  6656. // Any response received that does not match an existing client
  6657. // transaction state machine is simply dropped. (Implementations are,
  6658. // of course, free to log or do other implementation-specific things
  6659. // with such responses, but the implementer should be sure to consider
  6660. // the impact of large numbers of malicious stray responses.)
  6661. // https://tools.ietf.org/html/rfc6026#section-7.2
  6662. var message = "Received unexpected " + statusCode + " response while in state " + this.state + ".";
  6663. this.logger.warn(message);
  6664. return;
  6665. };
  6666. /**
  6667. * The client transaction SHOULD inform the TU that a transport failure
  6668. * has occurred, and the client transaction SHOULD transition directly
  6669. * to the "Terminated" state. The TU will handle the failover
  6670. * mechanisms described in [4].
  6671. * https://tools.ietf.org/html/rfc3261#section-17.1.4
  6672. * @param error - The error.
  6673. */
  6674. InviteClientTransaction.prototype.onTransportError = function (error) {
  6675. if (this.user.onTransportError) {
  6676. this.user.onTransportError(error);
  6677. }
  6678. this.stateTransition(transaction_state_1.TransactionState.Terminated, true);
  6679. };
  6680. /** For logging. */
  6681. InviteClientTransaction.prototype.typeToString = function () {
  6682. return "INVITE client transaction";
  6683. };
  6684. InviteClientTransaction.prototype.ack = function (response) {
  6685. var _this = this;
  6686. // The ACK request constructed by the client transaction MUST contain
  6687. // values for the Call-ID, From, and Request-URI that are equal to the
  6688. // values of those header fields in the request passed to the transport
  6689. // by the client transaction (call this the "original request"). The To
  6690. // header field in the ACK MUST equal the To header field in the
  6691. // response being acknowledged, and therefore will usually differ from
  6692. // the To header field in the original request by the addition of the
  6693. // tag parameter. The ACK MUST contain a single Via header field, and
  6694. // this MUST be equal to the top Via header field of the original
  6695. // request. The CSeq header field in the ACK MUST contain the same
  6696. // value for the sequence number as was present in the original request,
  6697. // but the method parameter MUST be equal to "ACK".
  6698. //
  6699. // If the INVITE request whose response is being acknowledged had Route
  6700. // header fields, those header fields MUST appear in the ACK. This is
  6701. // to ensure that the ACK can be routed properly through any downstream
  6702. // stateless proxies.
  6703. // https://tools.ietf.org/html/rfc3261#section-17.1.1.3
  6704. var ruri = this.request.ruri;
  6705. var callId = this.request.callId;
  6706. var cseq = this.request.cseq;
  6707. var from = this.request.getHeader("from");
  6708. var to = response.getHeader("to");
  6709. var via = this.request.getHeader("via");
  6710. var route = this.request.getHeader("route");
  6711. if (!from) {
  6712. throw new Error("From undefined.");
  6713. }
  6714. if (!to) {
  6715. throw new Error("To undefined.");
  6716. }
  6717. if (!via) {
  6718. throw new Error("Via undefined.");
  6719. }
  6720. var ack = "ACK " + ruri + " SIP/2.0\r\n";
  6721. if (route) {
  6722. ack += "Route: " + route + "\r\n";
  6723. }
  6724. ack += "Via: " + via + "\r\n";
  6725. ack += "To: " + to + "\r\n";
  6726. ack += "From: " + from + "\r\n";
  6727. ack += "Call-ID: " + callId + "\r\n";
  6728. ack += "CSeq: " + cseq + " ACK\r\n";
  6729. ack += "Max-Forwards: 70\r\n";
  6730. ack += "Content-Length: 0\r\n\r\n";
  6731. // TOOO: "User-Agent" header
  6732. this.send(ack).catch(function (error) {
  6733. _this.logTransportError(error, "Failed to send ACK to non-2xx response.");
  6734. });
  6735. return;
  6736. };
  6737. /**
  6738. * Execute a state transition.
  6739. * @param newState - New state.
  6740. */
  6741. InviteClientTransaction.prototype.stateTransition = function (newState, dueToTransportError) {
  6742. var _this = this;
  6743. if (dueToTransportError === void 0) { dueToTransportError = false; }
  6744. // Assert valid state transitions.
  6745. var invalidStateTransition = function () {
  6746. throw new Error("Invalid state transition from " + _this.state + " to " + newState);
  6747. };
  6748. switch (newState) {
  6749. case transaction_state_1.TransactionState.Calling:
  6750. invalidStateTransition();
  6751. break;
  6752. case transaction_state_1.TransactionState.Proceeding:
  6753. if (this.state !== transaction_state_1.TransactionState.Calling) {
  6754. invalidStateTransition();
  6755. }
  6756. break;
  6757. case transaction_state_1.TransactionState.Accepted:
  6758. case transaction_state_1.TransactionState.Completed:
  6759. if (this.state !== transaction_state_1.TransactionState.Calling &&
  6760. this.state !== transaction_state_1.TransactionState.Proceeding) {
  6761. invalidStateTransition();
  6762. }
  6763. break;
  6764. case transaction_state_1.TransactionState.Terminated:
  6765. if (this.state !== transaction_state_1.TransactionState.Calling &&
  6766. this.state !== transaction_state_1.TransactionState.Accepted &&
  6767. this.state !== transaction_state_1.TransactionState.Completed) {
  6768. if (!dueToTransportError) {
  6769. invalidStateTransition();
  6770. }
  6771. }
  6772. break;
  6773. default:
  6774. invalidStateTransition();
  6775. }
  6776. // While not spelled out in the RFC, Timer B is the maximum amount of time that a sender
  6777. // will wait for an INVITE message to be acknowledged (a SIP response message is received).
  6778. // So Timer B should be cleared when the transaction state proceeds from "Calling".
  6779. if (this.B) {
  6780. clearTimeout(this.B);
  6781. this.B = undefined;
  6782. }
  6783. if (newState === transaction_state_1.TransactionState.Proceeding) {
  6784. // Timers have no effect on "Proceeding" state.
  6785. // In the "Proceeding" state, the client transaction
  6786. // SHOULD NOT retransmit the request any longer.
  6787. // https://tools.ietf.org/html/rfc3261#section-17.1.1.2
  6788. }
  6789. // The client transaction MUST start Timer D when it enters the "Completed" state
  6790. // for any reason, with a value of at least 32 seconds for unreliable transports,
  6791. // and a value of zero seconds for reliable transports.
  6792. // https://tools.ietf.org/html/rfc6026#section-8.4
  6793. if (newState === transaction_state_1.TransactionState.Completed) {
  6794. this.D = setTimeout(function () { return _this.timer_D(); }, timers_1.Timers.TIMER_D);
  6795. }
  6796. // The client transaction MUST transition to the "Accepted" state,
  6797. // and Timer M MUST be started with a value of 64*T1.
  6798. // https://tools.ietf.org/html/rfc6026#section-8.4
  6799. if (newState === transaction_state_1.TransactionState.Accepted) {
  6800. this.M = setTimeout(function () { return _this.timer_M(); }, timers_1.Timers.TIMER_M);
  6801. }
  6802. // Once the transaction is in the "Terminated" state, it MUST be destroyed immediately.
  6803. // https://tools.ietf.org/html/rfc6026#section-8.7
  6804. if (newState === transaction_state_1.TransactionState.Terminated) {
  6805. this.dispose();
  6806. }
  6807. // Update state.
  6808. this.setState(newState);
  6809. };
  6810. /**
  6811. * When timer A fires, the client transaction MUST retransmit the
  6812. * request by passing it to the transport layer, and MUST reset the
  6813. * timer with a value of 2*T1.
  6814. * When timer A fires 2*T1 seconds later, the request MUST be
  6815. * retransmitted again (assuming the client transaction is still in this
  6816. * state). This process MUST continue so that the request is
  6817. * retransmitted with intervals that double after each transmission.
  6818. * These retransmissions SHOULD only be done while the client
  6819. * transaction is in the "Calling" state.
  6820. * https://tools.ietf.org/html/rfc3261#section-17.1.1.2
  6821. */
  6822. InviteClientTransaction.prototype.timer_A = function () {
  6823. // TODO
  6824. };
  6825. /**
  6826. * If the client transaction is still in the "Calling" state when timer
  6827. * B fires, the client transaction SHOULD inform the TU that a timeout
  6828. * has occurred. The client transaction MUST NOT generate an ACK.
  6829. * https://tools.ietf.org/html/rfc3261#section-17.1.1.2
  6830. */
  6831. InviteClientTransaction.prototype.timer_B = function () {
  6832. this.logger.debug("Timer B expired for INVITE client transaction " + this.id + ".");
  6833. if (this.state === transaction_state_1.TransactionState.Calling) {
  6834. this.onRequestTimeout();
  6835. this.stateTransition(transaction_state_1.TransactionState.Terminated);
  6836. }
  6837. };
  6838. /**
  6839. * If Timer D fires while the client transaction is in the "Completed" state,
  6840. * the client transaction MUST move to the "Terminated" state.
  6841. * https://tools.ietf.org/html/rfc6026#section-8.4
  6842. */
  6843. InviteClientTransaction.prototype.timer_D = function () {
  6844. this.logger.debug("Timer D expired for INVITE client transaction " + this.id + ".");
  6845. if (this.state === transaction_state_1.TransactionState.Completed) {
  6846. this.stateTransition(transaction_state_1.TransactionState.Terminated);
  6847. }
  6848. };
  6849. /**
  6850. * If Timer M fires while the client transaction is in the "Accepted"
  6851. * state, the client transaction MUST move to the "Terminated" state.
  6852. * https://tools.ietf.org/html/rfc6026#section-8.4
  6853. */
  6854. InviteClientTransaction.prototype.timer_M = function () {
  6855. this.logger.debug("Timer M expired for INVITE client transaction " + this.id + ".");
  6856. if (this.state === transaction_state_1.TransactionState.Accepted) {
  6857. this.stateTransition(transaction_state_1.TransactionState.Terminated);
  6858. }
  6859. };
  6860. return InviteClientTransaction;
  6861. }(client_transaction_1.ClientTransaction));
  6862. exports.InviteClientTransaction = InviteClientTransaction;
  6863. /***/ }),
  6864. /* 36 */
  6865. /***/ (function(module, exports, __webpack_require__) {
  6866. "use strict";
  6867. Object.defineProperty(exports, "__esModule", { value: true });
  6868. /**
  6869. * Transaction state.
  6870. * @public
  6871. */
  6872. var TransactionState;
  6873. (function (TransactionState) {
  6874. TransactionState["Accepted"] = "Accepted";
  6875. TransactionState["Calling"] = "Calling";
  6876. TransactionState["Completed"] = "Completed";
  6877. TransactionState["Confirmed"] = "Confirmed";
  6878. TransactionState["Proceeding"] = "Proceeding";
  6879. TransactionState["Terminated"] = "Terminated";
  6880. TransactionState["Trying"] = "Trying";
  6881. })(TransactionState = exports.TransactionState || (exports.TransactionState = {}));
  6882. /***/ }),
  6883. /* 37 */
  6884. /***/ (function(module, exports, __webpack_require__) {
  6885. "use strict";
  6886. Object.defineProperty(exports, "__esModule", { value: true });
  6887. var tslib_1 = __webpack_require__(1);
  6888. var messages_1 = __webpack_require__(5);
  6889. var timers_1 = __webpack_require__(26);
  6890. var server_transaction_1 = __webpack_require__(38);
  6891. var transaction_state_1 = __webpack_require__(36);
  6892. /**
  6893. * INVITE Server Transaction.
  6894. * @remarks
  6895. * https://tools.ietf.org/html/rfc3261#section-17.2.1
  6896. * @public
  6897. */
  6898. var InviteServerTransaction = /** @class */ (function (_super) {
  6899. tslib_1.__extends(InviteServerTransaction, _super);
  6900. /**
  6901. * Constructor.
  6902. * Upon construction, a "100 Trying" reply will be immediately sent.
  6903. * After construction the transaction will be in the "proceeding" state and the transaction
  6904. * `id` will equal the branch parameter set in the Via header of the incoming request.
  6905. * https://tools.ietf.org/html/rfc3261#section-17.2.1
  6906. * @param request - Incoming INVITE request from the transport.
  6907. * @param transport - The transport.
  6908. * @param user - The transaction user.
  6909. */
  6910. function InviteServerTransaction(request, transport, user) {
  6911. return _super.call(this, request, transport, user, transaction_state_1.TransactionState.Proceeding, "sip.transaction.ist") || this;
  6912. }
  6913. /**
  6914. * Destructor.
  6915. */
  6916. InviteServerTransaction.prototype.dispose = function () {
  6917. this.stopProgressExtensionTimer();
  6918. if (this.H) {
  6919. clearTimeout(this.H);
  6920. this.H = undefined;
  6921. }
  6922. if (this.I) {
  6923. clearTimeout(this.I);
  6924. this.I = undefined;
  6925. }
  6926. if (this.L) {
  6927. clearTimeout(this.L);
  6928. this.L = undefined;
  6929. }
  6930. _super.prototype.dispose.call(this);
  6931. };
  6932. Object.defineProperty(InviteServerTransaction.prototype, "kind", {
  6933. /** Transaction kind. Deprecated. */
  6934. get: function () {
  6935. return "ist";
  6936. },
  6937. enumerable: true,
  6938. configurable: true
  6939. });
  6940. /**
  6941. * Receive requests from transport matching this transaction.
  6942. * @param request - Request matching this transaction.
  6943. */
  6944. InviteServerTransaction.prototype.receiveRequest = function (request) {
  6945. var _this = this;
  6946. switch (this.state) {
  6947. case transaction_state_1.TransactionState.Proceeding:
  6948. // If a request retransmission is received while in the "Proceeding" state, the most
  6949. // recent provisional response that was received from the TU MUST be passed to the
  6950. // transport layer for retransmission.
  6951. // https://tools.ietf.org/html/rfc3261#section-17.2.1
  6952. if (request.method === messages_1.C.INVITE) {
  6953. if (this.lastProvisionalResponse) {
  6954. this.send(this.lastProvisionalResponse).catch(function (error) {
  6955. _this.logTransportError(error, "Failed to send retransmission of provisional response.");
  6956. });
  6957. }
  6958. return;
  6959. }
  6960. break;
  6961. case transaction_state_1.TransactionState.Accepted:
  6962. // While in the "Accepted" state, any retransmissions of the INVITE
  6963. // received will match this transaction state machine and will be
  6964. // absorbed by the machine without changing its state. These
  6965. // retransmissions are not passed onto the TU.
  6966. // https://tools.ietf.org/html/rfc6026#section-7.1
  6967. if (request.method === messages_1.C.INVITE) {
  6968. return;
  6969. }
  6970. break;
  6971. case transaction_state_1.TransactionState.Completed:
  6972. // Furthermore, while in the "Completed" state, if a request retransmission is
  6973. // received, the server SHOULD pass the response to the transport for retransmission.
  6974. // https://tools.ietf.org/html/rfc3261#section-17.2.1
  6975. if (request.method === messages_1.C.INVITE) {
  6976. if (!this.lastFinalResponse) {
  6977. throw new Error("Last final response undefined.");
  6978. }
  6979. this.send(this.lastFinalResponse).catch(function (error) {
  6980. _this.logTransportError(error, "Failed to send retransmission of final response.");
  6981. });
  6982. return;
  6983. }
  6984. // If an ACK is received while the server transaction is in the "Completed" state,
  6985. // the server transaction MUST transition to the "Confirmed" state.
  6986. // https://tools.ietf.org/html/rfc3261#section-17.2.1
  6987. if (request.method === messages_1.C.ACK) {
  6988. this.stateTransition(transaction_state_1.TransactionState.Confirmed);
  6989. return;
  6990. }
  6991. break;
  6992. case transaction_state_1.TransactionState.Confirmed:
  6993. // The purpose of the "Confirmed" state is to absorb any additional ACK messages that arrive,
  6994. // triggered from retransmissions of the final response.
  6995. // https://tools.ietf.org/html/rfc3261#section-17.2.1
  6996. if (request.method === messages_1.C.INVITE || request.method === messages_1.C.ACK) {
  6997. return;
  6998. }
  6999. break;
  7000. case transaction_state_1.TransactionState.Terminated:
  7001. // For good measure absorb any additional messages that arrive (should not happen).
  7002. if (request.method === messages_1.C.INVITE || request.method === messages_1.C.ACK) {
  7003. return;
  7004. }
  7005. break;
  7006. default:
  7007. throw new Error("Invalid state " + this.state);
  7008. }
  7009. var message = "INVITE server transaction received unexpected " + request.method + " request while in state " + this.state + ".";
  7010. this.logger.warn(message);
  7011. return;
  7012. };
  7013. /**
  7014. * Receive responses from TU for this transaction.
  7015. * @param statusCode - Status code of response.
  7016. * @param response - Response.
  7017. */
  7018. InviteServerTransaction.prototype.receiveResponse = function (statusCode, response) {
  7019. var _this = this;
  7020. if (statusCode < 100 || statusCode > 699) {
  7021. throw new Error("Invalid status code " + statusCode);
  7022. }
  7023. switch (this.state) {
  7024. case transaction_state_1.TransactionState.Proceeding:
  7025. // The TU passes any number of provisional responses to the server
  7026. // transaction. So long as the server transaction is in the
  7027. // "Proceeding" state, each of these MUST be passed to the transport
  7028. // layer for transmission. They are not sent reliably by the
  7029. // transaction layer (they are not retransmitted by it) and do not cause
  7030. // a change in the state of the server transaction.
  7031. // https://tools.ietf.org/html/rfc3261#section-17.2.1
  7032. if (statusCode >= 100 && statusCode <= 199) {
  7033. this.lastProvisionalResponse = response;
  7034. // Start the progress extension timer only for a non-100 provisional response.
  7035. if (statusCode > 100) {
  7036. this.startProgressExtensionTimer(); // FIXME: remove
  7037. }
  7038. this.send(response).catch(function (error) {
  7039. _this.logTransportError(error, "Failed to send 1xx response.");
  7040. });
  7041. return;
  7042. }
  7043. // If, while in the "Proceeding" state, the TU passes a 2xx response
  7044. // to the server transaction, the server transaction MUST pass this
  7045. // response to the transport layer for transmission. It is not
  7046. // retransmitted by the server transaction; retransmissions of 2xx
  7047. // responses are handled by the TU. The server transaction MUST then
  7048. // transition to the "Accepted" state.
  7049. // https://tools.ietf.org/html/rfc6026#section-8.5
  7050. if (statusCode >= 200 && statusCode <= 299) {
  7051. this.lastFinalResponse = response;
  7052. this.stateTransition(transaction_state_1.TransactionState.Accepted);
  7053. this.send(response).catch(function (error) {
  7054. _this.logTransportError(error, "Failed to send 2xx response.");
  7055. });
  7056. return;
  7057. }
  7058. // While in the "Proceeding" state, if the TU passes a response with
  7059. // status code from 300 to 699 to the server transaction, the response
  7060. // MUST be passed to the transport layer for transmission, and the state
  7061. // machine MUST enter the "Completed" state.
  7062. // https://tools.ietf.org/html/rfc3261#section-17.2.1
  7063. if (statusCode >= 300 && statusCode <= 699) {
  7064. this.lastFinalResponse = response;
  7065. this.stateTransition(transaction_state_1.TransactionState.Completed);
  7066. this.send(response).catch(function (error) {
  7067. _this.logTransportError(error, "Failed to send non-2xx final response.");
  7068. });
  7069. return;
  7070. }
  7071. break;
  7072. case transaction_state_1.TransactionState.Accepted:
  7073. // While in the "Accepted" state, if the TU passes a 2xx response,
  7074. // the server transaction MUST pass the response to the transport layer for transmission.
  7075. // https://tools.ietf.org/html/rfc6026#section-8.7
  7076. if (statusCode >= 200 && statusCode <= 299) {
  7077. this.send(response).catch(function (error) {
  7078. _this.logTransportError(error, "Failed to send 2xx response.");
  7079. });
  7080. return;
  7081. }
  7082. break;
  7083. case transaction_state_1.TransactionState.Completed:
  7084. break;
  7085. case transaction_state_1.TransactionState.Confirmed:
  7086. break;
  7087. case transaction_state_1.TransactionState.Terminated:
  7088. break;
  7089. default:
  7090. throw new Error("Invalid state " + this.state);
  7091. }
  7092. var message = "INVITE server transaction received unexpected " + statusCode + " response from TU while in state " + this.state + ".";
  7093. this.logger.error(message);
  7094. throw new Error(message);
  7095. };
  7096. /**
  7097. * Retransmit the last 2xx response. This is a noop if not in the "accepted" state.
  7098. */
  7099. InviteServerTransaction.prototype.retransmitAcceptedResponse = function () {
  7100. var _this = this;
  7101. if (this.state === transaction_state_1.TransactionState.Accepted && this.lastFinalResponse) {
  7102. this.send(this.lastFinalResponse).catch(function (error) {
  7103. _this.logTransportError(error, "Failed to send 2xx response.");
  7104. });
  7105. }
  7106. };
  7107. /**
  7108. * First, the procedures in [4] are followed, which attempt to deliver the response to a backup.
  7109. * If those should all fail, based on the definition of failure in [4], the server transaction SHOULD
  7110. * inform the TU that a failure has occurred, and MUST remain in the current state.
  7111. * https://tools.ietf.org/html/rfc6026#section-8.8
  7112. */
  7113. InviteServerTransaction.prototype.onTransportError = function (error) {
  7114. if (this.user.onTransportError) {
  7115. this.user.onTransportError(error);
  7116. }
  7117. };
  7118. /** For logging. */
  7119. InviteServerTransaction.prototype.typeToString = function () {
  7120. return "INVITE server transaction";
  7121. };
  7122. /**
  7123. * Execute a state transition.
  7124. * @param newState - New state.
  7125. */
  7126. InviteServerTransaction.prototype.stateTransition = function (newState) {
  7127. var _this = this;
  7128. // Assert valid state transitions.
  7129. var invalidStateTransition = function () {
  7130. throw new Error("Invalid state transition from " + _this.state + " to " + newState);
  7131. };
  7132. switch (newState) {
  7133. case transaction_state_1.TransactionState.Proceeding:
  7134. invalidStateTransition();
  7135. break;
  7136. case transaction_state_1.TransactionState.Accepted:
  7137. case transaction_state_1.TransactionState.Completed:
  7138. if (this.state !== transaction_state_1.TransactionState.Proceeding) {
  7139. invalidStateTransition();
  7140. }
  7141. break;
  7142. case transaction_state_1.TransactionState.Confirmed:
  7143. if (this.state !== transaction_state_1.TransactionState.Completed) {
  7144. invalidStateTransition();
  7145. }
  7146. break;
  7147. case transaction_state_1.TransactionState.Terminated:
  7148. if (this.state !== transaction_state_1.TransactionState.Accepted &&
  7149. this.state !== transaction_state_1.TransactionState.Completed &&
  7150. this.state !== transaction_state_1.TransactionState.Confirmed) {
  7151. invalidStateTransition();
  7152. }
  7153. break;
  7154. default:
  7155. invalidStateTransition();
  7156. }
  7157. // On any state transition, stop resending provisonal responses
  7158. this.stopProgressExtensionTimer();
  7159. // The purpose of the "Accepted" state is to absorb retransmissions of an accepted INVITE request.
  7160. // Any such retransmissions are absorbed entirely within the server transaction.
  7161. // They are not passed up to the TU since any downstream UAS cores that accepted the request have
  7162. // taken responsibility for reliability and will already retransmit their 2xx responses if necessary.
  7163. // https://tools.ietf.org/html/rfc6026#section-8.7
  7164. if (newState === transaction_state_1.TransactionState.Accepted) {
  7165. this.L = setTimeout(function () { return _this.timer_L(); }, timers_1.Timers.TIMER_L);
  7166. }
  7167. // When the "Completed" state is entered, timer H MUST be set to fire in 64*T1 seconds for all transports.
  7168. // Timer H determines when the server transaction abandons retransmitting the response.
  7169. // If an ACK is received while the server transaction is in the "Completed" state,
  7170. // the server transaction MUST transition to the "Confirmed" state.
  7171. // https://tools.ietf.org/html/rfc3261#section-17.2.1
  7172. if (newState === transaction_state_1.TransactionState.Completed) {
  7173. // FIXME: Missing timer G for unreliable transports.
  7174. this.H = setTimeout(function () { return _this.timer_H(); }, timers_1.Timers.TIMER_H);
  7175. }
  7176. // The purpose of the "Confirmed" state is to absorb any additional ACK messages that arrive,
  7177. // triggered from retransmissions of the final response. When this state is entered, timer I
  7178. // is set to fire in T4 seconds for unreliable transports, and zero seconds for reliable
  7179. // transports. Once timer I fires, the server MUST transition to the "Terminated" state.
  7180. // https://tools.ietf.org/html/rfc3261#section-17.2.1
  7181. if (newState === transaction_state_1.TransactionState.Confirmed) {
  7182. // FIXME: This timer is not getting set correctly for unreliable transports.
  7183. this.I = setTimeout(function () { return _this.timer_I(); }, timers_1.Timers.TIMER_I);
  7184. }
  7185. // Once the transaction is in the "Terminated" state, it MUST be destroyed immediately.
  7186. // https://tools.ietf.org/html/rfc6026#section-8.7
  7187. if (newState === transaction_state_1.TransactionState.Terminated) {
  7188. this.dispose();
  7189. }
  7190. // Update state.
  7191. this.setState(newState);
  7192. };
  7193. /**
  7194. * FIXME: UAS Provisional Retransmission Timer. See RFC 3261 Section 13.3.1.1
  7195. * This is in the wrong place. This is not a transaction level thing. It's a UAS level thing.
  7196. */
  7197. InviteServerTransaction.prototype.startProgressExtensionTimer = function () {
  7198. var _this = this;
  7199. // Start the progress extension timer only for the first non-100 provisional response.
  7200. if (this.progressExtensionTimer === undefined) {
  7201. this.progressExtensionTimer = setInterval(function () {
  7202. _this.logger.debug("Progress extension timer expired for INVITE server transaction " + _this.id + ".");
  7203. if (!_this.lastProvisionalResponse) {
  7204. throw new Error("Last provisional response undefined.");
  7205. }
  7206. _this.send(_this.lastProvisionalResponse).catch(function (error) {
  7207. _this.logTransportError(error, "Failed to send retransmission of provisional response.");
  7208. });
  7209. }, timers_1.Timers.PROVISIONAL_RESPONSE_INTERVAL);
  7210. }
  7211. };
  7212. /**
  7213. * FIXME: UAS Provisional Retransmission Timer id. See RFC 3261 Section 13.3.1.1
  7214. * This is in the wrong place. This is not a transaction level thing. It's a UAS level thing.
  7215. */
  7216. InviteServerTransaction.prototype.stopProgressExtensionTimer = function () {
  7217. if (this.progressExtensionTimer !== undefined) {
  7218. clearInterval(this.progressExtensionTimer);
  7219. this.progressExtensionTimer = undefined;
  7220. }
  7221. };
  7222. /**
  7223. * While in the "Proceeding" state, if the TU passes a response with status code
  7224. * from 300 to 699 to the server transaction, the response MUST be passed to the
  7225. * transport layer for transmission, and the state machine MUST enter the "Completed" state.
  7226. * For unreliable transports, timer G is set to fire in T1 seconds, and is not set to fire for
  7227. * reliable transports. If timer G fires, the response is passed to the transport layer once
  7228. * more for retransmission, and timer G is set to fire in MIN(2*T1, T2) seconds. From then on,
  7229. * when timer G fires, the response is passed to the transport again for transmission, and
  7230. * timer G is reset with a value that doubles, unless that value exceeds T2, in which case
  7231. * it is reset with the value of T2.
  7232. * https://tools.ietf.org/html/rfc3261#section-17.2.1
  7233. */
  7234. InviteServerTransaction.prototype.timer_G = function () {
  7235. // TODO
  7236. };
  7237. /**
  7238. * If timer H fires while in the "Completed" state, it implies that the ACK was never received.
  7239. * In this case, the server transaction MUST transition to the "Terminated" state, and MUST
  7240. * indicate to the TU that a transaction failure has occurred.
  7241. * https://tools.ietf.org/html/rfc3261#section-17.2.1
  7242. */
  7243. InviteServerTransaction.prototype.timer_H = function () {
  7244. this.logger.debug("Timer H expired for INVITE server transaction " + this.id + ".");
  7245. if (this.state === transaction_state_1.TransactionState.Completed) {
  7246. this.logger.warn("ACK to negative final response was never received, terminating transaction.");
  7247. this.stateTransition(transaction_state_1.TransactionState.Terminated);
  7248. }
  7249. };
  7250. /**
  7251. * Once timer I fires, the server MUST transition to the "Terminated" state.
  7252. * https://tools.ietf.org/html/rfc3261#section-17.2.1
  7253. */
  7254. InviteServerTransaction.prototype.timer_I = function () {
  7255. this.logger.debug("Timer I expired for INVITE server transaction " + this.id + ".");
  7256. this.stateTransition(transaction_state_1.TransactionState.Terminated);
  7257. };
  7258. /**
  7259. * When Timer L fires and the state machine is in the "Accepted" state, the machine MUST
  7260. * transition to the "Terminated" state. Once the transaction is in the "Terminated" state,
  7261. * it MUST be destroyed immediately. Timer L reflects the amount of time the server
  7262. * transaction could receive 2xx responses for retransmission from the
  7263. * TU while it is waiting to receive an ACK.
  7264. * https://tools.ietf.org/html/rfc6026#section-7.1
  7265. * https://tools.ietf.org/html/rfc6026#section-8.7
  7266. */
  7267. InviteServerTransaction.prototype.timer_L = function () {
  7268. this.logger.debug("Timer L expired for INVITE server transaction " + this.id + ".");
  7269. if (this.state === transaction_state_1.TransactionState.Accepted) {
  7270. this.stateTransition(transaction_state_1.TransactionState.Terminated);
  7271. }
  7272. };
  7273. return InviteServerTransaction;
  7274. }(server_transaction_1.ServerTransaction));
  7275. exports.InviteServerTransaction = InviteServerTransaction;
  7276. /***/ }),
  7277. /* 38 */
  7278. /***/ (function(module, exports, __webpack_require__) {
  7279. "use strict";
  7280. Object.defineProperty(exports, "__esModule", { value: true });
  7281. var tslib_1 = __webpack_require__(1);
  7282. var transaction_1 = __webpack_require__(29);
  7283. /**
  7284. * Server Transaction.
  7285. * @remarks
  7286. * The server transaction is responsible for the delivery of requests to
  7287. * the TU and the reliable transmission of responses. It accomplishes
  7288. * this through a state machine. Server transactions are created by the
  7289. * core when a request is received, and transaction handling is desired
  7290. * for that request (this is not always the case).
  7291. * https://tools.ietf.org/html/rfc3261#section-17.2
  7292. * @public
  7293. */
  7294. var ServerTransaction = /** @class */ (function (_super) {
  7295. tslib_1.__extends(ServerTransaction, _super);
  7296. function ServerTransaction(_request, transport, user, state, loggerCategory) {
  7297. var _this = _super.call(this, transport, user, _request.viaBranch, state, loggerCategory) || this;
  7298. _this._request = _request;
  7299. _this.user = user;
  7300. return _this;
  7301. }
  7302. Object.defineProperty(ServerTransaction.prototype, "request", {
  7303. /** The incoming request the transaction handling. */
  7304. get: function () {
  7305. return this._request;
  7306. },
  7307. enumerable: true,
  7308. configurable: true
  7309. });
  7310. return ServerTransaction;
  7311. }(transaction_1.Transaction));
  7312. exports.ServerTransaction = ServerTransaction;
  7313. /***/ }),
  7314. /* 39 */
  7315. /***/ (function(module, exports, __webpack_require__) {
  7316. "use strict";
  7317. Object.defineProperty(exports, "__esModule", { value: true });
  7318. var tslib_1 = __webpack_require__(1);
  7319. var timers_1 = __webpack_require__(26);
  7320. var client_transaction_1 = __webpack_require__(28);
  7321. var transaction_state_1 = __webpack_require__(36);
  7322. /**
  7323. * Non-INVITE Client Transaction.
  7324. * @remarks
  7325. * Non-INVITE transactions do not make use of ACK.
  7326. * They are simple request-response interactions.
  7327. * https://tools.ietf.org/html/rfc3261#section-17.1.2
  7328. * @public
  7329. */
  7330. var NonInviteClientTransaction = /** @class */ (function (_super) {
  7331. tslib_1.__extends(NonInviteClientTransaction, _super);
  7332. /**
  7333. * Constructor
  7334. * Upon construction, the outgoing request's Via header is updated by calling `setViaHeader`.
  7335. * Then `toString` is called on the outgoing request and the message is sent via the transport.
  7336. * After construction the transaction will be in the "calling" state and the transaction id
  7337. * will equal the branch parameter set in the Via header of the outgoing request.
  7338. * https://tools.ietf.org/html/rfc3261#section-17.1.2
  7339. * @param request - The outgoing Non-INVITE request.
  7340. * @param transport - The transport.
  7341. * @param user - The transaction user.
  7342. */
  7343. function NonInviteClientTransaction(request, transport, user) {
  7344. var _this = _super.call(this, request, transport, user, transaction_state_1.TransactionState.Trying, "sip.transaction.nict") || this;
  7345. // FIXME: Timer E for unreliable transports not implemented.
  7346. //
  7347. // The "Trying" state is entered when the TU initiates a new client
  7348. // transaction with a request. When entering this state, the client
  7349. // transaction SHOULD set timer F to fire in 64*T1 seconds. The request
  7350. // MUST be passed to the transport layer for transmission.
  7351. // https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7352. _this.F = setTimeout(function () { return _this.timer_F(); }, timers_1.Timers.TIMER_F);
  7353. _this.send(request.toString()).catch(function (error) {
  7354. _this.logTransportError(error, "Failed to send initial outgoing request.");
  7355. });
  7356. return _this;
  7357. }
  7358. /**
  7359. * Destructor.
  7360. */
  7361. NonInviteClientTransaction.prototype.dispose = function () {
  7362. if (this.F) {
  7363. clearTimeout(this.F);
  7364. this.F = undefined;
  7365. }
  7366. if (this.K) {
  7367. clearTimeout(this.K);
  7368. this.K = undefined;
  7369. }
  7370. _super.prototype.dispose.call(this);
  7371. };
  7372. Object.defineProperty(NonInviteClientTransaction.prototype, "kind", {
  7373. /** Transaction kind. Deprecated. */
  7374. get: function () {
  7375. return "nict";
  7376. },
  7377. enumerable: true,
  7378. configurable: true
  7379. });
  7380. /**
  7381. * Handler for incoming responses from the transport which match this transaction.
  7382. * @param response - The incoming response.
  7383. */
  7384. NonInviteClientTransaction.prototype.receiveResponse = function (response) {
  7385. var statusCode = response.statusCode;
  7386. if (!statusCode || statusCode < 100 || statusCode > 699) {
  7387. throw new Error("Invalid status code " + statusCode);
  7388. }
  7389. switch (this.state) {
  7390. case transaction_state_1.TransactionState.Trying:
  7391. // If a provisional response is received while in the "Trying" state, the
  7392. // response MUST be passed to the TU, and then the client transaction
  7393. // SHOULD move to the "Proceeding" state.
  7394. // https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7395. if (statusCode >= 100 && statusCode <= 199) {
  7396. this.stateTransition(transaction_state_1.TransactionState.Proceeding);
  7397. if (this.user.receiveResponse) {
  7398. this.user.receiveResponse(response);
  7399. }
  7400. return;
  7401. }
  7402. // If a final response (status codes 200-699) is received while in the
  7403. // "Trying" state, the response MUST be passed to the TU, and the
  7404. // client transaction MUST transition to the "Completed" state.
  7405. // https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7406. if (statusCode >= 200 && statusCode <= 699) {
  7407. this.stateTransition(transaction_state_1.TransactionState.Completed);
  7408. if (statusCode === 408) {
  7409. this.onRequestTimeout();
  7410. return;
  7411. }
  7412. if (this.user.receiveResponse) {
  7413. this.user.receiveResponse(response);
  7414. }
  7415. return;
  7416. }
  7417. break;
  7418. case transaction_state_1.TransactionState.Proceeding:
  7419. // If a provisional response is received while in the "Proceeding" state,
  7420. // the response MUST be passed to the TU. (From Figure 6)
  7421. // https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7422. if (statusCode >= 100 && statusCode <= 199) {
  7423. if (this.user.receiveResponse) {
  7424. return this.user.receiveResponse(response);
  7425. }
  7426. }
  7427. // If a final response (status codes 200-699) is received while in the
  7428. // "Proceeding" state, the response MUST be passed to the TU, and the
  7429. // client transaction MUST transition to the "Completed" state.
  7430. // https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7431. if (statusCode >= 200 && statusCode <= 699) {
  7432. this.stateTransition(transaction_state_1.TransactionState.Completed);
  7433. if (statusCode === 408) {
  7434. this.onRequestTimeout();
  7435. return;
  7436. }
  7437. if (this.user.receiveResponse) {
  7438. this.user.receiveResponse(response);
  7439. }
  7440. return;
  7441. }
  7442. case transaction_state_1.TransactionState.Completed:
  7443. // The "Completed" state exists to buffer any additional response
  7444. // retransmissions that may be received (which is why the client
  7445. // transaction remains there only for unreliable transports).
  7446. // https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7447. return;
  7448. case transaction_state_1.TransactionState.Terminated:
  7449. // For good measure just absorb additional response retransmissions.
  7450. return;
  7451. default:
  7452. throw new Error("Invalid state " + this.state);
  7453. }
  7454. var message = "Non-INVITE client transaction received unexpected " + statusCode + " response while in state " + this.state + ".";
  7455. this.logger.warn(message);
  7456. return;
  7457. };
  7458. /**
  7459. * The client transaction SHOULD inform the TU that a transport failure has occurred,
  7460. * and the client transaction SHOULD transition directly to the "Terminated" state.
  7461. * The TU will handle the failover mechanisms described in [4].
  7462. * https://tools.ietf.org/html/rfc3261#section-17.1.4
  7463. * @param error - Trasnsport error
  7464. */
  7465. NonInviteClientTransaction.prototype.onTransportError = function (error) {
  7466. if (this.user.onTransportError) {
  7467. this.user.onTransportError(error);
  7468. }
  7469. this.stateTransition(transaction_state_1.TransactionState.Terminated, true);
  7470. };
  7471. /** For logging. */
  7472. NonInviteClientTransaction.prototype.typeToString = function () {
  7473. return "non-INVITE client transaction";
  7474. };
  7475. /**
  7476. * Execute a state transition.
  7477. * @param newState - New state.
  7478. */
  7479. NonInviteClientTransaction.prototype.stateTransition = function (newState, dueToTransportError) {
  7480. var _this = this;
  7481. if (dueToTransportError === void 0) { dueToTransportError = false; }
  7482. // Assert valid state transitions.
  7483. var invalidStateTransition = function () {
  7484. throw new Error("Invalid state transition from " + _this.state + " to " + newState);
  7485. };
  7486. switch (newState) {
  7487. case transaction_state_1.TransactionState.Trying:
  7488. invalidStateTransition();
  7489. break;
  7490. case transaction_state_1.TransactionState.Proceeding:
  7491. if (this.state !== transaction_state_1.TransactionState.Trying) {
  7492. invalidStateTransition();
  7493. }
  7494. break;
  7495. case transaction_state_1.TransactionState.Completed:
  7496. if (this.state !== transaction_state_1.TransactionState.Trying &&
  7497. this.state !== transaction_state_1.TransactionState.Proceeding) {
  7498. invalidStateTransition();
  7499. }
  7500. break;
  7501. case transaction_state_1.TransactionState.Terminated:
  7502. if (this.state !== transaction_state_1.TransactionState.Trying &&
  7503. this.state !== transaction_state_1.TransactionState.Proceeding &&
  7504. this.state !== transaction_state_1.TransactionState.Completed) {
  7505. if (!dueToTransportError) {
  7506. invalidStateTransition();
  7507. }
  7508. }
  7509. break;
  7510. default:
  7511. invalidStateTransition();
  7512. }
  7513. // Once the client transaction enters the "Completed" state, it MUST set
  7514. // Timer K to fire in T4 seconds for unreliable transports, and zero
  7515. // seconds for reliable transports The "Completed" state exists to
  7516. // buffer any additional response retransmissions that may be received
  7517. // (which is why the client transaction remains there only for unreliable transports).
  7518. // https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7519. if (newState === transaction_state_1.TransactionState.Completed) {
  7520. if (this.F) {
  7521. clearTimeout(this.F);
  7522. this.F = undefined;
  7523. }
  7524. this.K = setTimeout(function () { return _this.timer_K(); }, timers_1.Timers.TIMER_K);
  7525. }
  7526. // Once the transaction is in the terminated state, it MUST be destroyed immediately.
  7527. // https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7528. if (newState === transaction_state_1.TransactionState.Terminated) {
  7529. this.dispose();
  7530. }
  7531. // Update state.
  7532. this.setState(newState);
  7533. };
  7534. /**
  7535. * If Timer F fires while the client transaction is still in the
  7536. * "Trying" state, the client transaction SHOULD inform the TU about the
  7537. * timeout, and then it SHOULD enter the "Terminated" state.
  7538. * If timer F fires while in the "Proceeding" state, the TU MUST be informed of
  7539. * a timeout, and the client transaction MUST transition to the terminated state.
  7540. * https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7541. */
  7542. NonInviteClientTransaction.prototype.timer_F = function () {
  7543. this.logger.debug("Timer F expired for non-INVITE client transaction " + this.id + ".");
  7544. if (this.state === transaction_state_1.TransactionState.Trying || this.state === transaction_state_1.TransactionState.Proceeding) {
  7545. this.onRequestTimeout();
  7546. this.stateTransition(transaction_state_1.TransactionState.Terminated);
  7547. }
  7548. };
  7549. /**
  7550. * If Timer K fires while in this (COMPLETED) state, the client transaction
  7551. * MUST transition to the "Terminated" state.
  7552. * https://tools.ietf.org/html/rfc3261#section-17.1.2.2
  7553. */
  7554. NonInviteClientTransaction.prototype.timer_K = function () {
  7555. if (this.state === transaction_state_1.TransactionState.Completed) {
  7556. this.stateTransition(transaction_state_1.TransactionState.Terminated);
  7557. }
  7558. };
  7559. return NonInviteClientTransaction;
  7560. }(client_transaction_1.ClientTransaction));
  7561. exports.NonInviteClientTransaction = NonInviteClientTransaction;
  7562. /***/ }),
  7563. /* 40 */
  7564. /***/ (function(module, exports, __webpack_require__) {
  7565. "use strict";
  7566. Object.defineProperty(exports, "__esModule", { value: true });
  7567. var tslib_1 = __webpack_require__(1);
  7568. var timers_1 = __webpack_require__(26);
  7569. var server_transaction_1 = __webpack_require__(38);
  7570. var transaction_state_1 = __webpack_require__(36);
  7571. /**
  7572. * Non-INVITE Server Transaction.
  7573. * @remarks
  7574. * https://tools.ietf.org/html/rfc3261#section-17.2.2
  7575. * @public
  7576. */
  7577. var NonInviteServerTransaction = /** @class */ (function (_super) {
  7578. tslib_1.__extends(NonInviteServerTransaction, _super);
  7579. /**
  7580. * Constructor.
  7581. * After construction the transaction will be in the "trying": state and the transaction
  7582. * `id` will equal the branch parameter set in the Via header of the incoming request.
  7583. * https://tools.ietf.org/html/rfc3261#section-17.2.2
  7584. * @param request - Incoming Non-INVITE request from the transport.
  7585. * @param transport - The transport.
  7586. * @param user - The transaction user.
  7587. */
  7588. function NonInviteServerTransaction(request, transport, user) {
  7589. return _super.call(this, request, transport, user, transaction_state_1.TransactionState.Trying, "sip.transaction.nist") || this;
  7590. }
  7591. /**
  7592. * Destructor.
  7593. */
  7594. NonInviteServerTransaction.prototype.dispose = function () {
  7595. if (this.J) {
  7596. clearTimeout(this.J);
  7597. this.J = undefined;
  7598. }
  7599. _super.prototype.dispose.call(this);
  7600. };
  7601. Object.defineProperty(NonInviteServerTransaction.prototype, "kind", {
  7602. /** Transaction kind. Deprecated. */
  7603. get: function () {
  7604. return "nist";
  7605. },
  7606. enumerable: true,
  7607. configurable: true
  7608. });
  7609. /**
  7610. * Receive requests from transport matching this transaction.
  7611. * @param request - Request matching this transaction.
  7612. */
  7613. NonInviteServerTransaction.prototype.receiveRequest = function (request) {
  7614. var _this = this;
  7615. switch (this.state) {
  7616. case transaction_state_1.TransactionState.Trying:
  7617. // Once in the "Trying" state, any further request retransmissions are discarded.
  7618. // https://tools.ietf.org/html/rfc3261#section-17.2.2
  7619. break;
  7620. case transaction_state_1.TransactionState.Proceeding:
  7621. // If a retransmission of the request is received while in the "Proceeding" state,
  7622. // the most recently sent provisional response MUST be passed to the transport layer for retransmission.
  7623. // https://tools.ietf.org/html/rfc3261#section-17.2.2
  7624. if (!this.lastResponse) {
  7625. throw new Error("Last response undefined.");
  7626. }
  7627. this.send(this.lastResponse).catch(function (error) {
  7628. _this.logTransportError(error, "Failed to send retransmission of provisional response.");
  7629. });
  7630. break;
  7631. case transaction_state_1.TransactionState.Completed:
  7632. // While in the "Completed" state, the server transaction MUST pass the final response to the transport
  7633. // layer for retransmission whenever a retransmission of the request is received. Any other final responses
  7634. // passed by the TU to the server transaction MUST be discarded while in the "Completed" state.
  7635. // https://tools.ietf.org/html/rfc3261#section-17.2.2
  7636. if (!this.lastResponse) {
  7637. throw new Error("Last response undefined.");
  7638. }
  7639. this.send(this.lastResponse).catch(function (error) {
  7640. _this.logTransportError(error, "Failed to send retransmission of final response.");
  7641. });
  7642. break;
  7643. case transaction_state_1.TransactionState.Terminated:
  7644. break;
  7645. default:
  7646. throw new Error("Invalid state " + this.state);
  7647. }
  7648. };
  7649. /**
  7650. * Receive responses from TU for this transaction.
  7651. * @param statusCode - Status code of repsonse. 101-199 not allowed per RFC 4320.
  7652. * @param response - Response to send.
  7653. */
  7654. NonInviteServerTransaction.prototype.receiveResponse = function (statusCode, response) {
  7655. var _this = this;
  7656. if (statusCode < 100 || statusCode > 699) {
  7657. throw new Error("Invalid status code " + statusCode);
  7658. }
  7659. // An SIP element MUST NOT send any provisional response with a
  7660. // Status-Code other than 100 to a non-INVITE request.
  7661. // An SIP element MUST NOT respond to a non-INVITE request with a
  7662. // Status-Code of 100 over any unreliable transport, such as UDP,
  7663. // before the amount of time it takes a client transaction's Timer E to be reset to T2.
  7664. // An SIP element MAY respond to a non-INVITE request with a
  7665. // Status-Code of 100 over a reliable transport at any time.
  7666. // https://tools.ietf.org/html/rfc4320#section-4.1
  7667. if (statusCode > 100 && statusCode <= 199) {
  7668. throw new Error("Provisional response other than 100 not allowed.");
  7669. }
  7670. switch (this.state) {
  7671. case transaction_state_1.TransactionState.Trying:
  7672. // While in the "Trying" state, if the TU passes a provisional response
  7673. // to the server transaction, the server transaction MUST enter the "Proceeding" state.
  7674. // The response MUST be passed to the transport layer for transmission.
  7675. // https://tools.ietf.org/html/rfc3261#section-17.2.2
  7676. this.lastResponse = response;
  7677. if (statusCode >= 100 && statusCode < 200) {
  7678. this.stateTransition(transaction_state_1.TransactionState.Proceeding);
  7679. this.send(response).catch(function (error) {
  7680. _this.logTransportError(error, "Failed to send provisional response.");
  7681. });
  7682. return;
  7683. }
  7684. if (statusCode >= 200 && statusCode <= 699) {
  7685. this.stateTransition(transaction_state_1.TransactionState.Completed);
  7686. this.send(response).catch(function (error) {
  7687. _this.logTransportError(error, "Failed to send final response.");
  7688. });
  7689. return;
  7690. }
  7691. break;
  7692. case transaction_state_1.TransactionState.Proceeding:
  7693. // Any further provisional responses that are received from the TU while
  7694. // in the "Proceeding" state MUST be passed to the transport layer for transmission.
  7695. // If the TU passes a final response (status codes 200-699) to the server while in
  7696. // the "Proceeding" state, the transaction MUST enter the "Completed" state, and
  7697. // the response MUST be passed to the transport layer for transmission.
  7698. // https://tools.ietf.org/html/rfc3261#section-17.2.2
  7699. this.lastResponse = response;
  7700. if (statusCode >= 200 && statusCode <= 699) {
  7701. this.stateTransition(transaction_state_1.TransactionState.Completed);
  7702. this.send(response).catch(function (error) {
  7703. _this.logTransportError(error, "Failed to send final response.");
  7704. });
  7705. return;
  7706. }
  7707. break;
  7708. case transaction_state_1.TransactionState.Completed:
  7709. // Any other final responses passed by the TU to the server
  7710. // transaction MUST be discarded while in the "Completed" state.
  7711. // https://tools.ietf.org/html/rfc3261#section-17.2.2
  7712. return;
  7713. case transaction_state_1.TransactionState.Terminated:
  7714. break;
  7715. default:
  7716. throw new Error("Invalid state " + this.state);
  7717. }
  7718. var message = "Non-INVITE server transaction received unexpected " + statusCode + " response from TU while in state " + this.state + ".";
  7719. this.logger.error(message);
  7720. throw new Error(message);
  7721. };
  7722. /**
  7723. * First, the procedures in [4] are followed, which attempt to deliver the response to a backup.
  7724. * If those should all fail, based on the definition of failure in [4], the server transaction SHOULD
  7725. * inform the TU that a failure has occurred, and SHOULD transition to the terminated state.
  7726. * https://tools.ietf.org/html/rfc3261#section-17.2.4
  7727. */
  7728. NonInviteServerTransaction.prototype.onTransportError = function (error) {
  7729. if (this.user.onTransportError) {
  7730. this.user.onTransportError(error);
  7731. }
  7732. this.stateTransition(transaction_state_1.TransactionState.Terminated, true);
  7733. };
  7734. /** For logging. */
  7735. NonInviteServerTransaction.prototype.typeToString = function () {
  7736. return "non-INVITE server transaction";
  7737. };
  7738. NonInviteServerTransaction.prototype.stateTransition = function (newState, dueToTransportError) {
  7739. var _this = this;
  7740. if (dueToTransportError === void 0) { dueToTransportError = false; }
  7741. // Assert valid state transitions.
  7742. var invalidStateTransition = function () {
  7743. throw new Error("Invalid state transition from " + _this.state + " to " + newState);
  7744. };
  7745. switch (newState) {
  7746. case transaction_state_1.TransactionState.Trying:
  7747. invalidStateTransition();
  7748. break;
  7749. case transaction_state_1.TransactionState.Proceeding:
  7750. if (this.state !== transaction_state_1.TransactionState.Trying) {
  7751. invalidStateTransition();
  7752. }
  7753. break;
  7754. case transaction_state_1.TransactionState.Completed:
  7755. if (this.state !== transaction_state_1.TransactionState.Trying && this.state !== transaction_state_1.TransactionState.Proceeding) {
  7756. invalidStateTransition();
  7757. }
  7758. break;
  7759. case transaction_state_1.TransactionState.Terminated:
  7760. if (this.state !== transaction_state_1.TransactionState.Proceeding && this.state !== transaction_state_1.TransactionState.Completed) {
  7761. if (!dueToTransportError) {
  7762. invalidStateTransition();
  7763. }
  7764. }
  7765. break;
  7766. default:
  7767. invalidStateTransition();
  7768. }
  7769. // When the server transaction enters the "Completed" state, it MUST set Timer J to fire
  7770. // in 64*T1 seconds for unreliable transports, and zero seconds for reliable transports.
  7771. // https://tools.ietf.org/html/rfc3261#section-17.2.2
  7772. if (newState === transaction_state_1.TransactionState.Completed) {
  7773. this.J = setTimeout(function () { return _this.timer_J(); }, timers_1.Timers.TIMER_J);
  7774. }
  7775. // The server transaction MUST be destroyed the instant it enters the "Terminated" state.
  7776. // https://tools.ietf.org/html/rfc3261#section-17.2.2
  7777. if (newState === transaction_state_1.TransactionState.Terminated) {
  7778. this.dispose();
  7779. }
  7780. this.setState(newState);
  7781. };
  7782. /**
  7783. * The server transaction remains in this state until Timer J fires,
  7784. * at which point it MUST transition to the "Terminated" state.
  7785. * https://tools.ietf.org/html/rfc3261#section-17.2.2
  7786. */
  7787. NonInviteServerTransaction.prototype.timer_J = function () {
  7788. this.logger.debug("Timer J expired for NON-INVITE server transaction " + this.id + ".");
  7789. if (this.state === transaction_state_1.TransactionState.Completed) {
  7790. this.stateTransition(transaction_state_1.TransactionState.Terminated);
  7791. }
  7792. };
  7793. return NonInviteServerTransaction;
  7794. }(server_transaction_1.ServerTransaction));
  7795. exports.NonInviteServerTransaction = NonInviteServerTransaction;
  7796. /***/ }),
  7797. /* 41 */
  7798. /***/ (function(module, exports, __webpack_require__) {
  7799. "use strict";
  7800. Object.defineProperty(exports, "__esModule", { value: true });
  7801. var tslib_1 = __webpack_require__(1);
  7802. var messages_1 = __webpack_require__(5);
  7803. var transactions_1 = __webpack_require__(27);
  7804. var user_agent_client_1 = __webpack_require__(42);
  7805. /**
  7806. * BYE UAC.
  7807. * @public
  7808. */
  7809. var ByeUserAgentClient = /** @class */ (function (_super) {
  7810. tslib_1.__extends(ByeUserAgentClient, _super);
  7811. function ByeUserAgentClient(dialog, delegate, options) {
  7812. var _this = this;
  7813. var message = dialog.createOutgoingRequestMessage(messages_1.C.BYE, options);
  7814. _this = _super.call(this, transactions_1.NonInviteClientTransaction, dialog.userAgentCore, message, delegate) || this;
  7815. dialog.dispose();
  7816. return _this;
  7817. }
  7818. return ByeUserAgentClient;
  7819. }(user_agent_client_1.UserAgentClient));
  7820. exports.ByeUserAgentClient = ByeUserAgentClient;
  7821. /***/ }),
  7822. /* 42 */
  7823. /***/ (function(module, exports, __webpack_require__) {
  7824. "use strict";
  7825. Object.defineProperty(exports, "__esModule", { value: true });
  7826. var messages_1 = __webpack_require__(5);
  7827. var transactions_1 = __webpack_require__(27);
  7828. /**
  7829. * User Agent Client (UAC).
  7830. * @remarks
  7831. * A user agent client is a logical entity
  7832. * that creates a new request, and then uses the client
  7833. * transaction state machinery to send it. The role of UAC lasts
  7834. * only for the duration of that transaction. In other words, if
  7835. * a piece of software initiates a request, it acts as a UAC for
  7836. * the duration of that transaction. If it receives a request
  7837. * later, it assumes the role of a user agent server for the
  7838. * processing of that transaction.
  7839. * https://tools.ietf.org/html/rfc3261#section-6
  7840. * @public
  7841. */
  7842. var UserAgentClient = /** @class */ (function () {
  7843. function UserAgentClient(transactionConstructor, core, message, delegate) {
  7844. this.transactionConstructor = transactionConstructor;
  7845. this.core = core;
  7846. this.message = message;
  7847. this.delegate = delegate;
  7848. this.challenged = false;
  7849. this.stale = false;
  7850. this.logger = this.loggerFactory.getLogger("sip.user-agent-client");
  7851. this.init();
  7852. }
  7853. UserAgentClient.prototype.dispose = function () {
  7854. this.transaction.dispose();
  7855. };
  7856. Object.defineProperty(UserAgentClient.prototype, "loggerFactory", {
  7857. get: function () {
  7858. return this.core.loggerFactory;
  7859. },
  7860. enumerable: true,
  7861. configurable: true
  7862. });
  7863. Object.defineProperty(UserAgentClient.prototype, "transaction", {
  7864. /** The transaction associated with this request. */
  7865. get: function () {
  7866. if (!this._transaction) {
  7867. throw new Error("Transaction undefined.");
  7868. }
  7869. return this._transaction;
  7870. },
  7871. enumerable: true,
  7872. configurable: true
  7873. });
  7874. /**
  7875. * Since requests other than INVITE are responded to immediately, sending a
  7876. * CANCEL for a non-INVITE request would always create a race condition.
  7877. * A CANCEL request SHOULD NOT be sent to cancel a request other than INVITE.
  7878. * https://tools.ietf.org/html/rfc3261#section-9.1
  7879. * @param options - Cancel options bucket.
  7880. */
  7881. UserAgentClient.prototype.cancel = function (reason, options) {
  7882. var _this = this;
  7883. if (options === void 0) { options = {}; }
  7884. if (!this.transaction) {
  7885. throw new Error("Transaction undefined.");
  7886. }
  7887. if (!this.message.to) {
  7888. throw new Error("To undefined.");
  7889. }
  7890. if (!this.message.from) {
  7891. throw new Error("From undefined.");
  7892. }
  7893. // The following procedures are used to construct a CANCEL request. The
  7894. // Request-URI, Call-ID, To, the numeric part of CSeq, and From header
  7895. // fields in the CANCEL request MUST be identical to those in the
  7896. // request being cancelled, including tags. A CANCEL constructed by a
  7897. // client MUST have only a single Via header field value matching the
  7898. // top Via value in the request being cancelled. Using the same values
  7899. // for these header fields allows the CANCEL to be matched with the
  7900. // request it cancels (Section 9.2 indicates how such matching occurs).
  7901. // However, the method part of the CSeq header field MUST have a value
  7902. // of CANCEL. This allows it to be identified and processed as a
  7903. // transaction in its own right (See Section 17).
  7904. // https://tools.ietf.org/html/rfc3261#section-9.1
  7905. var message = this.core.makeOutgoingRequestMessage(messages_1.C.CANCEL, this.message.ruri, this.message.from.uri, this.message.to.uri, {
  7906. toTag: this.message.toTag,
  7907. fromTag: this.message.fromTag,
  7908. callId: this.message.callId,
  7909. cseq: this.message.cseq
  7910. }, options.extraHeaders);
  7911. // TODO: Revisit this.
  7912. // The CANCEL needs to use the same branch parameter so that
  7913. // it matches the INVITE transaction, but this is a hacky way to do this.
  7914. // Or at the very least not well documented. If the the branch parameter
  7915. // is set on the outgoing request, the transaction will use it.
  7916. // Otherwise the transaction will make a new one.
  7917. message.branch = this.message.branch;
  7918. if (this.message.headers.Route) {
  7919. message.headers.Route = this.message.headers.Route;
  7920. }
  7921. if (reason) {
  7922. message.setHeader("Reason", reason);
  7923. }
  7924. // If no provisional response has been received, the CANCEL request MUST
  7925. // NOT be sent; rather, the client MUST wait for the arrival of a
  7926. // provisional response before sending the request. If the original
  7927. // request has generated a final response, the CANCEL SHOULD NOT be
  7928. // sent, as it is an effective no-op, since CANCEL has no effect on
  7929. // requests that have already generated a final response.
  7930. // https://tools.ietf.org/html/rfc3261#section-9.1
  7931. if (this.transaction.state === transactions_1.TransactionState.Proceeding) {
  7932. var uac = new UserAgentClient(transactions_1.NonInviteClientTransaction, this.core, message);
  7933. }
  7934. else {
  7935. this.transaction.once("stateChanged", function () {
  7936. if (_this.transaction && _this.transaction.state === transactions_1.TransactionState.Proceeding) {
  7937. var uac = new UserAgentClient(transactions_1.NonInviteClientTransaction, _this.core, message);
  7938. }
  7939. });
  7940. }
  7941. return message;
  7942. };
  7943. /**
  7944. * If a 401 (Unauthorized) or 407 (Proxy Authentication Required)
  7945. * response is received, the UAC SHOULD follow the authorization
  7946. * procedures of Section 22.2 and Section 22.3 to retry the request with
  7947. * credentials.
  7948. * https://tools.ietf.org/html/rfc3261#section-8.1.3.5
  7949. * 22 Usage of HTTP Authentication
  7950. * https://tools.ietf.org/html/rfc3261#section-22
  7951. * 22.1 Framework
  7952. * https://tools.ietf.org/html/rfc3261#section-22.1
  7953. * 22.2 User-to-User Authentication
  7954. * https://tools.ietf.org/html/rfc3261#section-22.2
  7955. * 22.3 Proxy-to-User Authentication
  7956. * https://tools.ietf.org/html/rfc3261#section-22.3
  7957. *
  7958. * FIXME: This "guard for and retry the request with credentials"
  7959. * implementation is not complete and at best minimally passable.
  7960. * @param response - The incoming response to guard.
  7961. * @returns True if the program execution is to continue in the branch in question.
  7962. * Otherwise the request is retried with credentials and current request processing must stop.
  7963. */
  7964. UserAgentClient.prototype.authenticationGuard = function (message) {
  7965. var statusCode = message.statusCode;
  7966. if (!statusCode) {
  7967. throw new Error("Response status code undefined.");
  7968. }
  7969. // If a 401 (Unauthorized) or 407 (Proxy Authentication Required)
  7970. // response is received, the UAC SHOULD follow the authorization
  7971. // procedures of Section 22.2 and Section 22.3 to retry the request with
  7972. // credentials.
  7973. // https://tools.ietf.org/html/rfc3261#section-8.1.3.5
  7974. if (statusCode !== 401 && statusCode !== 407) {
  7975. return true;
  7976. }
  7977. // Get and parse the appropriate WWW-Authenticate or Proxy-Authenticate header.
  7978. var challenge;
  7979. var authorizationHeaderName;
  7980. if (statusCode === 401) {
  7981. challenge = message.parseHeader("www-authenticate");
  7982. authorizationHeaderName = "authorization";
  7983. }
  7984. else {
  7985. challenge = message.parseHeader("proxy-authenticate");
  7986. authorizationHeaderName = "proxy-authorization";
  7987. }
  7988. // Verify it seems a valid challenge.
  7989. if (!challenge) {
  7990. this.logger.warn(statusCode + " with wrong or missing challenge, cannot authenticate");
  7991. return true;
  7992. }
  7993. // Avoid infinite authentications.
  7994. if (this.challenged && (this.stale || challenge.stale !== true)) {
  7995. this.logger.warn(statusCode + " apparently in authentication loop, cannot authenticate");
  7996. return true;
  7997. }
  7998. // Get credentials.
  7999. if (!this.credentials) {
  8000. this.credentials = this.core.configuration.authenticationFactory();
  8001. if (!this.credentials) {
  8002. this.logger.warn("Unable to obtain credentials, cannot authenticate");
  8003. return true;
  8004. }
  8005. }
  8006. // Verify that the challenge is really valid.
  8007. if (!this.credentials.authenticate(this.message, challenge)) {
  8008. return true;
  8009. }
  8010. this.challenged = true;
  8011. if (challenge.stale) {
  8012. this.stale = true;
  8013. }
  8014. var cseq = this.message.cseq += 1;
  8015. this.message.setHeader("cseq", cseq + " " + this.message.method);
  8016. this.message.setHeader(authorizationHeaderName, this.credentials.toString());
  8017. // Calling init (again) will swap out our existing client transaction with a new one.
  8018. // FIXME: HACK: An assumption is being made here that there is nothing that needs to
  8019. // be cleaned up beyond the client transaction which is being replaced. For example,
  8020. // it is assumed that no early dialogs have been created.
  8021. this.init();
  8022. return false;
  8023. };
  8024. /**
  8025. * 8.1.3.1 Transaction Layer Errors
  8026. * In some cases, the response returned by the transaction layer will
  8027. * not be a SIP message, but rather a transaction layer error. When a
  8028. * timeout error is received from the transaction layer, it MUST be
  8029. * treated as if a 408 (Request Timeout) status code has been received.
  8030. * If a fatal transport error is reported by the transport layer
  8031. * (generally, due to fatal ICMP errors in UDP or connection failures in
  8032. * TCP), the condition MUST be treated as a 503 (Service Unavailable)
  8033. * status code.
  8034. * https://tools.ietf.org/html/rfc3261#section-8.1.3.1
  8035. */
  8036. UserAgentClient.prototype.onRequestTimeout = function () {
  8037. this.logger.warn("User agent client request timed out. Generating internal 408 Request Timeout.");
  8038. var message = new messages_1.IncomingResponseMessage();
  8039. message.statusCode = 408;
  8040. message.reasonPhrase = "Request Timeout";
  8041. this.receiveResponse(message);
  8042. return;
  8043. };
  8044. /**
  8045. * 8.1.3.1 Transaction Layer Errors
  8046. * In some cases, the response returned by the transaction layer will
  8047. * not be a SIP message, but rather a transaction layer error. When a
  8048. * timeout error is received from the transaction layer, it MUST be
  8049. * treated as if a 408 (Request Timeout) status code has been received.
  8050. * If a fatal transport error is reported by the transport layer
  8051. * (generally, due to fatal ICMP errors in UDP or connection failures in
  8052. * TCP), the condition MUST be treated as a 503 (Service Unavailable)
  8053. * status code.
  8054. * https://tools.ietf.org/html/rfc3261#section-8.1.3.1
  8055. * @param error - Transport error
  8056. */
  8057. UserAgentClient.prototype.onTransportError = function (error) {
  8058. this.logger.error(error.message);
  8059. this.logger.error("User agent client request transport error. Generating internal 503 Service Unavailable.");
  8060. var message = new messages_1.IncomingResponseMessage();
  8061. message.statusCode = 503;
  8062. message.reasonPhrase = "Service Unavailable";
  8063. this.receiveResponse(message);
  8064. };
  8065. /**
  8066. * Receive a response from the transaction layer.
  8067. * @param message - Incoming response message.
  8068. */
  8069. UserAgentClient.prototype.receiveResponse = function (message) {
  8070. if (!this.authenticationGuard(message)) {
  8071. return;
  8072. }
  8073. var statusCode = message.statusCode ? message.statusCode.toString() : "";
  8074. if (!statusCode) {
  8075. throw new Error("Response status code undefined.");
  8076. }
  8077. switch (true) {
  8078. case /^100$/.test(statusCode):
  8079. if (this.delegate && this.delegate.onTrying) {
  8080. this.delegate.onTrying({ message: message });
  8081. }
  8082. break;
  8083. case /^1[0-9]{2}$/.test(statusCode):
  8084. if (this.delegate && this.delegate.onProgress) {
  8085. this.delegate.onProgress({ message: message });
  8086. }
  8087. break;
  8088. case /^2[0-9]{2}$/.test(statusCode):
  8089. if (this.delegate && this.delegate.onAccept) {
  8090. this.delegate.onAccept({ message: message });
  8091. }
  8092. break;
  8093. case /^3[0-9]{2}$/.test(statusCode):
  8094. if (this.delegate && this.delegate.onRedirect) {
  8095. this.delegate.onRedirect({ message: message });
  8096. }
  8097. break;
  8098. case /^[4-6][0-9]{2}$/.test(statusCode):
  8099. if (this.delegate && this.delegate.onReject) {
  8100. this.delegate.onReject({ message: message });
  8101. }
  8102. break;
  8103. default:
  8104. throw new Error("Invalid status code " + statusCode);
  8105. }
  8106. };
  8107. UserAgentClient.prototype.init = function () {
  8108. var _this = this;
  8109. // We are the transaction user.
  8110. var user = {
  8111. loggerFactory: this.loggerFactory,
  8112. onRequestTimeout: function () { return _this.onRequestTimeout(); },
  8113. onStateChange: function (newState) {
  8114. if (newState === transactions_1.TransactionState.Terminated) {
  8115. // Remove the terminated transaction from the core.
  8116. _this.core.userAgentClients.delete(userAgentClientId);
  8117. // FIXME: HACK: Our transaction may have been swapped out with a new one
  8118. // post authentication (see above), so make sure to only to dispose of
  8119. // ourselves if this terminating transaction is our current transaction.
  8120. if (transaction === _this._transaction) {
  8121. _this.dispose();
  8122. }
  8123. }
  8124. },
  8125. onTransportError: function (error) { return _this.onTransportError(error); },
  8126. receiveResponse: function (message) { return _this.receiveResponse(message); }
  8127. };
  8128. // Create a new transaction with us as the user.
  8129. var transaction = new this.transactionConstructor(this.message, this.core.transport, user);
  8130. this._transaction = transaction;
  8131. // Add the new transaction to the core.
  8132. var userAgentClientId = transaction.id + transaction.request.method;
  8133. this.core.userAgentClients.set(userAgentClientId, this);
  8134. };
  8135. return UserAgentClient;
  8136. }());
  8137. exports.UserAgentClient = UserAgentClient;
  8138. /***/ }),
  8139. /* 43 */
  8140. /***/ (function(module, exports, __webpack_require__) {
  8141. "use strict";
  8142. Object.defineProperty(exports, "__esModule", { value: true });
  8143. var tslib_1 = __webpack_require__(1);
  8144. var transactions_1 = __webpack_require__(27);
  8145. var user_agent_server_1 = __webpack_require__(44);
  8146. /**
  8147. * BYE UAS.
  8148. * @public
  8149. */
  8150. var ByeUserAgentServer = /** @class */ (function (_super) {
  8151. tslib_1.__extends(ByeUserAgentServer, _super);
  8152. function ByeUserAgentServer(dialog, message, delegate) {
  8153. return _super.call(this, transactions_1.NonInviteServerTransaction, dialog.userAgentCore, message, delegate) || this;
  8154. }
  8155. return ByeUserAgentServer;
  8156. }(user_agent_server_1.UserAgentServer));
  8157. exports.ByeUserAgentServer = ByeUserAgentServer;
  8158. /***/ }),
  8159. /* 44 */
  8160. /***/ (function(module, exports, __webpack_require__) {
  8161. "use strict";
  8162. Object.defineProperty(exports, "__esModule", { value: true });
  8163. var exceptions_1 = __webpack_require__(31);
  8164. var messages_1 = __webpack_require__(5);
  8165. var utils_1 = __webpack_require__(16);
  8166. var transactions_1 = __webpack_require__(27);
  8167. /**
  8168. * User Agent Server (UAS).
  8169. * @remarks
  8170. * A user agent server is a logical entity
  8171. * that generates a response to a SIP request. The response
  8172. * accepts, rejects, or redirects the request. This role lasts
  8173. * only for the duration of that transaction. In other words, if
  8174. * a piece of software responds to a request, it acts as a UAS for
  8175. * the duration of that transaction. If it generates a request
  8176. * later, it assumes the role of a user agent client for the
  8177. * processing of that transaction.
  8178. * https://tools.ietf.org/html/rfc3261#section-6
  8179. * @public
  8180. */
  8181. var UserAgentServer = /** @class */ (function () {
  8182. function UserAgentServer(transactionConstructor, core, message, delegate) {
  8183. this.transactionConstructor = transactionConstructor;
  8184. this.core = core;
  8185. this.message = message;
  8186. this.delegate = delegate;
  8187. this.logger = this.loggerFactory.getLogger("sip.user-agent-server");
  8188. this.toTag = message.toTag ? message.toTag : utils_1.newTag();
  8189. this.init();
  8190. }
  8191. UserAgentServer.prototype.dispose = function () {
  8192. this.transaction.dispose();
  8193. };
  8194. Object.defineProperty(UserAgentServer.prototype, "loggerFactory", {
  8195. get: function () {
  8196. return this.core.loggerFactory;
  8197. },
  8198. enumerable: true,
  8199. configurable: true
  8200. });
  8201. Object.defineProperty(UserAgentServer.prototype, "transaction", {
  8202. /** The transaction associated with this request. */
  8203. get: function () {
  8204. if (!this._transaction) {
  8205. throw new Error("Transaction undefined.");
  8206. }
  8207. return this._transaction;
  8208. },
  8209. enumerable: true,
  8210. configurable: true
  8211. });
  8212. UserAgentServer.prototype.accept = function (options) {
  8213. if (options === void 0) { options = { statusCode: 200 }; }
  8214. if (!this.acceptable) {
  8215. throw new exceptions_1.TransactionStateError(this.message.method + " not acceptable in state " + this.transaction.state + ".");
  8216. }
  8217. var statusCode = options.statusCode;
  8218. if (statusCode < 200 || statusCode > 299) {
  8219. throw new TypeError("Invalid statusCode: " + statusCode);
  8220. }
  8221. var response = this.reply(options);
  8222. return response;
  8223. };
  8224. UserAgentServer.prototype.progress = function (options) {
  8225. if (options === void 0) { options = { statusCode: 180 }; }
  8226. if (!this.progressable) {
  8227. throw new exceptions_1.TransactionStateError(this.message.method + " not progressable in state " + this.transaction.state + ".");
  8228. }
  8229. var statusCode = options.statusCode;
  8230. if (statusCode < 101 || statusCode > 199) {
  8231. throw new TypeError("Invalid statusCode: " + statusCode);
  8232. }
  8233. var response = this.reply(options);
  8234. return response;
  8235. };
  8236. UserAgentServer.prototype.redirect = function (contacts, options) {
  8237. if (options === void 0) { options = { statusCode: 302 }; }
  8238. if (!this.redirectable) {
  8239. throw new exceptions_1.TransactionStateError(this.message.method + " not redirectable in state " + this.transaction.state + ".");
  8240. }
  8241. var statusCode = options.statusCode;
  8242. if (statusCode < 300 || statusCode > 399) {
  8243. throw new TypeError("Invalid statusCode: " + statusCode);
  8244. }
  8245. var contactHeaders = new Array();
  8246. contacts.forEach(function (contact) { return contactHeaders.push("Contact: " + contact.toString()); });
  8247. options.extraHeaders = (options.extraHeaders || []).concat(contactHeaders);
  8248. var response = this.reply(options);
  8249. return response;
  8250. };
  8251. UserAgentServer.prototype.reject = function (options) {
  8252. if (options === void 0) { options = { statusCode: 480 }; }
  8253. if (!this.rejectable) {
  8254. throw new exceptions_1.TransactionStateError(this.message.method + " not rejectable in state " + this.transaction.state + ".");
  8255. }
  8256. var statusCode = options.statusCode;
  8257. if (statusCode < 400 || statusCode > 699) {
  8258. throw new TypeError("Invalid statusCode: " + statusCode);
  8259. }
  8260. var response = this.reply(options);
  8261. return response;
  8262. };
  8263. UserAgentServer.prototype.trying = function (options) {
  8264. if (!this.tryingable) {
  8265. throw new exceptions_1.TransactionStateError(this.message.method + " not tryingable in state " + this.transaction.state + ".");
  8266. }
  8267. var response = this.reply({ statusCode: 100 });
  8268. return response;
  8269. };
  8270. /**
  8271. * If the UAS did not find a matching transaction for the CANCEL
  8272. * according to the procedure above, it SHOULD respond to the CANCEL
  8273. * with a 481 (Call Leg/Transaction Does Not Exist). If the transaction
  8274. * for the original request still exists, the behavior of the UAS on
  8275. * receiving a CANCEL request depends on whether it has already sent a
  8276. * final response for the original request. If it has, the CANCEL
  8277. * request has no effect on the processing of the original request, no
  8278. * effect on any session state, and no effect on the responses generated
  8279. * for the original request. If the UAS has not issued a final response
  8280. * for the original request, its behavior depends on the method of the
  8281. * original request. If the original request was an INVITE, the UAS
  8282. * SHOULD immediately respond to the INVITE with a 487 (Request
  8283. * Terminated). A CANCEL request has no impact on the processing of
  8284. * transactions with any other method defined in this specification.
  8285. * https://tools.ietf.org/html/rfc3261#section-9.2
  8286. * @param request - Incoming CANCEL request.
  8287. */
  8288. UserAgentServer.prototype.receiveCancel = function (message) {
  8289. // Note: Currently CANCEL is being handled as a special case.
  8290. // No UAS is created to handle the CANCEL and the response to
  8291. // it CANCEL is being handled statelessly by the user agent core.
  8292. // As such, there is currently no way to externally impact the
  8293. // response to the a CANCEL request.
  8294. if (this.delegate && this.delegate.onCancel) {
  8295. this.delegate.onCancel(message);
  8296. }
  8297. };
  8298. Object.defineProperty(UserAgentServer.prototype, "acceptable", {
  8299. get: function () {
  8300. if (this.transaction instanceof transactions_1.InviteServerTransaction) {
  8301. return (this.transaction.state === transactions_1.TransactionState.Proceeding ||
  8302. this.transaction.state === transactions_1.TransactionState.Accepted);
  8303. }
  8304. if (this.transaction instanceof transactions_1.NonInviteServerTransaction) {
  8305. return (this.transaction.state === transactions_1.TransactionState.Trying ||
  8306. this.transaction.state === transactions_1.TransactionState.Proceeding);
  8307. }
  8308. throw new Error("Unknown transaction type.");
  8309. },
  8310. enumerable: true,
  8311. configurable: true
  8312. });
  8313. Object.defineProperty(UserAgentServer.prototype, "progressable", {
  8314. get: function () {
  8315. if (this.transaction instanceof transactions_1.InviteServerTransaction) {
  8316. return this.transaction.state === transactions_1.TransactionState.Proceeding;
  8317. }
  8318. if (this.transaction instanceof transactions_1.NonInviteServerTransaction) {
  8319. return false; // https://tools.ietf.org/html/rfc4320#section-4.1
  8320. }
  8321. throw new Error("Unknown transaction type.");
  8322. },
  8323. enumerable: true,
  8324. configurable: true
  8325. });
  8326. Object.defineProperty(UserAgentServer.prototype, "redirectable", {
  8327. get: function () {
  8328. if (this.transaction instanceof transactions_1.InviteServerTransaction) {
  8329. return this.transaction.state === transactions_1.TransactionState.Proceeding;
  8330. }
  8331. if (this.transaction instanceof transactions_1.NonInviteServerTransaction) {
  8332. return (this.transaction.state === transactions_1.TransactionState.Trying ||
  8333. this.transaction.state === transactions_1.TransactionState.Proceeding);
  8334. }
  8335. throw new Error("Unknown transaction type.");
  8336. },
  8337. enumerable: true,
  8338. configurable: true
  8339. });
  8340. Object.defineProperty(UserAgentServer.prototype, "rejectable", {
  8341. get: function () {
  8342. if (this.transaction instanceof transactions_1.InviteServerTransaction) {
  8343. return this.transaction.state === transactions_1.TransactionState.Proceeding;
  8344. }
  8345. if (this.transaction instanceof transactions_1.NonInviteServerTransaction) {
  8346. return (this.transaction.state === transactions_1.TransactionState.Trying ||
  8347. this.transaction.state === transactions_1.TransactionState.Proceeding);
  8348. }
  8349. throw new Error("Unknown transaction type.");
  8350. },
  8351. enumerable: true,
  8352. configurable: true
  8353. });
  8354. Object.defineProperty(UserAgentServer.prototype, "tryingable", {
  8355. get: function () {
  8356. if (this.transaction instanceof transactions_1.InviteServerTransaction) {
  8357. return this.transaction.state === transactions_1.TransactionState.Proceeding;
  8358. }
  8359. if (this.transaction instanceof transactions_1.NonInviteServerTransaction) {
  8360. return this.transaction.state === transactions_1.TransactionState.Trying;
  8361. }
  8362. throw new Error("Unknown transaction type.");
  8363. },
  8364. enumerable: true,
  8365. configurable: true
  8366. });
  8367. /**
  8368. * When a UAS wishes to construct a response to a request, it follows
  8369. * the general procedures detailed in the following subsections.
  8370. * Additional behaviors specific to the response code in question, which
  8371. * are not detailed in this section, may also be required.
  8372. *
  8373. * Once all procedures associated with the creation of a response have
  8374. * been completed, the UAS hands the response back to the server
  8375. * transaction from which it received the request.
  8376. * https://tools.ietf.org/html/rfc3261#section-8.2.6
  8377. * @param statusCode - Status code to reply with.
  8378. * @param options - Reply options bucket.
  8379. */
  8380. UserAgentServer.prototype.reply = function (options) {
  8381. if (!options.toTag && options.statusCode !== 100) {
  8382. options.toTag = this.toTag;
  8383. }
  8384. options.userAgent = options.userAgent || this.core.configuration.userAgentHeaderFieldValue;
  8385. options.supported = options.supported || this.core.configuration.supportedOptionTagsResponse;
  8386. var response = messages_1.constructOutgoingResponse(this.message, options);
  8387. this.transaction.receiveResponse(options.statusCode, response.message);
  8388. return response;
  8389. };
  8390. UserAgentServer.prototype.init = function () {
  8391. var _this = this;
  8392. // We are the transaction user.
  8393. var user = {
  8394. loggerFactory: this.loggerFactory,
  8395. onStateChange: function (newState) {
  8396. if (newState === transactions_1.TransactionState.Terminated) {
  8397. // Remove the terminated transaction from the core.
  8398. _this.core.userAgentServers.delete(userAgentServerId);
  8399. _this.dispose();
  8400. }
  8401. },
  8402. onTransportError: function (error) {
  8403. _this.logger.error(error.message);
  8404. if (_this.delegate && _this.delegate.onTransportError) {
  8405. _this.delegate.onTransportError(error);
  8406. }
  8407. else {
  8408. _this.logger.error("User agent server response transport error.");
  8409. }
  8410. }
  8411. };
  8412. // Create a new transaction with us as the user.
  8413. var transaction = new this.transactionConstructor(this.message, this.core.transport, user);
  8414. this._transaction = transaction;
  8415. // Add the new transaction to the core.
  8416. var userAgentServerId = transaction.id;
  8417. this.core.userAgentServers.set(transaction.id, this);
  8418. };
  8419. return UserAgentServer;
  8420. }());
  8421. exports.UserAgentServer = UserAgentServer;
  8422. /***/ }),
  8423. /* 45 */
  8424. /***/ (function(module, exports, __webpack_require__) {
  8425. "use strict";
  8426. Object.defineProperty(exports, "__esModule", { value: true });
  8427. var tslib_1 = __webpack_require__(1);
  8428. var messages_1 = __webpack_require__(5);
  8429. var transactions_1 = __webpack_require__(27);
  8430. var user_agent_client_1 = __webpack_require__(42);
  8431. /**
  8432. * INFO UAC.
  8433. * @public
  8434. */
  8435. var InfoUserAgentClient = /** @class */ (function (_super) {
  8436. tslib_1.__extends(InfoUserAgentClient, _super);
  8437. function InfoUserAgentClient(dialog, delegate, options) {
  8438. var _this = this;
  8439. var message = dialog.createOutgoingRequestMessage(messages_1.C.INFO, options);
  8440. _this = _super.call(this, transactions_1.NonInviteClientTransaction, dialog.userAgentCore, message, delegate) || this;
  8441. return _this;
  8442. }
  8443. return InfoUserAgentClient;
  8444. }(user_agent_client_1.UserAgentClient));
  8445. exports.InfoUserAgentClient = InfoUserAgentClient;
  8446. /***/ }),
  8447. /* 46 */
  8448. /***/ (function(module, exports, __webpack_require__) {
  8449. "use strict";
  8450. Object.defineProperty(exports, "__esModule", { value: true });
  8451. var tslib_1 = __webpack_require__(1);
  8452. var transactions_1 = __webpack_require__(27);
  8453. var user_agent_server_1 = __webpack_require__(44);
  8454. /**
  8455. * INFO UAS.
  8456. * @public
  8457. */
  8458. var InfoUserAgentServer = /** @class */ (function (_super) {
  8459. tslib_1.__extends(InfoUserAgentServer, _super);
  8460. function InfoUserAgentServer(dialog, message, delegate) {
  8461. return _super.call(this, transactions_1.NonInviteServerTransaction, dialog.userAgentCore, message, delegate) || this;
  8462. }
  8463. return InfoUserAgentServer;
  8464. }(user_agent_server_1.UserAgentServer));
  8465. exports.InfoUserAgentServer = InfoUserAgentServer;
  8466. /***/ }),
  8467. /* 47 */
  8468. /***/ (function(module, exports, __webpack_require__) {
  8469. "use strict";
  8470. Object.defineProperty(exports, "__esModule", { value: true });
  8471. var tslib_1 = __webpack_require__(1);
  8472. var messages_1 = __webpack_require__(5);
  8473. var transactions_1 = __webpack_require__(27);
  8474. var user_agent_client_1 = __webpack_require__(42);
  8475. /**
  8476. * NOTIFY UAS.
  8477. * @public
  8478. */
  8479. var NotifyUserAgentClient = /** @class */ (function (_super) {
  8480. tslib_1.__extends(NotifyUserAgentClient, _super);
  8481. function NotifyUserAgentClient(dialog, delegate, options) {
  8482. var _this = this;
  8483. var message = dialog.createOutgoingRequestMessage(messages_1.C.NOTIFY, options);
  8484. _this = _super.call(this, transactions_1.NonInviteClientTransaction, dialog.userAgentCore, message, delegate) || this;
  8485. return _this;
  8486. }
  8487. return NotifyUserAgentClient;
  8488. }(user_agent_client_1.UserAgentClient));
  8489. exports.NotifyUserAgentClient = NotifyUserAgentClient;
  8490. /***/ }),
  8491. /* 48 */
  8492. /***/ (function(module, exports, __webpack_require__) {
  8493. "use strict";
  8494. Object.defineProperty(exports, "__esModule", { value: true });
  8495. var tslib_1 = __webpack_require__(1);
  8496. var transactions_1 = __webpack_require__(27);
  8497. var user_agent_server_1 = __webpack_require__(44);
  8498. /**
  8499. * NOTIFY UAS.
  8500. * @public
  8501. */
  8502. var NotifyUserAgentServer = /** @class */ (function (_super) {
  8503. tslib_1.__extends(NotifyUserAgentServer, _super);
  8504. /**
  8505. * NOTIFY UAS constructor.
  8506. * @param dialogOrCore - Dialog for in dialog NOTIFY, UserAgentCore for out of dialog NOTIFY (deprecated).
  8507. * @param message - Incoming NOTIFY request message.
  8508. */
  8509. function NotifyUserAgentServer(dialogOrCore, message, delegate) {
  8510. var _this = this;
  8511. var userAgentCore = instanceOfDialog(dialogOrCore) ?
  8512. dialogOrCore.userAgentCore :
  8513. dialogOrCore;
  8514. _this = _super.call(this, transactions_1.NonInviteServerTransaction, userAgentCore, message, delegate) || this;
  8515. return _this;
  8516. }
  8517. return NotifyUserAgentServer;
  8518. }(user_agent_server_1.UserAgentServer));
  8519. exports.NotifyUserAgentServer = NotifyUserAgentServer;
  8520. function instanceOfDialog(object) {
  8521. return object.userAgentCore !== undefined;
  8522. }
  8523. /***/ }),
  8524. /* 49 */
  8525. /***/ (function(module, exports, __webpack_require__) {
  8526. "use strict";
  8527. Object.defineProperty(exports, "__esModule", { value: true });
  8528. var tslib_1 = __webpack_require__(1);
  8529. var messages_1 = __webpack_require__(5);
  8530. var transactions_1 = __webpack_require__(27);
  8531. var user_agent_client_1 = __webpack_require__(42);
  8532. /**
  8533. * PRACK UAC.
  8534. * @public
  8535. */
  8536. var PrackUserAgentClient = /** @class */ (function (_super) {
  8537. tslib_1.__extends(PrackUserAgentClient, _super);
  8538. function PrackUserAgentClient(dialog, delegate, options) {
  8539. var _this = this;
  8540. var message = dialog.createOutgoingRequestMessage(messages_1.C.PRACK, options);
  8541. _this = _super.call(this, transactions_1.NonInviteClientTransaction, dialog.userAgentCore, message, delegate) || this;
  8542. dialog.signalingStateTransition(message);
  8543. return _this;
  8544. }
  8545. return PrackUserAgentClient;
  8546. }(user_agent_client_1.UserAgentClient));
  8547. exports.PrackUserAgentClient = PrackUserAgentClient;
  8548. /***/ }),
  8549. /* 50 */
  8550. /***/ (function(module, exports, __webpack_require__) {
  8551. "use strict";
  8552. Object.defineProperty(exports, "__esModule", { value: true });
  8553. var tslib_1 = __webpack_require__(1);
  8554. var transactions_1 = __webpack_require__(27);
  8555. var user_agent_server_1 = __webpack_require__(44);
  8556. /**
  8557. * PRACK UAS.
  8558. * @public
  8559. */
  8560. var PrackUserAgentServer = /** @class */ (function (_super) {
  8561. tslib_1.__extends(PrackUserAgentServer, _super);
  8562. function PrackUserAgentServer(dialog, message, delegate) {
  8563. var _this = _super.call(this, transactions_1.NonInviteServerTransaction, dialog.userAgentCore, message, delegate) || this;
  8564. // Update dialog signaling state with offer/answer in body
  8565. dialog.signalingStateTransition(message);
  8566. _this.dialog = dialog;
  8567. return _this;
  8568. }
  8569. /**
  8570. * Update the dialog signaling state on a 2xx response.
  8571. * @param options - Options bucket.
  8572. */
  8573. PrackUserAgentServer.prototype.accept = function (options) {
  8574. if (options === void 0) { options = { statusCode: 200 }; }
  8575. if (options.body) {
  8576. // Update dialog signaling state with offer/answer in body
  8577. this.dialog.signalingStateTransition(options.body);
  8578. }
  8579. return _super.prototype.accept.call(this, options);
  8580. };
  8581. return PrackUserAgentServer;
  8582. }(user_agent_server_1.UserAgentServer));
  8583. exports.PrackUserAgentServer = PrackUserAgentServer;
  8584. /***/ }),
  8585. /* 51 */
  8586. /***/ (function(module, exports, __webpack_require__) {
  8587. "use strict";
  8588. Object.defineProperty(exports, "__esModule", { value: true });
  8589. var tslib_1 = __webpack_require__(1);
  8590. var messages_1 = __webpack_require__(5);
  8591. var transactions_1 = __webpack_require__(27);
  8592. var user_agent_client_1 = __webpack_require__(42);
  8593. /**
  8594. * Re-INVITE UAC.
  8595. * @remarks
  8596. * 14 Modifying an Existing Session
  8597. * https://tools.ietf.org/html/rfc3261#section-14
  8598. * 14.1 UAC Behavior
  8599. * https://tools.ietf.org/html/rfc3261#section-14.1
  8600. * @public
  8601. */
  8602. var ReInviteUserAgentClient = /** @class */ (function (_super) {
  8603. tslib_1.__extends(ReInviteUserAgentClient, _super);
  8604. function ReInviteUserAgentClient(dialog, delegate, options) {
  8605. var _this = this;
  8606. var message = dialog.createOutgoingRequestMessage(messages_1.C.INVITE, options);
  8607. _this = _super.call(this, transactions_1.InviteClientTransaction, dialog.userAgentCore, message, delegate) || this;
  8608. _this.delegate = delegate;
  8609. dialog.signalingStateTransition(message);
  8610. // FIXME: TODO: next line obviously needs to be improved...
  8611. dialog.reinviteUserAgentClient = _this; // let the dialog know re-invite request sent
  8612. _this.dialog = dialog;
  8613. return _this;
  8614. }
  8615. ReInviteUserAgentClient.prototype.receiveResponse = function (message) {
  8616. var _this = this;
  8617. var statusCode = message.statusCode ? message.statusCode.toString() : "";
  8618. if (!statusCode) {
  8619. throw new Error("Response status code undefined.");
  8620. }
  8621. switch (true) {
  8622. case /^100$/.test(statusCode):
  8623. if (this.delegate && this.delegate.onTrying) {
  8624. this.delegate.onTrying({ message: message });
  8625. }
  8626. break;
  8627. case /^1[0-9]{2}$/.test(statusCode):
  8628. if (this.delegate && this.delegate.onProgress) {
  8629. this.delegate.onProgress({
  8630. message: message,
  8631. session: this.dialog,
  8632. prack: function (options) {
  8633. throw new Error("Unimplemented.");
  8634. }
  8635. });
  8636. }
  8637. break;
  8638. case /^2[0-9]{2}$/.test(statusCode):
  8639. // Update dialog signaling state with offer/answer in body
  8640. this.dialog.signalingStateTransition(message);
  8641. if (this.delegate && this.delegate.onAccept) {
  8642. this.delegate.onAccept({
  8643. message: message,
  8644. session: this.dialog,
  8645. ack: function (options) {
  8646. var outgoingAckRequest = _this.dialog.ack(options);
  8647. return outgoingAckRequest;
  8648. }
  8649. });
  8650. }
  8651. break;
  8652. case /^3[0-9]{2}$/.test(statusCode):
  8653. this.dialog.signalingStateRollback();
  8654. this.dialog.reinviteUserAgentClient = undefined; // ACK was handled by transaction
  8655. if (this.delegate && this.delegate.onRedirect) {
  8656. this.delegate.onRedirect({ message: message });
  8657. }
  8658. break;
  8659. case /^[4-6][0-9]{2}$/.test(statusCode):
  8660. this.dialog.signalingStateRollback();
  8661. this.dialog.reinviteUserAgentClient = undefined; // ACK was handled by transaction
  8662. if (this.delegate && this.delegate.onReject) {
  8663. this.delegate.onReject({ message: message });
  8664. }
  8665. else {
  8666. // If a UA receives a non-2xx final response to a re-INVITE, the session
  8667. // parameters MUST remain unchanged, as if no re-INVITE had been issued.
  8668. // Note that, as stated in Section 12.2.1.2, if the non-2xx final
  8669. // response is a 481 (Call/Transaction Does Not Exist), or a 408
  8670. // (Request Timeout), or no response at all is received for the re-
  8671. // INVITE (that is, a timeout is returned by the INVITE client
  8672. // transaction), the UAC will terminate the dialog.
  8673. //
  8674. // If a UAC receives a 491 response to a re-INVITE, it SHOULD start a
  8675. // timer with a value T chosen as follows:
  8676. //
  8677. // 1. If the UAC is the owner of the Call-ID of the dialog ID
  8678. // (meaning it generated the value), T has a randomly chosen value
  8679. // between 2.1 and 4 seconds in units of 10 ms.
  8680. //
  8681. // 2. If the UAC is not the owner of the Call-ID of the dialog ID, T
  8682. // has a randomly chosen value of between 0 and 2 seconds in units
  8683. // of 10 ms.
  8684. //
  8685. // When the timer fires, the UAC SHOULD attempt the re-INVITE once more,
  8686. // if it still desires for that session modification to take place. For
  8687. // example, if the call was already hung up with a BYE, the re-INVITE
  8688. // would not take place.
  8689. // https://tools.ietf.org/html/rfc3261#section-14.1
  8690. // FIXME: TODO: The above.
  8691. }
  8692. break;
  8693. default:
  8694. throw new Error("Invalid status code " + statusCode);
  8695. }
  8696. };
  8697. return ReInviteUserAgentClient;
  8698. }(user_agent_client_1.UserAgentClient));
  8699. exports.ReInviteUserAgentClient = ReInviteUserAgentClient;
  8700. /***/ }),
  8701. /* 52 */
  8702. /***/ (function(module, exports, __webpack_require__) {
  8703. "use strict";
  8704. Object.defineProperty(exports, "__esModule", { value: true });
  8705. var tslib_1 = __webpack_require__(1);
  8706. var transactions_1 = __webpack_require__(27);
  8707. var user_agent_server_1 = __webpack_require__(44);
  8708. /**
  8709. * Re-INVITE UAS.
  8710. * @remarks
  8711. * 14 Modifying an Existing Session
  8712. * https://tools.ietf.org/html/rfc3261#section-14
  8713. * 14.2 UAS Behavior
  8714. * https://tools.ietf.org/html/rfc3261#section-14.2
  8715. * @public
  8716. */
  8717. var ReInviteUserAgentServer = /** @class */ (function (_super) {
  8718. tslib_1.__extends(ReInviteUserAgentServer, _super);
  8719. function ReInviteUserAgentServer(dialog, message, delegate) {
  8720. var _this = _super.call(this, transactions_1.InviteServerTransaction, dialog.userAgentCore, message, delegate) || this;
  8721. dialog.reinviteUserAgentServer = _this;
  8722. _this.dialog = dialog;
  8723. return _this;
  8724. }
  8725. /**
  8726. * Update the dialog signaling state on a 2xx response.
  8727. * @param options - Options bucket.
  8728. */
  8729. ReInviteUserAgentServer.prototype.accept = function (options) {
  8730. if (options === void 0) { options = { statusCode: 200 }; }
  8731. // FIXME: The next two lines SHOULD go away, but I suppose it's technically harmless...
  8732. // These are here because some versions of SIP.js prior to 0.13.8 set the route set
  8733. // of all in dialog ACKs based on the Record-Route headers in the associated 2xx
  8734. // response. While this worked for dialog forming 2xx responses, it was technically
  8735. // broken for re-INVITE ACKS as it only worked if the UAS populated the Record-Route
  8736. // headers in the re-INVITE 2xx response (which is not required and a waste of bandwidth
  8737. // as the should be ignored if present in re-INVITE ACKS) and the UAS populated
  8738. // the Record-Route headers with the correct values (would be weird not too, but...).
  8739. // Anyway, for now the technically useless Record-Route headers are being added
  8740. // to maintain "backwards compatibility" with the older broken versions of SIP.js.
  8741. options.extraHeaders = options.extraHeaders || [];
  8742. options.extraHeaders = options.extraHeaders.concat(this.dialog.routeSet.map(function (route) { return "Record-Route: " + route; }));
  8743. // Send and return the response
  8744. var response = _super.prototype.accept.call(this, options);
  8745. var session = this.dialog;
  8746. var result = tslib_1.__assign(tslib_1.__assign({}, response), { session: session });
  8747. if (options.body) {
  8748. // Update dialog signaling state with offer/answer in body
  8749. this.dialog.signalingStateTransition(options.body);
  8750. }
  8751. // Update dialog
  8752. this.dialog.reConfirm();
  8753. return result;
  8754. };
  8755. /**
  8756. * Update the dialog signaling state on a 1xx response.
  8757. * @param options - Progress options bucket.
  8758. */
  8759. ReInviteUserAgentServer.prototype.progress = function (options) {
  8760. if (options === void 0) { options = { statusCode: 180 }; }
  8761. // Send and return the response
  8762. var response = _super.prototype.progress.call(this, options);
  8763. var session = this.dialog;
  8764. var result = tslib_1.__assign(tslib_1.__assign({}, response), { session: session });
  8765. // Update dialog signaling state
  8766. if (options.body) {
  8767. this.dialog.signalingStateTransition(options.body);
  8768. }
  8769. return result;
  8770. };
  8771. /**
  8772. * TODO: Not Yet Supported
  8773. * @param contacts - Contacts to redirect to.
  8774. * @param options - Redirect options bucket.
  8775. */
  8776. ReInviteUserAgentServer.prototype.redirect = function (contacts, options) {
  8777. if (options === void 0) { options = { statusCode: 302 }; }
  8778. this.dialog.signalingStateRollback();
  8779. this.dialog.reinviteUserAgentServer = undefined; // ACK will be handled by transaction
  8780. throw new Error("Unimplemented.");
  8781. };
  8782. /**
  8783. * 3.1 Background on Re-INVITE Handling by UASs
  8784. * An error response to a re-INVITE has the following semantics. As
  8785. * specified in Section 12.2.2 of RFC 3261 [RFC3261], if a re-INVITE is
  8786. * rejected, no state changes are performed.
  8787. * https://tools.ietf.org/html/rfc6141#section-3.1
  8788. * @param options - Reject options bucket.
  8789. */
  8790. ReInviteUserAgentServer.prototype.reject = function (options) {
  8791. if (options === void 0) { options = { statusCode: 488 }; }
  8792. this.dialog.signalingStateRollback();
  8793. this.dialog.reinviteUserAgentServer = undefined; // ACK will be handled by transaction
  8794. return _super.prototype.reject.call(this, options);
  8795. };
  8796. return ReInviteUserAgentServer;
  8797. }(user_agent_server_1.UserAgentServer));
  8798. exports.ReInviteUserAgentServer = ReInviteUserAgentServer;
  8799. /***/ }),
  8800. /* 53 */
  8801. /***/ (function(module, exports, __webpack_require__) {
  8802. "use strict";
  8803. Object.defineProperty(exports, "__esModule", { value: true });
  8804. var tslib_1 = __webpack_require__(1);
  8805. var messages_1 = __webpack_require__(5);
  8806. var transactions_1 = __webpack_require__(27);
  8807. var user_agent_client_1 = __webpack_require__(42);
  8808. /**
  8809. * REFER UAC.
  8810. * @public
  8811. */
  8812. var ReferUserAgentClient = /** @class */ (function (_super) {
  8813. tslib_1.__extends(ReferUserAgentClient, _super);
  8814. function ReferUserAgentClient(dialog, delegate, options) {
  8815. var _this = this;
  8816. var message = dialog.createOutgoingRequestMessage(messages_1.C.REFER, options);
  8817. _this = _super.call(this, transactions_1.NonInviteClientTransaction, dialog.userAgentCore, message, delegate) || this;
  8818. return _this;
  8819. }
  8820. return ReferUserAgentClient;
  8821. }(user_agent_client_1.UserAgentClient));
  8822. exports.ReferUserAgentClient = ReferUserAgentClient;
  8823. /***/ }),
  8824. /* 54 */
  8825. /***/ (function(module, exports, __webpack_require__) {
  8826. "use strict";
  8827. Object.defineProperty(exports, "__esModule", { value: true });
  8828. var tslib_1 = __webpack_require__(1);
  8829. var transactions_1 = __webpack_require__(27);
  8830. var user_agent_server_1 = __webpack_require__(44);
  8831. /**
  8832. * REFER UAS.
  8833. * @public
  8834. */
  8835. var ReferUserAgentServer = /** @class */ (function (_super) {
  8836. tslib_1.__extends(ReferUserAgentServer, _super);
  8837. /**
  8838. * REFER UAS constructor.
  8839. * @param dialogOrCore - Dialog for in dialog REFER, UserAgentCore for out of dialog REFER.
  8840. * @param message - Incoming REFER request message.
  8841. */
  8842. function ReferUserAgentServer(dialogOrCore, message, delegate) {
  8843. var _this = this;
  8844. var userAgentCore = instanceOfSessionDialog(dialogOrCore) ?
  8845. dialogOrCore.userAgentCore :
  8846. dialogOrCore;
  8847. _this = _super.call(this, transactions_1.NonInviteServerTransaction, userAgentCore, message, delegate) || this;
  8848. return _this;
  8849. }
  8850. return ReferUserAgentServer;
  8851. }(user_agent_server_1.UserAgentServer));
  8852. exports.ReferUserAgentServer = ReferUserAgentServer;
  8853. function instanceOfSessionDialog(object) {
  8854. return object.userAgentCore !== undefined;
  8855. }
  8856. /***/ }),
  8857. /* 55 */
  8858. /***/ (function(module, exports, __webpack_require__) {
  8859. "use strict";
  8860. Object.defineProperty(exports, "__esModule", { value: true });
  8861. var tslib_1 = __webpack_require__(1);
  8862. var messages_1 = __webpack_require__(5);
  8863. var subscription_1 = __webpack_require__(56);
  8864. var timers_1 = __webpack_require__(26);
  8865. var allowed_methods_1 = __webpack_require__(58);
  8866. var notify_user_agent_server_1 = __webpack_require__(48);
  8867. var re_subscribe_user_agent_client_1 = __webpack_require__(59);
  8868. var dialog_1 = __webpack_require__(4);
  8869. /**
  8870. * Subscription Dialog.
  8871. * @remarks
  8872. * SIP-Specific Event Notification
  8873. *
  8874. * Abstract
  8875. *
  8876. * This document describes an extension to the Session Initiation
  8877. * Protocol (SIP) defined by RFC 3261. The purpose of this extension is
  8878. * to provide an extensible framework by which SIP nodes can request
  8879. * notification from remote nodes indicating that certain events have
  8880. * occurred.
  8881. *
  8882. * Note that the event notification mechanisms defined herein are NOT
  8883. * intended to be a general-purpose infrastructure for all classes of
  8884. * event subscription and notification.
  8885. *
  8886. * This document represents a backwards-compatible improvement on the
  8887. * original mechanism described by RFC 3265, taking into account several
  8888. * years of implementation experience. Accordingly, this document
  8889. * obsoletes RFC 3265. This document also updates RFC 4660 slightly to
  8890. * accommodate some small changes to the mechanism that were discussed
  8891. * in that document.
  8892. *
  8893. * https://tools.ietf.org/html/rfc6665
  8894. * @public
  8895. */
  8896. var SubscriptionDialog = /** @class */ (function (_super) {
  8897. tslib_1.__extends(SubscriptionDialog, _super);
  8898. function SubscriptionDialog(subscriptionEvent, subscriptionExpires, subscriptionState, core, state, delegate) {
  8899. var _this = _super.call(this, core, state) || this;
  8900. _this.delegate = delegate;
  8901. _this._autoRefresh = false;
  8902. _this._subscriptionEvent = subscriptionEvent;
  8903. _this._subscriptionExpires = subscriptionExpires;
  8904. _this._subscriptionExpiresInitial = subscriptionExpires;
  8905. _this._subscriptionExpiresLastSet = Math.floor(Date.now() / 1000);
  8906. _this._subscriptionRefresh = undefined;
  8907. _this._subscriptionRefreshLastSet = undefined;
  8908. _this._subscriptionState = subscriptionState;
  8909. _this.logger = core.loggerFactory.getLogger("sip.subscribe-dialog");
  8910. _this.logger.log("SUBSCRIBE dialog " + _this.id + " constructed");
  8911. return _this;
  8912. }
  8913. /**
  8914. * When a UAC receives a response that establishes a dialog, it
  8915. * constructs the state of the dialog. This state MUST be maintained
  8916. * for the duration of the dialog.
  8917. * https://tools.ietf.org/html/rfc3261#section-12.1.2
  8918. * @param outgoingRequestMessage - Outgoing request message for dialog.
  8919. * @param incomingResponseMessage - Incoming response message creating dialog.
  8920. */
  8921. SubscriptionDialog.initialDialogStateForSubscription = function (outgoingSubscribeRequestMessage, incomingNotifyRequestMessage) {
  8922. // If the request was sent over TLS, and the Request-URI contained a
  8923. // SIPS URI, the "secure" flag is set to TRUE.
  8924. // https://tools.ietf.org/html/rfc3261#section-12.1.2
  8925. var secure = false; // FIXME: Currently no support for TLS.
  8926. // The route set MUST be set to the list of URIs in the Record-Route
  8927. // header field from the response, taken in reverse order and preserving
  8928. // all URI parameters. If no Record-Route header field is present in
  8929. // the response, the route set MUST be set to the empty set. This route
  8930. // set, even if empty, overrides any pre-existing route set for future
  8931. // requests in this dialog. The remote target MUST be set to the URI
  8932. // from the Contact header field of the response.
  8933. // https://tools.ietf.org/html/rfc3261#section-12.1.2
  8934. var routeSet = incomingNotifyRequestMessage.getHeaders("record-route");
  8935. var contact = incomingNotifyRequestMessage.parseHeader("contact");
  8936. if (!contact) { // TODO: Review to make sure this will never happen
  8937. throw new Error("Contact undefined.");
  8938. }
  8939. if (!(contact instanceof messages_1.NameAddrHeader)) {
  8940. throw new Error("Contact not instance of NameAddrHeader.");
  8941. }
  8942. var remoteTarget = contact.uri;
  8943. // The local sequence number MUST be set to the value of the sequence
  8944. // number in the CSeq header field of the request. The remote sequence
  8945. // number MUST be empty (it is established when the remote UA sends a
  8946. // request within the dialog). The call identifier component of the
  8947. // dialog ID MUST be set to the value of the Call-ID in the request.
  8948. // The local tag component of the dialog ID MUST be set to the tag in
  8949. // the From field in the request, and the remote tag component of the
  8950. // dialog ID MUST be set to the tag in the To field of the response. A
  8951. // UAC MUST be prepared to receive a response without a tag in the To
  8952. // field, in which case the tag is considered to have a value of null.
  8953. //
  8954. // This is to maintain backwards compatibility with RFC 2543, which
  8955. // did not mandate To tags.
  8956. //
  8957. // https://tools.ietf.org/html/rfc3261#section-12.1.2
  8958. var localSequenceNumber = outgoingSubscribeRequestMessage.cseq;
  8959. var remoteSequenceNumber = undefined;
  8960. var callId = outgoingSubscribeRequestMessage.callId;
  8961. var localTag = outgoingSubscribeRequestMessage.fromTag;
  8962. var remoteTag = incomingNotifyRequestMessage.fromTag;
  8963. if (!callId) { // TODO: Review to make sure this will never happen
  8964. throw new Error("Call id undefined.");
  8965. }
  8966. if (!localTag) { // TODO: Review to make sure this will never happen
  8967. throw new Error("From tag undefined.");
  8968. }
  8969. if (!remoteTag) { // TODO: Review to make sure this will never happen
  8970. throw new Error("To tag undefined."); // FIXME: No backwards compatibility with RFC 2543
  8971. }
  8972. // The remote URI MUST be set to the URI in the To field, and the local
  8973. // URI MUST be set to the URI in the From field.
  8974. // https://tools.ietf.org/html/rfc3261#section-12.1.2
  8975. if (!outgoingSubscribeRequestMessage.from) { // TODO: Review to make sure this will never happen
  8976. throw new Error("From undefined.");
  8977. }
  8978. if (!outgoingSubscribeRequestMessage.to) { // TODO: Review to make sure this will never happen
  8979. throw new Error("To undefined.");
  8980. }
  8981. var localURI = outgoingSubscribeRequestMessage.from.uri;
  8982. var remoteURI = outgoingSubscribeRequestMessage.to.uri;
  8983. // A dialog can also be in the "early" state, which occurs when it is
  8984. // created with a provisional response, and then transition to the
  8985. // "confirmed" state when a 2xx final response arrives.
  8986. // https://tools.ietf.org/html/rfc3261#section-12
  8987. var early = false;
  8988. var dialogState = {
  8989. id: callId + localTag + remoteTag,
  8990. early: early,
  8991. callId: callId,
  8992. localTag: localTag,
  8993. remoteTag: remoteTag,
  8994. localSequenceNumber: localSequenceNumber,
  8995. remoteSequenceNumber: remoteSequenceNumber,
  8996. localURI: localURI,
  8997. remoteURI: remoteURI,
  8998. remoteTarget: remoteTarget,
  8999. routeSet: routeSet,
  9000. secure: secure
  9001. };
  9002. return dialogState;
  9003. };
  9004. SubscriptionDialog.prototype.dispose = function () {
  9005. _super.prototype.dispose.call(this);
  9006. if (this.N) {
  9007. clearTimeout(this.N);
  9008. this.N = undefined;
  9009. }
  9010. this.refreshTimerClear();
  9011. this.logger.log("SUBSCRIBE dialog " + this.id + " destroyed");
  9012. };
  9013. Object.defineProperty(SubscriptionDialog.prototype, "autoRefresh", {
  9014. get: function () {
  9015. return this._autoRefresh;
  9016. },
  9017. set: function (autoRefresh) {
  9018. this._autoRefresh = true;
  9019. this.refreshTimerSet();
  9020. },
  9021. enumerable: true,
  9022. configurable: true
  9023. });
  9024. Object.defineProperty(SubscriptionDialog.prototype, "subscriptionEvent", {
  9025. get: function () {
  9026. return this._subscriptionEvent;
  9027. },
  9028. enumerable: true,
  9029. configurable: true
  9030. });
  9031. Object.defineProperty(SubscriptionDialog.prototype, "subscriptionExpires", {
  9032. /** Number of seconds until subscription expires. */
  9033. get: function () {
  9034. var secondsSinceLastSet = Math.floor(Date.now() / 1000) - this._subscriptionExpiresLastSet;
  9035. var secondsUntilExpires = this._subscriptionExpires - secondsSinceLastSet;
  9036. return Math.max(secondsUntilExpires, 0);
  9037. },
  9038. set: function (expires) {
  9039. if (expires < 0) {
  9040. throw new Error("Expires must be greater than or equal to zero.");
  9041. }
  9042. this._subscriptionExpires = expires;
  9043. this._subscriptionExpiresLastSet = Math.floor(Date.now() / 1000);
  9044. if (this.autoRefresh) {
  9045. var refresh = this.subscriptionRefresh;
  9046. if (refresh === undefined || refresh >= expires) {
  9047. this.refreshTimerSet();
  9048. }
  9049. }
  9050. },
  9051. enumerable: true,
  9052. configurable: true
  9053. });
  9054. Object.defineProperty(SubscriptionDialog.prototype, "subscriptionExpiresInitial", {
  9055. get: function () {
  9056. return this._subscriptionExpiresInitial;
  9057. },
  9058. enumerable: true,
  9059. configurable: true
  9060. });
  9061. Object.defineProperty(SubscriptionDialog.prototype, "subscriptionRefresh", {
  9062. /** Number of seconds until subscription auto refresh. */
  9063. get: function () {
  9064. if (this._subscriptionRefresh === undefined || this._subscriptionRefreshLastSet === undefined) {
  9065. return undefined;
  9066. }
  9067. var secondsSinceLastSet = Math.floor(Date.now() / 1000) - this._subscriptionRefreshLastSet;
  9068. var secondsUntilExpires = this._subscriptionRefresh - secondsSinceLastSet;
  9069. return Math.max(secondsUntilExpires, 0);
  9070. },
  9071. enumerable: true,
  9072. configurable: true
  9073. });
  9074. Object.defineProperty(SubscriptionDialog.prototype, "subscriptionState", {
  9075. get: function () {
  9076. return this._subscriptionState;
  9077. },
  9078. enumerable: true,
  9079. configurable: true
  9080. });
  9081. /**
  9082. * Receive in dialog request message from transport.
  9083. * @param message - The incoming request message.
  9084. */
  9085. SubscriptionDialog.prototype.receiveRequest = function (message) {
  9086. this.logger.log("SUBSCRIBE dialog " + this.id + " received " + message.method + " request");
  9087. // Request within a dialog out of sequence guard.
  9088. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  9089. if (!this.sequenceGuard(message)) {
  9090. this.logger.log("SUBSCRIBE dialog " + this.id + " rejected out of order " + message.method + " request.");
  9091. return;
  9092. }
  9093. // Request within a dialog common processing.
  9094. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  9095. _super.prototype.receiveRequest.call(this, message);
  9096. // Switch on method and then delegate.
  9097. switch (message.method) {
  9098. case messages_1.C.NOTIFY:
  9099. this.onNotify(message);
  9100. break;
  9101. default:
  9102. this.logger.log("SUBSCRIBE dialog " + this.id + " received unimplemented " + message.method + " request");
  9103. this.core.replyStateless(message, { statusCode: 501 });
  9104. break;
  9105. }
  9106. };
  9107. /**
  9108. * 4.1.2.2. Refreshing of Subscriptions
  9109. * https://tools.ietf.org/html/rfc6665#section-4.1.2.2
  9110. */
  9111. SubscriptionDialog.prototype.refresh = function () {
  9112. var allowHeader = "Allow: " + allowed_methods_1.AllowedMethods.toString();
  9113. var options = {};
  9114. options.extraHeaders = (options.extraHeaders || []).slice();
  9115. options.extraHeaders.push(allowHeader);
  9116. options.extraHeaders.push("Event: " + this.subscriptionEvent);
  9117. options.extraHeaders.push("Expires: " + this.subscriptionExpiresInitial);
  9118. options.extraHeaders.push("Contact: " + this.core.configuration.contact.toString());
  9119. return this.subscribe(undefined, options);
  9120. };
  9121. /**
  9122. * 4.1.2.2. Refreshing of Subscriptions
  9123. * https://tools.ietf.org/html/rfc6665#section-4.1.2.2
  9124. * @param delegate - Delegate to handle responses.
  9125. * @param options - Options bucket.
  9126. */
  9127. SubscriptionDialog.prototype.subscribe = function (delegate, options) {
  9128. var _this = this;
  9129. if (options === void 0) { options = {}; }
  9130. if (this.subscriptionState !== subscription_1.SubscriptionState.Pending && this.subscriptionState !== subscription_1.SubscriptionState.Active) {
  9131. // FIXME: This needs to be a proper exception
  9132. throw new Error("Invalid state " + this.subscriptionState + ". May only re-subscribe while in state \"pending\" or \"active\".");
  9133. }
  9134. this.logger.log("SUBSCRIBE dialog " + this.id + " sending SUBSCRIBE request");
  9135. var uac = new re_subscribe_user_agent_client_1.ReSubscribeUserAgentClient(this, delegate, options);
  9136. // When refreshing a subscription, a subscriber starts Timer N, set to
  9137. // 64*T1, when it sends the SUBSCRIBE request.
  9138. // https://tools.ietf.org/html/rfc6665#section-4.1.2.2
  9139. this.N = setTimeout(function () { return _this.timer_N(); }, timers_1.Timers.TIMER_N);
  9140. return uac;
  9141. };
  9142. /**
  9143. * 4.4.1. Dialog Creation and Termination
  9144. * A subscription is destroyed after a notifier sends a NOTIFY request
  9145. * with a "Subscription-State" of "terminated", or in certain error
  9146. * situations described elsewhere in this document.
  9147. * https://tools.ietf.org/html/rfc6665#section-4.4.1
  9148. */
  9149. SubscriptionDialog.prototype.terminate = function () {
  9150. this.stateTransition(subscription_1.SubscriptionState.Terminated);
  9151. this.onTerminated();
  9152. };
  9153. /**
  9154. * 4.1.2.3. Unsubscribing
  9155. * https://tools.ietf.org/html/rfc6665#section-4.1.2.3
  9156. */
  9157. SubscriptionDialog.prototype.unsubscribe = function () {
  9158. var allowHeader = "Allow: " + allowed_methods_1.AllowedMethods.toString();
  9159. var options = {};
  9160. options.extraHeaders = (options.extraHeaders || []).slice();
  9161. options.extraHeaders.push(allowHeader);
  9162. options.extraHeaders.push("Event: " + this.subscriptionEvent);
  9163. options.extraHeaders.push("Expires: 0");
  9164. options.extraHeaders.push("Contact: " + this.core.configuration.contact.toString());
  9165. return this.subscribe(undefined, options);
  9166. };
  9167. /**
  9168. * Handle in dialog NOTIFY requests.
  9169. * This does not include the first NOTIFY which created the dialog.
  9170. * @param message - The incoming NOTIFY request message.
  9171. */
  9172. SubscriptionDialog.prototype.onNotify = function (message) {
  9173. // If, for some reason, the event package designated in the "Event"
  9174. // header field of the NOTIFY request is not supported, the subscriber
  9175. // will respond with a 489 (Bad Event) response.
  9176. // https://tools.ietf.org/html/rfc6665#section-4.1.3
  9177. var event = message.parseHeader("Event").event;
  9178. if (!event || event !== this.subscriptionEvent) {
  9179. this.core.replyStateless(message, { statusCode: 489 });
  9180. return;
  9181. }
  9182. // In the state diagram, "Re-subscription times out" means that an
  9183. // attempt to refresh or update the subscription using a new SUBSCRIBE
  9184. // request does not result in a NOTIFY request before the corresponding
  9185. // Timer N expires.
  9186. // https://tools.ietf.org/html/rfc6665#section-4.1.2
  9187. if (this.N) {
  9188. clearTimeout(this.N);
  9189. this.N = undefined;
  9190. }
  9191. // NOTIFY requests MUST contain "Subscription-State" header fields that
  9192. // indicate the status of the subscription.
  9193. // https://tools.ietf.org/html/rfc6665#section-4.1.3
  9194. var subscriptionState = message.parseHeader("Subscription-State");
  9195. if (!subscriptionState || !subscriptionState.state) {
  9196. this.core.replyStateless(message, { statusCode: 489 });
  9197. return;
  9198. }
  9199. var state = subscriptionState.state;
  9200. var expires = subscriptionState.expires ? Math.max(subscriptionState.expires, 0) : undefined;
  9201. // Update our state and expiration.
  9202. switch (state) {
  9203. case "pending":
  9204. this.stateTransition(subscription_1.SubscriptionState.Pending, expires);
  9205. break;
  9206. case "active":
  9207. this.stateTransition(subscription_1.SubscriptionState.Active, expires);
  9208. break;
  9209. case "terminated":
  9210. this.stateTransition(subscription_1.SubscriptionState.Terminated, expires);
  9211. break;
  9212. default:
  9213. this.logger.warn("Unrecognized subscription state.");
  9214. break;
  9215. }
  9216. // Delegate remainder of NOTIFY handling.
  9217. var uas = new notify_user_agent_server_1.NotifyUserAgentServer(this, message);
  9218. if (this.delegate && this.delegate.onNotify) {
  9219. this.delegate.onNotify(uas);
  9220. }
  9221. else {
  9222. uas.accept();
  9223. }
  9224. };
  9225. SubscriptionDialog.prototype.onRefresh = function (request) {
  9226. if (this.delegate && this.delegate.onRefresh) {
  9227. this.delegate.onRefresh(request);
  9228. }
  9229. };
  9230. SubscriptionDialog.prototype.onTerminated = function () {
  9231. if (this.delegate && this.delegate.onTerminated) {
  9232. this.delegate.onTerminated();
  9233. }
  9234. };
  9235. SubscriptionDialog.prototype.refreshTimerClear = function () {
  9236. if (this.refreshTimer) {
  9237. clearTimeout(this.refreshTimer);
  9238. this.refreshTimer = undefined;
  9239. }
  9240. };
  9241. SubscriptionDialog.prototype.refreshTimerSet = function () {
  9242. var _this = this;
  9243. this.refreshTimerClear();
  9244. if (this.autoRefresh && this.subscriptionExpires > 0) {
  9245. var refresh = this.subscriptionExpires * 900;
  9246. this._subscriptionRefresh = Math.floor(refresh / 1000);
  9247. this._subscriptionRefreshLastSet = Math.floor(Date.now() / 1000);
  9248. this.refreshTimer = setTimeout(function () {
  9249. _this.refreshTimer = undefined;
  9250. _this._subscriptionRefresh = undefined;
  9251. _this._subscriptionRefreshLastSet = undefined;
  9252. _this.onRefresh(_this.refresh());
  9253. }, refresh);
  9254. }
  9255. };
  9256. SubscriptionDialog.prototype.stateTransition = function (newState, newExpires) {
  9257. var _this = this;
  9258. // Assert valid state transitions.
  9259. var invalidStateTransition = function () {
  9260. _this.logger.warn("Invalid subscription state transition from " + _this.subscriptionState + " to " + newState);
  9261. };
  9262. switch (newState) {
  9263. case subscription_1.SubscriptionState.Initial:
  9264. invalidStateTransition();
  9265. return;
  9266. case subscription_1.SubscriptionState.NotifyWait:
  9267. invalidStateTransition();
  9268. return;
  9269. case subscription_1.SubscriptionState.Pending:
  9270. if (this.subscriptionState !== subscription_1.SubscriptionState.NotifyWait &&
  9271. this.subscriptionState !== subscription_1.SubscriptionState.Pending) {
  9272. invalidStateTransition();
  9273. return;
  9274. }
  9275. break;
  9276. case subscription_1.SubscriptionState.Active:
  9277. if (this.subscriptionState !== subscription_1.SubscriptionState.NotifyWait &&
  9278. this.subscriptionState !== subscription_1.SubscriptionState.Pending &&
  9279. this.subscriptionState !== subscription_1.SubscriptionState.Active) {
  9280. invalidStateTransition();
  9281. return;
  9282. }
  9283. break;
  9284. case subscription_1.SubscriptionState.Terminated:
  9285. if (this.subscriptionState !== subscription_1.SubscriptionState.NotifyWait &&
  9286. this.subscriptionState !== subscription_1.SubscriptionState.Pending &&
  9287. this.subscriptionState !== subscription_1.SubscriptionState.Active) {
  9288. invalidStateTransition();
  9289. return;
  9290. }
  9291. break;
  9292. default:
  9293. invalidStateTransition();
  9294. return;
  9295. }
  9296. // If the "Subscription-State" value is "pending", the subscription has
  9297. // been received by the notifier, but there is insufficient policy
  9298. // information to grant or deny the subscription yet. If the header
  9299. // field also contains an "expires" parameter, the subscriber SHOULD
  9300. // take it as the authoritative subscription duration and adjust
  9301. // accordingly. No further action is necessary on the part of the
  9302. // subscriber. The "retry-after" and "reason" parameters have no
  9303. // semantics for "pending".
  9304. // https://tools.ietf.org/html/rfc6665#section-4.1.3
  9305. if (newState === subscription_1.SubscriptionState.Pending) {
  9306. if (newExpires) {
  9307. this.subscriptionExpires = newExpires;
  9308. }
  9309. }
  9310. // If the "Subscription-State" header field value is "active", it means
  9311. // that the subscription has been accepted and (in general) has been
  9312. // authorized. If the header field also contains an "expires"
  9313. // parameter, the subscriber SHOULD take it as the authoritative
  9314. // subscription duration and adjust accordingly. The "retry-after" and
  9315. // "reason" parameters have no semantics for "active".
  9316. // https://tools.ietf.org/html/rfc6665#section-4.1.3
  9317. if (newState === subscription_1.SubscriptionState.Active) {
  9318. if (newExpires) {
  9319. this.subscriptionExpires = newExpires;
  9320. }
  9321. }
  9322. // If the "Subscription-State" value is "terminated", the subscriber
  9323. // MUST consider the subscription terminated. The "expires" parameter
  9324. // has no semantics for "terminated" -- notifiers SHOULD NOT include an
  9325. // "expires" parameter on a "Subscription-State" header field with a
  9326. // value of "terminated", and subscribers MUST ignore any such
  9327. // parameter, if present.
  9328. if (newState === subscription_1.SubscriptionState.Terminated) {
  9329. this.dispose();
  9330. }
  9331. this._subscriptionState = newState;
  9332. };
  9333. /**
  9334. * When refreshing a subscription, a subscriber starts Timer N, set to
  9335. * 64*T1, when it sends the SUBSCRIBE request. If this Timer N expires
  9336. * prior to the receipt of a NOTIFY request, the subscriber considers
  9337. * the subscription terminated. If the subscriber receives a success
  9338. * response to the SUBSCRIBE request that indicates that no NOTIFY
  9339. * request will be generated -- such as the 204 response defined for use
  9340. * with the optional extension described in [RFC5839] -- then it MUST
  9341. * cancel Timer N.
  9342. * https://tools.ietf.org/html/rfc6665#section-4.1.2.2
  9343. */
  9344. SubscriptionDialog.prototype.timer_N = function () {
  9345. if (this.subscriptionState !== subscription_1.SubscriptionState.Terminated) {
  9346. this.stateTransition(subscription_1.SubscriptionState.Terminated);
  9347. this.onTerminated();
  9348. }
  9349. };
  9350. return SubscriptionDialog;
  9351. }(dialog_1.Dialog));
  9352. exports.SubscriptionDialog = SubscriptionDialog;
  9353. /***/ }),
  9354. /* 56 */
  9355. /***/ (function(module, exports, __webpack_require__) {
  9356. "use strict";
  9357. Object.defineProperty(exports, "__esModule", { value: true });
  9358. var tslib_1 = __webpack_require__(1);
  9359. tslib_1.__exportStar(__webpack_require__(57), exports);
  9360. /***/ }),
  9361. /* 57 */
  9362. /***/ (function(module, exports, __webpack_require__) {
  9363. "use strict";
  9364. Object.defineProperty(exports, "__esModule", { value: true });
  9365. /**
  9366. * Subscription state.
  9367. * @remarks
  9368. * https://tools.ietf.org/html/rfc6665#section-4.1.2
  9369. * @public
  9370. */
  9371. var SubscriptionState;
  9372. (function (SubscriptionState) {
  9373. SubscriptionState["Initial"] = "Initial";
  9374. SubscriptionState["NotifyWait"] = "NotifyWait";
  9375. SubscriptionState["Pending"] = "Pending";
  9376. SubscriptionState["Active"] = "Active";
  9377. SubscriptionState["Terminated"] = "Terminated";
  9378. })(SubscriptionState = exports.SubscriptionState || (exports.SubscriptionState = {}));
  9379. /***/ }),
  9380. /* 58 */
  9381. /***/ (function(module, exports, __webpack_require__) {
  9382. "use strict";
  9383. Object.defineProperty(exports, "__esModule", { value: true });
  9384. var messages_1 = __webpack_require__(5);
  9385. /**
  9386. * FIXME: TODO: Should be configurable/variable.
  9387. */
  9388. exports.AllowedMethods = [
  9389. messages_1.C.ACK,
  9390. messages_1.C.BYE,
  9391. messages_1.C.CANCEL,
  9392. messages_1.C.INFO,
  9393. messages_1.C.INVITE,
  9394. messages_1.C.MESSAGE,
  9395. messages_1.C.NOTIFY,
  9396. messages_1.C.OPTIONS,
  9397. messages_1.C.PRACK,
  9398. messages_1.C.REFER,
  9399. messages_1.C.REGISTER,
  9400. messages_1.C.SUBSCRIBE
  9401. ];
  9402. /***/ }),
  9403. /* 59 */
  9404. /***/ (function(module, exports, __webpack_require__) {
  9405. "use strict";
  9406. Object.defineProperty(exports, "__esModule", { value: true });
  9407. var tslib_1 = __webpack_require__(1);
  9408. var messages_1 = __webpack_require__(5);
  9409. var transactions_1 = __webpack_require__(27);
  9410. var user_agent_client_1 = __webpack_require__(42);
  9411. /**
  9412. * Re-SUBSCRIBE UAC.
  9413. * @public
  9414. */
  9415. var ReSubscribeUserAgentClient = /** @class */ (function (_super) {
  9416. tslib_1.__extends(ReSubscribeUserAgentClient, _super);
  9417. function ReSubscribeUserAgentClient(dialog, delegate, options) {
  9418. var _this = this;
  9419. var message = dialog.createOutgoingRequestMessage(messages_1.C.SUBSCRIBE, options);
  9420. _this = _super.call(this, transactions_1.NonInviteClientTransaction, dialog.userAgentCore, message, delegate) || this;
  9421. _this.dialog = dialog;
  9422. return _this;
  9423. }
  9424. ReSubscribeUserAgentClient.prototype.waitNotifyStop = function () {
  9425. // TODO: Placeholder. Not utilized currently.
  9426. return;
  9427. };
  9428. /**
  9429. * Receive a response from the transaction layer.
  9430. * @param message - Incoming response message.
  9431. */
  9432. ReSubscribeUserAgentClient.prototype.receiveResponse = function (message) {
  9433. if (message.statusCode && message.statusCode >= 200 && message.statusCode < 300) {
  9434. // The "Expires" header field in a 200-class response to SUBSCRIBE
  9435. // request indicates the actual duration for which the subscription will
  9436. // remain active (unless refreshed). The received value might be
  9437. // smaller than the value indicated in the SUBSCRIBE request but cannot
  9438. // be larger; see Section 4.2.1 for details.
  9439. // https://tools.ietf.org/html/rfc6665#section-4.1.2.1
  9440. var expires = message.getHeader("Expires");
  9441. if (!expires) {
  9442. this.logger.warn("Expires header missing in a 200-class response to SUBSCRIBE");
  9443. }
  9444. else {
  9445. var subscriptionExpiresReceived = Number(expires);
  9446. if (this.dialog.subscriptionExpires > subscriptionExpiresReceived) {
  9447. this.dialog.subscriptionExpires = subscriptionExpiresReceived;
  9448. }
  9449. }
  9450. }
  9451. if (message.statusCode && message.statusCode >= 400 && message.statusCode < 700) {
  9452. // If a SUBSCRIBE request to refresh a subscription receives a 404, 405,
  9453. // 410, 416, 480-485, 489, 501, or 604 response, the subscriber MUST
  9454. // consider the subscription terminated. (See [RFC5057] for further
  9455. // details and notes about the effect of error codes on dialogs and
  9456. // usages within dialog, such as subscriptions). If the subscriber
  9457. // wishes to re-subscribe to the state, he does so by composing an
  9458. // unrelated initial SUBSCRIBE request with a freshly generated Call-ID
  9459. // and a new, unique "From" tag (see Section 4.1.2.1).
  9460. // https://tools.ietf.org/html/rfc6665#section-4.1.2.2
  9461. var errorCodes = [404, 405, 410, 416, 480, 481, 482, 483, 484, 485, 489, 501, 604];
  9462. if (errorCodes.indexOf(message.statusCode) !== -1) {
  9463. this.dialog.terminate();
  9464. }
  9465. // If a SUBSCRIBE request to refresh a subscription fails with any error
  9466. // code other than those listed above, the original subscription is
  9467. // still considered valid for the duration of the most recently known
  9468. // "Expires" value as negotiated by the most recent successful SUBSCRIBE
  9469. // transaction, or as communicated by a NOTIFY request in its
  9470. // "Subscription-State" header field "expires" parameter.
  9471. // https://tools.ietf.org/html/rfc6665#section-4.1.2.2
  9472. }
  9473. _super.prototype.receiveResponse.call(this, message);
  9474. };
  9475. return ReSubscribeUserAgentClient;
  9476. }(user_agent_client_1.UserAgentClient));
  9477. exports.ReSubscribeUserAgentClient = ReSubscribeUserAgentClient;
  9478. /***/ }),
  9479. /* 60 */
  9480. /***/ (function(module, exports, __webpack_require__) {
  9481. "use strict";
  9482. Object.defineProperty(exports, "__esModule", { value: true });
  9483. var tslib_1 = __webpack_require__(1);
  9484. tslib_1.__exportStar(__webpack_require__(61), exports);
  9485. tslib_1.__exportStar(__webpack_require__(62), exports);
  9486. tslib_1.__exportStar(__webpack_require__(63), exports);
  9487. /***/ }),
  9488. /* 61 */
  9489. /***/ (function(module, exports, __webpack_require__) {
  9490. "use strict";
  9491. Object.defineProperty(exports, "__esModule", { value: true });
  9492. /**
  9493. * Log levels.
  9494. * @public
  9495. */
  9496. var Levels;
  9497. (function (Levels) {
  9498. Levels[Levels["error"] = 0] = "error";
  9499. Levels[Levels["warn"] = 1] = "warn";
  9500. Levels[Levels["log"] = 2] = "log";
  9501. Levels[Levels["debug"] = 3] = "debug";
  9502. })(Levels = exports.Levels || (exports.Levels = {}));
  9503. /***/ }),
  9504. /* 62 */
  9505. /***/ (function(module, exports, __webpack_require__) {
  9506. "use strict";
  9507. Object.defineProperty(exports, "__esModule", { value: true });
  9508. var levels_1 = __webpack_require__(61);
  9509. var logger_1 = __webpack_require__(63);
  9510. /**
  9511. * Logger.
  9512. * @public
  9513. */
  9514. var LoggerFactory = /** @class */ (function () {
  9515. function LoggerFactory() {
  9516. this.builtinEnabled = true;
  9517. this._level = levels_1.Levels.log;
  9518. this.loggers = {};
  9519. this.logger = this.getLogger("sip:loggerfactory");
  9520. }
  9521. Object.defineProperty(LoggerFactory.prototype, "level", {
  9522. get: function () { return this._level; },
  9523. set: function (newLevel) {
  9524. if (newLevel >= 0 && newLevel <= 3) {
  9525. this._level = newLevel;
  9526. }
  9527. else if (newLevel > 3) {
  9528. this._level = 3;
  9529. }
  9530. else if (levels_1.Levels.hasOwnProperty(newLevel)) {
  9531. this._level = newLevel;
  9532. }
  9533. else {
  9534. this.logger.error("invalid 'level' parameter value: " + JSON.stringify(newLevel));
  9535. }
  9536. },
  9537. enumerable: true,
  9538. configurable: true
  9539. });
  9540. Object.defineProperty(LoggerFactory.prototype, "connector", {
  9541. get: function () {
  9542. return this._connector;
  9543. },
  9544. set: function (value) {
  9545. if (!value) {
  9546. this._connector = undefined;
  9547. }
  9548. else if (typeof value === "function") {
  9549. this._connector = value;
  9550. }
  9551. else {
  9552. this.logger.error("invalid 'connector' parameter value: " + JSON.stringify(value));
  9553. }
  9554. },
  9555. enumerable: true,
  9556. configurable: true
  9557. });
  9558. LoggerFactory.prototype.getLogger = function (category, label) {
  9559. if (label && this.level === 3) {
  9560. return new logger_1.Logger(this, category, label);
  9561. }
  9562. else if (this.loggers[category]) {
  9563. return this.loggers[category];
  9564. }
  9565. else {
  9566. var logger = new logger_1.Logger(this, category);
  9567. this.loggers[category] = logger;
  9568. return logger;
  9569. }
  9570. };
  9571. LoggerFactory.prototype.genericLog = function (levelToLog, category, label, content) {
  9572. if (this.level >= levelToLog) {
  9573. if (this.builtinEnabled) {
  9574. this.print(levelToLog, category, label, content);
  9575. }
  9576. }
  9577. if (this.connector) {
  9578. this.connector(levels_1.Levels[levelToLog], category, label, content);
  9579. }
  9580. };
  9581. LoggerFactory.prototype.print = function (levelToLog, category, label, content) {
  9582. if (typeof content === "string") {
  9583. var prefix = [new Date(), category];
  9584. if (label) {
  9585. prefix.push(label);
  9586. }
  9587. content = prefix.concat(content).join(" | ");
  9588. }
  9589. switch (levelToLog) {
  9590. case levels_1.Levels.error:
  9591. // tslint:disable-next-line:no-console
  9592. console.error(content);
  9593. break;
  9594. case levels_1.Levels.warn:
  9595. // tslint:disable-next-line:no-console
  9596. console.warn(content);
  9597. break;
  9598. case levels_1.Levels.log:
  9599. // tslint:disable-next-line:no-console
  9600. console.log(content);
  9601. break;
  9602. case levels_1.Levels.debug:
  9603. // tslint:disable-next-line:no-console
  9604. console.debug(content);
  9605. break;
  9606. default:
  9607. break;
  9608. }
  9609. };
  9610. return LoggerFactory;
  9611. }());
  9612. exports.LoggerFactory = LoggerFactory;
  9613. /***/ }),
  9614. /* 63 */
  9615. /***/ (function(module, exports, __webpack_require__) {
  9616. "use strict";
  9617. Object.defineProperty(exports, "__esModule", { value: true });
  9618. var levels_1 = __webpack_require__(61);
  9619. /**
  9620. * Logger.
  9621. * @public
  9622. */
  9623. var Logger = /** @class */ (function () {
  9624. function Logger(logger, category, label) {
  9625. this.logger = logger;
  9626. this.category = category;
  9627. this.label = label;
  9628. }
  9629. Logger.prototype.error = function (content) { this.genericLog(levels_1.Levels.error, content); };
  9630. Logger.prototype.warn = function (content) { this.genericLog(levels_1.Levels.warn, content); };
  9631. Logger.prototype.log = function (content) { this.genericLog(levels_1.Levels.log, content); };
  9632. Logger.prototype.debug = function (content) { this.genericLog(levels_1.Levels.debug, content); };
  9633. Logger.prototype.genericLog = function (level, content) {
  9634. this.logger.genericLog(level, this.category, this.label, content);
  9635. };
  9636. return Logger;
  9637. }());
  9638. exports.Logger = Logger;
  9639. /***/ }),
  9640. /* 64 */
  9641. /***/ (function(module, exports, __webpack_require__) {
  9642. "use strict";
  9643. Object.defineProperty(exports, "__esModule", { value: true });
  9644. var tslib_1 = __webpack_require__(1);
  9645. tslib_1.__exportStar(__webpack_require__(65), exports);
  9646. /***/ }),
  9647. /* 65 */
  9648. /***/ (function(module, exports, __webpack_require__) {
  9649. "use strict";
  9650. Object.defineProperty(exports, "__esModule", { value: true });
  9651. var tslib_1 = __webpack_require__(1);
  9652. var messages_1 = __webpack_require__(5);
  9653. var transactions_1 = __webpack_require__(27);
  9654. var user_agents_1 = __webpack_require__(66);
  9655. var allowed_methods_1 = __webpack_require__(58);
  9656. /**
  9657. * This is ported from UA.C.ACCEPTED_BODY_TYPES.
  9658. * FIXME: TODO: Should be configurable/variable.
  9659. */
  9660. var acceptedBodyTypes = [
  9661. "application/sdp",
  9662. "application/dtmf-relay"
  9663. ];
  9664. /**
  9665. * User Agent Core.
  9666. * @remarks
  9667. * Core designates the functions specific to a particular type
  9668. * of SIP entity, i.e., specific to either a stateful or stateless
  9669. * proxy, a user agent or registrar. All cores, except those for
  9670. * the stateless proxy, are transaction users.
  9671. * https://tools.ietf.org/html/rfc3261#section-6
  9672. *
  9673. * UAC Core: The set of processing functions required of a UAC that
  9674. * reside above the transaction and transport layers.
  9675. * https://tools.ietf.org/html/rfc3261#section-6
  9676. *
  9677. * UAS Core: The set of processing functions required at a UAS that
  9678. * resides above the transaction and transport layers.
  9679. * https://tools.ietf.org/html/rfc3261#section-6
  9680. * @public
  9681. */
  9682. var UserAgentCore = /** @class */ (function () {
  9683. /**
  9684. * Constructor.
  9685. * @param configuration - Configuration.
  9686. * @param delegate - Delegate.
  9687. */
  9688. function UserAgentCore(configuration, delegate) {
  9689. if (delegate === void 0) { delegate = {}; }
  9690. /** UACs. */
  9691. this.userAgentClients = new Map();
  9692. /** UASs. */
  9693. this.userAgentServers = new Map();
  9694. this.configuration = configuration;
  9695. this.delegate = delegate;
  9696. this.dialogs = new Map();
  9697. this.subscribers = new Map();
  9698. this.logger = configuration.loggerFactory.getLogger("sip.user-agent-core");
  9699. }
  9700. /** Destructor. */
  9701. UserAgentCore.prototype.dispose = function () {
  9702. this.reset();
  9703. };
  9704. /** Reset. */
  9705. UserAgentCore.prototype.reset = function () {
  9706. this.dialogs.forEach(function (dialog) { return dialog.dispose(); });
  9707. this.dialogs.clear();
  9708. this.subscribers.forEach(function (subscriber) { return subscriber.dispose(); });
  9709. this.subscribers.clear();
  9710. this.userAgentClients.forEach(function (uac) { return uac.dispose(); });
  9711. this.userAgentClients.clear();
  9712. this.userAgentServers.forEach(function (uac) { return uac.dispose(); });
  9713. this.userAgentServers.clear();
  9714. };
  9715. Object.defineProperty(UserAgentCore.prototype, "loggerFactory", {
  9716. /** Logger factory. */
  9717. get: function () {
  9718. return this.configuration.loggerFactory;
  9719. },
  9720. enumerable: true,
  9721. configurable: true
  9722. });
  9723. Object.defineProperty(UserAgentCore.prototype, "transport", {
  9724. /** Transport. */
  9725. get: function () {
  9726. var transport = this.configuration.transportAccessor();
  9727. if (!transport) {
  9728. throw new Error("Transport undefined.");
  9729. }
  9730. return transport;
  9731. },
  9732. enumerable: true,
  9733. configurable: true
  9734. });
  9735. /**
  9736. * Send INVITE.
  9737. * @param request - Outgoing request.
  9738. * @param delegate - Request delegate.
  9739. */
  9740. UserAgentCore.prototype.invite = function (request, delegate) {
  9741. return new user_agents_1.InviteUserAgentClient(this, request, delegate);
  9742. };
  9743. /**
  9744. * Send MESSAGE.
  9745. * @param request - Outgoing request.
  9746. * @param delegate - Request delegate.
  9747. */
  9748. UserAgentCore.prototype.message = function (request, delegate) {
  9749. return new user_agents_1.MessageUserAgentClient(this, request, delegate);
  9750. };
  9751. /**
  9752. * Send PUBLISH.
  9753. * @param request - Outgoing request.
  9754. * @param delegate - Request delegate.
  9755. */
  9756. UserAgentCore.prototype.publish = function (request, delegate) {
  9757. return new user_agents_1.PublishUserAgentClient(this, request, delegate);
  9758. };
  9759. /**
  9760. * Send REGISTER.
  9761. * @param request - Outgoing request.
  9762. * @param delegate - Request delegate.
  9763. */
  9764. UserAgentCore.prototype.register = function (request, delegate) {
  9765. return new user_agents_1.RegisterUserAgentClient(this, request, delegate);
  9766. };
  9767. /**
  9768. * Send SUBSCRIBE.
  9769. * @param request - Outgoing request.
  9770. * @param delegate - Request delegate.
  9771. */
  9772. UserAgentCore.prototype.subscribe = function (request, delegate) {
  9773. return new user_agents_1.SubscribeUserAgentClient(this, request, delegate);
  9774. };
  9775. /**
  9776. * Send a request.
  9777. * @param request - Outgoing request.
  9778. * @param delegate - Request delegate.
  9779. */
  9780. UserAgentCore.prototype.request = function (request, delegate) {
  9781. return new user_agents_1.UserAgentClient(transactions_1.NonInviteClientTransaction, this, request, delegate);
  9782. };
  9783. /**
  9784. * Outgoing request message factory function.
  9785. * @param method - Method.
  9786. * @param requestURI - Request-URI.
  9787. * @param fromURI - From URI.
  9788. * @param toURI - To URI.
  9789. * @param options - Request options.
  9790. * @param extraHeaders - Extra headers to add.
  9791. * @param body - Message body.
  9792. */
  9793. UserAgentCore.prototype.makeOutgoingRequestMessage = function (method, requestURI, fromURI, toURI, options, extraHeaders, body) {
  9794. // default values from user agent configuration
  9795. var callIdPrefix = this.configuration.sipjsId;
  9796. var fromDisplayName = this.configuration.displayName;
  9797. var forceRport = this.configuration.viaForceRport;
  9798. var hackViaTcp = this.configuration.hackViaTcp;
  9799. var optionTags = this.configuration.supportedOptionTags.slice();
  9800. if (method === messages_1.C.REGISTER) {
  9801. optionTags.push("path", "gruu");
  9802. }
  9803. if (method === messages_1.C.INVITE && (this.configuration.contact.pubGruu || this.configuration.contact.tempGruu)) {
  9804. optionTags.push("gruu");
  9805. }
  9806. var routeSet = this.configuration.routeSet;
  9807. var userAgentString = this.configuration.userAgentHeaderFieldValue;
  9808. var viaHost = this.configuration.viaHost;
  9809. var defaultOptions = {
  9810. callIdPrefix: callIdPrefix,
  9811. forceRport: forceRport,
  9812. fromDisplayName: fromDisplayName,
  9813. hackViaTcp: hackViaTcp,
  9814. optionTags: optionTags,
  9815. routeSet: routeSet,
  9816. userAgentString: userAgentString,
  9817. viaHost: viaHost,
  9818. };
  9819. // merge provided options with default options
  9820. var requestOptions = tslib_1.__assign(tslib_1.__assign({}, defaultOptions), options);
  9821. return new messages_1.OutgoingRequestMessage(method, requestURI, fromURI, toURI, requestOptions, extraHeaders, body);
  9822. };
  9823. /**
  9824. * Handle an incoming request message from the transport.
  9825. * @param message - Incoming request message from transport layer.
  9826. */
  9827. UserAgentCore.prototype.receiveIncomingRequestFromTransport = function (message) {
  9828. this.receiveRequestFromTransport(message);
  9829. };
  9830. /**
  9831. * Handle an incoming response message from the transport.
  9832. * @param message - Incoming response message from transport layer.
  9833. */
  9834. UserAgentCore.prototype.receiveIncomingResponseFromTransport = function (message) {
  9835. this.receiveResponseFromTransport(message);
  9836. };
  9837. /**
  9838. * A stateless UAS is a UAS that does not maintain transaction state.
  9839. * It replies to requests normally, but discards any state that would
  9840. * ordinarily be retained by a UAS after a response has been sent. If a
  9841. * stateless UAS receives a retransmission of a request, it regenerates
  9842. * the response and re-sends it, just as if it were replying to the first
  9843. * instance of the request. A UAS cannot be stateless unless the request
  9844. * processing for that method would always result in the same response
  9845. * if the requests are identical. This rules out stateless registrars,
  9846. * for example. Stateless UASs do not use a transaction layer; they
  9847. * receive requests directly from the transport layer and send responses
  9848. * directly to the transport layer.
  9849. * https://tools.ietf.org/html/rfc3261#section-8.2.7
  9850. * @param message - Incoming request message to reply to.
  9851. * @param statusCode - Status code to reply with.
  9852. */
  9853. UserAgentCore.prototype.replyStateless = function (message, options) {
  9854. var _this = this;
  9855. var userAgent = this.configuration.userAgentHeaderFieldValue;
  9856. var supported = this.configuration.supportedOptionTagsResponse;
  9857. options = tslib_1.__assign(tslib_1.__assign({}, options), { userAgent: userAgent, supported: supported });
  9858. var response = messages_1.constructOutgoingResponse(message, options);
  9859. this.transport.send(response.message).catch(function (error) {
  9860. // If the transport rejects, it SHOULD reject with a TransportError.
  9861. // But the transport may be external code, so we are careful...
  9862. if (error instanceof Error) {
  9863. _this.logger.error(error.message);
  9864. }
  9865. _this.logger.error("Transport error occurred sending stateless reply to " + message.method + " request.");
  9866. // TODO: Currently there is no hook to provide notification that a transport error occurred
  9867. // and throwing would result in an uncaught error (in promise), so we siliently eat the error.
  9868. // Furthermore, silienty eating stateless reply transport errors is arguably what we want to do here.
  9869. });
  9870. return response;
  9871. };
  9872. /**
  9873. * In Section 18.2.1, replace the last paragraph with:
  9874. *
  9875. * Next, the server transport attempts to match the request to a
  9876. * server transaction. It does so using the matching rules described
  9877. * in Section 17.2.3. If a matching server transaction is found, the
  9878. * request is passed to that transaction for processing. If no match
  9879. * is found, the request is passed to the core, which may decide to
  9880. * construct a new server transaction for that request.
  9881. * https://tools.ietf.org/html/rfc6026#section-8.10
  9882. * @param message - Incoming request message from transport layer.
  9883. */
  9884. UserAgentCore.prototype.receiveRequestFromTransport = function (message) {
  9885. // When a request is received from the network by the server, it has to
  9886. // be matched to an existing transaction. This is accomplished in the
  9887. // following manner.
  9888. //
  9889. // The branch parameter in the topmost Via header field of the request
  9890. // is examined. If it is present and begins with the magic cookie
  9891. // "z9hG4bK", the request was generated by a client transaction
  9892. // compliant to this specification. Therefore, the branch parameter
  9893. // will be unique across all transactions sent by that client. The
  9894. // request matches a transaction if:
  9895. //
  9896. // 1. the branch parameter in the request is equal to the one in the
  9897. // top Via header field of the request that created the
  9898. // transaction, and
  9899. //
  9900. // 2. the sent-by value in the top Via of the request is equal to the
  9901. // one in the request that created the transaction, and
  9902. //
  9903. // 3. the method of the request matches the one that created the
  9904. // transaction, except for ACK, where the method of the request
  9905. // that created the transaction is INVITE.
  9906. //
  9907. // This matching rule applies to both INVITE and non-INVITE transactions
  9908. // alike.
  9909. //
  9910. // The sent-by value is used as part of the matching process because
  9911. // there could be accidental or malicious duplication of branch
  9912. // parameters from different clients.
  9913. // https://tools.ietf.org/html/rfc3261#section-17.2.3
  9914. var transactionId = message.viaBranch; // FIXME: Currently only using rule 1...
  9915. var uas = this.userAgentServers.get(transactionId);
  9916. // When receiving an ACK that matches an existing INVITE server
  9917. // transaction and that does not contain a branch parameter containing
  9918. // the magic cookie defined in RFC 3261, the matching transaction MUST
  9919. // be checked to see if it is in the "Accepted" state. If it is, then
  9920. // the ACK must be passed directly to the transaction user instead of
  9921. // being absorbed by the transaction state machine. This is necessary
  9922. // as requests from RFC 2543 clients will not include a unique branch
  9923. // parameter, and the mechanisms for calculating the transaction ID from
  9924. // such a request will be the same for both INVITE and ACKs.
  9925. // https://tools.ietf.org/html/rfc6026#section-6
  9926. // Any ACKs received from the network while in the "Accepted" state MUST be
  9927. // passed directly to the TU and not absorbed.
  9928. // https://tools.ietf.org/html/rfc6026#section-7.1
  9929. if (message.method === messages_1.C.ACK) {
  9930. if (uas && uas.transaction.state === transactions_1.TransactionState.Accepted) {
  9931. if (uas instanceof user_agents_1.InviteUserAgentServer) {
  9932. // These are ACKs matching an INVITE server transaction.
  9933. // These should never happen with RFC 3261 compliant user agents
  9934. // (would be a broken ACK to negative final response or something)
  9935. // but is apparently how RFC 2543 user agents do things.
  9936. // We are not currently supporting this case.
  9937. // NOTE: Not backwards compatible with RFC 2543 (no support for strict-routing).
  9938. this.logger.warn("Discarding out of dialog ACK after 2xx response sent on transaction " + transactionId + ".");
  9939. return;
  9940. }
  9941. }
  9942. }
  9943. // The CANCEL method requests that the TU at the server side cancel a
  9944. // pending transaction. The TU determines the transaction to be
  9945. // cancelled by taking the CANCEL request, and then assuming that the
  9946. // request method is anything but CANCEL or ACK and applying the
  9947. // transaction matching procedures of Section 17.2.3. The matching
  9948. // transaction is the one to be cancelled.
  9949. // https://tools.ietf.org/html/rfc3261#section-9.2
  9950. if (message.method === messages_1.C.CANCEL) {
  9951. if (uas) {
  9952. // Regardless of the method of the original request, as long as the
  9953. // CANCEL matched an existing transaction, the UAS answers the CANCEL
  9954. // request itself with a 200 (OK) response.
  9955. // https://tools.ietf.org/html/rfc3261#section-9.2
  9956. this.replyStateless(message, { statusCode: 200 });
  9957. // If the transaction for the original request still exists, the behavior
  9958. // of the UAS on receiving a CANCEL request depends on whether it has already
  9959. // sent a final response for the original request. If it has, the CANCEL
  9960. // request has no effect on the processing of the original request, no
  9961. // effect on any session state, and no effect on the responses generated
  9962. // for the original request. If the UAS has not issued a final response
  9963. // for the original request, its behavior depends on the method of the
  9964. // original request. If the original request was an INVITE, the UAS
  9965. // SHOULD immediately respond to the INVITE with a 487 (Request
  9966. // Terminated).
  9967. // https://tools.ietf.org/html/rfc3261#section-9.2
  9968. if (uas.transaction instanceof transactions_1.InviteServerTransaction &&
  9969. uas.transaction.state === transactions_1.TransactionState.Proceeding) {
  9970. if (uas instanceof user_agents_1.InviteUserAgentServer) {
  9971. uas.receiveCancel(message);
  9972. }
  9973. // A CANCEL request has no impact on the processing of
  9974. // transactions with any other method defined in this specification.
  9975. // https://tools.ietf.org/html/rfc3261#section-9.2
  9976. }
  9977. }
  9978. else {
  9979. // If the UAS did not find a matching transaction for the CANCEL
  9980. // according to the procedure above, it SHOULD respond to the CANCEL
  9981. // with a 481 (Call Leg/Transaction Does Not Exist).
  9982. // https://tools.ietf.org/html/rfc3261#section-9.2
  9983. this.replyStateless(message, { statusCode: 481 });
  9984. }
  9985. return;
  9986. }
  9987. // If a matching server transaction is found, the request is passed to that
  9988. // transaction for processing.
  9989. // https://tools.ietf.org/html/rfc6026#section-8.10
  9990. if (uas) {
  9991. uas.transaction.receiveRequest(message);
  9992. return;
  9993. }
  9994. // If no match is found, the request is passed to the core, which may decide to
  9995. // construct a new server transaction for that request.
  9996. // https://tools.ietf.org/html/rfc6026#section-8.10
  9997. this.receiveRequest(message);
  9998. return;
  9999. };
  10000. /**
  10001. * UAC and UAS procedures depend strongly on two factors. First, based
  10002. * on whether the request or response is inside or outside of a dialog,
  10003. * and second, based on the method of a request. Dialogs are discussed
  10004. * thoroughly in Section 12; they represent a peer-to-peer relationship
  10005. * between user agents and are established by specific SIP methods, such
  10006. * as INVITE.
  10007. * @param message - Incoming request message.
  10008. */
  10009. UserAgentCore.prototype.receiveRequest = function (message) {
  10010. // 8.2 UAS Behavior
  10011. // UASs SHOULD process the requests in the order of the steps that
  10012. // follow in this section (that is, starting with authentication, then
  10013. // inspecting the method, the header fields, and so on throughout the
  10014. // remainder of this section).
  10015. // https://tools.ietf.org/html/rfc3261#section-8.2
  10016. // 8.2.1 Method Inspection
  10017. // Once a request is authenticated (or authentication is skipped), the
  10018. // UAS MUST inspect the method of the request. If the UAS recognizes
  10019. // but does not support the method of a request, it MUST generate a 405
  10020. // (Method Not Allowed) response. Procedures for generating responses
  10021. // are described in Section 8.2.6. The UAS MUST also add an Allow
  10022. // header field to the 405 (Method Not Allowed) response. The Allow
  10023. // header field MUST list the set of methods supported by the UAS
  10024. // generating the message.
  10025. // https://tools.ietf.org/html/rfc3261#section-8.2.1
  10026. if (allowed_methods_1.AllowedMethods.indexOf(message.method) === -1) {
  10027. var allowHeader = "Allow: " + allowed_methods_1.AllowedMethods.toString();
  10028. this.replyStateless(message, {
  10029. statusCode: 405,
  10030. extraHeaders: [allowHeader]
  10031. });
  10032. return;
  10033. }
  10034. // 8.2.2 Header Inspection
  10035. // https://tools.ietf.org/html/rfc3261#section-8.2.2
  10036. if (!message.ruri) { // FIXME: A request message should always have an ruri
  10037. throw new Error("Request-URI undefined.");
  10038. }
  10039. // 8.2.2.1 To and Request-URI
  10040. // If the Request-URI uses a scheme not supported by the UAS, it SHOULD
  10041. // reject the request with a 416 (Unsupported URI Scheme) response.
  10042. // https://tools.ietf.org/html/rfc3261#section-8.2.2.1
  10043. if (message.ruri.scheme !== "sip") {
  10044. this.replyStateless(message, { statusCode: 416 });
  10045. return;
  10046. }
  10047. // 8.2.2.1 To and Request-URI
  10048. // If the Request-URI does not identify an address that the
  10049. // UAS is willing to accept requests for, it SHOULD reject
  10050. // the request with a 404 (Not Found) response.
  10051. // https://tools.ietf.org/html/rfc3261#section-8.2.2.1
  10052. var ruri = message.ruri;
  10053. var ruriMatches = function (uri) {
  10054. return !!uri && uri.user === ruri.user;
  10055. };
  10056. if (!ruriMatches(this.configuration.aor) &&
  10057. !(ruriMatches(this.configuration.contact.uri) ||
  10058. ruriMatches(this.configuration.contact.pubGruu) ||
  10059. ruriMatches(this.configuration.contact.tempGruu))) {
  10060. this.logger.warn("Request-URI does not point to us.");
  10061. if (message.method !== messages_1.C.ACK) {
  10062. this.replyStateless(message, { statusCode: 404 });
  10063. }
  10064. return;
  10065. }
  10066. // 8.2.2.1 To and Request-URI
  10067. // Other potential sources of received Request-URIs include
  10068. // the Contact header fields of requests and responses sent by the UA
  10069. // that establish or refresh dialogs.
  10070. // https://tools.ietf.org/html/rfc3261#section-8.2.2.1
  10071. if (message.method === messages_1.C.INVITE) {
  10072. if (!message.hasHeader("Contact")) {
  10073. this.replyStateless(message, {
  10074. statusCode: 400,
  10075. reasonPhrase: "Missing Contact Header"
  10076. });
  10077. return;
  10078. }
  10079. }
  10080. // 8.2.2.2 Merged Requests
  10081. // If the request has no tag in the To header field, the UAS core MUST
  10082. // check the request against ongoing transactions. If the From tag,
  10083. // Call-ID, and CSeq exactly match those associated with an ongoing
  10084. // transaction, but the request does not match that transaction (based
  10085. // on the matching rules in Section 17.2.3), the UAS core SHOULD
  10086. // generate a 482 (Loop Detected) response and pass it to the server
  10087. // transaction.
  10088. //
  10089. // The same request has arrived at the UAS more than once, following
  10090. // different paths, most likely due to forking. The UAS processes
  10091. // the first such request received and responds with a 482 (Loop
  10092. // Detected) to the rest of them.
  10093. // https://tools.ietf.org/html/rfc3261#section-8.2.2.2
  10094. if (!message.toTag) {
  10095. var transactionId = message.viaBranch;
  10096. if (!this.userAgentServers.has(transactionId)) {
  10097. var mergedRequest = Array.from(this.userAgentServers.values())
  10098. .some(function (uas) {
  10099. return uas.transaction.request.fromTag === message.fromTag &&
  10100. uas.transaction.request.callId === message.callId &&
  10101. uas.transaction.request.cseq === message.cseq;
  10102. });
  10103. if (mergedRequest) {
  10104. this.replyStateless(message, { statusCode: 482 });
  10105. return;
  10106. }
  10107. }
  10108. }
  10109. // 8.2.2.3 Require
  10110. // https://tools.ietf.org/html/rfc3261#section-8.2.2.3
  10111. // TODO
  10112. // 8.2.3 Content Processing
  10113. // https://tools.ietf.org/html/rfc3261#section-8.2.3
  10114. // TODO
  10115. // 8.2.4 Applying Extensions
  10116. // https://tools.ietf.org/html/rfc3261#section-8.2.4
  10117. // TODO
  10118. // 8.2.5 Processing the Request
  10119. // Assuming all of the checks in the previous subsections are passed,
  10120. // the UAS processing becomes method-specific.
  10121. // https://tools.ietf.org/html/rfc3261#section-8.2.5
  10122. // The UAS will receive the request from the transaction layer. If the
  10123. // request has a tag in the To header field, the UAS core computes the
  10124. // dialog identifier corresponding to the request and compares it with
  10125. // existing dialogs. If there is a match, this is a mid-dialog request.
  10126. // In that case, the UAS first applies the same processing rules for
  10127. // requests outside of a dialog, discussed in Section 8.2.
  10128. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  10129. if (message.toTag) {
  10130. this.receiveInsideDialogRequest(message);
  10131. }
  10132. else {
  10133. this.receiveOutsideDialogRequest(message);
  10134. }
  10135. return;
  10136. };
  10137. /**
  10138. * Once a dialog has been established between two UAs, either of them
  10139. * MAY initiate new transactions as needed within the dialog. The UA
  10140. * sending the request will take the UAC role for the transaction. The
  10141. * UA receiving the request will take the UAS role. Note that these may
  10142. * be different roles than the UAs held during the transaction that
  10143. * established the dialog.
  10144. * https://tools.ietf.org/html/rfc3261#section-12.2
  10145. * @param message - Incoming request message.
  10146. */
  10147. UserAgentCore.prototype.receiveInsideDialogRequest = function (message) {
  10148. // NOTIFY requests are matched to such SUBSCRIBE requests if they
  10149. // contain the same "Call-ID", a "To" header field "tag" parameter that
  10150. // matches the "From" header field "tag" parameter of the SUBSCRIBE
  10151. // request, and the same "Event" header field. Rules for comparisons of
  10152. // the "Event" header fields are described in Section 8.2.1.
  10153. // https://tools.ietf.org/html/rfc6665#section-4.4.1
  10154. if (message.method === messages_1.C.NOTIFY) {
  10155. var event_1 = message.parseHeader("Event");
  10156. if (!event_1 || !event_1.event) {
  10157. this.replyStateless(message, { statusCode: 489 });
  10158. return;
  10159. }
  10160. // FIXME: Subscriber id should also matching on event id.
  10161. var subscriberId = message.callId + message.toTag + event_1.event;
  10162. var subscriber = this.subscribers.get(subscriberId);
  10163. if (subscriber) {
  10164. var uas = new user_agents_1.NotifyUserAgentServer(this, message);
  10165. subscriber.onNotify(uas);
  10166. return;
  10167. }
  10168. }
  10169. // Requests sent within a dialog, as any other requests, are atomic. If
  10170. // a particular request is accepted by the UAS, all the state changes
  10171. // associated with it are performed. If the request is rejected, none
  10172. // of the state changes are performed.
  10173. //
  10174. // Note that some requests, such as INVITEs, affect several pieces of
  10175. // state.
  10176. //
  10177. // The UAS will receive the request from the transaction layer. If the
  10178. // request has a tag in the To header field, the UAS core computes the
  10179. // dialog identifier corresponding to the request and compares it with
  10180. // existing dialogs. If there is a match, this is a mid-dialog request.
  10181. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  10182. var dialogId = message.callId + message.toTag + message.fromTag;
  10183. var dialog = this.dialogs.get(dialogId);
  10184. if (dialog) {
  10185. // [Sip-implementors] Reg. SIP reinvite, UPDATE and OPTIONS
  10186. // You got the question right.
  10187. //
  10188. // And you got the right answer too. :-)
  10189. //
  10190. // Thanks,
  10191. // Paul
  10192. //
  10193. // Robert Sparks wrote:
  10194. // > So I've lost track of the question during the musing.
  10195. // >
  10196. // > I _think_ the fundamental question being asked is this:
  10197. // >
  10198. // > Is an endpoint required to reject (with a 481) an OPTIONS request that
  10199. // > arrives with at to-tag but does not match any existing dialog state.
  10200. // > (Assuming some earlier requirement hasn't forced another error code). Or
  10201. // > is it OK if it just sends
  10202. // > a 200 OK anyhow.
  10203. // >
  10204. // > My take on the collection of specs is that its _not_ ok for it to send
  10205. // > the 200 OK anyhow and that it is required to send
  10206. // > the 481. I base this primarily on these sentences from 11.2 in 3261:
  10207. // >
  10208. // > The response to an OPTIONS is constructed using the standard rules
  10209. // > for a SIP response as discussed in Section 8.2.6. The response code
  10210. // > chosen MUST be the same that would have been chosen had the request
  10211. // > been an INVITE.
  10212. // >
  10213. // > Did I miss the point of the question?
  10214. // >
  10215. // > On May 15, 2008, at 12:48 PM, Paul Kyzivat wrote:
  10216. // >
  10217. // >> [Including Robert in hopes of getting his insight on this.]
  10218. // https://lists.cs.columbia.edu/pipermail/sip-implementors/2008-May/019178.html
  10219. //
  10220. // Requests that do not change in any way the state of a dialog may be
  10221. // received within a dialog (for example, an OPTIONS request). They are
  10222. // processed as if they had been received outside the dialog.
  10223. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  10224. if (message.method === messages_1.C.OPTIONS) {
  10225. var allowHeader = "Allow: " + allowed_methods_1.AllowedMethods.toString();
  10226. var acceptHeader = "Accept: " + acceptedBodyTypes.toString();
  10227. this.replyStateless(message, {
  10228. statusCode: 200,
  10229. extraHeaders: [allowHeader, acceptHeader]
  10230. });
  10231. return;
  10232. }
  10233. // Pass the incoming request to the dialog for further handling.
  10234. dialog.receiveRequest(message);
  10235. return;
  10236. }
  10237. // The most important behaviors of a stateless UAS are the following:
  10238. // ...
  10239. // o A stateless UAS MUST ignore ACK requests.
  10240. // ...
  10241. // https://tools.ietf.org/html/rfc3261#section-8.2.7
  10242. if (message.method === messages_1.C.ACK) {
  10243. // If a final response to an INVITE was sent statelessly,
  10244. // the corresponding ACK:
  10245. // - will not match an existing transaction
  10246. // - may have tag in the To header field
  10247. // - not not match any existing dialogs
  10248. // Absorb unmatched ACKs.
  10249. return;
  10250. }
  10251. // If the request has a tag in the To header field, but the dialog
  10252. // identifier does not match any existing dialogs, the UAS may have
  10253. // crashed and restarted, or it may have received a request for a
  10254. // different (possibly failed) UAS (the UASs can construct the To tags
  10255. // so that a UAS can identify that the tag was for a UAS for which it is
  10256. // providing recovery). Another possibility is that the incoming
  10257. // request has been simply mis-routed. Based on the To tag, the UAS MAY
  10258. // either accept or reject the request. Accepting the request for
  10259. // acceptable To tags provides robustness, so that dialogs can persist
  10260. // even through crashes. UAs wishing to support this capability must
  10261. // take into consideration some issues such as choosing monotonically
  10262. // increasing CSeq sequence numbers even across reboots, reconstructing
  10263. // the route set, and accepting out-of-range RTP timestamps and sequence
  10264. // numbers.
  10265. //
  10266. // If the UAS wishes to reject the request because it does not wish to
  10267. // recreate the dialog, it MUST respond to the request with a 481
  10268. // (Call/Transaction Does Not Exist) status code and pass that to the
  10269. // server transaction.
  10270. // https://tools.ietf.org/html/rfc3261#section-12.2.2
  10271. this.replyStateless(message, { statusCode: 481 });
  10272. return;
  10273. };
  10274. /**
  10275. * Assuming all of the checks in the previous subsections are passed,
  10276. * the UAS processing becomes method-specific.
  10277. * https://tools.ietf.org/html/rfc3261#section-8.2.5
  10278. * @param message - Incoming request message.
  10279. */
  10280. UserAgentCore.prototype.receiveOutsideDialogRequest = function (message) {
  10281. switch (message.method) {
  10282. case messages_1.C.ACK:
  10283. // Absorb stray out of dialog ACKs
  10284. break;
  10285. case messages_1.C.BYE:
  10286. // If the BYE does not match an existing dialog, the UAS core SHOULD
  10287. // generate a 481 (Call/Transaction Does Not Exist) response and pass
  10288. // that to the server transaction. This rule means that a BYE sent
  10289. // without tags by a UAC will be rejected.
  10290. // https://tools.ietf.org/html/rfc3261#section-15.1.2
  10291. this.replyStateless(message, { statusCode: 481 });
  10292. break;
  10293. case messages_1.C.CANCEL:
  10294. throw new Error("Unexpected out of dialog request method " + message.method + ".");
  10295. break;
  10296. case messages_1.C.INFO:
  10297. // Use of the INFO method does not constitute a separate dialog usage.
  10298. // INFO messages are always part of, and share the fate of, an invite
  10299. // dialog usage [RFC5057]. INFO messages cannot be sent as part of
  10300. // other dialog usages, or outside an existing dialog.
  10301. // https://tools.ietf.org/html/rfc6086#section-1
  10302. this.replyStateless(message, { statusCode: 405 }); // Should never happen
  10303. break;
  10304. case messages_1.C.INVITE:
  10305. // https://tools.ietf.org/html/rfc3261#section-13.3.1
  10306. {
  10307. var uas = new user_agents_1.InviteUserAgentServer(this, message);
  10308. this.delegate.onInvite ?
  10309. this.delegate.onInvite(uas) :
  10310. uas.reject();
  10311. }
  10312. break;
  10313. case messages_1.C.MESSAGE:
  10314. // MESSAGE requests are discouraged inside a dialog. Implementations
  10315. // are restricted from creating a usage for the purpose of carrying a
  10316. // sequence of MESSAGE requests (though some implementations use it that
  10317. // way, against the standard recommendation).
  10318. // https://tools.ietf.org/html/rfc5057#section-5.3
  10319. {
  10320. var uas = new user_agents_1.MessageUserAgentServer(this, message);
  10321. this.delegate.onMessage ?
  10322. this.delegate.onMessage(uas) :
  10323. uas.accept();
  10324. }
  10325. break;
  10326. case messages_1.C.NOTIFY:
  10327. // Obsoleted by: RFC 6665
  10328. // If any non-SUBSCRIBE mechanisms are defined to create subscriptions,
  10329. // it is the responsibility of the parties defining those mechanisms to
  10330. // ensure that correlation of a NOTIFY message to the corresponding
  10331. // subscription is possible. Designers of such mechanisms are also
  10332. // warned to make a distinction between sending a NOTIFY message to a
  10333. // subscriber who is aware of the subscription, and sending a NOTIFY
  10334. // message to an unsuspecting node. The latter behavior is invalid, and
  10335. // MUST receive a "481 Subscription does not exist" response (unless
  10336. // some other 400- or 500-class error code is more applicable), as
  10337. // described in section 3.2.4. In other words, knowledge of a
  10338. // subscription must exist in both the subscriber and the notifier to be
  10339. // valid, even if installed via a non-SUBSCRIBE mechanism.
  10340. // https://tools.ietf.org/html/rfc3265#section-3.2
  10341. //
  10342. // NOTIFY requests are sent to inform subscribers of changes in state to
  10343. // which the subscriber has a subscription. Subscriptions are created
  10344. // using the SUBSCRIBE method. In legacy implementations, it is
  10345. // possible that other means of subscription creation have been used.
  10346. // However, this specification does not allow the creation of
  10347. // subscriptions except through SUBSCRIBE requests and (for backwards-
  10348. // compatibility) REFER requests [RFC3515].
  10349. // https://tools.ietf.org/html/rfc6665#section-3.2
  10350. {
  10351. var uas = new user_agents_1.NotifyUserAgentServer(this, message);
  10352. this.delegate.onNotify ?
  10353. this.delegate.onNotify(uas) :
  10354. uas.reject({ statusCode: 405 });
  10355. }
  10356. break;
  10357. case messages_1.C.OPTIONS:
  10358. // https://tools.ietf.org/html/rfc3261#section-11.2
  10359. {
  10360. var allowHeader = "Allow: " + allowed_methods_1.AllowedMethods.toString();
  10361. var acceptHeader = "Accept: " + acceptedBodyTypes.toString();
  10362. this.replyStateless(message, {
  10363. statusCode: 200,
  10364. extraHeaders: [allowHeader, acceptHeader]
  10365. });
  10366. }
  10367. break;
  10368. case messages_1.C.REFER:
  10369. // https://tools.ietf.org/html/rfc3515#section-2.4.2
  10370. {
  10371. var uas = new user_agents_1.ReferUserAgentServer(this, message);
  10372. this.delegate.onRefer ?
  10373. this.delegate.onRefer(uas) :
  10374. uas.reject({ statusCode: 405 });
  10375. }
  10376. break;
  10377. case messages_1.C.REGISTER:
  10378. // https://tools.ietf.org/html/rfc3261#section-10.3
  10379. {
  10380. var uas = new user_agents_1.RegisterUserAgentServer(this, message);
  10381. this.delegate.onRegister ?
  10382. this.delegate.onRegister(uas) :
  10383. uas.reject({ statusCode: 405 });
  10384. }
  10385. break;
  10386. case messages_1.C.SUBSCRIBE:
  10387. // https://tools.ietf.org/html/rfc6665#section-4.2
  10388. {
  10389. var uas = new user_agents_1.SubscribeUserAgentServer(this, message);
  10390. this.delegate.onSubscribe ?
  10391. this.delegate.onSubscribe(uas) :
  10392. uas.reject({ statusCode: 480 });
  10393. }
  10394. break;
  10395. default:
  10396. throw new Error("Unexpected out of dialog request method " + message.method + ".");
  10397. }
  10398. return;
  10399. };
  10400. /**
  10401. * Responses are first processed by the transport layer and then passed
  10402. * up to the transaction layer. The transaction layer performs its
  10403. * processing and then passes the response up to the TU. The majority
  10404. * of response processing in the TU is method specific. However, there
  10405. * are some general behaviors independent of the method.
  10406. * https://tools.ietf.org/html/rfc3261#section-8.1.3
  10407. * @param message - Incoming response message from transport layer.
  10408. */
  10409. UserAgentCore.prototype.receiveResponseFromTransport = function (message) {
  10410. // 8.1.3.1 Transaction Layer Errors
  10411. // https://tools.ietf.org/html/rfc3261#section-8.1.3.1
  10412. // Handled by transaction layer callbacks.
  10413. // 8.1.3.2 Unrecognized Responses
  10414. // https://tools.ietf.org/html/rfc3261#section-8.1.3.1
  10415. // TODO
  10416. // 8.1.3.3 Vias
  10417. // https://tools.ietf.org/html/rfc3261#section-8.1.3.3
  10418. if (message.getHeaders("via").length > 1) {
  10419. this.logger.warn("More than one Via header field present in the response, dropping");
  10420. return;
  10421. }
  10422. // 8.1.3.4 Processing 3xx Responses
  10423. // https://tools.ietf.org/html/rfc3261#section-8.1.3.4
  10424. // TODO
  10425. // 8.1.3.5 Processing 4xx Responses
  10426. // https://tools.ietf.org/html/rfc3261#section-8.1.3.5
  10427. // TODO
  10428. // When the transport layer in the client receives a response, it has to
  10429. // determine which client transaction will handle the response, so that
  10430. // the processing of Sections 17.1.1 and 17.1.2 can take place. The
  10431. // branch parameter in the top Via header field is used for this
  10432. // purpose. A response matches a client transaction under two
  10433. // conditions:
  10434. //
  10435. // 1. If the response has the same value of the branch parameter in
  10436. // the top Via header field as the branch parameter in the top
  10437. // Via header field of the request that created the transaction.
  10438. //
  10439. // 2. If the method parameter in the CSeq header field matches the
  10440. // method of the request that created the transaction. The
  10441. // method is needed since a CANCEL request constitutes a
  10442. // different transaction, but shares the same value of the branch
  10443. // parameter.
  10444. // https://tools.ietf.org/html/rfc3261#section-17.1.3
  10445. var userAgentClientId = message.viaBranch + message.method;
  10446. var userAgentClient = this.userAgentClients.get(userAgentClientId);
  10447. // The client transport uses the matching procedures of Section
  10448. // 17.1.3 to attempt to match the response to an existing
  10449. // transaction. If there is a match, the response MUST be passed to
  10450. // that transaction. Otherwise, any element other than a stateless
  10451. // proxy MUST silently discard the response.
  10452. // https://tools.ietf.org/html/rfc6026#section-8.9
  10453. if (userAgentClient) {
  10454. userAgentClient.transaction.receiveResponse(message);
  10455. }
  10456. else {
  10457. this.logger.warn("Discarding unmatched " + message.statusCode + " response to " + message.method + " " + userAgentClientId + ".");
  10458. }
  10459. };
  10460. return UserAgentCore;
  10461. }());
  10462. exports.UserAgentCore = UserAgentCore;
  10463. /***/ }),
  10464. /* 66 */
  10465. /***/ (function(module, exports, __webpack_require__) {
  10466. "use strict";
  10467. Object.defineProperty(exports, "__esModule", { value: true });
  10468. var tslib_1 = __webpack_require__(1);
  10469. tslib_1.__exportStar(__webpack_require__(41), exports);
  10470. tslib_1.__exportStar(__webpack_require__(43), exports);
  10471. tslib_1.__exportStar(__webpack_require__(67), exports);
  10472. tslib_1.__exportStar(__webpack_require__(45), exports);
  10473. tslib_1.__exportStar(__webpack_require__(46), exports);
  10474. tslib_1.__exportStar(__webpack_require__(68), exports);
  10475. tslib_1.__exportStar(__webpack_require__(69), exports);
  10476. tslib_1.__exportStar(__webpack_require__(70), exports);
  10477. tslib_1.__exportStar(__webpack_require__(71), exports);
  10478. tslib_1.__exportStar(__webpack_require__(47), exports);
  10479. tslib_1.__exportStar(__webpack_require__(48), exports);
  10480. tslib_1.__exportStar(__webpack_require__(72), exports);
  10481. tslib_1.__exportStar(__webpack_require__(49), exports);
  10482. tslib_1.__exportStar(__webpack_require__(50), exports);
  10483. tslib_1.__exportStar(__webpack_require__(51), exports);
  10484. tslib_1.__exportStar(__webpack_require__(52), exports);
  10485. tslib_1.__exportStar(__webpack_require__(59), exports);
  10486. tslib_1.__exportStar(__webpack_require__(73), exports);
  10487. tslib_1.__exportStar(__webpack_require__(53), exports);
  10488. tslib_1.__exportStar(__webpack_require__(54), exports);
  10489. tslib_1.__exportStar(__webpack_require__(74), exports);
  10490. tslib_1.__exportStar(__webpack_require__(75), exports);
  10491. tslib_1.__exportStar(__webpack_require__(76), exports);
  10492. tslib_1.__exportStar(__webpack_require__(77), exports);
  10493. tslib_1.__exportStar(__webpack_require__(42), exports);
  10494. tslib_1.__exportStar(__webpack_require__(44), exports);
  10495. /***/ }),
  10496. /* 67 */
  10497. /***/ (function(module, exports, __webpack_require__) {
  10498. "use strict";
  10499. Object.defineProperty(exports, "__esModule", { value: true });
  10500. var tslib_1 = __webpack_require__(1);
  10501. var transactions_1 = __webpack_require__(27);
  10502. var user_agent_client_1 = __webpack_require__(42);
  10503. /**
  10504. * CANCEL UAC.
  10505. * @public
  10506. */
  10507. var CancelUserAgentClient = /** @class */ (function (_super) {
  10508. tslib_1.__extends(CancelUserAgentClient, _super);
  10509. function CancelUserAgentClient(core, message, delegate) {
  10510. return _super.call(this, transactions_1.NonInviteClientTransaction, core, message, delegate) || this;
  10511. }
  10512. return CancelUserAgentClient;
  10513. }(user_agent_client_1.UserAgentClient));
  10514. exports.CancelUserAgentClient = CancelUserAgentClient;
  10515. /***/ }),
  10516. /* 68 */
  10517. /***/ (function(module, exports, __webpack_require__) {
  10518. "use strict";
  10519. Object.defineProperty(exports, "__esModule", { value: true });
  10520. var tslib_1 = __webpack_require__(1);
  10521. var dialogs_1 = __webpack_require__(3);
  10522. var session_1 = __webpack_require__(24);
  10523. var transactions_1 = __webpack_require__(27);
  10524. var user_agent_client_1 = __webpack_require__(42);
  10525. /**
  10526. * INVITE UAC.
  10527. * @remarks
  10528. * 13 Initiating a Session
  10529. * https://tools.ietf.org/html/rfc3261#section-13
  10530. * 13.1 Overview
  10531. * https://tools.ietf.org/html/rfc3261#section-13.1
  10532. * 13.2 UAC Processing
  10533. * https://tools.ietf.org/html/rfc3261#section-13.2
  10534. * @public
  10535. */
  10536. var InviteUserAgentClient = /** @class */ (function (_super) {
  10537. tslib_1.__extends(InviteUserAgentClient, _super);
  10538. function InviteUserAgentClient(core, message, delegate) {
  10539. var _this = _super.call(this, transactions_1.InviteClientTransaction, core, message, delegate) || this;
  10540. _this.confirmedDialogAcks = new Map();
  10541. _this.confirmedDialogs = new Map();
  10542. _this.earlyDialogs = new Map();
  10543. _this.delegate = delegate;
  10544. return _this;
  10545. }
  10546. InviteUserAgentClient.prototype.dispose = function () {
  10547. // The UAC core considers the INVITE transaction completed 64*T1 seconds
  10548. // after the reception of the first 2xx response. At this point all the
  10549. // early dialogs that have not transitioned to established dialogs are
  10550. // terminated. Once the INVITE transaction is considered completed by
  10551. // the UAC core, no more new 2xx responses are expected to arrive.
  10552. //
  10553. // If, after acknowledging any 2xx response to an INVITE, the UAC does
  10554. // not want to continue with that dialog, then the UAC MUST terminate
  10555. // the dialog by sending a BYE request as described in Section 15.
  10556. // https://tools.ietf.org/html/rfc3261#section-13.2.2.4
  10557. this.earlyDialogs.forEach(function (earlyDialog) { return earlyDialog.dispose(); });
  10558. this.earlyDialogs.clear();
  10559. _super.prototype.dispose.call(this);
  10560. };
  10561. /**
  10562. * Special case for transport error while sending ACK.
  10563. * @param error - Transport error
  10564. */
  10565. InviteUserAgentClient.prototype.onTransportError = function (error) {
  10566. if (this.transaction.state === transactions_1.TransactionState.Calling) {
  10567. return _super.prototype.onTransportError.call(this, error);
  10568. }
  10569. // If not in 'calling' state, the transport error occurred while sending an ACK.
  10570. this.logger.error(error.message);
  10571. this.logger.error("User agent client request transport error while sending ACK.");
  10572. };
  10573. /**
  10574. * Once the INVITE has been passed to the INVITE client transaction, the
  10575. * UAC waits for responses for the INVITE.
  10576. * https://tools.ietf.org/html/rfc3261#section-13.2.2
  10577. * @param incomingResponse - Incoming response to INVITE request.
  10578. */
  10579. InviteUserAgentClient.prototype.receiveResponse = function (message) {
  10580. var _this = this;
  10581. if (!this.authenticationGuard(message)) {
  10582. return;
  10583. }
  10584. var statusCode = message.statusCode ? message.statusCode.toString() : "";
  10585. if (!statusCode) {
  10586. throw new Error("Response status code undefined.");
  10587. }
  10588. switch (true) {
  10589. case /^100$/.test(statusCode):
  10590. if (this.delegate && this.delegate.onTrying) {
  10591. this.delegate.onTrying({ message: message });
  10592. }
  10593. return;
  10594. case /^1[0-9]{2}$/.test(statusCode):
  10595. // Zero, one or multiple provisional responses may arrive before one or
  10596. // more final responses are received. Provisional responses for an
  10597. // INVITE request can create "early dialogs". If a provisional response
  10598. // has a tag in the To field, and if the dialog ID of the response does
  10599. // not match an existing dialog, one is constructed using the procedures
  10600. // defined in Section 12.1.2.
  10601. //
  10602. // The early dialog will only be needed if the UAC needs to send a
  10603. // request to its peer within the dialog before the initial INVITE
  10604. // transaction completes. Header fields present in a provisional
  10605. // response are applicable as long as the dialog is in the early state
  10606. // (for example, an Allow header field in a provisional response
  10607. // contains the methods that can be used in the dialog while this is in
  10608. // the early state).
  10609. // https://tools.ietf.org/html/rfc3261#section-13.2.2.1
  10610. {
  10611. // Provisional without to tag, no dialog to create.
  10612. if (!message.toTag) {
  10613. this.logger.warn("Non-100 1xx INVITE response received without a to tag, dropping.");
  10614. return;
  10615. }
  10616. // Compute dialog state.
  10617. var dialogState = dialogs_1.Dialog.initialDialogStateForUserAgentClient(this.message, message);
  10618. // Have existing early dialog or create a new one.
  10619. var earlyDialog = this.earlyDialogs.get(dialogState.id);
  10620. if (!earlyDialog) {
  10621. var transaction = this.transaction;
  10622. if (!(transaction instanceof transactions_1.InviteClientTransaction)) {
  10623. throw new Error("Transaction not instance of InviteClientTransaction.");
  10624. }
  10625. earlyDialog = new dialogs_1.SessionDialog(transaction, this.core, dialogState);
  10626. this.earlyDialogs.set(earlyDialog.id, earlyDialog);
  10627. }
  10628. // Guard against out of order reliable provisional responses.
  10629. // Note that this is where the rseq tracking is done.
  10630. if (!earlyDialog.reliableSequenceGuard(message)) {
  10631. this.logger.warn("1xx INVITE reliable response received out of order, dropping.");
  10632. return;
  10633. }
  10634. // If the initial offer is in an INVITE, the answer MUST be in a
  10635. // reliable non-failure message from UAS back to UAC which is
  10636. // correlated to that INVITE. For this specification, that is
  10637. // only the final 2xx response to that INVITE. That same exact
  10638. // answer MAY also be placed in any provisional responses sent
  10639. // prior to the answer. The UAC MUST treat the first session
  10640. // description it receives as the answer, and MUST ignore any
  10641. // session descriptions in subsequent responses to the initial
  10642. // INVITE.
  10643. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  10644. if (earlyDialog.signalingState === session_1.SignalingState.Initial ||
  10645. earlyDialog.signalingState === session_1.SignalingState.HaveLocalOffer) {
  10646. earlyDialog.signalingStateTransition(message);
  10647. }
  10648. // Pass response to delegate.
  10649. var session_2 = earlyDialog;
  10650. if (this.delegate && this.delegate.onProgress) {
  10651. this.delegate.onProgress({
  10652. message: message,
  10653. session: session_2,
  10654. prack: function (options) {
  10655. var outgoingPrackRequest = session_2.prack(undefined, options);
  10656. return outgoingPrackRequest;
  10657. }
  10658. });
  10659. }
  10660. }
  10661. return;
  10662. case /^2[0-9]{2}$/.test(statusCode):
  10663. // Multiple 2xx responses may arrive at the UAC for a single INVITE
  10664. // request due to a forking proxy. Each response is distinguished by
  10665. // the tag parameter in the To header field, and each represents a
  10666. // distinct dialog, with a distinct dialog identifier.
  10667. //
  10668. // If the dialog identifier in the 2xx response matches the dialog
  10669. // identifier of an existing dialog, the dialog MUST be transitioned to
  10670. // the "confirmed" state, and the route set for the dialog MUST be
  10671. // recomputed based on the 2xx response using the procedures of Section
  10672. // 12.2.1.2. Otherwise, a new dialog in the "confirmed" state MUST be
  10673. // constructed using the procedures of Section 12.1.2.
  10674. // https://tools.ietf.org/html/rfc3261#section-13.2.2.4
  10675. {
  10676. // Compute dialog state.
  10677. var dialogState = dialogs_1.Dialog.initialDialogStateForUserAgentClient(this.message, message);
  10678. // NOTE: Currently our transaction layer is caching the 2xx ACKs and
  10679. // handling retransmissions of the ACK which is an approach which is
  10680. // not to spec. In any event, this block is intended to provide a to
  10681. // spec implementation of ACK retransmissions, but it should not be
  10682. // hit currently.
  10683. var dialog = this.confirmedDialogs.get(dialogState.id);
  10684. if (dialog) {
  10685. // Once the ACK has been constructed, the procedures of [4] are used to
  10686. // determine the destination address, port and transport. However, the
  10687. // request is passed to the transport layer directly for transmission,
  10688. // rather than a client transaction. This is because the UAC core
  10689. // handles retransmissions of the ACK, not the transaction layer. The
  10690. // ACK MUST be passed to the client transport every time a
  10691. // retransmission of the 2xx final response that triggered the ACK
  10692. // arrives.
  10693. // https://tools.ietf.org/html/rfc3261#section-13.2.2.4
  10694. var outgoingAckRequest = this.confirmedDialogAcks.get(dialogState.id);
  10695. if (outgoingAckRequest) {
  10696. var transaction = this.transaction;
  10697. if (!(transaction instanceof transactions_1.InviteClientTransaction)) {
  10698. throw new Error("Client transaction not instance of InviteClientTransaction.");
  10699. }
  10700. transaction.ackResponse(outgoingAckRequest.message);
  10701. }
  10702. else {
  10703. // If still waiting for an ACK, drop the retransmission of the 2xx final response.
  10704. }
  10705. return;
  10706. }
  10707. // If the dialog identifier in the 2xx response matches the dialog
  10708. // identifier of an existing dialog, the dialog MUST be transitioned to
  10709. // the "confirmed" state, and the route set for the dialog MUST be
  10710. // recomputed based on the 2xx response using the procedures of Section
  10711. // 12.2.1.2. Otherwise, a new dialog in the "confirmed" state MUST be
  10712. // constructed using the procedures of Section 12.1.2.
  10713. // https://tools.ietf.org/html/rfc3261#section-13.2.2.4
  10714. dialog = this.earlyDialogs.get(dialogState.id);
  10715. if (dialog) {
  10716. dialog.confirm();
  10717. dialog.recomputeRouteSet(message);
  10718. this.earlyDialogs.delete(dialog.id);
  10719. this.confirmedDialogs.set(dialog.id, dialog);
  10720. }
  10721. else {
  10722. var transaction = this.transaction;
  10723. if (!(transaction instanceof transactions_1.InviteClientTransaction)) {
  10724. throw new Error("Transaction not instance of InviteClientTransaction.");
  10725. }
  10726. dialog = new dialogs_1.SessionDialog(transaction, this.core, dialogState);
  10727. this.confirmedDialogs.set(dialog.id, dialog);
  10728. }
  10729. // If the initial offer is in an INVITE, the answer MUST be in a
  10730. // reliable non-failure message from UAS back to UAC which is
  10731. // correlated to that INVITE. For this specification, that is
  10732. // only the final 2xx response to that INVITE. That same exact
  10733. // answer MAY also be placed in any provisional responses sent
  10734. // prior to the answer. The UAC MUST treat the first session
  10735. // description it receives as the answer, and MUST ignore any
  10736. // session descriptions in subsequent responses to the initial
  10737. // INVITE.
  10738. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  10739. if (dialog.signalingState === session_1.SignalingState.Initial ||
  10740. dialog.signalingState === session_1.SignalingState.HaveLocalOffer) {
  10741. dialog.signalingStateTransition(message);
  10742. }
  10743. // Session Initiated! :)
  10744. var session_3 = dialog;
  10745. // The UAC core MUST generate an ACK request for each 2xx received from
  10746. // the transaction layer. The header fields of the ACK are constructed
  10747. // in the same way as for any request sent within a dialog (see Section
  10748. // 12) with the exception of the CSeq and the header fields related to
  10749. // authentication. The sequence number of the CSeq header field MUST be
  10750. // the same as the INVITE being acknowledged, but the CSeq method MUST
  10751. // be ACK. The ACK MUST contain the same credentials as the INVITE. If
  10752. // the 2xx contains an offer (based on the rules above), the ACK MUST
  10753. // carry an answer in its body. If the offer in the 2xx response is not
  10754. // acceptable, the UAC core MUST generate a valid answer in the ACK and
  10755. // then send a BYE immediately.
  10756. // https://tools.ietf.org/html/rfc3261#section-13.2.2.4
  10757. if (this.delegate && this.delegate.onAccept) {
  10758. this.delegate.onAccept({
  10759. message: message,
  10760. session: session_3,
  10761. ack: function (options) {
  10762. var outgoingAckRequest = session_3.ack(options);
  10763. _this.confirmedDialogAcks.set(session_3.id, outgoingAckRequest);
  10764. return outgoingAckRequest;
  10765. }
  10766. });
  10767. }
  10768. else {
  10769. var outgoingAckRequest = session_3.ack();
  10770. this.confirmedDialogAcks.set(session_3.id, outgoingAckRequest);
  10771. }
  10772. }
  10773. return;
  10774. case /^3[0-9]{2}$/.test(statusCode):
  10775. // 12.3 Termination of a Dialog
  10776. //
  10777. // Independent of the method, if a request outside of a dialog generates
  10778. // a non-2xx final response, any early dialogs created through
  10779. // provisional responses to that request are terminated. The mechanism
  10780. // for terminating confirmed dialogs is method specific. In this
  10781. // specification, the BYE method terminates a session and the dialog
  10782. // associated with it. See Section 15 for details.
  10783. // https://tools.ietf.org/html/rfc3261#section-12.3
  10784. // All early dialogs are considered terminated upon reception of the
  10785. // non-2xx final response.
  10786. //
  10787. // After having received the non-2xx final response the UAC core
  10788. // considers the INVITE transaction completed. The INVITE client
  10789. // transaction handles the generation of ACKs for the response (see
  10790. // Section 17).
  10791. // https://tools.ietf.org/html/rfc3261#section-13.2.2.3
  10792. this.earlyDialogs.forEach(function (earlyDialog) { return earlyDialog.dispose(); });
  10793. this.earlyDialogs.clear();
  10794. // A 3xx response may contain one or more Contact header field values
  10795. // providing new addresses where the callee might be reachable.
  10796. // Depending on the status code of the 3xx response (see Section 21.3),
  10797. // the UAC MAY choose to try those new addresses.
  10798. // https://tools.ietf.org/html/rfc3261#section-13.2.2.2
  10799. if (this.delegate && this.delegate.onRedirect) {
  10800. this.delegate.onRedirect({ message: message });
  10801. }
  10802. return;
  10803. case /^[4-6][0-9]{2}$/.test(statusCode):
  10804. // 12.3 Termination of a Dialog
  10805. //
  10806. // Independent of the method, if a request outside of a dialog generates
  10807. // a non-2xx final response, any early dialogs created through
  10808. // provisional responses to that request are terminated. The mechanism
  10809. // for terminating confirmed dialogs is method specific. In this
  10810. // specification, the BYE method terminates a session and the dialog
  10811. // associated with it. See Section 15 for details.
  10812. // https://tools.ietf.org/html/rfc3261#section-12.3
  10813. // All early dialogs are considered terminated upon reception of the
  10814. // non-2xx final response.
  10815. //
  10816. // After having received the non-2xx final response the UAC core
  10817. // considers the INVITE transaction completed. The INVITE client
  10818. // transaction handles the generation of ACKs for the response (see
  10819. // Section 17).
  10820. // https://tools.ietf.org/html/rfc3261#section-13.2.2.3
  10821. this.earlyDialogs.forEach(function (earlyDialog) { return earlyDialog.dispose(); });
  10822. this.earlyDialogs.clear();
  10823. // A single non-2xx final response may be received for the INVITE. 4xx,
  10824. // 5xx and 6xx responses may contain a Contact header field value
  10825. // indicating the location where additional information about the error
  10826. // can be found. Subsequent final responses (which would only arrive
  10827. // under error conditions) MUST be ignored.
  10828. // https://tools.ietf.org/html/rfc3261#section-13.2.2.3
  10829. if (this.delegate && this.delegate.onReject) {
  10830. this.delegate.onReject({ message: message });
  10831. }
  10832. return;
  10833. default:
  10834. throw new Error("Invalid status code " + statusCode);
  10835. }
  10836. throw new Error("Executing what should be an unreachable code path receiving " + statusCode + " response.");
  10837. };
  10838. return InviteUserAgentClient;
  10839. }(user_agent_client_1.UserAgentClient));
  10840. exports.InviteUserAgentClient = InviteUserAgentClient;
  10841. /***/ }),
  10842. /* 69 */
  10843. /***/ (function(module, exports, __webpack_require__) {
  10844. "use strict";
  10845. Object.defineProperty(exports, "__esModule", { value: true });
  10846. var tslib_1 = __webpack_require__(1);
  10847. var dialogs_1 = __webpack_require__(3);
  10848. var exceptions_1 = __webpack_require__(31);
  10849. var session_1 = __webpack_require__(24);
  10850. var transactions_1 = __webpack_require__(27);
  10851. var allowed_methods_1 = __webpack_require__(58);
  10852. var user_agent_server_1 = __webpack_require__(44);
  10853. /**
  10854. * INVITE UAS.
  10855. * @remarks
  10856. * 13 Initiating a Session
  10857. * https://tools.ietf.org/html/rfc3261#section-13
  10858. * 13.1 Overview
  10859. * https://tools.ietf.org/html/rfc3261#section-13.1
  10860. * 13.3 UAS Processing
  10861. * https://tools.ietf.org/html/rfc3261#section-13.3
  10862. * @public
  10863. */
  10864. var InviteUserAgentServer = /** @class */ (function (_super) {
  10865. tslib_1.__extends(InviteUserAgentServer, _super);
  10866. function InviteUserAgentServer(core, message, delegate) {
  10867. var _this = _super.call(this, transactions_1.InviteServerTransaction, core, message, delegate) || this;
  10868. _this.core = core;
  10869. return _this;
  10870. }
  10871. InviteUserAgentServer.prototype.dispose = function () {
  10872. if (this.earlyDialog) {
  10873. this.earlyDialog.dispose();
  10874. }
  10875. _super.prototype.dispose.call(this);
  10876. };
  10877. /**
  10878. * 13.3.1.4 The INVITE is Accepted
  10879. * The UAS core generates a 2xx response. This response establishes a
  10880. * dialog, and therefore follows the procedures of Section 12.1.1 in
  10881. * addition to those of Section 8.2.6.
  10882. * https://tools.ietf.org/html/rfc3261#section-13.3.1.4
  10883. * @param options - Accept options bucket.
  10884. */
  10885. InviteUserAgentServer.prototype.accept = function (options) {
  10886. if (options === void 0) { options = { statusCode: 200 }; }
  10887. if (!this.acceptable) {
  10888. throw new exceptions_1.TransactionStateError(this.message.method + " not acceptable in state " + this.transaction.state + ".");
  10889. }
  10890. // This response establishes a dialog...
  10891. // https://tools.ietf.org/html/rfc3261#section-13.3.1.4
  10892. if (!this.confirmedDialog) {
  10893. if (this.earlyDialog) {
  10894. this.earlyDialog.confirm();
  10895. this.confirmedDialog = this.earlyDialog;
  10896. this.earlyDialog = undefined;
  10897. }
  10898. else {
  10899. var transaction = this.transaction;
  10900. if (!(transaction instanceof transactions_1.InviteServerTransaction)) {
  10901. throw new Error("Transaction not instance of InviteClientTransaction.");
  10902. }
  10903. var state = dialogs_1.Dialog.initialDialogStateForUserAgentServer(this.message, this.toTag);
  10904. this.confirmedDialog = new dialogs_1.SessionDialog(transaction, this.core, state);
  10905. }
  10906. }
  10907. // When a UAS responds to a request with a response that establishes a
  10908. // dialog (such as a 2xx to INVITE), the UAS MUST copy all Record-Route
  10909. // header field values from the request into the response (including the
  10910. // URIs, URI parameters, and any Record-Route header field parameters,
  10911. // whether they are known or unknown to the UAS) and MUST maintain the
  10912. // order of those values. The UAS MUST add a Contact header field to
  10913. // the response. The Contact header field contains an address where the
  10914. // UAS would like to be contacted for subsequent requests in the dialog
  10915. // (which includes the ACK for a 2xx response in the case of an INVITE).
  10916. // Generally, the host portion of this URI is the IP address or FQDN of
  10917. // the host. The URI provided in the Contact header field MUST be a SIP
  10918. // or SIPS URI. If the request that initiated the dialog contained a
  10919. // SIPS URI in the Request-URI or in the top Record-Route header field
  10920. // value, if there was any, or the Contact header field if there was no
  10921. // Record-Route header field, the Contact header field in the response
  10922. // MUST be a SIPS URI. The URI SHOULD have global scope (that is, the
  10923. // same URI can be used in messages outside this dialog). The same way,
  10924. // the scope of the URI in the Contact header field of the INVITE is not
  10925. // limited to this dialog either. It can therefore be used in messages
  10926. // to the UAC even outside this dialog.
  10927. // https://tools.ietf.org/html/rfc3261#section-12.1.1
  10928. var recordRouteHeader = this.message
  10929. .getHeaders("record-route")
  10930. .map(function (header) { return "Record-Route: " + header; });
  10931. var contactHeader = "Contact: " + this.core.configuration.contact.toString();
  10932. // A 2xx response to an INVITE SHOULD contain the Allow header field and
  10933. // the Supported header field, and MAY contain the Accept header field.
  10934. // Including these header fields allows the UAC to determine the
  10935. // features and extensions supported by the UAS for the duration of the
  10936. // call, without probing.
  10937. // https://tools.ietf.org/html/rfc3261#section-13.3.1.4
  10938. // FIXME: TODO: This should not be hard coded.
  10939. var allowHeader = "Allow: " + allowed_methods_1.AllowedMethods.toString();
  10940. // FIXME: TODO: Supported header (see reply())
  10941. // FIXME: TODO: Accept header
  10942. // If the INVITE request contained an offer, and the UAS had not yet
  10943. // sent an answer, the 2xx MUST contain an answer. If the INVITE did
  10944. // not contain an offer, the 2xx MUST contain an offer if the UAS had
  10945. // not yet sent an offer.
  10946. // https://tools.ietf.org/html/rfc3261#section-13.3.1.4
  10947. if (!options.body) {
  10948. if (this.confirmedDialog.signalingState === session_1.SignalingState.Stable) {
  10949. options.body = this.confirmedDialog.answer; // resend the answer sent in provisional response
  10950. }
  10951. else if (this.confirmedDialog.signalingState === session_1.SignalingState.Initial ||
  10952. this.confirmedDialog.signalingState === session_1.SignalingState.HaveRemoteOffer) {
  10953. throw new Error("Response must have a body.");
  10954. }
  10955. }
  10956. options.statusCode = options.statusCode || 200;
  10957. options.extraHeaders = options.extraHeaders || [];
  10958. options.extraHeaders = options.extraHeaders.concat(recordRouteHeader);
  10959. options.extraHeaders.push(allowHeader);
  10960. options.extraHeaders.push(contactHeader);
  10961. var response = _super.prototype.accept.call(this, options);
  10962. var session = this.confirmedDialog;
  10963. var result = tslib_1.__assign(tslib_1.__assign({}, response), { session: session });
  10964. // Update dialog signaling state
  10965. if (options.body) {
  10966. // Once the UAS has sent or received an answer to the initial
  10967. // offer, it MUST NOT generate subsequent offers in any responses
  10968. // to the initial INVITE. This means that a UAS based on this
  10969. // specification alone can never generate subsequent offers until
  10970. // completion of the initial transaction.
  10971. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  10972. if (this.confirmedDialog.signalingState !== session_1.SignalingState.Stable) {
  10973. this.confirmedDialog.signalingStateTransition(options.body);
  10974. }
  10975. }
  10976. return result;
  10977. };
  10978. /**
  10979. * 13.3.1.1 Progress
  10980. * If the UAS is not able to answer the invitation immediately, it can
  10981. * choose to indicate some kind of progress to the UAC (for example, an
  10982. * indication that a phone is ringing). This is accomplished with a
  10983. * provisional response between 101 and 199. These provisional
  10984. * responses establish early dialogs and therefore follow the procedures
  10985. * of Section 12.1.1 in addition to those of Section 8.2.6. A UAS MAY
  10986. * send as many provisional responses as it likes. Each of these MUST
  10987. * indicate the same dialog ID. However, these will not be delivered
  10988. * reliably.
  10989. *
  10990. * If the UAS desires an extended period of time to answer the INVITE,
  10991. * it will need to ask for an "extension" in order to prevent proxies
  10992. * from canceling the transaction. A proxy has the option of canceling
  10993. * a transaction when there is a gap of 3 minutes between responses in a
  10994. * transaction. To prevent cancellation, the UAS MUST send a non-100
  10995. * provisional response at every minute, to handle the possibility of
  10996. * lost provisional responses.
  10997. * https://tools.ietf.org/html/rfc3261#section-13.3.1.1
  10998. * @param options - Progress options bucket.
  10999. */
  11000. InviteUserAgentServer.prototype.progress = function (options) {
  11001. if (options === void 0) { options = { statusCode: 180 }; }
  11002. if (!this.progressable) {
  11003. throw new exceptions_1.TransactionStateError(this.message.method + " not progressable in state " + this.transaction.state + ".");
  11004. }
  11005. // This response establishes a dialog...
  11006. // https://tools.ietf.org/html/rfc3261#section-13.3.1.4
  11007. if (!this.earlyDialog) {
  11008. var transaction = this.transaction;
  11009. if (!(transaction instanceof transactions_1.InviteServerTransaction)) {
  11010. throw new Error("Transaction not instance of InviteClientTransaction.");
  11011. }
  11012. var state = dialogs_1.Dialog.initialDialogStateForUserAgentServer(this.message, this.toTag, true);
  11013. this.earlyDialog = new dialogs_1.SessionDialog(transaction, this.core, state);
  11014. }
  11015. // When a UAS responds to a request with a response that establishes a
  11016. // dialog (such as a 2xx to INVITE), the UAS MUST copy all Record-Route
  11017. // header field values from the request into the response (including the
  11018. // URIs, URI parameters, and any Record-Route header field parameters,
  11019. // whether they are known or unknown to the UAS) and MUST maintain the
  11020. // order of those values. The UAS MUST add a Contact header field to
  11021. // the response. The Contact header field contains an address where the
  11022. // UAS would like to be contacted for subsequent requests in the dialog
  11023. // (which includes the ACK for a 2xx response in the case of an INVITE).
  11024. // Generally, the host portion of this URI is the IP address or FQDN of
  11025. // the host. The URI provided in the Contact header field MUST be a SIP
  11026. // or SIPS URI. If the request that initiated the dialog contained a
  11027. // SIPS URI in the Request-URI or in the top Record-Route header field
  11028. // value, if there was any, or the Contact header field if there was no
  11029. // Record-Route header field, the Contact header field in the response
  11030. // MUST be a SIPS URI. The URI SHOULD have global scope (that is, the
  11031. // same URI can be used in messages outside this dialog). The same way,
  11032. // the scope of the URI in the Contact header field of the INVITE is not
  11033. // limited to this dialog either. It can therefore be used in messages
  11034. // to the UAC even outside this dialog.
  11035. // https://tools.ietf.org/html/rfc3261#section-12.1.1
  11036. var recordRouteHeader = this.message
  11037. .getHeaders("record-route")
  11038. .map(function (header) { return "Record-Route: " + header; });
  11039. var contactHeader = "Contact: " + this.core.configuration.contact;
  11040. options.extraHeaders = options.extraHeaders || [];
  11041. options.extraHeaders = options.extraHeaders.concat(recordRouteHeader);
  11042. options.extraHeaders.push(contactHeader);
  11043. var response = _super.prototype.progress.call(this, options);
  11044. var session = this.earlyDialog;
  11045. var result = tslib_1.__assign(tslib_1.__assign({}, response), { session: session });
  11046. // Update dialog signaling state
  11047. if (options.body) {
  11048. // Once the UAS has sent or received an answer to the initial
  11049. // offer, it MUST NOT generate subsequent offers in any responses
  11050. // to the initial INVITE. This means that a UAS based on this
  11051. // specification alone can never generate subsequent offers until
  11052. // completion of the initial transaction.
  11053. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  11054. if (this.earlyDialog.signalingState !== session_1.SignalingState.Stable) {
  11055. this.earlyDialog.signalingStateTransition(options.body);
  11056. }
  11057. }
  11058. return result;
  11059. };
  11060. /**
  11061. * 13.3.1.2 The INVITE is Redirected
  11062. * If the UAS decides to redirect the call, a 3xx response is sent. A
  11063. * 300 (Multiple Choices), 301 (Moved Permanently) or 302 (Moved
  11064. * Temporarily) response SHOULD contain a Contact header field
  11065. * containing one or more URIs of new addresses to be tried. The
  11066. * response is passed to the INVITE server transaction, which will deal
  11067. * with its retransmissions.
  11068. * https://tools.ietf.org/html/rfc3261#section-13.3.1.2
  11069. * @param contacts - Contacts to redirect to.
  11070. * @param options - Redirect options bucket.
  11071. */
  11072. InviteUserAgentServer.prototype.redirect = function (contacts, options) {
  11073. if (options === void 0) { options = { statusCode: 302 }; }
  11074. return _super.prototype.redirect.call(this, contacts, options);
  11075. };
  11076. /**
  11077. * 13.3.1.3 The INVITE is Rejected
  11078. * A common scenario occurs when the callee is currently not willing or
  11079. * able to take additional calls at this end system. A 486 (Busy Here)
  11080. * SHOULD be returned in such a scenario.
  11081. * https://tools.ietf.org/html/rfc3261#section-13.3.1.3
  11082. * @param options - Reject options bucket.
  11083. */
  11084. InviteUserAgentServer.prototype.reject = function (options) {
  11085. if (options === void 0) { options = { statusCode: 486 }; }
  11086. return _super.prototype.reject.call(this, options);
  11087. };
  11088. return InviteUserAgentServer;
  11089. }(user_agent_server_1.UserAgentServer));
  11090. exports.InviteUserAgentServer = InviteUserAgentServer;
  11091. /***/ }),
  11092. /* 70 */
  11093. /***/ (function(module, exports, __webpack_require__) {
  11094. "use strict";
  11095. Object.defineProperty(exports, "__esModule", { value: true });
  11096. var tslib_1 = __webpack_require__(1);
  11097. var transactions_1 = __webpack_require__(27);
  11098. var user_agent_client_1 = __webpack_require__(42);
  11099. /**
  11100. * MESSAGE UAS.
  11101. * @public
  11102. */
  11103. var MessageUserAgentClient = /** @class */ (function (_super) {
  11104. tslib_1.__extends(MessageUserAgentClient, _super);
  11105. function MessageUserAgentClient(core, message, delegate) {
  11106. return _super.call(this, transactions_1.NonInviteClientTransaction, core, message, delegate) || this;
  11107. }
  11108. return MessageUserAgentClient;
  11109. }(user_agent_client_1.UserAgentClient));
  11110. exports.MessageUserAgentClient = MessageUserAgentClient;
  11111. /***/ }),
  11112. /* 71 */
  11113. /***/ (function(module, exports, __webpack_require__) {
  11114. "use strict";
  11115. Object.defineProperty(exports, "__esModule", { value: true });
  11116. var tslib_1 = __webpack_require__(1);
  11117. var transactions_1 = __webpack_require__(27);
  11118. var user_agent_server_1 = __webpack_require__(44);
  11119. /**
  11120. * MESSAGE UAS.
  11121. * @public
  11122. */
  11123. var MessageUserAgentServer = /** @class */ (function (_super) {
  11124. tslib_1.__extends(MessageUserAgentServer, _super);
  11125. function MessageUserAgentServer(core, message, delegate) {
  11126. var _this = _super.call(this, transactions_1.NonInviteServerTransaction, core, message, delegate) || this;
  11127. _this.core = core;
  11128. return _this;
  11129. }
  11130. return MessageUserAgentServer;
  11131. }(user_agent_server_1.UserAgentServer));
  11132. exports.MessageUserAgentServer = MessageUserAgentServer;
  11133. /***/ }),
  11134. /* 72 */
  11135. /***/ (function(module, exports, __webpack_require__) {
  11136. "use strict";
  11137. Object.defineProperty(exports, "__esModule", { value: true });
  11138. var tslib_1 = __webpack_require__(1);
  11139. var transactions_1 = __webpack_require__(27);
  11140. var user_agent_client_1 = __webpack_require__(42);
  11141. /**
  11142. * PUBLISH UAC.
  11143. * @public
  11144. */
  11145. var PublishUserAgentClient = /** @class */ (function (_super) {
  11146. tslib_1.__extends(PublishUserAgentClient, _super);
  11147. function PublishUserAgentClient(core, message, delegate) {
  11148. return _super.call(this, transactions_1.NonInviteClientTransaction, core, message, delegate) || this;
  11149. }
  11150. return PublishUserAgentClient;
  11151. }(user_agent_client_1.UserAgentClient));
  11152. exports.PublishUserAgentClient = PublishUserAgentClient;
  11153. /***/ }),
  11154. /* 73 */
  11155. /***/ (function(module, exports, __webpack_require__) {
  11156. "use strict";
  11157. Object.defineProperty(exports, "__esModule", { value: true });
  11158. var tslib_1 = __webpack_require__(1);
  11159. var transactions_1 = __webpack_require__(27);
  11160. var user_agent_server_1 = __webpack_require__(44);
  11161. /**
  11162. * Re-SUBSCRIBE UAS.
  11163. * @public
  11164. */
  11165. var ReSubscribeUserAgentServer = /** @class */ (function (_super) {
  11166. tslib_1.__extends(ReSubscribeUserAgentServer, _super);
  11167. function ReSubscribeUserAgentServer(dialog, message, delegate) {
  11168. return _super.call(this, transactions_1.NonInviteServerTransaction, dialog.userAgentCore, message, delegate) || this;
  11169. }
  11170. return ReSubscribeUserAgentServer;
  11171. }(user_agent_server_1.UserAgentServer));
  11172. exports.ReSubscribeUserAgentServer = ReSubscribeUserAgentServer;
  11173. /***/ }),
  11174. /* 74 */
  11175. /***/ (function(module, exports, __webpack_require__) {
  11176. "use strict";
  11177. Object.defineProperty(exports, "__esModule", { value: true });
  11178. var tslib_1 = __webpack_require__(1);
  11179. var transactions_1 = __webpack_require__(27);
  11180. var user_agent_client_1 = __webpack_require__(42);
  11181. /**
  11182. * REGISTER UAC.
  11183. * @public
  11184. */
  11185. var RegisterUserAgentClient = /** @class */ (function (_super) {
  11186. tslib_1.__extends(RegisterUserAgentClient, _super);
  11187. function RegisterUserAgentClient(core, message, delegate) {
  11188. return _super.call(this, transactions_1.NonInviteClientTransaction, core, message, delegate) || this;
  11189. }
  11190. return RegisterUserAgentClient;
  11191. }(user_agent_client_1.UserAgentClient));
  11192. exports.RegisterUserAgentClient = RegisterUserAgentClient;
  11193. /***/ }),
  11194. /* 75 */
  11195. /***/ (function(module, exports, __webpack_require__) {
  11196. "use strict";
  11197. Object.defineProperty(exports, "__esModule", { value: true });
  11198. var tslib_1 = __webpack_require__(1);
  11199. var transactions_1 = __webpack_require__(27);
  11200. var user_agent_server_1 = __webpack_require__(44);
  11201. /**
  11202. * REGISTER UAS.
  11203. * @public
  11204. */
  11205. var RegisterUserAgentServer = /** @class */ (function (_super) {
  11206. tslib_1.__extends(RegisterUserAgentServer, _super);
  11207. function RegisterUserAgentServer(core, message, delegate) {
  11208. var _this = _super.call(this, transactions_1.NonInviteServerTransaction, core, message, delegate) || this;
  11209. _this.core = core;
  11210. return _this;
  11211. }
  11212. return RegisterUserAgentServer;
  11213. }(user_agent_server_1.UserAgentServer));
  11214. exports.RegisterUserAgentServer = RegisterUserAgentServer;
  11215. /***/ }),
  11216. /* 76 */
  11217. /***/ (function(module, exports, __webpack_require__) {
  11218. "use strict";
  11219. Object.defineProperty(exports, "__esModule", { value: true });
  11220. var tslib_1 = __webpack_require__(1);
  11221. var subscription_dialog_1 = __webpack_require__(55);
  11222. var subscription_1 = __webpack_require__(56);
  11223. var timers_1 = __webpack_require__(26);
  11224. var transactions_1 = __webpack_require__(27);
  11225. var user_agent_client_1 = __webpack_require__(42);
  11226. /**
  11227. * SUBSCRIBE UAC.
  11228. * @remarks
  11229. * 4.1. Subscriber Behavior
  11230. * https://tools.ietf.org/html/rfc6665#section-4.1
  11231. *
  11232. * User agent client for installation of a single subscription per SUBSCRIBE request.
  11233. * TODO: Support for installation of multiple subscriptions on forked SUBSCRIBE reqeuests.
  11234. * @public
  11235. */
  11236. var SubscribeUserAgentClient = /** @class */ (function (_super) {
  11237. tslib_1.__extends(SubscribeUserAgentClient, _super);
  11238. function SubscribeUserAgentClient(core, message, delegate) {
  11239. var _this = this;
  11240. // Get event from request message.
  11241. var event = message.getHeader("Event");
  11242. if (!event) {
  11243. throw new Error("Event undefined");
  11244. }
  11245. // Get expires from reqeust message.
  11246. var expires = message.getHeader("Expires");
  11247. if (!expires) {
  11248. throw new Error("Expires undefined");
  11249. }
  11250. _this = _super.call(this, transactions_1.NonInviteClientTransaction, core, message, delegate) || this;
  11251. _this.delegate = delegate;
  11252. // FIXME: Subscriber id should also be matching on event id.
  11253. _this.subscriberId = message.callId + message.fromTag + event;
  11254. _this.subscriptionExpiresRequested = _this.subscriptionExpires = Number(expires);
  11255. _this.subscriptionEvent = event;
  11256. _this.subscriptionState = subscription_1.SubscriptionState.NotifyWait;
  11257. // Start waiting for a NOTIFY we can use to create a subscription.
  11258. _this.waitNotifyStart();
  11259. return _this;
  11260. }
  11261. /**
  11262. * Destructor.
  11263. * Note that Timer N may live on waiting for an initial NOTIFY and
  11264. * the delegate may still receive that NOTIFY. If you don't want
  11265. * that behavior then either clear the delegate so the delegate
  11266. * doesn't get called (a 200 will be sent in response to the NOTIFY)
  11267. * or call `waitNotifyStop` which will clear Timer N and remove this
  11268. * UAC from the core (a 481 will be sent in response to the NOTIFY).
  11269. */
  11270. SubscribeUserAgentClient.prototype.dispose = function () {
  11271. _super.prototype.dispose.call(this);
  11272. };
  11273. /**
  11274. * Handle out of dialog NOTIFY assoicated with SUBSCRIBE request.
  11275. * This is the first NOTIFY received after the SUBSCRIBE request.
  11276. * @param uas - User agent server handling the subscription creating NOTIFY.
  11277. */
  11278. SubscribeUserAgentClient.prototype.onNotify = function (uas) {
  11279. // NOTIFY requests are matched to such SUBSCRIBE requests if they
  11280. // contain the same "Call-ID", a "To" header field "tag" parameter that
  11281. // matches the "From" header field "tag" parameter of the SUBSCRIBE
  11282. // request, and the same "Event" header field. Rules for comparisons of
  11283. // the "Event" header fields are described in Section 8.2.1.
  11284. // https://tools.ietf.org/html/rfc6665#section-4.4.1
  11285. var event = uas.message.parseHeader("Event").event;
  11286. if (!event || event !== this.subscriptionEvent) {
  11287. this.logger.warn("Failed to parse event.");
  11288. uas.reject({ statusCode: 489 });
  11289. return;
  11290. }
  11291. // NOTIFY requests MUST contain "Subscription-State" header fields that
  11292. // indicate the status of the subscription.
  11293. // https://tools.ietf.org/html/rfc6665#section-4.1.3
  11294. var subscriptionState = uas.message.parseHeader("Subscription-State");
  11295. if (!subscriptionState || !subscriptionState.state) {
  11296. this.logger.warn("Failed to parse subscription state.");
  11297. uas.reject({ statusCode: 489 });
  11298. return;
  11299. }
  11300. // Validate subscription state.
  11301. var state = subscriptionState.state;
  11302. switch (state) {
  11303. case "pending":
  11304. break;
  11305. case "active":
  11306. break;
  11307. case "terminated":
  11308. break;
  11309. default:
  11310. this.logger.warn("Invalid subscription state " + state);
  11311. uas.reject({ statusCode: 489 });
  11312. return;
  11313. }
  11314. // Dialogs usages are created upon completion of a NOTIFY transaction
  11315. // for a new subscription, unless the NOTIFY request contains a
  11316. // "Subscription-State" of "terminated."
  11317. // https://tools.ietf.org/html/rfc6665#section-4.4.1
  11318. if (state !== "terminated") {
  11319. // The Contact header field MUST be present and contain exactly one SIP
  11320. // or SIPS URI in any request that can result in the establishment of a
  11321. // dialog.
  11322. // https://tools.ietf.org/html/rfc3261#section-8.1.1.8
  11323. var contact = uas.message.parseHeader("contact");
  11324. if (!contact) {
  11325. this.logger.warn("Failed to parse contact.");
  11326. uas.reject({ statusCode: 489 });
  11327. return;
  11328. }
  11329. }
  11330. // In accordance with the rules for proxying non-INVITE requests as
  11331. // defined in [RFC3261], successful SUBSCRIBE requests will receive only
  11332. // one 200-class response; however, due to forking, the subscription may
  11333. // have been accepted by multiple nodes. The subscriber MUST therefore
  11334. // be prepared to receive NOTIFY requests with "From:" tags that differ
  11335. // from the "To:" tag received in the SUBSCRIBE 200-class response.
  11336. //
  11337. // If multiple NOTIFY requests are received in different dialogs in
  11338. // response to a single SUBSCRIBE request, each dialog represents a
  11339. // different destination to which the SUBSCRIBE request was forked.
  11340. // Subscriber handling in such situations varies by event package; see
  11341. // Section 5.4.9 for details.
  11342. // https://tools.ietf.org/html/rfc6665#section-4.1.4
  11343. // Each event package MUST specify whether forked SUBSCRIBE requests are
  11344. // allowed to install multiple subscriptions.
  11345. //
  11346. // If such behavior is not allowed, the first potential dialog-
  11347. // establishing message will create a dialog. All subsequent NOTIFY
  11348. // requests that correspond to the SUBSCRIBE request (i.e., have
  11349. // matching "To", "From", "Call-ID", and "Event" header fields, as well
  11350. // as "From" header field "tag" parameter and "Event" header field "id"
  11351. // parameter) but that do not match the dialog would be rejected with a
  11352. // 481 response. Note that the 200-class response to the SUBSCRIBE
  11353. // request can arrive after a matching NOTIFY request has been received;
  11354. // such responses might not correlate to the same dialog established by
  11355. // the NOTIFY request. Except as required to complete the SUBSCRIBE
  11356. // transaction, such non-matching 200-class responses are ignored.
  11357. //
  11358. // If installing of multiple subscriptions by way of a single forked
  11359. // SUBSCRIBE request is allowed, the subscriber establishes a new dialog
  11360. // towards each notifier by returning a 200-class response to each
  11361. // NOTIFY request. Each dialog is then handled as its own entity and is
  11362. // refreshed independently of the other dialogs.
  11363. //
  11364. // In the case that multiple subscriptions are allowed, the event
  11365. // package MUST specify whether merging of the notifications to form a
  11366. // single state is required, and how such merging is to be performed.
  11367. // Note that it is possible that some event packages may be defined in
  11368. // such a way that each dialog is tied to a mutually exclusive state
  11369. // that is unaffected by the other dialogs; this MUST be clearly stated
  11370. // if it is the case.
  11371. // https://tools.ietf.org/html/rfc6665#section-5.4.9
  11372. // *** NOTE: This implementation is only for event packages which
  11373. // do not allow forked requests to install muliple subscriptions.
  11374. // As such and in accordance with the specificaiton, we stop waiting
  11375. // and any future NOTIFY requests will be rejected with a 481.
  11376. if (this.dialog) {
  11377. throw new Error("Dialog already created. This implementation only supports install of single subscriptions.");
  11378. }
  11379. this.waitNotifyStop();
  11380. // Update expires.
  11381. this.subscriptionExpires =
  11382. subscriptionState.expires ?
  11383. Math.min(this.subscriptionExpires, Math.max(subscriptionState.expires, 0)) :
  11384. this.subscriptionExpires;
  11385. // Update subscriptoin state.
  11386. switch (state) {
  11387. case "pending":
  11388. this.subscriptionState = subscription_1.SubscriptionState.Pending;
  11389. break;
  11390. case "active":
  11391. this.subscriptionState = subscription_1.SubscriptionState.Active;
  11392. break;
  11393. case "terminated":
  11394. this.subscriptionState = subscription_1.SubscriptionState.Terminated;
  11395. break;
  11396. default:
  11397. throw new Error("Unrecognized state " + state + ".");
  11398. }
  11399. // Dialogs usages are created upon completion of a NOTIFY transaction
  11400. // for a new subscription, unless the NOTIFY request contains a
  11401. // "Subscription-State" of "terminated."
  11402. // https://tools.ietf.org/html/rfc6665#section-4.4.1
  11403. if (this.subscriptionState !== subscription_1.SubscriptionState.Terminated) {
  11404. // Because the dialog usage is established by the NOTIFY request, the
  11405. // route set at the subscriber is taken from the NOTIFY request itself,
  11406. // as opposed to the route set present in the 200-class response to the
  11407. // SUBSCRIBE request.
  11408. // https://tools.ietf.org/html/rfc6665#section-4.4.1
  11409. var dialogState = subscription_dialog_1.SubscriptionDialog.initialDialogStateForSubscription(this.message, uas.message);
  11410. // Subscription Initiated! :)
  11411. this.dialog = new subscription_dialog_1.SubscriptionDialog(this.subscriptionEvent, this.subscriptionExpires, this.subscriptionState, this.core, dialogState);
  11412. }
  11413. // Delegate.
  11414. if (this.delegate && this.delegate.onNotify) {
  11415. var request = uas;
  11416. var subscription = this.dialog;
  11417. this.delegate.onNotify({ request: request, subscription: subscription });
  11418. }
  11419. else {
  11420. uas.accept();
  11421. }
  11422. };
  11423. SubscribeUserAgentClient.prototype.waitNotifyStart = function () {
  11424. var _this = this;
  11425. if (!this.N) {
  11426. // Add ourselves to the core's subscriber map.
  11427. // This allows the core to route out of dialog NOTIFY messages to us.
  11428. this.core.subscribers.set(this.subscriberId, this);
  11429. this.N = setTimeout(function () { return _this.timer_N(); }, timers_1.Timers.TIMER_N);
  11430. }
  11431. };
  11432. SubscribeUserAgentClient.prototype.waitNotifyStop = function () {
  11433. if (this.N) {
  11434. // Remove ourselves to the core's subscriber map.
  11435. // Any future out of dialog NOTIFY messages will be rejected with a 481.
  11436. this.core.subscribers.delete(this.subscriberId);
  11437. clearTimeout(this.N);
  11438. this.N = undefined;
  11439. }
  11440. };
  11441. /**
  11442. * Receive a response from the transaction layer.
  11443. * @param message - Incoming response message.
  11444. */
  11445. SubscribeUserAgentClient.prototype.receiveResponse = function (message) {
  11446. if (!this.authenticationGuard(message)) {
  11447. return;
  11448. }
  11449. if (message.statusCode && message.statusCode >= 200 && message.statusCode < 300) {
  11450. // The "Expires" header field in a 200-class response to SUBSCRIBE
  11451. // request indicates the actual duration for which the subscription will
  11452. // remain active (unless refreshed). The received value might be
  11453. // smaller than the value indicated in the SUBSCRIBE request but cannot
  11454. // be larger; see Section 4.2.1 for details.
  11455. // https://tools.ietf.org/html/rfc6665#section-4.1.2.1
  11456. // The "Expires" values present in SUBSCRIBE 200-class responses behave
  11457. // in the same way as they do in REGISTER responses: the server MAY
  11458. // shorten the interval but MUST NOT lengthen it.
  11459. //
  11460. // If the duration specified in a SUBSCRIBE request is unacceptably
  11461. // short, the notifier may be able to send a 423 response, as
  11462. // described earlier in this section.
  11463. //
  11464. // 200-class responses to SUBSCRIBE requests will not generally contain
  11465. // any useful information beyond subscription duration; their primary
  11466. // purpose is to serve as a reliability mechanism. State information
  11467. // will be communicated via a subsequent NOTIFY request from the
  11468. // notifier.
  11469. // https://tools.ietf.org/html/rfc6665#section-4.2.1.1
  11470. var expires = message.getHeader("Expires");
  11471. if (!expires) {
  11472. this.logger.warn("Expires header missing in a 200-class response to SUBSCRIBE");
  11473. }
  11474. else {
  11475. var subscriptionExpiresReceived = Number(expires);
  11476. if (subscriptionExpiresReceived > this.subscriptionExpiresRequested) {
  11477. this.logger.warn("Expires header in a 200-class response to SUBSCRIBE with a higher value than the one in the request");
  11478. }
  11479. if (subscriptionExpiresReceived < this.subscriptionExpires) {
  11480. this.subscriptionExpires = subscriptionExpiresReceived;
  11481. }
  11482. }
  11483. // If a NOTIFY arrived before 200-class response a dialog may have been created.
  11484. // Updated the dialogs expiration only if this indicates earlier expiration.
  11485. if (this.dialog) {
  11486. if (this.dialog.subscriptionExpires > this.subscriptionExpires) {
  11487. this.dialog.subscriptionExpires = this.subscriptionExpires;
  11488. }
  11489. }
  11490. }
  11491. if (message.statusCode && message.statusCode >= 300 && message.statusCode < 700) {
  11492. this.waitNotifyStop(); // No NOTIFY will be sent after a negative final response.
  11493. }
  11494. _super.prototype.receiveResponse.call(this, message);
  11495. };
  11496. /**
  11497. * To ensure that subscribers do not wait indefinitely for a
  11498. * subscription to be established, a subscriber starts a Timer N, set to
  11499. * 64*T1, when it sends a SUBSCRIBE request. If this Timer N expires
  11500. * prior to the receipt of a NOTIFY request, the subscriber considers
  11501. * the subscription failed, and cleans up any state associated with the
  11502. * subscription attempt.
  11503. * https://tools.ietf.org/html/rfc6665#section-4.1.2.4
  11504. */
  11505. SubscribeUserAgentClient.prototype.timer_N = function () {
  11506. this.logger.warn("Timer N expired for SUBSCRIBE user agent client. Timed out waiting for NOTIFY.");
  11507. this.waitNotifyStop();
  11508. if (this.delegate && this.delegate.onNotifyTimeout) {
  11509. this.delegate.onNotifyTimeout();
  11510. }
  11511. };
  11512. return SubscribeUserAgentClient;
  11513. }(user_agent_client_1.UserAgentClient));
  11514. exports.SubscribeUserAgentClient = SubscribeUserAgentClient;
  11515. /***/ }),
  11516. /* 77 */
  11517. /***/ (function(module, exports, __webpack_require__) {
  11518. "use strict";
  11519. Object.defineProperty(exports, "__esModule", { value: true });
  11520. var tslib_1 = __webpack_require__(1);
  11521. var transactions_1 = __webpack_require__(27);
  11522. var user_agent_server_1 = __webpack_require__(44);
  11523. /**
  11524. * SUBSCRIBE UAS.
  11525. * @public
  11526. */
  11527. var SubscribeUserAgentServer = /** @class */ (function (_super) {
  11528. tslib_1.__extends(SubscribeUserAgentServer, _super);
  11529. function SubscribeUserAgentServer(core, message, delegate) {
  11530. var _this = _super.call(this, transactions_1.NonInviteServerTransaction, core, message, delegate) || this;
  11531. _this.core = core;
  11532. return _this;
  11533. }
  11534. return SubscribeUserAgentServer;
  11535. }(user_agent_server_1.UserAgentServer));
  11536. exports.SubscribeUserAgentServer = SubscribeUserAgentServer;
  11537. /***/ }),
  11538. /* 78 */
  11539. /***/ (function(module, exports, __webpack_require__) {
  11540. "use strict";
  11541. Object.defineProperty(exports, "__esModule", { value: true });
  11542. var tslib_1 = __webpack_require__(1);
  11543. var events_1 = __webpack_require__(30);
  11544. /**
  11545. * Transport.
  11546. * @remarks
  11547. * Abstract transport layer base class.
  11548. * @public
  11549. */
  11550. var Transport = /** @class */ (function (_super) {
  11551. tslib_1.__extends(Transport, _super);
  11552. /**
  11553. * Constructor
  11554. * @param logger - Logger.
  11555. * @param options - Options bucket. Deprecated.
  11556. */
  11557. function Transport(logger, options) {
  11558. var _this = _super.call(this) || this;
  11559. _this.logger = logger;
  11560. return _this;
  11561. }
  11562. /**
  11563. * Returns the promise designated by the child layer then emits a connected event.
  11564. * Automatically emits an event upon resolution, unless overrideEvent is set. If you
  11565. * override the event in this fashion, you should emit it in your implementation of connectPromise
  11566. * @param options - Options bucket.
  11567. */
  11568. Transport.prototype.connect = function (options) {
  11569. var _this = this;
  11570. if (options === void 0) { options = {}; }
  11571. return this.connectPromise(options).then(function (data) {
  11572. if (!data.overrideEvent) {
  11573. _this.emit("connected");
  11574. }
  11575. });
  11576. };
  11577. /**
  11578. * Sends a message then emits a 'messageSent' event. Automatically emits an
  11579. * event upon resolution, unless data.overrideEvent is set. If you override
  11580. * the event in this fashion, you should emit it in your implementation of sendPromise
  11581. * Rejects with an Error if message fails to send.
  11582. * @param message - Message.
  11583. * @param options - Options bucket.
  11584. */
  11585. Transport.prototype.send = function (message, options) {
  11586. var _this = this;
  11587. if (options === void 0) { options = {}; }
  11588. // Error handling is independent of whether the message was a request or
  11589. // response.
  11590. //
  11591. // If the transport user asks for a message to be sent over an
  11592. // unreliable transport, and the result is an ICMP error, the behavior
  11593. // depends on the type of ICMP error. Host, network, port or protocol
  11594. // unreachable errors, or parameter problem errors SHOULD cause the
  11595. // transport layer to inform the transport user of a failure in sending.
  11596. // Source quench and TTL exceeded ICMP errors SHOULD be ignored.
  11597. //
  11598. // If the transport user asks for a request to be sent over a reliable
  11599. // transport, and the result is a connection failure, the transport
  11600. // layer SHOULD inform the transport user of a failure in sending.
  11601. // https://tools.ietf.org/html/rfc3261#section-18.4
  11602. return this.sendPromise(message).then(function (result) {
  11603. if (!result.overrideEvent) {
  11604. _this.emit("messageSent", result.msg);
  11605. }
  11606. });
  11607. };
  11608. /**
  11609. * Returns the promise designated by the child layer then emits a
  11610. * disconnected event. Automatically emits an event upon resolution,
  11611. * unless overrideEvent is set. If you override the event in this fashion,
  11612. * you should emit it in your implementation of disconnectPromise
  11613. * @param options - Options bucket
  11614. */
  11615. Transport.prototype.disconnect = function (options) {
  11616. var _this = this;
  11617. if (options === void 0) { options = {}; }
  11618. return this.disconnectPromise(options).then(function (data) {
  11619. if (!data.overrideEvent) {
  11620. _this.emit("disconnected");
  11621. }
  11622. });
  11623. };
  11624. Transport.prototype.afterConnected = function (callback) {
  11625. if (this.isConnected()) {
  11626. callback();
  11627. }
  11628. else {
  11629. this.once("connected", callback);
  11630. }
  11631. };
  11632. /**
  11633. * Returns a promise which resolves once the UA is connected. DEPRECATION WARNING: just use afterConnected()
  11634. */
  11635. Transport.prototype.waitForConnected = function () {
  11636. var _this = this;
  11637. // tslint:disable-next-line:no-console
  11638. console.warn("DEPRECATION WARNING Transport.waitForConnected(): use afterConnected() instead");
  11639. return new Promise(function (resolve) {
  11640. _this.afterConnected(resolve);
  11641. });
  11642. };
  11643. return Transport;
  11644. }(events_1.EventEmitter));
  11645. exports.Transport = Transport;
  11646. /***/ }),
  11647. /* 79 */
  11648. /***/ (function(module, exports, __webpack_require__) {
  11649. "use strict";
  11650. Object.defineProperty(exports, "__esModule", { value: true });
  11651. var tslib_1 = __webpack_require__(1);
  11652. var events_1 = __webpack_require__(30);
  11653. var Constants_1 = __webpack_require__(80);
  11654. var core_1 = __webpack_require__(2);
  11655. var Enums_1 = __webpack_require__(82);
  11656. var Utils_1 = __webpack_require__(83);
  11657. var ClientContext = /** @class */ (function (_super) {
  11658. tslib_1.__extends(ClientContext, _super);
  11659. function ClientContext(ua, method, target, options) {
  11660. var _this = _super.call(this) || this;
  11661. _this.data = {};
  11662. ClientContext.initializer(_this, ua, method, target, options);
  11663. return _this;
  11664. }
  11665. ClientContext.initializer = function (objToConstruct, ua, method, originalTarget, options) {
  11666. objToConstruct.type = Enums_1.TypeStrings.ClientContext;
  11667. // Validate arguments
  11668. if (originalTarget === undefined) {
  11669. throw new TypeError("Not enough arguments");
  11670. }
  11671. objToConstruct.ua = ua;
  11672. objToConstruct.logger = ua.getLogger("sip.clientcontext");
  11673. objToConstruct.method = method;
  11674. var target = ua.normalizeTarget(originalTarget);
  11675. if (!target) {
  11676. throw new TypeError("Invalid target: " + originalTarget);
  11677. }
  11678. var fromURI = ua.userAgentCore.configuration.aor;
  11679. if (options && options.params && options.params.fromUri) {
  11680. fromURI =
  11681. (typeof options.params.fromUri === "string") ?
  11682. core_1.Grammar.URIParse(options.params.fromUri) :
  11683. options.params.fromUri;
  11684. if (!fromURI) {
  11685. throw new TypeError("Invalid from URI: " + options.params.fromUri);
  11686. }
  11687. }
  11688. var toURI = target;
  11689. if (options && options.params && options.params.toUri) {
  11690. toURI =
  11691. (typeof options.params.toUri === "string") ?
  11692. core_1.Grammar.URIParse(options.params.toUri) :
  11693. options.params.toUri;
  11694. if (!toURI) {
  11695. throw new TypeError("Invalid to URI: " + options.params.toUri);
  11696. }
  11697. }
  11698. /* Options
  11699. * - extraHeaders
  11700. * - params
  11701. * - contentType
  11702. * - body
  11703. */
  11704. options = Object.create(options || Object.prototype);
  11705. options = options || {};
  11706. var extraHeaders = (options.extraHeaders || []).slice();
  11707. var params = options.params || {};
  11708. var bodyObj;
  11709. if (options.body) {
  11710. bodyObj = {
  11711. body: options.body,
  11712. contentType: options.contentType ? options.contentType : "application/sdp"
  11713. };
  11714. objToConstruct.body = bodyObj;
  11715. }
  11716. var body;
  11717. if (bodyObj) {
  11718. body = Utils_1.Utils.fromBodyObj(bodyObj);
  11719. }
  11720. // Build the request
  11721. objToConstruct.request = ua.userAgentCore.makeOutgoingRequestMessage(method, target, fromURI, toURI, params, extraHeaders, body);
  11722. /* Set other properties from the request */
  11723. if (objToConstruct.request.from) {
  11724. objToConstruct.localIdentity = objToConstruct.request.from;
  11725. }
  11726. if (objToConstruct.request.to) {
  11727. objToConstruct.remoteIdentity = objToConstruct.request.to;
  11728. }
  11729. };
  11730. ClientContext.prototype.send = function () {
  11731. var _this = this;
  11732. this.ua.userAgentCore.request(this.request, {
  11733. onAccept: function (response) { return _this.receiveResponse(response.message); },
  11734. onProgress: function (response) { return _this.receiveResponse(response.message); },
  11735. onRedirect: function (response) { return _this.receiveResponse(response.message); },
  11736. onReject: function (response) { return _this.receiveResponse(response.message); },
  11737. onTrying: function (response) { return _this.receiveResponse(response.message); }
  11738. });
  11739. return this;
  11740. };
  11741. ClientContext.prototype.receiveResponse = function (response) {
  11742. var statusCode = response.statusCode || 0;
  11743. var cause = Utils_1.Utils.getReasonPhrase(statusCode);
  11744. switch (true) {
  11745. case /^1[0-9]{2}$/.test(statusCode.toString()):
  11746. this.emit("progress", response, cause);
  11747. break;
  11748. case /^2[0-9]{2}$/.test(statusCode.toString()):
  11749. if (this.ua.applicants[this.toString()]) {
  11750. delete this.ua.applicants[this.toString()];
  11751. }
  11752. this.emit("accepted", response, cause);
  11753. break;
  11754. default:
  11755. if (this.ua.applicants[this.toString()]) {
  11756. delete this.ua.applicants[this.toString()];
  11757. }
  11758. this.emit("rejected", response, cause);
  11759. this.emit("failed", response, cause);
  11760. break;
  11761. }
  11762. };
  11763. ClientContext.prototype.onRequestTimeout = function () {
  11764. this.emit("failed", undefined, Constants_1.C.causes.REQUEST_TIMEOUT);
  11765. };
  11766. ClientContext.prototype.onTransportError = function () {
  11767. this.emit("failed", undefined, Constants_1.C.causes.CONNECTION_ERROR);
  11768. };
  11769. return ClientContext;
  11770. }(events_1.EventEmitter));
  11771. exports.ClientContext = ClientContext;
  11772. /***/ }),
  11773. /* 80 */
  11774. /***/ (function(module, exports, __webpack_require__) {
  11775. "use strict";
  11776. Object.defineProperty(exports, "__esModule", { value: true });
  11777. var version_1 = __webpack_require__(81);
  11778. var C;
  11779. (function (C) {
  11780. C.version = version_1.LIBRARY_VERSION;
  11781. C.USER_AGENT = "SIP.js/" + version_1.LIBRARY_VERSION;
  11782. // SIP scheme
  11783. C.SIP = "sip";
  11784. C.SIPS = "sips";
  11785. // End and Failure causes
  11786. var causes;
  11787. (function (causes) {
  11788. // Generic error causes
  11789. causes["CONNECTION_ERROR"] = "Connection Error";
  11790. causes["INTERNAL_ERROR"] = "Internal Error";
  11791. causes["REQUEST_TIMEOUT"] = "Request Timeout";
  11792. causes["SIP_FAILURE_CODE"] = "SIP Failure Code";
  11793. // SIP error causes
  11794. causes["ADDRESS_INCOMPLETE"] = "Address Incomplete";
  11795. causes["AUTHENTICATION_ERROR"] = "Authentication Error";
  11796. causes["BUSY"] = "Busy";
  11797. causes["DIALOG_ERROR"] = "Dialog Error";
  11798. causes["INCOMPATIBLE_SDP"] = "Incompatible SDP";
  11799. causes["NOT_FOUND"] = "Not Found";
  11800. causes["REDIRECTED"] = "Redirected";
  11801. causes["REJECTED"] = "Rejected";
  11802. causes["UNAVAILABLE"] = "Unavailable";
  11803. // Session error causes
  11804. causes["BAD_MEDIA_DESCRIPTION"] = "Bad Media Description";
  11805. causes["CANCELED"] = "Canceled";
  11806. causes["EXPIRES"] = "Expires";
  11807. causes["NO_ACK"] = "No ACK";
  11808. causes["NO_ANSWER"] = "No Answer";
  11809. causes["NO_PRACK"] = "No PRACK";
  11810. causes["RTP_TIMEOUT"] = "RTP Timeout";
  11811. causes["USER_DENIED_MEDIA_ACCESS"] = "User Denied Media Access";
  11812. causes["WEBRTC_ERROR"] = "WebRTC Error";
  11813. causes["WEBRTC_NOT_SUPPORTED"] = "WebRTC Not Supported";
  11814. })(causes = C.causes || (C.causes = {}));
  11815. var supported;
  11816. (function (supported) {
  11817. supported["REQUIRED"] = "required";
  11818. supported["SUPPORTED"] = "supported";
  11819. supported["UNSUPPORTED"] = "none";
  11820. })(supported = C.supported || (C.supported = {}));
  11821. C.SIP_ERROR_CAUSES = {
  11822. ADDRESS_INCOMPLETE: [484],
  11823. AUTHENTICATION_ERROR: [401, 407],
  11824. BUSY: [486, 600],
  11825. INCOMPATIBLE_SDP: [488, 606],
  11826. NOT_FOUND: [404, 604],
  11827. REDIRECTED: [300, 301, 302, 305, 380],
  11828. REJECTED: [403, 603],
  11829. UNAVAILABLE: [480, 410, 408, 430]
  11830. };
  11831. // SIP Methods
  11832. C.ACK = "ACK";
  11833. C.BYE = "BYE";
  11834. C.CANCEL = "CANCEL";
  11835. C.INFO = "INFO";
  11836. C.INVITE = "INVITE";
  11837. C.MESSAGE = "MESSAGE";
  11838. C.NOTIFY = "NOTIFY";
  11839. C.OPTIONS = "OPTIONS";
  11840. C.REGISTER = "REGISTER";
  11841. C.UPDATE = "UPDATE";
  11842. C.SUBSCRIBE = "SUBSCRIBE";
  11843. C.PUBLISH = "PUBLISH";
  11844. C.REFER = "REFER";
  11845. C.PRACK = "PRACK";
  11846. /* SIP Response Reasons
  11847. * DOC: http://www.iana.org/assignments/sip-parameters
  11848. * Copied from https://github.com/versatica/OverSIP/blob/master/lib/oversip/sip/constants.rb#L7
  11849. */
  11850. C.REASON_PHRASE = {
  11851. 100: "Trying",
  11852. 180: "Ringing",
  11853. 181: "Call Is Being Forwarded",
  11854. 182: "Queued",
  11855. 183: "Session Progress",
  11856. 199: "Early Dialog Terminated",
  11857. 200: "OK",
  11858. 202: "Accepted",
  11859. 204: "No Notification",
  11860. 300: "Multiple Choices",
  11861. 301: "Moved Permanently",
  11862. 302: "Moved Temporarily",
  11863. 305: "Use Proxy",
  11864. 380: "Alternative Service",
  11865. 400: "Bad Request",
  11866. 401: "Unauthorized",
  11867. 402: "Payment Required",
  11868. 403: "Forbidden",
  11869. 404: "Not Found",
  11870. 405: "Method Not Allowed",
  11871. 406: "Not Acceptable",
  11872. 407: "Proxy Authentication Required",
  11873. 408: "Request Timeout",
  11874. 410: "Gone",
  11875. 412: "Conditional Request Failed",
  11876. 413: "Request Entity Too Large",
  11877. 414: "Request-URI Too Long",
  11878. 415: "Unsupported Media Type",
  11879. 416: "Unsupported URI Scheme",
  11880. 417: "Unknown Resource-Priority",
  11881. 420: "Bad Extension",
  11882. 421: "Extension Required",
  11883. 422: "Session Interval Too Small",
  11884. 423: "Interval Too Brief",
  11885. 428: "Use Identity Header",
  11886. 429: "Provide Referrer Identity",
  11887. 430: "Flow Failed",
  11888. 433: "Anonymity Disallowed",
  11889. 436: "Bad Identity-Info",
  11890. 437: "Unsupported Certificate",
  11891. 438: "Invalid Identity Header",
  11892. 439: "First Hop Lacks Outbound Support",
  11893. 440: "Max-Breadth Exceeded",
  11894. 469: "Bad Info Package",
  11895. 470: "Consent Needed",
  11896. 478: "Unresolvable Destination",
  11897. 480: "Temporarily Unavailable",
  11898. 481: "Call/Transaction Does Not Exist",
  11899. 482: "Loop Detected",
  11900. 483: "Too Many Hops",
  11901. 484: "Address Incomplete",
  11902. 485: "Ambiguous",
  11903. 486: "Busy Here",
  11904. 487: "Request Terminated",
  11905. 488: "Not Acceptable Here",
  11906. 489: "Bad Event",
  11907. 491: "Request Pending",
  11908. 493: "Undecipherable",
  11909. 494: "Security Agreement Required",
  11910. 500: "Internal Server Error",
  11911. 501: "Not Implemented",
  11912. 502: "Bad Gateway",
  11913. 503: "Service Unavailable",
  11914. 504: "Server Time-out",
  11915. 505: "Version Not Supported",
  11916. 513: "Message Too Large",
  11917. 580: "Precondition Failure",
  11918. 600: "Busy Everywhere",
  11919. 603: "Decline",
  11920. 604: "Does Not Exist Anywhere",
  11921. 606: "Not Acceptable"
  11922. };
  11923. /* SIP Option Tags
  11924. * DOC: http://www.iana.org/assignments/sip-parameters/sip-parameters.xhtml#sip-parameters-4
  11925. */
  11926. C.OPTION_TAGS = {
  11927. "100rel": true,
  11928. "199": true,
  11929. "answermode": true,
  11930. "early-session": true,
  11931. "eventlist": true,
  11932. "explicitsub": true,
  11933. "from-change": true,
  11934. "geolocation-http": true,
  11935. "geolocation-sip": true,
  11936. "gin": true,
  11937. "gruu": true,
  11938. "histinfo": true,
  11939. "ice": true,
  11940. "join": true,
  11941. "multiple-refer": true,
  11942. "norefersub": true,
  11943. "nosub": true,
  11944. "outbound": true,
  11945. "path": true,
  11946. "policy": true,
  11947. "precondition": true,
  11948. "pref": true,
  11949. "privacy": true,
  11950. "recipient-list-invite": true,
  11951. "recipient-list-message": true,
  11952. "recipient-list-subscribe": true,
  11953. "replaces": true,
  11954. "resource-priority": true,
  11955. "sdp-anat": true,
  11956. "sec-agree": true,
  11957. "tdialog": true,
  11958. "timer": true,
  11959. "uui": true // RFC 7433
  11960. };
  11961. var dtmfType;
  11962. (function (dtmfType) {
  11963. dtmfType["INFO"] = "info";
  11964. dtmfType["RTP"] = "rtp";
  11965. })(dtmfType = C.dtmfType || (C.dtmfType = {}));
  11966. })(C = exports.C || (exports.C = {}));
  11967. /***/ }),
  11968. /* 81 */
  11969. /***/ (function(module, exports, __webpack_require__) {
  11970. "use strict";
  11971. Object.defineProperty(exports, "__esModule", { value: true });
  11972. exports.LIBRARY_VERSION = "0.15.6";
  11973. /***/ }),
  11974. /* 82 */
  11975. /***/ (function(module, exports, __webpack_require__) {
  11976. "use strict";
  11977. // enums can't really be declared, so they are set here.
  11978. // pulled out of individual files to avoid circular dependencies
  11979. Object.defineProperty(exports, "__esModule", { value: true });
  11980. var DialogStatus;
  11981. (function (DialogStatus) {
  11982. DialogStatus[DialogStatus["STATUS_EARLY"] = 1] = "STATUS_EARLY";
  11983. DialogStatus[DialogStatus["STATUS_CONFIRMED"] = 2] = "STATUS_CONFIRMED";
  11984. })(DialogStatus = exports.DialogStatus || (exports.DialogStatus = {}));
  11985. var SessionStatus;
  11986. (function (SessionStatus) {
  11987. // Session states
  11988. SessionStatus[SessionStatus["STATUS_NULL"] = 0] = "STATUS_NULL";
  11989. SessionStatus[SessionStatus["STATUS_INVITE_SENT"] = 1] = "STATUS_INVITE_SENT";
  11990. SessionStatus[SessionStatus["STATUS_1XX_RECEIVED"] = 2] = "STATUS_1XX_RECEIVED";
  11991. SessionStatus[SessionStatus["STATUS_INVITE_RECEIVED"] = 3] = "STATUS_INVITE_RECEIVED";
  11992. SessionStatus[SessionStatus["STATUS_WAITING_FOR_ANSWER"] = 4] = "STATUS_WAITING_FOR_ANSWER";
  11993. SessionStatus[SessionStatus["STATUS_ANSWERED"] = 5] = "STATUS_ANSWERED";
  11994. SessionStatus[SessionStatus["STATUS_WAITING_FOR_PRACK"] = 6] = "STATUS_WAITING_FOR_PRACK";
  11995. SessionStatus[SessionStatus["STATUS_WAITING_FOR_ACK"] = 7] = "STATUS_WAITING_FOR_ACK";
  11996. SessionStatus[SessionStatus["STATUS_CANCELED"] = 8] = "STATUS_CANCELED";
  11997. SessionStatus[SessionStatus["STATUS_TERMINATED"] = 9] = "STATUS_TERMINATED";
  11998. SessionStatus[SessionStatus["STATUS_ANSWERED_WAITING_FOR_PRACK"] = 10] = "STATUS_ANSWERED_WAITING_FOR_PRACK";
  11999. SessionStatus[SessionStatus["STATUS_EARLY_MEDIA"] = 11] = "STATUS_EARLY_MEDIA";
  12000. SessionStatus[SessionStatus["STATUS_CONFIRMED"] = 12] = "STATUS_CONFIRMED";
  12001. })(SessionStatus = exports.SessionStatus || (exports.SessionStatus = {}));
  12002. var TypeStrings;
  12003. (function (TypeStrings) {
  12004. TypeStrings[TypeStrings["ClientContext"] = 0] = "ClientContext";
  12005. TypeStrings[TypeStrings["ConfigurationError"] = 1] = "ConfigurationError";
  12006. TypeStrings[TypeStrings["Dialog"] = 2] = "Dialog";
  12007. TypeStrings[TypeStrings["DigestAuthentication"] = 3] = "DigestAuthentication";
  12008. TypeStrings[TypeStrings["DTMF"] = 4] = "DTMF";
  12009. TypeStrings[TypeStrings["IncomingMessage"] = 5] = "IncomingMessage";
  12010. TypeStrings[TypeStrings["IncomingRequest"] = 6] = "IncomingRequest";
  12011. TypeStrings[TypeStrings["IncomingResponse"] = 7] = "IncomingResponse";
  12012. TypeStrings[TypeStrings["InvalidStateError"] = 8] = "InvalidStateError";
  12013. TypeStrings[TypeStrings["InviteClientContext"] = 9] = "InviteClientContext";
  12014. TypeStrings[TypeStrings["InviteServerContext"] = 10] = "InviteServerContext";
  12015. TypeStrings[TypeStrings["Logger"] = 11] = "Logger";
  12016. TypeStrings[TypeStrings["LoggerFactory"] = 12] = "LoggerFactory";
  12017. TypeStrings[TypeStrings["MethodParameterError"] = 13] = "MethodParameterError";
  12018. TypeStrings[TypeStrings["NameAddrHeader"] = 14] = "NameAddrHeader";
  12019. TypeStrings[TypeStrings["NotSupportedError"] = 15] = "NotSupportedError";
  12020. TypeStrings[TypeStrings["OutgoingRequest"] = 16] = "OutgoingRequest";
  12021. TypeStrings[TypeStrings["Parameters"] = 17] = "Parameters";
  12022. TypeStrings[TypeStrings["PublishContext"] = 18] = "PublishContext";
  12023. TypeStrings[TypeStrings["ReferClientContext"] = 19] = "ReferClientContext";
  12024. TypeStrings[TypeStrings["ReferServerContext"] = 20] = "ReferServerContext";
  12025. TypeStrings[TypeStrings["RegisterContext"] = 21] = "RegisterContext";
  12026. TypeStrings[TypeStrings["RenegotiationError"] = 22] = "RenegotiationError";
  12027. TypeStrings[TypeStrings["RequestSender"] = 23] = "RequestSender";
  12028. TypeStrings[TypeStrings["ServerContext"] = 24] = "ServerContext";
  12029. TypeStrings[TypeStrings["Session"] = 25] = "Session";
  12030. TypeStrings[TypeStrings["SessionDescriptionHandler"] = 26] = "SessionDescriptionHandler";
  12031. TypeStrings[TypeStrings["SessionDescriptionHandlerError"] = 27] = "SessionDescriptionHandlerError";
  12032. TypeStrings[TypeStrings["SessionDescriptionHandlerObserver"] = 28] = "SessionDescriptionHandlerObserver";
  12033. TypeStrings[TypeStrings["Subscription"] = 29] = "Subscription";
  12034. TypeStrings[TypeStrings["Transport"] = 30] = "Transport";
  12035. TypeStrings[TypeStrings["UA"] = 31] = "UA";
  12036. TypeStrings[TypeStrings["URI"] = 32] = "URI";
  12037. })(TypeStrings = exports.TypeStrings || (exports.TypeStrings = {}));
  12038. // UA status codes
  12039. var UAStatus;
  12040. (function (UAStatus) {
  12041. UAStatus[UAStatus["STATUS_INIT"] = 0] = "STATUS_INIT";
  12042. UAStatus[UAStatus["STATUS_STARTING"] = 1] = "STATUS_STARTING";
  12043. UAStatus[UAStatus["STATUS_READY"] = 2] = "STATUS_READY";
  12044. UAStatus[UAStatus["STATUS_USER_CLOSED"] = 3] = "STATUS_USER_CLOSED";
  12045. UAStatus[UAStatus["STATUS_NOT_READY"] = 4] = "STATUS_NOT_READY";
  12046. })(UAStatus = exports.UAStatus || (exports.UAStatus = {}));
  12047. /***/ }),
  12048. /* 83 */
  12049. /***/ (function(module, exports, __webpack_require__) {
  12050. "use strict";
  12051. Object.defineProperty(exports, "__esModule", { value: true });
  12052. var Constants_1 = __webpack_require__(80);
  12053. var grammar_1 = __webpack_require__(11);
  12054. var uri_1 = __webpack_require__(15);
  12055. var Utils;
  12056. (function (Utils) {
  12057. function defer() {
  12058. var deferred = {};
  12059. deferred.promise = new Promise(function (resolve, reject) {
  12060. deferred.resolve = resolve;
  12061. deferred.reject = reject;
  12062. });
  12063. return deferred;
  12064. }
  12065. Utils.defer = defer;
  12066. function reducePromises(arr, val) {
  12067. return arr.reduce(function (acc, fn) {
  12068. acc = acc.then(fn);
  12069. return acc;
  12070. }, Promise.resolve(val));
  12071. }
  12072. Utils.reducePromises = reducePromises;
  12073. function str_utf8_length(str) {
  12074. return encodeURIComponent(str).replace(/%[A-F\d]{2}/g, "U").length;
  12075. }
  12076. Utils.str_utf8_length = str_utf8_length;
  12077. function generateFakeSDP(body) {
  12078. if (!body) {
  12079. return;
  12080. }
  12081. var start = body.indexOf("o=");
  12082. var end = body.indexOf("\r\n", start);
  12083. return "v=0\r\n" + body.slice(start, end) + "\r\ns=-\r\nt=0 0\r\nc=IN IP4 0.0.0.0";
  12084. }
  12085. Utils.generateFakeSDP = generateFakeSDP;
  12086. function isDecimal(num) {
  12087. var numAsNum = parseInt(num, 10);
  12088. return !isNaN(numAsNum) && (parseFloat(num) === numAsNum);
  12089. }
  12090. Utils.isDecimal = isDecimal;
  12091. function createRandomToken(size, base) {
  12092. if (base === void 0) { base = 32; }
  12093. var token = "";
  12094. for (var i = 0; i < size; i++) {
  12095. var r = Math.floor(Math.random() * base);
  12096. token += r.toString(base);
  12097. }
  12098. return token;
  12099. }
  12100. Utils.createRandomToken = createRandomToken;
  12101. function newTag() {
  12102. // used to use the constant in UA
  12103. return Utils.createRandomToken(10);
  12104. }
  12105. Utils.newTag = newTag;
  12106. // http://stackoverflow.com/users/109538/broofa
  12107. function newUUID() {
  12108. var UUID = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
  12109. var r = Math.floor(Math.random() * 16);
  12110. var v = c === "x" ? r : (r % 4 + 8);
  12111. return v.toString(16);
  12112. });
  12113. return UUID;
  12114. }
  12115. Utils.newUUID = newUUID;
  12116. /*
  12117. * Normalize SIP URI.
  12118. * NOTE: It does not allow a SIP URI without username.
  12119. * Accepts 'sip', 'sips' and 'tel' URIs and convert them into 'sip'.
  12120. * Detects the domain part (if given) and properly hex-escapes the user portion.
  12121. * If the user portion has only 'tel' number symbols the user portion is clean of 'tel' visual separators.
  12122. * @private
  12123. * @param {String} target
  12124. * @param {String} [domain]
  12125. */
  12126. function normalizeTarget(target, domain) {
  12127. // If no target is given then raise an error.
  12128. if (!target) {
  12129. return;
  12130. // If a SIP.URI instance is given then return it.
  12131. }
  12132. else if (target instanceof uri_1.URI) {
  12133. return target;
  12134. // If a string is given split it by '@':
  12135. // - Last fragment is the desired domain.
  12136. // - Otherwise append the given domain argument.
  12137. }
  12138. else if (typeof target === "string") {
  12139. var targetArray = target.split("@");
  12140. var targetUser = void 0;
  12141. var targetDomain = void 0;
  12142. switch (targetArray.length) {
  12143. case 1:
  12144. if (!domain) {
  12145. return;
  12146. }
  12147. targetUser = target;
  12148. targetDomain = domain;
  12149. break;
  12150. case 2:
  12151. targetUser = targetArray[0];
  12152. targetDomain = targetArray[1];
  12153. break;
  12154. default:
  12155. targetUser = targetArray.slice(0, targetArray.length - 1).join("@");
  12156. targetDomain = targetArray[targetArray.length - 1];
  12157. }
  12158. // Remove the URI scheme (if present).
  12159. targetUser = targetUser.replace(/^(sips?|tel):/i, "");
  12160. // Remove 'tel' visual separators if the user portion just contains 'tel' number symbols.
  12161. if (/^[\-\.\(\)]*\+?[0-9\-\.\(\)]+$/.test(targetUser)) {
  12162. targetUser = targetUser.replace(/[\-\.\(\)]/g, "");
  12163. }
  12164. // Build the complete SIP URI.
  12165. target = Constants_1.C.SIP + ":" + Utils.escapeUser(targetUser) + "@" + targetDomain;
  12166. // Finally parse the resulting URI.
  12167. return grammar_1.Grammar.URIParse(target);
  12168. }
  12169. else {
  12170. return;
  12171. }
  12172. }
  12173. Utils.normalizeTarget = normalizeTarget;
  12174. /*
  12175. * Hex-escape a SIP URI user.
  12176. * @private
  12177. * @param {String} user
  12178. */
  12179. function escapeUser(user) {
  12180. // Don't hex-escape ':' (%3A), '+' (%2B), '?' (%3F"), '/' (%2F).
  12181. return encodeURIComponent(decodeURIComponent(user))
  12182. .replace(/%3A/ig, ":")
  12183. .replace(/%2B/ig, "+")
  12184. .replace(/%3F/ig, "?")
  12185. .replace(/%2F/ig, "/");
  12186. }
  12187. Utils.escapeUser = escapeUser;
  12188. function headerize(str) {
  12189. var exceptions = {
  12190. "Call-Id": "Call-ID",
  12191. "Cseq": "CSeq",
  12192. "Min-Se": "Min-SE",
  12193. "Rack": "RAck",
  12194. "Rseq": "RSeq",
  12195. "Www-Authenticate": "WWW-Authenticate",
  12196. };
  12197. var name = str.toLowerCase().replace(/_/g, "-").split("-");
  12198. var parts = name.length;
  12199. var hname = "";
  12200. for (var part = 0; part < parts; part++) {
  12201. if (part !== 0) {
  12202. hname += "-";
  12203. }
  12204. hname += name[part].charAt(0).toUpperCase() + name[part].substring(1);
  12205. }
  12206. if (exceptions[hname]) {
  12207. hname = exceptions[hname];
  12208. }
  12209. return hname;
  12210. }
  12211. Utils.headerize = headerize;
  12212. function sipErrorCause(statusCode) {
  12213. for (var cause in Constants_1.C.SIP_ERROR_CAUSES) {
  12214. if (Constants_1.C.SIP_ERROR_CAUSES[cause].indexOf(statusCode) !== -1) {
  12215. return Constants_1.C.causes[cause];
  12216. }
  12217. }
  12218. return Constants_1.C.causes.SIP_FAILURE_CODE;
  12219. }
  12220. Utils.sipErrorCause = sipErrorCause;
  12221. function getReasonPhrase(code, specific) {
  12222. return specific || Constants_1.C.REASON_PHRASE[code] || "";
  12223. }
  12224. Utils.getReasonPhrase = getReasonPhrase;
  12225. function getReasonHeaderValue(code, reason) {
  12226. reason = Utils.getReasonPhrase(code, reason);
  12227. return "SIP;cause=" + code + ';text="' + reason + '"';
  12228. }
  12229. Utils.getReasonHeaderValue = getReasonHeaderValue;
  12230. function getCancelReason(code, reason) {
  12231. if (code && code < 200 || code > 699) {
  12232. throw new TypeError("Invalid statusCode: " + code);
  12233. }
  12234. else if (code) {
  12235. return Utils.getReasonHeaderValue(code, reason);
  12236. }
  12237. }
  12238. Utils.getCancelReason = getCancelReason;
  12239. function buildStatusLine(code, reason) {
  12240. // Validate code and reason values
  12241. if (!code || (code < 100 || code > 699)) {
  12242. throw new TypeError("Invalid statusCode: " + code);
  12243. }
  12244. else if (reason && typeof reason !== "string" && !(reason instanceof String)) {
  12245. throw new TypeError("Invalid reason: " + reason);
  12246. }
  12247. reason = Utils.getReasonPhrase(code, reason);
  12248. return "SIP/2.0 " + code + " " + reason + "\r\n";
  12249. }
  12250. Utils.buildStatusLine = buildStatusLine;
  12251. /**
  12252. * Create a Body given a BodyObj.
  12253. * @param bodyObj Body Object
  12254. */
  12255. function fromBodyObj(bodyObj) {
  12256. var content = bodyObj.body;
  12257. var contentType = bodyObj.contentType;
  12258. var contentDisposition = contentTypeToContentDisposition(contentType);
  12259. var body = { contentDisposition: contentDisposition, contentType: contentType, content: content };
  12260. return body;
  12261. }
  12262. Utils.fromBodyObj = fromBodyObj;
  12263. /**
  12264. * Create a BodyObj given a Body.
  12265. * @param bodyObj Body Object
  12266. */
  12267. function toBodyObj(body) {
  12268. var bodyObj = {
  12269. body: body.content,
  12270. contentType: body.contentType
  12271. };
  12272. return bodyObj;
  12273. }
  12274. Utils.toBodyObj = toBodyObj;
  12275. // If the Content-Disposition header field is missing, bodies of
  12276. // Content-Type application/sdp imply the disposition "session", while
  12277. // other content types imply "render".
  12278. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  12279. function contentTypeToContentDisposition(contentType) {
  12280. if (contentType === "application/sdp") {
  12281. return "session";
  12282. }
  12283. else {
  12284. return "render";
  12285. }
  12286. }
  12287. })(Utils = exports.Utils || (exports.Utils = {}));
  12288. /***/ }),
  12289. /* 84 */
  12290. /***/ (function(module, exports, __webpack_require__) {
  12291. "use strict";
  12292. Object.defineProperty(exports, "__esModule", { value: true });
  12293. var tslib_1 = __webpack_require__(1);
  12294. var core_1 = __webpack_require__(2);
  12295. var Enums_1 = __webpack_require__(82);
  12296. // tslint:disable:max-classes-per-file
  12297. var Exceptions;
  12298. (function (Exceptions) {
  12299. /**
  12300. * Indicates the session description handler has closed.
  12301. * Occurs when getDescription() or setDescription() are called after close() has been called.
  12302. * Occurs when close() is called while getDescription() or setDescription() are in progress.
  12303. */
  12304. var ClosedSessionDescriptionHandlerError = /** @class */ (function (_super) {
  12305. tslib_1.__extends(ClosedSessionDescriptionHandlerError, _super);
  12306. function ClosedSessionDescriptionHandlerError() {
  12307. return _super.call(this, "The session description handler has closed.") || this;
  12308. }
  12309. return ClosedSessionDescriptionHandlerError;
  12310. }(core_1.Exception));
  12311. Exceptions.ClosedSessionDescriptionHandlerError = ClosedSessionDescriptionHandlerError;
  12312. /**
  12313. * Indicates the session terminated before the action completed.
  12314. */
  12315. var TerminatedSessionError = /** @class */ (function (_super) {
  12316. tslib_1.__extends(TerminatedSessionError, _super);
  12317. function TerminatedSessionError() {
  12318. return _super.call(this, "The session has terminated.") || this;
  12319. }
  12320. return TerminatedSessionError;
  12321. }(core_1.Exception));
  12322. Exceptions.TerminatedSessionError = TerminatedSessionError;
  12323. /**
  12324. * Unsupported session description content type.
  12325. */
  12326. var UnsupportedSessionDescriptionContentTypeError = /** @class */ (function (_super) {
  12327. tslib_1.__extends(UnsupportedSessionDescriptionContentTypeError, _super);
  12328. function UnsupportedSessionDescriptionContentTypeError(message) {
  12329. return _super.call(this, message ? message : "Unsupported session description content type.") || this;
  12330. }
  12331. return UnsupportedSessionDescriptionContentTypeError;
  12332. }(core_1.Exception));
  12333. Exceptions.UnsupportedSessionDescriptionContentTypeError = UnsupportedSessionDescriptionContentTypeError;
  12334. })(Exceptions = exports.Exceptions || (exports.Exceptions = {}));
  12335. /**
  12336. * DEPRECATED: The original implementation of exceptions in this library attempted to
  12337. * deal with the lack of type checking in JavaScript by adding a "type" attribute
  12338. * to objects and using that to discriminate. On top of that it layered allcoated
  12339. * "code" numbers and constant "name" strings. All of that is unnecessary when using
  12340. * TypeScript, inheriting from Error and properly setting up the prototype chain...
  12341. */
  12342. var LegacyException = /** @class */ (function (_super) {
  12343. tslib_1.__extends(LegacyException, _super);
  12344. function LegacyException(code, name, message) {
  12345. var _this = _super.call(this, message) || this;
  12346. _this.code = code;
  12347. _this.name = name;
  12348. _this.message = message;
  12349. return _this;
  12350. }
  12351. return LegacyException;
  12352. }(core_1.Exception));
  12353. (function (Exceptions) {
  12354. var ConfigurationError = /** @class */ (function (_super) {
  12355. tslib_1.__extends(ConfigurationError, _super);
  12356. function ConfigurationError(parameter, value) {
  12357. var _this = _super.call(this, 1, "CONFIGURATION_ERROR", (!value) ? "Missing parameter: " + parameter :
  12358. "Invalid value " + JSON.stringify(value) + " for parameter '" + parameter + "'") || this;
  12359. _this.type = Enums_1.TypeStrings.ConfigurationError;
  12360. _this.parameter = parameter;
  12361. _this.value = value;
  12362. return _this;
  12363. }
  12364. return ConfigurationError;
  12365. }(LegacyException));
  12366. Exceptions.ConfigurationError = ConfigurationError;
  12367. var InvalidStateError = /** @class */ (function (_super) {
  12368. tslib_1.__extends(InvalidStateError, _super);
  12369. function InvalidStateError(status) {
  12370. var _this = _super.call(this, 2, "INVALID_STATE_ERROR", "Invalid status: " + status) || this;
  12371. _this.type = Enums_1.TypeStrings.InvalidStateError;
  12372. _this.status = status;
  12373. return _this;
  12374. }
  12375. return InvalidStateError;
  12376. }(LegacyException));
  12377. Exceptions.InvalidStateError = InvalidStateError;
  12378. var NotSupportedError = /** @class */ (function (_super) {
  12379. tslib_1.__extends(NotSupportedError, _super);
  12380. function NotSupportedError(message) {
  12381. var _this = _super.call(this, 3, "NOT_SUPPORTED_ERROR", message) || this;
  12382. _this.type = Enums_1.TypeStrings.NotSupportedError;
  12383. return _this;
  12384. }
  12385. return NotSupportedError;
  12386. }(LegacyException));
  12387. Exceptions.NotSupportedError = NotSupportedError;
  12388. // 4 was GetDescriptionError, which was deprecated and now removed
  12389. var RenegotiationError = /** @class */ (function (_super) {
  12390. tslib_1.__extends(RenegotiationError, _super);
  12391. function RenegotiationError(message) {
  12392. var _this = _super.call(this, 5, "RENEGOTIATION_ERROR", message) || this;
  12393. _this.type = Enums_1.TypeStrings.RenegotiationError;
  12394. return _this;
  12395. }
  12396. return RenegotiationError;
  12397. }(LegacyException));
  12398. Exceptions.RenegotiationError = RenegotiationError;
  12399. var MethodParameterError = /** @class */ (function (_super) {
  12400. tslib_1.__extends(MethodParameterError, _super);
  12401. function MethodParameterError(method, parameter, value) {
  12402. var _this = _super.call(this, 6, "METHOD_PARAMETER_ERROR", (!value) ?
  12403. "Missing parameter: " + parameter :
  12404. "Invalid value " + JSON.stringify(value) + " for parameter '" + parameter + "'") || this;
  12405. _this.type = Enums_1.TypeStrings.MethodParameterError;
  12406. _this.method = method;
  12407. _this.parameter = parameter;
  12408. _this.value = value;
  12409. return _this;
  12410. }
  12411. return MethodParameterError;
  12412. }(LegacyException));
  12413. Exceptions.MethodParameterError = MethodParameterError;
  12414. // 7 was TransportError, which was replaced
  12415. var SessionDescriptionHandlerError = /** @class */ (function (_super) {
  12416. tslib_1.__extends(SessionDescriptionHandlerError, _super);
  12417. function SessionDescriptionHandlerError(method, error, message) {
  12418. var _this = _super.call(this, 8, "SESSION_DESCRIPTION_HANDLER_ERROR", message || "Error with Session Description Handler") || this;
  12419. _this.type = Enums_1.TypeStrings.SessionDescriptionHandlerError;
  12420. _this.method = method;
  12421. _this.error = error;
  12422. return _this;
  12423. }
  12424. return SessionDescriptionHandlerError;
  12425. }(LegacyException));
  12426. Exceptions.SessionDescriptionHandlerError = SessionDescriptionHandlerError;
  12427. })(Exceptions = exports.Exceptions || (exports.Exceptions = {}));
  12428. /***/ }),
  12429. /* 85 */
  12430. /***/ (function(module, exports, __webpack_require__) {
  12431. "use strict";
  12432. Object.defineProperty(exports, "__esModule", { value: true });
  12433. var core_1 = __webpack_require__(2);
  12434. /**
  12435. * Extract and parse every header of a SIP message.
  12436. * @namespace
  12437. */
  12438. var Parser;
  12439. (function (Parser) {
  12440. function getHeader(data, headerStart) {
  12441. // 'start' position of the header.
  12442. var start = headerStart;
  12443. // 'end' position of the header.
  12444. var end = 0;
  12445. // 'partial end' position of the header.
  12446. var partialEnd = 0;
  12447. // End of message.
  12448. if (data.substring(start, start + 2).match(/(^\r\n)/)) {
  12449. return -2;
  12450. }
  12451. while (end === 0) {
  12452. // Partial End of Header.
  12453. partialEnd = data.indexOf("\r\n", start);
  12454. // 'indexOf' returns -1 if the value to be found never occurs.
  12455. if (partialEnd === -1) {
  12456. return partialEnd;
  12457. }
  12458. if (!data.substring(partialEnd + 2, partialEnd + 4).match(/(^\r\n)/) &&
  12459. data.charAt(partialEnd + 2).match(/(^\s+)/)) {
  12460. // Not the end of the message. Continue from the next position.
  12461. start = partialEnd + 2;
  12462. }
  12463. else {
  12464. end = partialEnd;
  12465. }
  12466. }
  12467. return end;
  12468. }
  12469. Parser.getHeader = getHeader;
  12470. function parseHeader(message, data, headerStart, headerEnd) {
  12471. var hcolonIndex = data.indexOf(":", headerStart);
  12472. var headerName = data.substring(headerStart, hcolonIndex).trim();
  12473. var headerValue = data.substring(hcolonIndex + 1, headerEnd).trim();
  12474. var parsed;
  12475. // If header-field is well-known, parse it.
  12476. switch (headerName.toLowerCase()) {
  12477. case "via":
  12478. case "v":
  12479. message.addHeader("via", headerValue);
  12480. if (message.getHeaders("via").length === 1) {
  12481. parsed = message.parseHeader("Via");
  12482. if (parsed) {
  12483. message.via = parsed;
  12484. message.viaBranch = parsed.branch;
  12485. }
  12486. }
  12487. else {
  12488. parsed = 0;
  12489. }
  12490. break;
  12491. case "from":
  12492. case "f":
  12493. message.setHeader("from", headerValue);
  12494. parsed = message.parseHeader("from");
  12495. if (parsed) {
  12496. message.from = parsed;
  12497. message.fromTag = parsed.getParam("tag");
  12498. }
  12499. break;
  12500. case "to":
  12501. case "t":
  12502. message.setHeader("to", headerValue);
  12503. parsed = message.parseHeader("to");
  12504. if (parsed) {
  12505. message.to = parsed;
  12506. message.toTag = parsed.getParam("tag");
  12507. }
  12508. break;
  12509. case "record-route":
  12510. parsed = core_1.Grammar.parse(headerValue, "Record_Route");
  12511. if (parsed === -1) {
  12512. parsed = undefined;
  12513. break;
  12514. }
  12515. for (var header in parsed) {
  12516. if (parsed[header]) {
  12517. message.addHeader("record-route", headerValue.substring(parsed[header].position, parsed[header].offset));
  12518. message.headers["Record-Route"][message.getHeaders("record-route").length - 1].parsed =
  12519. parsed[header].parsed;
  12520. }
  12521. }
  12522. break;
  12523. case "call-id":
  12524. case "i":
  12525. message.setHeader("call-id", headerValue);
  12526. parsed = message.parseHeader("call-id");
  12527. if (parsed) {
  12528. message.callId = headerValue;
  12529. }
  12530. break;
  12531. case "contact":
  12532. case "m":
  12533. parsed = core_1.Grammar.parse(headerValue, "Contact");
  12534. if (parsed === -1) {
  12535. parsed = undefined;
  12536. break;
  12537. }
  12538. if (!(parsed instanceof Array)) {
  12539. parsed = undefined;
  12540. break;
  12541. }
  12542. parsed.forEach(function (header) {
  12543. message.addHeader("contact", headerValue.substring(header.position, header.offset));
  12544. message.headers.Contact[message.getHeaders("contact").length - 1].parsed = header.parsed;
  12545. });
  12546. break;
  12547. case "content-length":
  12548. case "l":
  12549. message.setHeader("content-length", headerValue);
  12550. parsed = message.parseHeader("content-length");
  12551. break;
  12552. case "content-type":
  12553. case "c":
  12554. message.setHeader("content-type", headerValue);
  12555. parsed = message.parseHeader("content-type");
  12556. break;
  12557. case "cseq":
  12558. message.setHeader("cseq", headerValue);
  12559. parsed = message.parseHeader("cseq");
  12560. if (parsed) {
  12561. message.cseq = parsed.value;
  12562. }
  12563. if (message instanceof core_1.IncomingResponseMessage) {
  12564. message.method = parsed.method;
  12565. }
  12566. break;
  12567. case "max-forwards":
  12568. message.setHeader("max-forwards", headerValue);
  12569. parsed = message.parseHeader("max-forwards");
  12570. break;
  12571. case "www-authenticate":
  12572. message.setHeader("www-authenticate", headerValue);
  12573. parsed = message.parseHeader("www-authenticate");
  12574. break;
  12575. case "proxy-authenticate":
  12576. message.setHeader("proxy-authenticate", headerValue);
  12577. parsed = message.parseHeader("proxy-authenticate");
  12578. break;
  12579. case "refer-to":
  12580. case "r":
  12581. message.setHeader("refer-to", headerValue);
  12582. parsed = message.parseHeader("refer-to");
  12583. if (parsed) {
  12584. message.referTo = parsed;
  12585. }
  12586. break;
  12587. default:
  12588. // Do not parse this header.
  12589. message.addHeader(headerName.toLowerCase(), headerValue);
  12590. parsed = 0;
  12591. }
  12592. if (parsed === undefined) {
  12593. return {
  12594. error: "error parsing header '" + headerName + "'"
  12595. };
  12596. }
  12597. else {
  12598. return true;
  12599. }
  12600. }
  12601. Parser.parseHeader = parseHeader;
  12602. /** Parse SIP Message
  12603. * @function
  12604. * @param {String} message SIP message.
  12605. * @param {Object} logger object.
  12606. * @returns {SIP.IncomingRequest|SIP.IncomingResponse|undefined}
  12607. */
  12608. function parseMessage(data, logger) {
  12609. var headerStart = 0;
  12610. var headerEnd = data.indexOf("\r\n");
  12611. if (headerEnd === -1) {
  12612. logger.warn("no CRLF found, not a SIP message, discarded");
  12613. return;
  12614. }
  12615. // Parse first line. Check if it is a Request or a Reply.
  12616. var firstLine = data.substring(0, headerEnd);
  12617. var parsed = core_1.Grammar.parse(firstLine, "Request_Response");
  12618. var message;
  12619. if (parsed === -1) {
  12620. logger.warn('error parsing first line of SIP message: "' + firstLine + '"');
  12621. return;
  12622. }
  12623. else if (!parsed.status_code) {
  12624. message = new core_1.IncomingRequestMessage();
  12625. message.method = parsed.method;
  12626. message.ruri = parsed.uri;
  12627. }
  12628. else {
  12629. message = new core_1.IncomingResponseMessage();
  12630. message.statusCode = parsed.status_code;
  12631. message.reasonPhrase = parsed.reason_phrase;
  12632. }
  12633. message.data = data;
  12634. headerStart = headerEnd + 2;
  12635. /* Loop over every line in data. Detect the end of each header and parse
  12636. * it or simply add to the headers collection.
  12637. */
  12638. var bodyStart;
  12639. while (true) {
  12640. headerEnd = getHeader(data, headerStart);
  12641. // The SIP message has normally finished.
  12642. if (headerEnd === -2) {
  12643. bodyStart = headerStart + 2;
  12644. break;
  12645. }
  12646. else if (headerEnd === -1) {
  12647. // data.indexOf returned -1 due to a malformed message.
  12648. logger.error("malformed message");
  12649. return;
  12650. }
  12651. var parsedHeader = parseHeader(message, data, headerStart, headerEnd);
  12652. if (parsedHeader !== true) {
  12653. logger.error(parsed.error);
  12654. return;
  12655. }
  12656. headerStart = headerEnd + 2;
  12657. }
  12658. /* RFC3261 18.3.
  12659. * If there are additional bytes in the transport packet
  12660. * beyond the end of the body, they MUST be discarded.
  12661. */
  12662. if (message.hasHeader("content-length")) {
  12663. message.body = data.substr(bodyStart, Number(message.getHeader("content-length")));
  12664. }
  12665. else {
  12666. message.body = data.substring(bodyStart);
  12667. }
  12668. return message;
  12669. }
  12670. Parser.parseMessage = parseMessage;
  12671. })(Parser = exports.Parser || (exports.Parser = {}));
  12672. /***/ }),
  12673. /* 86 */
  12674. /***/ (function(module, exports, __webpack_require__) {
  12675. "use strict";
  12676. Object.defineProperty(exports, "__esModule", { value: true });
  12677. var tslib_1 = __webpack_require__(1);
  12678. var ClientContext_1 = __webpack_require__(79);
  12679. var Constants_1 = __webpack_require__(80);
  12680. var core_1 = __webpack_require__(2);
  12681. var Enums_1 = __webpack_require__(82);
  12682. var Exceptions_1 = __webpack_require__(84);
  12683. var Utils_1 = __webpack_require__(83);
  12684. /**
  12685. * SIP Publish (SIP Extension for Event State Publication RFC3903)
  12686. * @class Class creating a SIP PublishContext.
  12687. */
  12688. var PublishContext = /** @class */ (function (_super) {
  12689. tslib_1.__extends(PublishContext, _super);
  12690. function PublishContext(ua, target, event, options) {
  12691. if (options === void 0) { options = {}; }
  12692. var _this = this;
  12693. options.extraHeaders = (options.extraHeaders || []).slice();
  12694. options.contentType = (options.contentType || "text/plain");
  12695. if (typeof options.expires !== "number" || (options.expires % 1) !== 0) {
  12696. options.expires = 3600;
  12697. }
  12698. else {
  12699. options.expires = Number(options.expires);
  12700. }
  12701. if (typeof (options.unpublishOnClose) !== "boolean") {
  12702. options.unpublishOnClose = true;
  12703. }
  12704. if (target === undefined || target === null || target === "") {
  12705. throw new Exceptions_1.Exceptions.MethodParameterError("Publish", "Target", target);
  12706. }
  12707. else {
  12708. target = ua.normalizeTarget(target);
  12709. if (target === undefined) {
  12710. throw new Exceptions_1.Exceptions.MethodParameterError("Publish", "Target", target);
  12711. }
  12712. }
  12713. _this = _super.call(this, ua, Constants_1.C.PUBLISH, target, options) || this;
  12714. _this.type = Enums_1.TypeStrings.PublishContext;
  12715. _this.options = options;
  12716. _this.target = target;
  12717. if (event === undefined || event === null || event === "") {
  12718. throw new Exceptions_1.Exceptions.MethodParameterError("Publish", "Event", event);
  12719. }
  12720. else {
  12721. _this.event = event;
  12722. }
  12723. _this.logger = ua.getLogger("sip.publish");
  12724. _this.pubRequestExpires = _this.options.expires;
  12725. return _this;
  12726. }
  12727. /**
  12728. * Publish
  12729. * @param {string} Event body to publish, optional
  12730. */
  12731. PublishContext.prototype.publish = function (body) {
  12732. // Clean up before the run
  12733. if (this.publishRefreshTimer) {
  12734. clearTimeout(this.publishRefreshTimer);
  12735. this.publishRefreshTimer = undefined;
  12736. }
  12737. // is Inital or Modify request
  12738. this.options.body = body;
  12739. this.pubRequestBody = this.options.body;
  12740. if (this.pubRequestExpires === 0) {
  12741. // This is Initial request after unpublish
  12742. this.pubRequestExpires = this.options.expires;
  12743. this.pubRequestEtag = undefined;
  12744. }
  12745. if (!(this.ua.publishers[this.target.toString() + ":" + this.event])) {
  12746. this.ua.publishers[this.target.toString() + ":" + this.event] = this;
  12747. }
  12748. this.sendPublishRequest();
  12749. };
  12750. /**
  12751. * Unpublish
  12752. */
  12753. PublishContext.prototype.unpublish = function () {
  12754. // Clean up before the run
  12755. if (this.publishRefreshTimer) {
  12756. clearTimeout(this.publishRefreshTimer);
  12757. this.publishRefreshTimer = undefined;
  12758. }
  12759. this.pubRequestBody = undefined;
  12760. this.pubRequestExpires = 0;
  12761. if (this.pubRequestEtag !== undefined) {
  12762. this.sendPublishRequest();
  12763. }
  12764. };
  12765. /**
  12766. * Close
  12767. */
  12768. PublishContext.prototype.close = function () {
  12769. // Send unpublish, if requested
  12770. if (this.options.unpublishOnClose) {
  12771. this.unpublish();
  12772. }
  12773. else {
  12774. if (this.publishRefreshTimer) {
  12775. clearTimeout(this.publishRefreshTimer);
  12776. this.publishRefreshTimer = undefined;
  12777. }
  12778. this.pubRequestBody = undefined;
  12779. this.pubRequestExpires = 0;
  12780. this.pubRequestEtag = undefined;
  12781. }
  12782. if (this.ua.publishers[this.target.toString() + ":" + this.event]) {
  12783. delete this.ua.publishers[this.target.toString() + ":" + this.event];
  12784. }
  12785. };
  12786. PublishContext.prototype.onRequestTimeout = function () {
  12787. _super.prototype.onRequestTimeout.call(this);
  12788. this.emit("unpublished", undefined, Constants_1.C.causes.REQUEST_TIMEOUT);
  12789. };
  12790. PublishContext.prototype.onTransportError = function () {
  12791. _super.prototype.onTransportError.call(this);
  12792. this.emit("unpublished", undefined, Constants_1.C.causes.CONNECTION_ERROR);
  12793. };
  12794. PublishContext.prototype.receiveResponse = function (response) {
  12795. var _this = this;
  12796. var statusCode = response.statusCode || 0;
  12797. var cause = Utils_1.Utils.getReasonPhrase(statusCode);
  12798. switch (true) {
  12799. case /^1[0-9]{2}$/.test(statusCode.toString()):
  12800. this.emit("progress", response, cause);
  12801. break;
  12802. case /^2[0-9]{2}$/.test(statusCode.toString()):
  12803. // Set SIP-Etag
  12804. if (response.hasHeader("SIP-ETag")) {
  12805. this.pubRequestEtag = response.getHeader("SIP-ETag");
  12806. }
  12807. else {
  12808. this.logger.warn("SIP-ETag header missing in a 200-class response to PUBLISH");
  12809. }
  12810. // Update Expire
  12811. if (response.hasHeader("Expires")) {
  12812. var expires = Number(response.getHeader("Expires"));
  12813. if (typeof expires === "number" && expires >= 0 && expires <= this.pubRequestExpires) {
  12814. this.pubRequestExpires = expires;
  12815. }
  12816. else {
  12817. this.logger.warn("Bad Expires header in a 200-class response to PUBLISH");
  12818. }
  12819. }
  12820. else {
  12821. this.logger.warn("Expires header missing in a 200-class response to PUBLISH");
  12822. }
  12823. if (this.pubRequestExpires !== 0) {
  12824. // Schedule refresh
  12825. this.publishRefreshTimer = setTimeout(function () { return _this.refreshRequest(); }, this.pubRequestExpires * 900);
  12826. this.emit("published", response, cause);
  12827. }
  12828. else {
  12829. this.emit("unpublished", response, cause);
  12830. }
  12831. break;
  12832. case /^412$/.test(statusCode.toString()):
  12833. // 412 code means no matching ETag - possibly the PUBLISH expired
  12834. // Resubmit as new request, if the current request is not a "remove"
  12835. if (this.pubRequestEtag !== undefined && this.pubRequestExpires !== 0) {
  12836. this.logger.warn("412 response to PUBLISH, recovering");
  12837. this.pubRequestEtag = undefined;
  12838. this.emit("progress", response, cause);
  12839. this.publish(this.options.body);
  12840. }
  12841. else {
  12842. this.logger.warn("412 response to PUBLISH, recovery failed");
  12843. this.pubRequestExpires = 0;
  12844. this.emit("failed", response, cause);
  12845. this.emit("unpublished", response, cause);
  12846. }
  12847. break;
  12848. case /^423$/.test(statusCode.toString()):
  12849. // 423 code means we need to adjust the Expires interval up
  12850. if (this.pubRequestExpires !== 0 && response.hasHeader("Min-Expires")) {
  12851. var minExpires = Number(response.getHeader("Min-Expires"));
  12852. if (typeof minExpires === "number" || minExpires > this.pubRequestExpires) {
  12853. this.logger.warn("423 code in response to PUBLISH, adjusting the Expires value and trying to recover");
  12854. this.pubRequestExpires = minExpires;
  12855. this.emit("progress", response, cause);
  12856. this.publish(this.options.body);
  12857. }
  12858. else {
  12859. this.logger.warn("Bad 423 response Min-Expires header received for PUBLISH");
  12860. this.pubRequestExpires = 0;
  12861. this.emit("failed", response, cause);
  12862. this.emit("unpublished", response, cause);
  12863. }
  12864. }
  12865. else {
  12866. this.logger.warn("423 response to PUBLISH, recovery failed");
  12867. this.pubRequestExpires = 0;
  12868. this.emit("failed", response, cause);
  12869. this.emit("unpublished", response, cause);
  12870. }
  12871. break;
  12872. default:
  12873. this.pubRequestExpires = 0;
  12874. this.emit("failed", response, cause);
  12875. this.emit("unpublished", response, cause);
  12876. break;
  12877. }
  12878. // Do the cleanup
  12879. if (this.pubRequestExpires === 0) {
  12880. if (this.publishRefreshTimer) {
  12881. clearTimeout(this.publishRefreshTimer);
  12882. this.publishRefreshTimer = undefined;
  12883. }
  12884. this.pubRequestBody = undefined;
  12885. this.pubRequestEtag = undefined;
  12886. }
  12887. };
  12888. PublishContext.prototype.send = function () {
  12889. var _this = this;
  12890. this.ua.userAgentCore.publish(this.request, {
  12891. onAccept: function (response) { return _this.receiveResponse(response.message); },
  12892. onProgress: function (response) { return _this.receiveResponse(response.message); },
  12893. onRedirect: function (response) { return _this.receiveResponse(response.message); },
  12894. onReject: function (response) { return _this.receiveResponse(response.message); },
  12895. onTrying: function (response) { return _this.receiveResponse(response.message); }
  12896. });
  12897. return this;
  12898. };
  12899. PublishContext.prototype.refreshRequest = function () {
  12900. // Clean up before the run
  12901. if (this.publishRefreshTimer) {
  12902. clearTimeout(this.publishRefreshTimer);
  12903. this.publishRefreshTimer = undefined;
  12904. }
  12905. // This is Refresh request
  12906. this.pubRequestBody = undefined;
  12907. if (this.pubRequestEtag === undefined) {
  12908. // Request not valid
  12909. throw new Exceptions_1.Exceptions.MethodParameterError("Publish", "Body", undefined);
  12910. }
  12911. if (this.pubRequestExpires === 0) {
  12912. // Request not valid
  12913. throw new Exceptions_1.Exceptions.MethodParameterError("Publish", "Expire", this.pubRequestExpires);
  12914. }
  12915. this.sendPublishRequest();
  12916. };
  12917. PublishContext.prototype.sendPublishRequest = function () {
  12918. var reqOptions = Object.create(this.options || Object.prototype);
  12919. reqOptions.extraHeaders = (this.options.extraHeaders || []).slice();
  12920. reqOptions.extraHeaders.push("Event: " + this.event);
  12921. reqOptions.extraHeaders.push("Expires: " + this.pubRequestExpires);
  12922. if (this.pubRequestEtag !== undefined) {
  12923. reqOptions.extraHeaders.push("SIP-If-Match: " + this.pubRequestEtag);
  12924. }
  12925. var ruri = this.target instanceof core_1.URI ? this.target : this.ua.normalizeTarget(this.target);
  12926. if (!ruri) {
  12927. throw new Error("ruri undefined.");
  12928. }
  12929. var params = this.options.params || {};
  12930. var bodyObj;
  12931. if (this.pubRequestBody !== undefined) {
  12932. bodyObj = {
  12933. body: this.pubRequestBody,
  12934. contentType: this.options.contentType
  12935. };
  12936. }
  12937. var body;
  12938. if (bodyObj) {
  12939. body = Utils_1.Utils.fromBodyObj(bodyObj);
  12940. }
  12941. this.request = this.ua.userAgentCore.makeOutgoingRequestMessage(Constants_1.C.PUBLISH, ruri, params.fromUri ? params.fromUri : this.ua.userAgentCore.configuration.aor, params.toUri ? params.toUri : this.target, params, reqOptions.extraHeaders, body);
  12942. this.send();
  12943. };
  12944. return PublishContext;
  12945. }(ClientContext_1.ClientContext));
  12946. exports.PublishContext = PublishContext;
  12947. /***/ }),
  12948. /* 87 */
  12949. /***/ (function(module, exports, __webpack_require__) {
  12950. "use strict";
  12951. Object.defineProperty(exports, "__esModule", { value: true });
  12952. var tslib_1 = __webpack_require__(1);
  12953. var ClientContext_1 = __webpack_require__(79);
  12954. var Constants_1 = __webpack_require__(80);
  12955. var core_1 = __webpack_require__(2);
  12956. var Enums_1 = __webpack_require__(82);
  12957. var Exceptions_1 = __webpack_require__(84);
  12958. var ServerContext_1 = __webpack_require__(88);
  12959. // tslint:disable-next-line:max-classes-per-file
  12960. var ReferClientContext = /** @class */ (function (_super) {
  12961. tslib_1.__extends(ReferClientContext, _super);
  12962. function ReferClientContext(ua, applicant, target, options) {
  12963. if (options === void 0) { options = {}; }
  12964. var _this = this;
  12965. if (ua === undefined || applicant === undefined || target === undefined) {
  12966. throw new TypeError("Not enough arguments");
  12967. }
  12968. _this = _super.call(this, ua, Constants_1.C.REFER, applicant.remoteIdentity.uri.toString(), options) || this;
  12969. _this.type = Enums_1.TypeStrings.ReferClientContext;
  12970. _this.options = options;
  12971. _this.extraHeaders = (_this.options.extraHeaders || []).slice();
  12972. _this.applicant = applicant;
  12973. _this.target = _this.initReferTo(target);
  12974. if (_this.ua) {
  12975. _this.extraHeaders.push("Referred-By: <" + _this.ua.configuration.uri + ">");
  12976. }
  12977. // TODO: Check that this is correct isc/icc
  12978. _this.extraHeaders.push("Contact: " + applicant.contact);
  12979. // this is UA.C.ALLOWED_METHODS, removed to get around circular dependency
  12980. _this.extraHeaders.push("Allow: " + [
  12981. "ACK",
  12982. "CANCEL",
  12983. "INVITE",
  12984. "MESSAGE",
  12985. "BYE",
  12986. "OPTIONS",
  12987. "INFO",
  12988. "NOTIFY",
  12989. "REFER"
  12990. ].toString());
  12991. _this.extraHeaders.push("Refer-To: " + _this.target);
  12992. _this.errorListener = _this.onTransportError.bind(_this);
  12993. if (ua.transport) {
  12994. ua.transport.on("transportError", _this.errorListener);
  12995. }
  12996. return _this;
  12997. }
  12998. ReferClientContext.prototype.refer = function (options) {
  12999. var _this = this;
  13000. if (options === void 0) { options = {}; }
  13001. var extraHeaders = (this.extraHeaders || []).slice();
  13002. if (options.extraHeaders) {
  13003. extraHeaders.concat(options.extraHeaders);
  13004. }
  13005. this.applicant.sendRequest(Constants_1.C.REFER, {
  13006. extraHeaders: this.extraHeaders,
  13007. receiveResponse: function (response) {
  13008. var statusCode = response && response.statusCode ? response.statusCode.toString() : "";
  13009. if (/^1[0-9]{2}$/.test(statusCode)) {
  13010. _this.emit("referRequestProgress", _this);
  13011. }
  13012. else if (/^2[0-9]{2}$/.test(statusCode)) {
  13013. _this.emit("referRequestAccepted", _this);
  13014. }
  13015. else if (/^[4-6][0-9]{2}$/.test(statusCode)) {
  13016. _this.emit("referRequestRejected", _this);
  13017. }
  13018. if (options.receiveResponse) {
  13019. options.receiveResponse(response);
  13020. }
  13021. }
  13022. });
  13023. return this;
  13024. };
  13025. ReferClientContext.prototype.receiveNotify = function (request) {
  13026. // If we can correctly handle this, then we need to send a 200 OK!
  13027. var contentType = request.message.hasHeader("Content-Type") ?
  13028. request.message.getHeader("Content-Type") : undefined;
  13029. if (contentType && contentType.search(/^message\/sipfrag/) !== -1) {
  13030. var messageBody = core_1.Grammar.parse(request.message.body, "sipfrag");
  13031. if (messageBody === -1) {
  13032. request.reject({
  13033. statusCode: 489,
  13034. reasonPhrase: "Bad Event"
  13035. });
  13036. return;
  13037. }
  13038. switch (true) {
  13039. case (/^1[0-9]{2}$/.test(messageBody.status_code)):
  13040. this.emit("referProgress", this);
  13041. break;
  13042. case (/^2[0-9]{2}$/.test(messageBody.status_code)):
  13043. this.emit("referAccepted", this);
  13044. if (!this.options.activeAfterTransfer && this.applicant.terminate) {
  13045. this.applicant.terminate();
  13046. }
  13047. break;
  13048. default:
  13049. this.emit("referRejected", this);
  13050. break;
  13051. }
  13052. request.accept();
  13053. this.emit("notify", request.message);
  13054. return;
  13055. }
  13056. request.reject({
  13057. statusCode: 489,
  13058. reasonPhrase: "Bad Event"
  13059. });
  13060. };
  13061. ReferClientContext.prototype.initReferTo = function (target) {
  13062. var stringOrURI;
  13063. if (typeof target === "string") {
  13064. // REFER without Replaces (Blind Transfer)
  13065. var targetString = core_1.Grammar.parse(target, "Refer_To");
  13066. stringOrURI = targetString && targetString.uri ? targetString.uri : target;
  13067. // Check target validity
  13068. var targetUri = this.ua.normalizeTarget(target);
  13069. if (!targetUri) {
  13070. throw new TypeError("Invalid target: " + target);
  13071. }
  13072. stringOrURI = targetUri;
  13073. }
  13074. else {
  13075. // REFER with Replaces (Attended Transfer)
  13076. if (!target.session) {
  13077. throw new Error("Session undefined.");
  13078. }
  13079. var displayName = target.remoteIdentity.friendlyName;
  13080. var remoteTarget = target.session.remoteTarget.toString();
  13081. var callId = target.session.callId;
  13082. var remoteTag = target.session.remoteTag;
  13083. var localTag = target.session.localTag;
  13084. var replaces = encodeURIComponent(callId + ";to-tag=" + remoteTag + ";from-tag=" + localTag);
  13085. stringOrURI = "\"" + displayName + "\" <" + remoteTarget + "?Replaces=" + replaces + ">";
  13086. }
  13087. return stringOrURI;
  13088. };
  13089. return ReferClientContext;
  13090. }(ClientContext_1.ClientContext));
  13091. exports.ReferClientContext = ReferClientContext;
  13092. // tslint:disable-next-line:max-classes-per-file
  13093. var ReferServerContext = /** @class */ (function (_super) {
  13094. tslib_1.__extends(ReferServerContext, _super);
  13095. function ReferServerContext(ua, incomingRequest, session) {
  13096. var _this = _super.call(this, ua, incomingRequest) || this;
  13097. _this.session = session;
  13098. _this.type = Enums_1.TypeStrings.ReferServerContext;
  13099. _this.ua = ua;
  13100. _this.status = Enums_1.SessionStatus.STATUS_INVITE_RECEIVED;
  13101. _this.fromTag = _this.request.fromTag;
  13102. _this.id = _this.request.callId + _this.fromTag;
  13103. _this.contact = _this.ua.contact.toString();
  13104. _this.logger = ua.getLogger("sip.referservercontext", _this.id);
  13105. // Needed to send the NOTIFY's
  13106. _this.cseq = Math.floor(Math.random() * 10000);
  13107. _this.callId = _this.request.callId;
  13108. _this.fromUri = _this.request.to.uri;
  13109. _this.fromTag = _this.request.to.parameters.tag;
  13110. _this.remoteTarget = _this.request.headers.Contact[0].parsed.uri;
  13111. _this.toUri = _this.request.from.uri;
  13112. _this.toTag = _this.request.fromTag;
  13113. _this.routeSet = _this.request.getHeaders("record-route");
  13114. // RFC 3515 2.4.1
  13115. if (!_this.request.hasHeader("refer-to")) {
  13116. _this.logger.warn("Invalid REFER packet. A refer-to header is required. Rejecting refer.");
  13117. _this.reject();
  13118. return _this;
  13119. }
  13120. _this.referTo = _this.request.parseHeader("refer-to");
  13121. // TODO: Must set expiration timer and send 202 if there is no response by then
  13122. _this.referredSession = _this.ua.findSession(_this.request);
  13123. if (_this.request.hasHeader("referred-by")) {
  13124. _this.referredBy = _this.request.getHeader("referred-by");
  13125. }
  13126. if (_this.referTo.uri.hasHeader("replaces")) {
  13127. _this.replaces = _this.referTo.uri.getHeader("replaces");
  13128. }
  13129. _this.errorListener = _this.onTransportError.bind(_this);
  13130. if (ua.transport) {
  13131. ua.transport.on("transportError", _this.errorListener);
  13132. }
  13133. _this.status = Enums_1.SessionStatus.STATUS_WAITING_FOR_ANSWER;
  13134. return _this;
  13135. }
  13136. ReferServerContext.prototype.progress = function () {
  13137. if (this.status !== Enums_1.SessionStatus.STATUS_WAITING_FOR_ANSWER) {
  13138. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  13139. }
  13140. this.incomingRequest.trying();
  13141. };
  13142. ReferServerContext.prototype.reject = function (options) {
  13143. if (options === void 0) { options = {}; }
  13144. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  13145. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  13146. }
  13147. this.logger.log("Rejecting refer");
  13148. this.status = Enums_1.SessionStatus.STATUS_TERMINATED;
  13149. _super.prototype.reject.call(this, options);
  13150. this.emit("referRequestRejected", this);
  13151. };
  13152. ReferServerContext.prototype.accept = function (options, modifiers) {
  13153. var _this = this;
  13154. if (options === void 0) { options = {}; }
  13155. if (this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_ANSWER) {
  13156. this.status = Enums_1.SessionStatus.STATUS_ANSWERED;
  13157. }
  13158. else {
  13159. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  13160. }
  13161. this.incomingRequest.accept({
  13162. statusCode: 202,
  13163. reasonPhrase: "Accepted"
  13164. });
  13165. this.emit("referRequestAccepted", this);
  13166. if (options.followRefer) {
  13167. this.logger.log("Accepted refer, attempting to automatically follow it");
  13168. var target = this.referTo.uri;
  13169. if (!target.scheme || !target.scheme.match("^sips?$")) {
  13170. this.logger.error("SIP.js can only automatically follow SIP refer target");
  13171. this.reject();
  13172. return;
  13173. }
  13174. var inviteOptions = options.inviteOptions || {};
  13175. var extraHeaders = (inviteOptions.extraHeaders || []).slice();
  13176. if (this.replaces) {
  13177. // decodeURIComponent is a holdover from 2c086eb4. Not sure that it is actually necessary
  13178. extraHeaders.push("Replaces: " + decodeURIComponent(this.replaces));
  13179. }
  13180. if (this.referredBy) {
  13181. extraHeaders.push("Referred-By: " + this.referredBy);
  13182. }
  13183. inviteOptions.extraHeaders = extraHeaders;
  13184. target.clearHeaders();
  13185. this.targetSession = this.ua.invite(target.toString(), inviteOptions, modifiers);
  13186. this.emit("referInviteSent", this);
  13187. if (this.targetSession) {
  13188. this.targetSession.once("progress", function (response) {
  13189. var statusCode = response.statusCode || 100;
  13190. var reasonPhrase = response.reasonPhrase;
  13191. _this.sendNotify(("SIP/2.0 " + statusCode + " " + reasonPhrase).trim());
  13192. _this.emit("referProgress", _this);
  13193. if (_this.referredSession) {
  13194. _this.referredSession.emit("referProgress", _this);
  13195. }
  13196. });
  13197. this.targetSession.once("accepted", function () {
  13198. _this.logger.log("Successfully followed the refer");
  13199. _this.sendNotify("SIP/2.0 200 OK");
  13200. _this.emit("referAccepted", _this);
  13201. if (_this.referredSession) {
  13202. _this.referredSession.emit("referAccepted", _this);
  13203. }
  13204. });
  13205. var referFailed = function (response) {
  13206. if (_this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  13207. return; // No throw here because it is possible this gets called multiple times
  13208. }
  13209. _this.logger.log("Refer was not successful. Resuming session");
  13210. if (response && response.statusCode === 429) {
  13211. _this.logger.log("Alerting referrer that identity is required.");
  13212. _this.sendNotify("SIP/2.0 429 Provide Referrer Identity");
  13213. return;
  13214. }
  13215. _this.sendNotify("SIP/2.0 603 Declined");
  13216. // Must change the status after sending the final Notify or it will not send due to check
  13217. _this.status = Enums_1.SessionStatus.STATUS_TERMINATED;
  13218. _this.emit("referRejected", _this);
  13219. if (_this.referredSession) {
  13220. _this.referredSession.emit("referRejected");
  13221. }
  13222. };
  13223. this.targetSession.once("rejected", referFailed);
  13224. this.targetSession.once("failed", referFailed);
  13225. }
  13226. }
  13227. else {
  13228. this.logger.log("Accepted refer, but did not automatically follow it");
  13229. this.sendNotify("SIP/2.0 200 OK");
  13230. this.emit("referAccepted", this);
  13231. if (this.referredSession) {
  13232. this.referredSession.emit("referAccepted", this);
  13233. }
  13234. }
  13235. };
  13236. ReferServerContext.prototype.sendNotify = function (bodyStr) {
  13237. // FIXME: Ported this. Clean it up. Session knows its state.
  13238. if (this.status !== Enums_1.SessionStatus.STATUS_ANSWERED) {
  13239. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  13240. }
  13241. if (core_1.Grammar.parse(bodyStr, "sipfrag") === -1) {
  13242. throw new Error("sipfrag body is required to send notify for refer");
  13243. }
  13244. var body = {
  13245. contentDisposition: "render",
  13246. contentType: "message/sipfrag",
  13247. content: bodyStr
  13248. };
  13249. // NOTIFY requests sent in same dialog as in dialog REFER.
  13250. if (this.session) {
  13251. this.session.notify(undefined, {
  13252. extraHeaders: [
  13253. "Event: refer",
  13254. "Subscription-State: terminated",
  13255. ],
  13256. body: body
  13257. });
  13258. return;
  13259. }
  13260. // The implicit subscription created by a REFER is the same as a
  13261. // subscription created with a SUBSCRIBE request. The agent issuing the
  13262. // REFER can terminate this subscription prematurely by unsubscribing
  13263. // using the mechanisms described in [2]. Terminating a subscription,
  13264. // either by explicitly unsubscribing or rejecting NOTIFY, is not an
  13265. // indication that the referenced request should be withdrawn or
  13266. // abandoned.
  13267. // https://tools.ietf.org/html/rfc3515#section-2.4.4
  13268. // NOTIFY requests sent in new dialog for out of dialog REFER.
  13269. // FIXME: TODO: This should be done in a subscribe dialog to satisfy the above.
  13270. var request = this.ua.userAgentCore.makeOutgoingRequestMessage(Constants_1.C.NOTIFY, this.remoteTarget, this.fromUri, this.toUri, {
  13271. cseq: this.cseq += 1,
  13272. callId: this.callId,
  13273. fromTag: this.fromTag,
  13274. toTag: this.toTag,
  13275. routeSet: this.routeSet
  13276. }, [
  13277. "Event: refer",
  13278. "Subscription-State: terminated",
  13279. "Content-Type: message/sipfrag"
  13280. ], body);
  13281. var transport = this.ua.transport;
  13282. if (!transport) {
  13283. throw new Error("Transport undefined.");
  13284. }
  13285. var user = {
  13286. loggerFactory: this.ua.getLoggerFactory()
  13287. };
  13288. var nic = new core_1.NonInviteClientTransaction(request, transport, user);
  13289. };
  13290. ReferServerContext.prototype.on = function (name, callback) { return _super.prototype.on.call(this, name, callback); };
  13291. return ReferServerContext;
  13292. }(ServerContext_1.ServerContext));
  13293. exports.ReferServerContext = ReferServerContext;
  13294. /***/ }),
  13295. /* 88 */
  13296. /***/ (function(module, exports, __webpack_require__) {
  13297. "use strict";
  13298. Object.defineProperty(exports, "__esModule", { value: true });
  13299. var tslib_1 = __webpack_require__(1);
  13300. var events_1 = __webpack_require__(30);
  13301. var Constants_1 = __webpack_require__(80);
  13302. var core_1 = __webpack_require__(2);
  13303. var Enums_1 = __webpack_require__(82);
  13304. var Utils_1 = __webpack_require__(83);
  13305. var ServerContext = /** @class */ (function (_super) {
  13306. tslib_1.__extends(ServerContext, _super);
  13307. function ServerContext(ua, incomingRequest) {
  13308. var _this = _super.call(this) || this;
  13309. _this.incomingRequest = incomingRequest;
  13310. _this.data = {};
  13311. ServerContext.initializer(_this, ua, incomingRequest);
  13312. return _this;
  13313. }
  13314. // hack to get around our multiple inheritance issues
  13315. ServerContext.initializer = function (objectToConstruct, ua, incomingRequest) {
  13316. var request = incomingRequest.message;
  13317. objectToConstruct.type = Enums_1.TypeStrings.ServerContext;
  13318. objectToConstruct.ua = ua;
  13319. objectToConstruct.logger = ua.getLogger("sip.servercontext");
  13320. objectToConstruct.request = request;
  13321. if (request.body) {
  13322. objectToConstruct.body = request.body;
  13323. }
  13324. if (request.hasHeader("Content-Type")) {
  13325. objectToConstruct.contentType = request.getHeader("Content-Type");
  13326. }
  13327. objectToConstruct.method = request.method;
  13328. objectToConstruct.localIdentity = request.to;
  13329. objectToConstruct.remoteIdentity = request.from;
  13330. var hasAssertedIdentity = request.hasHeader("P-Asserted-Identity");
  13331. if (hasAssertedIdentity) {
  13332. var assertedIdentity = request.getHeader("P-Asserted-Identity");
  13333. if (assertedIdentity) {
  13334. objectToConstruct.assertedIdentity = core_1.Grammar.nameAddrHeaderParse(assertedIdentity);
  13335. }
  13336. }
  13337. };
  13338. ServerContext.prototype.progress = function (options) {
  13339. if (options === void 0) { options = {}; }
  13340. options.statusCode = options.statusCode || 180;
  13341. options.minCode = 100;
  13342. options.maxCode = 199;
  13343. options.events = ["progress"];
  13344. return this.reply(options);
  13345. };
  13346. ServerContext.prototype.accept = function (options) {
  13347. if (options === void 0) { options = {}; }
  13348. options.statusCode = options.statusCode || 200;
  13349. options.minCode = 200;
  13350. options.maxCode = 299;
  13351. options.events = ["accepted"];
  13352. return this.reply(options);
  13353. };
  13354. ServerContext.prototype.reject = function (options) {
  13355. if (options === void 0) { options = {}; }
  13356. options.statusCode = options.statusCode || 480;
  13357. options.minCode = 300;
  13358. options.maxCode = 699;
  13359. options.events = ["rejected", "failed"];
  13360. return this.reply(options);
  13361. };
  13362. ServerContext.prototype.reply = function (options) {
  13363. var _this = this;
  13364. if (options === void 0) { options = {}; }
  13365. var statusCode = options.statusCode || 100;
  13366. var minCode = options.minCode || 100;
  13367. var maxCode = options.maxCode || 699;
  13368. var reasonPhrase = Utils_1.Utils.getReasonPhrase(statusCode, options.reasonPhrase);
  13369. var extraHeaders = options.extraHeaders || [];
  13370. var body = options.body ? core_1.fromBodyLegacy(options.body) : undefined;
  13371. var events = options.events || [];
  13372. if (statusCode < minCode || statusCode > maxCode) {
  13373. throw new TypeError("Invalid statusCode: " + statusCode);
  13374. }
  13375. var responseOptions = {
  13376. statusCode: statusCode,
  13377. reasonPhrase: reasonPhrase,
  13378. extraHeaders: extraHeaders,
  13379. body: body
  13380. };
  13381. var response;
  13382. var statusCodeString = statusCode.toString();
  13383. switch (true) {
  13384. case /^100$/.test(statusCodeString):
  13385. response = this.incomingRequest.trying(responseOptions).message;
  13386. break;
  13387. case /^1[0-9]{2}$/.test(statusCodeString):
  13388. response = this.incomingRequest.progress(responseOptions).message;
  13389. break;
  13390. case /^2[0-9]{2}$/.test(statusCodeString):
  13391. response = this.incomingRequest.accept(responseOptions).message;
  13392. break;
  13393. case /^3[0-9]{2}$/.test(statusCodeString):
  13394. response = this.incomingRequest.redirect([], responseOptions).message;
  13395. break;
  13396. case /^[4-6][0-9]{2}$/.test(statusCodeString):
  13397. response = this.incomingRequest.reject(responseOptions).message;
  13398. break;
  13399. default:
  13400. throw new Error("Invalid status code " + statusCode);
  13401. }
  13402. events.forEach(function (event) {
  13403. _this.emit(event, response, reasonPhrase);
  13404. });
  13405. return this;
  13406. };
  13407. ServerContext.prototype.onRequestTimeout = function () {
  13408. this.emit("failed", undefined, Constants_1.C.causes.REQUEST_TIMEOUT);
  13409. };
  13410. ServerContext.prototype.onTransportError = function () {
  13411. this.emit("failed", undefined, Constants_1.C.causes.CONNECTION_ERROR);
  13412. };
  13413. return ServerContext;
  13414. }(events_1.EventEmitter));
  13415. exports.ServerContext = ServerContext;
  13416. /***/ }),
  13417. /* 89 */
  13418. /***/ (function(module, exports, __webpack_require__) {
  13419. "use strict";
  13420. Object.defineProperty(exports, "__esModule", { value: true });
  13421. var tslib_1 = __webpack_require__(1);
  13422. var ClientContext_1 = __webpack_require__(79);
  13423. var Constants_1 = __webpack_require__(80);
  13424. var core_1 = __webpack_require__(2);
  13425. var Enums_1 = __webpack_require__(82);
  13426. var Exceptions_1 = __webpack_require__(84);
  13427. var Utils_1 = __webpack_require__(83);
  13428. /**
  13429. * Configuration load.
  13430. * @private
  13431. * returns {any}
  13432. */
  13433. function loadConfig(configuration) {
  13434. var settings = {
  13435. expires: 600,
  13436. extraContactHeaderParams: [],
  13437. instanceId: undefined,
  13438. params: {},
  13439. regId: undefined,
  13440. registrar: undefined,
  13441. };
  13442. var configCheck = getConfigurationCheck();
  13443. // Check Mandatory parameters
  13444. for (var parameter in configCheck.mandatory) {
  13445. if (!configuration.hasOwnProperty(parameter)) {
  13446. throw new Exceptions_1.Exceptions.ConfigurationError(parameter);
  13447. }
  13448. else {
  13449. var value = configuration[parameter];
  13450. var checkedValue = configCheck.mandatory[parameter](value);
  13451. if (checkedValue !== undefined) {
  13452. settings[parameter] = checkedValue;
  13453. }
  13454. else {
  13455. throw new Exceptions_1.Exceptions.ConfigurationError(parameter, value);
  13456. }
  13457. }
  13458. }
  13459. // Check Optional parameters
  13460. for (var parameter in configCheck.optional) {
  13461. if (configuration.hasOwnProperty(parameter)) {
  13462. var value = configuration[parameter];
  13463. // If the parameter value is an empty array, but shouldn't be, apply its default value.
  13464. if (value instanceof Array && value.length === 0) {
  13465. continue;
  13466. }
  13467. // If the parameter value is null, empty string, or undefined then apply its default value.
  13468. // If it's a number with NaN value then also apply its default value.
  13469. // NOTE: JS does not allow "value === NaN", the following does the work:
  13470. if (value === null || value === "" || value === undefined ||
  13471. (typeof (value) === "number" && isNaN(value))) {
  13472. continue;
  13473. }
  13474. var checkedValue = configCheck.optional[parameter](value);
  13475. if (checkedValue !== undefined) {
  13476. settings[parameter] = checkedValue;
  13477. }
  13478. else {
  13479. throw new Exceptions_1.Exceptions.ConfigurationError(parameter, value);
  13480. }
  13481. }
  13482. }
  13483. return settings;
  13484. }
  13485. function getConfigurationCheck() {
  13486. return {
  13487. mandatory: {},
  13488. optional: {
  13489. expires: function (expires) {
  13490. if (Utils_1.Utils.isDecimal(expires)) {
  13491. var value = Number(expires);
  13492. if (value >= 0) {
  13493. return value;
  13494. }
  13495. }
  13496. },
  13497. extraContactHeaderParams: function (extraContactHeaderParams) {
  13498. if (extraContactHeaderParams instanceof Array) {
  13499. return extraContactHeaderParams.filter(function (contactHeaderParam) { return (typeof contactHeaderParam === "string"); });
  13500. }
  13501. },
  13502. instanceId: function (instanceId) {
  13503. if (typeof instanceId !== "string") {
  13504. return;
  13505. }
  13506. if ((/^uuid:/i.test(instanceId))) {
  13507. instanceId = instanceId.substr(5);
  13508. }
  13509. if (core_1.Grammar.parse(instanceId, "uuid") === -1) {
  13510. return;
  13511. }
  13512. else {
  13513. return instanceId;
  13514. }
  13515. },
  13516. params: function (params) {
  13517. if (typeof params === "object") {
  13518. return params;
  13519. }
  13520. },
  13521. regId: function (regId) {
  13522. if (Utils_1.Utils.isDecimal(regId)) {
  13523. var value = Number(regId);
  13524. if (value >= 0) {
  13525. return value;
  13526. }
  13527. }
  13528. },
  13529. registrar: function (registrar) {
  13530. if (typeof registrar !== "string") {
  13531. return;
  13532. }
  13533. if (!/^sip:/i.test(registrar)) {
  13534. registrar = Constants_1.C.SIP + ":" + registrar;
  13535. }
  13536. var parsed = core_1.Grammar.URIParse(registrar);
  13537. if (!parsed) {
  13538. return;
  13539. }
  13540. else if (parsed.user) {
  13541. return;
  13542. }
  13543. else {
  13544. return parsed;
  13545. }
  13546. }
  13547. }
  13548. };
  13549. }
  13550. var RegisterContext = /** @class */ (function (_super) {
  13551. tslib_1.__extends(RegisterContext, _super);
  13552. function RegisterContext(ua, options) {
  13553. if (options === void 0) { options = {}; }
  13554. var _this = this;
  13555. var settings = loadConfig(options);
  13556. if (settings.regId && !settings.instanceId) {
  13557. settings.instanceId = Utils_1.Utils.newUUID();
  13558. }
  13559. else if (!settings.regId && settings.instanceId) {
  13560. settings.regId = 1;
  13561. }
  13562. settings.params.toUri = settings.params.toUri || ua.configuration.uri;
  13563. settings.params.toDisplayName = settings.params.toDisplayName || ua.configuration.displayName;
  13564. settings.params.callId = settings.params.callId || Utils_1.Utils.createRandomToken(22);
  13565. settings.params.cseq = settings.params.cseq || Math.floor(Math.random() * 10000);
  13566. /* If no 'registrarServer' is set use the 'uri' value without user portion. */
  13567. if (!settings.registrar) {
  13568. var registrarServer = {};
  13569. if (typeof ua.configuration.uri === "object") {
  13570. registrarServer = ua.configuration.uri.clone();
  13571. registrarServer.user = undefined;
  13572. }
  13573. else {
  13574. registrarServer = ua.configuration.uri;
  13575. }
  13576. settings.registrar = registrarServer;
  13577. }
  13578. _this = _super.call(this, ua, Constants_1.C.REGISTER, settings.registrar, settings) || this;
  13579. _this.type = Enums_1.TypeStrings.RegisterContext;
  13580. _this.options = settings;
  13581. _this.logger = ua.getLogger("sip.registercontext");
  13582. _this.logger.log("configuration parameters for RegisterContext after validation:");
  13583. for (var parameter in settings) {
  13584. if (settings.hasOwnProperty(parameter)) {
  13585. _this.logger.log("· " + parameter + ": " + JSON.stringify(settings[parameter]));
  13586. }
  13587. }
  13588. // Registration expires
  13589. _this.expires = settings.expires;
  13590. // Contact header
  13591. _this.contact = ua.contact.toString();
  13592. // Set status
  13593. _this.registered = false;
  13594. ua.transport.on("disconnected", function () { return _this.onTransportDisconnected(); });
  13595. return _this;
  13596. }
  13597. RegisterContext.prototype.register = function (options) {
  13598. var _this = this;
  13599. if (options === void 0) { options = {}; }
  13600. // Handle Options
  13601. this.options = tslib_1.__assign(tslib_1.__assign({}, this.options), options);
  13602. var extraHeaders = (this.options.extraHeaders || []).slice();
  13603. extraHeaders.push("Contact: " + this.generateContactHeader(this.expires));
  13604. // this is UA.C.ALLOWED_METHODS, removed to get around circular dependency
  13605. extraHeaders.push("Allow: " + [
  13606. "ACK",
  13607. "CANCEL",
  13608. "INVITE",
  13609. "MESSAGE",
  13610. "BYE",
  13611. "OPTIONS",
  13612. "INFO",
  13613. "NOTIFY",
  13614. "REFER"
  13615. ].toString());
  13616. // Save original extraHeaders to be used in .close
  13617. this.closeHeaders = this.options.closeWithHeaders ?
  13618. (this.options.extraHeaders || []).slice() : [];
  13619. this.receiveResponse = function (response) {
  13620. // Discard responses to older REGISTER/un-REGISTER requests.
  13621. if (response.cseq !== _this.request.cseq) {
  13622. return;
  13623. }
  13624. // Clear registration timer
  13625. if (_this.registrationTimer !== undefined) {
  13626. clearTimeout(_this.registrationTimer);
  13627. _this.registrationTimer = undefined;
  13628. }
  13629. var statusCode = (response.statusCode || 0).toString();
  13630. switch (true) {
  13631. case /^1[0-9]{2}$/.test(statusCode):
  13632. _this.emit("progress", response);
  13633. break;
  13634. case /^2[0-9]{2}$/.test(statusCode):
  13635. _this.emit("accepted", response);
  13636. var expires = void 0;
  13637. if (response.hasHeader("expires")) {
  13638. expires = Number(response.getHeader("expires"));
  13639. }
  13640. if (_this.registrationExpiredTimer !== undefined) {
  13641. clearTimeout(_this.registrationExpiredTimer);
  13642. _this.registrationExpiredTimer = undefined;
  13643. }
  13644. // Search the Contact pointing to us and update the expires value accordingly.
  13645. var contacts = response.getHeaders("contact").length;
  13646. if (!contacts) {
  13647. _this.logger.warn("no Contact header in response to REGISTER, response ignored");
  13648. break;
  13649. }
  13650. var contact = void 0;
  13651. while (contacts--) {
  13652. contact = response.parseHeader("contact", contacts);
  13653. if (contact.uri.user === _this.ua.contact.uri.user) {
  13654. expires = contact.getParam("expires");
  13655. break;
  13656. }
  13657. else {
  13658. contact = undefined;
  13659. }
  13660. }
  13661. if (!contact) {
  13662. _this.logger.warn("no Contact header pointing to us, response ignored");
  13663. break;
  13664. }
  13665. if (expires === undefined) {
  13666. expires = _this.expires;
  13667. }
  13668. // Re-Register before the expiration interval has elapsed.
  13669. // For that, decrease the expires value. ie: 3 seconds
  13670. _this.registrationTimer = setTimeout(function () {
  13671. _this.registrationTimer = undefined;
  13672. _this.register(_this.options);
  13673. }, (expires * 1000) - 3000);
  13674. _this.registrationExpiredTimer = setTimeout(function () {
  13675. _this.logger.warn("registration expired");
  13676. if (_this.registered) {
  13677. _this.unregistered(undefined, Constants_1.C.causes.EXPIRES);
  13678. }
  13679. }, expires * 1000);
  13680. // Save gruu values
  13681. if (contact.hasParam("temp-gruu")) {
  13682. _this.ua.contact.tempGruu = core_1.Grammar.URIParse(contact.getParam("temp-gruu").replace(/"/g, ""));
  13683. }
  13684. if (contact.hasParam("pub-gruu")) {
  13685. _this.ua.contact.pubGruu = core_1.Grammar.URIParse(contact.getParam("pub-gruu").replace(/"/g, ""));
  13686. }
  13687. _this.registered = true;
  13688. _this.emit("registered", response || undefined);
  13689. break;
  13690. // Interval too brief RFC3261 10.2.8
  13691. case /^423$/.test(statusCode):
  13692. if (response.hasHeader("min-expires")) {
  13693. // Increase our registration interval to the suggested minimum
  13694. _this.expires = Number(response.getHeader("min-expires"));
  13695. // Attempt the registration again immediately
  13696. _this.register(_this.options);
  13697. }
  13698. else { // This response MUST contain a Min-Expires header field
  13699. _this.logger.warn("423 response received for REGISTER without Min-Expires");
  13700. _this.registrationFailure(response, Constants_1.C.causes.SIP_FAILURE_CODE);
  13701. }
  13702. break;
  13703. default:
  13704. _this.registrationFailure(response, Utils_1.Utils.sipErrorCause(response.statusCode || 0));
  13705. }
  13706. };
  13707. this.onRequestTimeout = function () {
  13708. _this.registrationFailure(undefined, Constants_1.C.causes.REQUEST_TIMEOUT);
  13709. };
  13710. this.onTransportError = function () {
  13711. _this.registrationFailure(undefined, Constants_1.C.causes.CONNECTION_ERROR);
  13712. };
  13713. this.request.cseq++;
  13714. this.request.setHeader("cseq", this.request.cseq + " REGISTER");
  13715. this.request.extraHeaders = extraHeaders;
  13716. this.send();
  13717. };
  13718. RegisterContext.prototype.close = function () {
  13719. var options = {
  13720. all: false,
  13721. extraHeaders: this.closeHeaders
  13722. };
  13723. this.registeredBefore = this.registered;
  13724. if (this.registered) {
  13725. this.unregister(options);
  13726. }
  13727. };
  13728. RegisterContext.prototype.unregister = function (options) {
  13729. var _this = this;
  13730. if (options === void 0) { options = {}; }
  13731. if (!this.registered && !options.all) {
  13732. this.logger.warn("Already unregistered, but sending an unregister anyways.");
  13733. }
  13734. var extraHeaders = (options.extraHeaders || []).slice();
  13735. this.registered = false;
  13736. // Clear the registration timer.
  13737. if (this.registrationTimer !== undefined) {
  13738. clearTimeout(this.registrationTimer);
  13739. this.registrationTimer = undefined;
  13740. }
  13741. if (options.all) {
  13742. extraHeaders.push("Contact: *");
  13743. extraHeaders.push("Expires: 0");
  13744. }
  13745. else {
  13746. extraHeaders.push("Contact: " + this.generateContactHeader(0));
  13747. }
  13748. this.receiveResponse = function (response) {
  13749. var statusCode = (response && response.statusCode) ? response.statusCode.toString() : "";
  13750. switch (true) {
  13751. case /^1[0-9]{2}$/.test(statusCode):
  13752. _this.emit("progress", response);
  13753. break;
  13754. case /^2[0-9]{2}$/.test(statusCode):
  13755. _this.emit("accepted", response);
  13756. if (_this.registrationExpiredTimer !== undefined) {
  13757. clearTimeout(_this.registrationExpiredTimer);
  13758. _this.registrationExpiredTimer = undefined;
  13759. }
  13760. _this.unregistered(response);
  13761. break;
  13762. default:
  13763. _this.unregistered(response, Utils_1.Utils.sipErrorCause(response.statusCode || 0));
  13764. }
  13765. };
  13766. this.onRequestTimeout = function () {
  13767. // Not actually unregistered...
  13768. // this.unregistered(undefined, SIP.C.causes.REQUEST_TIMEOUT);
  13769. };
  13770. this.request.cseq++;
  13771. this.request.setHeader("cseq", this.request.cseq + " REGISTER");
  13772. this.request.extraHeaders = extraHeaders;
  13773. this.send();
  13774. };
  13775. RegisterContext.prototype.unregistered = function (response, cause) {
  13776. this.registered = false;
  13777. this.emit("unregistered", response || undefined, cause || undefined);
  13778. };
  13779. RegisterContext.prototype.send = function () {
  13780. var _this = this;
  13781. this.ua.userAgentCore.register(this.request, {
  13782. onAccept: function (response) { return _this.receiveResponse(response.message); },
  13783. onProgress: function (response) { return _this.receiveResponse(response.message); },
  13784. onRedirect: function (response) { return _this.receiveResponse(response.message); },
  13785. onReject: function (response) { return _this.receiveResponse(response.message); },
  13786. onTrying: function (response) { return _this.receiveResponse(response.message); }
  13787. });
  13788. return this;
  13789. };
  13790. RegisterContext.prototype.registrationFailure = function (response, cause) {
  13791. this.emit("failed", response || undefined, cause || undefined);
  13792. };
  13793. RegisterContext.prototype.onTransportDisconnected = function () {
  13794. this.registeredBefore = this.registered;
  13795. if (this.registrationTimer !== undefined) {
  13796. clearTimeout(this.registrationTimer);
  13797. this.registrationTimer = undefined;
  13798. }
  13799. if (this.registrationExpiredTimer !== undefined) {
  13800. clearTimeout(this.registrationExpiredTimer);
  13801. this.registrationExpiredTimer = undefined;
  13802. }
  13803. if (this.registered) {
  13804. this.unregistered(undefined, Constants_1.C.causes.CONNECTION_ERROR);
  13805. }
  13806. };
  13807. /**
  13808. * Helper Function to generate Contact Header
  13809. * @private
  13810. * returns {String}
  13811. */
  13812. RegisterContext.prototype.generateContactHeader = function (expires) {
  13813. if (expires === void 0) { expires = 0; }
  13814. var contact = this.contact;
  13815. if (this.options.regId && this.options.instanceId) {
  13816. contact += ";reg-id=" + this.options.regId;
  13817. contact += ';+sip.instance="<urn:uuid:' + this.options.instanceId + '>"';
  13818. }
  13819. if (this.options.extraContactHeaderParams) {
  13820. this.options.extraContactHeaderParams.forEach(function (header) {
  13821. contact += ";" + header;
  13822. });
  13823. }
  13824. contact += ";expires=" + expires;
  13825. return contact;
  13826. };
  13827. return RegisterContext;
  13828. }(ClientContext_1.ClientContext));
  13829. exports.RegisterContext = RegisterContext;
  13830. /***/ }),
  13831. /* 90 */
  13832. /***/ (function(module, exports, __webpack_require__) {
  13833. "use strict";
  13834. Object.defineProperty(exports, "__esModule", { value: true });
  13835. var tslib_1 = __webpack_require__(1);
  13836. var events_1 = __webpack_require__(30);
  13837. var ClientContext_1 = __webpack_require__(79);
  13838. var Constants_1 = __webpack_require__(80);
  13839. var core_1 = __webpack_require__(2);
  13840. var Enums_1 = __webpack_require__(82);
  13841. var Exceptions_1 = __webpack_require__(84);
  13842. var ReferContext_1 = __webpack_require__(87);
  13843. var ServerContext_1 = __webpack_require__(88);
  13844. var DTMF_1 = __webpack_require__(91);
  13845. var Utils_1 = __webpack_require__(83);
  13846. /*
  13847. * @param {function returning SIP.sessionDescriptionHandler} [sessionDescriptionHandlerFactory]
  13848. * (See the documentation for the sessionDescriptionHandlerFactory argument of the UA constructor.)
  13849. */
  13850. var Session = /** @class */ (function (_super) {
  13851. tslib_1.__extends(Session, _super);
  13852. function Session(sessionDescriptionHandlerFactory) {
  13853. var _this = _super.call(this) || this;
  13854. _this.data = {};
  13855. _this.type = Enums_1.TypeStrings.Session;
  13856. if (!sessionDescriptionHandlerFactory) {
  13857. throw new Exceptions_1.Exceptions.SessionDescriptionHandlerError("A session description handler is required for the session to function");
  13858. }
  13859. _this.status = Session.C.STATUS_NULL;
  13860. _this.pendingReinvite = false;
  13861. _this.sessionDescriptionHandlerFactory = sessionDescriptionHandlerFactory;
  13862. _this.hasOffer = false;
  13863. _this.hasAnswer = false;
  13864. // Session Timers
  13865. _this.timers = {
  13866. ackTimer: undefined,
  13867. expiresTimer: undefined,
  13868. invite2xxTimer: undefined,
  13869. userNoAnswerTimer: undefined,
  13870. rel1xxTimer: undefined,
  13871. prackTimer: undefined
  13872. };
  13873. // Session info
  13874. _this.startTime = undefined;
  13875. _this.endTime = undefined;
  13876. _this.tones = undefined;
  13877. // Hold state
  13878. _this.localHold = false;
  13879. _this.earlySdp = undefined;
  13880. _this.rel100 = Constants_1.C.supported.UNSUPPORTED;
  13881. return _this;
  13882. }
  13883. Session.prototype.dtmf = function (tones, options) {
  13884. var _this = this;
  13885. if (options === void 0) { options = {}; }
  13886. // Check Session Status
  13887. if (this.status !== Enums_1.SessionStatus.STATUS_CONFIRMED && this.status !== Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK) {
  13888. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  13889. }
  13890. // Check tones
  13891. if (!tones || !tones.toString().match(/^[0-9A-D#*,]+$/i)) {
  13892. throw new TypeError("Invalid tones: " + tones);
  13893. }
  13894. var sendDTMF = function () {
  13895. if (_this.status === Enums_1.SessionStatus.STATUS_TERMINATED || !_this.tones || _this.tones.length === 0) {
  13896. // Stop sending DTMF
  13897. _this.tones = undefined;
  13898. return;
  13899. }
  13900. var dtmf = _this.tones.shift();
  13901. var timeout;
  13902. if (dtmf.tone === ",") {
  13903. timeout = 2000;
  13904. }
  13905. else {
  13906. dtmf.on("failed", function () { _this.tones = undefined; });
  13907. dtmf.send(options);
  13908. timeout = dtmf.duration + dtmf.interToneGap;
  13909. }
  13910. // Set timeout for the next tone
  13911. setTimeout(sendDTMF, timeout);
  13912. };
  13913. tones = tones.toString();
  13914. var dtmfType = this.ua.configuration.dtmfType;
  13915. if (this.sessionDescriptionHandler && dtmfType === Constants_1.C.dtmfType.RTP) {
  13916. var sent = this.sessionDescriptionHandler.sendDtmf(tones, options);
  13917. if (!sent) {
  13918. this.logger.warn("Attempt to use dtmfType 'RTP' has failed, falling back to INFO packet method");
  13919. dtmfType = Constants_1.C.dtmfType.INFO;
  13920. }
  13921. }
  13922. if (dtmfType === Constants_1.C.dtmfType.INFO) {
  13923. var dtmfs = [];
  13924. var tonesArray = tones.split("");
  13925. while (tonesArray.length > 0) {
  13926. dtmfs.push(new DTMF_1.DTMF(this, tonesArray.shift(), options));
  13927. }
  13928. if (this.tones) {
  13929. // Tones are already queued, just add to the queue
  13930. this.tones = this.tones.concat(dtmfs);
  13931. return this;
  13932. }
  13933. this.tones = dtmfs;
  13934. sendDTMF();
  13935. }
  13936. return this;
  13937. };
  13938. Session.prototype.bye = function (options) {
  13939. if (options === void 0) { options = {}; }
  13940. // Check Session Status
  13941. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  13942. this.logger.error("Error: Attempted to send BYE in a terminated session.");
  13943. return this;
  13944. }
  13945. this.logger.log("terminating Session");
  13946. var statusCode = options.statusCode;
  13947. if (statusCode && (statusCode < 200 || statusCode >= 700)) {
  13948. throw new TypeError("Invalid statusCode: " + statusCode);
  13949. }
  13950. options.receiveResponse = function () { };
  13951. return this.sendRequest(Constants_1.C.BYE, options).terminated();
  13952. };
  13953. Session.prototype.refer = function (target, options) {
  13954. if (options === void 0) { options = {}; }
  13955. // Check Session Status
  13956. if (this.status !== Enums_1.SessionStatus.STATUS_CONFIRMED) {
  13957. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  13958. }
  13959. this.referContext = new ReferContext_1.ReferClientContext(this.ua, this, target, options);
  13960. this.emit("referRequested", this.referContext);
  13961. this.referContext.refer(options);
  13962. return this.referContext;
  13963. };
  13964. /**
  13965. * Sends in dialog request.
  13966. * @param method Request method.
  13967. * @param options Options bucket.
  13968. */
  13969. Session.prototype.sendRequest = function (method, options) {
  13970. if (options === void 0) { options = {}; }
  13971. if (!this.session) {
  13972. throw new Error("Session undefined.");
  13973. }
  13974. // Convert any "body" option to a Body.
  13975. if (options.body) {
  13976. options.body = Utils_1.Utils.fromBodyObj(options.body);
  13977. }
  13978. // Convert any "receiveResponse" callback option passed to an OutgoingRequestDelegate.
  13979. var delegate;
  13980. var callback = options.receiveResponse;
  13981. if (callback) {
  13982. delegate = {
  13983. onAccept: function (response) { return callback(response.message); },
  13984. onProgress: function (response) { return callback(response.message); },
  13985. onRedirect: function (response) { return callback(response.message); },
  13986. onReject: function (response) { return callback(response.message); },
  13987. onTrying: function (response) { return callback(response.message); }
  13988. };
  13989. }
  13990. var request;
  13991. var requestOptions = options;
  13992. switch (method) {
  13993. case Constants_1.C.BYE:
  13994. request = this.session.bye(delegate, requestOptions);
  13995. break;
  13996. case Constants_1.C.INVITE:
  13997. request = this.session.invite(delegate, requestOptions);
  13998. break;
  13999. case Constants_1.C.REFER:
  14000. request = this.session.refer(delegate, requestOptions);
  14001. break;
  14002. default:
  14003. throw new Error("Unexpected " + method + ". Method not implemented by user agent core.");
  14004. }
  14005. // Ported - Emit the request event
  14006. this.emit(method.toLowerCase(), request.message);
  14007. return this;
  14008. };
  14009. Session.prototype.close = function () {
  14010. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  14011. return this;
  14012. }
  14013. this.logger.log("closing INVITE session " + this.id);
  14014. // 1st Step. Terminate media.
  14015. if (this.sessionDescriptionHandler) {
  14016. this.sessionDescriptionHandler.close();
  14017. }
  14018. // 2nd Step. Terminate signaling.
  14019. // Clear session timers
  14020. for (var timer in this.timers) {
  14021. if (this.timers[timer]) {
  14022. clearTimeout(this.timers[timer]);
  14023. }
  14024. }
  14025. this.status = Enums_1.SessionStatus.STATUS_TERMINATED;
  14026. if (this.ua.transport) {
  14027. this.ua.transport.removeListener("transportError", this.errorListener);
  14028. }
  14029. delete this.ua.sessions[this.id];
  14030. return this;
  14031. };
  14032. Session.prototype.mute = function(options) {
  14033. var pc = this.sessionDescriptionHandler.peerConnection;
  14034. if(pc.getSenders) {
  14035. pc.getSenders().forEach( function(sender) {
  14036. if(sender.track) {
  14037. sender.track.enabled = false;
  14038. }
  14039. });
  14040. } else {
  14041. pc.getLocalStreams().forEach(function (stream) {
  14042. stream.getAudioTracks().forEach(function (track) {
  14043. track.enabled = false;
  14044. });
  14045. stream.getVideoTracks().forEach(function (track) {
  14046. track.enabled = false;
  14047. });
  14048. });
  14049. }
  14050. this.emit("muted");
  14051. };
  14052. Session.prototype.unmute = function(options) {
  14053. var pc = this.sessionDescriptionHandler.peerConnection;
  14054. if (pc.getSenders) {
  14055. pc.getSenders().forEach(function (sender) {
  14056. if (sender.track) {
  14057. sender.track.enabled = true;
  14058. }
  14059. });
  14060. } else {
  14061. pc.getLocalStreams().forEach(function (stream) {
  14062. stream.getAudioTracks().forEach(function (track) {
  14063. track.enabled = true;
  14064. });
  14065. stream.getVideoTracks().forEach(function (track) {
  14066. track.enabled = true;
  14067. });
  14068. });
  14069. }
  14070. this.emit("unmuted");
  14071. };
  14072. Session.prototype.hold = function (options, modifiers) {
  14073. if (options === void 0) { options = {}; }
  14074. if (modifiers === void 0) { modifiers = []; }
  14075. if (this.status !== Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK && this.status !== Enums_1.SessionStatus.STATUS_CONFIRMED) {
  14076. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  14077. }
  14078. if (this.localHold) {
  14079. this.logger.log("Session is already on hold, cannot put it on hold again");
  14080. return;
  14081. }
  14082. options.modifiers = modifiers;
  14083. if (this.sessionDescriptionHandler) {
  14084. options.modifiers.push(this.sessionDescriptionHandler.holdModifier);
  14085. }
  14086. this.localHold = true;
  14087. this.sendReinvite(options);
  14088. this.emit("hold");
  14089. };
  14090. Session.prototype.unhold = function (options, modifiers) {
  14091. if (options === void 0) { options = {}; }
  14092. if (modifiers === void 0) { modifiers = []; }
  14093. if (this.status !== Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK && this.status !== Enums_1.SessionStatus.STATUS_CONFIRMED) {
  14094. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  14095. }
  14096. if (!this.localHold) {
  14097. this.logger.log("Session is not on hold, cannot unhold it");
  14098. return;
  14099. }
  14100. options.modifiers = modifiers;
  14101. this.localHold = false;
  14102. this.sendReinvite(options);
  14103. this.emit("unhold");
  14104. };
  14105. Session.prototype.reinvite = function (options, modifiers) {
  14106. if (options === void 0) { options = {}; }
  14107. if (modifiers === void 0) { modifiers = []; }
  14108. options.modifiers = modifiers;
  14109. return this.sendReinvite(options);
  14110. };
  14111. Session.prototype.terminate = function (options) {
  14112. // here for types and to be overridden
  14113. return this;
  14114. };
  14115. Session.prototype.onTransportError = function () {
  14116. if (this.status !== Enums_1.SessionStatus.STATUS_CONFIRMED && this.status !== Enums_1.SessionStatus.STATUS_TERMINATED) {
  14117. this.failed(undefined, Constants_1.C.causes.CONNECTION_ERROR);
  14118. }
  14119. };
  14120. Session.prototype.onRequestTimeout = function () {
  14121. if (this.status === Enums_1.SessionStatus.STATUS_CONFIRMED) {
  14122. this.terminated(undefined, Constants_1.C.causes.REQUEST_TIMEOUT);
  14123. }
  14124. else if (this.status !== Enums_1.SessionStatus.STATUS_TERMINATED) {
  14125. this.failed(undefined, Constants_1.C.causes.REQUEST_TIMEOUT);
  14126. this.terminated(undefined, Constants_1.C.causes.REQUEST_TIMEOUT);
  14127. }
  14128. };
  14129. Session.prototype.onDialogError = function (response) {
  14130. if (this.status === Enums_1.SessionStatus.STATUS_CONFIRMED) {
  14131. this.terminated(response, Constants_1.C.causes.DIALOG_ERROR);
  14132. }
  14133. else if (this.status !== Enums_1.SessionStatus.STATUS_TERMINATED) {
  14134. this.failed(response, Constants_1.C.causes.DIALOG_ERROR);
  14135. this.terminated(response, Constants_1.C.causes.DIALOG_ERROR);
  14136. }
  14137. };
  14138. Session.prototype.on = function (name, callback) {
  14139. return _super.prototype.on.call(this, name, callback);
  14140. };
  14141. Session.prototype.onAck = function (incomingRequest) {
  14142. var _this = this;
  14143. var confirmSession = function () {
  14144. clearTimeout(_this.timers.ackTimer);
  14145. clearTimeout(_this.timers.invite2xxTimer);
  14146. _this.status = Enums_1.SessionStatus.STATUS_CONFIRMED;
  14147. var contentDisp = incomingRequest.message.getHeader("Content-Disposition");
  14148. if (contentDisp && contentDisp.type === "render") {
  14149. _this.renderbody = incomingRequest.message.body;
  14150. _this.rendertype = incomingRequest.message.getHeader("Content-Type");
  14151. }
  14152. _this.emit("confirmed", incomingRequest.message);
  14153. };
  14154. if (this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK) {
  14155. if (this.sessionDescriptionHandler &&
  14156. this.sessionDescriptionHandler.hasDescription(incomingRequest.message.getHeader("Content-Type") || "")) {
  14157. this.hasAnswer = true;
  14158. this.sessionDescriptionHandler.setDescription(incomingRequest.message.body, this.sessionDescriptionHandlerOptions, this.modifiers).catch(function (e) {
  14159. _this.logger.warn(e);
  14160. _this.terminate({
  14161. statusCode: "488",
  14162. reasonPhrase: "Bad Media Description"
  14163. });
  14164. _this.failed(incomingRequest.message, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  14165. _this.terminated(incomingRequest.message, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  14166. throw e;
  14167. }).then(function () { return confirmSession(); });
  14168. }
  14169. else {
  14170. confirmSession();
  14171. }
  14172. }
  14173. };
  14174. Session.prototype.receiveRequest = function (incomingRequest) {
  14175. switch (incomingRequest.message.method) { // TODO: This needs a default case
  14176. case Constants_1.C.BYE:
  14177. incomingRequest.accept();
  14178. if (this.status === Enums_1.SessionStatus.STATUS_CONFIRMED) {
  14179. this.emit("bye", incomingRequest.message);
  14180. this.terminated(incomingRequest.message, Constants_1.C.BYE);
  14181. }
  14182. break;
  14183. case Constants_1.C.INVITE:
  14184. if (this.status === Enums_1.SessionStatus.STATUS_CONFIRMED) {
  14185. this.logger.log("re-INVITE received");
  14186. this.receiveReinvite(incomingRequest);
  14187. }
  14188. break;
  14189. case Constants_1.C.INFO:
  14190. if (this.status === Enums_1.SessionStatus.STATUS_CONFIRMED || this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK) {
  14191. if (this.onInfo) {
  14192. return this.onInfo(incomingRequest.message);
  14193. }
  14194. var contentType = incomingRequest.message.getHeader("content-type");
  14195. if (contentType) {
  14196. if (contentType.match(/^application\/dtmf-relay/i)) {
  14197. if (incomingRequest.message.body) {
  14198. var body = incomingRequest.message.body.split("\r\n", 2);
  14199. if (body.length === 2) {
  14200. var tone = void 0;
  14201. var duration = void 0;
  14202. var regTone = /^(Signal\s*?=\s*?)([0-9A-D#*]{1})(\s)?.*/;
  14203. if (regTone.test(body[0])) {
  14204. tone = body[0].replace(regTone, "$2");
  14205. }
  14206. var regDuration = /^(Duration\s?=\s?)([0-9]{1,4})(\s)?.*/;
  14207. if (regDuration.test(body[1])) {
  14208. duration = parseInt(body[1].replace(regDuration, "$2"), 10);
  14209. }
  14210. if (tone && duration) {
  14211. new DTMF_1.DTMF(this, tone, { duration: duration }).init_incoming(incomingRequest);
  14212. }
  14213. }
  14214. }
  14215. }
  14216. else {
  14217. incomingRequest.reject({
  14218. statusCode: 415,
  14219. extraHeaders: ["Accept: application/dtmf-relay"]
  14220. });
  14221. }
  14222. }
  14223. }
  14224. break;
  14225. case Constants_1.C.REFER:
  14226. if (this.status === Enums_1.SessionStatus.STATUS_CONFIRMED) {
  14227. this.logger.log("REFER received");
  14228. this.referContext = new ReferContext_1.ReferServerContext(this.ua, incomingRequest, this.session);
  14229. if (this.listeners("referRequested").length) {
  14230. this.emit("referRequested", this.referContext);
  14231. }
  14232. else {
  14233. this.logger.log("No referRequested listeners, automatically accepting and following the refer");
  14234. var options = { followRefer: true };
  14235. if (this.passedOptions) {
  14236. options.inviteOptions = this.passedOptions;
  14237. }
  14238. this.referContext.accept(options, this.modifiers);
  14239. }
  14240. }
  14241. break;
  14242. case Constants_1.C.NOTIFY:
  14243. if (this.referContext &&
  14244. this.referContext.type === Enums_1.TypeStrings.ReferClientContext &&
  14245. incomingRequest.message.hasHeader("event") &&
  14246. /^refer(;.*)?$/.test(incomingRequest.message.getHeader("event"))) {
  14247. this.referContext.receiveNotify(incomingRequest);
  14248. return;
  14249. }
  14250. incomingRequest.accept();
  14251. this.emit("notify", incomingRequest.message);
  14252. break;
  14253. }
  14254. };
  14255. // In dialog INVITE Reception
  14256. Session.prototype.receiveReinvite = function (incomingRequest) {
  14257. // TODO: Should probably check state of the session
  14258. var _this = this;
  14259. this.emit("reinvite", this, incomingRequest.message);
  14260. if (incomingRequest.message.hasHeader("P-Asserted-Identity")) {
  14261. this.assertedIdentity =
  14262. core_1.Grammar.nameAddrHeaderParse(incomingRequest.message.getHeader("P-Asserted-Identity"));
  14263. }
  14264. var promise;
  14265. if (!this.sessionDescriptionHandler) {
  14266. this.logger.warn("No SessionDescriptionHandler to reinvite");
  14267. return;
  14268. }
  14269. if (incomingRequest.message.getHeader("Content-Length") === "0" &&
  14270. !incomingRequest.message.getHeader("Content-Type")) { // Invite w/o SDP
  14271. promise = this.sessionDescriptionHandler.getDescription(this.sessionDescriptionHandlerOptions, this.modifiers);
  14272. }
  14273. else if (this.sessionDescriptionHandler.hasDescription(incomingRequest.message.getHeader("Content-Type") || "")) {
  14274. // Invite w/ SDP
  14275. promise = this.sessionDescriptionHandler.setDescription(incomingRequest.message.body, this.sessionDescriptionHandlerOptions, this.modifiers).then(this.sessionDescriptionHandler.getDescription.bind(this.sessionDescriptionHandler, this.sessionDescriptionHandlerOptions, this.modifiers));
  14276. }
  14277. else { // Bad Packet (should never get hit)
  14278. incomingRequest.reject({ statusCode: 415 });
  14279. this.emit("reinviteFailed", this);
  14280. return;
  14281. }
  14282. promise.catch(function (e) {
  14283. var statusCode;
  14284. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  14285. statusCode = 500;
  14286. }
  14287. else if (e.type === Enums_1.TypeStrings.RenegotiationError) {
  14288. _this.emit("renegotiationError", e);
  14289. _this.logger.warn(e.toString());
  14290. statusCode = 488;
  14291. }
  14292. else {
  14293. _this.logger.error(e);
  14294. statusCode = 488;
  14295. }
  14296. incomingRequest.reject({ statusCode: statusCode });
  14297. _this.emit("reinviteFailed", _this);
  14298. // TODO: This could be better
  14299. throw e;
  14300. }).then(function (description) {
  14301. var extraHeaders = ["Contact: " + _this.contact];
  14302. incomingRequest.accept({
  14303. statusCode: 200,
  14304. extraHeaders: extraHeaders,
  14305. body: Utils_1.Utils.fromBodyObj(description)
  14306. });
  14307. _this.status = Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK;
  14308. _this.emit("reinviteAccepted", _this);
  14309. });
  14310. };
  14311. Session.prototype.sendReinvite = function (options) {
  14312. var _this = this;
  14313. if (options === void 0) { options = {}; }
  14314. if (this.pendingReinvite) {
  14315. this.logger.warn("Reinvite in progress. Please wait until complete, then try again.");
  14316. return;
  14317. }
  14318. if (!this.sessionDescriptionHandler) {
  14319. this.logger.warn("No SessionDescriptionHandler, can't reinvite..");
  14320. return;
  14321. }
  14322. this.pendingReinvite = true;
  14323. options.modifiers = options.modifiers || [];
  14324. var extraHeaders = (options.extraHeaders || []).slice();
  14325. extraHeaders.push("Contact: " + this.contact);
  14326. // this is UA.C.ALLOWED_METHODS, removed to get around circular dependency
  14327. extraHeaders.push("Allow: " + [
  14328. "ACK",
  14329. "CANCEL",
  14330. "INVITE",
  14331. "MESSAGE",
  14332. "BYE",
  14333. "OPTIONS",
  14334. "INFO",
  14335. "NOTIFY",
  14336. "REFER"
  14337. ].toString());
  14338. this.sessionDescriptionHandler.getDescription(options.sessionDescriptionHandlerOptions, options.modifiers)
  14339. .then(function (description) {
  14340. if (!_this.session) {
  14341. throw new Error("Session undefined.");
  14342. }
  14343. var delegate = {
  14344. onAccept: function (response) {
  14345. if (_this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  14346. _this.logger.error("Received reinvite response, but in STATUS_TERMINATED");
  14347. // TODO: Do we need to send a SIP response?
  14348. return;
  14349. }
  14350. if (!_this.pendingReinvite) {
  14351. _this.logger.error("Received reinvite response, but have no pending reinvite");
  14352. // TODO: Do we need to send a SIP response?
  14353. return;
  14354. }
  14355. // FIXME: Why is this set here?
  14356. _this.status = Enums_1.SessionStatus.STATUS_CONFIRMED;
  14357. // 17.1.1.1 - For each final response that is received at the client transaction,
  14358. // the client transaction sends an ACK,
  14359. _this.emit("ack", response.ack());
  14360. _this.pendingReinvite = false;
  14361. // TODO: All of these timers should move into the Transaction layer
  14362. clearTimeout(_this.timers.invite2xxTimer);
  14363. if (!_this.sessionDescriptionHandler ||
  14364. !_this.sessionDescriptionHandler.hasDescription(response.message.getHeader("Content-Type") || "")) {
  14365. _this.logger.error("2XX response received to re-invite but did not have a description");
  14366. _this.emit("reinviteFailed", _this);
  14367. _this.emit("renegotiationError", new Exceptions_1.Exceptions.RenegotiationError("2XX response received to re-invite but did not have a description"));
  14368. return;
  14369. }
  14370. _this.sessionDescriptionHandler
  14371. .setDescription(response.message.body, _this.sessionDescriptionHandlerOptions, _this.modifiers)
  14372. .catch(function (e) {
  14373. _this.logger.error("Could not set the description in 2XX response");
  14374. _this.logger.error(e);
  14375. _this.emit("reinviteFailed", _this);
  14376. _this.emit("renegotiationError", e);
  14377. _this.sendRequest(Constants_1.C.BYE, {
  14378. extraHeaders: ["Reason: " + Utils_1.Utils.getReasonHeaderValue(488, "Not Acceptable Here")]
  14379. });
  14380. _this.terminated(undefined, Constants_1.C.causes.INCOMPATIBLE_SDP);
  14381. throw e;
  14382. })
  14383. .then(function () {
  14384. _this.emit("reinviteAccepted", _this);
  14385. });
  14386. },
  14387. onProgress: function (response) {
  14388. return;
  14389. },
  14390. onRedirect: function (response) {
  14391. // FIXME: Does ACK need to be sent?
  14392. _this.pendingReinvite = false;
  14393. _this.logger.log("Received a non 1XX or 2XX response to a re-invite");
  14394. _this.emit("reinviteFailed", _this);
  14395. _this.emit("renegotiationError", new Exceptions_1.Exceptions.RenegotiationError("Invalid response to a re-invite"));
  14396. },
  14397. onReject: function (response) {
  14398. // FIXME: Does ACK need to be sent?
  14399. _this.pendingReinvite = false;
  14400. _this.logger.log("Received a non 1XX or 2XX response to a re-invite");
  14401. _this.emit("reinviteFailed", _this);
  14402. _this.emit("renegotiationError", new Exceptions_1.Exceptions.RenegotiationError("Invalid response to a re-invite"));
  14403. },
  14404. onTrying: function (response) {
  14405. return;
  14406. }
  14407. };
  14408. var requestOptions = {
  14409. extraHeaders: extraHeaders,
  14410. body: Utils_1.Utils.fromBodyObj(description)
  14411. };
  14412. _this.session.invite(delegate, requestOptions);
  14413. }).catch(function (e) {
  14414. if (e.type === Enums_1.TypeStrings.RenegotiationError) {
  14415. _this.pendingReinvite = false;
  14416. _this.emit("renegotiationError", e);
  14417. _this.logger.warn("Renegotiation Error");
  14418. _this.logger.warn(e.toString());
  14419. throw e;
  14420. }
  14421. _this.logger.error("sessionDescriptionHandler error");
  14422. _this.logger.error(e);
  14423. throw e;
  14424. });
  14425. };
  14426. Session.prototype.failed = function (response, cause) {
  14427. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  14428. return this;
  14429. }
  14430. this.emit("failed", response, cause);
  14431. return this;
  14432. };
  14433. Session.prototype.rejected = function (response, cause) {
  14434. this.emit("rejected", response, cause);
  14435. return this;
  14436. };
  14437. Session.prototype.canceled = function () {
  14438. if (this.sessionDescriptionHandler) {
  14439. this.sessionDescriptionHandler.close();
  14440. }
  14441. this.emit("cancel");
  14442. return this;
  14443. };
  14444. Session.prototype.accepted = function (response, cause) {
  14445. if (!(response instanceof String)) {
  14446. cause = Utils_1.Utils.getReasonPhrase((response && response.statusCode) || 0, cause);
  14447. }
  14448. this.startTime = new Date();
  14449. if (this.replacee) {
  14450. this.replacee.emit("replaced", this);
  14451. this.replacee.terminate();
  14452. }
  14453. this.emit("accepted", response, cause);
  14454. return this;
  14455. };
  14456. Session.prototype.terminated = function (message, cause) {
  14457. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  14458. return this;
  14459. }
  14460. this.endTime = new Date();
  14461. this.close();
  14462. this.emit("terminated", message, cause);
  14463. return this;
  14464. };
  14465. Session.prototype.connecting = function (request) {
  14466. this.emit("connecting", { request: request });
  14467. return this;
  14468. };
  14469. Session.C = Enums_1.SessionStatus;
  14470. return Session;
  14471. }(events_1.EventEmitter));
  14472. exports.Session = Session;
  14473. // tslint:disable-next-line:max-classes-per-file
  14474. var InviteServerContext = /** @class */ (function (_super) {
  14475. tslib_1.__extends(InviteServerContext, _super);
  14476. function InviteServerContext(ua, incomingInviteRequest) {
  14477. var _this = this;
  14478. if (!ua.configuration.sessionDescriptionHandlerFactory) {
  14479. ua.logger.warn("Can't build ISC without SDH Factory");
  14480. throw new Error("ISC Constructor Failed");
  14481. }
  14482. _this = _super.call(this, ua.configuration.sessionDescriptionHandlerFactory) || this;
  14483. _this._canceled = false;
  14484. _this.rseq = Math.floor(Math.random() * 10000);
  14485. _this.incomingRequest = incomingInviteRequest;
  14486. var request = incomingInviteRequest.message;
  14487. ServerContext_1.ServerContext.initializer(_this, ua, incomingInviteRequest);
  14488. _this.type = Enums_1.TypeStrings.InviteServerContext;
  14489. var contentDisp = request.parseHeader("Content-Disposition");
  14490. if (contentDisp && contentDisp.type === "render") {
  14491. _this.renderbody = request.body;
  14492. _this.rendertype = request.getHeader("Content-Type");
  14493. }
  14494. _this.status = Enums_1.SessionStatus.STATUS_INVITE_RECEIVED;
  14495. _this.fromTag = request.fromTag;
  14496. _this.id = request.callId + _this.fromTag;
  14497. _this.request = request;
  14498. _this.contact = _this.ua.contact.toString();
  14499. _this.logger = ua.getLogger("sip.inviteservercontext", _this.id);
  14500. // Save the session into the ua sessions collection.
  14501. _this.ua.sessions[_this.id] = _this;
  14502. // Set 100rel if necessary
  14503. var set100rel = function (header, relSetting) {
  14504. if (request.hasHeader(header) && request.getHeader(header).toLowerCase().indexOf("100rel") >= 0) {
  14505. _this.rel100 = relSetting;
  14506. }
  14507. };
  14508. set100rel("require", Constants_1.C.supported.REQUIRED);
  14509. set100rel("supported", Constants_1.C.supported.SUPPORTED);
  14510. // Set the toTag on the incoming request to the toTag which
  14511. // will be used in the response to the incoming request!!!
  14512. // FIXME: HACK: This is a hack to port an existing behavior.
  14513. // The behavior being ported appears to be a hack itself,
  14514. // so this is a hack to port a hack. At least one test spec
  14515. // relies on it (which is yet another hack).
  14516. _this.request.toTag = incomingInviteRequest.toTag;
  14517. _this.status = Enums_1.SessionStatus.STATUS_WAITING_FOR_ANSWER;
  14518. // Set userNoAnswerTimer
  14519. _this.timers.userNoAnswerTimer = setTimeout(function () {
  14520. incomingInviteRequest.reject({ statusCode: 408 });
  14521. _this.failed(request, Constants_1.C.causes.NO_ANSWER);
  14522. _this.terminated(request, Constants_1.C.causes.NO_ANSWER);
  14523. }, _this.ua.configuration.noAnswerTimeout || 60);
  14524. /* Set expiresTimer
  14525. * RFC3261 13.3.1
  14526. */
  14527. // Get the Expires header value if exists
  14528. if (request.hasHeader("expires")) {
  14529. var expires = Number(request.getHeader("expires") || 0) * 1000;
  14530. _this.timers.expiresTimer = setTimeout(function () {
  14531. if (_this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_ANSWER) {
  14532. incomingInviteRequest.reject({ statusCode: 487 });
  14533. _this.failed(request, Constants_1.C.causes.EXPIRES);
  14534. _this.terminated(request, Constants_1.C.causes.EXPIRES);
  14535. }
  14536. }, expires);
  14537. }
  14538. _this.errorListener = _this.onTransportError.bind(_this);
  14539. if (ua.transport) {
  14540. ua.transport.on("transportError", _this.errorListener);
  14541. }
  14542. return _this;
  14543. }
  14544. Object.defineProperty(InviteServerContext.prototype, "autoSendAnInitialProvisionalResponse", {
  14545. /**
  14546. * If true, a first provisional response after the 100 Trying
  14547. * will be sent automatically. This is false it the UAC required
  14548. * reliable provisional responses (100rel in Require header),
  14549. * otherwise it is true. The provisional is sent by calling
  14550. * `progress()` without any options.
  14551. *
  14552. * FIXME: TODO: It seems reasonable that the ISC user should
  14553. * be able to optionally disable this behavior. As the provisional
  14554. * is sent prior to the "invite" event being emitted, it's a known
  14555. * issue that the ISC user cannot register listeners or do any other
  14556. * setup prior to the call to `progress()`. As an example why this is
  14557. * an issue, setting `ua.configuration.rel100` to REQUIRED will result
  14558. * in an attempt by `progress()` to send a 183 with SDP produced by
  14559. * calling `getDescription()` on a session description handler, but
  14560. * the ISC user cannot perform any potentially required session description
  14561. * handler initialization (thus preventing the utilization of setting
  14562. * `ua.configuration.rel100` to REQUIRED). That begs the question of
  14563. * why this behavior is disabled when the UAC requires 100rel but not
  14564. * when the UAS requires 100rel? But ignoring that, it's just one example
  14565. * of a class of cases where the ISC user needs to do something prior
  14566. * to the first call to `progress()` and is unable to do so.
  14567. */
  14568. get: function () {
  14569. return this.rel100 === Constants_1.C.supported.REQUIRED ? false : true;
  14570. },
  14571. enumerable: true,
  14572. configurable: true
  14573. });
  14574. // type hack for servercontext interface
  14575. InviteServerContext.prototype.reply = function (options) {
  14576. if (options === void 0) { options = {}; }
  14577. return this;
  14578. };
  14579. // typing note: this was the only function using its super in ServerContext
  14580. // so the bottom half of this function is copied and paired down from that
  14581. InviteServerContext.prototype.reject = function (options) {
  14582. var _this = this;
  14583. if (options === void 0) { options = {}; }
  14584. // Check Session Status
  14585. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  14586. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  14587. }
  14588. this.logger.log("rejecting RTCSession");
  14589. var statusCode = options.statusCode || 480;
  14590. var reasonPhrase = Utils_1.Utils.getReasonPhrase(statusCode, options.reasonPhrase);
  14591. var extraHeaders = options.extraHeaders || [];
  14592. if (statusCode < 300 || statusCode > 699) {
  14593. throw new TypeError("Invalid statusCode: " + statusCode);
  14594. }
  14595. var body = options.body ? core_1.fromBodyLegacy(options.body) : undefined;
  14596. // FIXME: Need to redirect to someplae
  14597. var response = statusCode < 400 ?
  14598. this.incomingRequest.redirect([], { statusCode: statusCode, reasonPhrase: reasonPhrase, extraHeaders: extraHeaders, body: body }) :
  14599. this.incomingRequest.reject({ statusCode: statusCode, reasonPhrase: reasonPhrase, extraHeaders: extraHeaders, body: body });
  14600. (["rejected", "failed"]).forEach(function (event) {
  14601. _this.emit(event, response.message, reasonPhrase);
  14602. });
  14603. return this.terminated();
  14604. };
  14605. /**
  14606. * Accept the incoming INVITE request to start a Session.
  14607. * Replies to the INVITE request with a 200 Ok response.
  14608. * @param options Options bucket.
  14609. */
  14610. InviteServerContext.prototype.accept = function (options) {
  14611. var _this = this;
  14612. if (options === void 0) { options = {}; }
  14613. // FIXME: Need guard against calling more than once.
  14614. this._accept(options)
  14615. .then(function (_a) {
  14616. var message = _a.message, session = _a.session;
  14617. session.delegate = {
  14618. onAck: function (ackRequest) { return _this.onAck(ackRequest); },
  14619. onAckTimeout: function () { return _this.onAckTimeout(); },
  14620. onBye: function (byeRequest) { return _this.receiveRequest(byeRequest); },
  14621. onInfo: function (infoRequest) { return _this.receiveRequest(infoRequest); },
  14622. onInvite: function (inviteRequest) { return _this.receiveRequest(inviteRequest); },
  14623. onNotify: function (notifyRequest) { return _this.receiveRequest(notifyRequest); },
  14624. onPrack: function (prackRequest) { return _this.receiveRequest(prackRequest); },
  14625. onRefer: function (referRequest) { return _this.receiveRequest(referRequest); }
  14626. };
  14627. _this.session = session;
  14628. _this.status = Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK;
  14629. _this.accepted(message, Utils_1.Utils.getReasonPhrase(200));
  14630. })
  14631. .catch(function (error) {
  14632. _this.onContextError(error);
  14633. // FIXME: Assuming error due to async race on CANCEL and eating error.
  14634. if (!_this._canceled) {
  14635. throw error;
  14636. }
  14637. });
  14638. return this;
  14639. };
  14640. /**
  14641. * Report progress to the the caller.
  14642. * Replies to the INVITE request with a 1xx provisional response.
  14643. * @param options Options bucket.
  14644. */
  14645. InviteServerContext.prototype.progress = function (options) {
  14646. var _this = this;
  14647. if (options === void 0) { options = {}; }
  14648. // Ported
  14649. var statusCode = options.statusCode || 180;
  14650. if (statusCode < 100 || statusCode > 199) {
  14651. throw new TypeError("Invalid statusCode: " + statusCode);
  14652. }
  14653. // Ported
  14654. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  14655. this.logger.warn("Unexpected call for progress while terminated, ignoring");
  14656. return this;
  14657. }
  14658. // Added
  14659. if (this.status === Enums_1.SessionStatus.STATUS_ANSWERED) {
  14660. this.logger.warn("Unexpected call for progress while answered, ignoring");
  14661. return this;
  14662. }
  14663. // Added
  14664. if (this.status === Enums_1.SessionStatus.STATUS_ANSWERED_WAITING_FOR_PRACK) {
  14665. this.logger.warn("Unexpected call for progress while answered (waiting for prack), ignoring");
  14666. return this;
  14667. }
  14668. // After the first reliable provisional response for a request has been
  14669. // acknowledged, the UAS MAY send additional reliable provisional
  14670. // responses. The UAS MUST NOT send a second reliable provisional
  14671. // response until the first is acknowledged. After the first, it is
  14672. // RECOMMENDED that the UAS not send an additional reliable provisional
  14673. // response until the previous is acknowledged. The first reliable
  14674. // provisional response receives special treatment because it conveys
  14675. // the initial sequence number. If additional reliable provisional
  14676. // responses were sent before the first was acknowledged, the UAS could
  14677. // not be certain these were received in order.
  14678. // https://tools.ietf.org/html/rfc3262#section-3
  14679. if (this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_PRACK) {
  14680. this.logger.warn("Unexpected call for progress while waiting for prack, ignoring");
  14681. return this;
  14682. }
  14683. // Ported
  14684. if (options.statusCode === 100) {
  14685. try {
  14686. this.incomingRequest.trying();
  14687. }
  14688. catch (error) {
  14689. this.onContextError(error);
  14690. // FIXME: Assuming error due to async race on CANCEL and eating error.
  14691. if (!this._canceled) {
  14692. throw error;
  14693. }
  14694. }
  14695. return this;
  14696. }
  14697. // Standard provisional response.
  14698. if (!(this.rel100 === Constants_1.C.supported.REQUIRED) &&
  14699. !(this.rel100 === Constants_1.C.supported.SUPPORTED && options.rel100) &&
  14700. !(this.rel100 === Constants_1.C.supported.SUPPORTED && this.ua.configuration.rel100 === Constants_1.C.supported.REQUIRED)) {
  14701. this._progress(options)
  14702. .catch(function (error) {
  14703. _this.onContextError(error);
  14704. // FIXME: Assuming error due to async race on CANCEL and eating error.
  14705. if (!_this._canceled) {
  14706. throw error;
  14707. }
  14708. });
  14709. return this;
  14710. }
  14711. // Reliable provisional response.
  14712. this._reliableProgressWaitForPrack(options)
  14713. .catch(function (error) {
  14714. _this.onContextError(error);
  14715. // FIXME: Assuming error due to async race on CANCEL and eating error.
  14716. if (!_this._canceled) {
  14717. throw error;
  14718. }
  14719. });
  14720. return this;
  14721. };
  14722. /**
  14723. * Reject an unaccepted incoming INVITE request or send BYE if established session.
  14724. * @param options Options bucket. FIXME: This options bucket needs to be typed.
  14725. */
  14726. InviteServerContext.prototype.terminate = function (options) {
  14727. // The caller's UA MAY send a BYE for either confirmed or early dialogs,
  14728. // and the callee's UA MAY send a BYE on confirmed dialogs, but MUST NOT
  14729. // send a BYE on early dialogs. However, the callee's UA MUST NOT send a
  14730. // BYE on a confirmed dialog until it has received an ACK for its 2xx
  14731. // response or until the server transaction times out.
  14732. // https://tools.ietf.org/html/rfc3261#section-15
  14733. var _this = this;
  14734. if (options === void 0) { options = {}; }
  14735. // We don't yet have a dialog, so reject request.
  14736. if (!this.session) {
  14737. this.reject(options);
  14738. return this;
  14739. }
  14740. switch (this.session.sessionState) {
  14741. case core_1.SessionState.Initial:
  14742. this.reject(options);
  14743. return this;
  14744. case core_1.SessionState.Early:
  14745. this.reject(options);
  14746. return this;
  14747. case core_1.SessionState.AckWait:
  14748. this.session.delegate = {
  14749. // When ACK shows up, say BYE.
  14750. onAck: function () {
  14751. _this.sendRequest(Constants_1.C.BYE, options);
  14752. },
  14753. // Or the server transaction times out before the ACK arrives.
  14754. onAckTimeout: function () {
  14755. _this.sendRequest(Constants_1.C.BYE, options);
  14756. }
  14757. };
  14758. // Ported
  14759. this.emit("bye", this.request);
  14760. this.terminated();
  14761. return this;
  14762. case core_1.SessionState.Confirmed:
  14763. this.bye(options);
  14764. return this;
  14765. case core_1.SessionState.Terminated:
  14766. return this;
  14767. default:
  14768. return this;
  14769. }
  14770. };
  14771. InviteServerContext.prototype.onCancel = function (message) {
  14772. if (this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_ANSWER ||
  14773. this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_PRACK ||
  14774. this.status === Enums_1.SessionStatus.STATUS_ANSWERED_WAITING_FOR_PRACK ||
  14775. this.status === Enums_1.SessionStatus.STATUS_EARLY_MEDIA ||
  14776. this.status === Enums_1.SessionStatus.STATUS_ANSWERED) {
  14777. this.status = Enums_1.SessionStatus.STATUS_CANCELED;
  14778. this.incomingRequest.reject({ statusCode: 487 });
  14779. this.canceled();
  14780. this.rejected(message, Constants_1.C.causes.CANCELED);
  14781. this.failed(message, Constants_1.C.causes.CANCELED);
  14782. this.terminated(message, Constants_1.C.causes.CANCELED);
  14783. }
  14784. };
  14785. InviteServerContext.prototype.receiveRequest = function (incomingRequest) {
  14786. var _this = this;
  14787. switch (incomingRequest.message.method) {
  14788. case Constants_1.C.PRACK:
  14789. if (this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_PRACK ||
  14790. this.status === Enums_1.SessionStatus.STATUS_ANSWERED_WAITING_FOR_PRACK) {
  14791. if (!this.hasAnswer) {
  14792. this.sessionDescriptionHandler = this.setupSessionDescriptionHandler();
  14793. this.emit("SessionDescriptionHandler-created", this.sessionDescriptionHandler);
  14794. if (this.sessionDescriptionHandler.hasDescription(incomingRequest.message.getHeader("Content-Type") || "")) {
  14795. this.hasAnswer = true;
  14796. this.sessionDescriptionHandler.setDescription(incomingRequest.message.body, this.sessionDescriptionHandlerOptions, this.modifiers).then(function () {
  14797. clearTimeout(_this.timers.rel1xxTimer);
  14798. clearTimeout(_this.timers.prackTimer);
  14799. incomingRequest.accept();
  14800. if (_this.status === Enums_1.SessionStatus.STATUS_ANSWERED_WAITING_FOR_PRACK) {
  14801. _this.status = Enums_1.SessionStatus.STATUS_EARLY_MEDIA;
  14802. _this.accept();
  14803. }
  14804. _this.status = Enums_1.SessionStatus.STATUS_EARLY_MEDIA;
  14805. }, function (e) {
  14806. _this.logger.warn(e);
  14807. _this.terminate({
  14808. statusCode: "488",
  14809. reasonPhrase: "Bad Media Description"
  14810. });
  14811. _this.failed(incomingRequest.message, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  14812. _this.terminated(incomingRequest.message, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  14813. });
  14814. }
  14815. else {
  14816. this.terminate({
  14817. statusCode: "488",
  14818. reasonPhrase: "Bad Media Description"
  14819. });
  14820. this.failed(incomingRequest.message, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  14821. this.terminated(incomingRequest.message, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  14822. }
  14823. }
  14824. else {
  14825. clearTimeout(this.timers.rel1xxTimer);
  14826. clearTimeout(this.timers.prackTimer);
  14827. incomingRequest.accept();
  14828. if (this.status === Enums_1.SessionStatus.STATUS_ANSWERED_WAITING_FOR_PRACK) {
  14829. this.status = Enums_1.SessionStatus.STATUS_EARLY_MEDIA;
  14830. this.accept();
  14831. }
  14832. this.status = Enums_1.SessionStatus.STATUS_EARLY_MEDIA;
  14833. }
  14834. }
  14835. else if (this.status === Enums_1.SessionStatus.STATUS_EARLY_MEDIA) {
  14836. incomingRequest.accept();
  14837. }
  14838. break;
  14839. default:
  14840. _super.prototype.receiveRequest.call(this, incomingRequest);
  14841. break;
  14842. }
  14843. };
  14844. // Internal Function to setup the handler consistently
  14845. InviteServerContext.prototype.setupSessionDescriptionHandler = function () {
  14846. if (this.sessionDescriptionHandler) {
  14847. return this.sessionDescriptionHandler;
  14848. }
  14849. return this.sessionDescriptionHandlerFactory(this, this.ua.configuration.sessionDescriptionHandlerFactoryOptions);
  14850. };
  14851. InviteServerContext.prototype.generateResponseOfferAnswer = function (options) {
  14852. if (!this.session) {
  14853. var body = core_1.getBody(this.incomingRequest.message);
  14854. if (!body || body.contentDisposition !== "session") {
  14855. return this.getOffer(options);
  14856. }
  14857. else {
  14858. return this.setOfferAndGetAnswer(body, options);
  14859. }
  14860. }
  14861. else {
  14862. switch (this.session.signalingState) {
  14863. case core_1.SignalingState.Initial:
  14864. return this.getOffer(options);
  14865. case core_1.SignalingState.Stable:
  14866. return Promise.resolve(undefined);
  14867. case core_1.SignalingState.HaveLocalOffer:
  14868. // o Once the UAS has sent or received an answer to the initial
  14869. // offer, it MUST NOT generate subsequent offers in any responses
  14870. // to the initial INVITE. This means that a UAS based on this
  14871. // specification alone can never generate subsequent offers until
  14872. // completion of the initial transaction.
  14873. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  14874. return Promise.resolve(undefined);
  14875. case core_1.SignalingState.HaveRemoteOffer:
  14876. if (!this.session.offer) {
  14877. throw new Error("Session offer undefined");
  14878. }
  14879. return this.setOfferAndGetAnswer(this.session.offer, options);
  14880. case core_1.SignalingState.Closed:
  14881. throw new Error("Invalid signaling state " + this.session.signalingState + ".");
  14882. default:
  14883. throw new Error("Invalid signaling state " + this.session.signalingState + ".");
  14884. }
  14885. }
  14886. };
  14887. InviteServerContext.prototype.handlePrackOfferAnswer = function (request, options) {
  14888. if (!this.session) {
  14889. throw new Error("Session undefined.");
  14890. }
  14891. // If the PRACK doesn't have an offer/answer, nothing to be done.
  14892. var body = core_1.getBody(request.message);
  14893. if (!body || body.contentDisposition !== "session") {
  14894. return Promise.resolve(undefined);
  14895. }
  14896. // If the UAC receives a reliable provisional response with an offer
  14897. // (this would occur if the UAC sent an INVITE without an offer, in
  14898. // which case the first reliable provisional response will contain the
  14899. // offer), it MUST generate an answer in the PRACK. If the UAC receives
  14900. // a reliable provisional response with an answer, it MAY generate an
  14901. // additional offer in the PRACK. If the UAS receives a PRACK with an
  14902. // offer, it MUST place the answer in the 2xx to the PRACK.
  14903. // https://tools.ietf.org/html/rfc3262#section-5
  14904. switch (this.session.signalingState) {
  14905. case core_1.SignalingState.Initial:
  14906. // State should never be reached as first reliable provisional response must have answer/offer.
  14907. throw new Error("Invalid signaling state " + this.session.signalingState + ".");
  14908. case core_1.SignalingState.Stable:
  14909. // Receved answer.
  14910. return this.setAnswer(body, options).then(function () { return undefined; });
  14911. case core_1.SignalingState.HaveLocalOffer:
  14912. // State should never be reached as local offer would be answered by this PRACK
  14913. throw new Error("Invalid signaling state " + this.session.signalingState + ".");
  14914. case core_1.SignalingState.HaveRemoteOffer:
  14915. // Receved offer, generate answer.
  14916. return this.setOfferAndGetAnswer(body, options);
  14917. case core_1.SignalingState.Closed:
  14918. throw new Error("Invalid signaling state " + this.session.signalingState + ".");
  14919. default:
  14920. throw new Error("Invalid signaling state " + this.session.signalingState + ".");
  14921. }
  14922. };
  14923. /**
  14924. * Called when session canceled.
  14925. */
  14926. InviteServerContext.prototype.canceled = function () {
  14927. this._canceled = true;
  14928. return _super.prototype.canceled.call(this);
  14929. };
  14930. /**
  14931. * Called when session terminated.
  14932. * Using it here just for the PRACK timeout.
  14933. */
  14934. InviteServerContext.prototype.terminated = function (message, cause) {
  14935. this.prackNeverArrived();
  14936. return _super.prototype.terminated.call(this, message, cause);
  14937. };
  14938. /**
  14939. * A version of `accept` which resolves a session when the 200 Ok response is sent.
  14940. * @param options Options bucket.
  14941. * @throws {ClosedSessionDescriptionHandlerError} The session description handler closed before method completed.
  14942. * @throws {TransactionStateError} The transaction state does not allow for `accept()` to be called.
  14943. * Note that the transaction state can change while this call is in progress.
  14944. */
  14945. InviteServerContext.prototype._accept = function (options) {
  14946. var _this = this;
  14947. if (options === void 0) { options = {}; }
  14948. // FIXME: Ported - callback for in dialog INFO requests.
  14949. // Turns out accept() can be called more than once if we are waiting
  14950. // for a PRACK in which case "options" get completely tossed away.
  14951. // So this is broken in that case (and potentially other uses of options).
  14952. // Tempted to just try to fix it now, but leaving it broken for the moment.
  14953. this.onInfo = options.onInfo;
  14954. // The UAS MAY send a final response to the initial request before
  14955. // having received PRACKs for all unacknowledged reliable provisional
  14956. // responses, unless the final response is 2xx and any of the
  14957. // unacknowledged reliable provisional responses contained a session
  14958. // description. In that case, it MUST NOT send a final response until
  14959. // those provisional responses are acknowledged. If the UAS does send a
  14960. // final response when reliable responses are still unacknowledged, it
  14961. // SHOULD NOT continue to retransmit the unacknowledged reliable
  14962. // provisional responses, but it MUST be prepared to process PRACK
  14963. // requests for those outstanding responses. A UAS MUST NOT send new
  14964. // reliable provisional responses (as opposed to retransmissions of
  14965. // unacknowledged ones) after sending a final response to a request.
  14966. // https://tools.ietf.org/html/rfc3262#section-3
  14967. if (this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_PRACK) {
  14968. this.status = Enums_1.SessionStatus.STATUS_ANSWERED_WAITING_FOR_PRACK;
  14969. return this.waitForArrivalOfPrack()
  14970. .then(function () {
  14971. _this.status = Enums_1.SessionStatus.STATUS_ANSWERED;
  14972. clearTimeout(_this.timers.userNoAnswerTimer); // Ported
  14973. })
  14974. .then(function () { return _this.generateResponseOfferAnswer(options); })
  14975. .then(function (body) { return _this.incomingRequest.accept({ statusCode: 200, body: body }); });
  14976. }
  14977. // Ported
  14978. if (this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_ANSWER) {
  14979. this.status = Enums_1.SessionStatus.STATUS_ANSWERED;
  14980. }
  14981. else {
  14982. return Promise.reject(new Exceptions_1.Exceptions.InvalidStateError(this.status));
  14983. }
  14984. this.status = Enums_1.SessionStatus.STATUS_ANSWERED;
  14985. clearTimeout(this.timers.userNoAnswerTimer); // Ported
  14986. return this.generateResponseOfferAnswer(options)
  14987. .then(function (body) { return _this.incomingRequest.accept({ statusCode: 200, body: body }); });
  14988. };
  14989. /**
  14990. * A version of `progress` which resolves when the provisional response is sent.
  14991. * @param options Options bucket.
  14992. * @throws {ClosedSessionDescriptionHandlerError} The session description handler closed before method completed.
  14993. * @throws {TransactionStateError} The transaction state does not allow for `progress()` to be called.
  14994. * Note that the transaction state can change while this call is in progress.
  14995. */
  14996. InviteServerContext.prototype._progress = function (options) {
  14997. if (options === void 0) { options = {}; }
  14998. // Ported
  14999. var statusCode = options.statusCode || 180;
  15000. var reasonPhrase = options.reasonPhrase;
  15001. var extraHeaders = (options.extraHeaders || []).slice();
  15002. var body = options.body ? core_1.fromBodyLegacy(options.body) : undefined;
  15003. // The 183 (Session Progress) response is used to convey information
  15004. // about the progress of the call that is not otherwise classified. The
  15005. // Reason-Phrase, header fields, or message body MAY be used to convey
  15006. // more details about the call progress.
  15007. // https://tools.ietf.org/html/rfc3261#section-21.1.5
  15008. // It is the de facto industry standard to utilize 183 with SDP to provide "early media".
  15009. // While it is unlikely someone would want to send a 183 without SDP, so it should be an option.
  15010. if (statusCode === 183 && !body) {
  15011. return this._progressWithSDP(options);
  15012. }
  15013. try {
  15014. var progressResponse = this.incomingRequest.progress({ statusCode: statusCode, reasonPhrase: reasonPhrase, extraHeaders: extraHeaders, body: body });
  15015. this.emit("progress", progressResponse.message, reasonPhrase); // Ported
  15016. this.session = progressResponse.session;
  15017. return Promise.resolve(progressResponse);
  15018. }
  15019. catch (error) {
  15020. return Promise.reject(error);
  15021. }
  15022. };
  15023. /**
  15024. * A version of `progress` which resolves when the provisional response with sdp is sent.
  15025. * @param options Options bucket.
  15026. * @throws {ClosedSessionDescriptionHandlerError} The session description handler closed before method completed.
  15027. * @throws {TransactionStateError} The transaction state does not allow for `progress()` to be called.
  15028. * Note that the transaction state can change while this call is in progress.
  15029. */
  15030. InviteServerContext.prototype._progressWithSDP = function (options) {
  15031. var _this = this;
  15032. if (options === void 0) { options = {}; }
  15033. var statusCode = options.statusCode || 183;
  15034. var reasonPhrase = options.reasonPhrase;
  15035. var extraHeaders = (options.extraHeaders || []).slice();
  15036. // Get an offer/answer and send a reply.
  15037. return this.generateResponseOfferAnswer(options)
  15038. .then(function (body) { return _this.incomingRequest.progress({ statusCode: statusCode, reasonPhrase: reasonPhrase, extraHeaders: extraHeaders, body: body }); })
  15039. .then(function (progressResponse) {
  15040. _this.emit("progress", progressResponse.message, reasonPhrase); // Ported
  15041. _this.session = progressResponse.session;
  15042. return progressResponse;
  15043. });
  15044. };
  15045. /**
  15046. * A version of `progress` which resolves when the reliable provisional response is sent.
  15047. * @param options Options bucket.
  15048. * @throws {ClosedSessionDescriptionHandlerError} The session description handler closed before method completed.
  15049. * @throws {TransactionStateError} The transaction state does not allow for `progress()` to be called.
  15050. * Note that the transaction state can change while this call is in progress.
  15051. */
  15052. InviteServerContext.prototype._reliableProgress = function (options) {
  15053. var _this = this;
  15054. if (options === void 0) { options = {}; }
  15055. var statusCode = options.statusCode || 183;
  15056. var reasonPhrase = options.reasonPhrase;
  15057. var extraHeaders = (options.extraHeaders || []).slice();
  15058. extraHeaders.push("Require: 100rel");
  15059. extraHeaders.push("RSeq: " + Math.floor(Math.random() * 10000));
  15060. // Get an offer/answer and send a reply.
  15061. return this.generateResponseOfferAnswer(options)
  15062. .then(function (body) { return _this.incomingRequest.progress({ statusCode: statusCode, reasonPhrase: reasonPhrase, extraHeaders: extraHeaders, body: body }); })
  15063. .then(function (progressResponse) {
  15064. _this.emit("progress", progressResponse.message, reasonPhrase); // Ported
  15065. _this.session = progressResponse.session;
  15066. return progressResponse;
  15067. });
  15068. };
  15069. /**
  15070. * A version of `progress` which resolves when the reliable provisional response is acknowledged.
  15071. * @param options Options bucket.
  15072. * @throws {ClosedSessionDescriptionHandlerError} The session description handler closed before method completed.
  15073. * @throws {TransactionStateError} The transaction state does not allow for `progress()` to be called.
  15074. * Note that the transaction state can change while this call is in progress.
  15075. */
  15076. InviteServerContext.prototype._reliableProgressWaitForPrack = function (options) {
  15077. var _this = this;
  15078. if (options === void 0) { options = {}; }
  15079. var statusCode = options.statusCode || 183;
  15080. var reasonPhrase = options.reasonPhrase;
  15081. var extraHeaders = (options.extraHeaders || []).slice();
  15082. extraHeaders.push("Require: 100rel");
  15083. extraHeaders.push("RSeq: " + this.rseq++);
  15084. var body;
  15085. // Ported - set status.
  15086. this.status = Enums_1.SessionStatus.STATUS_WAITING_FOR_PRACK;
  15087. return new Promise(function (resolve, reject) {
  15088. var waitingForPrack = true;
  15089. return _this.generateResponseOfferAnswer(options)
  15090. .then(function (offerAnswer) {
  15091. body = offerAnswer;
  15092. return _this.incomingRequest.progress({ statusCode: statusCode, reasonPhrase: reasonPhrase, extraHeaders: extraHeaders, body: body });
  15093. })
  15094. .then(function (progressResponse) {
  15095. _this.emit("progress", progressResponse.message, reasonPhrase); // Ported
  15096. _this.session = progressResponse.session;
  15097. var prackRequest;
  15098. var prackResponse;
  15099. progressResponse.session.delegate = {
  15100. onPrack: function (request) {
  15101. prackRequest = request;
  15102. clearTimeout(prackWaitTimeoutTimer);
  15103. clearTimeout(rel1xxRetransmissionTimer);
  15104. if (!waitingForPrack) {
  15105. return;
  15106. }
  15107. waitingForPrack = false;
  15108. _this.handlePrackOfferAnswer(prackRequest, options)
  15109. .then(function (prackResponseBody) {
  15110. try {
  15111. prackResponse = prackRequest.accept({ statusCode: 200, body: prackResponseBody });
  15112. // Ported - set status.
  15113. if (_this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_PRACK) {
  15114. _this.status = Enums_1.SessionStatus.STATUS_WAITING_FOR_ANSWER;
  15115. }
  15116. _this.prackArrived();
  15117. resolve({ prackRequest: prackRequest, prackResponse: prackResponse, progressResponse: progressResponse });
  15118. }
  15119. catch (error) {
  15120. reject(error);
  15121. }
  15122. });
  15123. }
  15124. };
  15125. // https://tools.ietf.org/html/rfc3262#section-3
  15126. var prackWaitTimeout = function () {
  15127. if (!waitingForPrack) {
  15128. return;
  15129. }
  15130. waitingForPrack = false;
  15131. _this.logger.warn("No PRACK received, rejecting INVITE.");
  15132. clearTimeout(rel1xxRetransmissionTimer);
  15133. try {
  15134. _this.incomingRequest.reject({ statusCode: 504 });
  15135. _this.terminated(undefined, Constants_1.C.causes.NO_PRACK);
  15136. reject(new Exceptions_1.Exceptions.TerminatedSessionError());
  15137. }
  15138. catch (error) {
  15139. reject(error);
  15140. }
  15141. };
  15142. var prackWaitTimeoutTimer = setTimeout(prackWaitTimeout, core_1.Timers.T1 * 64);
  15143. // https://tools.ietf.org/html/rfc3262#section-3
  15144. var rel1xxRetransmission = function () {
  15145. try {
  15146. _this.incomingRequest.progress({ statusCode: statusCode, reasonPhrase: reasonPhrase, extraHeaders: extraHeaders, body: body });
  15147. }
  15148. catch (error) {
  15149. waitingForPrack = false;
  15150. reject(error);
  15151. return;
  15152. }
  15153. rel1xxRetransmissionTimer = setTimeout(rel1xxRetransmission, timeout *= 2);
  15154. };
  15155. var timeout = core_1.Timers.T1;
  15156. var rel1xxRetransmissionTimer = setTimeout(rel1xxRetransmission, timeout);
  15157. });
  15158. });
  15159. };
  15160. /**
  15161. * Callback for when ACK for a 2xx response is never received.
  15162. * @param session Session the ACK never arrived for
  15163. */
  15164. InviteServerContext.prototype.onAckTimeout = function () {
  15165. if (this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK) {
  15166. this.logger.log("no ACK received for an extended period of time, terminating the call");
  15167. if (!this.session) {
  15168. throw new Error("Session undefined.");
  15169. }
  15170. this.session.bye();
  15171. this.terminated(undefined, Constants_1.C.causes.NO_ACK);
  15172. }
  15173. };
  15174. /**
  15175. * FIXME: TODO: The current library interface presents async methods without a
  15176. * proper async error handling mechanism. Arguably a promise based interface
  15177. * would be an improvement over the pattern of returning `this`. The approach has
  15178. * been generally along the lines of log a error and terminate.
  15179. */
  15180. InviteServerContext.prototype.onContextError = function (error) {
  15181. var statusCode = 480;
  15182. if (error instanceof core_1.Exception) { // There might be interest in catching these Exceptions.
  15183. if (error instanceof Exceptions_1.Exceptions.SessionDescriptionHandlerError) {
  15184. this.logger.error(error.message);
  15185. if (error.error) {
  15186. this.logger.error(error.error);
  15187. }
  15188. }
  15189. else if (error instanceof Exceptions_1.Exceptions.TerminatedSessionError) {
  15190. // PRACK never arrived, so we timed out waiting for it.
  15191. this.logger.warn("Incoming session terminated while waiting for PRACK.");
  15192. }
  15193. else if (error instanceof Exceptions_1.Exceptions.UnsupportedSessionDescriptionContentTypeError) {
  15194. statusCode = 415;
  15195. }
  15196. else if (error instanceof core_1.Exception) {
  15197. this.logger.error(error.message);
  15198. }
  15199. }
  15200. else if (error instanceof Error) { // Other Errors hould go uncaught.
  15201. this.logger.error(error.message);
  15202. }
  15203. else {
  15204. // We don't actually know what a session description handler implementation might throw
  15205. // our way, so as a last resort, just assume we are getting an "any" and log it.
  15206. this.logger.error("An error occurred in the session description handler.");
  15207. this.logger.error(error);
  15208. }
  15209. try {
  15210. this.incomingRequest.reject({ statusCode: statusCode }); // "Temporarily Unavailable"
  15211. this.failed(this.incomingRequest.message, error.message);
  15212. this.terminated(this.incomingRequest.message, error.message);
  15213. }
  15214. catch (error) {
  15215. return;
  15216. }
  15217. };
  15218. InviteServerContext.prototype.prackArrived = function () {
  15219. if (this.waitingForPrackResolve) {
  15220. this.waitingForPrackResolve();
  15221. }
  15222. this.waitingForPrackPromise = undefined;
  15223. this.waitingForPrackResolve = undefined;
  15224. this.waitingForPrackReject = undefined;
  15225. };
  15226. InviteServerContext.prototype.prackNeverArrived = function () {
  15227. if (this.waitingForPrackReject) {
  15228. this.waitingForPrackReject(new Exceptions_1.Exceptions.TerminatedSessionError());
  15229. }
  15230. this.waitingForPrackPromise = undefined;
  15231. this.waitingForPrackResolve = undefined;
  15232. this.waitingForPrackReject = undefined;
  15233. };
  15234. /**
  15235. * @throws {Exceptions.TerminatedSessionError} The session terminated before being accepted (i.e. cancel arrived).
  15236. */
  15237. InviteServerContext.prototype.waitForArrivalOfPrack = function () {
  15238. var _this = this;
  15239. if (this.waitingForPrackPromise) {
  15240. throw new Error("Already waiting for PRACK");
  15241. }
  15242. this.waitingForPrackPromise = new Promise(function (resolve, reject) {
  15243. _this.waitingForPrackResolve = resolve;
  15244. _this.waitingForPrackReject = reject;
  15245. });
  15246. return this.waitingForPrackPromise;
  15247. };
  15248. InviteServerContext.prototype.getOffer = function (options) {
  15249. this.hasOffer = true;
  15250. var sdh = this.getSessionDescriptionHandler();
  15251. return sdh
  15252. .getDescription(options.sessionDescriptionHandlerOptions, options.modifiers)
  15253. .then(function (bodyObj) { return Utils_1.Utils.fromBodyObj(bodyObj); });
  15254. };
  15255. InviteServerContext.prototype.setAnswer = function (answer, options) {
  15256. this.hasAnswer = true;
  15257. var sdh = this.getSessionDescriptionHandler();
  15258. if (!sdh.hasDescription(answer.contentType)) {
  15259. return Promise.reject(new Exceptions_1.Exceptions.UnsupportedSessionDescriptionContentTypeError());
  15260. }
  15261. return sdh
  15262. .setDescription(answer.content, options.sessionDescriptionHandlerOptions, options.modifiers);
  15263. };
  15264. InviteServerContext.prototype.setOfferAndGetAnswer = function (offer, options) {
  15265. this.hasOffer = true;
  15266. this.hasAnswer = true;
  15267. var sdh = this.getSessionDescriptionHandler();
  15268. if (!sdh.hasDescription(offer.contentType)) {
  15269. return Promise.reject(new Exceptions_1.Exceptions.UnsupportedSessionDescriptionContentTypeError());
  15270. }
  15271. return sdh
  15272. .setDescription(offer.content, options.sessionDescriptionHandlerOptions, options.modifiers)
  15273. .then(function () { return sdh.getDescription(options.sessionDescriptionHandlerOptions, options.modifiers); })
  15274. .then(function (bodyObj) { return Utils_1.Utils.fromBodyObj(bodyObj); });
  15275. };
  15276. InviteServerContext.prototype.getSessionDescriptionHandler = function () {
  15277. // Create our session description handler if not already done so...
  15278. var sdh = this.sessionDescriptionHandler = this.setupSessionDescriptionHandler();
  15279. // FIXME: Ported - this can get emitted multiple times even when only created once... don't we care?
  15280. this.emit("SessionDescriptionHandler-created", this.sessionDescriptionHandler);
  15281. // Return.
  15282. return sdh;
  15283. };
  15284. return InviteServerContext;
  15285. }(Session));
  15286. exports.InviteServerContext = InviteServerContext;
  15287. // tslint:disable-next-line:max-classes-per-file
  15288. var InviteClientContext = /** @class */ (function (_super) {
  15289. tslib_1.__extends(InviteClientContext, _super);
  15290. function InviteClientContext(ua, target, options, modifiers) {
  15291. if (options === void 0) { options = {}; }
  15292. if (modifiers === void 0) { modifiers = []; }
  15293. var _this = this;
  15294. if (!ua.configuration.sessionDescriptionHandlerFactory) {
  15295. ua.logger.warn("Can't build ISC without SDH Factory");
  15296. throw new Error("ICC Constructor Failed");
  15297. }
  15298. options.params = options.params || {};
  15299. var anonymous = options.anonymous || false;
  15300. var fromTag = Utils_1.Utils.newTag();
  15301. options.params.fromTag = fromTag;
  15302. /* Do not add ;ob in initial forming dialog requests if the registration over
  15303. * the current connection got a GRUU URI.
  15304. */
  15305. var contact = ua.contact.toString({
  15306. anonymous: anonymous,
  15307. outbound: anonymous ? !ua.contact.tempGruu : !ua.contact.pubGruu
  15308. });
  15309. var extraHeaders = (options.extraHeaders || []).slice();
  15310. if (anonymous && ua.configuration.uri) {
  15311. options.params.fromDisplayName = "Anonymous";
  15312. options.params.fromUri = "sip:anonymous@anonymous.invalid";
  15313. extraHeaders.push("P-Preferred-Identity: " + ua.configuration.uri.toString());
  15314. extraHeaders.push("Privacy: id");
  15315. }
  15316. extraHeaders.push("Contact: " + contact);
  15317. // this is UA.C.ALLOWED_METHODS, removed to get around circular dependency
  15318. extraHeaders.push("Allow: " + [
  15319. "ACK",
  15320. "CANCEL",
  15321. "INVITE",
  15322. "MESSAGE",
  15323. "BYE",
  15324. "OPTIONS",
  15325. "INFO",
  15326. "NOTIFY",
  15327. "REFER"
  15328. ].toString());
  15329. if (ua.configuration.rel100 === Constants_1.C.supported.REQUIRED) {
  15330. extraHeaders.push("Require: 100rel");
  15331. }
  15332. if (ua.configuration.replaces === Constants_1.C.supported.REQUIRED) {
  15333. extraHeaders.push("Require: replaces");
  15334. }
  15335. options.extraHeaders = extraHeaders;
  15336. _this = _super.call(this, ua.configuration.sessionDescriptionHandlerFactory) || this;
  15337. ClientContext_1.ClientContext.initializer(_this, ua, Constants_1.C.INVITE, target, options);
  15338. _this.earlyMediaSessionDescriptionHandlers = new Map();
  15339. _this.type = Enums_1.TypeStrings.InviteClientContext;
  15340. _this.passedOptions = options; // Save for later to use with refer
  15341. _this.sessionDescriptionHandlerOptions = options.sessionDescriptionHandlerOptions || {};
  15342. _this.modifiers = modifiers;
  15343. _this.inviteWithoutSdp = options.inviteWithoutSdp || false;
  15344. // Set anonymous property
  15345. _this.anonymous = options.anonymous || false;
  15346. // Custom data to be sent either in INVITE or in ACK
  15347. _this.renderbody = options.renderbody || undefined;
  15348. _this.rendertype = options.rendertype || "text/plain";
  15349. // Session parameter initialization
  15350. _this.fromTag = fromTag;
  15351. _this.contact = contact;
  15352. // Check Session Status
  15353. if (_this.status !== Enums_1.SessionStatus.STATUS_NULL) {
  15354. throw new Exceptions_1.Exceptions.InvalidStateError(_this.status);
  15355. }
  15356. // OutgoingSession specific parameters
  15357. _this.isCanceled = false;
  15358. _this.received100 = false;
  15359. _this.method = Constants_1.C.INVITE;
  15360. _this.logger = ua.getLogger("sip.inviteclientcontext");
  15361. ua.applicants[_this.toString()] = _this;
  15362. _this.id = _this.request.callId + _this.fromTag;
  15363. _this.onInfo = options.onInfo;
  15364. _this.errorListener = _this.onTransportError.bind(_this);
  15365. if (ua.transport) {
  15366. ua.transport.on("transportError", _this.errorListener);
  15367. }
  15368. return _this;
  15369. }
  15370. InviteClientContext.prototype.receiveResponse = function (response) {
  15371. throw new Error("Unimplemented.");
  15372. };
  15373. // hack for getting around ClientContext interface
  15374. InviteClientContext.prototype.send = function () {
  15375. this.sendInvite();
  15376. return this;
  15377. };
  15378. InviteClientContext.prototype.invite = function () {
  15379. var _this = this;
  15380. // Save the session into the ua sessions collection.
  15381. // Note: placing in constructor breaks call to request.cancel on close... User does not need this anyway
  15382. this.ua.sessions[this.id] = this;
  15383. // This should allow the function to return so that listeners can be set up for these events
  15384. Promise.resolve().then(function () {
  15385. // FIXME: There is a race condition where cancel (or terminate) can be called synchronously after invite.
  15386. if (_this.isCanceled || _this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  15387. return;
  15388. }
  15389. if (_this.inviteWithoutSdp) {
  15390. // just send an invite with no sdp...
  15391. if (_this.renderbody && _this.rendertype) {
  15392. _this.request.body = {
  15393. body: _this.renderbody,
  15394. contentType: _this.rendertype
  15395. };
  15396. }
  15397. _this.status = Enums_1.SessionStatus.STATUS_INVITE_SENT;
  15398. _this.send();
  15399. }
  15400. else {
  15401. // Initialize Media Session
  15402. _this.sessionDescriptionHandler = _this.sessionDescriptionHandlerFactory(_this, _this.ua.configuration.sessionDescriptionHandlerFactoryOptions || {});
  15403. _this.emit("SessionDescriptionHandler-created", _this.sessionDescriptionHandler);
  15404. _this.sessionDescriptionHandler.getDescription(_this.sessionDescriptionHandlerOptions, _this.modifiers)
  15405. .then(function (description) {
  15406. // FIXME: There is a race condition where cancel (or terminate) can be called (a)synchronously after invite.
  15407. if (_this.isCanceled || _this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  15408. return;
  15409. }
  15410. _this.hasOffer = true;
  15411. _this.request.body = description;
  15412. _this.status = Enums_1.SessionStatus.STATUS_INVITE_SENT;
  15413. _this.send();
  15414. }, function (err) {
  15415. if (err.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  15416. _this.logger.log(err.message);
  15417. if (err.error) {
  15418. _this.logger.log(err.error);
  15419. }
  15420. }
  15421. if (_this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  15422. return;
  15423. }
  15424. _this.failed(undefined, Constants_1.C.causes.WEBRTC_ERROR);
  15425. _this.terminated(undefined, Constants_1.C.causes.WEBRTC_ERROR);
  15426. });
  15427. }
  15428. });
  15429. return this;
  15430. };
  15431. InviteClientContext.prototype.cancel = function (options) {
  15432. if (options === void 0) { options = {}; }
  15433. // Check Session Status
  15434. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED || this.status === Enums_1.SessionStatus.STATUS_CONFIRMED) {
  15435. throw new Exceptions_1.Exceptions.InvalidStateError(this.status);
  15436. }
  15437. if (this.isCanceled) {
  15438. throw new Exceptions_1.Exceptions.InvalidStateError(Enums_1.SessionStatus.STATUS_CANCELED);
  15439. }
  15440. this.isCanceled = true;
  15441. this.logger.log("Canceling session");
  15442. var cancelReason = Utils_1.Utils.getCancelReason(options.statusCode, options.reasonPhrase);
  15443. options.extraHeaders = (options.extraHeaders || []).slice();
  15444. if (this.outgoingInviteRequest) {
  15445. this.logger.warn("Canceling session before it was created");
  15446. this.outgoingInviteRequest.cancel(cancelReason, options);
  15447. }
  15448. return this.canceled();
  15449. };
  15450. InviteClientContext.prototype.terminate = function (options) {
  15451. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  15452. return this;
  15453. }
  15454. if (this.status === Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK || this.status === Enums_1.SessionStatus.STATUS_CONFIRMED) {
  15455. this.bye(options);
  15456. }
  15457. else {
  15458. this.cancel(options);
  15459. }
  15460. return this;
  15461. };
  15462. /**
  15463. * 13.2.1 Creating the Initial INVITE
  15464. *
  15465. * Since the initial INVITE represents a request outside of a dialog,
  15466. * its construction follows the procedures of Section 8.1.1. Additional
  15467. * processing is required for the specific case of INVITE.
  15468. *
  15469. * An Allow header field (Section 20.5) SHOULD be present in the INVITE.
  15470. * It indicates what methods can be invoked within a dialog, on the UA
  15471. * sending the INVITE, for the duration of the dialog. For example, a
  15472. * UA capable of receiving INFO requests within a dialog [34] SHOULD
  15473. * include an Allow header field listing the INFO method.
  15474. *
  15475. * A Supported header field (Section 20.37) SHOULD be present in the
  15476. * INVITE. It enumerates all the extensions understood by the UAC.
  15477. *
  15478. * An Accept (Section 20.1) header field MAY be present in the INVITE.
  15479. * It indicates which Content-Types are acceptable to the UA, in both
  15480. * the response received by it, and in any subsequent requests sent to
  15481. * it within dialogs established by the INVITE. The Accept header field
  15482. * is especially useful for indicating support of various session
  15483. * description formats.
  15484. *
  15485. * The UAC MAY add an Expires header field (Section 20.19) to limit the
  15486. * validity of the invitation. If the time indicated in the Expires
  15487. * header field is reached and no final answer for the INVITE has been
  15488. * received, the UAC core SHOULD generate a CANCEL request for the
  15489. * INVITE, as per Section 9.
  15490. *
  15491. * A UAC MAY also find it useful to add, among others, Subject (Section
  15492. * 20.36), Organization (Section 20.25) and User-Agent (Section 20.41)
  15493. * header fields. They all contain information related to the INVITE.
  15494. *
  15495. * The UAC MAY choose to add a message body to the INVITE. Section
  15496. * 8.1.1.10 deals with how to construct the header fields -- Content-
  15497. * Type among others -- needed to describe the message body.
  15498. *
  15499. * https://tools.ietf.org/html/rfc3261#section-13.2.1
  15500. */
  15501. InviteClientContext.prototype.sendInvite = function () {
  15502. // There are special rules for message bodies that contain a session
  15503. // description - their corresponding Content-Disposition is "session".
  15504. // SIP uses an offer/answer model where one UA sends a session
  15505. // description, called the offer, which contains a proposed description
  15506. // of the session. The offer indicates the desired communications means
  15507. // (audio, video, games), parameters of those means (such as codec
  15508. // types) and addresses for receiving media from the answerer. The
  15509. // other UA responds with another session description, called the
  15510. // answer, which indicates which communications means are accepted, the
  15511. // parameters that apply to those means, and addresses for receiving
  15512. // media from the offerer. An offer/answer exchange is within the
  15513. // context of a dialog, so that if a SIP INVITE results in multiple
  15514. // dialogs, each is a separate offer/answer exchange. The offer/answer
  15515. // model defines restrictions on when offers and answers can be made
  15516. // (for example, you cannot make a new offer while one is in progress).
  15517. // This results in restrictions on where the offers and answers can
  15518. // appear in SIP messages. In this specification, offers and answers
  15519. // can only appear in INVITE requests and responses, and ACK. The usage
  15520. // of offers and answers is further restricted. For the initial INVITE
  15521. // transaction, the rules are:
  15522. //
  15523. // o The initial offer MUST be in either an INVITE or, if not there,
  15524. // in the first reliable non-failure message from the UAS back to
  15525. // the UAC. In this specification, that is the final 2xx
  15526. // response.
  15527. //
  15528. // o If the initial offer is in an INVITE, the answer MUST be in a
  15529. // reliable non-failure message from UAS back to UAC which is
  15530. // correlated to that INVITE. For this specification, that is
  15531. // only the final 2xx response to that INVITE. That same exact
  15532. // answer MAY also be placed in any provisional responses sent
  15533. // prior to the answer. The UAC MUST treat the first session
  15534. // description it receives as the answer, and MUST ignore any
  15535. // session descriptions in subsequent responses to the initial
  15536. // INVITE.
  15537. //
  15538. // o If the initial offer is in the first reliable non-failure
  15539. // message from the UAS back to UAC, the answer MUST be in the
  15540. // acknowledgement for that message (in this specification, ACK
  15541. // for a 2xx response).
  15542. //
  15543. // o After having sent or received an answer to the first offer, the
  15544. // UAC MAY generate subsequent offers in requests based on rules
  15545. // specified for that method, but only if it has received answers
  15546. // to any previous offers, and has not sent any offers to which it
  15547. // hasn't gotten an answer.
  15548. //
  15549. // o Once the UAS has sent or received an answer to the initial
  15550. // offer, it MUST NOT generate subsequent offers in any responses
  15551. // to the initial INVITE. This means that a UAS based on this
  15552. // specification alone can never generate subsequent offers until
  15553. // completion of the initial transaction.
  15554. //
  15555. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  15556. var _this = this;
  15557. // 5 The Offer/Answer Model and PRACK
  15558. //
  15559. // RFC 3261 describes guidelines for the sets of messages in which
  15560. // offers and answers [3] can appear. Based on those guidelines, this
  15561. // extension provides additional opportunities for offer/answer
  15562. // exchanges.
  15563. // If the INVITE contained an offer, the UAS MAY generate an answer in a
  15564. // reliable provisional response (assuming these are supported by the
  15565. // UAC). That results in the establishment of the session before
  15566. // completion of the call. Similarly, if a reliable provisional
  15567. // response is the first reliable message sent back to the UAC, and the
  15568. // INVITE did not contain an offer, one MUST appear in that reliable
  15569. // provisional response.
  15570. // If the UAC receives a reliable provisional response with an offer
  15571. // (this would occur if the UAC sent an INVITE without an offer, in
  15572. // which case the first reliable provisional response will contain the
  15573. // offer), it MUST generate an answer in the PRACK. If the UAC receives
  15574. // a reliable provisional response with an answer, it MAY generate an
  15575. // additional offer in the PRACK. If the UAS receives a PRACK with an
  15576. // offer, it MUST place the answer in the 2xx to the PRACK.
  15577. // Once an answer has been sent or received, the UA SHOULD establish the
  15578. // session based on the parameters of the offer and answer, even if the
  15579. // original INVITE itself has not been responded to.
  15580. // If the UAS had placed a session description in any reliable
  15581. // provisional response that is unacknowledged when the INVITE is
  15582. // accepted, the UAS MUST delay sending the 2xx until the provisional
  15583. // response is acknowledged. Otherwise, the reliability of the 1xx
  15584. // cannot be guaranteed, and reliability is needed for proper operation
  15585. // of the offer/answer exchange.
  15586. // All user agents that support this extension MUST support all
  15587. // offer/answer exchanges that are possible based on the rules in
  15588. // Section 13.2 of RFC 3261, based on the existence of INVITE and PRACK
  15589. // as requests, and 2xx and reliable 1xx as non-failure reliable
  15590. // responses.
  15591. //
  15592. // https://tools.ietf.org/html/rfc3262#section-5
  15593. ////
  15594. // The Offer/Answer Model Implementation
  15595. //
  15596. // The offer/answer model is straight forward, but one MUST READ the specifications...
  15597. //
  15598. // 13.2.1 Creating the Initial INVITE (paragraph 8 in particular)
  15599. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  15600. //
  15601. // 5 The Offer/Answer Model and PRACK
  15602. // https://tools.ietf.org/html/rfc3262#section-5
  15603. //
  15604. // Session Initiation Protocol (SIP) Usage of the Offer/Answer Model
  15605. // https://tools.ietf.org/html/rfc6337
  15606. //
  15607. // *** IMPORTANT IMPLEMENTATION CHOICES ***
  15608. //
  15609. // TLDR...
  15610. //
  15611. // 1) Only one offer/answer exchange permitted during initial INVITE.
  15612. // 2) No "early media" if the initial offer is in an INVITE.
  15613. //
  15614. //
  15615. // 1) Initial Offer/Answer Restriction.
  15616. //
  15617. // Our implementation replaces the following bullet point...
  15618. //
  15619. // o After having sent or received an answer to the first offer, the
  15620. // UAC MAY generate subsequent offers in requests based on rules
  15621. // specified for that method, but only if it has received answers
  15622. // to any previous offers, and has not sent any offers to which it
  15623. // hasn't gotten an answer.
  15624. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  15625. //
  15626. // ...with...
  15627. //
  15628. // o After having sent or received an answer to the first offer, the
  15629. // UAC MUST NOT generate subsequent offers in requests based on rules
  15630. // specified for that method.
  15631. //
  15632. // ...which in combination with this bullet point...
  15633. //
  15634. // o Once the UAS has sent or received an answer to the initial
  15635. // offer, it MUST NOT generate subsequent offers in any responses
  15636. // to the initial INVITE. This means that a UAS based on this
  15637. // specification alone can never generate subsequent offers until
  15638. // completion of the initial transaction.
  15639. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  15640. //
  15641. // ...ensures that EXACTLY ONE offer/answer exchange will occur
  15642. // during an initial out of dialog INVITE request made by our UAC.
  15643. //
  15644. //
  15645. // 2) Early Media Restriction.
  15646. //
  15647. // While our implementation adheres to the following bullet point...
  15648. //
  15649. // o If the initial offer is in an INVITE, the answer MUST be in a
  15650. // reliable non-failure message from UAS back to UAC which is
  15651. // correlated to that INVITE. For this specification, that is
  15652. // only the final 2xx response to that INVITE. That same exact
  15653. // answer MAY also be placed in any provisional responses sent
  15654. // prior to the answer. The UAC MUST treat the first session
  15655. // description it receives as the answer, and MUST ignore any
  15656. // session descriptions in subsequent responses to the initial
  15657. // INVITE.
  15658. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  15659. //
  15660. // We have made the following implementation decision with regard to early media...
  15661. //
  15662. // o If the initial offer is in the INVITE, the answer from the
  15663. // UAS back to the UAC will establish a media session only
  15664. // only after the final 2xx response to that INVITE is received.
  15665. //
  15666. // The reason for this decision is rooted in a restriction currently
  15667. // inherent in WebRTC. Specifically, while a SIP INVITE request with an
  15668. // initial offer may fork resulting in more than one provisional answer,
  15669. // there is currently no easy/good way to to "fork" an offer generated
  15670. // by a peer connection. In particular, a WebRTC offer currently may only
  15671. // be matched with one answer and we have no good way to know which
  15672. // "provisional answer" is going to be the "final answer". So we have
  15673. // decided to punt and not create any "early media" sessions in this case.
  15674. //
  15675. // The upshot is that if you want "early media", you must not put the
  15676. // initial offer in the INVITE. Instead, force the UAS to provide the
  15677. // initial offer by sending an INVITE without an offer. In the WebRTC
  15678. // case this allows us to create a unique peer connection with a unique
  15679. // answer for every provisional offer with "early media" on all of them.
  15680. ////
  15681. ////
  15682. // ROADMAP: The Offer/Answer Model Implementation
  15683. //
  15684. // The "no early media if offer in INVITE" implementation is not a
  15685. // welcome one. The masses want it. The want it and they want it
  15686. // to work for WebRTC (so they want to have their cake and eat too).
  15687. //
  15688. // So while we currently cannot make the offer in INVITE+forking+webrtc
  15689. // case work, we decided to do the following...
  15690. //
  15691. // 1) modify SDH Factory to provide an initial offer without giving us the SDH, and then...
  15692. // 2) stick that offer in the initial INVITE, and when 183 with initial answer is received...
  15693. // 3) ask SDH Factory if it supports "earlyRemoteAnswer"
  15694. // a) if true, ask SDH Factory to createSDH(localOffer).then((sdh) => sdh.setDescription(remoteAnswer)
  15695. // b) if false, defer getting a SDH until 2xx response is received
  15696. //
  15697. // Our supplied WebRTC SDH will default to behavior 3b which works in forking environment (without)
  15698. // early media if initial offer is in the INVITE). We will, however, provide an "inviteWillNotFork"
  15699. // option which if set to "true" will have our supplied WebRTC SDH behave in the 3a manner.
  15700. // That will result in
  15701. // - early media working with initial offer in the INVITE, and...
  15702. // - if the INVITE forks, the session terminating with an ERROR that reads like
  15703. // "You set 'inviteWillNotFork' to true but the INVITE forked. You can't eat your cake, and have it too."
  15704. // - furthermore, we accept that users will report that error to us as "bug" regardless
  15705. //
  15706. // So, SDH Factory is going to end up with a new interface along the lines of...
  15707. //
  15708. // interface SessionDescriptionHandlerFactory {
  15709. // makeLocalOffer(): Promise<ContentTypeAndBody>;
  15710. // makeSessionDescriptionHandler(
  15711. // initialOffer: ContentTypeAndBody, offerType: "local" | "remote"
  15712. // ): Promise<SessionDescriptionHandler>;
  15713. // supportsEarlyRemoteAnswer: boolean;
  15714. // supportsContentType(contentType: string): boolean;
  15715. // getDescription(description: ContentTypeAndBody): Promise<ContentTypeAndBody>
  15716. // setDescription(description: ContentTypeAndBody): Promise<void>
  15717. // }
  15718. //
  15719. // We should be able to get rid of all the hasOffer/hasAnswer tracking code and otherwise code
  15720. // it up to the same interaction with the SDH Factory and SDH regardless of signaling scenario.
  15721. ////
  15722. // Send the INVITE request.
  15723. this.outgoingInviteRequest = this.ua.userAgentCore.invite(this.request, {
  15724. onAccept: function (inviteResponse) { return _this.onAccept(inviteResponse); },
  15725. onProgress: function (inviteResponse) { return _this.onProgress(inviteResponse); },
  15726. onRedirect: function (inviteResponse) { return _this.onRedirect(inviteResponse); },
  15727. onReject: function (inviteResponse) { return _this.onReject(inviteResponse); },
  15728. onTrying: function (inviteResponse) { return _this.onTrying(inviteResponse); }
  15729. });
  15730. };
  15731. InviteClientContext.prototype.ackAndBye = function (inviteResponse, session, statusCode, reasonPhrase) {
  15732. if (!this.ua.userAgentCore) {
  15733. throw new Error("Method requires user agent core.");
  15734. }
  15735. var extraHeaders = [];
  15736. if (statusCode) {
  15737. extraHeaders.push("Reason: " + Utils_1.Utils.getReasonHeaderValue(statusCode, reasonPhrase));
  15738. }
  15739. var outgoingAckRequest = inviteResponse.ack();
  15740. this.emit("ack", outgoingAckRequest.message);
  15741. var outgoingByeRequest = session.bye(undefined, { extraHeaders: extraHeaders });
  15742. this.emit("bye", outgoingByeRequest.message);
  15743. };
  15744. InviteClientContext.prototype.disposeEarlyMedia = function () {
  15745. if (!this.earlyMediaSessionDescriptionHandlers) {
  15746. throw new Error("Early media session description handlers undefined.");
  15747. }
  15748. this.earlyMediaSessionDescriptionHandlers.forEach(function (sessionDescriptionHandler) {
  15749. sessionDescriptionHandler.close();
  15750. });
  15751. };
  15752. /**
  15753. * Handle final response to initial INVITE.
  15754. * @param inviteResponse 2xx response.
  15755. */
  15756. InviteClientContext.prototype.onAccept = function (inviteResponse) {
  15757. var _this = this;
  15758. if (!this.earlyMediaSessionDescriptionHandlers) {
  15759. throw new Error("Early media session description handlers undefined.");
  15760. }
  15761. var response = inviteResponse.message;
  15762. var session = inviteResponse.session;
  15763. // Our transaction layer is "non-standard" in that it will only
  15764. // pass us a 2xx response once per branch, so there is no need to
  15765. // worry about dealing with 2xx retransmissions. However, we can
  15766. // and do still get 2xx responses for multiple branches (when an
  15767. // INVITE is forked) which may create multiple confirmed dialogs.
  15768. // Herein we are acking and sending a bye to any confirmed dialogs
  15769. // which arrive beyond the first one. This is the desired behavior
  15770. // for most applications (but certainly not all).
  15771. // If we already received a confirmed dialog, ack & bye this session.
  15772. if (this.session) {
  15773. this.ackAndBye(inviteResponse, session);
  15774. return;
  15775. }
  15776. // If the user requested cancellation, ack & bye this session.
  15777. if (this.isCanceled) {
  15778. this.ackAndBye(inviteResponse, session);
  15779. this.emit("bye", this.request); // FIXME: Ported this odd second "bye" emit
  15780. return;
  15781. }
  15782. // Ported behavior.
  15783. if (response.hasHeader("P-Asserted-Identity")) {
  15784. this.assertedIdentity = core_1.Grammar.nameAddrHeaderParse(response.getHeader("P-Asserted-Identity"));
  15785. }
  15786. // We have a confirmed dialog.
  15787. this.session = session;
  15788. this.session.delegate = {
  15789. onAck: function (ackRequest) { return _this.onAck(ackRequest); },
  15790. onBye: function (byeRequest) { return _this.receiveRequest(byeRequest); },
  15791. onInfo: function (infoRequest) { return _this.receiveRequest(infoRequest); },
  15792. onInvite: function (inviteRequest) { return _this.receiveRequest(inviteRequest); },
  15793. onNotify: function (notifyRequest) { return _this.receiveRequest(notifyRequest); },
  15794. onPrack: function (prackRequest) { return _this.receiveRequest(prackRequest); },
  15795. onRefer: function (referRequest) { return _this.receiveRequest(referRequest); }
  15796. };
  15797. switch (session.signalingState) {
  15798. case core_1.SignalingState.Initial:
  15799. // INVITE without Offer, so MUST have Offer at this point, so invalid state.
  15800. this.ackAndBye(inviteResponse, session, 400, "Missing session description");
  15801. this.failed(response, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  15802. break;
  15803. case core_1.SignalingState.HaveLocalOffer:
  15804. // INVITE with Offer, so MUST have Answer at this point, so invalid state.
  15805. this.ackAndBye(inviteResponse, session, 400, "Missing session description");
  15806. this.failed(response, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  15807. break;
  15808. case core_1.SignalingState.HaveRemoteOffer:
  15809. // INVITE without Offer, received offer in 2xx, so MUST send Answer in ACK.
  15810. var sdh_1 = this.sessionDescriptionHandlerFactory(this, this.ua.configuration.sessionDescriptionHandlerFactoryOptions || {});
  15811. this.sessionDescriptionHandler = sdh_1;
  15812. this.emit("SessionDescriptionHandler-created", this.sessionDescriptionHandler);
  15813. if (!sdh_1.hasDescription(response.getHeader("Content-Type") || "")) {
  15814. this.ackAndBye(inviteResponse, session, 400, "Missing session description");
  15815. this.failed(response, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  15816. break;
  15817. }
  15818. this.hasOffer = true;
  15819. sdh_1
  15820. .setDescription(response.body, this.sessionDescriptionHandlerOptions, this.modifiers)
  15821. .then(function () { return sdh_1.getDescription(_this.sessionDescriptionHandlerOptions, _this.modifiers); })
  15822. .then(function (description) {
  15823. if (_this.isCanceled || _this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  15824. return;
  15825. }
  15826. _this.status = Enums_1.SessionStatus.STATUS_CONFIRMED;
  15827. _this.hasAnswer = true;
  15828. var body = {
  15829. contentDisposition: "session", contentType: description.contentType, content: description.body
  15830. };
  15831. var ackRequest = inviteResponse.ack({ body: body });
  15832. _this.emit("ack", ackRequest.message);
  15833. _this.accepted(response);
  15834. })
  15835. .catch(function (e) {
  15836. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  15837. _this.logger.warn("invalid description");
  15838. _this.logger.warn(e.toString());
  15839. // TODO: This message is inconsistent
  15840. _this.ackAndBye(inviteResponse, session, 488, "Invalid session description");
  15841. _this.failed(response, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  15842. }
  15843. else {
  15844. throw e;
  15845. }
  15846. });
  15847. break;
  15848. case core_1.SignalingState.Stable:
  15849. // This session has completed an initial offer/answer exchange...
  15850. var options_1;
  15851. if (this.renderbody && this.rendertype) {
  15852. options_1 = { body: { contentDisposition: "render", contentType: this.rendertype, content: this.renderbody } };
  15853. }
  15854. // If INVITE with Offer and we have been waiting till now to apply the answer.
  15855. if (this.hasOffer && !this.hasAnswer) {
  15856. if (!this.sessionDescriptionHandler) {
  15857. throw new Error("Session description handler undefined.");
  15858. }
  15859. var answer = session.answer;
  15860. if (!answer) {
  15861. throw new Error("Answer is undefined.");
  15862. }
  15863. this.sessionDescriptionHandler
  15864. .setDescription(answer.content, this.sessionDescriptionHandlerOptions, this.modifiers)
  15865. .then(function () {
  15866. _this.hasAnswer = true;
  15867. _this.status = Enums_1.SessionStatus.STATUS_CONFIRMED;
  15868. var ackRequest = inviteResponse.ack(options_1);
  15869. _this.emit("ack", ackRequest.message);
  15870. _this.accepted(response);
  15871. })
  15872. .catch(function (error) {
  15873. _this.logger.error(error);
  15874. _this.ackAndBye(inviteResponse, session, 488, "Not Acceptable Here");
  15875. _this.failed(response, Constants_1.C.causes.BAD_MEDIA_DESCRIPTION);
  15876. // FIME: DON'T EAT UNHANDLED ERRORS!
  15877. });
  15878. }
  15879. else {
  15880. // Otherwise INVITE with or without Offer and we have already completed the initial exchange.
  15881. this.sessionDescriptionHandler = this.earlyMediaSessionDescriptionHandlers.get(session.id);
  15882. if (!this.sessionDescriptionHandler) {
  15883. throw new Error("Session description handler undefined.");
  15884. }
  15885. this.earlyMediaSessionDescriptionHandlers.delete(session.id);
  15886. this.hasOffer = true;
  15887. this.hasAnswer = true;
  15888. this.status = Enums_1.SessionStatus.STATUS_CONFIRMED;
  15889. var ackRequest = inviteResponse.ack();
  15890. this.emit("ack", ackRequest.message);
  15891. this.accepted(response);
  15892. }
  15893. break;
  15894. case core_1.SignalingState.Closed:
  15895. // Dialog has terminated.
  15896. break;
  15897. default:
  15898. throw new Error("Unknown session signaling state.");
  15899. }
  15900. this.disposeEarlyMedia();
  15901. };
  15902. /**
  15903. * Handle provisional response to initial INVITE.
  15904. * @param inviteResponse 1xx response.
  15905. */
  15906. InviteClientContext.prototype.onProgress = function (inviteResponse) {
  15907. var _this = this;
  15908. // Ported - User requested cancellation.
  15909. if (this.isCanceled) {
  15910. return;
  15911. }
  15912. if (!this.outgoingInviteRequest) {
  15913. throw new Error("Outgoing INVITE request undefined.");
  15914. }
  15915. if (!this.earlyMediaSessionDescriptionHandlers) {
  15916. throw new Error("Early media session description handlers undefined.");
  15917. }
  15918. var response = inviteResponse.message;
  15919. var session = inviteResponse.session;
  15920. // Ported - Set status.
  15921. this.status = Enums_1.SessionStatus.STATUS_1XX_RECEIVED;
  15922. // Ported - Set assertedIdentity.
  15923. if (response.hasHeader("P-Asserted-Identity")) {
  15924. this.assertedIdentity = core_1.Grammar.nameAddrHeaderParse(response.getHeader("P-Asserted-Identity"));
  15925. }
  15926. // The provisional response MUST establish a dialog if one is not yet created.
  15927. // https://tools.ietf.org/html/rfc3262#section-4
  15928. if (!session) {
  15929. // A response with a to tag MUST create a session (should never get here).
  15930. throw new Error("Session undefined.");
  15931. }
  15932. // If a provisional response is received for an initial request, and
  15933. // that response contains a Require header field containing the option
  15934. // tag 100rel, the response is to be sent reliably. If the response is
  15935. // a 100 (Trying) (as opposed to 101 to 199), this option tag MUST be
  15936. // ignored, and the procedures below MUST NOT be used.
  15937. // https://tools.ietf.org/html/rfc3262#section-4
  15938. var requireHeader = response.getHeader("require");
  15939. var rseqHeader = response.getHeader("rseq");
  15940. var rseq = requireHeader && requireHeader.includes("100rel") && rseqHeader ? Number(rseqHeader) : undefined;
  15941. var responseReliable = !!rseq;
  15942. var extraHeaders = [];
  15943. if (responseReliable) {
  15944. extraHeaders.push("RAck: " + response.getHeader("rseq") + " " + response.getHeader("cseq"));
  15945. }
  15946. // INVITE without Offer and session still has no offer (and no answer).
  15947. if (session.signalingState === core_1.SignalingState.Initial) {
  15948. // Similarly, if a reliable provisional
  15949. // response is the first reliable message sent back to the UAC, and the
  15950. // INVITE did not contain an offer, one MUST appear in that reliable
  15951. // provisional response.
  15952. // https://tools.ietf.org/html/rfc3262#section-5
  15953. if (responseReliable) {
  15954. this.logger.warn("First reliable provisional response received MUST contain an offer when INVITE does not contain an offer.");
  15955. // FIXME: Known popular UA's currently end up here...
  15956. inviteResponse.prack({ extraHeaders: extraHeaders });
  15957. }
  15958. this.emit("progress", response);
  15959. return;
  15960. }
  15961. // INVITE with Offer and session only has that initial local offer.
  15962. if (session.signalingState === core_1.SignalingState.HaveLocalOffer) {
  15963. if (responseReliable) {
  15964. inviteResponse.prack({ extraHeaders: extraHeaders });
  15965. }
  15966. this.emit("progress", response);
  15967. return;
  15968. }
  15969. // INVITE without Offer and received initial offer in provisional response
  15970. if (session.signalingState === core_1.SignalingState.HaveRemoteOffer) {
  15971. // The initial offer MUST be in either an INVITE or, if not there,
  15972. // in the first reliable non-failure message from the UAS back to
  15973. // the UAC.
  15974. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  15975. // According to Section 13.2.1 of [RFC3261], 'The first reliable
  15976. // non-failure message' must have an offer if there is no offer in the
  15977. // INVITE request. This means that the User Agent (UA) that receives
  15978. // the INVITE request without an offer must include an offer in the
  15979. // first reliable response with 100rel extension. If no reliable
  15980. // provisional response has been sent, the User Agent Server (UAS) must
  15981. // include an offer when sending 2xx response.
  15982. // https://tools.ietf.org/html/rfc6337#section-2.2
  15983. if (!responseReliable) {
  15984. this.logger.warn("Non-reliable provisional response MUST NOT contain an initial offer, discarding response.");
  15985. return;
  15986. }
  15987. // If the initial offer is in the first reliable non-failure
  15988. // message from the UAS back to UAC, the answer MUST be in the
  15989. // acknowledgement for that message
  15990. var sdh_2 = this.sessionDescriptionHandlerFactory(this, this.ua.configuration.sessionDescriptionHandlerFactoryOptions || {});
  15991. this.emit("SessionDescriptionHandler-created", sdh_2);
  15992. this.earlyMediaSessionDescriptionHandlers.set(session.id, sdh_2);
  15993. sdh_2
  15994. .setDescription(response.body, this.sessionDescriptionHandlerOptions, this.modifiers)
  15995. .then(function () { return sdh_2.getDescription(_this.sessionDescriptionHandlerOptions, _this.modifiers); })
  15996. .then(function (description) {
  15997. var body = {
  15998. contentDisposition: "session", contentType: description.contentType, content: description.body
  15999. };
  16000. inviteResponse.prack({ extraHeaders: extraHeaders, body: body });
  16001. _this.status = Enums_1.SessionStatus.STATUS_EARLY_MEDIA;
  16002. _this.emit("progress", response);
  16003. })
  16004. .catch(function (error) {
  16005. if (_this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  16006. return;
  16007. }
  16008. _this.failed(undefined, Constants_1.C.causes.WEBRTC_ERROR);
  16009. _this.terminated(undefined, Constants_1.C.causes.WEBRTC_ERROR);
  16010. });
  16011. return;
  16012. }
  16013. // This session has completed an initial offer/answer exchange, so...
  16014. // - INVITE with SDP and this provisional response MAY be reliable
  16015. // - INVITE without SDP and this provisional response MAY be reliable
  16016. if (session.signalingState === core_1.SignalingState.Stable) {
  16017. if (responseReliable) {
  16018. inviteResponse.prack({ extraHeaders: extraHeaders });
  16019. }
  16020. // Note: As documented, no early media if offer was in INVITE, so nothing to be done.
  16021. // FIXME: TODO: Add a flag/hack to allow early media in this case. There are people
  16022. // in non-forking environments (think straight to FreeSWITCH) who want
  16023. // early media on a 183. Not sure how to actually make it work, basically
  16024. // something like...
  16025. if (false) {}
  16026. this.emit("progress", response);
  16027. return;
  16028. }
  16029. };
  16030. /**
  16031. * Handle final response to initial INVITE.
  16032. * @param inviteResponse 3xx response.
  16033. */
  16034. InviteClientContext.prototype.onRedirect = function (inviteResponse) {
  16035. this.disposeEarlyMedia();
  16036. var response = inviteResponse.message;
  16037. var statusCode = response.statusCode;
  16038. var cause = Utils_1.Utils.sipErrorCause(statusCode || 0);
  16039. this.rejected(response, cause);
  16040. this.failed(response, cause);
  16041. this.terminated(response, cause);
  16042. };
  16043. /**
  16044. * Handle final response to initial INVITE.
  16045. * @param inviteResponse 4xx, 5xx, or 6xx response.
  16046. */
  16047. InviteClientContext.prototype.onReject = function (inviteResponse) {
  16048. this.disposeEarlyMedia();
  16049. var response = inviteResponse.message;
  16050. var statusCode = response.statusCode;
  16051. var cause = Utils_1.Utils.sipErrorCause(statusCode || 0);
  16052. this.rejected(response, cause);
  16053. this.failed(response, cause);
  16054. this.terminated(response, cause);
  16055. };
  16056. /**
  16057. * Handle final response to initial INVITE.
  16058. * @param inviteResponse 100 response.
  16059. */
  16060. InviteClientContext.prototype.onTrying = function (inviteResponse) {
  16061. this.received100 = true;
  16062. this.emit("progress", inviteResponse.message);
  16063. };
  16064. return InviteClientContext;
  16065. }(Session));
  16066. exports.InviteClientContext = InviteClientContext;
  16067. /***/ }),
  16068. /* 91 */
  16069. /***/ (function(module, exports, __webpack_require__) {
  16070. "use strict";
  16071. Object.defineProperty(exports, "__esModule", { value: true });
  16072. var tslib_1 = __webpack_require__(1);
  16073. var events_1 = __webpack_require__(30);
  16074. var Constants_1 = __webpack_require__(80);
  16075. var Enums_1 = __webpack_require__(82);
  16076. var Exceptions_1 = __webpack_require__(84);
  16077. var Utils_1 = __webpack_require__(83);
  16078. /**
  16079. * @class DTMF
  16080. * @param {SIP.Session} session
  16081. */
  16082. var DTMF = /** @class */ (function (_super) {
  16083. tslib_1.__extends(DTMF, _super);
  16084. function DTMF(session, tone, options) {
  16085. if (options === void 0) { options = {}; }
  16086. var _this = _super.call(this) || this;
  16087. _this.C = {
  16088. MIN_DURATION: 70,
  16089. MAX_DURATION: 6000,
  16090. DEFAULT_DURATION: 100,
  16091. MIN_INTER_TONE_GAP: 50,
  16092. DEFAULT_INTER_TONE_GAP: 500
  16093. };
  16094. _this.type = Enums_1.TypeStrings.DTMF;
  16095. if (tone === undefined) {
  16096. throw new TypeError("Not enough arguments");
  16097. }
  16098. _this.logger = session.ua.getLogger("sip.invitecontext.dtmf", session.id);
  16099. _this.owner = session;
  16100. // Check tone type
  16101. if (typeof tone === "string") {
  16102. tone = tone.toUpperCase();
  16103. }
  16104. else if (typeof tone === "number") {
  16105. tone = tone.toString();
  16106. }
  16107. else {
  16108. throw new TypeError("Invalid tone: " + tone);
  16109. }
  16110. // Check tone value
  16111. if (!tone.match(/^[0-9A-D#*]$/)) {
  16112. throw new TypeError("Invalid tone: " + tone);
  16113. }
  16114. else {
  16115. _this.tone = tone;
  16116. }
  16117. var duration = options.duration;
  16118. var interToneGap = options.interToneGap;
  16119. // Check duration
  16120. if (duration && !Utils_1.Utils.isDecimal(duration)) {
  16121. throw new TypeError("Invalid tone duration: " + duration);
  16122. }
  16123. else if (!duration) {
  16124. duration = _this.C.DEFAULT_DURATION;
  16125. }
  16126. else if (duration < _this.C.MIN_DURATION) {
  16127. _this.logger.warn("'duration' value is lower than the minimum allowed, setting it to " +
  16128. _this.C.MIN_DURATION + " milliseconds");
  16129. duration = _this.C.MIN_DURATION;
  16130. }
  16131. else if (duration > _this.C.MAX_DURATION) {
  16132. _this.logger.warn("'duration' value is greater than the maximum allowed, setting it to " +
  16133. _this.C.MAX_DURATION + " milliseconds");
  16134. duration = _this.C.MAX_DURATION;
  16135. }
  16136. else {
  16137. duration = Math.abs(duration);
  16138. }
  16139. _this.duration = duration;
  16140. // Check interToneGap
  16141. if (interToneGap && !Utils_1.Utils.isDecimal(interToneGap)) {
  16142. throw new TypeError("Invalid interToneGap: " + interToneGap);
  16143. }
  16144. else if (!interToneGap) {
  16145. interToneGap = _this.C.DEFAULT_INTER_TONE_GAP;
  16146. }
  16147. else if (interToneGap < _this.C.MIN_INTER_TONE_GAP) {
  16148. _this.logger.warn("'interToneGap' value is lower than the minimum allowed, setting it to " +
  16149. _this.C.MIN_INTER_TONE_GAP + " milliseconds");
  16150. interToneGap = _this.C.MIN_INTER_TONE_GAP;
  16151. }
  16152. else {
  16153. interToneGap = Math.abs(interToneGap);
  16154. }
  16155. _this.interToneGap = interToneGap;
  16156. return _this;
  16157. }
  16158. DTMF.prototype.send = function (options) {
  16159. if (options === void 0) { options = {}; }
  16160. // Check RTCSession Status
  16161. if (this.owner.status !== Enums_1.SessionStatus.STATUS_CONFIRMED &&
  16162. this.owner.status !== Enums_1.SessionStatus.STATUS_WAITING_FOR_ACK) {
  16163. throw new Exceptions_1.Exceptions.InvalidStateError(this.owner.status);
  16164. }
  16165. // Get DTMF options
  16166. var extraHeaders = options.extraHeaders ? options.extraHeaders.slice() : [];
  16167. var body = {
  16168. contentType: "application/dtmf-relay",
  16169. body: "Signal= " + this.tone + "\r\nDuration= " + this.duration
  16170. };
  16171. if (this.owner.session) {
  16172. var request = this.owner.session.info(undefined, {
  16173. extraHeaders: extraHeaders,
  16174. body: Utils_1.Utils.fromBodyObj(body)
  16175. });
  16176. this.owner.emit("dtmf", request.message, this);
  16177. return;
  16178. }
  16179. };
  16180. DTMF.prototype.init_incoming = function (request) {
  16181. request.accept();
  16182. if (!this.tone || !this.duration) {
  16183. this.logger.warn("invalid INFO DTMF received, discarded");
  16184. }
  16185. else {
  16186. this.owner.emit("dtmf", request.message, this);
  16187. }
  16188. };
  16189. DTMF.prototype.receiveResponse = function (response) {
  16190. var statusCode = response && response.statusCode ? response.statusCode : 0;
  16191. switch (true) {
  16192. case /^1[0-9]{2}$/.test(statusCode.toString()):
  16193. // Ignore provisional responses.
  16194. break;
  16195. case /^2[0-9]{2}$/.test(statusCode.toString()):
  16196. this.emit("succeeded", {
  16197. originator: "remote",
  16198. response: response
  16199. });
  16200. break;
  16201. default:
  16202. var cause = Utils_1.Utils.sipErrorCause(statusCode);
  16203. this.emit("failed", response, cause);
  16204. break;
  16205. }
  16206. };
  16207. DTMF.prototype.onRequestTimeout = function () {
  16208. this.emit("failed", undefined, Constants_1.C.causes.REQUEST_TIMEOUT);
  16209. this.owner.onRequestTimeout();
  16210. };
  16211. DTMF.prototype.onTransportError = function () {
  16212. this.emit("failed", undefined, Constants_1.C.causes.CONNECTION_ERROR);
  16213. this.owner.onTransportError();
  16214. };
  16215. DTMF.prototype.onDialogError = function (response) {
  16216. this.emit("failed", response, Constants_1.C.causes.DIALOG_ERROR);
  16217. this.owner.onDialogError(response);
  16218. };
  16219. return DTMF;
  16220. }(events_1.EventEmitter));
  16221. exports.DTMF = DTMF;
  16222. /***/ }),
  16223. /* 92 */
  16224. /***/ (function(module, exports, __webpack_require__) {
  16225. "use strict";
  16226. Object.defineProperty(exports, "__esModule", { value: true });
  16227. var tslib_1 = __webpack_require__(1);
  16228. var events_1 = __webpack_require__(30);
  16229. var Constants_1 = __webpack_require__(80);
  16230. var core_1 = __webpack_require__(2);
  16231. var allowed_methods_1 = __webpack_require__(58);
  16232. var Enums_1 = __webpack_require__(82);
  16233. var Utils_1 = __webpack_require__(83);
  16234. /**
  16235. * While this class is named `Subscription`, it is closer to
  16236. * an implementation of a "subscriber" as defined in RFC 6665
  16237. * "SIP-Specific Event Notifications".
  16238. * https://tools.ietf.org/html/rfc6665
  16239. * @class Class creating a SIP Subscriber.
  16240. */
  16241. var Subscription = /** @class */ (function (_super) {
  16242. tslib_1.__extends(Subscription, _super);
  16243. /**
  16244. * Constructor.
  16245. * @param ua User agent.
  16246. * @param target Subscription target.
  16247. * @param event Subscription event.
  16248. * @param options Options bucket.
  16249. */
  16250. function Subscription(ua, target, event, options) {
  16251. if (options === void 0) { options = {}; }
  16252. var _this = _super.call(this) || this;
  16253. _this.data = {};
  16254. _this.method = Constants_1.C.SUBSCRIBE;
  16255. _this.body = undefined;
  16256. // ClientContext interface
  16257. _this.type = Enums_1.TypeStrings.Subscription;
  16258. _this.ua = ua;
  16259. _this.logger = ua.getLogger("sip.subscription");
  16260. if (options.body) {
  16261. _this.body = {
  16262. body: options.body,
  16263. contentType: options.contentType ? options.contentType : "application/sdp"
  16264. };
  16265. }
  16266. // Target URI
  16267. var uri = ua.normalizeTarget(target);
  16268. if (!uri) {
  16269. throw new TypeError("Invalid target: " + target);
  16270. }
  16271. _this.uri = uri;
  16272. // Subscription event
  16273. _this.event = event;
  16274. // Subscription expires
  16275. if (options.expires === undefined) {
  16276. _this.expires = 3600;
  16277. }
  16278. else if (typeof options.expires !== "number") { // pre-typescript type guard
  16279. ua.logger.warn("Option \"expires\" must be a number. Using default of 3600.");
  16280. _this.expires = 3600;
  16281. }
  16282. else {
  16283. _this.expires = options.expires;
  16284. }
  16285. // Subscription extra headers
  16286. _this.extraHeaders = (options.extraHeaders || []).slice();
  16287. // Subscription context.
  16288. _this.context = _this.initContext();
  16289. _this.disposed = false;
  16290. // ClientContext interface
  16291. _this.request = _this.context.message;
  16292. if (!_this.request.from) {
  16293. throw new Error("From undefined.");
  16294. }
  16295. if (!_this.request.to) {
  16296. throw new Error("From undefined.");
  16297. }
  16298. _this.localIdentity = _this.request.from;
  16299. _this.remoteIdentity = _this.request.to;
  16300. // Add to UA's collection
  16301. _this.id = _this.request.callId + _this.request.from.parameters.tag + _this.event;
  16302. _this.ua.subscriptions[_this.id] = _this;
  16303. return _this;
  16304. }
  16305. /**
  16306. * Destructor.
  16307. */
  16308. Subscription.prototype.dispose = function () {
  16309. if (this.disposed) {
  16310. return;
  16311. }
  16312. if (this.retryAfterTimer) {
  16313. clearTimeout(this.retryAfterTimer);
  16314. this.retryAfterTimer = undefined;
  16315. }
  16316. this.context.dispose();
  16317. this.disposed = true;
  16318. // Remove from UA's collection
  16319. delete this.ua.subscriptions[this.id];
  16320. };
  16321. Subscription.prototype.on = function (name, callback) {
  16322. return _super.prototype.on.call(this, name, callback);
  16323. };
  16324. Subscription.prototype.emit = function (event) {
  16325. var args = [];
  16326. for (var _i = 1; _i < arguments.length; _i++) {
  16327. args[_i - 1] = arguments[_i];
  16328. }
  16329. return _super.prototype.emit.apply(this, tslib_1.__spreadArrays([event], args));
  16330. };
  16331. /**
  16332. * Gracefully terminate.
  16333. */
  16334. Subscription.prototype.close = function () {
  16335. if (this.disposed) {
  16336. return;
  16337. }
  16338. this.dispose();
  16339. switch (this.context.state) {
  16340. case core_1.SubscriptionState.Initial:
  16341. this.onTerminated();
  16342. break;
  16343. case core_1.SubscriptionState.NotifyWait:
  16344. this.onTerminated();
  16345. break;
  16346. case core_1.SubscriptionState.Pending:
  16347. this.unsubscribe();
  16348. break;
  16349. case core_1.SubscriptionState.Active:
  16350. this.unsubscribe();
  16351. break;
  16352. case core_1.SubscriptionState.Terminated:
  16353. this.onTerminated();
  16354. break;
  16355. default:
  16356. break;
  16357. }
  16358. };
  16359. /**
  16360. * Send a re-SUBSCRIBE request if there is an "active" subscription.
  16361. */
  16362. Subscription.prototype.refresh = function () {
  16363. var _this = this;
  16364. switch (this.context.state) {
  16365. case core_1.SubscriptionState.Initial:
  16366. break;
  16367. case core_1.SubscriptionState.NotifyWait:
  16368. break;
  16369. case core_1.SubscriptionState.Pending:
  16370. break;
  16371. case core_1.SubscriptionState.Active:
  16372. if (this.subscription) {
  16373. var request = this.subscription.refresh();
  16374. request.delegate = {
  16375. onAccept: (function (response) { return _this.onAccepted(response); }),
  16376. onRedirect: (function (response) { return _this.onFailed(response); }),
  16377. onReject: (function (response) { return _this.onFailed(response); }),
  16378. };
  16379. }
  16380. break;
  16381. case core_1.SubscriptionState.Terminated:
  16382. break;
  16383. default:
  16384. break;
  16385. }
  16386. };
  16387. /**
  16388. * Send an initial SUBSCRIBE request if no subscription.
  16389. * Send a re-SUBSCRIBE request if there is an "active" subscription.
  16390. */
  16391. Subscription.prototype.subscribe = function () {
  16392. var _this = this;
  16393. switch (this.context.state) {
  16394. case core_1.SubscriptionState.Initial:
  16395. this.context.subscribe().then(function (result) {
  16396. if (result.success) {
  16397. if (result.success.subscription) {
  16398. _this.subscription = result.success.subscription;
  16399. _this.subscription.delegate = {
  16400. onNotify: function (request) { return _this.onNotify(request); },
  16401. onRefresh: function (request) { return _this.onRefresh(request); },
  16402. onTerminated: function () { return _this.close(); }
  16403. };
  16404. }
  16405. _this.onNotify(result.success.request);
  16406. }
  16407. else if (result.failure) {
  16408. _this.onFailed(result.failure.response);
  16409. }
  16410. });
  16411. break;
  16412. case core_1.SubscriptionState.NotifyWait:
  16413. break;
  16414. case core_1.SubscriptionState.Pending:
  16415. break;
  16416. case core_1.SubscriptionState.Active:
  16417. this.refresh();
  16418. break;
  16419. case core_1.SubscriptionState.Terminated:
  16420. break;
  16421. default:
  16422. break;
  16423. }
  16424. return this;
  16425. };
  16426. /**
  16427. * Send a re-SUBSCRIBE request if there is a "pending" or "active" subscription.
  16428. */
  16429. Subscription.prototype.unsubscribe = function () {
  16430. this.dispose();
  16431. switch (this.context.state) {
  16432. case core_1.SubscriptionState.Initial:
  16433. break;
  16434. case core_1.SubscriptionState.NotifyWait:
  16435. break;
  16436. case core_1.SubscriptionState.Pending:
  16437. if (this.subscription) {
  16438. this.subscription.unsubscribe();
  16439. // responses intentionally ignored
  16440. }
  16441. break;
  16442. case core_1.SubscriptionState.Active:
  16443. if (this.subscription) {
  16444. this.subscription.unsubscribe();
  16445. // responses intentionally ignored
  16446. }
  16447. break;
  16448. case core_1.SubscriptionState.Terminated:
  16449. break;
  16450. default:
  16451. break;
  16452. }
  16453. this.onTerminated();
  16454. };
  16455. Subscription.prototype.onAccepted = function (response) {
  16456. var statusCode = response.message.statusCode ? response.message.statusCode : 0;
  16457. var cause = Utils_1.Utils.getReasonPhrase(statusCode);
  16458. this.emit("accepted", response.message, cause);
  16459. };
  16460. Subscription.prototype.onFailed = function (response) {
  16461. this.close();
  16462. if (response) {
  16463. var statusCode = response.message.statusCode ? response.message.statusCode : 0;
  16464. var cause = Utils_1.Utils.getReasonPhrase(statusCode);
  16465. this.emit("failed", response.message, cause);
  16466. this.emit("rejected", response.message, cause);
  16467. }
  16468. };
  16469. Subscription.prototype.onNotify = function (request) {
  16470. var _this = this;
  16471. request.accept(); // Send 200 response.
  16472. this.emit("notify", { request: request.message });
  16473. // If we've set state to done, no further processing should take place
  16474. // and we are only interested in cleaning up after the appropriate NOTIFY.
  16475. if (this.disposed) {
  16476. return;
  16477. }
  16478. // If the "Subscription-State" value is "terminated", the subscriber
  16479. // MUST consider the subscription terminated. The "expires" parameter
  16480. // has no semantics for "terminated" -- notifiers SHOULD NOT include an
  16481. // "expires" parameter on a "Subscription-State" header field with a
  16482. // value of "terminated", and subscribers MUST ignore any such
  16483. // parameter, if present. If a reason code is present, the client
  16484. // should behave as described below. If no reason code or an unknown
  16485. // reason code is present, the client MAY attempt to re-subscribe at any
  16486. // time (unless a "retry-after" parameter is present, in which case the
  16487. // client SHOULD NOT attempt re-subscription until after the number of
  16488. // seconds specified by the "retry-after" parameter). The reason codes
  16489. // defined by this document are:
  16490. // https://tools.ietf.org/html/rfc6665#section-4.1.3
  16491. var subscriptionState = request.message.parseHeader("Subscription-State");
  16492. if (subscriptionState && subscriptionState.state) {
  16493. switch (subscriptionState.state) {
  16494. case "terminated":
  16495. if (subscriptionState.reason) {
  16496. this.logger.log("Terminated subscription with reason " + subscriptionState.reason);
  16497. switch (subscriptionState.reason) {
  16498. case "deactivated":
  16499. case "timeout":
  16500. this.initContext();
  16501. this.subscribe();
  16502. return;
  16503. case "probation":
  16504. case "giveup":
  16505. this.initContext();
  16506. if (subscriptionState.params && subscriptionState.params["retry-after"]) {
  16507. this.retryAfterTimer = setTimeout(function () { return _this.subscribe(); }, subscriptionState.params["retry-after"]);
  16508. }
  16509. else {
  16510. this.subscribe();
  16511. }
  16512. return;
  16513. case "rejected":
  16514. case "noresource":
  16515. case "invariant":
  16516. break;
  16517. }
  16518. }
  16519. this.close();
  16520. break;
  16521. default:
  16522. break;
  16523. }
  16524. }
  16525. };
  16526. Subscription.prototype.onRefresh = function (request) {
  16527. var _this = this;
  16528. request.delegate = {
  16529. onAccept: function (response) { return _this.onAccepted(response); }
  16530. };
  16531. };
  16532. Subscription.prototype.onTerminated = function () {
  16533. this.emit("terminated");
  16534. };
  16535. Subscription.prototype.initContext = function () {
  16536. var _this = this;
  16537. var options = {
  16538. extraHeaders: this.extraHeaders,
  16539. body: this.body ? Utils_1.Utils.fromBodyObj(this.body) : undefined
  16540. };
  16541. this.context = new SubscribeClientContext(this.ua.userAgentCore, this.uri, this.event, this.expires, options);
  16542. this.context.delegate = {
  16543. onAccept: (function (response) { return _this.onAccepted(response); })
  16544. };
  16545. return this.context;
  16546. };
  16547. return Subscription;
  16548. }(events_1.EventEmitter));
  16549. exports.Subscription = Subscription;
  16550. // tslint:disable-next-line:max-classes-per-file
  16551. var SubscribeClientContext = /** @class */ (function () {
  16552. function SubscribeClientContext(core, target, event, expires, options, delegate) {
  16553. this.core = core;
  16554. this.target = target;
  16555. this.event = event;
  16556. this.expires = expires;
  16557. this.subscribed = false;
  16558. this.logger = core.loggerFactory.getLogger("sip.subscription");
  16559. this.delegate = delegate;
  16560. var allowHeader = "Allow: " + allowed_methods_1.AllowedMethods.toString();
  16561. var extraHeaders = (options && options.extraHeaders || []).slice();
  16562. extraHeaders.push(allowHeader);
  16563. extraHeaders.push("Event: " + this.event);
  16564. extraHeaders.push("Expires: " + this.expires);
  16565. extraHeaders.push("Contact: " + this.core.configuration.contact.toString());
  16566. var body = options && options.body;
  16567. this.message = core.makeOutgoingRequestMessage(Constants_1.C.SUBSCRIBE, this.target, this.core.configuration.aor, this.target, {}, extraHeaders, body);
  16568. }
  16569. /** Destructor. */
  16570. SubscribeClientContext.prototype.dispose = function () {
  16571. if (this.subscription) {
  16572. this.subscription.dispose();
  16573. }
  16574. if (this.request) {
  16575. this.request.waitNotifyStop();
  16576. this.request.dispose();
  16577. }
  16578. };
  16579. Object.defineProperty(SubscribeClientContext.prototype, "state", {
  16580. /** Subscription state. */
  16581. get: function () {
  16582. if (this.subscription) {
  16583. return this.subscription.subscriptionState;
  16584. }
  16585. else if (this.subscribed) {
  16586. return core_1.SubscriptionState.NotifyWait;
  16587. }
  16588. else {
  16589. return core_1.SubscriptionState.Initial;
  16590. }
  16591. },
  16592. enumerable: true,
  16593. configurable: true
  16594. });
  16595. /**
  16596. * Establish subscription.
  16597. * @param options Options bucket.
  16598. */
  16599. SubscribeClientContext.prototype.subscribe = function () {
  16600. var _this = this;
  16601. if (this.subscribed) {
  16602. return Promise.reject(new Error("Not in initial state. Did you call subscribe more than once?"));
  16603. }
  16604. this.subscribed = true;
  16605. return new Promise(function (resolve, reject) {
  16606. if (!_this.message) {
  16607. throw new Error("Message undefined.");
  16608. }
  16609. _this.request = _this.core.subscribe(_this.message, {
  16610. // This SUBSCRIBE request will be confirmed with a final response.
  16611. // 200-class responses indicate that the subscription has been accepted
  16612. // and that a NOTIFY request will be sent immediately.
  16613. // https://tools.ietf.org/html/rfc6665#section-4.1.2.1
  16614. onAccept: function (response) {
  16615. if (_this.delegate && _this.delegate.onAccept) {
  16616. _this.delegate.onAccept(response);
  16617. }
  16618. },
  16619. // Due to the potential for out-of-order messages, packet loss, and
  16620. // forking, the subscriber MUST be prepared to receive NOTIFY requests
  16621. // before the SUBSCRIBE transaction has completed.
  16622. // https://tools.ietf.org/html/rfc6665#section-4.1.2.4
  16623. onNotify: function (requestWithSubscription) {
  16624. _this.subscription = requestWithSubscription.subscription;
  16625. if (_this.subscription) {
  16626. _this.subscription.autoRefresh = true;
  16627. }
  16628. resolve({ success: requestWithSubscription });
  16629. },
  16630. // If this Timer N expires prior to the receipt of a NOTIFY request,
  16631. // the subscriber considers the subscription failed, and cleans up
  16632. // any state associated with the subscription attempt.
  16633. // https://tools.ietf.org/html/rfc6665#section-4.1.2.4
  16634. onNotifyTimeout: function () {
  16635. resolve({ failure: {} });
  16636. },
  16637. // This SUBSCRIBE request will be confirmed with a final response.
  16638. // Non-200-class final responses indicate that no subscription or new
  16639. // dialog usage has been created, and no subsequent NOTIFY request will
  16640. // be sent.
  16641. // https://tools.ietf.org/html/rfc6665#section-4.1.2.1
  16642. onRedirect: function (response) {
  16643. resolve({ failure: { response: response } });
  16644. },
  16645. // This SUBSCRIBE request will be confirmed with a final response.
  16646. // Non-200-class final responses indicate that no subscription or new
  16647. // dialog usage has been created, and no subsequent NOTIFY request will
  16648. // be sent.
  16649. // https://tools.ietf.org/html/rfc6665#section-4.1.2.1
  16650. onReject: function (response) {
  16651. resolve({ failure: { response: response } });
  16652. }
  16653. });
  16654. });
  16655. };
  16656. return SubscribeClientContext;
  16657. }());
  16658. /***/ }),
  16659. /* 93 */
  16660. /***/ (function(module, exports, __webpack_require__) {
  16661. "use strict";
  16662. Object.defineProperty(exports, "__esModule", { value: true });
  16663. var tslib_1 = __webpack_require__(1);
  16664. var events_1 = __webpack_require__(30);
  16665. var ClientContext_1 = __webpack_require__(79);
  16666. var Constants_1 = __webpack_require__(80);
  16667. var core_1 = __webpack_require__(2);
  16668. var Enums_1 = __webpack_require__(82);
  16669. var Exceptions_1 = __webpack_require__(84);
  16670. var Parser_1 = __webpack_require__(85);
  16671. var PublishContext_1 = __webpack_require__(86);
  16672. var ReferContext_1 = __webpack_require__(87);
  16673. var RegisterContext_1 = __webpack_require__(89);
  16674. var ServerContext_1 = __webpack_require__(88);
  16675. var Session_1 = __webpack_require__(90);
  16676. var Subscription_1 = __webpack_require__(92);
  16677. var Utils_1 = __webpack_require__(83);
  16678. var SessionDescriptionHandler_1 = __webpack_require__(94);
  16679. var Transport_1 = __webpack_require__(103);
  16680. /**
  16681. * @class Class creating a SIP User Agent.
  16682. * @param {function returning SIP.sessionDescriptionHandler} [configuration.sessionDescriptionHandlerFactory]
  16683. * A function will be invoked by each of the UA's Sessions to build the sessionDescriptionHandler for that Session.
  16684. * If no (or a falsy) value is provided, each Session will use a default (WebRTC) sessionDescriptionHandler.
  16685. */
  16686. var UA = /** @class */ (function (_super) {
  16687. tslib_1.__extends(UA, _super);
  16688. function UA(configuration) {
  16689. var _this = _super.call(this) || this;
  16690. /** Unload listener. */
  16691. _this.unloadListener = (function () { _this.stop(); });
  16692. _this.type = Enums_1.TypeStrings.UA;
  16693. _this.log = new core_1.LoggerFactory();
  16694. _this.logger = _this.getLogger("sip.ua");
  16695. _this.configuration = {};
  16696. // User actions outside any session/dialog (MESSAGE)
  16697. _this.applicants = {};
  16698. _this.data = {};
  16699. _this.sessions = {};
  16700. _this.subscriptions = {};
  16701. _this.publishers = {};
  16702. _this.status = Enums_1.UAStatus.STATUS_INIT;
  16703. /**
  16704. * Load configuration
  16705. *
  16706. * @throws {SIP.Exceptions.ConfigurationError}
  16707. * @throws {TypeError}
  16708. */
  16709. if (configuration === undefined) {
  16710. configuration = {};
  16711. }
  16712. else if (typeof configuration === "string" || configuration instanceof String) {
  16713. configuration = {
  16714. uri: configuration
  16715. };
  16716. }
  16717. // Apply log configuration if present
  16718. if (configuration.log) {
  16719. _this.log.builtinEnabled = configuration.log.builtinEnabled;
  16720. if (configuration.log.hasOwnProperty("connector")) {
  16721. _this.log.connector = configuration.log.connector;
  16722. }
  16723. if (configuration.log.hasOwnProperty("level")) {
  16724. var level = configuration.log.level;
  16725. var normalized = void 0;
  16726. if (typeof level === "string") {
  16727. switch (level) {
  16728. case "error":
  16729. normalized = core_1.Levels.error;
  16730. break;
  16731. case "warn":
  16732. normalized = core_1.Levels.warn;
  16733. break;
  16734. case "log":
  16735. normalized = core_1.Levels.log;
  16736. break;
  16737. case "debug":
  16738. normalized = core_1.Levels.debug;
  16739. break;
  16740. default:
  16741. break;
  16742. }
  16743. }
  16744. else {
  16745. switch (level) {
  16746. case 0:
  16747. normalized = core_1.Levels.error;
  16748. break;
  16749. case 1:
  16750. normalized = core_1.Levels.warn;
  16751. break;
  16752. case 2:
  16753. normalized = core_1.Levels.log;
  16754. break;
  16755. case 3:
  16756. normalized = core_1.Levels.debug;
  16757. break;
  16758. default:
  16759. break;
  16760. }
  16761. }
  16762. // avoid setting level when invalid, use default level instead
  16763. if (normalized === undefined) {
  16764. _this.logger.error("Invalid \"level\" parameter value: " + JSON.stringify(level));
  16765. }
  16766. else {
  16767. _this.log.level = normalized;
  16768. }
  16769. }
  16770. }
  16771. var deprecatedMessage = "The UA class has been deprecated and will no longer be available starting with SIP.js release 0.16.0. " +
  16772. "The UA has been replaced by the UserAgent class. Please update accordingly.";
  16773. _this.logger.warn(deprecatedMessage);
  16774. try {
  16775. _this.loadConfig(configuration);
  16776. }
  16777. catch (e) {
  16778. _this.status = Enums_1.UAStatus.STATUS_NOT_READY;
  16779. _this.error = UA.C.CONFIGURATION_ERROR;
  16780. throw e;
  16781. }
  16782. if (!_this.configuration.transportConstructor) {
  16783. throw new core_1.TransportError("Transport constructor not set");
  16784. }
  16785. _this.transport = new _this.configuration.transportConstructor(_this.getLogger("sip.transport"), _this.configuration.transportOptions);
  16786. var userAgentCoreConfiguration = makeUserAgentCoreConfigurationFromUA(_this);
  16787. // The Replaces header contains information used to match an existing
  16788. // SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE
  16789. // with a Replaces header, the User Agent (UA) attempts to match this
  16790. // information with a confirmed or early dialog.
  16791. // https://tools.ietf.org/html/rfc3891#section-3
  16792. var handleInviteWithReplacesHeader = function (context, request) {
  16793. if (_this.configuration.replaces !== Constants_1.C.supported.UNSUPPORTED) {
  16794. var replaces = request.parseHeader("replaces");
  16795. if (replaces) {
  16796. var targetSession = _this.sessions[replaces.call_id + replaces.replaces_from_tag] ||
  16797. _this.sessions[replaces.call_id + replaces.replaces_to_tag] ||
  16798. undefined;
  16799. if (!targetSession) {
  16800. _this.userAgentCore.replyStateless(request, { statusCode: 481 });
  16801. return;
  16802. }
  16803. if (targetSession.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  16804. _this.userAgentCore.replyStateless(request, { statusCode: 603 });
  16805. return;
  16806. }
  16807. var targetDialogId = replaces.call_id + replaces.replaces_to_tag + replaces.replaces_from_tag;
  16808. var targetDialog = _this.userAgentCore.dialogs.get(targetDialogId);
  16809. if (!targetDialog) {
  16810. _this.userAgentCore.replyStateless(request, { statusCode: 481 });
  16811. return;
  16812. }
  16813. if (!targetDialog.early && replaces.early_only) {
  16814. _this.userAgentCore.replyStateless(request, { statusCode: 486 });
  16815. return;
  16816. }
  16817. context.replacee = targetSession;
  16818. }
  16819. }
  16820. };
  16821. var userAgentCoreDelegate = {
  16822. onInvite: function (incomingInviteRequest) {
  16823. // FIXME: Ported - 100 Trying send should be configurable.
  16824. // Only required if TU will not respond in 200ms.
  16825. // https://tools.ietf.org/html/rfc3261#section-17.2.1
  16826. incomingInviteRequest.trying();
  16827. incomingInviteRequest.delegate = {
  16828. onCancel: function (cancel) {
  16829. context.onCancel(cancel);
  16830. },
  16831. onTransportError: function (error) {
  16832. context.onTransportError();
  16833. }
  16834. };
  16835. var context = new Session_1.InviteServerContext(_this, incomingInviteRequest);
  16836. // Ported - handling of out of dialog INVITE with Replaces.
  16837. handleInviteWithReplacesHeader(context, incomingInviteRequest.message);
  16838. // Ported - make the first call to progress automatically.
  16839. if (context.autoSendAnInitialProvisionalResponse) {
  16840. context.progress();
  16841. }
  16842. _this.emit("invite", context);
  16843. },
  16844. onMessage: function (incomingMessageRequest) {
  16845. // Ported - handling of out of dialog MESSAGE.
  16846. var serverContext = new ServerContext_1.ServerContext(_this, incomingMessageRequest);
  16847. serverContext.body = incomingMessageRequest.message.body;
  16848. serverContext.contentType = incomingMessageRequest.message.getHeader("Content-Type") || "text/plain";
  16849. incomingMessageRequest.accept();
  16850. _this.emit("message", serverContext); // TODO: Review. Why is a "ServerContext" emitted? What use it is?
  16851. },
  16852. onNotify: function (incomingNotifyRequest) {
  16853. // DEPRECATED: Out of dialog NOTIFY is an obsolete usage.
  16854. // Ported - handling of out of dialog NOTIFY.
  16855. if (_this.configuration.allowLegacyNotifications && _this.listeners("notify").length > 0) {
  16856. incomingNotifyRequest.accept();
  16857. _this.emit("notify", { request: incomingNotifyRequest.message });
  16858. }
  16859. else {
  16860. incomingNotifyRequest.reject({ statusCode: 481 });
  16861. }
  16862. },
  16863. onRefer: function (incomingReferRequest) {
  16864. // Ported - handling of out of dialog REFER.
  16865. _this.logger.log("Received an out of dialog refer");
  16866. if (!_this.configuration.allowOutOfDialogRefers) {
  16867. incomingReferRequest.reject({ statusCode: 405 });
  16868. }
  16869. _this.logger.log("Allow out of dialog refers is enabled on the UA");
  16870. var referContext = new ReferContext_1.ReferServerContext(_this, incomingReferRequest);
  16871. if (_this.listeners("outOfDialogReferRequested").length) {
  16872. _this.emit("outOfDialogReferRequested", referContext);
  16873. }
  16874. else {
  16875. _this.logger.log("No outOfDialogReferRequest listeners, automatically accepting and following the out of dialog refer");
  16876. referContext.accept({ followRefer: true });
  16877. }
  16878. },
  16879. onSubscribe: function (incomingSubscribeRequest) {
  16880. _this.emit("subscribe", incomingSubscribeRequest);
  16881. },
  16882. };
  16883. _this.userAgentCore = new core_1.UserAgentCore(userAgentCoreConfiguration, userAgentCoreDelegate);
  16884. // Initialize registerContext
  16885. _this.registerContext = new RegisterContext_1.RegisterContext(_this, configuration.registerOptions);
  16886. _this.registerContext.on("failed", _this.emit.bind(_this, "registrationFailed"));
  16887. _this.registerContext.on("registered", _this.emit.bind(_this, "registered"));
  16888. _this.registerContext.on("unregistered", _this.emit.bind(_this, "unregistered"));
  16889. if (_this.configuration.autostart) {
  16890. _this.start();
  16891. }
  16892. return _this;
  16893. }
  16894. // =================
  16895. // High Level API
  16896. // =================
  16897. UA.prototype.register = function (options) {
  16898. if (options === void 0) { options = {}; }
  16899. if (options.register) {
  16900. this.configuration.register = true;
  16901. }
  16902. this.registerContext.register(options);
  16903. return this;
  16904. };
  16905. /**
  16906. * Unregister.
  16907. *
  16908. * @param {Boolean} [all] unregister all user bindings.
  16909. *
  16910. */
  16911. UA.prototype.unregister = function (options) {
  16912. var _this = this;
  16913. this.configuration.register = false;
  16914. this.transport.afterConnected(function () {
  16915. _this.registerContext.unregister(options);
  16916. });
  16917. return this;
  16918. };
  16919. UA.prototype.isRegistered = function () {
  16920. return this.registerContext.registered;
  16921. };
  16922. /**
  16923. * Make an outgoing call.
  16924. *
  16925. * @param {String} target
  16926. * @param {Object} views
  16927. * @param {Object} [options.media] gets passed to SIP.sessionDescriptionHandler.getDescription as mediaHint
  16928. *
  16929. * @throws {TypeError}
  16930. *
  16931. */
  16932. UA.prototype.invite = function (target, options, modifiers) {
  16933. var _this = this;
  16934. var context = new Session_1.InviteClientContext(this, target, options, modifiers);
  16935. // Delay sending actual invite until the next 'tick' if we are already
  16936. // connected, so that API consumers can register to events fired by the
  16937. // the session.
  16938. this.transport.afterConnected(function () {
  16939. context.invite();
  16940. _this.emit("inviteSent", context);
  16941. });
  16942. return context;
  16943. };
  16944. UA.prototype.subscribe = function (target, event, options) {
  16945. var sub = new Subscription_1.Subscription(this, target, event, options);
  16946. this.transport.afterConnected(function () { return sub.subscribe(); });
  16947. return sub;
  16948. };
  16949. /**
  16950. * Send PUBLISH Event State Publication (RFC3903)
  16951. *
  16952. * @param {String} target
  16953. * @param {String} event
  16954. * @param {String} body
  16955. * @param {Object} [options]
  16956. *
  16957. * @throws {SIP.Exceptions.MethodParameterError}
  16958. */
  16959. UA.prototype.publish = function (target, event, body, options) {
  16960. var pub = new PublishContext_1.PublishContext(this, target, event, options);
  16961. this.transport.afterConnected(function () {
  16962. pub.publish(body);
  16963. });
  16964. return pub;
  16965. };
  16966. /**
  16967. * Send a message.
  16968. *
  16969. * @param {String} target
  16970. * @param {String} body
  16971. * @param {Object} [options]
  16972. *
  16973. * @throws {TypeError}
  16974. */
  16975. UA.prototype.message = function (target, body, options) {
  16976. if (options === void 0) { options = {}; }
  16977. if (body === undefined) {
  16978. throw new TypeError("Not enough arguments");
  16979. }
  16980. // There is no Message module, so it is okay that the UA handles defaults here.
  16981. options.contentType = options.contentType || "text/plain";
  16982. options.body = body;
  16983. return this.request(Constants_1.C.MESSAGE, target, options);
  16984. };
  16985. UA.prototype.request = function (method, target, options) {
  16986. var req = new ClientContext_1.ClientContext(this, method, target, options);
  16987. this.transport.afterConnected(function () { return req.send(); });
  16988. return req;
  16989. };
  16990. /**
  16991. * Gracefully close.
  16992. */
  16993. UA.prototype.stop = function () {
  16994. this.logger.log("user requested closure...");
  16995. if (this.status === Enums_1.UAStatus.STATUS_USER_CLOSED) {
  16996. this.logger.warn("UA already closed");
  16997. return this;
  16998. }
  16999. // Close registerContext
  17000. this.logger.log("closing registerContext");
  17001. this.registerContext.close();
  17002. // Run terminate on every Session
  17003. for (var session in this.sessions) {
  17004. if (this.sessions[session]) {
  17005. this.logger.log("closing session " + session);
  17006. this.sessions[session].terminate();
  17007. }
  17008. }
  17009. // Run unsubscribe on every Subscription
  17010. for (var subscription in this.subscriptions) {
  17011. if (this.subscriptions[subscription]) {
  17012. this.logger.log("unsubscribe " + subscription);
  17013. this.subscriptions[subscription].unsubscribe();
  17014. }
  17015. }
  17016. // Run close on every Publisher
  17017. for (var publisher in this.publishers) {
  17018. if (this.publishers[publisher]) {
  17019. this.logger.log("unpublish " + publisher);
  17020. this.publishers[publisher].close();
  17021. }
  17022. }
  17023. // Run close on every applicant
  17024. for (var applicant in this.applicants) {
  17025. if (this.applicants[applicant]) {
  17026. this.applicants[applicant].close();
  17027. }
  17028. }
  17029. this.status = Enums_1.UAStatus.STATUS_USER_CLOSED;
  17030. // Disconnect the transport and reset user agent core
  17031. this.transport.disconnect();
  17032. this.userAgentCore.reset();
  17033. if (this.configuration.autostop) {
  17034. // Google Chrome Packaged Apps don't allow 'unload' listeners: unload is not available in packaged apps
  17035. var googleChromePackagedApp = typeof chrome !== "undefined" && chrome.app && chrome.app.runtime ? true : false;
  17036. if (typeof window !== "undefined" &&
  17037. typeof window.removeEventListener === "function" &&
  17038. !googleChromePackagedApp) {
  17039. window.removeEventListener("unload", this.unloadListener);
  17040. }
  17041. }
  17042. return this;
  17043. };
  17044. /**
  17045. * Connect to the WS server if status = STATUS_INIT.
  17046. * Resume UA after being closed.
  17047. *
  17048. */
  17049. UA.prototype.start = function () {
  17050. this.logger.log("user requested startup...");
  17051. if (this.status === Enums_1.UAStatus.STATUS_INIT) {
  17052. this.status = Enums_1.UAStatus.STATUS_STARTING;
  17053. this.setTransportListeners();
  17054. this.emit("transportCreated", this.transport);
  17055. this.transport.connect();
  17056. }
  17057. else if (this.status === Enums_1.UAStatus.STATUS_USER_CLOSED) {
  17058. this.logger.log("resuming");
  17059. this.status = Enums_1.UAStatus.STATUS_READY;
  17060. this.transport.connect();
  17061. }
  17062. else if (this.status === Enums_1.UAStatus.STATUS_STARTING) {
  17063. this.logger.log("UA is in STARTING status, not opening new connection");
  17064. }
  17065. else if (this.status === Enums_1.UAStatus.STATUS_READY) {
  17066. this.logger.log("UA is in READY status, not resuming");
  17067. }
  17068. else {
  17069. this.logger.error("Connection is down. Auto-Recovery system is trying to connect");
  17070. }
  17071. if (this.configuration.autostop) {
  17072. // Google Chrome Packaged Apps don't allow 'unload' listeners: unload is not available in packaged apps
  17073. var googleChromePackagedApp = typeof chrome !== "undefined" && chrome.app && chrome.app.runtime ? true : false;
  17074. if (typeof window !== "undefined" &&
  17075. typeof window.addEventListener === "function" &&
  17076. !googleChromePackagedApp) {
  17077. window.addEventListener("unload", this.unloadListener);
  17078. }
  17079. }
  17080. return this;
  17081. };
  17082. /**
  17083. * Normalize a string into a valid SIP request URI
  17084. *
  17085. * @param {String} target
  17086. *
  17087. * @returns {SIP.URI|undefined}
  17088. */
  17089. UA.prototype.normalizeTarget = function (target) {
  17090. return Utils_1.Utils.normalizeTarget(target, this.configuration.hostportParams);
  17091. };
  17092. UA.prototype.getLogger = function (category, label) {
  17093. return this.log.getLogger(category, label);
  17094. };
  17095. UA.prototype.getLoggerFactory = function () {
  17096. return this.log;
  17097. };
  17098. UA.prototype.getSupportedResponseOptions = function () {
  17099. var optionTags = [];
  17100. if (this.contact.pubGruu || this.contact.tempGruu) {
  17101. optionTags.push("gruu");
  17102. }
  17103. if (this.configuration.rel100 === Constants_1.C.supported.SUPPORTED) {
  17104. optionTags.push("100rel");
  17105. }
  17106. if (this.configuration.replaces === Constants_1.C.supported.SUPPORTED) {
  17107. optionTags.push("replaces");
  17108. }
  17109. optionTags.push("outbound");
  17110. optionTags = optionTags.concat(this.configuration.extraSupported || []);
  17111. var allowUnregistered = this.configuration.hackAllowUnregisteredOptionTags || false;
  17112. var optionTagSet = {};
  17113. optionTags = optionTags.filter(function (optionTag) {
  17114. var registered = Constants_1.C.OPTION_TAGS[optionTag];
  17115. var unique = !optionTagSet[optionTag];
  17116. optionTagSet[optionTag] = true;
  17117. return (registered || allowUnregistered) && unique;
  17118. });
  17119. return optionTags;
  17120. };
  17121. /**
  17122. * Get the session to which the request belongs to, if any.
  17123. * @param {SIP.IncomingRequest} request.
  17124. * @returns {SIP.OutgoingSession|SIP.IncomingSession|undefined}
  17125. */
  17126. UA.prototype.findSession = function (request) {
  17127. return this.sessions[request.callId + request.fromTag] ||
  17128. this.sessions[request.callId + request.toTag] ||
  17129. undefined;
  17130. };
  17131. UA.prototype.on = function (name, callback) { return _super.prototype.on.call(this, name, callback); };
  17132. // ==============================
  17133. // Event Handlers
  17134. // ==============================
  17135. UA.prototype.onTransportError = function () {
  17136. if (this.status === Enums_1.UAStatus.STATUS_USER_CLOSED) {
  17137. return;
  17138. }
  17139. if (!this.error || this.error !== UA.C.NETWORK_ERROR) {
  17140. this.status = Enums_1.UAStatus.STATUS_NOT_READY;
  17141. this.error = UA.C.NETWORK_ERROR;
  17142. }
  17143. };
  17144. /**
  17145. * Helper function. Sets transport listeners
  17146. */
  17147. UA.prototype.setTransportListeners = function () {
  17148. var _this = this;
  17149. this.transport.on("connected", function () { return _this.onTransportConnected(); });
  17150. this.transport.on("message", function (message) { return _this.onTransportReceiveMsg(message); });
  17151. this.transport.on("transportError", function () { return _this.onTransportError(); });
  17152. };
  17153. /**
  17154. * Transport connection event.
  17155. * @event
  17156. * @param {SIP.Transport} transport.
  17157. */
  17158. UA.prototype.onTransportConnected = function () {
  17159. var _this = this;
  17160. if (this.configuration.register) {
  17161. // In an effor to maintain behavior from when we "initialized" an
  17162. // authentication factory, this is in a Promise.then
  17163. Promise.resolve().then(function () { return _this.registerContext.register(); });
  17164. }
  17165. };
  17166. /**
  17167. * Handle SIP message received from the transport.
  17168. * @param messageString The message.
  17169. */
  17170. UA.prototype.onTransportReceiveMsg = function (messageString) {
  17171. var _this = this;
  17172. var message = Parser_1.Parser.parseMessage(messageString, this.getLogger("sip.parser"));
  17173. if (!message) {
  17174. this.logger.warn("UA failed to parse incoming SIP message - discarding.");
  17175. return;
  17176. }
  17177. if (this.status === Enums_1.UAStatus.STATUS_USER_CLOSED && message instanceof core_1.IncomingRequestMessage) {
  17178. this.logger.warn("UA received message when status = USER_CLOSED - aborting");
  17179. return;
  17180. }
  17181. // A valid SIP request formulated by a UAC MUST, at a minimum, contain
  17182. // the following header fields: To, From, CSeq, Call-ID, Max-Forwards,
  17183. // and Via; all of these header fields are mandatory in all SIP
  17184. // requests.
  17185. // https://tools.ietf.org/html/rfc3261#section-8.1.1
  17186. var hasMinimumHeaders = function () {
  17187. var mandatoryHeaders = ["from", "to", "call_id", "cseq", "via"];
  17188. for (var _i = 0, mandatoryHeaders_1 = mandatoryHeaders; _i < mandatoryHeaders_1.length; _i++) {
  17189. var header = mandatoryHeaders_1[_i];
  17190. if (!message.hasHeader(header)) {
  17191. _this.logger.warn("Missing mandatory header field : " + header + ".");
  17192. return false;
  17193. }
  17194. }
  17195. return true;
  17196. };
  17197. // Request Checks
  17198. if (message instanceof core_1.IncomingRequestMessage) {
  17199. // This is port of SanityCheck.minimumHeaders().
  17200. if (!hasMinimumHeaders()) {
  17201. this.logger.warn("Request missing mandatory header field. Dropping.");
  17202. return;
  17203. }
  17204. // FIXME: This is non-standard and should be a configruable behavior (desirable regardless).
  17205. // Custom SIP.js check to reject request from ourself (this instance of SIP.js).
  17206. // This is port of SanityCheck.rfc3261_16_3_4().
  17207. if (!message.toTag && message.callId.substr(0, 5) === this.configuration.sipjsId) {
  17208. this.userAgentCore.replyStateless(message, { statusCode: 482 });
  17209. return;
  17210. }
  17211. // FIXME: This should be Transport check before we get here (Section 18).
  17212. // Custom SIP.js check to reject requests if body length wrong.
  17213. // This is port of SanityCheck.rfc3261_18_3_request().
  17214. var len = Utils_1.Utils.str_utf8_length(message.body);
  17215. var contentLength = message.getHeader("content-length");
  17216. if (contentLength && len < Number(contentLength)) {
  17217. this.userAgentCore.replyStateless(message, { statusCode: 400 });
  17218. return;
  17219. }
  17220. }
  17221. // Reponse Checks
  17222. if (message instanceof core_1.IncomingResponseMessage) {
  17223. // This is port of SanityCheck.minimumHeaders().
  17224. if (!hasMinimumHeaders()) {
  17225. this.logger.warn("Response missing mandatory header field. Dropping.");
  17226. return;
  17227. }
  17228. // Custom SIP.js check to drop responses if multiple Via headers.
  17229. // This is port of SanityCheck.rfc3261_8_1_3_3().
  17230. if (message.getHeaders("via").length > 1) {
  17231. this.logger.warn("More than one Via header field present in the response. Dropping.");
  17232. return;
  17233. }
  17234. // FIXME: This should be Transport check before we get here (Section 18).
  17235. // Custom SIP.js check to drop responses if bad Via header.
  17236. // This is port of SanityCheck.rfc3261_18_1_2().
  17237. if (message.via.host !== this.configuration.viaHost || message.via.port !== undefined) {
  17238. this.logger.warn("Via sent-by in the response does not match UA Via host value. Dropping.");
  17239. return;
  17240. }
  17241. // FIXME: This should be Transport check before we get here (Section 18).
  17242. // Custom SIP.js check to reject requests if body length wrong.
  17243. // This is port of SanityCheck.rfc3261_18_3_response().
  17244. var len = Utils_1.Utils.str_utf8_length(message.body);
  17245. var contentLength = message.getHeader("content-length");
  17246. if (contentLength && len < Number(contentLength)) {
  17247. this.logger.warn("Message body length is lower than the value in Content-Length header field. Dropping.");
  17248. return;
  17249. }
  17250. }
  17251. // Handle Request
  17252. if (message instanceof core_1.IncomingRequestMessage) {
  17253. this.userAgentCore.receiveIncomingRequestFromTransport(message);
  17254. return;
  17255. }
  17256. // Handle Response
  17257. if (message instanceof core_1.IncomingResponseMessage) {
  17258. this.userAgentCore.receiveIncomingResponseFromTransport(message);
  17259. return;
  17260. }
  17261. throw new Error("Invalid message type.");
  17262. };
  17263. // =================
  17264. // Utils
  17265. // =================
  17266. UA.prototype.checkAuthenticationFactory = function (authenticationFactory) {
  17267. if (!(authenticationFactory instanceof Function)) {
  17268. return;
  17269. }
  17270. if (!authenticationFactory.initialize) {
  17271. authenticationFactory.initialize = function () {
  17272. return Promise.resolve();
  17273. };
  17274. }
  17275. return authenticationFactory;
  17276. };
  17277. /**
  17278. * Configuration load.
  17279. * returns {void}
  17280. */
  17281. UA.prototype.loadConfig = function (configuration) {
  17282. var _this = this;
  17283. // Settings and default values
  17284. var settings = {
  17285. /* Host address
  17286. * Value to be set in Via sent_by and host part of Contact FQDN
  17287. */
  17288. viaHost: Utils_1.Utils.createRandomToken(12) + ".invalid",
  17289. uri: new core_1.URI("sip", "anonymous." + Utils_1.Utils.createRandomToken(6), "anonymous.invalid", undefined, undefined),
  17290. // Custom Configuration Settings
  17291. custom: {},
  17292. // Display name
  17293. displayName: "",
  17294. // Password
  17295. password: undefined,
  17296. register: true,
  17297. // Registration parameters
  17298. registerOptions: {},
  17299. // Transport related parameters
  17300. transportConstructor: Transport_1.Transport,
  17301. transportOptions: {},
  17302. usePreloadedRoute: false,
  17303. // string to be inserted into User-Agent request header
  17304. userAgentString: Constants_1.C.USER_AGENT,
  17305. // Session parameters
  17306. noAnswerTimeout: 60,
  17307. // Hacks
  17308. hackViaTcp: false,
  17309. hackIpInContact: false,
  17310. hackWssInTransport: false,
  17311. hackAllowUnregisteredOptionTags: false,
  17312. // Session Description Handler Options
  17313. sessionDescriptionHandlerFactoryOptions: {
  17314. constraints: {},
  17315. peerConnectionOptions: {}
  17316. },
  17317. extraSupported: [],
  17318. contactName: Utils_1.Utils.createRandomToken(8),
  17319. contactTransport: "ws",
  17320. forceRport: false,
  17321. // autostarting
  17322. autostart: true,
  17323. autostop: true,
  17324. // Reliable Provisional Responses
  17325. rel100: Constants_1.C.supported.UNSUPPORTED,
  17326. // DTMF type: 'info' or 'rtp' (RFC 4733)
  17327. // RTP Payload Spec: https://tools.ietf.org/html/rfc4733
  17328. // WebRTC Audio Spec: https://tools.ietf.org/html/rfc7874
  17329. dtmfType: Constants_1.C.dtmfType.INFO,
  17330. // Replaces header (RFC 3891)
  17331. // http://tools.ietf.org/html/rfc3891
  17332. replaces: Constants_1.C.supported.UNSUPPORTED,
  17333. sessionDescriptionHandlerFactory: SessionDescriptionHandler_1.SessionDescriptionHandler.defaultFactory,
  17334. authenticationFactory: this.checkAuthenticationFactory(function (ua) {
  17335. return new core_1.DigestAuthentication(ua.getLoggerFactory(), _this.configuration.authorizationUser, _this.configuration.password);
  17336. }),
  17337. allowLegacyNotifications: false,
  17338. allowOutOfDialogRefers: false,
  17339. experimentalFeatures: false
  17340. };
  17341. var configCheck = this.getConfigurationCheck();
  17342. // Check Mandatory parameters
  17343. for (var parameter in configCheck.mandatory) {
  17344. if (!configuration.hasOwnProperty(parameter)) {
  17345. throw new Exceptions_1.Exceptions.ConfigurationError(parameter);
  17346. }
  17347. else {
  17348. var value = configuration[parameter];
  17349. var checkedValue = configCheck.mandatory[parameter](value);
  17350. if (checkedValue !== undefined) {
  17351. settings[parameter] = checkedValue;
  17352. }
  17353. else {
  17354. throw new Exceptions_1.Exceptions.ConfigurationError(parameter, value);
  17355. }
  17356. }
  17357. }
  17358. // Check Optional parameters
  17359. for (var parameter in configCheck.optional) {
  17360. if (configuration.hasOwnProperty(parameter)) {
  17361. var value = configuration[parameter];
  17362. // If the parameter value is an empty array, but shouldn't be, apply its default value.
  17363. // If the parameter value is null, empty string, or undefined then apply its default value.
  17364. // If it's a number with NaN value then also apply its default value.
  17365. // NOTE: JS does not allow "value === NaN", the following does the work:
  17366. if ((value instanceof Array && value.length === 0) ||
  17367. (value === null || value === "" || value === undefined) ||
  17368. (typeof (value) === "number" && isNaN(value))) {
  17369. continue;
  17370. }
  17371. var checkedValue = configCheck.optional[parameter](value);
  17372. if (checkedValue !== undefined) {
  17373. settings[parameter] = checkedValue;
  17374. }
  17375. else {
  17376. throw new Exceptions_1.Exceptions.ConfigurationError(parameter, value);
  17377. }
  17378. }
  17379. }
  17380. // Post Configuration Process
  17381. // Allow passing 0 number as displayName.
  17382. if (settings.displayName === 0) {
  17383. settings.displayName = "0";
  17384. }
  17385. // sipjsId instance parameter. Static random tag of length 5
  17386. settings.sipjsId = Utils_1.Utils.createRandomToken(5);
  17387. // String containing settings.uri without scheme and user.
  17388. var hostportParams = settings.uri.clone();
  17389. hostportParams.user = undefined;
  17390. settings.hostportParams = hostportParams.toRaw().replace(/^sip:/i, "");
  17391. /* Check whether authorizationUser is explicitly defined.
  17392. * Take 'settings.uri.user' value if not.
  17393. */
  17394. if (!settings.authorizationUser) {
  17395. settings.authorizationUser = settings.uri.user;
  17396. }
  17397. // User noAnswerTimeout
  17398. settings.noAnswerTimeout = settings.noAnswerTimeout * 1000;
  17399. // Via Host
  17400. if (settings.hackIpInContact) {
  17401. if (typeof settings.hackIpInContact === "boolean") {
  17402. var from = 1;
  17403. var to = 254;
  17404. var octet = Math.floor(Math.random() * (to - from + 1) + from);
  17405. // random Test-Net IP (http://tools.ietf.org/html/rfc5735)
  17406. settings.viaHost = "192.0.2." + octet;
  17407. }
  17408. else if (typeof settings.hackIpInContact === "string") {
  17409. settings.viaHost = settings.hackIpInContact;
  17410. }
  17411. }
  17412. // Contact transport parameter
  17413. if (settings.hackWssInTransport) {
  17414. settings.contactTransport = "wss";
  17415. }
  17416. this.contact = {
  17417. pubGruu: undefined,
  17418. tempGruu: undefined,
  17419. uri: new core_1.URI("sip", settings.contactName, settings.viaHost, undefined, { transport: settings.contactTransport }),
  17420. toString: function (options) {
  17421. if (options === void 0) { options = {}; }
  17422. var anonymous = options.anonymous || false;
  17423. var outbound = options.outbound || false;
  17424. var contact = "<";
  17425. if (anonymous) {
  17426. contact += (_this.contact.tempGruu ||
  17427. ("sip:anonymous@anonymous.invalid;transport=" + settings.contactTransport)).toString();
  17428. }
  17429. else {
  17430. contact += (_this.contact.pubGruu || _this.contact.uri).toString();
  17431. }
  17432. if (outbound) {
  17433. contact += ";ob";
  17434. }
  17435. contact += ">";
  17436. return contact;
  17437. }
  17438. };
  17439. var skeleton = {};
  17440. // Fill the value of the configuration_skeleton
  17441. for (var parameter in settings) {
  17442. if (settings.hasOwnProperty(parameter)) {
  17443. skeleton[parameter] = settings[parameter];
  17444. }
  17445. }
  17446. Object.assign(this.configuration, skeleton);
  17447. this.logger.log("configuration parameters after validation:");
  17448. for (var parameter in settings) {
  17449. if (settings.hasOwnProperty(parameter)) {
  17450. switch (parameter) {
  17451. case "uri":
  17452. case "sessionDescriptionHandlerFactory":
  17453. this.logger.log("· " + parameter + ": " + settings[parameter]);
  17454. break;
  17455. case "password":
  17456. this.logger.log("· " + parameter + ": " + "NOT SHOWN");
  17457. break;
  17458. case "transportConstructor":
  17459. this.logger.log("· " + parameter + ": " + settings[parameter].name);
  17460. break;
  17461. default:
  17462. this.logger.log("· " + parameter + ": " + JSON.stringify(settings[parameter]));
  17463. }
  17464. }
  17465. }
  17466. return;
  17467. };
  17468. /**
  17469. * Configuration checker.
  17470. * @return {Boolean}
  17471. */
  17472. UA.prototype.getConfigurationCheck = function () {
  17473. return {
  17474. mandatory: {},
  17475. optional: {
  17476. uri: function (uri) {
  17477. if (!(/^sip:/i).test(uri)) {
  17478. uri = Constants_1.C.SIP + ":" + uri;
  17479. }
  17480. var parsed = core_1.Grammar.URIParse(uri);
  17481. if (!parsed || !parsed.user) {
  17482. return;
  17483. }
  17484. else {
  17485. return parsed;
  17486. }
  17487. },
  17488. transportConstructor: function (transportConstructor) {
  17489. if (transportConstructor instanceof Function) {
  17490. return transportConstructor;
  17491. }
  17492. },
  17493. transportOptions: function (transportOptions) {
  17494. if (typeof transportOptions === "object") {
  17495. return transportOptions;
  17496. }
  17497. },
  17498. authorizationUser: function (authorizationUser) {
  17499. if (core_1.Grammar.parse('"' + authorizationUser + '"', "quoted_string") === -1) {
  17500. return;
  17501. }
  17502. else {
  17503. return authorizationUser;
  17504. }
  17505. },
  17506. displayName: function (displayName) {
  17507. if (core_1.Grammar.parse('"' + displayName + '"', "displayName") === -1) {
  17508. return;
  17509. }
  17510. else {
  17511. return displayName;
  17512. }
  17513. },
  17514. dtmfType: function (dtmfType) {
  17515. switch (dtmfType) {
  17516. case Constants_1.C.dtmfType.RTP:
  17517. return Constants_1.C.dtmfType.RTP;
  17518. case Constants_1.C.dtmfType.INFO:
  17519. // Fall through
  17520. default:
  17521. return Constants_1.C.dtmfType.INFO;
  17522. }
  17523. },
  17524. hackViaTcp: function (hackViaTcp) {
  17525. if (typeof hackViaTcp === "boolean") {
  17526. return hackViaTcp;
  17527. }
  17528. },
  17529. hackIpInContact: function (hackIpInContact) {
  17530. if (typeof hackIpInContact === "boolean") {
  17531. return hackIpInContact;
  17532. }
  17533. else if (typeof hackIpInContact === "string" && core_1.Grammar.parse(hackIpInContact, "host") !== -1) {
  17534. return hackIpInContact;
  17535. }
  17536. },
  17537. hackWssInTransport: function (hackWssInTransport) {
  17538. if (typeof hackWssInTransport === "boolean") {
  17539. return hackWssInTransport;
  17540. }
  17541. },
  17542. hackAllowUnregisteredOptionTags: function (hackAllowUnregisteredOptionTags) {
  17543. if (typeof hackAllowUnregisteredOptionTags === "boolean") {
  17544. return hackAllowUnregisteredOptionTags;
  17545. }
  17546. },
  17547. contactTransport: function (contactTransport) {
  17548. if (typeof contactTransport === "string") {
  17549. return contactTransport;
  17550. }
  17551. },
  17552. extraSupported: function (optionTags) {
  17553. if (!(optionTags instanceof Array)) {
  17554. return;
  17555. }
  17556. for (var _i = 0, optionTags_1 = optionTags; _i < optionTags_1.length; _i++) {
  17557. var tag = optionTags_1[_i];
  17558. if (typeof tag !== "string") {
  17559. return;
  17560. }
  17561. }
  17562. return optionTags;
  17563. },
  17564. forceRport: function (forceRport) {
  17565. if (typeof forceRport === "boolean") {
  17566. return forceRport;
  17567. }
  17568. },
  17569. noAnswerTimeout: function (noAnswerTimeout) {
  17570. if (Utils_1.Utils.isDecimal(noAnswerTimeout)) {
  17571. var value = Number(noAnswerTimeout);
  17572. if (value > 0) {
  17573. return value;
  17574. }
  17575. }
  17576. },
  17577. password: function (password) {
  17578. return String(password);
  17579. },
  17580. rel100: function (rel100) {
  17581. if (rel100 === Constants_1.C.supported.REQUIRED) {
  17582. return Constants_1.C.supported.REQUIRED;
  17583. }
  17584. else if (rel100 === Constants_1.C.supported.SUPPORTED) {
  17585. return Constants_1.C.supported.SUPPORTED;
  17586. }
  17587. else {
  17588. return Constants_1.C.supported.UNSUPPORTED;
  17589. }
  17590. },
  17591. replaces: function (replaces) {
  17592. if (replaces === Constants_1.C.supported.REQUIRED) {
  17593. return Constants_1.C.supported.REQUIRED;
  17594. }
  17595. else if (replaces === Constants_1.C.supported.SUPPORTED) {
  17596. return Constants_1.C.supported.SUPPORTED;
  17597. }
  17598. else {
  17599. return Constants_1.C.supported.UNSUPPORTED;
  17600. }
  17601. },
  17602. register: function (register) {
  17603. if (typeof register === "boolean") {
  17604. return register;
  17605. }
  17606. },
  17607. registerOptions: function (registerOptions) {
  17608. if (typeof registerOptions === "object") {
  17609. return registerOptions;
  17610. }
  17611. },
  17612. usePreloadedRoute: function (usePreloadedRoute) {
  17613. if (typeof usePreloadedRoute === "boolean") {
  17614. return usePreloadedRoute;
  17615. }
  17616. },
  17617. userAgentString: function (userAgentString) {
  17618. if (typeof userAgentString === "string") {
  17619. return userAgentString;
  17620. }
  17621. },
  17622. autostart: function (autostart) {
  17623. if (typeof autostart === "boolean") {
  17624. return autostart;
  17625. }
  17626. },
  17627. autostop: function (autostop) {
  17628. if (typeof autostop === "boolean") {
  17629. return autostop;
  17630. }
  17631. },
  17632. sessionDescriptionHandlerFactory: function (sessionDescriptionHandlerFactory) {
  17633. if (sessionDescriptionHandlerFactory instanceof Function) {
  17634. return sessionDescriptionHandlerFactory;
  17635. }
  17636. },
  17637. sessionDescriptionHandlerFactoryOptions: function (options) {
  17638. if (typeof options === "object") {
  17639. return options;
  17640. }
  17641. },
  17642. authenticationFactory: this.checkAuthenticationFactory,
  17643. allowLegacyNotifications: function (allowLegacyNotifications) {
  17644. if (typeof allowLegacyNotifications === "boolean") {
  17645. return allowLegacyNotifications;
  17646. }
  17647. },
  17648. custom: function (custom) {
  17649. if (typeof custom === "object") {
  17650. return custom;
  17651. }
  17652. },
  17653. contactName: function (contactName) {
  17654. if (typeof contactName === "string") {
  17655. return contactName;
  17656. }
  17657. },
  17658. experimentalFeatures: function (experimentalFeatures) {
  17659. if (typeof experimentalFeatures === "boolean") {
  17660. return experimentalFeatures;
  17661. }
  17662. },
  17663. }
  17664. };
  17665. };
  17666. UA.C = {
  17667. // UA status codes
  17668. STATUS_INIT: 0,
  17669. STATUS_STARTING: 1,
  17670. STATUS_READY: 2,
  17671. STATUS_USER_CLOSED: 3,
  17672. STATUS_NOT_READY: 4,
  17673. // UA error codes
  17674. CONFIGURATION_ERROR: 1,
  17675. NETWORK_ERROR: 2,
  17676. ALLOWED_METHODS: [
  17677. "ACK",
  17678. "CANCEL",
  17679. "INVITE",
  17680. "MESSAGE",
  17681. "BYE",
  17682. "OPTIONS",
  17683. "INFO",
  17684. "NOTIFY",
  17685. "REFER"
  17686. ],
  17687. ACCEPTED_BODY_TYPES: [
  17688. "application/sdp",
  17689. "application/dtmf-relay"
  17690. ],
  17691. MAX_FORWARDS: 70,
  17692. TAG_LENGTH: 10
  17693. };
  17694. return UA;
  17695. }(events_1.EventEmitter));
  17696. exports.UA = UA;
  17697. (function (UA) {
  17698. var DtmfType;
  17699. (function (DtmfType) {
  17700. DtmfType["RTP"] = "rtp";
  17701. DtmfType["INFO"] = "info";
  17702. })(DtmfType = UA.DtmfType || (UA.DtmfType = {}));
  17703. })(UA = exports.UA || (exports.UA = {}));
  17704. exports.UA = UA;
  17705. /**
  17706. * Factory function to generate configuration give a UA.
  17707. * @param ua UA
  17708. */
  17709. function makeUserAgentCoreConfigurationFromUA(ua) {
  17710. // FIXME: Configuration URI is a bad mix of types currently. It also needs to exist.
  17711. if (!(ua.configuration.uri instanceof core_1.URI)) {
  17712. throw new Error("Configuration URI not instance of URI.");
  17713. }
  17714. var aor = ua.configuration.uri;
  17715. var contact = ua.contact;
  17716. var displayName = ua.configuration.displayName ? ua.configuration.displayName : "";
  17717. var hackViaTcp = ua.configuration.hackViaTcp ? true : false;
  17718. var routeSet = ua.configuration.usePreloadedRoute && ua.transport.server && ua.transport.server.sipUri ?
  17719. [ua.transport.server.sipUri] :
  17720. [];
  17721. var sipjsId = ua.configuration.sipjsId || Utils_1.Utils.createRandomToken(5);
  17722. var supportedOptionTags = [];
  17723. supportedOptionTags.push("outbound"); // TODO: is this really supported?
  17724. if (ua.configuration.rel100 === Constants_1.C.supported.SUPPORTED) {
  17725. supportedOptionTags.push("100rel");
  17726. }
  17727. if (ua.configuration.replaces === Constants_1.C.supported.SUPPORTED) {
  17728. supportedOptionTags.push("replaces");
  17729. }
  17730. if (ua.configuration.extraSupported) {
  17731. supportedOptionTags.push.apply(supportedOptionTags, ua.configuration.extraSupported);
  17732. }
  17733. if (!ua.configuration.hackAllowUnregisteredOptionTags) {
  17734. supportedOptionTags = supportedOptionTags.filter(function (optionTag) { return Constants_1.C.OPTION_TAGS[optionTag]; });
  17735. }
  17736. supportedOptionTags = Array.from(new Set(supportedOptionTags)); // array of unique values
  17737. var supportedOptionTagsResponse = ua.getSupportedResponseOptions();
  17738. var userAgentHeaderFieldValue = ua.configuration.userAgentString || "sipjs";
  17739. if (!(ua.configuration.viaHost)) {
  17740. throw new Error("Configuration via host undefined");
  17741. }
  17742. var viaForceRport = ua.configuration.forceRport ? true : false;
  17743. var viaHost = ua.configuration.viaHost;
  17744. var configuration = {
  17745. aor: aor,
  17746. contact: contact,
  17747. displayName: displayName,
  17748. hackViaTcp: hackViaTcp,
  17749. loggerFactory: ua.getLoggerFactory(),
  17750. routeSet: routeSet,
  17751. sipjsId: sipjsId,
  17752. supportedOptionTags: supportedOptionTags,
  17753. supportedOptionTagsResponse: supportedOptionTagsResponse,
  17754. userAgentHeaderFieldValue: userAgentHeaderFieldValue,
  17755. viaForceRport: viaForceRport,
  17756. viaHost: viaHost,
  17757. authenticationFactory: function () {
  17758. if (ua.configuration.authenticationFactory) {
  17759. return ua.configuration.authenticationFactory(ua);
  17760. }
  17761. return undefined;
  17762. },
  17763. transportAccessor: function () { return ua.transport; }
  17764. };
  17765. return configuration;
  17766. }
  17767. exports.makeUserAgentCoreConfigurationFromUA = makeUserAgentCoreConfigurationFromUA;
  17768. /***/ }),
  17769. /* 94 */
  17770. /***/ (function(module, exports, __webpack_require__) {
  17771. "use strict";
  17772. Object.defineProperty(exports, "__esModule", { value: true });
  17773. var tslib_1 = __webpack_require__(1);
  17774. var events_1 = __webpack_require__(30);
  17775. var session_1 = __webpack_require__(95);
  17776. var Enums_1 = __webpack_require__(82);
  17777. var Exceptions_1 = __webpack_require__(84);
  17778. var Utils_1 = __webpack_require__(83);
  17779. var Modifiers = tslib_1.__importStar(__webpack_require__(101));
  17780. var SessionDescriptionHandlerObserver_1 = __webpack_require__(102);
  17781. /* SessionDescriptionHandler
  17782. * @class PeerConnection helper Class.
  17783. * @param {SIP.Session} session
  17784. * @param {Object} [options]
  17785. */
  17786. var SessionDescriptionHandler = /** @class */ (function (_super) {
  17787. tslib_1.__extends(SessionDescriptionHandler, _super);
  17788. function SessionDescriptionHandler(logger, observer, options) {
  17789. var _this = _super.call(this) || this;
  17790. _this.type = Enums_1.TypeStrings.SessionDescriptionHandler;
  17791. // TODO: Validate the options
  17792. _this.options = options || {};
  17793. _this.logger = logger;
  17794. _this.observer = observer;
  17795. _this.dtmfSender = undefined;
  17796. _this.shouldAcquireMedia = true;
  17797. _this.CONTENT_TYPE = "application/sdp";
  17798. _this.C = {
  17799. DIRECTION: {
  17800. NULL: null,
  17801. SENDRECV: "sendrecv",
  17802. SENDONLY: "sendonly",
  17803. RECVONLY: "recvonly",
  17804. INACTIVE: "inactive"
  17805. }
  17806. };
  17807. _this.logger.log("SessionDescriptionHandlerOptions: " + JSON.stringify(_this.options));
  17808. _this.direction = _this.C.DIRECTION.NULL;
  17809. _this.modifiers = _this.options.modifiers || [];
  17810. if (!Array.isArray(_this.modifiers)) {
  17811. _this.modifiers = [_this.modifiers];
  17812. }
  17813. _this.iceGatheringTimeout = false;
  17814. _this.initPeerConnection(_this.options.peerConnectionOptions);
  17815. _this.constraints = _this.checkAndDefaultConstraints(_this.options.constraints);
  17816. return _this;
  17817. }
  17818. /**
  17819. * @param {SIP.Session} session
  17820. * @param {Object} [options]
  17821. */
  17822. SessionDescriptionHandler.defaultFactory = function (session, options) {
  17823. var logger = (session instanceof session_1.Session) ?
  17824. session.userAgent.getLogger("sip.sessionDescriptionHandler", session.id) :
  17825. session.ua.getLogger("sip.invitecontext.sessionDescriptionHandler", session.id);
  17826. var observer = new SessionDescriptionHandlerObserver_1.SessionDescriptionHandlerObserver(session, options);
  17827. return new SessionDescriptionHandler(logger, observer, options);
  17828. };
  17829. // Functions the sesssion can use
  17830. /**
  17831. * Destructor
  17832. */
  17833. SessionDescriptionHandler.prototype.close = function () {
  17834. this.logger.log("closing PeerConnection");
  17835. // have to check signalingState since this.close() gets called multiple times
  17836. if (this.peerConnection && this.peerConnection.signalingState !== "closed") {
  17837. if (this.peerConnection.getSenders) {
  17838. this.peerConnection.getSenders().forEach(function (sender) {
  17839. if (sender.track) {
  17840. sender.track.stop();
  17841. }
  17842. });
  17843. }
  17844. else {
  17845. this.logger.warn("Using getLocalStreams which is deprecated");
  17846. this.peerConnection.getLocalStreams().forEach(function (stream) {
  17847. stream.getTracks().forEach(function (track) {
  17848. track.stop();
  17849. });
  17850. });
  17851. }
  17852. if (this.peerConnection.getReceivers) {
  17853. this.peerConnection.getReceivers().forEach(function (receiver) {
  17854. if (receiver.track) {
  17855. receiver.track.stop();
  17856. }
  17857. });
  17858. }
  17859. else {
  17860. this.logger.warn("Using getRemoteStreams which is deprecated");
  17861. this.peerConnection.getRemoteStreams().forEach(function (stream) {
  17862. stream.getTracks().forEach(function (track) {
  17863. track.stop();
  17864. });
  17865. });
  17866. }
  17867. this.resetIceGatheringComplete();
  17868. this.peerConnection.close();
  17869. }
  17870. };
  17871. /**
  17872. * Gets the local description from the underlying media implementation
  17873. * @param {Object} [options] Options object to be used by getDescription
  17874. * @param {MediaStreamConstraints} [options.constraints] MediaStreamConstraints
  17875. * https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints
  17876. * @param {Object} [options.peerConnectionOptions] If this is set it will recreate the peer
  17877. * connection with the new options
  17878. * @param {Array} [modifiers] Array with one time use description modifiers
  17879. * @returns {Promise} Promise that resolves with the local description to be used for the session
  17880. */
  17881. SessionDescriptionHandler.prototype.getDescription = function (options, modifiers) {
  17882. var _this = this;
  17883. if (options === void 0) { options = {}; }
  17884. if (modifiers === void 0) { modifiers = []; }
  17885. if (options.peerConnectionOptions) {
  17886. this.initPeerConnection(options.peerConnectionOptions);
  17887. }
  17888. // Merge passed constraints with saved constraints and save
  17889. var newConstraints = Object.assign({}, this.constraints, options.constraints);
  17890. newConstraints = this.checkAndDefaultConstraints(newConstraints);
  17891. if (JSON.stringify(newConstraints) !== JSON.stringify(this.constraints)) {
  17892. this.constraints = newConstraints;
  17893. this.shouldAcquireMedia = true;
  17894. }
  17895. if (!Array.isArray(modifiers)) {
  17896. modifiers = [modifiers];
  17897. }
  17898. modifiers = modifiers.concat(this.modifiers);
  17899. return Promise.resolve().then(function () {
  17900. if (_this.shouldAcquireMedia) {
  17901. return _this.acquire(_this.constraints).then(function () {
  17902. _this.shouldAcquireMedia = false;
  17903. });
  17904. }
  17905. }).then(function () { return _this.createOfferOrAnswer(options.RTCOfferOptions, modifiers); })
  17906. .then(function (description) {
  17907. if (description.sdp === undefined) {
  17908. throw new Exceptions_1.Exceptions.SessionDescriptionHandlerError("getDescription", undefined, "SDP undefined");
  17909. }
  17910. _this.emit("getDescription", description);
  17911. return {
  17912. body: description.sdp,
  17913. contentType: _this.CONTENT_TYPE
  17914. };
  17915. });
  17916. };
  17917. /**
  17918. * Check if the Session Description Handler can handle the Content-Type described by a SIP Message
  17919. * @param {String} contentType The content type that is in the SIP Message
  17920. * @returns {boolean}
  17921. */
  17922. SessionDescriptionHandler.prototype.hasDescription = function (contentType) {
  17923. return contentType === this.CONTENT_TYPE;
  17924. };
  17925. /**
  17926. * The modifier that should be used when the session would like to place the call on hold
  17927. * @param {String} [sdp] The description that will be modified
  17928. * @returns {Promise} Promise that resolves with modified SDP
  17929. */
  17930. SessionDescriptionHandler.prototype.holdModifier = function (description) {
  17931. if (!description.sdp) {
  17932. return Promise.resolve(description);
  17933. }
  17934. if (!(/a=(sendrecv|sendonly|recvonly|inactive)/).test(description.sdp)) {
  17935. description.sdp = description.sdp.replace(/(m=[^\r]*\r\n)/g, "$1a=sendonly\r\n");
  17936. }
  17937. else {
  17938. description.sdp = description.sdp.replace(/a=sendrecv\r\n/g, "a=sendonly\r\n");
  17939. description.sdp = description.sdp.replace(/a=recvonly\r\n/g, "a=inactive\r\n");
  17940. }
  17941. return Promise.resolve(description);
  17942. };
  17943. /**
  17944. * Set the remote description to the underlying media implementation
  17945. * @param {String} sessionDescription The description provided by a SIP message to be set on the media implementation
  17946. * @param {Object} [options] Options object to be used by getDescription
  17947. * @param {MediaStreamConstraints} [options.constraints] MediaStreamConstraints
  17948. * https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints
  17949. * @param {Object} [options.peerConnectionOptions] If this is set it will recreate the peer
  17950. * connection with the new options
  17951. * @param {Array} [modifiers] Array with one time use description modifiers
  17952. * @returns {Promise} Promise that resolves once the description is set
  17953. */
  17954. SessionDescriptionHandler.prototype.setDescription = function (sessionDescription, options, modifiers) {
  17955. var _this = this;
  17956. if (options === void 0) { options = {}; }
  17957. if (modifiers === void 0) { modifiers = []; }
  17958. if (options.peerConnectionOptions) {
  17959. this.initPeerConnection(options.peerConnectionOptions);
  17960. }
  17961. if (!Array.isArray(modifiers)) {
  17962. modifiers = [modifiers];
  17963. }
  17964. modifiers = modifiers.concat(this.modifiers);
  17965. var description = {
  17966. type: this.hasOffer("local") ? "answer" : "offer",
  17967. sdp: sessionDescription
  17968. };
  17969. return Promise.resolve().then(function () {
  17970. // Media should be acquired in getDescription unless we need to do it sooner for some reason (FF61+)
  17971. if (_this.shouldAcquireMedia && _this.options.alwaysAcquireMediaFirst) {
  17972. return _this.acquire(_this.constraints).then(function () {
  17973. _this.shouldAcquireMedia = false;
  17974. });
  17975. }
  17976. }).then(function () { return Utils_1.Utils.reducePromises(modifiers, description); })
  17977. .catch(function (e) {
  17978. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  17979. throw e;
  17980. }
  17981. var error = new Exceptions_1.Exceptions.SessionDescriptionHandlerError("setDescription", e, "The modifiers did not resolve successfully");
  17982. _this.logger.error(error.message);
  17983. _this.emit("peerConnection-setRemoteDescriptionFailed", error);
  17984. throw error;
  17985. }).then(function (modifiedDescription) {
  17986. _this.emit("setDescription", modifiedDescription);
  17987. return _this.peerConnection.setRemoteDescription(modifiedDescription);
  17988. }).catch(function (e) {
  17989. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  17990. throw e;
  17991. }
  17992. // Check the original SDP for video, and ensure that we have want to do audio fallback
  17993. if ((/^m=video.+$/gm).test(sessionDescription) && !options.disableAudioFallback) {
  17994. // Do not try to audio fallback again
  17995. options.disableAudioFallback = true;
  17996. // Remove video first, then do the other modifiers
  17997. return _this.setDescription(sessionDescription, options, [Modifiers.stripVideo].concat(modifiers));
  17998. }
  17999. var error = new Exceptions_1.Exceptions.SessionDescriptionHandlerError("setDescription", e);
  18000. if (error.error) {
  18001. _this.logger.error(error.error);
  18002. }
  18003. _this.emit("peerConnection-setRemoteDescriptionFailed", error);
  18004. throw error;
  18005. }).then(function () {
  18006. if (_this.peerConnection.getReceivers) {
  18007. _this.emit("setRemoteDescription", _this.peerConnection.getReceivers());
  18008. }
  18009. else {
  18010. _this.emit("setRemoteDescription", _this.peerConnection.getRemoteStreams());
  18011. }
  18012. _this.emit("confirmed", _this);
  18013. });
  18014. };
  18015. /**
  18016. * Send DTMF via RTP (RFC 4733)
  18017. * @param {String} tones A string containing DTMF digits
  18018. * @param {Object} [options] Options object to be used by sendDtmf
  18019. * @returns {boolean} true if DTMF send is successful, false otherwise
  18020. */
  18021. SessionDescriptionHandler.prototype.sendDtmf = function (tones, options) {
  18022. if (options === void 0) { options = {}; }
  18023. if (!this.dtmfSender && this.hasBrowserGetSenderSupport()) {
  18024. var senders = this.peerConnection.getSenders();
  18025. if (senders.length > 0) {
  18026. this.dtmfSender = senders[0].dtmf;
  18027. }
  18028. }
  18029. if (!this.dtmfSender && this.hasBrowserTrackSupport()) {
  18030. var streams = this.peerConnection.getLocalStreams();
  18031. if (streams.length > 0) {
  18032. var audioTracks = streams[0].getAudioTracks();
  18033. if (audioTracks.length > 0) {
  18034. this.dtmfSender = this.peerConnection.createDTMFSender(audioTracks[0]);
  18035. }
  18036. }
  18037. }
  18038. if (!this.dtmfSender) {
  18039. return false;
  18040. }
  18041. try {
  18042. this.dtmfSender.insertDTMF(tones, options.duration, options.interToneGap);
  18043. }
  18044. catch (e) {
  18045. if (e.type === "InvalidStateError" || e.type === "InvalidCharacterError") {
  18046. this.logger.error(e);
  18047. return false;
  18048. }
  18049. else {
  18050. throw e;
  18051. }
  18052. }
  18053. this.logger.log("DTMF sent via RTP: " + tones.toString());
  18054. return true;
  18055. };
  18056. /**
  18057. * Get the direction of the session description
  18058. * @returns {String} direction of the description
  18059. */
  18060. SessionDescriptionHandler.prototype.getDirection = function () {
  18061. return this.direction;
  18062. };
  18063. SessionDescriptionHandler.prototype.on = function (name, callback) { return _super.prototype.on.call(this, name, callback); };
  18064. SessionDescriptionHandler.prototype.getMediaStream = function (constraints) {
  18065. return navigator.mediaDevices.getUserMedia(constraints);
  18066. };
  18067. // Internal functions
  18068. SessionDescriptionHandler.prototype.createOfferOrAnswer = function (RTCOfferOptions, modifiers) {
  18069. var _this = this;
  18070. if (RTCOfferOptions === void 0) { RTCOfferOptions = {}; }
  18071. if (modifiers === void 0) { modifiers = []; }
  18072. var methodName = this.hasOffer("remote") ? "createAnswer" : "createOffer";
  18073. var pc = this.peerConnection;
  18074. this.logger.log(methodName);
  18075. var method = this.hasOffer("remote") ? pc.createAnswer : pc.createOffer;
  18076. return method.apply(pc, RTCOfferOptions).catch(function (e) {
  18077. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  18078. throw e;
  18079. }
  18080. var error = new Exceptions_1.Exceptions.SessionDescriptionHandlerError("createOfferOrAnswer", e, "peerConnection-" + methodName + "Failed");
  18081. _this.emit("peerConnection-" + methodName + "Failed", error);
  18082. throw error;
  18083. }).then(function (sdp) {
  18084. return Utils_1.Utils.reducePromises(modifiers, _this.createRTCSessionDescriptionInit(sdp));
  18085. }).then(function (sdp) {
  18086. _this.resetIceGatheringComplete();
  18087. _this.logger.log("Setting local sdp.");
  18088. _this.logger.log("sdp is " + sdp.sdp || false);
  18089. return pc.setLocalDescription(sdp);
  18090. }).catch(function (e) {
  18091. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  18092. throw e;
  18093. }
  18094. var error = new Exceptions_1.Exceptions.SessionDescriptionHandlerError("createOfferOrAnswer", e, "peerConnection-SetLocalDescriptionFailed");
  18095. _this.emit("peerConnection-SetLocalDescriptionFailed", error);
  18096. throw error;
  18097. }).then(function () { return _this.waitForIceGatheringComplete(); })
  18098. .then(function () {
  18099. if (!_this.peerConnection.localDescription) {
  18100. throw new Exceptions_1.Exceptions.SessionDescriptionHandlerError("Missing local description");
  18101. }
  18102. var localDescription = _this.createRTCSessionDescriptionInit(_this.peerConnection.localDescription);
  18103. return Utils_1.Utils.reducePromises(modifiers, localDescription);
  18104. }).then(function (localDescription) {
  18105. _this.setDirection(localDescription.sdp || "");
  18106. return localDescription;
  18107. }).catch(function (e) {
  18108. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  18109. throw e;
  18110. }
  18111. var error = new Exceptions_1.Exceptions.SessionDescriptionHandlerError("createOfferOrAnswer", e);
  18112. _this.logger.error(error.toString());
  18113. throw error;
  18114. });
  18115. };
  18116. // Creates an RTCSessionDescriptionInit from an RTCSessionDescription
  18117. SessionDescriptionHandler.prototype.createRTCSessionDescriptionInit = function (RTCSessionDescription) {
  18118. return {
  18119. type: RTCSessionDescription.type,
  18120. sdp: RTCSessionDescription.sdp
  18121. };
  18122. };
  18123. SessionDescriptionHandler.prototype.addDefaultIceCheckingTimeout = function (peerConnectionOptions) {
  18124. if (peerConnectionOptions.iceCheckingTimeout === undefined) {
  18125. peerConnectionOptions.iceCheckingTimeout = 5000;
  18126. }
  18127. return peerConnectionOptions;
  18128. };
  18129. SessionDescriptionHandler.prototype.addDefaultIceServers = function (rtcConfiguration) {
  18130. if (!rtcConfiguration.iceServers) {
  18131. rtcConfiguration.iceServers = [{ urls: "stun:stun.l.google.com:19302" }];
  18132. }
  18133. return rtcConfiguration;
  18134. };
  18135. SessionDescriptionHandler.prototype.checkAndDefaultConstraints = function (constraints) {
  18136. var defaultConstraints = { audio: true, video: !this.options.alwaysAcquireMediaFirst };
  18137. constraints = constraints || defaultConstraints;
  18138. // Empty object check
  18139. if (Object.keys(constraints).length === 0 && constraints.constructor === Object) {
  18140. return defaultConstraints;
  18141. }
  18142. return constraints;
  18143. };
  18144. SessionDescriptionHandler.prototype.hasBrowserTrackSupport = function () {
  18145. return Boolean(this.peerConnection.addTrack);
  18146. };
  18147. SessionDescriptionHandler.prototype.hasBrowserGetSenderSupport = function () {
  18148. return Boolean(this.peerConnection.getSenders);
  18149. };
  18150. SessionDescriptionHandler.prototype.initPeerConnection = function (options) {
  18151. var _this = this;
  18152. if (options === void 0) { options = {}; }
  18153. options = this.addDefaultIceCheckingTimeout(options);
  18154. options.rtcConfiguration = options.rtcConfiguration || {};
  18155. options.rtcConfiguration = this.addDefaultIceServers(options.rtcConfiguration);
  18156. this.logger.log("initPeerConnection");
  18157. if (this.peerConnection) {
  18158. this.logger.log("Already have a peer connection for this session. Tearing down.");
  18159. this.resetIceGatheringComplete();
  18160. this.peerConnection.close();
  18161. }
  18162. this.peerConnection = new RTCPeerConnection(options.rtcConfiguration);
  18163. this.logger.log("New peer connection created");
  18164. if ("ontrack" in this.peerConnection) {
  18165. this.peerConnection.addEventListener("track", function (e) {
  18166. _this.logger.log("track added");
  18167. _this.observer.trackAdded();
  18168. _this.emit("addTrack", e);
  18169. });
  18170. }
  18171. else {
  18172. this.logger.warn("Using onaddstream which is deprecated");
  18173. this.peerConnection.onaddstream = function (e) {
  18174. _this.logger.log("stream added");
  18175. _this.emit("addStream", e);
  18176. };
  18177. }
  18178. this.peerConnection.onicecandidate = function (e) {
  18179. _this.emit("iceCandidate", e);
  18180. if (e.candidate) {
  18181. _this.logger.log("ICE candidate received: " +
  18182. (e.candidate.candidate === null ? null : e.candidate.candidate.trim()));
  18183. }
  18184. else if (e.candidate === null) {
  18185. // indicates the end of candidate gathering
  18186. _this.logger.log("ICE candidate gathering complete");
  18187. _this.triggerIceGatheringComplete();
  18188. }
  18189. };
  18190. this.peerConnection.onicegatheringstatechange = function () {
  18191. _this.logger.log("RTCIceGatheringState changed: " + _this.peerConnection.iceGatheringState);
  18192. switch (_this.peerConnection.iceGatheringState) {
  18193. case "gathering":
  18194. _this.emit("iceGathering", _this);
  18195. if (!_this.iceGatheringTimer && options.iceCheckingTimeout) {
  18196. _this.iceGatheringTimeout = false;
  18197. _this.iceGatheringTimer = setTimeout(function () {
  18198. _this.logger.log("RTCIceChecking Timeout Triggered after " + options.iceCheckingTimeout + " milliseconds");
  18199. _this.iceGatheringTimeout = true;
  18200. _this.triggerIceGatheringComplete();
  18201. }, options.iceCheckingTimeout);
  18202. }
  18203. break;
  18204. case "complete":
  18205. _this.triggerIceGatheringComplete();
  18206. break;
  18207. }
  18208. };
  18209. this.peerConnection.oniceconnectionstatechange = function () {
  18210. var stateEvent;
  18211. switch (_this.peerConnection.iceConnectionState) {
  18212. case "new":
  18213. stateEvent = "iceConnection";
  18214. break;
  18215. case "checking":
  18216. stateEvent = "iceConnectionChecking";
  18217. break;
  18218. case "connected":
  18219. stateEvent = "iceConnectionConnected";
  18220. break;
  18221. case "completed":
  18222. stateEvent = "iceConnectionCompleted";
  18223. break;
  18224. case "failed":
  18225. stateEvent = "iceConnectionFailed";
  18226. break;
  18227. case "disconnected":
  18228. stateEvent = "iceConnectionDisconnected";
  18229. break;
  18230. case "closed":
  18231. stateEvent = "iceConnectionClosed";
  18232. break;
  18233. default:
  18234. _this.logger.warn("Unknown iceConnection state: " + _this.peerConnection.iceConnectionState);
  18235. return;
  18236. }
  18237. _this.logger.log("ICE Connection State changed to " + stateEvent);
  18238. _this.emit(stateEvent, _this);
  18239. };
  18240. };
  18241. SessionDescriptionHandler.prototype.acquire = function (constraints) {
  18242. var _this = this;
  18243. // Default audio & video to true
  18244. constraints = this.checkAndDefaultConstraints(constraints);
  18245. return new Promise(function (resolve, reject) {
  18246. /*
  18247. * Make the call asynchronous, so that ICCs have a chance
  18248. * to define callbacks to `userMediaRequest`
  18249. */
  18250. _this.logger.log("acquiring local media");
  18251. _this.emit("userMediaRequest", constraints);
  18252. if (constraints.audio || constraints.video) {
  18253. _this.getMediaStream(constraints).then(function (streams) {
  18254. _this.observer.trackAdded();
  18255. _this.emit("userMedia", streams);
  18256. resolve(streams);
  18257. }).catch(function (e) {
  18258. _this.emit("userMediaFailed", e);
  18259. reject(e);
  18260. });
  18261. }
  18262. else {
  18263. // Local streams were explicitly excluded.
  18264. resolve([]);
  18265. }
  18266. }).catch(function (e) {
  18267. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  18268. throw e;
  18269. }
  18270. var error = new Exceptions_1.Exceptions.SessionDescriptionHandlerError("acquire", e, "unable to acquire streams");
  18271. _this.logger.error(error.message);
  18272. if (error.error) {
  18273. _this.logger.error(error.error);
  18274. }
  18275. throw error;
  18276. }).then(function (streams) {
  18277. _this.logger.log("acquired local media streams");
  18278. // Remove old tracks
  18279. if (_this.peerConnection.removeTrack) {
  18280. _this.peerConnection.getSenders().forEach(function (sender) {
  18281. _this.peerConnection.removeTrack(sender);
  18282. });
  18283. }
  18284. return streams;
  18285. }).catch(function (e) {
  18286. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  18287. throw e;
  18288. }
  18289. var error = new Exceptions_1.Exceptions.SessionDescriptionHandlerError("acquire", e, "error removing streams");
  18290. _this.logger.error(error.message);
  18291. if (error.error) {
  18292. _this.logger.error(error.error);
  18293. }
  18294. throw error;
  18295. }).then(function (streams) {
  18296. var streamsArr = [].concat(streams);
  18297. streamsArr.forEach(function (stream) {
  18298. if (_this.peerConnection.addTrack) {
  18299. stream.getTracks().forEach(function (track) {
  18300. _this.peerConnection.addTrack(track, stream);
  18301. });
  18302. }
  18303. else {
  18304. // Chrome 59 does not support addTrack
  18305. _this.peerConnection.addStream(stream);
  18306. }
  18307. });
  18308. return Promise.resolve();
  18309. }).catch(function (e) {
  18310. if (e.type === Enums_1.TypeStrings.SessionDescriptionHandlerError) {
  18311. throw e;
  18312. }
  18313. var error = new Exceptions_1.Exceptions.SessionDescriptionHandlerError("acquire", e, "error adding stream");
  18314. _this.logger.error(error.message);
  18315. if (error.error) {
  18316. _this.logger.error(error.error);
  18317. }
  18318. throw error;
  18319. });
  18320. };
  18321. SessionDescriptionHandler.prototype.hasOffer = function (where) {
  18322. var offerState = "have-" + where + "-offer";
  18323. return this.peerConnection.signalingState === offerState;
  18324. };
  18325. // ICE gathering state handling
  18326. SessionDescriptionHandler.prototype.isIceGatheringComplete = function () {
  18327. return this.peerConnection.iceGatheringState === "complete" || this.iceGatheringTimeout;
  18328. };
  18329. SessionDescriptionHandler.prototype.resetIceGatheringComplete = function () {
  18330. this.iceGatheringTimeout = false;
  18331. this.logger.log("resetIceGatheringComplete");
  18332. if (this.iceGatheringTimer) {
  18333. clearTimeout(this.iceGatheringTimer);
  18334. this.iceGatheringTimer = undefined;
  18335. }
  18336. if (this.iceGatheringDeferred) {
  18337. this.iceGatheringDeferred.reject();
  18338. this.iceGatheringDeferred = undefined;
  18339. }
  18340. };
  18341. SessionDescriptionHandler.prototype.setDirection = function (sdp) {
  18342. var match = sdp.match(/a=(sendrecv|sendonly|recvonly|inactive)/);
  18343. if (match === null) {
  18344. this.direction = this.C.DIRECTION.NULL;
  18345. this.observer.directionChanged();
  18346. return;
  18347. }
  18348. var direction = match[1];
  18349. switch (direction) {
  18350. case this.C.DIRECTION.SENDRECV:
  18351. case this.C.DIRECTION.SENDONLY:
  18352. case this.C.DIRECTION.RECVONLY:
  18353. case this.C.DIRECTION.INACTIVE:
  18354. this.direction = direction;
  18355. break;
  18356. default:
  18357. this.direction = this.C.DIRECTION.NULL;
  18358. break;
  18359. }
  18360. this.observer.directionChanged();
  18361. };
  18362. SessionDescriptionHandler.prototype.triggerIceGatheringComplete = function () {
  18363. if (this.isIceGatheringComplete()) {
  18364. this.emit("iceGatheringComplete", this);
  18365. if (this.iceGatheringTimer) {
  18366. clearTimeout(this.iceGatheringTimer);
  18367. this.iceGatheringTimer = undefined;
  18368. }
  18369. if (this.iceGatheringDeferred) {
  18370. this.iceGatheringDeferred.resolve();
  18371. this.iceGatheringDeferred = undefined;
  18372. }
  18373. }
  18374. };
  18375. SessionDescriptionHandler.prototype.waitForIceGatheringComplete = function () {
  18376. this.logger.log("waitForIceGatheringComplete");
  18377. if (this.isIceGatheringComplete()) {
  18378. this.logger.log("ICE is already complete. Return resolved.");
  18379. return Promise.resolve();
  18380. }
  18381. else if (!this.iceGatheringDeferred) {
  18382. this.iceGatheringDeferred = Utils_1.Utils.defer();
  18383. }
  18384. this.logger.log("ICE is not complete. Returning promise");
  18385. return this.iceGatheringDeferred ? this.iceGatheringDeferred.promise : Promise.resolve();
  18386. };
  18387. return SessionDescriptionHandler;
  18388. }(events_1.EventEmitter));
  18389. exports.SessionDescriptionHandler = SessionDescriptionHandler;
  18390. /***/ }),
  18391. /* 95 */
  18392. /***/ (function(module, exports, __webpack_require__) {
  18393. "use strict";
  18394. Object.defineProperty(exports, "__esModule", { value: true });
  18395. var tslib_1 = __webpack_require__(1);
  18396. var events_1 = __webpack_require__(30);
  18397. var Constants_1 = __webpack_require__(80);
  18398. var core_1 = __webpack_require__(2);
  18399. var allowed_methods_1 = __webpack_require__(58);
  18400. var Enums_1 = __webpack_require__(82);
  18401. var Exceptions_1 = __webpack_require__(84);
  18402. var Utils_1 = __webpack_require__(83);
  18403. var emitter_1 = __webpack_require__(96);
  18404. var info_1 = __webpack_require__(97);
  18405. var notification_1 = __webpack_require__(98);
  18406. var referral_1 = __webpack_require__(99);
  18407. var session_state_1 = __webpack_require__(100);
  18408. /**
  18409. * A session provides real time communication between one or more participants.
  18410. * @public
  18411. */
  18412. var Session = /** @class */ (function (_super) {
  18413. tslib_1.__extends(Session, _super);
  18414. /**
  18415. * Constructor.
  18416. * @param userAgent - User agent. See {@link UserAgent} for details.
  18417. * @internal
  18418. */
  18419. function Session(userAgent, options) {
  18420. if (options === void 0) { options = {}; }
  18421. var _this = _super.call(this) || this;
  18422. // Property overlap with ClientContext & ServerContext Interfaces
  18423. /** @internal */
  18424. _this.type = Enums_1.TypeStrings.Session;
  18425. /** @internal */
  18426. _this.method = Constants_1.C.INVITE;
  18427. /** @internal */
  18428. _this.localHold = false;
  18429. /** DEPRECATED: Session status */
  18430. /** @internal */
  18431. _this.status = Enums_1.SessionStatus.STATUS_NULL;
  18432. /** True if an error caused session termination. */
  18433. /** @internal */
  18434. _this.isFailed = false;
  18435. /** @internal */
  18436. _this.rel100 = Constants_1.C.supported.UNSUPPORTED;
  18437. /** @internal */
  18438. _this.expiresTimer = undefined;
  18439. /** @internal */
  18440. _this.userNoAnswerTimer = undefined;
  18441. _this._state = session_state_1.SessionState.Initial;
  18442. _this._stateEventEmitter = new events_1.EventEmitter();
  18443. _this.pendingReinvite = false;
  18444. _this.tones = undefined;
  18445. _this.userAgent = userAgent;
  18446. _this.delegate = options.delegate;
  18447. _this.logger = userAgent.getLogger("sip.session");
  18448. return _this;
  18449. }
  18450. /**
  18451. * Called to cleanup session after terminated.
  18452. * @internal
  18453. */
  18454. Session.prototype.close = function () {
  18455. this.logger.log("Session[" + this.id + "].close");
  18456. if (this.status === Enums_1.SessionStatus.STATUS_TERMINATED) {
  18457. return;
  18458. }
  18459. // 1st Step. Terminate media.
  18460. if (this._sessionDescriptionHandler) {
  18461. this._sessionDescriptionHandler.close();
  18462. }
  18463. // 2nd Step. Terminate signaling.
  18464. // Clear session timers
  18465. if (this.expiresTimer) {
  18466. clearTimeout(this.expiresTimer);
  18467. }
  18468. if (this.userNoAnswerTimer) {
  18469. clearTimeout(this.userNoAnswerTimer);
  18470. }
  18471. this.status = Enums_1.SessionStatus.STATUS_TERMINATED;
  18472. if (!this.id) {
  18473. throw new Error("Session id undefined.");
  18474. }
  18475. delete this.userAgent.sessions[this.id];
  18476. return;
  18477. };
  18478. /**
  18479. * @deprecated Legacy state transition.
  18480. * @internal
  18481. */
  18482. Session.prototype.on = function (name, callback) {
  18483. return _super.prototype.on.call(this, name, callback);
  18484. };
  18485. /**
  18486. * @deprecated Legacy state transition.
  18487. * @internal
  18488. */
  18489. Session.prototype.emit = function (event) {
  18490. var args = [];
  18491. for (var _i = 1; _i < arguments.length; _i++) {
  18492. args[_i - 1] = arguments[_i];
  18493. }
  18494. return _super.prototype.emit.apply(this, tslib_1.__spreadArrays([event], args));
  18495. };
  18496. Object.defineProperty(Session.prototype, "sessionDescriptionHandler", {
  18497. /**
  18498. * Session description handler.
  18499. */
  18500. get: function () {
  18501. return this._sessionDescriptionHandler;
  18502. },
  18503. enumerable: true,
  18504. configurable: true
  18505. });
  18506. Object.defineProperty(Session.prototype, "sessionDescriptionHandlerFactory", {
  18507. /**
  18508. * Session description handler factory.
  18509. */
  18510. get: function () {
  18511. return this.userAgent.configuration.sessionDescriptionHandlerFactory;
  18512. },
  18513. enumerable: true,
  18514. configurable: true
  18515. });
  18516. Object.defineProperty(Session.prototype, "state", {
  18517. /**
  18518. * Session state.
  18519. */
  18520. get: function () {
  18521. return this._state;
  18522. },
  18523. enumerable: true,
  18524. configurable: true
  18525. });
  18526. Object.defineProperty(Session.prototype, "stateChange", {
  18527. /**
  18528. * Session state change emitter.
  18529. */
  18530. get: function () {
  18531. return emitter_1.makeEmitter(this._stateEventEmitter);
  18532. },
  18533. enumerable: true,
  18534. configurable: true
  18535. });
  18536. /**
  18537. * Renegotiate the session. Sends a re-INVITE.
  18538. * @param options - Options bucket.
  18539. */
  18540. Session.prototype.invite = function (options) {
  18541. var _this = this;
  18542. if (options === void 0) { options = {}; }
  18543. this.logger.log("Session.invite");
  18544. if (this.state !== session_state_1.SessionState.Established) {
  18545. return Promise.reject(new Error("Invalid session state " + this.state));
  18546. }
  18547. if (this.pendingReinvite) {
  18548. return Promise.reject(new Error("Reinvite in progress. Please wait until complete, then try again."));
  18549. }
  18550. if (!this._sessionDescriptionHandler) {
  18551. throw new Error("Session description handler undefined.");
  18552. }
  18553. this.pendingReinvite = true;
  18554. var delegate = {
  18555. onAccept: function (response) {
  18556. // A re-INVITE transaction has an offer/answer [RFC3264] exchange
  18557. // associated with it. The UAC (User Agent Client) generating a given
  18558. // re-INVITE can act as the offerer or as the answerer. A UAC willing
  18559. // to act as the offerer includes an offer in the re-INVITE. The UAS
  18560. // (User Agent Server) then provides an answer in a response to the
  18561. // re-INVITE. A UAC willing to act as answerer does not include an
  18562. // offer in the re-INVITE. The UAS then provides an offer in a response
  18563. // to the re-INVITE becoming, thus, the offerer.
  18564. // https://tools.ietf.org/html/rfc6141#section-1
  18565. var body = core_1.getBody(response.message);
  18566. if (!body) {
  18567. // No way to recover, so terminate session and mark as failed.
  18568. _this.logger.error("Received 2xx response to re-INVITE without a session description");
  18569. _this.ackAndBye(response, 400, "Missing session description");
  18570. _this.stateTransition(session_state_1.SessionState.Terminated);
  18571. _this.isFailed = true;
  18572. _this.pendingReinvite = false;
  18573. return;
  18574. }
  18575. if (options.withoutSdp) {
  18576. // INVITE without SDP - set remote offer and send an answer in the ACK
  18577. // FIXME: SDH options & SDH modifiers options are applied somewhat ambiguously
  18578. // This behavior was ported from legacy code and the issue punted down the road.
  18579. var answerOptions = {
  18580. sessionDescriptionHandlerOptions: options.sessionDescriptionHandlerOptions,
  18581. sessionDescriptionHandlerModifiers: options.sessionDescriptionHandlerModifiers
  18582. };
  18583. _this.setOfferAndGetAnswer(body, answerOptions)
  18584. .then(function (answerBody) {
  18585. response.ack({ body: answerBody });
  18586. })
  18587. .catch(function (error) {
  18588. // No way to recover, so terminate session and mark as failed.
  18589. _this.logger.error("Failed to handle offer in 2xx response to re-INVITE");
  18590. _this.logger.error(error.message);
  18591. if (_this.state === session_state_1.SessionState.Terminated) {
  18592. // A BYE should not be sent if alreadly terminated.
  18593. // For example, a BYE may be sent/received while re-INVITE is outstanding.
  18594. response.ack();
  18595. }
  18596. else {
  18597. _this.ackAndBye(response, 488, "Bad Media Description");
  18598. _this.stateTransition(session_state_1.SessionState.Terminated);
  18599. _this.isFailed = true;
  18600. }
  18601. })
  18602. .then(function () {
  18603. _this.pendingReinvite = false;
  18604. if (options.requestDelegate && options.requestDelegate.onAccept) {
  18605. options.requestDelegate.onAccept(response);
  18606. }
  18607. });
  18608. }
  18609. else {
  18610. // INVITE with SDP - set remote answer and send an ACK
  18611. // FIXME: SDH options & SDH modifiers options are applied somewhat ambiguously
  18612. // This behavior was ported from legacy code and the issue punted down the road.
  18613. var answerOptions = {
  18614. sessionDescriptionHandlerOptions: _this.sessionDescriptionHandlerOptions,
  18615. sessionDescriptionHandlerModifiers: _this.sessionDescriptionHandlerModifiers
  18616. };
  18617. _this.setAnswer(body, answerOptions)
  18618. .then(function () {
  18619. response.ack();
  18620. })
  18621. .catch(function (error) {
  18622. // No way to recover, so terminate session and mark as failed.
  18623. _this.logger.error("Failed to handle answer in 2xx response to re-INVITE");
  18624. _this.logger.error(error.message);
  18625. // A BYE should only be sent if session is not alreadly terminated.
  18626. // For example, a BYE may be sent/received while re-INVITE is outstanding.
  18627. // The ACK needs to be sent regardless as it was not handled by the transaction.
  18628. if (_this.state !== session_state_1.SessionState.Terminated) {
  18629. _this.ackAndBye(response, 488, "Bad Media Description");
  18630. _this.stateTransition(session_state_1.SessionState.Terminated);
  18631. _this.isFailed = true;
  18632. }
  18633. else {
  18634. response.ack();
  18635. }
  18636. })
  18637. .then(function () {
  18638. _this.pendingReinvite = false;
  18639. if (options.requestDelegate && options.requestDelegate.onAccept) {
  18640. options.requestDelegate.onAccept(response);
  18641. }
  18642. });
  18643. }
  18644. },
  18645. onProgress: function (response) {
  18646. return;
  18647. },
  18648. onRedirect: function (response) {
  18649. return;
  18650. },
  18651. onReject: function (response) {
  18652. _this.logger.warn("Received a non-2xx response to re-INVITE");
  18653. _this.pendingReinvite = false;
  18654. if (options.withoutSdp) {
  18655. if (options.requestDelegate && options.requestDelegate.onReject) {
  18656. options.requestDelegate.onReject(response);
  18657. }
  18658. }
  18659. else {
  18660. _this.rollbackOffer()
  18661. .catch(function (error) {
  18662. // No way to recover, so terminate session and mark as failed.
  18663. _this.logger.error("Failed to rollback offer on non-2xx response to re-INVITE");
  18664. _this.logger.error(error.message);
  18665. // A BYE should only be sent if session is not alreadly terminated.
  18666. // For example, a BYE may be sent/received while re-INVITE is outstanding.
  18667. // Note that the ACK was already sent by the transaction, so just need to send BYE.
  18668. if (_this.state !== session_state_1.SessionState.Terminated) {
  18669. if (!_this.dialog) {
  18670. throw new Error("Dialog undefined.");
  18671. }
  18672. var extraHeaders = [];
  18673. extraHeaders.push("Reason: " + Utils_1.Utils.getReasonHeaderValue(500, "Internal Server Error"));
  18674. _this.dialog.bye(undefined, { extraHeaders: extraHeaders });
  18675. _this.stateTransition(session_state_1.SessionState.Terminated);
  18676. _this.isFailed = true;
  18677. }
  18678. })
  18679. .then(function () {
  18680. if (options.requestDelegate && options.requestDelegate.onReject) {
  18681. options.requestDelegate.onReject(response);
  18682. }
  18683. });
  18684. }
  18685. },
  18686. onTrying: function (response) {
  18687. return;
  18688. }
  18689. };
  18690. var requestOptions = options.requestOptions || {};
  18691. requestOptions.extraHeaders = (requestOptions.extraHeaders || []).slice();
  18692. requestOptions.extraHeaders.push("Allow: " + allowed_methods_1.AllowedMethods.toString());
  18693. requestOptions.extraHeaders.push("Contact: " + this.contact);
  18694. // Just send an INVITE with no sdp...
  18695. if (options.withoutSdp) {
  18696. if (!this.dialog) {
  18697. this.pendingReinvite = false;
  18698. return Promise.reject(new Error("Dialog undefined."));
  18699. }
  18700. return Promise.resolve(this.dialog.invite(delegate, requestOptions));
  18701. }
  18702. // Get an offer and send it in an INVITE
  18703. // FIXME: SDH options & SDH modifiers options are applied somewhat ambiguously
  18704. // This behavior was ported from legacy code and the issue punted down the road.
  18705. var offerOptions = {
  18706. sessionDescriptionHandlerOptions: options.sessionDescriptionHandlerOptions,
  18707. sessionDescriptionHandlerModifiers: options.sessionDescriptionHandlerModifiers
  18708. };
  18709. return this.getOffer(offerOptions)
  18710. .then(function (offerBody) {
  18711. if (!_this.dialog) {
  18712. _this.pendingReinvite = false;
  18713. throw new Error("Dialog undefined.");
  18714. }
  18715. requestOptions.body = offerBody;
  18716. return _this.dialog.invite(delegate, requestOptions);
  18717. })
  18718. .catch(function (error) {
  18719. _this.logger.error(error.message);
  18720. _this.logger.error("Failed to send re-INVITE");
  18721. _this.pendingReinvite = false;
  18722. throw error;
  18723. });
  18724. };
  18725. /**
  18726. * Send BYE.
  18727. * @param delegate - Request delegate.
  18728. * @param options - Request options bucket.
  18729. * @internal
  18730. */
  18731. Session.prototype.bye = function (delegate, options) {
  18732. var _this = this;
  18733. // Using core session dialog
  18734. if (!this.dialog) {
  18735. return Promise.reject(new Error("Session dialog undefined."));
  18736. }
  18737. var dialog = this.dialog;
  18738. // The caller's UA MAY send a BYE for either confirmed or early dialogs,
  18739. // and the callee's UA MAY send a BYE on confirmed dialogs, but MUST NOT
  18740. // send a BYE on early dialogs. However, the callee's UA MUST NOT send a
  18741. // BYE on a confirmed dialog until it has received an ACK for its 2xx
  18742. // response or until the server transaction times out.
  18743. // https://tools.ietf.org/html/rfc3261#section-15
  18744. switch (dialog.sessionState) {
  18745. case core_1.SessionState.Initial:
  18746. throw new Error("Invalid dialog state " + dialog.sessionState);
  18747. case core_1.SessionState.Early: // Implementation choice - not sending BYE for early dialogs.
  18748. throw new Error("Invalid dialog state " + dialog.sessionState);
  18749. case core_1.SessionState.AckWait: { // This state only occurs if we are the callee.
  18750. this.stateTransition(session_state_1.SessionState.Terminating); // We're terminating
  18751. return new Promise(function (resolve, reject) {
  18752. dialog.delegate = {
  18753. // When ACK shows up, say BYE.
  18754. onAck: function () {
  18755. var request = dialog.bye(delegate, options);
  18756. _this.stateTransition(session_state_1.SessionState.Terminated);
  18757. resolve(request);
  18758. },
  18759. // Or the server transaction times out before the ACK arrives.
  18760. onAckTimeout: function () {
  18761. var request = dialog.bye(delegate, options);
  18762. _this.stateTransition(session_state_1.SessionState.Terminated);
  18763. resolve(request);
  18764. }
  18765. };
  18766. });
  18767. }
  18768. case core_1.SessionState.Confirmed: {
  18769. var request = dialog.bye(delegate, options);
  18770. this.stateTransition(session_state_1.SessionState.Terminated);
  18771. return Promise.resolve(request);
  18772. }
  18773. case core_1.SessionState.Terminated:
  18774. throw new Error("Invalid dialog state " + dialog.sessionState);
  18775. default:
  18776. throw new Error("Unrecognized state.");
  18777. }
  18778. };
  18779. /**
  18780. * Send INFO.
  18781. * @param delegate - Request delegate.
  18782. * @param options - Request options bucket.
  18783. * @internal
  18784. */
  18785. Session.prototype.info = function (delegate, options) {
  18786. // Using core session dialog
  18787. if (!this.dialog) {
  18788. return Promise.reject(new Error("Session dialog undefined."));
  18789. }
  18790. return Promise.resolve(this.dialog.info(delegate, options));
  18791. };
  18792. /**
  18793. * Send REFER.
  18794. * @param referrer - Referrer.
  18795. * @param delegate - Request delegate.
  18796. * @param options - Request options bucket.
  18797. * @internal
  18798. */
  18799. Session.prototype.refer = function (referrer, delegate, options) {
  18800. // Using core session dialog
  18801. if (!this.dialog) {
  18802. return Promise.reject(new Error("Session dialog undefined."));
  18803. }
  18804. // If the session has a referrer, it will receive any in-dialog NOTIFY requests.
  18805. this.referrer = referrer;
  18806. return Promise.resolve(this.dialog.refer(delegate, options));
  18807. };
  18808. /**
  18809. * Send ACK and then BYE. There are unrecoverable errors which can occur
  18810. * while handling dialog forming and in-dialog INVITE responses and when
  18811. * they occur we ACK the response and send a BYE.
  18812. * Note that the BYE is sent in the dialog associated with the response
  18813. * which is not necessarily `this.dialog`. And, accordingly, the
  18814. * session state is not transitioned to terminated and session is not closed.
  18815. * @param inviteResponse - The response causing the error.
  18816. * @param statusCode - Status code for he reason phrase.
  18817. * @param reasonPhrase - Reason phrase for the BYE.
  18818. * @internal
  18819. */
  18820. Session.prototype.ackAndBye = function (response, statusCode, reasonPhrase) {
  18821. response.ack();
  18822. var extraHeaders = [];
  18823. if (statusCode) {
  18824. extraHeaders.push("Reason: " + Utils_1.Utils.getReasonHeaderValue(statusCode, reasonPhrase));
  18825. }
  18826. // Using the dialog session associate with the response (which might not be this.dialog)
  18827. response.session.bye(undefined, { extraHeaders: extraHeaders });
  18828. };
  18829. /**
  18830. * Handle in dialog ACK request.
  18831. * @internal
  18832. */
  18833. Session.prototype.onAckRequest = function (request) {
  18834. var _this = this;
  18835. this.logger.log("Session.onAckRequest");
  18836. if (this.state !== session_state_1.SessionState.Initial &&
  18837. this.state !== session_state_1.SessionState.Establishing &&
  18838. this.state !== session_state_1.SessionState.Established &&
  18839. this.state !== session_state_1.SessionState.Terminating) {
  18840. this.logger.error("ACK received while in state " + this.state + ", dropping request");
  18841. return;
  18842. }
  18843. // FIXME: Review is this ever true? We're "Established" when dialog created in accept().
  18844. if (this.state === session_state_1.SessionState.Initial || this.state === session_state_1.SessionState.Establishing) {
  18845. this.stateTransition(session_state_1.SessionState.Established);
  18846. }
  18847. var dialog = this.dialog;
  18848. if (!dialog) {
  18849. throw new Error("Dialog undefined.");
  18850. }
  18851. switch (dialog.signalingState) {
  18852. case core_1.SignalingState.Initial: {
  18853. // State should never be reached as first reliable response must have answer/offer.
  18854. // So we must have never has sent an offer.
  18855. this.logger.error("Invalid signaling state " + dialog.signalingState + ".");
  18856. this.isFailed = true;
  18857. var extraHeaders = ["Reason: " + Utils_1.Utils.getReasonHeaderValue(488, "Bad Media Description")];
  18858. dialog.bye(undefined, { extraHeaders: extraHeaders });
  18859. this.stateTransition(session_state_1.SessionState.Terminated);
  18860. return;
  18861. }
  18862. case core_1.SignalingState.Stable: {
  18863. // State we should be in.
  18864. // Either the ACK has the answer that got us here, or we were in this state prior to the ACK.
  18865. var body = core_1.getBody(request.message);
  18866. // If the ACK doesn't have an answer, nothing to be done.
  18867. if (!body) {
  18868. this.status = Enums_1.SessionStatus.STATUS_CONFIRMED;
  18869. return;
  18870. }
  18871. if (body.contentDisposition === "render") {
  18872. this.renderbody = body.content;
  18873. this.rendertype = body.contentType;
  18874. this.status = Enums_1.SessionStatus.STATUS_CONFIRMED;
  18875. return;
  18876. }
  18877. if (body.contentDisposition !== "session") {
  18878. this.status = Enums_1.SessionStatus.STATUS_CONFIRMED;
  18879. return;
  18880. }
  18881. // Receved answer in ACK.
  18882. var options = {
  18883. sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptions,
  18884. sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiers
  18885. };
  18886. this.setAnswer(body, options)
  18887. .then(function () { _this.status = Enums_1.SessionStatus.STATUS_CONFIRMED; })
  18888. .catch(function (error) {
  18889. _this.logger.error(error.message);
  18890. _this.isFailed = true;
  18891. var extraHeaders = ["Reason: " + Utils_1.Utils.getReasonHeaderValue(488, "Bad Media Description")];
  18892. dialog.bye(undefined, { extraHeaders: extraHeaders });
  18893. _this.stateTransition(session_state_1.SessionState.Terminated);
  18894. });
  18895. return;
  18896. }
  18897. case core_1.SignalingState.HaveLocalOffer: {
  18898. // State should never be reached as local offer would be answered by this ACK.
  18899. // So we must have received an ACK without an answer.
  18900. this.logger.error("Invalid signaling state " + dialog.signalingState + ".");
  18901. this.isFailed = true;
  18902. var extraHeaders = ["Reason: " + Utils_1.Utils.getReasonHeaderValue(488, "Bad Media Description")];
  18903. dialog.bye(undefined, { extraHeaders: extraHeaders });
  18904. this.stateTransition(session_state_1.SessionState.Terminated);
  18905. return;
  18906. }
  18907. case core_1.SignalingState.HaveRemoteOffer: {
  18908. // State should never be reached as remote offer would be answered in first reliable response.
  18909. // So we must have never has sent an answer.
  18910. this.logger.error("Invalid signaling state " + dialog.signalingState + ".");
  18911. this.isFailed = true;
  18912. var extraHeaders = ["Reason: " + Utils_1.Utils.getReasonHeaderValue(488, "Bad Media Description")];
  18913. dialog.bye(undefined, { extraHeaders: extraHeaders });
  18914. this.stateTransition(session_state_1.SessionState.Terminated);
  18915. return;
  18916. }
  18917. case core_1.SignalingState.Closed:
  18918. throw new Error("Invalid signaling state " + dialog.signalingState + ".");
  18919. default:
  18920. throw new Error("Invalid signaling state " + dialog.signalingState + ".");
  18921. }
  18922. };
  18923. /**
  18924. * Handle in dialog BYE request.
  18925. * @internal
  18926. */
  18927. Session.prototype.onByeRequest = function (request) {
  18928. this.logger.log("Session.onByeRequest");
  18929. if (this.state !== session_state_1.SessionState.Established) {
  18930. this.logger.error("BYE received while in state " + this.state + ", dropping request");
  18931. return;
  18932. }
  18933. request.accept();
  18934. this.stateTransition(session_state_1.SessionState.Terminated);
  18935. };
  18936. /**
  18937. * Handle in dialog INFO request.
  18938. * @internal
  18939. */
  18940. Session.prototype.onInfoRequest = function (request) {
  18941. this.logger.log("Session.onInfoRequest");
  18942. if (this.state !== session_state_1.SessionState.Established) {
  18943. this.logger.error("INFO received while in state " + this.state + ", dropping request");
  18944. return;
  18945. }
  18946. if (this.delegate && this.delegate.onInfo) {
  18947. var info = new info_1.Info(request);
  18948. this.delegate.onInfo(info);
  18949. }
  18950. else {
  18951. request.accept();
  18952. }
  18953. };
  18954. /**
  18955. * Handle in dialog INVITE request.
  18956. * @internal
  18957. */
  18958. Session.prototype.onInviteRequest = function (request) {
  18959. var _this = this;
  18960. this.logger.log("Session.onInviteRequest");
  18961. if (this.state !== session_state_1.SessionState.Established) {
  18962. this.logger.error("INVITE received while in state " + this.state + ", dropping request");
  18963. return;
  18964. }
  18965. // TODO: would be nice to have core track and set the Contact header,
  18966. // but currently the session which is setting it is holding onto it.
  18967. var extraHeaders = ["Contact: " + this.contact];
  18968. // Handle P-Asserted-Identity
  18969. if (request.message.hasHeader("P-Asserted-Identity")) {
  18970. var header = request.message.getHeader("P-Asserted-Identity");
  18971. if (!header) {
  18972. throw new Error("Header undefined.");
  18973. }
  18974. this.assertedIdentity = core_1.Grammar.nameAddrHeaderParse(header);
  18975. }
  18976. // FIXME: SDH options & SDH modifiers options are applied somewhat ambiguously
  18977. // This behavior was ported from legacy code and the issue punted down the road.
  18978. var options = {
  18979. sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptions,
  18980. sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiers
  18981. };
  18982. this.generateResponseOfferAnswerInDialog(options)
  18983. .then(function (body) {
  18984. var outgoingResponse = request.accept({ statusCode: 200, extraHeaders: extraHeaders, body: body });
  18985. if (_this.delegate && _this.delegate.onInvite) {
  18986. _this.delegate.onInvite(request.message, outgoingResponse.message, 200);
  18987. }
  18988. })
  18989. .catch(function (error) {
  18990. _this.logger.error(error.message);
  18991. _this.logger.error("Failed to handle to re-INVITE request");
  18992. if (!_this.dialog) {
  18993. throw new Error("Dialog undefined.");
  18994. }
  18995. _this.logger.error(_this.dialog.signalingState);
  18996. // If we don't have a local/remote offer...
  18997. if (_this.dialog.signalingState === core_1.SignalingState.Stable) {
  18998. var outgoingResponse = request.reject({ statusCode: 488 }); // Not Acceptable Here
  18999. if (_this.delegate && _this.delegate.onInvite) {
  19000. _this.delegate.onInvite(request.message, outgoingResponse.message, 488);
  19001. }
  19002. return;
  19003. }
  19004. // Otherwise rollback
  19005. _this.rollbackOffer()
  19006. .then(function () {
  19007. var outgoingResponse = request.reject({ statusCode: 488 }); // Not Acceptable Here
  19008. if (_this.delegate && _this.delegate.onInvite) {
  19009. _this.delegate.onInvite(request.message, outgoingResponse.message, 488);
  19010. }
  19011. })
  19012. .catch(function (errorRollback) {
  19013. // No way to recover, so terminate session and mark as failed.
  19014. _this.logger.error(errorRollback.message);
  19015. _this.logger.error("Failed to rollback offer on re-INVITE request");
  19016. var outgoingResponse = request.reject({ statusCode: 488 }); // Not Acceptable Here
  19017. // A BYE should only be sent if session is not alreadly terminated.
  19018. // For example, a BYE may be sent/received while re-INVITE is outstanding.
  19019. // Note that the ACK was already sent by the transaction, so just need to send BYE.
  19020. if (_this.state !== session_state_1.SessionState.Terminated) {
  19021. if (!_this.dialog) {
  19022. throw new Error("Dialog undefined.");
  19023. }
  19024. var extraHeadersBye = [];
  19025. extraHeadersBye.push("Reason: " + Utils_1.Utils.getReasonHeaderValue(500, "Internal Server Error"));
  19026. _this.dialog.bye(undefined, { extraHeaders: extraHeaders });
  19027. _this.stateTransition(session_state_1.SessionState.Terminated);
  19028. _this.isFailed = true;
  19029. }
  19030. if (_this.delegate && _this.delegate.onInvite) {
  19031. _this.delegate.onInvite(request.message, outgoingResponse.message, 488);
  19032. }
  19033. });
  19034. });
  19035. };
  19036. /**
  19037. * Handle in dialog NOTIFY request.
  19038. * @internal
  19039. */
  19040. Session.prototype.onNotifyRequest = function (request) {
  19041. this.logger.log("Session.onNotifyRequest");
  19042. if (this.state !== session_state_1.SessionState.Established) {
  19043. this.logger.error("NOTIFY received while in state " + this.state + ", dropping request");
  19044. return;
  19045. }
  19046. // If this a NOTIFY associated with the progress of a REFER,
  19047. // look to delegate handling to the associated Referrer.
  19048. if (this.referrer && this.referrer.delegate && this.referrer.delegate.onNotify) {
  19049. var notification = new notification_1.Notification(request);
  19050. this.referrer.delegate.onNotify(notification);
  19051. return;
  19052. }
  19053. // Otherwise accept the NOTIFY.
  19054. if (this.delegate && this.delegate.onNotify) {
  19055. var notification = new notification_1.Notification(request);
  19056. this.delegate.onNotify(notification);
  19057. }
  19058. else {
  19059. request.accept();
  19060. }
  19061. };
  19062. /**
  19063. * Handle in dialog PRACK request.
  19064. * @internal
  19065. */
  19066. Session.prototype.onPrackRequest = function (request) {
  19067. this.logger.log("Session.onPrackRequest");
  19068. if (this.state !== session_state_1.SessionState.Established) {
  19069. this.logger.error("PRACK received while in state " + this.state + ", dropping request");
  19070. return;
  19071. }
  19072. throw new Error("Unimplemented.");
  19073. };
  19074. /**
  19075. * Handle in dialog REFER request.
  19076. * @internal
  19077. */
  19078. Session.prototype.onReferRequest = function (request) {
  19079. var _this = this;
  19080. this.logger.log("Session.onReferRequest");
  19081. if (this.state !== session_state_1.SessionState.Established) {
  19082. this.logger.error("REFER received while in state " + this.state + ", dropping request");
  19083. return;
  19084. }
  19085. if (this.status === Enums_1.SessionStatus.STATUS_CONFIRMED) {
  19086. // RFC 3515 2.4.1
  19087. if (!request.message.hasHeader("refer-to")) {
  19088. this.logger.warn("Invalid REFER packet. A refer-to header is required. Rejecting.");
  19089. request.reject();
  19090. return;
  19091. }
  19092. var referral_2 = new referral_1.Referral(request, this);
  19093. if (this.delegate && this.delegate.onRefer) {
  19094. this.delegate.onRefer(referral_2);
  19095. }
  19096. else {
  19097. this.logger.log("No delegate available to handle REFER, automatically accepting and following.");
  19098. referral_2
  19099. .accept()
  19100. .then(function () { return referral_2
  19101. .makeInviter(_this.passedOptions)
  19102. .invite(); })
  19103. .catch(function (error) {
  19104. // FIXME: logging and eating error...
  19105. _this.logger.error(error.message);
  19106. });
  19107. }
  19108. }
  19109. };
  19110. /**
  19111. * Generate an offer or answer for a response to an INVITE request.
  19112. * If a remote offer was provided in the request, set the remote
  19113. * description and get a local answer. If a remote offer was not
  19114. * provided, generates a local offer.
  19115. * @internal
  19116. */
  19117. Session.prototype.generateResponseOfferAnswer = function (request, options) {
  19118. if (this.dialog) {
  19119. return this.generateResponseOfferAnswerInDialog(options);
  19120. }
  19121. var body = core_1.getBody(request.message);
  19122. if (!body || body.contentDisposition !== "session") {
  19123. return this.getOffer(options);
  19124. }
  19125. else {
  19126. return this.setOfferAndGetAnswer(body, options);
  19127. }
  19128. };
  19129. /**
  19130. * Generate an offer or answer for a response to an INVITE request
  19131. * when a dialog (early or otherwise) has already been established.
  19132. * This method may NOT be called if a dialog has yet to be established.
  19133. * @internal
  19134. */
  19135. Session.prototype.generateResponseOfferAnswerInDialog = function (options) {
  19136. if (!this.dialog) {
  19137. throw new Error("Dialog undefined.");
  19138. }
  19139. switch (this.dialog.signalingState) {
  19140. case core_1.SignalingState.Initial:
  19141. return this.getOffer(options);
  19142. case core_1.SignalingState.HaveLocalOffer:
  19143. // o Once the UAS has sent or received an answer to the initial
  19144. // offer, it MUST NOT generate subsequent offers in any responses
  19145. // to the initial INVITE. This means that a UAS based on this
  19146. // specification alone can never generate subsequent offers until
  19147. // completion of the initial transaction.
  19148. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  19149. return Promise.resolve(undefined);
  19150. case core_1.SignalingState.HaveRemoteOffer:
  19151. if (!this.dialog.offer) {
  19152. throw new Error("Session offer undefined in signaling state " + this.dialog.signalingState + ".");
  19153. }
  19154. return this.setOfferAndGetAnswer(this.dialog.offer, options);
  19155. case core_1.SignalingState.Stable:
  19156. // o Once the UAS has sent or received an answer to the initial
  19157. // offer, it MUST NOT generate subsequent offers in any responses
  19158. // to the initial INVITE. This means that a UAS based on this
  19159. // specification alone can never generate subsequent offers until
  19160. // completion of the initial transaction.
  19161. // https://tools.ietf.org/html/rfc3261#section-13.2.1
  19162. if (this.state !== session_state_1.SessionState.Established) {
  19163. return Promise.resolve(undefined);
  19164. }
  19165. // In dialog INVITE without offer, get an offer for the response.
  19166. return this.getOffer(options);
  19167. case core_1.SignalingState.Closed:
  19168. throw new Error("Invalid signaling state " + this.dialog.signalingState + ".");
  19169. default:
  19170. throw new Error("Invalid signaling state " + this.dialog.signalingState + ".");
  19171. }
  19172. };
  19173. /**
  19174. * Get local offer.
  19175. * @internal
  19176. */
  19177. Session.prototype.getOffer = function (options) {
  19178. var _this = this;
  19179. var sdh = this.setupSessionDescriptionHandler();
  19180. var sdhOptions = options.sessionDescriptionHandlerOptions;
  19181. var sdhModifiers = options.sessionDescriptionHandlerModifiers;
  19182. // This is intentionally written very defensively. Don't trust SDH to behave.
  19183. try {
  19184. return sdh.getDescription(sdhOptions, sdhModifiers)
  19185. .then(function (bodyAndContentType) { return Utils_1.Utils.fromBodyObj(bodyAndContentType); })
  19186. .catch(function (error) {
  19187. _this.logger.error("Session.getOffer: SDH getDescription rejected...");
  19188. var e = error instanceof Error ? error : new Error(error);
  19189. _this.logger.error(e.message);
  19190. throw e;
  19191. });
  19192. }
  19193. catch (error) { // don't trust SDH to throw an Error
  19194. this.logger.error("Session.getOffer: SDH getDescription threw...");
  19195. var e = error instanceof Error ? error : new Error(error);
  19196. this.logger.error(e.message);
  19197. return Promise.reject(e);
  19198. }
  19199. };
  19200. /**
  19201. * Rollback local/remote offer.
  19202. * @internal
  19203. */
  19204. Session.prototype.rollbackOffer = function () {
  19205. var _this = this;
  19206. var sdh = this.setupSessionDescriptionHandler();
  19207. if (!sdh.rollbackDescription) {
  19208. return Promise.resolve();
  19209. }
  19210. // This is intentionally written very defensively. Don't trust SDH to behave.
  19211. try {
  19212. return sdh.rollbackDescription()
  19213. .catch(function (error) {
  19214. _this.logger.error("Session.rollbackOffer: SDH rollbackDescription rejected...");
  19215. var e = error instanceof Error ? error : new Error(error);
  19216. _this.logger.error(e.message);
  19217. throw e;
  19218. });
  19219. }
  19220. catch (error) { // don't trust SDH to throw an Error
  19221. this.logger.error("Session.rollbackOffer: SDH rollbackDescription threw...");
  19222. var e = error instanceof Error ? error : new Error(error);
  19223. this.logger.error(e.message);
  19224. return Promise.reject(e);
  19225. }
  19226. };
  19227. /**
  19228. * Set remote answer.
  19229. * @internal
  19230. */
  19231. Session.prototype.setAnswer = function (answer, options) {
  19232. var _this = this;
  19233. var sdh = this.setupSessionDescriptionHandler();
  19234. var sdhOptions = options.sessionDescriptionHandlerOptions;
  19235. var sdhModifiers = options.sessionDescriptionHandlerModifiers;
  19236. // This is intentionally written very defensively. Don't trust SDH to behave.
  19237. try {
  19238. if (!sdh.hasDescription(answer.contentType)) {
  19239. return Promise.reject(new Exceptions_1.Exceptions.UnsupportedSessionDescriptionContentTypeError());
  19240. }
  19241. }
  19242. catch (error) {
  19243. this.logger.error("Session.setAnswer: SDH hasDescription threw...");
  19244. var e = error instanceof Error ? error : new Error(error);
  19245. this.logger.error(e.message);
  19246. return Promise.reject(e);
  19247. }
  19248. try {
  19249. return sdh.setDescription(answer.content, sdhOptions, sdhModifiers)
  19250. .catch(function (error) {
  19251. _this.logger.error("Session.setAnswer: SDH setDescription rejected...");
  19252. var e = error instanceof Error ? error : new Error(error);
  19253. _this.logger.error(e.message);
  19254. throw e;
  19255. });
  19256. }
  19257. catch (error) { // don't trust SDH to throw an Error
  19258. this.logger.error("Session.setAnswer: SDH setDescription threw...");
  19259. var e = error instanceof Error ? error : new Error(error);
  19260. this.logger.error(e.message);
  19261. return Promise.reject(e);
  19262. }
  19263. };
  19264. /**
  19265. * Set remote offer and get local answer.
  19266. * @internal
  19267. */
  19268. Session.prototype.setOfferAndGetAnswer = function (offer, options) {
  19269. var _this = this;
  19270. var sdh = this.setupSessionDescriptionHandler();
  19271. var sdhOptions = options.sessionDescriptionHandlerOptions;
  19272. var sdhModifiers = options.sessionDescriptionHandlerModifiers;
  19273. // This is intentionally written very defensively. Don't trust SDH to behave.
  19274. try {
  19275. if (!sdh.hasDescription(offer.contentType)) {
  19276. return Promise.reject(new Exceptions_1.Exceptions.UnsupportedSessionDescriptionContentTypeError());
  19277. }
  19278. }
  19279. catch (error) {
  19280. this.logger.error("Session.setOfferAndGetAnswer: SDH hasDescription threw...");
  19281. var e = error instanceof Error ? error : new Error(error);
  19282. this.logger.error(e.message);
  19283. return Promise.reject(e);
  19284. }
  19285. try {
  19286. return sdh.setDescription(offer.content, sdhOptions, sdhModifiers)
  19287. .then(function () { return sdh.getDescription(sdhOptions, sdhModifiers); })
  19288. .then(function (bodyAndContentType) { return Utils_1.Utils.fromBodyObj(bodyAndContentType); })
  19289. .catch(function (error) {
  19290. _this.logger.error("Session.setOfferAndGetAnswer: SDH setDescription or getDescription rejected...");
  19291. var e = error instanceof Error ? error : new Error(error);
  19292. _this.logger.error(e.message);
  19293. throw e;
  19294. });
  19295. }
  19296. catch (error) { // don't trust SDH to throw an Error
  19297. this.logger.error("Session.setOfferAndGetAnswer: SDH setDescription or getDescription threw...");
  19298. var e = error instanceof Error ? error : new Error(error);
  19299. this.logger.error(e.message);
  19300. return Promise.reject(e);
  19301. }
  19302. };
  19303. /**
  19304. * SDH for confirmed dialog.
  19305. * @internal
  19306. */
  19307. Session.prototype.setSessionDescriptionHandler = function (sdh) {
  19308. if (this._sessionDescriptionHandler) {
  19309. throw new Error("Sessionn description handler defined.");
  19310. }
  19311. this._sessionDescriptionHandler = sdh;
  19312. };
  19313. /**
  19314. * SDH for confirmed dialog.
  19315. * @internal
  19316. */
  19317. Session.prototype.setupSessionDescriptionHandler = function () {
  19318. if (this._sessionDescriptionHandler) {
  19319. return this._sessionDescriptionHandler;
  19320. }
  19321. this._sessionDescriptionHandler =
  19322. this.sessionDescriptionHandlerFactory(this, this.userAgent.configuration.sessionDescriptionHandlerFactoryOptions);
  19323. this.emit("SessionDescriptionHandler-created", this._sessionDescriptionHandler);
  19324. return this._sessionDescriptionHandler;
  19325. };
  19326. /**
  19327. * Transition session state.
  19328. * @internal
  19329. */
  19330. Session.prototype.stateTransition = function (newState) {
  19331. var _this = this;
  19332. var invalidTransition = function () {
  19333. throw new Error("Invalid state transition from " + _this._state + " to " + newState);
  19334. };
  19335. // Validate transition
  19336. switch (this._state) {
  19337. case session_state_1.SessionState.Initial:
  19338. if (newState !== session_state_1.SessionState.Establishing &&
  19339. newState !== session_state_1.SessionState.Established &&
  19340. newState !== session_state_1.SessionState.Terminating &&
  19341. newState !== session_state_1.SessionState.Terminated) {
  19342. invalidTransition();
  19343. }
  19344. break;
  19345. case session_state_1.SessionState.Establishing:
  19346. if (newState !== session_state_1.SessionState.Established &&
  19347. newState !== session_state_1.SessionState.Terminating &&
  19348. newState !== session_state_1.SessionState.Terminated) {
  19349. invalidTransition();
  19350. }
  19351. break;
  19352. case session_state_1.SessionState.Established:
  19353. if (newState !== session_state_1.SessionState.Terminating &&
  19354. newState !== session_state_1.SessionState.Terminated) {
  19355. invalidTransition();
  19356. }
  19357. break;
  19358. case session_state_1.SessionState.Terminating:
  19359. if (newState !== session_state_1.SessionState.Terminated) {
  19360. invalidTransition();
  19361. }
  19362. break;
  19363. case session_state_1.SessionState.Terminated:
  19364. invalidTransition();
  19365. break;
  19366. default:
  19367. throw new Error("Unrecognized state.");
  19368. }
  19369. if (newState === session_state_1.SessionState.Established) {
  19370. this.startTime = new Date(); // Deprecated legacy ported behavior
  19371. }
  19372. if (newState === session_state_1.SessionState.Terminated) {
  19373. this.endTime = new Date(); // Deprecated legacy ported behavior
  19374. this.close();
  19375. }
  19376. // Transition
  19377. this._state = newState;
  19378. this.logger.log("Session " + this.id + " transitioned to state " + this._state);
  19379. this._stateEventEmitter.emit("event", this._state);
  19380. };
  19381. // DEPRECATED
  19382. /** @internal */
  19383. Session.C = Enums_1.SessionStatus;
  19384. return Session;
  19385. }(events_1.EventEmitter));
  19386. exports.Session = Session;
  19387. /***/ }),
  19388. /* 96 */
  19389. /***/ (function(module, exports, __webpack_require__) {
  19390. "use strict";
  19391. Object.defineProperty(exports, "__esModule", { value: true });
  19392. /**
  19393. * Creates an {@link Emitter}.
  19394. * @param eventEmitter - An event emitter.
  19395. * @param eventName - Event name.
  19396. * @internal
  19397. */
  19398. function makeEmitter(eventEmitter, eventName) {
  19399. if (eventName === void 0) { eventName = "event"; }
  19400. return {
  19401. on: function (listener) {
  19402. eventEmitter.on(eventName, listener);
  19403. },
  19404. off: function (listener) {
  19405. eventEmitter.removeListener(eventName, listener);
  19406. },
  19407. once: function (listener) {
  19408. eventEmitter.once(eventName, listener);
  19409. }
  19410. };
  19411. }
  19412. exports.makeEmitter = makeEmitter;
  19413. /***/ }),
  19414. /* 97 */
  19415. /***/ (function(module, exports, __webpack_require__) {
  19416. "use strict";
  19417. Object.defineProperty(exports, "__esModule", { value: true });
  19418. /**
  19419. * An exchange of information (incoming INFO).
  19420. * @public
  19421. */
  19422. var Info = /** @class */ (function () {
  19423. /** @internal */
  19424. function Info(incomingInfoRequest) {
  19425. this.incomingInfoRequest = incomingInfoRequest;
  19426. }
  19427. Object.defineProperty(Info.prototype, "request", {
  19428. /** Incoming MESSAGE request message. */
  19429. get: function () {
  19430. return this.incomingInfoRequest.message;
  19431. },
  19432. enumerable: true,
  19433. configurable: true
  19434. });
  19435. /** Accept the request. */
  19436. Info.prototype.accept = function (options) {
  19437. this.incomingInfoRequest.accept(options);
  19438. return Promise.resolve();
  19439. };
  19440. /** Reject the request. */
  19441. Info.prototype.reject = function (options) {
  19442. this.incomingInfoRequest.reject(options);
  19443. return Promise.resolve();
  19444. };
  19445. return Info;
  19446. }());
  19447. exports.Info = Info;
  19448. /***/ }),
  19449. /* 98 */
  19450. /***/ (function(module, exports, __webpack_require__) {
  19451. "use strict";
  19452. Object.defineProperty(exports, "__esModule", { value: true });
  19453. /**
  19454. * A notification of an event (incoming NOTIFY).
  19455. * @public
  19456. */
  19457. var Notification = /** @class */ (function () {
  19458. /** @internal */
  19459. function Notification(incomingNotifyRequest) {
  19460. this.incomingNotifyRequest = incomingNotifyRequest;
  19461. }
  19462. Object.defineProperty(Notification.prototype, "request", {
  19463. /** Incoming NOTIFY request message. */
  19464. get: function () {
  19465. return this.incomingNotifyRequest.message;
  19466. },
  19467. enumerable: true,
  19468. configurable: true
  19469. });
  19470. /** Accept the request. */
  19471. Notification.prototype.accept = function (options) {
  19472. this.incomingNotifyRequest.accept(options);
  19473. return Promise.resolve();
  19474. };
  19475. /** Reject the request. */
  19476. Notification.prototype.reject = function (options) {
  19477. this.incomingNotifyRequest.reject(options);
  19478. return Promise.resolve();
  19479. };
  19480. return Notification;
  19481. }());
  19482. exports.Notification = Notification;
  19483. /***/ }),
  19484. /* 99 */
  19485. /***/ (function(module, exports, __webpack_require__) {
  19486. "use strict";
  19487. Object.defineProperty(exports, "__esModule", { value: true });
  19488. var core_1 = __webpack_require__(2);
  19489. /**
  19490. * A request to establish a {@link Session} elsewhere (incoming REFER).
  19491. * @public
  19492. */
  19493. var Referral = /** @class */ (function () {
  19494. /** @internal */
  19495. function Referral(incomingReferRequest, session) {
  19496. this.incomingReferRequest = incomingReferRequest;
  19497. this.session = session;
  19498. }
  19499. Object.defineProperty(Referral.prototype, "referTo", {
  19500. get: function () {
  19501. var referTo = this.incomingReferRequest.message.parseHeader("refer-to");
  19502. if (!(referTo instanceof core_1.NameAddrHeader)) {
  19503. throw new Error("Failed to parse Refer-To header.");
  19504. }
  19505. return referTo;
  19506. },
  19507. enumerable: true,
  19508. configurable: true
  19509. });
  19510. Object.defineProperty(Referral.prototype, "referredBy", {
  19511. get: function () {
  19512. return this.incomingReferRequest.message.getHeader("referred-by");
  19513. },
  19514. enumerable: true,
  19515. configurable: true
  19516. });
  19517. Object.defineProperty(Referral.prototype, "replaces", {
  19518. get: function () {
  19519. return this.referTo.uri.getHeader("replaces");
  19520. },
  19521. enumerable: true,
  19522. configurable: true
  19523. });
  19524. Object.defineProperty(Referral.prototype, "request", {
  19525. /** Incoming REFER request message. */
  19526. get: function () {
  19527. return this.incomingReferRequest.message;
  19528. },
  19529. enumerable: true,
  19530. configurable: true
  19531. });
  19532. /** Accept the request. */
  19533. Referral.prototype.accept = function (options) {
  19534. if (options === void 0) { options = { statusCode: 202 }; }
  19535. this.incomingReferRequest.accept(options);
  19536. return Promise.resolve();
  19537. };
  19538. /** Reject the request. */
  19539. Referral.prototype.reject = function (options) {
  19540. this.incomingReferRequest.reject(options);
  19541. return Promise.resolve();
  19542. };
  19543. /**
  19544. * Creates an inviter which may be used to send an out of dialog INVITE request.
  19545. *
  19546. * @remarks
  19547. * This a helper method to create an Inviter which will execute the referral
  19548. * of the `Session` which was referred. The appropriate headers are set and
  19549. * the referred `Session` is linked to the new `Session`. Note that only a
  19550. * single instance of the `Inviter` will be created and returned (if called
  19551. * more than once a reference to the same `Inviter` will be returned every time).
  19552. *
  19553. * @param options - Options bucket.
  19554. * @param modifiers - Session description handler modifiers.
  19555. */
  19556. Referral.prototype.makeInviter = function (options) {
  19557. if (this.inviter) {
  19558. return this.inviter;
  19559. }
  19560. var targetURI = this.referTo.uri.clone();
  19561. targetURI.clearHeaders();
  19562. options = options || {};
  19563. var extraHeaders = (options.extraHeaders || []).slice();
  19564. var replaces = this.replaces;
  19565. if (replaces) {
  19566. // decodeURIComponent is a holdover from 2c086eb4. Not sure that it is actually necessary
  19567. extraHeaders.push("Replaces: " + decodeURIComponent(replaces));
  19568. }
  19569. var referredBy = this.referredBy;
  19570. if (referredBy) {
  19571. extraHeaders.push("Referred-By: " + referredBy);
  19572. }
  19573. options.extraHeaders = extraHeaders;
  19574. this.inviter = this.session.userAgent.makeInviter(targetURI, options);
  19575. this.inviter.referred = this.session;
  19576. this.session.referral = this.inviter;
  19577. return this.inviter;
  19578. };
  19579. return Referral;
  19580. }());
  19581. exports.Referral = Referral;
  19582. /***/ }),
  19583. /* 100 */
  19584. /***/ (function(module, exports, __webpack_require__) {
  19585. "use strict";
  19586. Object.defineProperty(exports, "__esModule", { value: true });
  19587. /**
  19588. * {@link Session} state.
  19589. * @remarks
  19590. * Valid state transitions:
  19591. * ```
  19592. * 1. "initial" --> "establishing" (before INVITE sent on outgoing, before OK sent on incoming)
  19593. * 2. "initial" --> "established" (after ACK is sent on outgoing, after OK sent on incoming)
  19594. * 4. "initial" --> "terminating"
  19595. * 4. "initial" --> "terminated"
  19596. * 5. "establishing" --> "established"
  19597. * 6. "establishing" --> "terminating"
  19598. * 7. "establishing" --> "terminated"
  19599. * 8. "established" --> "terminating"
  19600. * 9. "established" --> "terminated"
  19601. * 10. "terminating" --> "terminated"
  19602. * ```
  19603. * @public
  19604. */
  19605. var SessionState;
  19606. (function (SessionState) {
  19607. SessionState["Initial"] = "Initial";
  19608. SessionState["Establishing"] = "Establishing";
  19609. SessionState["Established"] = "Established";
  19610. SessionState["Terminating"] = "Terminating";
  19611. SessionState["Terminated"] = "Terminated";
  19612. })(SessionState = exports.SessionState || (exports.SessionState = {}));
  19613. /***/ }),
  19614. /* 101 */
  19615. /***/ (function(module, exports, __webpack_require__) {
  19616. "use strict";
  19617. Object.defineProperty(exports, "__esModule", { value: true });
  19618. var stripPayload = function (sdp, payload) {
  19619. var mediaDescs = [];
  19620. var lines = sdp.split(/\r\n/);
  19621. var currentMediaDesc;
  19622. for (var i = 0; i < lines.length;) {
  19623. var line = lines[i];
  19624. if (/^m=(?:audio|video)/.test(line)) {
  19625. currentMediaDesc = {
  19626. index: i,
  19627. stripped: []
  19628. };
  19629. mediaDescs.push(currentMediaDesc);
  19630. }
  19631. else if (currentMediaDesc) {
  19632. var rtpmap = /^a=rtpmap:(\d+) ([^/]+)\//.exec(line);
  19633. if (rtpmap && payload === rtpmap[2]) {
  19634. lines.splice(i, 1);
  19635. currentMediaDesc.stripped.push(rtpmap[1]);
  19636. continue; // Don't increment 'i'
  19637. }
  19638. }
  19639. i++;
  19640. }
  19641. for (var _i = 0, mediaDescs_1 = mediaDescs; _i < mediaDescs_1.length; _i++) {
  19642. var mediaDesc = mediaDescs_1[_i];
  19643. var mline = lines[mediaDesc.index].split(" ");
  19644. // Ignore the first 3 parameters of the mline. The codec information is after that
  19645. for (var j = 3; j < mline.length;) {
  19646. if (mediaDesc.stripped.indexOf(mline[j]) !== -1) {
  19647. mline.splice(j, 1);
  19648. continue;
  19649. }
  19650. j++;
  19651. }
  19652. lines[mediaDesc.index] = mline.join(" ");
  19653. }
  19654. return lines.join("\r\n");
  19655. };
  19656. var stripMediaDescription = function (sdp, description) {
  19657. var descriptionRegExp = new RegExp("m=" + description + ".*$", "gm");
  19658. var groupRegExp = new RegExp("^a=group:.*$", "gm");
  19659. if (descriptionRegExp.test(sdp)) {
  19660. var midLineToRemove_1;
  19661. sdp = sdp.split(/^m=/gm).filter(function (section) {
  19662. if (section.substr(0, description.length) === description) {
  19663. midLineToRemove_1 = section.match(/^a=mid:.*$/gm);
  19664. if (midLineToRemove_1) {
  19665. var step = midLineToRemove_1[0].match(/:.+$/g);
  19666. if (step) {
  19667. midLineToRemove_1 = step[0].substr(1);
  19668. }
  19669. }
  19670. return false;
  19671. }
  19672. return true;
  19673. }).join("m=");
  19674. var groupLine = sdp.match(groupRegExp);
  19675. if (groupLine && groupLine.length === 1) {
  19676. var groupLinePortion = groupLine[0];
  19677. var groupRegExpReplace = new RegExp("\ *" + midLineToRemove_1 + "[^\ ]*", "g");
  19678. groupLinePortion = groupLinePortion.replace(groupRegExpReplace, "");
  19679. sdp = sdp.split(groupRegExp).join(groupLinePortion);
  19680. }
  19681. }
  19682. return sdp;
  19683. };
  19684. function stripTcpCandidates(description) {
  19685. description.sdp = (description.sdp || "").replace(/^a=candidate:\d+ \d+ tcp .*?\r\n/img, "");
  19686. return Promise.resolve(description);
  19687. }
  19688. exports.stripTcpCandidates = stripTcpCandidates;
  19689. function stripTelephoneEvent(description) {
  19690. description.sdp = stripPayload(description.sdp || "", "telephone-event");
  19691. return Promise.resolve(description);
  19692. }
  19693. exports.stripTelephoneEvent = stripTelephoneEvent;
  19694. function cleanJitsiSdpImageattr(description) {
  19695. description.sdp = (description.sdp || "").replace(/^(a=imageattr:.*?)(x|y)=\[0-/gm, "$1$2=[1:");
  19696. return Promise.resolve(description);
  19697. }
  19698. exports.cleanJitsiSdpImageattr = cleanJitsiSdpImageattr;
  19699. function stripG722(description) {
  19700. description.sdp = stripPayload(description.sdp || "", "G722");
  19701. return Promise.resolve(description);
  19702. }
  19703. exports.stripG722 = stripG722;
  19704. function stripRtpPayload(payload) {
  19705. return function (description) {
  19706. description.sdp = stripPayload(description.sdp || "", payload);
  19707. return Promise.resolve(description);
  19708. };
  19709. }
  19710. exports.stripRtpPayload = stripRtpPayload;
  19711. function stripVideo(description) {
  19712. description.sdp = stripMediaDescription(description.sdp || "", "video");
  19713. return Promise.resolve(description);
  19714. }
  19715. exports.stripVideo = stripVideo;
  19716. function addMidLines(description) {
  19717. var sdp = description.sdp || "";
  19718. if (sdp.search(/^a=mid.*$/gm) === -1) {
  19719. var mlines_1 = sdp.match(/^m=.*$/gm);
  19720. var sdpArray_1 = sdp.split(/^m=.*$/gm);
  19721. if (mlines_1) {
  19722. mlines_1.forEach(function (elem, idx) {
  19723. mlines_1[idx] = elem + "\na=mid:" + idx;
  19724. });
  19725. }
  19726. sdpArray_1.forEach(function (elem, idx) {
  19727. if (mlines_1 && mlines_1[idx]) {
  19728. sdpArray_1[idx] = elem + mlines_1[idx];
  19729. }
  19730. });
  19731. sdp = sdpArray_1.join("");
  19732. description.sdp = sdp;
  19733. }
  19734. return Promise.resolve(description);
  19735. }
  19736. exports.addMidLines = addMidLines;
  19737. /***/ }),
  19738. /* 102 */
  19739. /***/ (function(module, exports, __webpack_require__) {
  19740. "use strict";
  19741. Object.defineProperty(exports, "__esModule", { value: true });
  19742. var Enums_1 = __webpack_require__(82);
  19743. /* SessionDescriptionHandlerObserver
  19744. * @class SessionDescriptionHandler Observer Class.
  19745. * @param {SIP.Session} session
  19746. * @param {Object} [options]
  19747. */
  19748. var SessionDescriptionHandlerObserver = /** @class */ (function () {
  19749. function SessionDescriptionHandlerObserver(session, options) {
  19750. this.type = Enums_1.TypeStrings.SessionDescriptionHandlerObserver;
  19751. this.session = session;
  19752. this.options = options;
  19753. }
  19754. SessionDescriptionHandlerObserver.prototype.trackAdded = function () {
  19755. this.session.emit("trackAdded");
  19756. };
  19757. SessionDescriptionHandlerObserver.prototype.directionChanged = function () {
  19758. this.session.emit("directionChanged");
  19759. };
  19760. return SessionDescriptionHandlerObserver;
  19761. }());
  19762. exports.SessionDescriptionHandlerObserver = SessionDescriptionHandlerObserver;
  19763. /***/ }),
  19764. /* 103 */
  19765. /***/ (function(module, exports, __webpack_require__) {
  19766. "use strict";
  19767. Object.defineProperty(exports, "__esModule", { value: true });
  19768. var tslib_1 = __webpack_require__(1);
  19769. var core_1 = __webpack_require__(2);
  19770. var Enums_1 = __webpack_require__(82);
  19771. var Exceptions_1 = __webpack_require__(84);
  19772. var Utils_1 = __webpack_require__(83);
  19773. var TransportStatus;
  19774. (function (TransportStatus) {
  19775. TransportStatus[TransportStatus["STATUS_CONNECTING"] = 0] = "STATUS_CONNECTING";
  19776. TransportStatus[TransportStatus["STATUS_OPEN"] = 1] = "STATUS_OPEN";
  19777. TransportStatus[TransportStatus["STATUS_CLOSING"] = 2] = "STATUS_CLOSING";
  19778. TransportStatus[TransportStatus["STATUS_CLOSED"] = 3] = "STATUS_CLOSED";
  19779. })(TransportStatus = exports.TransportStatus || (exports.TransportStatus = {}));
  19780. /**
  19781. * Compute an amount of time in seconds to wait before sending another
  19782. * keep-alive.
  19783. * @returns {Number}
  19784. */
  19785. var computeKeepAliveTimeout = function (upperBound) {
  19786. var lowerBound = upperBound * 0.8;
  19787. return 1000 * (Math.random() * (upperBound - lowerBound) + lowerBound);
  19788. };
  19789. /**
  19790. * @class Transport
  19791. * @param {Object} options
  19792. */
  19793. var Transport = /** @class */ (function (_super) {
  19794. tslib_1.__extends(Transport, _super);
  19795. function Transport(logger, options) {
  19796. if (options === void 0) { options = {}; }
  19797. var _this = _super.call(this, logger) || this;
  19798. _this.type = Enums_1.TypeStrings.Transport;
  19799. _this.reconnectionAttempts = 0;
  19800. _this.status = TransportStatus.STATUS_CONNECTING;
  19801. _this.configuration = _this.loadConfig(options);
  19802. _this.server = _this.configuration.wsServers[0];
  19803. return _this;
  19804. }
  19805. /**
  19806. * @returns {Boolean}
  19807. */
  19808. Transport.prototype.isConnected = function () {
  19809. return this.status === TransportStatus.STATUS_OPEN;
  19810. };
  19811. /**
  19812. * Send a message.
  19813. * @param message - Outgoing message.
  19814. * @param options - Options bucket.
  19815. */
  19816. Transport.prototype.sendPromise = function (message, options) {
  19817. if (options === void 0) { options = {}; }
  19818. if (this.ws === undefined) {
  19819. this.onError("unable to send message - WebSocket undefined");
  19820. return Promise.reject(new Error("WebSocket undefined."));
  19821. }
  19822. // FIXME: This check is likely not necessary as WebSocket.send() will
  19823. // throw INVALID_STATE_ERR if the connection is not currently open
  19824. // which could happen regardless of what we thing the state is.
  19825. if (!this.statusAssert(TransportStatus.STATUS_OPEN, options.force)) {
  19826. this.onError("unable to send message - WebSocket not open");
  19827. return Promise.reject(new Error("WebSocket not open."));
  19828. }
  19829. if (this.configuration.traceSip === true) {
  19830. this.logger.log("sending WebSocket message:\n\n" + message + "\n");
  19831. }
  19832. // WebSocket.send() can throw.
  19833. // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
  19834. try {
  19835. this.ws.send(message);
  19836. }
  19837. catch (error) {
  19838. if (error instanceof error) {
  19839. Promise.reject(error);
  19840. }
  19841. return Promise.reject(new Error("Failed to send message."));
  19842. }
  19843. return Promise.resolve({ msg: message });
  19844. };
  19845. /**
  19846. * Disconnect socket.
  19847. */
  19848. Transport.prototype.disconnectPromise = function (options) {
  19849. var _this = this;
  19850. if (options === void 0) { options = {}; }
  19851. if (this.disconnectionPromise) { // Already disconnecting. Just return this.
  19852. return this.disconnectionPromise;
  19853. }
  19854. options.code = options.code || 1000;
  19855. if (!this.statusTransition(TransportStatus.STATUS_CLOSING, options.force)) {
  19856. if (this.status === TransportStatus.STATUS_CLOSED) { // Websocket is already closed
  19857. return Promise.resolve({ overrideEvent: true });
  19858. }
  19859. else if (this.connectionPromise) { // Websocket is connecting, cannot move to disconneting yet
  19860. return this.connectionPromise.then(function () { return Promise.reject("The websocket did not disconnect"); })
  19861. .catch(function () { return Promise.resolve({ overrideEvent: true }); });
  19862. }
  19863. else {
  19864. // Cannot move to disconnecting, but not in connecting state.
  19865. return Promise.reject("The websocket did not disconnect");
  19866. }
  19867. }
  19868. this.emit("disconnecting");
  19869. this.disconnectionPromise = new Promise(function (resolve, reject) {
  19870. _this.disconnectDeferredResolve = resolve;
  19871. if (_this.reconnectTimer) {
  19872. clearTimeout(_this.reconnectTimer);
  19873. _this.reconnectTimer = undefined;
  19874. }
  19875. if (_this.ws) {
  19876. _this.stopSendingKeepAlives();
  19877. _this.logger.log("closing WebSocket " + _this.server.wsUri);
  19878. _this.ws.close(options.code, options.reason);
  19879. }
  19880. else {
  19881. reject("Attempted to disconnect but the websocket doesn't exist");
  19882. }
  19883. });
  19884. return this.disconnectionPromise;
  19885. };
  19886. /**
  19887. * Connect socket.
  19888. */
  19889. Transport.prototype.connectPromise = function (options) {
  19890. var _this = this;
  19891. if (options === void 0) { options = {}; }
  19892. if (this.status === TransportStatus.STATUS_CLOSING && !options.force) {
  19893. return Promise.reject("WebSocket " + this.server.wsUri + " is closing");
  19894. }
  19895. if (this.connectionPromise) {
  19896. return this.connectionPromise;
  19897. }
  19898. this.server = this.server || this.getNextWsServer(options.force);
  19899. this.connectionPromise = new Promise(function (resolve, reject) {
  19900. if ((_this.status === TransportStatus.STATUS_OPEN || _this.status === TransportStatus.STATUS_CLOSING)
  19901. && !options.force) {
  19902. _this.logger.warn("WebSocket " + _this.server.wsUri + " is already connected");
  19903. reject("Failed status check - attempted to open a connection but already open/closing");
  19904. return;
  19905. }
  19906. _this.connectDeferredResolve = resolve;
  19907. _this.connectDeferredReject = reject;
  19908. _this.status = TransportStatus.STATUS_CONNECTING;
  19909. _this.emit("connecting");
  19910. _this.logger.log("connecting to WebSocket " + _this.server.wsUri);
  19911. _this.disposeWs();
  19912. try {
  19913. _this.ws = new WebSocket(_this.server.wsUri, "sip");
  19914. }
  19915. catch (e) {
  19916. _this.ws = undefined;
  19917. _this.statusTransition(TransportStatus.STATUS_CLOSED, true);
  19918. _this.onError("error connecting to WebSocket " + _this.server.wsUri + ":" + e);
  19919. reject("Failed to create a websocket");
  19920. _this.connectDeferredResolve = undefined;
  19921. _this.connectDeferredReject = undefined;
  19922. return;
  19923. }
  19924. if (!_this.ws) {
  19925. reject("Unexpected instance websocket not set");
  19926. _this.connectDeferredResolve = undefined;
  19927. _this.connectDeferredReject = undefined;
  19928. return;
  19929. }
  19930. _this.connectionTimeout = setTimeout(function () {
  19931. _this.statusTransition(TransportStatus.STATUS_CLOSED);
  19932. _this.logger.warn("took too long to connect - exceeded time set in configuration.connectionTimeout: " +
  19933. _this.configuration.connectionTimeout + "s");
  19934. _this.emit("disconnected", { code: 1000 });
  19935. _this.connectionPromise = undefined;
  19936. reject("Connection timeout");
  19937. _this.connectDeferredResolve = undefined;
  19938. _this.connectDeferredReject = undefined;
  19939. var ws = _this.ws;
  19940. _this.disposeWs();
  19941. if (ws) {
  19942. ws.close(1000);
  19943. }
  19944. }, _this.configuration.connectionTimeout * 1000);
  19945. _this.boundOnOpen = _this.onOpen.bind(_this);
  19946. _this.boundOnMessage = _this.onMessage.bind(_this);
  19947. _this.boundOnClose = _this.onClose.bind(_this);
  19948. _this.boundOnError = _this.onWebsocketError.bind(_this);
  19949. _this.ws.addEventListener("open", _this.boundOnOpen);
  19950. _this.ws.addEventListener("message", _this.boundOnMessage);
  19951. _this.ws.addEventListener("close", _this.boundOnClose);
  19952. _this.ws.addEventListener("error", _this.boundOnError);
  19953. });
  19954. return this.connectionPromise;
  19955. };
  19956. /**
  19957. * @event
  19958. * @param {event} e
  19959. */
  19960. Transport.prototype.onMessage = function (e) {
  19961. var data = e.data;
  19962. var finishedData;
  19963. // CRLF Keep Alive response from server. Clear our keep alive timeout.
  19964. if (/^(\r\n)+$/.test(data)) {
  19965. this.clearKeepAliveTimeout();
  19966. if (this.configuration.traceSip === true) {
  19967. this.logger.log("received WebSocket message with CRLF Keep Alive response");
  19968. }
  19969. return;
  19970. }
  19971. else if (!data) {
  19972. this.logger.warn("received empty message, message discarded");
  19973. return;
  19974. }
  19975. else if (typeof data !== "string") { // WebSocket binary message.
  19976. try {
  19977. // the UInt8Data was here prior to types, and doesn't check
  19978. finishedData = String.fromCharCode.apply(null, new Uint8Array(data));
  19979. }
  19980. catch (err) {
  19981. this.logger.warn("received WebSocket binary message failed to be converted into string, message discarded");
  19982. return;
  19983. }
  19984. if (this.configuration.traceSip === true) {
  19985. this.logger.log("received WebSocket binary message:\n\n" + data + "\n");
  19986. }
  19987. }
  19988. else { // WebSocket text message.
  19989. if (this.configuration.traceSip === true) {
  19990. this.logger.log("received WebSocket text message:\n\n" + data + "\n");
  19991. }
  19992. finishedData = data;
  19993. }
  19994. this.emit("message", finishedData);
  19995. };
  19996. // Transport Event Handlers
  19997. /**
  19998. * @event
  19999. * @param {event} e
  20000. */
  20001. Transport.prototype.onOpen = function () {
  20002. if (this.status === TransportStatus.STATUS_CLOSED) { // Indicated that the transport thinks the ws is dead already
  20003. var ws = this.ws;
  20004. this.disposeWs();
  20005. if (ws) {
  20006. ws.close(1000);
  20007. }
  20008. return;
  20009. }
  20010. this.statusTransition(TransportStatus.STATUS_OPEN, true);
  20011. this.emit("connected");
  20012. if (this.connectionTimeout) {
  20013. clearTimeout(this.connectionTimeout);
  20014. this.connectionTimeout = undefined;
  20015. }
  20016. this.logger.log("WebSocket " + this.server.wsUri + " connected");
  20017. // Clear reconnectTimer since we are not disconnected
  20018. if (this.reconnectTimer !== undefined) {
  20019. clearTimeout(this.reconnectTimer);
  20020. this.reconnectTimer = undefined;
  20021. }
  20022. // Reset reconnectionAttempts
  20023. this.reconnectionAttempts = 0;
  20024. // Reset disconnection promise so we can disconnect from a fresh state
  20025. this.disconnectionPromise = undefined;
  20026. this.disconnectDeferredResolve = undefined;
  20027. // Start sending keep-alives
  20028. this.startSendingKeepAlives();
  20029. if (this.connectDeferredResolve) {
  20030. this.connectDeferredResolve({ overrideEvent: true });
  20031. this.connectDeferredResolve = undefined;
  20032. this.connectDeferredReject = undefined;
  20033. }
  20034. else {
  20035. this.logger.warn("Unexpected websocket.onOpen with no connectDeferredResolve");
  20036. }
  20037. };
  20038. /**
  20039. * @event
  20040. * @param {event} e
  20041. */
  20042. Transport.prototype.onClose = function (e) {
  20043. this.logger.log("WebSocket disconnected (code: " + e.code + (e.reason ? "| reason: " + e.reason : "") + ")");
  20044. if (this.status !== TransportStatus.STATUS_CLOSING) {
  20045. this.logger.warn("WebSocket closed without SIP.js requesting it");
  20046. this.emit("transportError");
  20047. }
  20048. this.stopSendingKeepAlives();
  20049. // Clean up connection variables so we can connect again from a fresh state
  20050. if (this.connectionTimeout) {
  20051. clearTimeout(this.connectionTimeout);
  20052. }
  20053. if (this.connectDeferredReject) {
  20054. this.connectDeferredReject("Websocket Closed");
  20055. }
  20056. this.connectionTimeout = undefined;
  20057. this.connectionPromise = undefined;
  20058. this.connectDeferredResolve = undefined;
  20059. this.connectDeferredReject = undefined;
  20060. // Check whether the user requested to close.
  20061. if (this.disconnectDeferredResolve) {
  20062. this.disconnectDeferredResolve({ overrideEvent: true });
  20063. this.statusTransition(TransportStatus.STATUS_CLOSED);
  20064. this.disconnectDeferredResolve = undefined;
  20065. return;
  20066. }
  20067. this.statusTransition(TransportStatus.STATUS_CLOSED, true);
  20068. this.emit("disconnected", { code: e.code, reason: e.reason });
  20069. this.disposeWs();
  20070. this.reconnect();
  20071. };
  20072. /**
  20073. * Removes event listeners and clears the instance ws
  20074. */
  20075. Transport.prototype.disposeWs = function () {
  20076. if (this.ws) {
  20077. this.ws.removeEventListener("open", this.boundOnOpen);
  20078. this.ws.removeEventListener("message", this.boundOnMessage);
  20079. this.ws.removeEventListener("close", this.boundOnClose);
  20080. this.ws.removeEventListener("error", this.boundOnError);
  20081. this.ws = undefined;
  20082. }
  20083. };
  20084. /**
  20085. * @event
  20086. * @param {string} e
  20087. */
  20088. Transport.prototype.onError = function (e) {
  20089. this.logger.warn("Transport error: " + e);
  20090. this.emit("transportError");
  20091. };
  20092. /**
  20093. * @event
  20094. * @private
  20095. */
  20096. Transport.prototype.onWebsocketError = function () {
  20097. this.onError("The Websocket had an error");
  20098. };
  20099. /**
  20100. * Reconnection attempt logic.
  20101. */
  20102. Transport.prototype.reconnect = function () {
  20103. var _this = this;
  20104. if (this.reconnectionAttempts > 0) {
  20105. this.logger.log("Reconnection attempt " + this.reconnectionAttempts + " failed");
  20106. }
  20107. if (this.noAvailableServers()) {
  20108. this.logger.warn("attempted to get next ws server but there are no available ws servers left");
  20109. this.logger.warn("no available ws servers left - going to closed state");
  20110. this.statusTransition(TransportStatus.STATUS_CLOSED, true);
  20111. this.emit("closed");
  20112. this.resetServerErrorStatus();
  20113. return;
  20114. }
  20115. if (this.isConnected()) {
  20116. this.logger.warn("attempted to reconnect while connected - forcing disconnect");
  20117. this.disconnect({ force: true });
  20118. }
  20119. this.reconnectionAttempts += 1;
  20120. if (this.reconnectionAttempts > this.configuration.maxReconnectionAttempts) {
  20121. this.logger.warn("maximum reconnection attempts for WebSocket " + this.server.wsUri);
  20122. this.logger.log("transport " + this.server.wsUri + " failed | connection state set to 'error'");
  20123. this.server.isError = true;
  20124. this.emit("transportError");
  20125. if (!this.noAvailableServers()) {
  20126. this.server = this.getNextWsServer();
  20127. }
  20128. // When there are no available servers, the reconnect function ends on the next recursive call
  20129. // after checking for no available servers again.
  20130. this.reconnectionAttempts = 0;
  20131. this.reconnect();
  20132. }
  20133. else {
  20134. this.logger.log("trying to reconnect to WebSocket " +
  20135. this.server.wsUri + " (reconnection attempt " + this.reconnectionAttempts + ")");
  20136. this.reconnectTimer = setTimeout(function () {
  20137. _this.connect();
  20138. _this.reconnectTimer = undefined;
  20139. }, (this.reconnectionAttempts === 1) ? 0 : this.configuration.reconnectionTimeout * 1000);
  20140. }
  20141. };
  20142. /**
  20143. * Resets the error state of all servers in the configuration
  20144. */
  20145. Transport.prototype.resetServerErrorStatus = function () {
  20146. for (var _i = 0, _a = this.configuration.wsServers; _i < _a.length; _i++) {
  20147. var websocket = _a[_i];
  20148. websocket.isError = false;
  20149. }
  20150. };
  20151. /**
  20152. * Retrieve the next server to which connect.
  20153. * @param {Boolean} force allows bypass of server error status checking
  20154. * @returns {Object} WsServer
  20155. */
  20156. Transport.prototype.getNextWsServer = function (force) {
  20157. if (force === void 0) { force = false; }
  20158. if (this.noAvailableServers()) {
  20159. this.logger.warn("attempted to get next ws server but there are no available ws servers left");
  20160. throw new Error("Attempted to get next ws server, but there are no available ws servers left.");
  20161. }
  20162. // Order servers by weight
  20163. var candidates = [];
  20164. for (var _i = 0, _a = this.configuration.wsServers; _i < _a.length; _i++) {
  20165. var wsServer = _a[_i];
  20166. if (wsServer.isError && !force) {
  20167. continue;
  20168. }
  20169. else if (candidates.length === 0) {
  20170. candidates.push(wsServer);
  20171. }
  20172. else if (wsServer.weight > candidates[0].weight) {
  20173. candidates = [wsServer];
  20174. }
  20175. else if (wsServer.weight === candidates[0].weight) {
  20176. candidates.push(wsServer);
  20177. }
  20178. }
  20179. var idx = Math.floor(Math.random() * candidates.length);
  20180. return candidates[idx];
  20181. };
  20182. /**
  20183. * Checks all configuration servers, returns true if all of them have isError: true and false otherwise
  20184. * @returns {Boolean}
  20185. */
  20186. Transport.prototype.noAvailableServers = function () {
  20187. for (var _i = 0, _a = this.configuration.wsServers; _i < _a.length; _i++) {
  20188. var server = _a[_i];
  20189. if (!server.isError) {
  20190. return false;
  20191. }
  20192. }
  20193. return true;
  20194. };
  20195. // ==============================
  20196. // KeepAlive Stuff
  20197. // ==============================
  20198. /**
  20199. * Send a keep-alive (a double-CRLF sequence).
  20200. * @returns {Boolean}
  20201. */
  20202. Transport.prototype.sendKeepAlive = function () {
  20203. var _this = this;
  20204. if (this.keepAliveDebounceTimeout) {
  20205. // We already have an outstanding keep alive, do not send another.
  20206. return;
  20207. }
  20208. this.keepAliveDebounceTimeout = setTimeout(function () {
  20209. _this.emit("keepAliveDebounceTimeout");
  20210. _this.clearKeepAliveTimeout();
  20211. }, this.configuration.keepAliveDebounce * 1000);
  20212. return this.send("\r\n\r\n");
  20213. };
  20214. Transport.prototype.clearKeepAliveTimeout = function () {
  20215. if (this.keepAliveDebounceTimeout) {
  20216. clearTimeout(this.keepAliveDebounceTimeout);
  20217. }
  20218. this.keepAliveDebounceTimeout = undefined;
  20219. };
  20220. /**
  20221. * Start sending keep-alives.
  20222. */
  20223. Transport.prototype.startSendingKeepAlives = function () {
  20224. var _this = this;
  20225. if (this.configuration.keepAliveInterval && !this.keepAliveInterval) {
  20226. this.keepAliveInterval = setInterval(function () {
  20227. _this.sendKeepAlive();
  20228. _this.startSendingKeepAlives();
  20229. }, computeKeepAliveTimeout(this.configuration.keepAliveInterval));
  20230. }
  20231. };
  20232. /**
  20233. * Stop sending keep-alives.
  20234. */
  20235. Transport.prototype.stopSendingKeepAlives = function () {
  20236. if (this.keepAliveInterval) {
  20237. clearInterval(this.keepAliveInterval);
  20238. }
  20239. if (this.keepAliveDebounceTimeout) {
  20240. clearTimeout(this.keepAliveDebounceTimeout);
  20241. }
  20242. this.keepAliveInterval = undefined;
  20243. this.keepAliveDebounceTimeout = undefined;
  20244. };
  20245. // ==============================
  20246. // Status Stuff
  20247. // ==============================
  20248. /**
  20249. * Checks given status against instance current status. Returns true if they match
  20250. * @param {Number} status
  20251. * @param {Boolean} [force]
  20252. * @returns {Boolean}
  20253. */
  20254. Transport.prototype.statusAssert = function (status, force) {
  20255. if (status === this.status) {
  20256. return true;
  20257. }
  20258. else {
  20259. if (force) {
  20260. this.logger.warn("Attempted to assert " +
  20261. Object.keys(TransportStatus)[this.status] + " as " +
  20262. Object.keys(TransportStatus)[status] + "- continuing with option: 'force'");
  20263. return true;
  20264. }
  20265. else {
  20266. this.logger.warn("Tried to assert " +
  20267. Object.keys(TransportStatus)[status] + " but is currently " +
  20268. Object.keys(TransportStatus)[this.status]);
  20269. return false;
  20270. }
  20271. }
  20272. };
  20273. /**
  20274. * Transitions the status. Checks for legal transition via assertion beforehand
  20275. * @param {Number} status
  20276. * @param {Boolean} [force]
  20277. * @returns {Boolean}
  20278. */
  20279. Transport.prototype.statusTransition = function (status, force) {
  20280. if (force === void 0) { force = false; }
  20281. this.logger.log("Attempting to transition status from " +
  20282. Object.keys(TransportStatus)[this.status] + " to " +
  20283. Object.keys(TransportStatus)[status]);
  20284. if ((status === TransportStatus.STATUS_CONNECTING && this.statusAssert(TransportStatus.STATUS_CLOSED, force)) ||
  20285. (status === TransportStatus.STATUS_OPEN && this.statusAssert(TransportStatus.STATUS_CONNECTING, force)) ||
  20286. (status === TransportStatus.STATUS_CLOSING && this.statusAssert(TransportStatus.STATUS_OPEN, force)) ||
  20287. (status === TransportStatus.STATUS_CLOSED)) {
  20288. this.status = status;
  20289. return true;
  20290. }
  20291. else {
  20292. this.logger.warn("Status transition failed - result: no-op - reason:" +
  20293. " either gave an nonexistent status or attempted illegal transition");
  20294. return false;
  20295. }
  20296. };
  20297. // ==============================
  20298. // Configuration Handling
  20299. // ==============================
  20300. /**
  20301. * Configuration load.
  20302. * returns {Configuration}
  20303. */
  20304. Transport.prototype.loadConfig = function (configuration) {
  20305. var settings = {
  20306. wsServers: [{
  20307. scheme: "WSS",
  20308. sipUri: "<sip:edge.sip.onsip.com;transport=ws;lr>",
  20309. weight: 0,
  20310. wsUri: "wss://edge.sip.onsip.com",
  20311. isError: false
  20312. }],
  20313. connectionTimeout: 5,
  20314. maxReconnectionAttempts: 3,
  20315. reconnectionTimeout: 4,
  20316. keepAliveInterval: 0,
  20317. keepAliveDebounce: 10,
  20318. // Logging
  20319. traceSip: false
  20320. };
  20321. var configCheck = this.getConfigurationCheck();
  20322. // Check Mandatory parameters
  20323. for (var parameter in configCheck.mandatory) {
  20324. if (!configuration.hasOwnProperty(parameter)) {
  20325. throw new Exceptions_1.Exceptions.ConfigurationError(parameter);
  20326. }
  20327. else {
  20328. var value = configuration[parameter];
  20329. var checkedValue = configCheck.mandatory[parameter](value);
  20330. if (checkedValue !== undefined) {
  20331. settings[parameter] = checkedValue;
  20332. }
  20333. else {
  20334. throw new Exceptions_1.Exceptions.ConfigurationError(parameter, value);
  20335. }
  20336. }
  20337. }
  20338. // Check Optional parameters
  20339. for (var parameter in configCheck.optional) {
  20340. if (configuration.hasOwnProperty(parameter)) {
  20341. var value = configuration[parameter];
  20342. // If the parameter value is an empty array, but shouldn't be, apply its default value.
  20343. // If the parameter value is null, empty string, or undefined then apply its default value.
  20344. // If it's a number with NaN value then also apply its default value.
  20345. // NOTE: JS does not allow "value === NaN", the following does the work:
  20346. if ((value instanceof Array && value.length === 0) ||
  20347. (value === null || value === "" || value === undefined) ||
  20348. (typeof (value) === "number" && isNaN(value))) {
  20349. continue;
  20350. }
  20351. var checkedValue = configCheck.optional[parameter](value);
  20352. if (checkedValue !== undefined) {
  20353. settings[parameter] = checkedValue;
  20354. }
  20355. else {
  20356. throw new Exceptions_1.Exceptions.ConfigurationError(parameter, value);
  20357. }
  20358. }
  20359. }
  20360. var skeleton = {}; // Fill the value of the configuration_skeleton
  20361. for (var parameter in settings) {
  20362. if (settings.hasOwnProperty(parameter)) {
  20363. skeleton[parameter] = {
  20364. value: settings[parameter],
  20365. };
  20366. }
  20367. }
  20368. var returnConfiguration = Object.defineProperties({}, skeleton);
  20369. this.logger.log("configuration parameters after validation:");
  20370. for (var parameter in settings) {
  20371. if (settings.hasOwnProperty(parameter)) {
  20372. this.logger.log("· " + parameter + ": " + JSON.stringify(settings[parameter]));
  20373. }
  20374. }
  20375. return returnConfiguration;
  20376. };
  20377. /**
  20378. * Configuration checker.
  20379. * @return {Boolean}
  20380. */
  20381. Transport.prototype.getConfigurationCheck = function () {
  20382. return {
  20383. mandatory: {},
  20384. optional: {
  20385. // Note: this function used to call 'this.logger.error' but calling 'this' with anything here is invalid
  20386. wsServers: function (wsServers) {
  20387. /* Allow defining wsServers parameter as:
  20388. * String: "host"
  20389. * Array of Strings: ["host1", "host2"]
  20390. * Array of Objects: [{wsUri:"host1", weight:1}, {wsUri:"host2", weight:0}]
  20391. * Array of Objects and Strings: [{wsUri:"host1"}, "host2"]
  20392. */
  20393. if (typeof wsServers === "string") {
  20394. wsServers = [{ wsUri: wsServers }];
  20395. }
  20396. else if (wsServers instanceof Array) {
  20397. for (var idx = 0; idx < wsServers.length; idx++) {
  20398. if (typeof wsServers[idx] === "string") {
  20399. wsServers[idx] = { wsUri: wsServers[idx] };
  20400. }
  20401. }
  20402. }
  20403. else {
  20404. return;
  20405. }
  20406. if (wsServers.length === 0) {
  20407. return false;
  20408. }
  20409. for (var _i = 0, wsServers_1 = wsServers; _i < wsServers_1.length; _i++) {
  20410. var wsServer = wsServers_1[_i];
  20411. if (!wsServer.wsUri) {
  20412. return;
  20413. }
  20414. if (wsServer.weight && !Number(wsServer.weight)) {
  20415. return;
  20416. }
  20417. var url = core_1.Grammar.parse(wsServer.wsUri, "absoluteURI");
  20418. if (url === -1) {
  20419. return;
  20420. }
  20421. else if (["wss", "ws", "udp"].indexOf(url.scheme) < 0) {
  20422. return;
  20423. }
  20424. else {
  20425. wsServer.sipUri = "<sip:" + url.host +
  20426. (url.port ? ":" + url.port : "") + ";transport=" + url.scheme.replace(/^wss$/i, "ws") + ";lr>";
  20427. if (!wsServer.weight) {
  20428. wsServer.weight = 0;
  20429. }
  20430. wsServer.isError = false;
  20431. wsServer.scheme = url.scheme.toUpperCase();
  20432. }
  20433. }
  20434. return wsServers;
  20435. },
  20436. keepAliveInterval: function (keepAliveInterval) {
  20437. if (Utils_1.Utils.isDecimal(keepAliveInterval)) {
  20438. var value = Number(keepAliveInterval);
  20439. if (value > 0) {
  20440. return value;
  20441. }
  20442. }
  20443. },
  20444. keepAliveDebounce: function (keepAliveDebounce) {
  20445. if (Utils_1.Utils.isDecimal(keepAliveDebounce)) {
  20446. var value = Number(keepAliveDebounce);
  20447. if (value > 0) {
  20448. return value;
  20449. }
  20450. }
  20451. },
  20452. traceSip: function (traceSip) {
  20453. if (typeof traceSip === "boolean") {
  20454. return traceSip;
  20455. }
  20456. },
  20457. connectionTimeout: function (connectionTimeout) {
  20458. if (Utils_1.Utils.isDecimal(connectionTimeout)) {
  20459. var value = Number(connectionTimeout);
  20460. if (value > 0) {
  20461. return value;
  20462. }
  20463. }
  20464. },
  20465. maxReconnectionAttempts: function (maxReconnectionAttempts) {
  20466. if (Utils_1.Utils.isDecimal(maxReconnectionAttempts)) {
  20467. var value = Number(maxReconnectionAttempts);
  20468. if (value >= 0) {
  20469. return value;
  20470. }
  20471. }
  20472. },
  20473. reconnectionTimeout: function (reconnectionTimeout) {
  20474. if (Utils_1.Utils.isDecimal(reconnectionTimeout)) {
  20475. var value = Number(reconnectionTimeout);
  20476. if (value > 0) {
  20477. return value;
  20478. }
  20479. }
  20480. }
  20481. }
  20482. };
  20483. };
  20484. Transport.C = TransportStatus;
  20485. return Transport;
  20486. }(core_1.Transport));
  20487. exports.Transport = Transport;
  20488. /***/ }),
  20489. /* 104 */
  20490. /***/ (function(module, exports, __webpack_require__) {
  20491. "use strict";
  20492. Object.defineProperty(exports, "__esModule", { value: true });
  20493. var tslib_1 = __webpack_require__(1);
  20494. var Modifiers = tslib_1.__importStar(__webpack_require__(101));
  20495. exports.Modifiers = Modifiers;
  20496. var Simple_1 = __webpack_require__(105);
  20497. exports.Simple = Simple_1.Simple;
  20498. var SessionDescriptionHandler_1 = __webpack_require__(94);
  20499. exports.SessionDescriptionHandler = SessionDescriptionHandler_1.SessionDescriptionHandler;
  20500. var Transport_1 = __webpack_require__(103);
  20501. exports.Transport = Transport_1.Transport;
  20502. /***/ }),
  20503. /* 105 */
  20504. /***/ (function(module, exports, __webpack_require__) {
  20505. "use strict";
  20506. Object.defineProperty(exports, "__esModule", { value: true });
  20507. var tslib_1 = __webpack_require__(1);
  20508. var events_1 = __webpack_require__(30);
  20509. var UA_1 = __webpack_require__(93);
  20510. var Modifiers = tslib_1.__importStar(__webpack_require__(101));
  20511. /* Simple
  20512. * @class Simple
  20513. */
  20514. var SimpleStatus;
  20515. (function (SimpleStatus) {
  20516. SimpleStatus[SimpleStatus["STATUS_NULL"] = 0] = "STATUS_NULL";
  20517. SimpleStatus[SimpleStatus["STATUS_NEW"] = 1] = "STATUS_NEW";
  20518. SimpleStatus[SimpleStatus["STATUS_CONNECTING"] = 2] = "STATUS_CONNECTING";
  20519. SimpleStatus[SimpleStatus["STATUS_CONNECTED"] = 3] = "STATUS_CONNECTED";
  20520. SimpleStatus[SimpleStatus["STATUS_COMPLETED"] = 4] = "STATUS_COMPLETED";
  20521. })(SimpleStatus = exports.SimpleStatus || (exports.SimpleStatus = {}));
  20522. var Simple = /** @class */ (function (_super) {
  20523. tslib_1.__extends(Simple, _super);
  20524. function Simple(options) {
  20525. var _this = _super.call(this) || this;
  20526. /*
  20527. * {
  20528. * media: {
  20529. * remote: {
  20530. * audio: <DOM element>,
  20531. * video: <DOM element>
  20532. * },
  20533. * local: {
  20534. * video: <DOM element>
  20535. * }
  20536. * },
  20537. * ua: {
  20538. * <UA Configuration Options>
  20539. * }
  20540. * }
  20541. */
  20542. if (options.media.remote.video) {
  20543. _this.video = true;
  20544. }
  20545. else {
  20546. _this.video = false;
  20547. }
  20548. if (options.media.remote.audio) {
  20549. _this.audio = true;
  20550. }
  20551. else {
  20552. _this.audio = false;
  20553. }
  20554. if (!_this.audio && !_this.video) {
  20555. // Need to do at least audio or video
  20556. // Error
  20557. throw new Error("At least one remote audio or video element is required for Simple.");
  20558. }
  20559. _this.options = options;
  20560. // https://stackoverflow.com/questions/7944460/detect-safari-browser
  20561. var browserUa = navigator.userAgent.toLowerCase();
  20562. var isSafari = false;
  20563. var isFirefox = false;
  20564. if (browserUa.indexOf("safari") > -1 && browserUa.indexOf("chrome") < 0) {
  20565. isSafari = true;
  20566. }
  20567. else if (browserUa.indexOf("firefox") > -1 && browserUa.indexOf("chrome") < 0) {
  20568. isFirefox = true;
  20569. }
  20570. var sessionDescriptionHandlerFactoryOptions = {};
  20571. if (isSafari) {
  20572. sessionDescriptionHandlerFactoryOptions.modifiers = [Modifiers.stripG722];
  20573. }
  20574. if (isFirefox) {
  20575. sessionDescriptionHandlerFactoryOptions.alwaysAcquireMediaFirst = true;
  20576. }
  20577. if (!_this.options.ua.uri) {
  20578. _this.anonymous = true;
  20579. }
  20580. else {
  20581. _this.anonymous = false;
  20582. }
  20583. _this.ua = new UA_1.UA({
  20584. // User Configurable Options
  20585. uri: _this.options.ua.uri,
  20586. authorizationUser: _this.options.ua.authorizationUser,
  20587. password: _this.options.ua.password,
  20588. displayName: _this.options.ua.displayName,
  20589. // Undocumented "Advanced" Options
  20590. userAgentString: _this.options.ua.userAgentString,
  20591. // Fixed Options
  20592. register: true,
  20593. sessionDescriptionHandlerFactoryOptions: sessionDescriptionHandlerFactoryOptions,
  20594. transportOptions: {
  20595. traceSip: _this.options.ua.traceSip,
  20596. wsServers: _this.options.ua.wsServers
  20597. }
  20598. });
  20599. _this.state = SimpleStatus.STATUS_NULL;
  20600. _this.logger = _this.ua.getLogger("sip.simple");
  20601. _this.ua.on("registered", function () {
  20602. _this.emit("registered", _this.ua);
  20603. });
  20604. _this.ua.on("unregistered", function () {
  20605. _this.emit("unregistered", _this.ua);
  20606. });
  20607. _this.ua.on("registrationFailed", function () {
  20608. _this.emit("unregistered", _this.ua);
  20609. });
  20610. _this.ua.on("invite", function (session) {
  20611. // If there is already an active session reject the incoming session
  20612. if (_this.state !== SimpleStatus.STATUS_NULL && _this.state !== SimpleStatus.STATUS_COMPLETED) {
  20613. _this.logger.warn("Rejecting incoming call. Simple only supports 1 call at a time");
  20614. session.reject();
  20615. return;
  20616. }
  20617. _this.session = session;
  20618. _this.setupSession();
  20619. _this.emit("ringing", _this.session);
  20620. });
  20621. _this.ua.on("message", function (message) {
  20622. _this.emit("message", message);
  20623. });
  20624. return _this;
  20625. }
  20626. Simple.prototype.call = function (destination) {
  20627. if (!this.ua || !this.checkRegistration()) {
  20628. this.logger.warn("A registered UA is required for calling");
  20629. return;
  20630. }
  20631. if (this.state !== SimpleStatus.STATUS_NULL && this.state !== SimpleStatus.STATUS_COMPLETED) {
  20632. this.logger.warn("Cannot make more than a single call with Simple");
  20633. return;
  20634. }
  20635. // Safari hack, because you cannot call .play() from a non user action
  20636. if (this.options.media.remote.audio) {
  20637. this.options.media.remote.audio.autoplay = true;
  20638. }
  20639. if (this.options.media.remote.video) {
  20640. this.options.media.remote.video.autoplay = true;
  20641. }
  20642. if (this.options.media.local && this.options.media.local.video) {
  20643. this.options.media.local.video.autoplay = true;
  20644. this.options.media.local.video.volume = 0;
  20645. }
  20646. this.session = this.ua.invite(destination, {
  20647. sessionDescriptionHandlerOptions: {
  20648. constraints: {
  20649. audio: this.audio,
  20650. video: this.video
  20651. }
  20652. }
  20653. });
  20654. this.setupSession();
  20655. return this.session;
  20656. };
  20657. Simple.prototype.answer = function () {
  20658. if (this.state !== SimpleStatus.STATUS_NEW && this.state !== SimpleStatus.STATUS_CONNECTING) {
  20659. this.logger.warn("No call to answer");
  20660. return;
  20661. }
  20662. // Safari hack, because you cannot call .play() from a non user action
  20663. if (this.options.media.remote.audio) {
  20664. this.options.media.remote.audio.autoplay = true;
  20665. }
  20666. if (this.options.media.remote.video) {
  20667. this.options.media.remote.video.autoplay = true;
  20668. }
  20669. return this.session.accept({
  20670. sessionDescriptionHandlerOptions: {
  20671. constraints: {
  20672. audio: this.audio,
  20673. video: this.video
  20674. }
  20675. }
  20676. });
  20677. // emit call is active
  20678. };
  20679. Simple.prototype.reject = function () {
  20680. if (this.state !== SimpleStatus.STATUS_NEW && this.state !== SimpleStatus.STATUS_CONNECTING) {
  20681. this.logger.warn("Call is already answered");
  20682. return;
  20683. }
  20684. return this.session.reject();
  20685. };
  20686. Simple.prototype.hangup = function () {
  20687. if (this.state !== SimpleStatus.STATUS_CONNECTED &&
  20688. this.state !== SimpleStatus.STATUS_CONNECTING &&
  20689. this.state !== SimpleStatus.STATUS_NEW) {
  20690. this.logger.warn("No active call to hang up on");
  20691. return;
  20692. }
  20693. if (this.state !== SimpleStatus.STATUS_CONNECTED) {
  20694. return this.session.cancel();
  20695. }
  20696. else if (this.session) {
  20697. return this.session.bye();
  20698. }
  20699. };
  20700. Simple.prototype.hold = function () {
  20701. if (this.state !== SimpleStatus.STATUS_CONNECTED || !this.session || this.session.localHold) {
  20702. this.logger.warn("Cannot put call on hold");
  20703. return;
  20704. }
  20705. this.mute();
  20706. this.logger.log("Placing session on hold");
  20707. return this.session.hold();
  20708. };
  20709. Simple.prototype.unhold = function () {
  20710. if (this.state !== SimpleStatus.STATUS_CONNECTED || !this.session || !this.session.localHold) {
  20711. this.logger.warn("Cannot unhold a call that is not on hold");
  20712. return;
  20713. }
  20714. this.unmute();
  20715. this.logger.log("Placing call off hold");
  20716. return this.session.unhold();
  20717. };
  20718. Simple.prototype.mute = function () {
  20719. if (this.state !== SimpleStatus.STATUS_CONNECTED) {
  20720. this.logger.warn("An acitve call is required to mute audio");
  20721. return;
  20722. }
  20723. this.logger.log("Muting Audio");
  20724. this.toggleMute(true);
  20725. this.emit("mute", this);
  20726. };
  20727. Simple.prototype.unmute = function () {
  20728. if (this.state !== SimpleStatus.STATUS_CONNECTED) {
  20729. this.logger.warn("An active call is required to unmute audio");
  20730. return;
  20731. }
  20732. this.logger.log("Unmuting Audio");
  20733. this.toggleMute(false);
  20734. this.emit("unmute", this);
  20735. };
  20736. Simple.prototype.sendDTMF = function (tone) {
  20737. if (this.state !== SimpleStatus.STATUS_CONNECTED || !this.session) {
  20738. this.logger.warn("An active call is required to send a DTMF tone");
  20739. return;
  20740. }
  20741. this.logger.log("Sending DTMF tone: " + tone);
  20742. this.session.dtmf(tone);
  20743. };
  20744. Simple.prototype.message = function (destination, message) {
  20745. if (!this.ua || !this.checkRegistration()) {
  20746. this.logger.warn("A registered UA is required to send a message");
  20747. return;
  20748. }
  20749. if (!destination || !message) {
  20750. this.logger.warn("A destination and message are required to send a message");
  20751. return;
  20752. }
  20753. this.ua.message(destination, message);
  20754. };
  20755. // Private Helpers
  20756. Simple.prototype.checkRegistration = function () {
  20757. return (this.anonymous || (this.ua && this.ua.isRegistered()));
  20758. };
  20759. Simple.prototype.setupRemoteMedia = function () {
  20760. var _this = this;
  20761. if (!this.session) {
  20762. this.logger.warn("No session to set remote media on");
  20763. return;
  20764. }
  20765. // If there is a video track, it will attach the video and audio to the same element
  20766. var pc = this.session.sessionDescriptionHandler.peerConnection;
  20767. var remoteStream;
  20768. if (pc.getReceivers) {
  20769. remoteStream = new MediaStream();
  20770. pc.getReceivers().forEach(function (receiver) {
  20771. var track = receiver.track;
  20772. if (track) {
  20773. remoteStream.addTrack(track);
  20774. }
  20775. });
  20776. }
  20777. else {
  20778. remoteStream = pc.getRemoteStreams()[0];
  20779. }
  20780. if (this.video) {
  20781. this.options.media.remote.video.srcObject = remoteStream;
  20782. this.options.media.remote.video.play().catch(function () {
  20783. _this.logger.log("play was rejected");
  20784. });
  20785. }
  20786. else if (this.audio) {
  20787. this.options.media.remote.audio.srcObject = remoteStream;
  20788. this.options.media.remote.audio.play().catch(function () {
  20789. _this.logger.log("play was rejected");
  20790. });
  20791. }
  20792. };
  20793. Simple.prototype.setupLocalMedia = function () {
  20794. if (!this.session) {
  20795. this.logger.warn("No session to set local media on");
  20796. return;
  20797. }
  20798. if (this.video && this.options.media.local && this.options.media.local.video) {
  20799. var pc = this.session.sessionDescriptionHandler.peerConnection;
  20800. var localStream_1;
  20801. if (pc.getSenders) {
  20802. localStream_1 = new MediaStream();
  20803. pc.getSenders().forEach(function (sender) {
  20804. var track = sender.track;
  20805. if (track && track.kind === "video") {
  20806. localStream_1.addTrack(track);
  20807. }
  20808. });
  20809. }
  20810. else {
  20811. localStream_1 = pc.getLocalStreams()[0];
  20812. }
  20813. this.options.media.local.video.srcObject = localStream_1;
  20814. this.options.media.local.video.volume = 0;
  20815. this.options.media.local.video.play();
  20816. }
  20817. };
  20818. Simple.prototype.cleanupMedia = function () {
  20819. if (this.video) {
  20820. this.options.media.remote.video.srcObject = null;
  20821. this.options.media.remote.video.pause();
  20822. if (this.options.media.local && this.options.media.local.video) {
  20823. this.options.media.local.video.srcObject = null;
  20824. this.options.media.local.video.pause();
  20825. }
  20826. }
  20827. if (this.audio) {
  20828. this.options.media.remote.audio.srcObject = null;
  20829. this.options.media.remote.audio.pause();
  20830. }
  20831. };
  20832. Simple.prototype.setupSession = function () {
  20833. var _this = this;
  20834. if (!this.session) {
  20835. this.logger.warn("No session to set up");
  20836. return;
  20837. }
  20838. this.state = SimpleStatus.STATUS_NEW;
  20839. this.emit("new", this.session);
  20840. this.session.on("progress", function () { return _this.onProgress(); });
  20841. this.session.on("accepted", function () { return _this.onAccepted(); });
  20842. this.session.on("rejected", function () { return _this.onEnded(); });
  20843. this.session.on("failed", function () { return _this.onFailed(); });
  20844. this.session.on("terminated", function () { return _this.onEnded(); });
  20845. };
  20846. Simple.prototype.destroyMedia = function () {
  20847. if (this.session && this.session.sessionDescriptionHandler) {
  20848. this.session.sessionDescriptionHandler.close();
  20849. }
  20850. };
  20851. Simple.prototype.toggleMute = function (mute) {
  20852. if (!this.session) {
  20853. this.logger.warn("No session to toggle mute");
  20854. return;
  20855. }
  20856. var pc = this.session.sessionDescriptionHandler.peerConnection;
  20857. if (pc.getSenders) {
  20858. pc.getSenders().forEach(function (sender) {
  20859. if (sender.track) {
  20860. sender.track.enabled = !mute;
  20861. }
  20862. });
  20863. }
  20864. else {
  20865. pc.getLocalStreams().forEach(function (stream) {
  20866. stream.getAudioTracks().forEach(function (track) {
  20867. track.enabled = !mute;
  20868. });
  20869. stream.getVideoTracks().forEach(function (track) {
  20870. track.enabled = !mute;
  20871. });
  20872. });
  20873. }
  20874. };
  20875. Simple.prototype.onAccepted = function () {
  20876. var _this = this;
  20877. if (!this.session) {
  20878. this.logger.warn("No session for accepting");
  20879. return;
  20880. }
  20881. this.state = SimpleStatus.STATUS_CONNECTED;
  20882. this.emit("connected", this.session);
  20883. this.setupLocalMedia();
  20884. this.setupRemoteMedia();
  20885. if (this.session.sessionDescriptionHandler) {
  20886. this.session.sessionDescriptionHandler.on("addTrack", function () {
  20887. _this.logger.log("A track has been added, triggering new remoteMedia setup");
  20888. _this.setupRemoteMedia();
  20889. });
  20890. this.session.sessionDescriptionHandler.on("addStream", function () {
  20891. _this.logger.log("A stream has been added, trigger new remoteMedia setup");
  20892. _this.setupRemoteMedia();
  20893. });
  20894. }
  20895. this.session.on("dtmf", function (request, dtmf) {
  20896. _this.emit("dtmf", dtmf.tone);
  20897. });
  20898. this.session.on("bye", function () { return _this.onEnded(); });
  20899. };
  20900. Simple.prototype.onProgress = function () {
  20901. this.state = SimpleStatus.STATUS_CONNECTING;
  20902. this.emit("connecting", this.session);
  20903. };
  20904. Simple.prototype.onFailed = function () {
  20905. this.onEnded();
  20906. };
  20907. Simple.prototype.onEnded = function () {
  20908. this.state = SimpleStatus.STATUS_COMPLETED;
  20909. this.emit("ended", this.session);
  20910. this.cleanupMedia();
  20911. };
  20912. Simple.C = SimpleStatus;
  20913. return Simple;
  20914. }(events_1.EventEmitter));
  20915. exports.Simple = Simple;
  20916. /***/ })
  20917. /******/ ]);
  20918. });