ue-softphone-sdk 2.2.3 → 2.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/dist/api/bye.d.ts +16 -0
  2. package/dist/api/dtmf.d.ts +15 -0
  3. package/dist/api/emitter.d.ts +88 -0
  4. package/dist/api/exceptions/content-type-unsupported.d.ts +8 -0
  5. package/dist/api/exceptions/index.d.ts +5 -0
  6. package/dist/api/exceptions/request-pending.d.ts +9 -0
  7. package/dist/api/exceptions/session-description-handler.d.ts +8 -0
  8. package/dist/api/exceptions/session-terminated.d.ts +8 -0
  9. package/dist/api/exceptions/state-transition.d.ts +8 -0
  10. package/dist/api/index.d.ts +58 -0
  11. package/dist/api/info.d.ts +16 -0
  12. package/dist/api/invitation-accept-options.d.ts +19 -0
  13. package/dist/api/invitation-progress-options.d.ts +38 -0
  14. package/dist/api/invitation-reject-options.d.ts +25 -0
  15. package/dist/api/invitation.d.ts +179 -0
  16. package/dist/api/inviter-cancel-options.d.ts +9 -0
  17. package/dist/api/inviter-invite-options.d.ts +28 -0
  18. package/dist/api/inviter-options.d.ts +43 -0
  19. package/dist/api/inviter.d.ts +236 -0
  20. package/dist/api/message.d.ts +16 -0
  21. package/dist/api/messager-message-options.d.ts +11 -0
  22. package/dist/api/messager-options.d.ts +17 -0
  23. package/dist/api/messager.d.ts +26 -0
  24. package/dist/api/notification.d.ts +16 -0
  25. package/dist/api/notifier.d.ts +8 -0
  26. package/dist/api/publisher-options.d.ts +33 -0
  27. package/dist/api/publisher-publish-options.d.ts +6 -0
  28. package/dist/api/publisher-state.d.ts +21 -0
  29. package/dist/api/publisher-unpublish-options.d.ts +6 -0
  30. package/dist/api/publisher.d.ts +65 -0
  31. package/dist/api/referral.d.ts +38 -0
  32. package/dist/api/registerer-options.d.ts +46 -0
  33. package/dist/api/registerer-register-options.d.ts +11 -0
  34. package/dist/api/registerer-state.d.ts +21 -0
  35. package/dist/api/registerer-unregister-options.d.ts +16 -0
  36. package/dist/api/registerer.d.ts +144 -0
  37. package/dist/api/session-bye-options.d.ts +11 -0
  38. package/dist/api/session-delegate.d.ts +73 -0
  39. package/dist/api/session-description-handler-factory.d.ts +15 -0
  40. package/dist/api/session-description-handler.d.ts +74 -0
  41. package/dist/api/session-info-options.d.ts +11 -0
  42. package/dist/api/session-invite-options.d.ts +28 -0
  43. package/dist/api/session-message-options.d.ts +11 -0
  44. package/dist/api/session-options.d.ts +8 -0
  45. package/dist/api/session-refer-options.d.ts +14 -0
  46. package/dist/api/session-state.d.ts +45 -0
  47. package/dist/api/session.d.ts +359 -0
  48. package/dist/api/subscriber-options.d.ts +11 -0
  49. package/dist/api/subscriber-subscribe-options.d.ts +6 -0
  50. package/dist/api/subscriber.d.ts +94 -0
  51. package/dist/api/subscription-delegate.d.ts +12 -0
  52. package/dist/api/subscription-options.d.ts +8 -0
  53. package/dist/api/subscription-state.d.ts +19 -0
  54. package/dist/api/subscription-subscribe-options.d.ts +6 -0
  55. package/dist/api/subscription-unsubscribe-options.d.ts +6 -0
  56. package/dist/api/subscription.d.ts +84 -0
  57. package/dist/api/transport-state.d.ts +37 -0
  58. package/dist/api/transport.d.ts +159 -0
  59. package/dist/api/user-agent-delegate.d.ts +84 -0
  60. package/dist/api/user-agent-options.d.ts +253 -0
  61. package/dist/api/user-agent-state.d.ts +14 -0
  62. package/dist/api/user-agent.d.ts +200 -0
  63. package/dist/core/dialogs/dialog-state.d.ts +34 -0
  64. package/dist/core/dialogs/dialog.d.ts +161 -0
  65. package/dist/core/dialogs/index.d.ts +4 -0
  66. package/dist/core/dialogs/session-dialog.d.ts +196 -0
  67. package/dist/core/dialogs/subscription-dialog.d.ts +120 -0
  68. package/dist/core/exceptions/exception.d.ts +8 -0
  69. package/dist/core/exceptions/index.d.ts +3 -0
  70. package/dist/core/exceptions/transaction-state-error.d.ts +8 -0
  71. package/dist/core/exceptions/transport-error.d.ts +8 -0
  72. package/dist/core/index.d.ts +15 -0
  73. package/dist/core/log/index.d.ts +3 -0
  74. package/dist/core/log/levels.d.ts +10 -0
  75. package/dist/core/log/logger-factory.d.ts +21 -0
  76. package/dist/core/log/logger.d.ts +19 -0
  77. package/dist/core/messages/body.d.ts +64 -0
  78. package/dist/core/messages/digest-authentication.d.ts +51 -0
  79. package/dist/core/messages/incoming-message.d.ts +79 -0
  80. package/dist/core/messages/incoming-request-message.d.ts +10 -0
  81. package/dist/core/messages/incoming-request.d.ts +67 -0
  82. package/dist/core/messages/incoming-response-message.d.ts +10 -0
  83. package/dist/core/messages/incoming-response.d.ts +12 -0
  84. package/dist/core/messages/index.d.ts +13 -0
  85. package/dist/core/messages/md5.d.ts +32 -0
  86. package/dist/core/messages/methods/ack.d.ts +18 -0
  87. package/dist/core/messages/methods/bye.d.ts +21 -0
  88. package/dist/core/messages/methods/cancel.d.ts +21 -0
  89. package/dist/core/messages/methods/constants.d.ts +20 -0
  90. package/dist/core/messages/methods/index.d.ts +13 -0
  91. package/dist/core/messages/methods/info.d.ts +21 -0
  92. package/dist/core/messages/methods/invite.d.ts +86 -0
  93. package/dist/core/messages/methods/message.d.ts +21 -0
  94. package/dist/core/messages/methods/notify.d.ts +21 -0
  95. package/dist/core/messages/methods/prack.d.ts +21 -0
  96. package/dist/core/messages/methods/publish.d.ts +21 -0
  97. package/dist/core/messages/methods/refer.d.ts +21 -0
  98. package/dist/core/messages/methods/register.d.ts +21 -0
  99. package/dist/core/messages/methods/subscribe.d.ts +54 -0
  100. package/dist/core/messages/outgoing-request-message.d.ts +94 -0
  101. package/dist/core/messages/outgoing-request.d.ts +67 -0
  102. package/dist/core/messages/outgoing-response.d.ts +42 -0
  103. package/dist/core/messages/parser.d.ts +14 -0
  104. package/dist/core/messages/utils.d.ts +24 -0
  105. package/dist/core/session/index.d.ts +2 -0
  106. package/dist/core/session/session-delegate.d.ts +70 -0
  107. package/dist/core/session/session.d.ts +134 -0
  108. package/dist/core/subscription/index.d.ts +2 -0
  109. package/dist/core/subscription/subscription-delegate.d.ts +27 -0
  110. package/dist/core/subscription/subscription.d.ts +55 -0
  111. package/dist/core/timers.d.ts +20 -0
  112. package/dist/core/transactions/client-transaction.d.ts +45 -0
  113. package/dist/core/transactions/index.d.ts +10 -0
  114. package/dist/core/transactions/invite-client-transaction.d.ts +116 -0
  115. package/dist/core/transactions/invite-server-transaction.d.ts +127 -0
  116. package/dist/core/transactions/non-invite-client-transaction.d.ts +69 -0
  117. package/dist/core/transactions/non-invite-server-transaction.d.ts +57 -0
  118. package/dist/core/transactions/server-transaction.d.ts +35 -0
  119. package/dist/core/transactions/transaction-state.d.ts +13 -0
  120. package/dist/core/transactions/transaction-user.d.ts +72 -0
  121. package/dist/core/transactions/transaction.d.ts +79 -0
  122. package/dist/core/transport.d.ts +31 -0
  123. package/dist/core/user-agent-core/allowed-methods.d.ts +4 -0
  124. package/dist/core/user-agent-core/index.d.ts +3 -0
  125. package/dist/core/user-agent-core/user-agent-core-configuration.d.ts +99 -0
  126. package/dist/core/user-agent-core/user-agent-core-delegate.d.ts +37 -0
  127. package/dist/core/user-agent-core/user-agent-core.d.ts +179 -0
  128. package/dist/core/user-agents/bye-user-agent-client.d.ts +10 -0
  129. package/dist/core/user-agents/bye-user-agent-server.d.ts +10 -0
  130. package/dist/core/user-agents/cancel-user-agent-client.d.ts +10 -0
  131. package/dist/core/user-agents/index.d.ts +26 -0
  132. package/dist/core/user-agents/info-user-agent-client.d.ts +10 -0
  133. package/dist/core/user-agents/info-user-agent-server.d.ts +10 -0
  134. package/dist/core/user-agents/invite-user-agent-client.d.ts +35 -0
  135. package/dist/core/user-agents/invite-user-agent-server.d.ts +77 -0
  136. package/dist/core/user-agents/message-user-agent-client.d.ts +10 -0
  137. package/dist/core/user-agents/message-user-agent-server.d.ts +10 -0
  138. package/dist/core/user-agents/notify-user-agent-client.d.ts +10 -0
  139. package/dist/core/user-agents/notify-user-agent-server.d.ts +16 -0
  140. package/dist/core/user-agents/prack-user-agent-client.d.ts +10 -0
  141. package/dist/core/user-agents/prack-user-agent-server.d.ts +16 -0
  142. package/dist/core/user-agents/publish-user-agent-client.d.ts +10 -0
  143. package/dist/core/user-agents/re-invite-user-agent-client.d.ts +18 -0
  144. package/dist/core/user-agents/re-invite-user-agent-server.d.ts +41 -0
  145. package/dist/core/user-agents/re-subscribe-user-agent-client.d.ts +17 -0
  146. package/dist/core/user-agents/re-subscribe-user-agent-server.d.ts +10 -0
  147. package/dist/core/user-agents/refer-user-agent-client.d.ts +10 -0
  148. package/dist/core/user-agents/refer-user-agent-server.d.ts +16 -0
  149. package/dist/core/user-agents/register-user-agent-client.d.ts +10 -0
  150. package/dist/core/user-agents/register-user-agent-server.d.ts +11 -0
  151. package/dist/core/user-agents/subscribe-user-agent-client.d.ts +65 -0
  152. package/dist/core/user-agents/subscribe-user-agent-server.d.ts +11 -0
  153. package/dist/core/user-agents/user-agent-client.d.ts +103 -0
  154. package/dist/core/user-agents/user-agent-server.d.ts +79 -0
  155. package/dist/grammar/grammar.d.ts +26 -0
  156. package/dist/grammar/index.d.ts +4 -0
  157. package/dist/grammar/name-addr-header.d.ts +24 -0
  158. package/dist/grammar/parameters.d.ts +16 -0
  159. package/dist/grammar/pegjs/dist/grammar.d.ts +50 -0
  160. package/dist/grammar/uri.d.ts +62 -0
  161. package/dist/{types/index.d.ts → index.d.ts} +7 -3
  162. package/dist/main.d.ts +9 -0
  163. package/dist/new-index.d.ts +199 -0
  164. package/dist/platform/web/index.d.ts +4 -0
  165. package/dist/platform/web/modifiers/index.d.ts +5 -0
  166. package/dist/platform/web/modifiers/modifiers.d.ts +41 -0
  167. package/dist/platform/web/session-description-handler/index.d.ts +14 -0
  168. package/dist/platform/web/session-description-handler/media-stream-factory-default.d.ts +6 -0
  169. package/dist/platform/web/session-description-handler/media-stream-factory.d.ts +6 -0
  170. package/dist/platform/web/session-description-handler/peer-connection-configuration-default.d.ts +5 -0
  171. package/dist/platform/web/session-description-handler/peer-connection-delegate.d.ts +63 -0
  172. package/dist/platform/web/session-description-handler/session-description-handler-configuration.d.ts +16 -0
  173. package/dist/platform/web/session-description-handler/session-description-handler-factory-default.d.ts +11 -0
  174. package/dist/platform/web/session-description-handler/session-description-handler-factory-options.d.ts +9 -0
  175. package/dist/platform/web/session-description-handler/session-description-handler-factory.d.ts +16 -0
  176. package/dist/platform/web/session-description-handler/session-description-handler-options.d.ts +47 -0
  177. package/dist/platform/web/session-description-handler/session-description-handler.d.ts +212 -0
  178. package/dist/platform/web/simple-user/index.d.ts +7 -0
  179. package/dist/platform/web/simple-user/simple-user-delegate.d.ts +72 -0
  180. package/dist/platform/web/simple-user/simple-user-options.d.ts +90 -0
  181. package/dist/platform/web/simple-user/simple-user.d.ts +226 -0
  182. package/dist/platform/web/transport/index.d.ts +6 -0
  183. package/dist/platform/web/transport/transport-options.d.ts +30 -0
  184. package/dist/platform/web/transport/transport.d.ts +125 -0
  185. package/dist/ue-softphone-sdk.js +2 -1
  186. package/dist/ue-softphone-sdk.js.map +1 -0
  187. package/dist/version.d.ts +1 -0
  188. package/dist/webPhoneSdk.d.ts +24 -0
  189. package/dist/webrtc.d.ts +17 -0
  190. package/{rollup-new.config.mjs → new-rollup.config.mjs} +1 -1
  191. package/package.json +6 -6
  192. package/rollup.config.js +15 -14
  193. package/src/api/api-extractor.json +358 -0
  194. package/src/api/bye.ts +27 -0
  195. package/src/api/dtmf.ts +27 -0
  196. package/src/api/emitter.ts +110 -0
  197. package/src/api/exceptions/content-type-unsupported.ts +11 -0
  198. package/src/api/exceptions/index.ts +5 -0
  199. package/src/api/exceptions/request-pending.ts +12 -0
  200. package/src/api/exceptions/session-description-handler.ts +11 -0
  201. package/src/api/exceptions/session-terminated.ts +11 -0
  202. package/src/api/exceptions/state-transition.ts +11 -0
  203. package/src/api/index.ts +58 -0
  204. package/src/api/info.ts +27 -0
  205. package/src/api/invitation-accept-options.ts +20 -0
  206. package/src/api/invitation-progress-options.ts +36 -0
  207. package/src/api/invitation-reject-options.ts +22 -0
  208. package/src/api/invitation.ts +816 -0
  209. package/src/api/inviter-cancel-options.ts +9 -0
  210. package/src/api/inviter-invite-options.ts +29 -0
  211. package/src/api/inviter-options.ts +44 -0
  212. package/src/api/inviter.ts +1126 -0
  213. package/src/api/message.ts +27 -0
  214. package/src/api/messager-message-options.ts +12 -0
  215. package/src/api/messager-options.ts +18 -0
  216. package/src/api/messager.ts +89 -0
  217. package/src/api/notification.ts +27 -0
  218. package/src/api/notifier.ts +7 -0
  219. package/src/api/publisher-options.ts +34 -0
  220. package/src/api/publisher-publish-options.ts +6 -0
  221. package/src/api/publisher-state.ts +21 -0
  222. package/src/api/publisher-unpublish-options.ts +6 -0
  223. package/src/api/publisher.ts +418 -0
  224. package/src/api/referral.ts +89 -0
  225. package/src/api/registerer-options.ts +55 -0
  226. package/src/api/registerer-register-options.ts +12 -0
  227. package/src/api/registerer-state.ts +21 -0
  228. package/src/api/registerer-unregister-options.ts +17 -0
  229. package/src/api/registerer.ts +814 -0
  230. package/src/api/session-bye-options.ts +12 -0
  231. package/src/api/session-delegate.ts +80 -0
  232. package/src/api/session-description-handler-factory.ts +16 -0
  233. package/src/api/session-description-handler.ts +89 -0
  234. package/src/api/session-info-options.ts +12 -0
  235. package/src/api/session-invite-options.ts +29 -0
  236. package/src/api/session-message-options.ts +12 -0
  237. package/src/api/session-options.ts +8 -0
  238. package/src/api/session-refer-options.ts +15 -0
  239. package/src/api/session-state.ts +45 -0
  240. package/src/api/session.ts +1448 -0
  241. package/src/api/subscriber-options.ts +12 -0
  242. package/src/api/subscriber-subscribe-options.ts +6 -0
  243. package/src/api/subscriber.ts +536 -0
  244. package/src/api/subscription-delegate.ts +13 -0
  245. package/src/api/subscription-options.ts +8 -0
  246. package/src/api/subscription-state.ts +19 -0
  247. package/src/api/subscription-subscribe-options.ts +6 -0
  248. package/src/api/subscription-unsubscribe-options.ts +6 -0
  249. package/src/api/subscription.ts +161 -0
  250. package/src/api/transport-state.ts +37 -0
  251. package/src/api/transport.ts +169 -0
  252. package/src/api/user-agent-delegate.ts +95 -0
  253. package/src/api/user-agent-options.ts +322 -0
  254. package/src/api/user-agent-state.ts +14 -0
  255. package/src/api/user-agent.ts +1014 -0
  256. package/src/core/api-extractor.json +358 -0
  257. package/src/core/dialogs/dialog-state.ts +35 -0
  258. package/src/core/dialogs/dialog.ts +605 -0
  259. package/src/core/dialogs/index.ts +4 -0
  260. package/src/core/dialogs/session-dialog.ts +996 -0
  261. package/src/core/dialogs/subscription-dialog.ts +557 -0
  262. package/src/core/exceptions/exception.ts +11 -0
  263. package/src/core/exceptions/index.ts +3 -0
  264. package/src/core/exceptions/transaction-state-error.ts +11 -0
  265. package/src/core/exceptions/transport-error.ts +11 -0
  266. package/src/core/index.ts +19 -0
  267. package/src/core/log/index.ts +3 -0
  268. package/src/core/log/levels.ts +10 -0
  269. package/src/core/log/logger-factory.ts +119 -0
  270. package/src/core/log/logger.ts +42 -0
  271. package/src/core/messages/body.ts +171 -0
  272. package/src/core/messages/digest-authentication.ts +190 -0
  273. package/src/core/messages/incoming-message.ts +152 -0
  274. package/src/core/messages/incoming-request-message.ts +14 -0
  275. package/src/core/messages/incoming-request.ts +75 -0
  276. package/src/core/messages/incoming-response-message.ts +14 -0
  277. package/src/core/messages/incoming-response.ts +13 -0
  278. package/src/core/messages/index.ts +18 -0
  279. package/src/core/messages/md5.ts +437 -0
  280. package/src/core/messages/methods/ack.ts +22 -0
  281. package/src/core/messages/methods/bye.ts +22 -0
  282. package/src/core/messages/methods/cancel.ts +22 -0
  283. package/src/core/messages/methods/constants.ts +21 -0
  284. package/src/core/messages/methods/index.ts +13 -0
  285. package/src/core/messages/methods/info.ts +22 -0
  286. package/src/core/messages/methods/invite.ts +104 -0
  287. package/src/core/messages/methods/message.ts +22 -0
  288. package/src/core/messages/methods/notify.ts +22 -0
  289. package/src/core/messages/methods/prack.ts +22 -0
  290. package/src/core/messages/methods/publish.ts +22 -0
  291. package/src/core/messages/methods/refer.ts +22 -0
  292. package/src/core/messages/methods/register.ts +22 -0
  293. package/src/core/messages/methods/subscribe.ts +59 -0
  294. package/src/core/messages/outgoing-request-message.ts +299 -0
  295. package/src/core/messages/outgoing-request.ts +77 -0
  296. package/src/core/messages/outgoing-response.ts +174 -0
  297. package/src/core/messages/parser.ts +265 -0
  298. package/src/core/messages/utils.ts +144 -0
  299. package/src/core/session/index.ts +2 -0
  300. package/src/core/session/session-delegate.ts +88 -0
  301. package/src/core/session/session.ts +158 -0
  302. package/src/core/subscription/index.ts +2 -0
  303. package/src/core/subscription/subscription-delegate.ts +30 -0
  304. package/src/core/subscription/subscription.ts +61 -0
  305. package/src/core/timers.ts +24 -0
  306. package/src/core/transactions/client-transaction.ts +78 -0
  307. package/src/core/transactions/index.ts +10 -0
  308. package/src/core/transactions/invite-client-transaction.ts +504 -0
  309. package/src/core/transactions/invite-server-transaction.ts +432 -0
  310. package/src/core/transactions/non-invite-client-transaction.ts +257 -0
  311. package/src/core/transactions/non-invite-server-transaction.ts +241 -0
  312. package/src/core/transactions/server-transaction.ts +47 -0
  313. package/src/core/transactions/transaction-state.ts +13 -0
  314. package/src/core/transactions/transaction-user.ts +82 -0
  315. package/src/core/transactions/transaction.ts +149 -0
  316. package/src/core/transport.ts +32 -0
  317. package/src/core/user-agent-core/allowed-methods.ts +19 -0
  318. package/src/core/user-agent-core/index.ts +3 -0
  319. package/src/core/user-agent-core/user-agent-core-configuration.ts +111 -0
  320. package/src/core/user-agent-core/user-agent-core-delegate.ts +50 -0
  321. package/src/core/user-agent-core/user-agent-core.ts +905 -0
  322. package/src/core/user-agents/bye-user-agent-client.ts +16 -0
  323. package/src/core/user-agents/bye-user-agent-server.ts +14 -0
  324. package/src/core/user-agents/cancel-user-agent-client.ts +14 -0
  325. package/src/core/user-agents/index.ts +26 -0
  326. package/src/core/user-agents/info-user-agent-client.ts +15 -0
  327. package/src/core/user-agents/info-user-agent-server.ts +14 -0
  328. package/src/core/user-agents/invite-user-agent-client.ts +405 -0
  329. package/src/core/user-agents/invite-user-agent-server.ts +269 -0
  330. package/src/core/user-agents/message-user-agent-client.ts +14 -0
  331. package/src/core/user-agents/message-user-agent-server.ts +14 -0
  332. package/src/core/user-agents/notify-user-agent-client.ts +15 -0
  333. package/src/core/user-agents/notify-user-agent-server.ts +30 -0
  334. package/src/core/user-agents/prack-user-agent-client.ts +16 -0
  335. package/src/core/user-agents/prack-user-agent-server.ts +37 -0
  336. package/src/core/user-agents/publish-user-agent-client.ts +14 -0
  337. package/src/core/user-agents/re-invite-user-agent-client.ts +127 -0
  338. package/src/core/user-agents/re-invite-user-agent-server.ts +109 -0
  339. package/src/core/user-agents/re-subscribe-user-agent-client.ts +78 -0
  340. package/src/core/user-agents/re-subscribe-user-agent-server.ts +14 -0
  341. package/src/core/user-agents/refer-user-agent-client.ts +15 -0
  342. package/src/core/user-agents/refer-user-agent-server.ts +30 -0
  343. package/src/core/user-agents/register-user-agent-client.ts +14 -0
  344. package/src/core/user-agents/register-user-agent-server.ts +14 -0
  345. package/src/core/user-agents/subscribe-user-agent-client.ts +341 -0
  346. package/src/core/user-agents/subscribe-user-agent-server.ts +14 -0
  347. package/src/core/user-agents/user-agent-client.ts +378 -0
  348. package/src/core/user-agents/user-agent-server.ts +276 -0
  349. package/src/grammar/grammar.ts +55 -0
  350. package/src/grammar/index.ts +4 -0
  351. package/src/grammar/name-addr-header.ts +58 -0
  352. package/src/grammar/parameters.ts +45 -0
  353. package/src/grammar/pegjs/README.md +9 -0
  354. package/src/grammar/pegjs/dist/grammar.ts +1557 -0
  355. package/src/grammar/pegjs/src/grammar.pegjs +1009 -0
  356. package/src/grammar/uri.ts +370 -0
  357. package/src/index.ts +49 -26
  358. package/src/lib/socket.io.esm.min.js +7 -0
  359. package/src/main.ts +26 -0
  360. package/src/new-index.ts +2478 -0
  361. package/src/platform/react/README.md +1 -0
  362. package/src/platform/web/index.ts +4 -0
  363. package/src/platform/web/modifiers/index.ts +5 -0
  364. package/src/platform/web/modifiers/modifiers.ts +180 -0
  365. package/src/platform/web/session-description-handler/api-extractor.json +358 -0
  366. package/src/platform/web/session-description-handler/index.ts +14 -0
  367. package/src/platform/web/session-description-handler/media-stream-factory-default.ts +22 -0
  368. package/src/platform/web/session-description-handler/media-stream-factory.ts +10 -0
  369. package/src/platform/web/session-description-handler/peer-connection-configuration-default.ts +17 -0
  370. package/src/platform/web/session-description-handler/peer-connection-delegate.ts +72 -0
  371. package/src/platform/web/session-description-handler/session-description-handler-configuration.ts +17 -0
  372. package/src/platform/web/session-description-handler/session-description-handler-factory-default.ts +45 -0
  373. package/src/platform/web/session-description-handler/session-description-handler-factory-options.ts +10 -0
  374. package/src/platform/web/session-description-handler/session-description-handler-factory.ts +17 -0
  375. package/src/platform/web/session-description-handler/session-description-handler-options.ts +56 -0
  376. package/src/platform/web/session-description-handler/session-description-handler.ts +938 -0
  377. package/src/platform/web/simple-user/api-extractor.json +358 -0
  378. package/src/platform/web/simple-user/index.ts +7 -0
  379. package/src/platform/web/simple-user/simple-user-delegate.ts +82 -0
  380. package/src/platform/web/simple-user/simple-user-options.ts +102 -0
  381. package/src/platform/web/simple-user/simple-user.ts +1099 -0
  382. package/src/platform/web/transport/api-extractor.json +358 -0
  383. package/src/platform/web/transport/index.ts +6 -0
  384. package/src/platform/web/transport/transport-options.ts +34 -0
  385. package/src/platform/web/transport/transport.ts +742 -0
  386. package/src/version.ts +8 -0
  387. package/src/webPhoneSdk.ts +67 -0
  388. package/src/webrtc.ts +318 -0
  389. package/tsconfig.json +26 -10
  390. /package/dist/{types/config.d.ts → config.d.ts} +0 -0
@@ -0,0 +1,1126 @@
1
+ import {
2
+ AckableIncomingResponseWithSession,
3
+ Body,
4
+ C,
5
+ Grammar,
6
+ IncomingResponse,
7
+ Logger,
8
+ NameAddrHeader,
9
+ OutgoingInviteRequest,
10
+ OutgoingRequestMessage,
11
+ OutgoingRequestMessageOptions,
12
+ PrackableIncomingResponseWithSession,
13
+ RequestOptions,
14
+ Session as SessionDialog,
15
+ SignalingState,
16
+ URI
17
+ } from "../core";
18
+ import { getReasonPhrase, newTag } from "../core/messages/utils";
19
+ import { InviterCancelOptions } from "./inviter-cancel-options";
20
+ import { InviterInviteOptions } from "./inviter-invite-options";
21
+ import { InviterOptions } from "./inviter-options";
22
+ import { Session } from "./session";
23
+ import { BodyAndContentType, SessionDescriptionHandler } from "./session-description-handler";
24
+ import { SessionState } from "./session-state";
25
+ import { UserAgent } from "./user-agent";
26
+ import { SIPExtension } from "./user-agent-options";
27
+
28
+ /**
29
+ * An inviter offers to establish a {@link Session} (outgoing INVITE).
30
+ * @public
31
+ */
32
+ export class Inviter extends Session {
33
+ /**
34
+ * If this Inviter was created as a result of a REFER, the referred Session. Otherwise undefined.
35
+ * @internal
36
+ */
37
+ public _referred: Session | undefined;
38
+
39
+ /**
40
+ * Logger.
41
+ */
42
+ protected logger: Logger;
43
+
44
+ /** @internal */
45
+ protected _id: string;
46
+
47
+ /** True if dispose() has been called. */
48
+ private disposed = false;
49
+ /** True if early media use is enabled. */
50
+ private earlyMedia = false;
51
+ /** The early media session. */
52
+ private earlyMediaDialog: SessionDialog | undefined;
53
+ /** The early media session description handlers. */
54
+ private earlyMediaSessionDescriptionHandlers = new Map<string, SessionDescriptionHandler>();
55
+ /** Our From tag. */
56
+ private fromTag: string;
57
+ /** True if cancel() was called. */
58
+ private isCanceled = false;
59
+ /** True if initial INVITE without SDP. */
60
+ private inviteWithoutSdp = false;
61
+ /** Initial INVITE request sent by core. Undefined until sent. */
62
+ private outgoingInviteRequest: OutgoingInviteRequest | undefined;
63
+ /** Initial INVITE message provided to core to send. */
64
+ private outgoingRequestMessage: OutgoingRequestMessage;
65
+
66
+ /**
67
+ * Constructs a new instance of the `Inviter` class.
68
+ * @param userAgent - User agent. See {@link UserAgent} for details.
69
+ * @param targetURI - Request URI identifying the target of the message.
70
+ * @param options - Options bucket. See {@link InviterOptions} for details.
71
+ */
72
+ public constructor(userAgent: UserAgent, targetURI: URI, options: InviterOptions = {}) {
73
+ super(userAgent, options);
74
+
75
+ this.logger = userAgent.getLogger("sip.Inviter");
76
+
77
+ // Early media
78
+ this.earlyMedia = options.earlyMedia !== undefined ? options.earlyMedia : this.earlyMedia;
79
+
80
+ // From tag
81
+ this.fromTag = newTag();
82
+
83
+ // Invite without SDP
84
+ this.inviteWithoutSdp = options.inviteWithoutSdp !== undefined ? options.inviteWithoutSdp : this.inviteWithoutSdp;
85
+
86
+ // Inviter options (could do better copying these options)
87
+ const inviterOptions: InviterOptions = { ...options };
88
+ inviterOptions.params = { ...options.params };
89
+
90
+ // Anonymous call
91
+ const anonymous = options.anonymous || false;
92
+
93
+ // Contact
94
+ const contact = userAgent.contact.toString({
95
+ anonymous,
96
+ // Do not add ;ob in initial forming dialog requests if the
97
+ // registration over the current connection got a GRUU URI.
98
+ outbound: anonymous ? !userAgent.contact.tempGruu : !userAgent.contact.pubGruu
99
+ });
100
+
101
+ // FIXME: TODO: We should not be parsing URIs here as if it fails we have to throw an exception
102
+ // which is not something we want our constructor to do. URIs should be passed in as params.
103
+ // URIs
104
+ if (anonymous && userAgent.configuration.uri) {
105
+ inviterOptions.params.fromDisplayName = "Anonymous";
106
+ inviterOptions.params.fromUri = "sip:anonymous@anonymous.invalid";
107
+ }
108
+ let fromURI: URI | undefined = userAgent.userAgentCore.configuration.aor;
109
+ if (inviterOptions.params.fromUri) {
110
+ fromURI =
111
+ typeof inviterOptions.params.fromUri === "string"
112
+ ? Grammar.URIParse(inviterOptions.params.fromUri)
113
+ : inviterOptions.params.fromUri;
114
+ }
115
+ if (!fromURI) {
116
+ throw new TypeError("Invalid from URI: " + inviterOptions.params.fromUri);
117
+ }
118
+ let toURI: URI | undefined = targetURI;
119
+ if (inviterOptions.params.toUri) {
120
+ toURI =
121
+ typeof inviterOptions.params.toUri === "string"
122
+ ? Grammar.URIParse(inviterOptions.params.toUri)
123
+ : inviterOptions.params.toUri;
124
+ }
125
+ if (!toURI) {
126
+ throw new TypeError("Invalid to URI: " + inviterOptions.params.toUri);
127
+ }
128
+
129
+ // Params
130
+ const messageOptions: OutgoingRequestMessageOptions = { ...inviterOptions.params };
131
+ messageOptions.fromTag = this.fromTag;
132
+
133
+ // Extra headers
134
+ const extraHeaders: Array<string> = (inviterOptions.extraHeaders || []).slice();
135
+ if (anonymous && userAgent.configuration.uri) {
136
+ extraHeaders.push("P-Preferred-Identity: " + userAgent.configuration.uri.toString());
137
+ extraHeaders.push("Privacy: id");
138
+ }
139
+ extraHeaders.push("Contact: " + contact);
140
+ extraHeaders.push(
141
+ "Allow: " + ["ACK", "CANCEL", "INVITE", "MESSAGE", "BYE", "OPTIONS", "INFO", "NOTIFY", "REFER"].toString()
142
+ );
143
+ if (userAgent.configuration.sipExtension100rel === SIPExtension.Required) {
144
+ extraHeaders.push("Require: 100rel");
145
+ }
146
+ if (userAgent.configuration.sipExtensionReplaces === SIPExtension.Required) {
147
+ extraHeaders.push("Require: replaces");
148
+ }
149
+ inviterOptions.extraHeaders = extraHeaders;
150
+
151
+ // Body
152
+ const body: Body | undefined = undefined;
153
+
154
+ // Make initial outgoing request message
155
+ this.outgoingRequestMessage = userAgent.userAgentCore.makeOutgoingRequestMessage(
156
+ C.INVITE,
157
+ targetURI,
158
+ fromURI,
159
+ toURI,
160
+ messageOptions,
161
+ extraHeaders,
162
+ body
163
+ );
164
+
165
+ // Session parent properties
166
+ this._contact = contact;
167
+ this._referralInviterOptions = inviterOptions;
168
+ this._renderbody = options.renderbody;
169
+ this._rendertype = options.rendertype;
170
+
171
+ // Modifiers and options for initial INVITE transaction
172
+ if (options.sessionDescriptionHandlerModifiers) {
173
+ this.sessionDescriptionHandlerModifiers = options.sessionDescriptionHandlerModifiers;
174
+ }
175
+ if (options.sessionDescriptionHandlerOptions) {
176
+ this.sessionDescriptionHandlerOptions = options.sessionDescriptionHandlerOptions;
177
+ }
178
+
179
+ // Modifiers and options for re-INVITE transactions
180
+ if (options.sessionDescriptionHandlerModifiersReInvite) {
181
+ this.sessionDescriptionHandlerModifiersReInvite = options.sessionDescriptionHandlerModifiersReInvite;
182
+ }
183
+ if (options.sessionDescriptionHandlerOptionsReInvite) {
184
+ this.sessionDescriptionHandlerOptionsReInvite = options.sessionDescriptionHandlerOptionsReInvite;
185
+ }
186
+
187
+ // Identifier
188
+ this._id = this.outgoingRequestMessage.callId + this.fromTag;
189
+
190
+ // Add to the user agent's session collection.
191
+ this.userAgent._sessions[this._id] = this;
192
+ }
193
+
194
+ /**
195
+ * Destructor.
196
+ */
197
+ public dispose(): Promise<void> {
198
+ // Only run through this once. It can and does get called multiple times
199
+ // depending on the what the sessions state is when first called.
200
+ // For example, if called when "establishing" it will be called again
201
+ // at least once when the session transitions to "terminated".
202
+ // Regardless, running through this more than once is pointless.
203
+ if (this.disposed) {
204
+ return Promise.resolve();
205
+ }
206
+ this.disposed = true;
207
+
208
+ // Dispose of early dialog media
209
+ this.disposeEarlyMedia();
210
+
211
+ // If the final response for the initial INVITE not yet been received, cancel it
212
+ switch (this.state) {
213
+ case SessionState.Initial:
214
+ return this.cancel().then(() => super.dispose());
215
+ case SessionState.Establishing:
216
+ return this.cancel().then(() => super.dispose());
217
+ case SessionState.Established:
218
+ return super.dispose();
219
+ case SessionState.Terminating:
220
+ return super.dispose();
221
+ case SessionState.Terminated:
222
+ return super.dispose();
223
+ default:
224
+ throw new Error("Unknown state.");
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Initial outgoing INVITE request message body.
230
+ */
231
+ public get body(): BodyAndContentType | undefined {
232
+ return this.outgoingRequestMessage.body;
233
+ }
234
+
235
+ /**
236
+ * The identity of the local user.
237
+ */
238
+ public get localIdentity(): NameAddrHeader {
239
+ return this.outgoingRequestMessage.from;
240
+ }
241
+
242
+ /**
243
+ * The identity of the remote user.
244
+ */
245
+ public get remoteIdentity(): NameAddrHeader {
246
+ return this.outgoingRequestMessage.to;
247
+ }
248
+
249
+ /**
250
+ * Initial outgoing INVITE request message.
251
+ */
252
+ public get request(): OutgoingRequestMessage {
253
+ return this.outgoingRequestMessage;
254
+ }
255
+
256
+ /**
257
+ * Cancels the INVITE request.
258
+ *
259
+ * @remarks
260
+ * Sends a CANCEL request.
261
+ * Resolves once the response sent, otherwise rejects.
262
+ *
263
+ * After sending a CANCEL request the expectation is that a 487 final response
264
+ * will be received for the INVITE. However a 200 final response to the INVITE
265
+ * may nonetheless arrive (it's a race between the CANCEL reaching the UAS before
266
+ * the UAS sends a 200) in which case an ACK & BYE will be sent. The net effect
267
+ * is that this method will terminate the session regardless of the race.
268
+ * @param options - Options bucket.
269
+ */
270
+ public cancel(options: InviterCancelOptions = {}): Promise<void> {
271
+ this.logger.log("Inviter.cancel");
272
+
273
+ // validate state
274
+ if (this.state !== SessionState.Initial && this.state !== SessionState.Establishing) {
275
+ const error = new Error(`Invalid session state ${this.state}`);
276
+ this.logger.error(error.message);
277
+ return Promise.reject(error);
278
+ }
279
+
280
+ // flag canceled
281
+ this.isCanceled = true;
282
+
283
+ // transition state
284
+ this.stateTransition(SessionState.Terminating);
285
+
286
+ // helper function
287
+ function getCancelReason(code: number, reason: string): string | undefined {
288
+ if ((code && code < 200) || code > 699) {
289
+ throw new TypeError("Invalid statusCode: " + code);
290
+ } else if (code) {
291
+ const cause = code;
292
+ const text = getReasonPhrase(code) || reason;
293
+ return "SIP;cause=" + cause + ';text="' + text + '"';
294
+ }
295
+ }
296
+
297
+ if (this.outgoingInviteRequest) {
298
+ // the CANCEL may not be respected by peer(s), so don't transition to terminated
299
+ let cancelReason: string | undefined;
300
+ if (options.statusCode && options.reasonPhrase) {
301
+ cancelReason = getCancelReason(options.statusCode, options.reasonPhrase);
302
+ }
303
+ this.outgoingInviteRequest.cancel(cancelReason, options);
304
+ } else {
305
+ this.logger.warn("Canceled session before INVITE was sent");
306
+ this.stateTransition(SessionState.Terminated);
307
+ }
308
+
309
+ return Promise.resolve();
310
+ }
311
+
312
+ /**
313
+ * Sends the INVITE request.
314
+ *
315
+ * @remarks
316
+ * TLDR...
317
+ * 1) Only one offer/answer exchange permitted during initial INVITE.
318
+ * 2) No "early media" if the initial offer is in an INVITE (default behavior).
319
+ * 3) If "early media" and the initial offer is in an INVITE, no INVITE forking.
320
+ *
321
+ * 1) Only one offer/answer exchange permitted during initial INVITE.
322
+ *
323
+ * Our implementation replaces the following bullet point...
324
+ *
325
+ * o After having sent or received an answer to the first offer, the
326
+ * UAC MAY generate subsequent offers in requests based on rules
327
+ * specified for that method, but only if it has received answers
328
+ * to any previous offers, and has not sent any offers to which it
329
+ * hasn't gotten an answer.
330
+ * https://tools.ietf.org/html/rfc3261#section-13.2.1
331
+ *
332
+ * ...with...
333
+ *
334
+ * o After having sent or received an answer to the first offer, the
335
+ * UAC MUST NOT generate subsequent offers in requests based on rules
336
+ * specified for that method.
337
+ *
338
+ * ...which in combination with this bullet point...
339
+ *
340
+ * o Once the UAS has sent or received an answer to the initial
341
+ * offer, it MUST NOT generate subsequent offers in any responses
342
+ * to the initial INVITE. This means that a UAS based on this
343
+ * specification alone can never generate subsequent offers until
344
+ * completion of the initial transaction.
345
+ * https://tools.ietf.org/html/rfc3261#section-13.2.1
346
+ *
347
+ * ...ensures that EXACTLY ONE offer/answer exchange will occur
348
+ * during an initial out of dialog INVITE request made by our UAC.
349
+ *
350
+ *
351
+ * 2) No "early media" if the initial offer is in an INVITE (default behavior).
352
+ *
353
+ * While our implementation adheres to the following bullet point...
354
+ *
355
+ * o If the initial offer is in an INVITE, the answer MUST be in a
356
+ * reliable non-failure message from UAS back to UAC which is
357
+ * correlated to that INVITE. For this specification, that is
358
+ * only the final 2xx response to that INVITE. That same exact
359
+ * answer MAY also be placed in any provisional responses sent
360
+ * prior to the answer. The UAC MUST treat the first session
361
+ * description it receives as the answer, and MUST ignore any
362
+ * session descriptions in subsequent responses to the initial
363
+ * INVITE.
364
+ * https://tools.ietf.org/html/rfc3261#section-13.2.1
365
+ *
366
+ * We have made the following implementation decision with regard to early media...
367
+ *
368
+ * o If the initial offer is in the INVITE, the answer from the
369
+ * UAS back to the UAC will establish a media session only
370
+ * only after the final 2xx response to that INVITE is received.
371
+ *
372
+ * The reason for this decision is rooted in a restriction currently
373
+ * inherent in WebRTC. Specifically, while a SIP INVITE request with an
374
+ * initial offer may fork resulting in more than one provisional answer,
375
+ * there is currently no easy/good way to to "fork" an offer generated
376
+ * by a peer connection. In particular, a WebRTC offer currently may only
377
+ * be matched with one answer and we have no good way to know which
378
+ * "provisional answer" is going to be the "final answer". So we have
379
+ * decided to punt and not create any "early media" sessions in this case.
380
+ *
381
+ * The upshot is that if you want "early media", you must not put the
382
+ * initial offer in the INVITE. Instead, force the UAS to provide the
383
+ * initial offer by sending an INVITE without an offer. In the WebRTC
384
+ * case this allows us to create a unique peer connection with a unique
385
+ * answer for every provisional offer with "early media" on all of them.
386
+ *
387
+ *
388
+ * 3) If "early media" and the initial offer is in an INVITE, no INVITE forking.
389
+ *
390
+ * The default behavior may be altered and "early media" utilized if the
391
+ * initial offer is in the an INVITE by setting the `earlyMedia` options.
392
+ * However in that case the INVITE request MUST NOT fork. This allows for
393
+ * "early media" in environments where the forking behavior of the SIP
394
+ * servers being utilized is configured to disallow forking.
395
+ */
396
+ public invite(options: InviterInviteOptions = {}): Promise<OutgoingInviteRequest> {
397
+ this.logger.log("Inviter.invite");
398
+
399
+ // validate state
400
+ if (this.state !== SessionState.Initial) {
401
+ // re-invite
402
+ return super.invite(options);
403
+ }
404
+
405
+ // Modifiers and options for initial INVITE transaction
406
+ if (options.sessionDescriptionHandlerModifiers) {
407
+ this.sessionDescriptionHandlerModifiers = options.sessionDescriptionHandlerModifiers;
408
+ }
409
+ if (options.sessionDescriptionHandlerOptions) {
410
+ this.sessionDescriptionHandlerOptions = options.sessionDescriptionHandlerOptions;
411
+ }
412
+
413
+ // just send an INVITE with no sdp...
414
+ if (options.withoutSdp || this.inviteWithoutSdp) {
415
+ if (this._renderbody && this._rendertype) {
416
+ this.outgoingRequestMessage.body = { contentType: this._rendertype, body: this._renderbody };
417
+ }
418
+
419
+ // transition state
420
+ this.stateTransition(SessionState.Establishing);
421
+
422
+ return Promise.resolve(this.sendInvite(options));
423
+ }
424
+
425
+ // get an offer and send it in an INVITE
426
+ const offerOptions = {
427
+ sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiers,
428
+ sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptions
429
+ };
430
+ return this.getOffer(offerOptions)
431
+ .then((body) => {
432
+ this.outgoingRequestMessage.body = { body: body.content, contentType: body.contentType };
433
+
434
+ // transition state
435
+ this.stateTransition(SessionState.Establishing);
436
+
437
+ return this.sendInvite(options);
438
+ })
439
+ .catch((error) => {
440
+ this.logger.log(error.message);
441
+ this.stateTransition(SessionState.Terminated);
442
+ throw error;
443
+ });
444
+ }
445
+
446
+ /**
447
+ * 13.2.1 Creating the Initial INVITE
448
+ *
449
+ * Since the initial INVITE represents a request outside of a dialog,
450
+ * its construction follows the procedures of Section 8.1.1. Additional
451
+ * processing is required for the specific case of INVITE.
452
+ *
453
+ * An Allow header field (Section 20.5) SHOULD be present in the INVITE.
454
+ * It indicates what methods can be invoked within a dialog, on the UA
455
+ * sending the INVITE, for the duration of the dialog. For example, a
456
+ * UA capable of receiving INFO requests within a dialog [34] SHOULD
457
+ * include an Allow header field listing the INFO method.
458
+ *
459
+ * A Supported header field (Section 20.37) SHOULD be present in the
460
+ * INVITE. It enumerates all the extensions understood by the UAC.
461
+ *
462
+ * An Accept (Section 20.1) header field MAY be present in the INVITE.
463
+ * It indicates which Content-Types are acceptable to the UA, in both
464
+ * the response received by it, and in any subsequent requests sent to
465
+ * it within dialogs established by the INVITE. The Accept header field
466
+ * is especially useful for indicating support of various session
467
+ * description formats.
468
+ *
469
+ * The UAC MAY add an Expires header field (Section 20.19) to limit the
470
+ * validity of the invitation. If the time indicated in the Expires
471
+ * header field is reached and no final answer for the INVITE has been
472
+ * received, the UAC core SHOULD generate a CANCEL request for the
473
+ * INVITE, as per Section 9.
474
+ *
475
+ * A UAC MAY also find it useful to add, among others, Subject (Section
476
+ * 20.36), Organization (Section 20.25) and User-Agent (Section 20.41)
477
+ * header fields. They all contain information related to the INVITE.
478
+ *
479
+ * The UAC MAY choose to add a message body to the INVITE. Section
480
+ * 8.1.1.10 deals with how to construct the header fields -- Content-
481
+ * Type among others -- needed to describe the message body.
482
+ *
483
+ * https://tools.ietf.org/html/rfc3261#section-13.2.1
484
+ */
485
+ private sendInvite(options: InviterInviteOptions = {}): OutgoingInviteRequest {
486
+ // There are special rules for message bodies that contain a session
487
+ // description - their corresponding Content-Disposition is "session".
488
+ // SIP uses an offer/answer model where one UA sends a session
489
+ // description, called the offer, which contains a proposed description
490
+ // of the session. The offer indicates the desired communications means
491
+ // (audio, video, games), parameters of those means (such as codec
492
+ // types) and addresses for receiving media from the answerer. The
493
+ // other UA responds with another session description, called the
494
+ // answer, which indicates which communications means are accepted, the
495
+ // parameters that apply to those means, and addresses for receiving
496
+ // media from the offerer. An offer/answer exchange is within the
497
+ // context of a dialog, so that if a SIP INVITE results in multiple
498
+ // dialogs, each is a separate offer/answer exchange. The offer/answer
499
+ // model defines restrictions on when offers and answers can be made
500
+ // (for example, you cannot make a new offer while one is in progress).
501
+ // This results in restrictions on where the offers and answers can
502
+ // appear in SIP messages. In this specification, offers and answers
503
+ // can only appear in INVITE requests and responses, and ACK. The usage
504
+ // of offers and answers is further restricted. For the initial INVITE
505
+ // transaction, the rules are:
506
+ //
507
+ // o The initial offer MUST be in either an INVITE or, if not there,
508
+ // in the first reliable non-failure message from the UAS back to
509
+ // the UAC. In this specification, that is the final 2xx
510
+ // response.
511
+ //
512
+ // o If the initial offer is in an INVITE, the answer MUST be in a
513
+ // reliable non-failure message from UAS back to UAC which is
514
+ // correlated to that INVITE. For this specification, that is
515
+ // only the final 2xx response to that INVITE. That same exact
516
+ // answer MAY also be placed in any provisional responses sent
517
+ // prior to the answer. The UAC MUST treat the first session
518
+ // description it receives as the answer, and MUST ignore any
519
+ // session descriptions in subsequent responses to the initial
520
+ // INVITE.
521
+ //
522
+ // o If the initial offer is in the first reliable non-failure
523
+ // message from the UAS back to UAC, the answer MUST be in the
524
+ // acknowledgement for that message (in this specification, ACK
525
+ // for a 2xx response).
526
+ //
527
+ // o After having sent or received an answer to the first offer, the
528
+ // UAC MAY generate subsequent offers in requests based on rules
529
+ // specified for that method, but only if it has received answers
530
+ // to any previous offers, and has not sent any offers to which it
531
+ // hasn't gotten an answer.
532
+ //
533
+ // o Once the UAS has sent or received an answer to the initial
534
+ // offer, it MUST NOT generate subsequent offers in any responses
535
+ // to the initial INVITE. This means that a UAS based on this
536
+ // specification alone can never generate subsequent offers until
537
+ // completion of the initial transaction.
538
+ //
539
+ // https://tools.ietf.org/html/rfc3261#section-13.2.1
540
+
541
+ // 5 The Offer/Answer Model and PRACK
542
+ //
543
+ // RFC 3261 describes guidelines for the sets of messages in which
544
+ // offers and answers [3] can appear. Based on those guidelines, this
545
+ // extension provides additional opportunities for offer/answer
546
+ // exchanges.
547
+
548
+ // If the INVITE contained an offer, the UAS MAY generate an answer in a
549
+ // reliable provisional response (assuming these are supported by the
550
+ // UAC). That results in the establishment of the session before
551
+ // completion of the call. Similarly, if a reliable provisional
552
+ // response is the first reliable message sent back to the UAC, and the
553
+ // INVITE did not contain an offer, one MUST appear in that reliable
554
+ // provisional response.
555
+
556
+ // If the UAC receives a reliable provisional response with an offer
557
+ // (this would occur if the UAC sent an INVITE without an offer, in
558
+ // which case the first reliable provisional response will contain the
559
+ // offer), it MUST generate an answer in the PRACK. If the UAC receives
560
+ // a reliable provisional response with an answer, it MAY generate an
561
+ // additional offer in the PRACK. If the UAS receives a PRACK with an
562
+ // offer, it MUST place the answer in the 2xx to the PRACK.
563
+
564
+ // Once an answer has been sent or received, the UA SHOULD establish the
565
+ // session based on the parameters of the offer and answer, even if the
566
+ // original INVITE itself has not been responded to.
567
+
568
+ // If the UAS had placed a session description in any reliable
569
+ // provisional response that is unacknowledged when the INVITE is
570
+ // accepted, the UAS MUST delay sending the 2xx until the provisional
571
+ // response is acknowledged. Otherwise, the reliability of the 1xx
572
+ // cannot be guaranteed, and reliability is needed for proper operation
573
+ // of the offer/answer exchange.
574
+
575
+ // All user agents that support this extension MUST support all
576
+ // offer/answer exchanges that are possible based on the rules in
577
+ // Section 13.2 of RFC 3261, based on the existence of INVITE and PRACK
578
+ // as requests, and 2xx and reliable 1xx as non-failure reliable
579
+ // responses.
580
+ //
581
+ // https://tools.ietf.org/html/rfc3262#section-5
582
+
583
+ ////
584
+ // The Offer/Answer Model Implementation
585
+ //
586
+ // The offer/answer model is straight forward, but one MUST READ the specifications...
587
+ //
588
+ // 13.2.1 Creating the Initial INVITE (paragraph 8 in particular)
589
+ // https://tools.ietf.org/html/rfc3261#section-13.2.1
590
+ //
591
+ // 5 The Offer/Answer Model and PRACK
592
+ // https://tools.ietf.org/html/rfc3262#section-5
593
+ //
594
+ // Session Initiation Protocol (SIP) Usage of the Offer/Answer Model
595
+ // https://tools.ietf.org/html/rfc6337
596
+ ////
597
+
598
+ ////
599
+ // TODO: The Offer/Answer Model Implementation
600
+ //
601
+ // Currently if `earlyMedia` is enabled and the INVITE request forks,
602
+ // the session is terminated if the early dialog does not match the
603
+ // confirmed dialog. This restriction make sense in a WebRTC environment,
604
+ // but there are other environments where this restriction does not hold.
605
+ //
606
+ // So while we currently cannot make the offer in INVITE+forking+webrtc
607
+ // case work, we propose doing the following...
608
+ //
609
+ // OPTION 1
610
+ // - add a `earlyMediaForking` option and
611
+ // - require SDH.setDescription() to be callable multiple times.
612
+ //
613
+ // OPTION 2
614
+ // 1) modify SDH Factory to provide an initial offer without giving us the SDH, and then...
615
+ // 2) stick that offer in the initial INVITE, and when 183 with initial answer is received...
616
+ // 3) ask SDH Factory if it supports "earlyRemoteAnswer"
617
+ // a) if true, ask SDH Factory to createSDH(localOffer).then((sdh) => sdh.setDescription(remoteAnswer)
618
+ // b) if false, defer getting a SDH until 2xx response is received
619
+ //
620
+ // Our supplied WebRTC SDH will default to behavior 3b which works in forking environment (without)
621
+ // early media if initial offer is in the INVITE). We will, however, provide an "inviteWillNotFork"
622
+ // option which if set to "true" will have our supplied WebRTC SDH behave in the 3a manner.
623
+ // That will result in
624
+ // - early media working with initial offer in the INVITE, and...
625
+ // - if the INVITE forks, the session terminating with an ERROR that reads like
626
+ // "You set 'inviteWillNotFork' to true but the INVITE forked. You can't eat your cake, and have it too."
627
+ // - furthermore, we accept that users will report that error to us as "bug" regardless
628
+ //
629
+ // So, SDH Factory is going to end up with a new interface along the lines of...
630
+ //
631
+ // interface SessionDescriptionHandlerFactory {
632
+ // makeLocalOffer(): Promise<ContentTypeAndBody>;
633
+ // makeSessionDescriptionHandler(
634
+ // initialOffer: ContentTypeAndBody, offerType: "local" | "remote"
635
+ // ): Promise<SessionDescriptionHandler>;
636
+ // supportsEarlyRemoteAnswer: boolean;
637
+ // supportsContentType(contentType: string): boolean;
638
+ // getDescription(description: ContentTypeAndBody): Promise<ContentTypeAndBody>
639
+ // setDescription(description: ContentTypeAndBody): Promise<void>
640
+ // }
641
+ ////
642
+
643
+ // Send the INVITE request.
644
+ this.outgoingInviteRequest = this.userAgent.userAgentCore.invite(this.outgoingRequestMessage, {
645
+ onAccept: (inviteResponse) => {
646
+ // Our transaction layer is "non-standard" in that it will only
647
+ // pass us a 2xx response once per branch, so there is no need to
648
+ // worry about dealing with 2xx retransmissions. However, we can
649
+ // and do still get 2xx responses for multiple branches (when an
650
+ // INVITE is forked) which may create multiple confirmed dialogs.
651
+ // Herein we are acking and sending a bye to any confirmed dialogs
652
+ // which arrive beyond the first one. This is the desired behavior
653
+ // for most applications (but certainly not all).
654
+
655
+ // If we already received a confirmed dialog, ack & bye this additional confirmed session.
656
+ if (this.dialog) {
657
+ this.logger.log("Additional confirmed dialog, sending ACK and BYE");
658
+ this.ackAndBye(inviteResponse);
659
+ // We do NOT transition state in this case (this is an "extra" dialog)
660
+ return;
661
+ }
662
+
663
+ // If the user requested cancellation, ack & bye this session.
664
+ if (this.isCanceled) {
665
+ this.logger.log("Canceled session accepted, sending ACK and BYE");
666
+ this.ackAndBye(inviteResponse);
667
+ this.stateTransition(SessionState.Terminated);
668
+ return;
669
+ }
670
+
671
+ this.notifyReferer(inviteResponse);
672
+ this.onAccept(inviteResponse)
673
+ .then(() => {
674
+ this.disposeEarlyMedia();
675
+ })
676
+ .catch(() => {
677
+ this.disposeEarlyMedia();
678
+ })
679
+ .then(() => {
680
+ if (options.requestDelegate && options.requestDelegate.onAccept) {
681
+ options.requestDelegate.onAccept(inviteResponse);
682
+ }
683
+ });
684
+ },
685
+ onProgress: (inviteResponse) => {
686
+ // If the user requested cancellation, ignore response.
687
+ if (this.isCanceled) {
688
+ return;
689
+ }
690
+ this.notifyReferer(inviteResponse);
691
+ this.onProgress(inviteResponse)
692
+ .catch(() => {
693
+ this.disposeEarlyMedia();
694
+ })
695
+ .then(() => {
696
+ if (options.requestDelegate && options.requestDelegate.onProgress) {
697
+ options.requestDelegate.onProgress(inviteResponse);
698
+ }
699
+ });
700
+ },
701
+ onRedirect: (inviteResponse) => {
702
+ this.notifyReferer(inviteResponse);
703
+ this.onRedirect(inviteResponse);
704
+ if (options.requestDelegate && options.requestDelegate.onRedirect) {
705
+ options.requestDelegate.onRedirect(inviteResponse);
706
+ }
707
+ },
708
+ onReject: (inviteResponse) => {
709
+ this.notifyReferer(inviteResponse);
710
+ this.onReject(inviteResponse);
711
+ if (options.requestDelegate && options.requestDelegate.onReject) {
712
+ options.requestDelegate.onReject(inviteResponse);
713
+ }
714
+ },
715
+ onTrying: (inviteResponse) => {
716
+ this.notifyReferer(inviteResponse);
717
+ this.onTrying(inviteResponse);
718
+ if (options.requestDelegate && options.requestDelegate.onTrying) {
719
+ options.requestDelegate.onTrying(inviteResponse);
720
+ }
721
+ }
722
+ });
723
+
724
+ return this.outgoingInviteRequest;
725
+ }
726
+
727
+ private disposeEarlyMedia(): void {
728
+ this.earlyMediaSessionDescriptionHandlers.forEach((sessionDescriptionHandler) => {
729
+ sessionDescriptionHandler.close();
730
+ });
731
+ this.earlyMediaSessionDescriptionHandlers.clear();
732
+ }
733
+
734
+ private notifyReferer(response: IncomingResponse): void {
735
+ if (!this._referred) {
736
+ return;
737
+ }
738
+ if (!(this._referred instanceof Session)) {
739
+ throw new Error("Referred session not instance of session");
740
+ }
741
+ if (!this._referred.dialog) {
742
+ return;
743
+ }
744
+ if (!response.message.statusCode) {
745
+ throw new Error("Status code undefined.");
746
+ }
747
+ if (!response.message.reasonPhrase) {
748
+ throw new Error("Reason phrase undefined.");
749
+ }
750
+ const statusCode = response.message.statusCode;
751
+ const reasonPhrase = response.message.reasonPhrase;
752
+ const body = `SIP/2.0 ${statusCode} ${reasonPhrase}`.trim();
753
+
754
+ const outgoingNotifyRequest = this._referred.dialog.notify(undefined, {
755
+ extraHeaders: ["Event: refer", "Subscription-State: terminated"],
756
+ body: {
757
+ contentDisposition: "render",
758
+ contentType: "message/sipfrag",
759
+ content: body
760
+ }
761
+ });
762
+
763
+ // The implicit subscription created by a REFER is the same as a
764
+ // subscription created with a SUBSCRIBE request. The agent issuing the
765
+ // REFER can terminate this subscription prematurely by unsubscribing
766
+ // using the mechanisms described in [2]. Terminating a subscription,
767
+ // either by explicitly unsubscribing or rejecting NOTIFY, is not an
768
+ // indication that the referenced request should be withdrawn or
769
+ // abandoned.
770
+ // https://tools.ietf.org/html/rfc3515#section-2.4.4
771
+
772
+ // FIXME: TODO: This should be done in a subscribe dialog to satisfy the above.
773
+ // If the notify is rejected, stop sending NOTIFY requests.
774
+ outgoingNotifyRequest.delegate = {
775
+ onReject: (): void => {
776
+ this._referred = undefined;
777
+ }
778
+ };
779
+ }
780
+
781
+ /**
782
+ * Handle final response to initial INVITE.
783
+ * @param inviteResponse - 2xx response.
784
+ */
785
+ private onAccept(inviteResponse: AckableIncomingResponseWithSession): Promise<void> {
786
+ this.logger.log("Inviter.onAccept");
787
+
788
+ // validate state
789
+ if (this.state !== SessionState.Establishing) {
790
+ this.logger.error(`Accept received while in state ${this.state}, dropping response`);
791
+ return Promise.reject(new Error(`Invalid session state ${this.state}`));
792
+ }
793
+
794
+ const response = inviteResponse.message;
795
+ const session = inviteResponse.session;
796
+
797
+ // Ported behavior.
798
+ if (response.hasHeader("P-Asserted-Identity")) {
799
+ this._assertedIdentity = Grammar.nameAddrHeaderParse(response.getHeader("P-Asserted-Identity") as string);
800
+ }
801
+
802
+ // We have a confirmed dialog.
803
+ session.delegate = {
804
+ onAck: (ackRequest): Promise<void> => this.onAckRequest(ackRequest),
805
+ onBye: (byeRequest): void => this.onByeRequest(byeRequest),
806
+ onInfo: (infoRequest): void => this.onInfoRequest(infoRequest),
807
+ onInvite: (inviteRequest): void => this.onInviteRequest(inviteRequest),
808
+ onMessage: (messageRequest): void => this.onMessageRequest(messageRequest),
809
+ onNotify: (notifyRequest): void => this.onNotifyRequest(notifyRequest),
810
+ onPrack: (prackRequest): void => this.onPrackRequest(prackRequest),
811
+ onRefer: (referRequest): void => this.onReferRequest(referRequest)
812
+ };
813
+ this._dialog = session;
814
+
815
+ switch (session.signalingState) {
816
+ case SignalingState.Initial:
817
+ // INVITE without offer, so MUST have offer at this point, so invalid state.
818
+ this.logger.error("Received 2xx response to INVITE without a session description");
819
+ this.ackAndBye(inviteResponse, 400, "Missing session description");
820
+ this.stateTransition(SessionState.Terminated);
821
+ return Promise.reject(new Error("Bad Media Description"));
822
+ case SignalingState.HaveLocalOffer:
823
+ // INVITE with offer, so MUST have answer at this point, so invalid state.
824
+ this.logger.error("Received 2xx response to INVITE without a session description");
825
+ this.ackAndBye(inviteResponse, 400, "Missing session description");
826
+ this.stateTransition(SessionState.Terminated);
827
+ return Promise.reject(new Error("Bad Media Description"));
828
+ case SignalingState.HaveRemoteOffer: {
829
+ // INVITE without offer, received offer in 2xx, so MUST send answer in ACK.
830
+ if (!this._dialog.offer) {
831
+ throw new Error(`Session offer undefined in signaling state ${this._dialog.signalingState}.`);
832
+ }
833
+ const options = {
834
+ sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiers,
835
+ sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptions
836
+ };
837
+ return this.setOfferAndGetAnswer(this._dialog.offer, options)
838
+ .then((body) => {
839
+ inviteResponse.ack({ body });
840
+ this.stateTransition(SessionState.Established);
841
+ })
842
+ .catch((error: Error) => {
843
+ this.ackAndBye(inviteResponse, 488, "Invalid session description");
844
+ this.stateTransition(SessionState.Terminated);
845
+ throw error;
846
+ });
847
+ }
848
+ case SignalingState.Stable: {
849
+ // If INVITE without offer and we have already completed the initial exchange.
850
+ if (this.earlyMediaSessionDescriptionHandlers.size > 0) {
851
+ const sdh = this.earlyMediaSessionDescriptionHandlers.get(session.id);
852
+ if (!sdh) {
853
+ throw new Error("Session description handler undefined.");
854
+ }
855
+ this.setSessionDescriptionHandler(sdh);
856
+ this.earlyMediaSessionDescriptionHandlers.delete(session.id);
857
+ inviteResponse.ack();
858
+ this.stateTransition(SessionState.Established);
859
+ return Promise.resolve();
860
+ }
861
+
862
+ // If INVITE with offer and we used an "early" answer in a provisional response for media
863
+ if (this.earlyMediaDialog) {
864
+ // If early media dialog doesn't match confirmed dialog, we must unfortunately fail.
865
+ // This limitation stems from how WebRTC currently implements its offer/answer model.
866
+ // There are details elsewhere, but in short a WebRTC offer cannot be forked.
867
+ if (this.earlyMediaDialog !== session) {
868
+ if (this.earlyMedia) {
869
+ const message =
870
+ "You have set the 'earlyMedia' option to 'true' which requires that your INVITE requests " +
871
+ "do not fork and yet this INVITE request did in fact fork. Consequentially and not surprisingly " +
872
+ "the end point which accepted the INVITE (confirmed dialog) does not match the end point with " +
873
+ "which early media has been setup (early dialog) and thus this session is unable to proceed. " +
874
+ "In accordance with the SIP specifications, the SIP servers your end point is connected to " +
875
+ "determine if an INVITE forks and the forking behavior of those servers cannot be controlled " +
876
+ "by this library. If you wish to use early media with this library you must configure those " +
877
+ "servers accordingly. Alternatively you may set the 'earlyMedia' to 'false' which will allow " +
878
+ "this library to function with any INVITE requests which do fork.";
879
+ this.logger.error(message);
880
+ }
881
+ const error = new Error("Early media dialog does not equal confirmed dialog, terminating session");
882
+ this.logger.error(error.message);
883
+ this.ackAndBye(inviteResponse, 488, "Not Acceptable Here");
884
+ this.stateTransition(SessionState.Terminated);
885
+ return Promise.reject(error);
886
+ }
887
+ // Otherwise we are good to go.
888
+ inviteResponse.ack();
889
+ this.stateTransition(SessionState.Established);
890
+ return Promise.resolve();
891
+ }
892
+
893
+ // If INVITE with offer and we have been waiting till now to apply the answer.
894
+ const answer = session.answer;
895
+ if (!answer) {
896
+ throw new Error("Answer is undefined.");
897
+ }
898
+ const options = {
899
+ sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiers,
900
+ sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptions
901
+ };
902
+ return this.setAnswer(answer, options)
903
+ .then(() => {
904
+ // This session has completed an initial offer/answer exchange...
905
+ let ackOptions: RequestOptions | undefined;
906
+ if (this._renderbody && this._rendertype) {
907
+ ackOptions = {
908
+ body: { contentDisposition: "render", contentType: this._rendertype, content: this._renderbody }
909
+ };
910
+ }
911
+ inviteResponse.ack(ackOptions);
912
+ this.stateTransition(SessionState.Established);
913
+ })
914
+ .catch((error: Error) => {
915
+ this.logger.error(error.message);
916
+ this.ackAndBye(inviteResponse, 488, "Not Acceptable Here");
917
+ this.stateTransition(SessionState.Terminated);
918
+ throw error;
919
+ });
920
+ }
921
+ case SignalingState.Closed:
922
+ // Dialog has terminated.
923
+ return Promise.reject(new Error("Terminated."));
924
+ default:
925
+ throw new Error("Unknown session signaling state.");
926
+ }
927
+ }
928
+
929
+ /**
930
+ * Handle provisional response to initial INVITE.
931
+ * @param inviteResponse - 1xx response.
932
+ */
933
+ private onProgress(inviteResponse: PrackableIncomingResponseWithSession): Promise<void> {
934
+ this.logger.log("Inviter.onProgress");
935
+
936
+ // validate state
937
+ if (this.state !== SessionState.Establishing) {
938
+ this.logger.error(`Progress received while in state ${this.state}, dropping response`);
939
+ return Promise.reject(new Error(`Invalid session state ${this.state}`));
940
+ }
941
+
942
+ if (!this.outgoingInviteRequest) {
943
+ throw new Error("Outgoing INVITE request undefined.");
944
+ }
945
+
946
+ const response = inviteResponse.message;
947
+ const session = inviteResponse.session;
948
+
949
+ // Ported - Set assertedIdentity.
950
+ if (response.hasHeader("P-Asserted-Identity")) {
951
+ this._assertedIdentity = Grammar.nameAddrHeaderParse(response.getHeader("P-Asserted-Identity") as string);
952
+ }
953
+
954
+ // If a provisional response is received for an initial request, and
955
+ // that response contains a Require header field containing the option
956
+ // tag 100rel, the response is to be sent reliably. If the response is
957
+ // a 100 (Trying) (as opposed to 101 to 199), this option tag MUST be
958
+ // ignored, and the procedures below MUST NOT be used.
959
+ // https://tools.ietf.org/html/rfc3262#section-4
960
+ const requireHeader = response.getHeader("require");
961
+ const rseqHeader = response.getHeader("rseq");
962
+ const rseq = requireHeader && requireHeader.includes("100rel") && rseqHeader ? Number(rseqHeader) : undefined;
963
+ const responseReliable = !!rseq;
964
+
965
+ const extraHeaders: Array<string> = [];
966
+ if (responseReliable) {
967
+ extraHeaders.push("RAck: " + response.getHeader("rseq") + " " + response.getHeader("cseq"));
968
+ }
969
+
970
+ switch (session.signalingState) {
971
+ case SignalingState.Initial:
972
+ // INVITE without offer and session still has no offer (and no answer).
973
+ if (responseReliable) {
974
+ // Similarly, if a reliable provisional
975
+ // response is the first reliable message sent back to the UAC, and the
976
+ // INVITE did not contain an offer, one MUST appear in that reliable
977
+ // provisional response.
978
+ // https://tools.ietf.org/html/rfc3262#section-5
979
+ this.logger.warn(
980
+ "First reliable provisional response received MUST contain an offer when INVITE does not contain an offer."
981
+ );
982
+ // FIXME: Known popular UA's currently end up here...
983
+ inviteResponse.prack({ extraHeaders });
984
+ }
985
+ return Promise.resolve();
986
+ case SignalingState.HaveLocalOffer:
987
+ // INVITE with offer and session only has that initial local offer.
988
+ if (responseReliable) {
989
+ inviteResponse.prack({ extraHeaders });
990
+ }
991
+ return Promise.resolve();
992
+ case SignalingState.HaveRemoteOffer:
993
+ if (!responseReliable) {
994
+ // The initial offer MUST be in either an INVITE or, if not there,
995
+ // in the first reliable non-failure message from the UAS back to
996
+ // the UAC.
997
+ // https://tools.ietf.org/html/rfc3261#section-13.2.1
998
+
999
+ // According to Section 13.2.1 of [RFC3261], 'The first reliable
1000
+ // non-failure message' must have an offer if there is no offer in the
1001
+ // INVITE request. This means that the User Agent (UA) that receives
1002
+ // the INVITE request without an offer must include an offer in the
1003
+ // first reliable response with 100rel extension. If no reliable
1004
+ // provisional response has been sent, the User Agent Server (UAS) must
1005
+ // include an offer when sending 2xx response.
1006
+ // https://tools.ietf.org/html/rfc6337#section-2.2
1007
+
1008
+ this.logger.warn("Non-reliable provisional response MUST NOT contain an initial offer, discarding response.");
1009
+ return Promise.resolve();
1010
+ }
1011
+ {
1012
+ // If the initial offer is in the first reliable non-failure
1013
+ // message from the UAS back to UAC, the answer MUST be in the
1014
+ // acknowledgement for that message
1015
+ const sdh = this.sessionDescriptionHandlerFactory(
1016
+ this,
1017
+ this.userAgent.configuration.sessionDescriptionHandlerFactoryOptions || {}
1018
+ );
1019
+ if (this.delegate?.onSessionDescriptionHandler) {
1020
+ this.delegate.onSessionDescriptionHandler(sdh, true);
1021
+ }
1022
+ this.earlyMediaSessionDescriptionHandlers.set(session.id, sdh);
1023
+ return sdh
1024
+ .setDescription(
1025
+ response.body,
1026
+ this.sessionDescriptionHandlerOptions,
1027
+ this.sessionDescriptionHandlerModifiers
1028
+ )
1029
+ .then(() =>
1030
+ sdh.getDescription(this.sessionDescriptionHandlerOptions, this.sessionDescriptionHandlerModifiers)
1031
+ )
1032
+ .then((description) => {
1033
+ const body: Body = {
1034
+ contentDisposition: "session",
1035
+ contentType: description.contentType,
1036
+ content: description.body
1037
+ };
1038
+ inviteResponse.prack({ extraHeaders, body });
1039
+ })
1040
+ .catch((error) => {
1041
+ this.stateTransition(SessionState.Terminated);
1042
+ throw error;
1043
+ });
1044
+ }
1045
+ case SignalingState.Stable:
1046
+ // This session has completed an initial offer/answer exchange, so...
1047
+ // - INVITE with SDP and this provisional response MAY be reliable
1048
+ // - INVITE without SDP and this provisional response MAY be reliable
1049
+ if (responseReliable) {
1050
+ inviteResponse.prack({ extraHeaders });
1051
+ }
1052
+ if (this.earlyMedia && !this.earlyMediaDialog) {
1053
+ this.earlyMediaDialog = session;
1054
+ const answer = session.answer;
1055
+ if (!answer) {
1056
+ throw new Error("Answer is undefined.");
1057
+ }
1058
+ const options = {
1059
+ sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiers,
1060
+ sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptions
1061
+ };
1062
+ return this.setAnswer(answer, options).catch((error: Error) => {
1063
+ this.stateTransition(SessionState.Terminated);
1064
+ throw error;
1065
+ });
1066
+ }
1067
+ return Promise.resolve();
1068
+ case SignalingState.Closed:
1069
+ // Dialog has terminated.
1070
+ return Promise.reject(new Error("Terminated."));
1071
+ default:
1072
+ throw new Error("Unknown session signaling state.");
1073
+ }
1074
+ }
1075
+
1076
+ /**
1077
+ * Handle final response to initial INVITE.
1078
+ * @param inviteResponse - 3xx response.
1079
+ */
1080
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1081
+ private onRedirect(inviteResponse: IncomingResponse): void {
1082
+ this.logger.log("Inviter.onRedirect");
1083
+
1084
+ // validate state
1085
+ if (this.state !== SessionState.Establishing && this.state !== SessionState.Terminating) {
1086
+ this.logger.error(`Redirect received while in state ${this.state}, dropping response`);
1087
+ return;
1088
+ }
1089
+
1090
+ // transition state
1091
+ this.stateTransition(SessionState.Terminated);
1092
+ }
1093
+
1094
+ /**
1095
+ * Handle final response to initial INVITE.
1096
+ * @param inviteResponse - 4xx, 5xx, or 6xx response.
1097
+ */
1098
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1099
+ private onReject(inviteResponse: IncomingResponse): void {
1100
+ this.logger.log("Inviter.onReject");
1101
+
1102
+ // validate state
1103
+ if (this.state !== SessionState.Establishing && this.state !== SessionState.Terminating) {
1104
+ this.logger.error(`Reject received while in state ${this.state}, dropping response`);
1105
+ return;
1106
+ }
1107
+
1108
+ // transition state
1109
+ this.stateTransition(SessionState.Terminated);
1110
+ }
1111
+
1112
+ /**
1113
+ * Handle final response to initial INVITE.
1114
+ * @param inviteResponse - 100 response.
1115
+ */
1116
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1117
+ private onTrying(inviteResponse: IncomingResponse): void {
1118
+ this.logger.log("Inviter.onTrying");
1119
+
1120
+ // validate state
1121
+ if (this.state !== SessionState.Establishing) {
1122
+ this.logger.error(`Trying received while in state ${this.state}, dropping response`);
1123
+ return;
1124
+ }
1125
+ }
1126
+ }