ue-softphone-sdk 2.2.2 → 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 +59 -28
  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,1448 @@
1
+ import {
2
+ AckableIncomingResponseWithSession,
3
+ Body,
4
+ fromBodyLegacy,
5
+ getBody,
6
+ Grammar,
7
+ IncomingAckRequest,
8
+ IncomingByeRequest,
9
+ IncomingInfoRequest,
10
+ IncomingInviteRequest,
11
+ IncomingMessageRequest,
12
+ IncomingNotifyRequest,
13
+ IncomingPrackRequest,
14
+ IncomingReferRequest,
15
+ Logger,
16
+ NameAddrHeader,
17
+ OutgoingByeRequest,
18
+ OutgoingInfoRequest,
19
+ OutgoingInviteRequest,
20
+ OutgoingInviteRequestDelegate,
21
+ OutgoingMessageRequest,
22
+ OutgoingReferRequest,
23
+ OutgoingRequestDelegate,
24
+ RequestOptions,
25
+ Session as SessionDialog,
26
+ SessionState as SessionDialogState,
27
+ SignalingState,
28
+ URI
29
+ } from "../core";
30
+ import { getReasonPhrase } from "../core/messages/utils";
31
+ import { AllowedMethods } from "../core/user-agent-core/allowed-methods";
32
+ import { Bye } from "./bye";
33
+ import { Emitter, EmitterImpl } from "./emitter";
34
+ import { ContentTypeUnsupportedError, RequestPendingError } from "./exceptions";
35
+ import { Info } from "./info";
36
+ import { Inviter } from "./inviter";
37
+ import { InviterOptions } from "./inviter-options";
38
+ import { Message } from "./message";
39
+ import { Notification } from "./notification";
40
+ import { Referral } from "./referral";
41
+ import { SessionByeOptions } from "./session-bye-options";
42
+ import { SessionDelegate } from "./session-delegate";
43
+ import {
44
+ SessionDescriptionHandler,
45
+ SessionDescriptionHandlerModifier,
46
+ SessionDescriptionHandlerOptions
47
+ } from "./session-description-handler";
48
+ import { SessionDescriptionHandlerFactory } from "./session-description-handler-factory";
49
+ import { SessionInfoOptions } from "./session-info-options";
50
+ import { SessionInviteOptions } from "./session-invite-options";
51
+ import { SessionMessageOptions } from "./session-message-options";
52
+ import { SessionOptions } from "./session-options";
53
+ import { SessionReferOptions } from "./session-refer-options";
54
+ import { SessionState } from "./session-state";
55
+ import { UserAgent } from "./user-agent";
56
+
57
+ /**
58
+ * A session provides real time communication between one or more participants.
59
+ *
60
+ * @remarks
61
+ * The transport behaves in a deterministic manner according to the
62
+ * the state defined in {@link SessionState}.
63
+ * @public
64
+ */
65
+ export abstract class Session {
66
+ /**
67
+ * Property reserved for use by instance owner.
68
+ * @defaultValue `undefined`
69
+ */
70
+ public data: unknown;
71
+
72
+ /**
73
+ * The session delegate.
74
+ * @defaultValue `undefined`
75
+ */
76
+ public delegate: SessionDelegate | undefined;
77
+
78
+ //
79
+ // Public properties for internal use only
80
+ //
81
+ /** @internal */
82
+ public _contact: string | undefined;
83
+ /** @internal */
84
+ public _referral: Inviter | undefined;
85
+ /** @internal */
86
+ public _replacee: Session | undefined;
87
+
88
+ //
89
+ // Protected properties for internal use only
90
+ //
91
+ /** @internal */
92
+ protected _assertedIdentity: NameAddrHeader | undefined;
93
+ /** @internal */
94
+ protected _dialog: SessionDialog | undefined;
95
+ /** @internal */
96
+ protected _referralInviterOptions: InviterOptions | undefined; // FIXME: This is not getting set by Invitation
97
+ /** @internal */
98
+ protected _renderbody: string | undefined;
99
+ /** @internal */
100
+ protected _rendertype: string | undefined;
101
+
102
+ /** If defined, NOTIFYs associated with a REFER subscription are delivered here. */
103
+ private onNotify: ((notification: Notification) => void) | undefined;
104
+ /** True if there is an outgoing re-INVITE request outstanding. */
105
+ private pendingReinvite = false;
106
+ /** True if there is an incoming re-INVITE ACK request outstanding. */
107
+ private pendingReinviteAck = false;
108
+ /** Dialogs session description handler. */
109
+ private _sessionDescriptionHandler: SessionDescriptionHandler | undefined;
110
+ /** SDH modifiers for the initial INVITE transaction. */
111
+ private _sessionDescriptionHandlerModifiers: Array<SessionDescriptionHandlerModifier> | undefined;
112
+ /** SDH options for the initial INVITE transaction. */
113
+ private _sessionDescriptionHandlerOptions: SessionDescriptionHandlerOptions | undefined;
114
+ /** SDH modifiers for re-INVITE transactions. */
115
+ private _sessionDescriptionHandlerModifiersReInvite: Array<SessionDescriptionHandlerModifier> | undefined;
116
+ /** SDH options for re-NVITE transactions.*/
117
+ private _sessionDescriptionHandlerOptionsReInvite: SessionDescriptionHandlerOptions | undefined;
118
+ /** Session state. */
119
+ private _state: SessionState = SessionState.Initial;
120
+ /** Session state emitter. */
121
+ private _stateEventEmitter: EmitterImpl<SessionState>;
122
+ /** User agent. */
123
+ private _userAgent: UserAgent;
124
+
125
+ /**
126
+ * The identity of the local user.
127
+ */
128
+ public abstract readonly localIdentity: NameAddrHeader;
129
+
130
+ /**
131
+ * The identity of the remote user.
132
+ */
133
+ public abstract readonly remoteIdentity: NameAddrHeader;
134
+
135
+ /**
136
+ * Logger.
137
+ */
138
+ protected abstract logger: Logger;
139
+
140
+ /** @internal */
141
+ protected abstract _id: string;
142
+
143
+ /**
144
+ * Constructor.
145
+ * @param userAgent - User agent. See {@link UserAgent} for details.
146
+ * @internal
147
+ */
148
+ protected constructor(userAgent: UserAgent, options: SessionOptions = {}) {
149
+ this.delegate = options.delegate;
150
+ this._stateEventEmitter = new EmitterImpl<SessionState>();
151
+ this._userAgent = userAgent;
152
+ }
153
+
154
+ /**
155
+ * Destructor.
156
+ */
157
+ public dispose(): Promise<void> {
158
+ this.logger.log(`Session ${this.id} in state ${this._state} is being disposed`);
159
+
160
+ // Remove from the user agent's session collection
161
+ delete this.userAgent._sessions[this.id];
162
+
163
+ // Dispose of dialog media
164
+ if (this._sessionDescriptionHandler) {
165
+ this._sessionDescriptionHandler.close();
166
+
167
+ // TODO: The SDH needs to remain defined as it will be called after it is closed in cases
168
+ // where an answer/offer arrives while the session is being torn down. There are a variety
169
+ // of circumstances where this can happen - sending a BYE during a re-INVITE for example.
170
+ // The code is currently written such that it lazily makes a new SDH when it needs one
171
+ // and one is not yet defined. Thus if we undefined it here, it will currently make a
172
+ // new one which is out of sync and then never gets cleaned up.
173
+ //
174
+ // The downside of leaving it defined are that calls this closed SDH will continue to be
175
+ // made (think setDescription) and those should/will fail. These failures are handled, but
176
+ // it would be nice to have it all coded up in a way where having an undefined SDH where
177
+ // one is expected throws an error.
178
+ //
179
+ // this._sessionDescriptionHandler = undefined;
180
+ }
181
+
182
+ switch (this.state) {
183
+ case SessionState.Initial:
184
+ break; // the Inviter/Invitation sub class dispose method handles this case
185
+ case SessionState.Establishing:
186
+ break; // the Inviter/Invitation sub class dispose method handles this case
187
+ case SessionState.Established:
188
+ return new Promise((resolve) => {
189
+ this._bye({
190
+ // wait for the response to the BYE before resolving
191
+ onAccept: () => resolve(),
192
+ onRedirect: () => resolve(),
193
+ onReject: () => resolve()
194
+ });
195
+ });
196
+ case SessionState.Terminating:
197
+ break; // nothing to be done
198
+ case SessionState.Terminated:
199
+ break; // nothing to be done
200
+ default:
201
+ throw new Error("Unknown state.");
202
+ }
203
+
204
+ return Promise.resolve();
205
+ }
206
+
207
+ /**
208
+ * The asserted identity of the remote user.
209
+ */
210
+ public get assertedIdentity(): NameAddrHeader | undefined {
211
+ return this._assertedIdentity;
212
+ }
213
+
214
+ /**
215
+ * The confirmed session dialog.
216
+ */
217
+ public get dialog(): SessionDialog | undefined {
218
+ return this._dialog;
219
+ }
220
+
221
+ /**
222
+ * A unique identifier for this session.
223
+ */
224
+ public get id(): string {
225
+ return this._id;
226
+ }
227
+
228
+ /**
229
+ * The session being replace by this one.
230
+ */
231
+ public get replacee(): Session | undefined {
232
+ return this._replacee;
233
+ }
234
+
235
+ /**
236
+ * Session description handler.
237
+ * @remarks
238
+ * If `this` is an instance of `Invitation`,
239
+ * `sessionDescriptionHandler` will be defined when the session state changes to "established".
240
+ * If `this` is an instance of `Inviter` and an offer was sent in the INVITE,
241
+ * `sessionDescriptionHandler` will be defined when the session state changes to "establishing".
242
+ * If `this` is an instance of `Inviter` and an offer was not sent in the INVITE,
243
+ * `sessionDescriptionHandler` will be defined when the session state changes to "established".
244
+ * Otherwise `undefined`.
245
+ */
246
+ public get sessionDescriptionHandler(): SessionDescriptionHandler | undefined {
247
+ return this._sessionDescriptionHandler;
248
+ }
249
+
250
+ /**
251
+ * Session description handler factory.
252
+ */
253
+ public get sessionDescriptionHandlerFactory(): SessionDescriptionHandlerFactory {
254
+ return this.userAgent.configuration.sessionDescriptionHandlerFactory;
255
+ }
256
+
257
+ /**
258
+ * SDH modifiers for the initial INVITE transaction.
259
+ * @remarks
260
+ * Used in all cases when handling the initial INVITE transaction as either UAC or UAS.
261
+ * May be set directly at anytime.
262
+ * May optionally be set via constructor option.
263
+ * May optionally be set via options passed to Inviter.invite() or Invitation.accept().
264
+ */
265
+ public get sessionDescriptionHandlerModifiers(): Array<SessionDescriptionHandlerModifier> {
266
+ return this._sessionDescriptionHandlerModifiers || [];
267
+ }
268
+
269
+ public set sessionDescriptionHandlerModifiers(modifiers: Array<SessionDescriptionHandlerModifier>) {
270
+ this._sessionDescriptionHandlerModifiers = modifiers.slice();
271
+ }
272
+
273
+ /**
274
+ * SDH options for the initial INVITE transaction.
275
+ * @remarks
276
+ * Used in all cases when handling the initial INVITE transaction as either UAC or UAS.
277
+ * May be set directly at anytime.
278
+ * May optionally be set via constructor option.
279
+ * May optionally be set via options passed to Inviter.invite() or Invitation.accept().
280
+ */
281
+ public get sessionDescriptionHandlerOptions(): SessionDescriptionHandlerOptions {
282
+ return this._sessionDescriptionHandlerOptions || {};
283
+ }
284
+
285
+ public set sessionDescriptionHandlerOptions(options: SessionDescriptionHandlerOptions) {
286
+ this._sessionDescriptionHandlerOptions = { ...options };
287
+ }
288
+
289
+ /**
290
+ * SDH modifiers for re-INVITE transactions.
291
+ * @remarks
292
+ * Used in all cases when handling a re-INVITE transaction as either UAC or UAS.
293
+ * May be set directly at anytime.
294
+ * May optionally be set via constructor option.
295
+ * May optionally be set via options passed to Session.invite().
296
+ */
297
+ public get sessionDescriptionHandlerModifiersReInvite(): Array<SessionDescriptionHandlerModifier> {
298
+ return this._sessionDescriptionHandlerModifiersReInvite || [];
299
+ }
300
+
301
+ public set sessionDescriptionHandlerModifiersReInvite(modifiers: Array<SessionDescriptionHandlerModifier>) {
302
+ this._sessionDescriptionHandlerModifiersReInvite = modifiers.slice();
303
+ }
304
+
305
+ /**
306
+ * SDH options for re-INVITE transactions.
307
+ * @remarks
308
+ * Used in all cases when handling a re-INVITE transaction as either UAC or UAS.
309
+ * May be set directly at anytime.
310
+ * May optionally be set via constructor option.
311
+ * May optionally be set via options passed to Session.invite().
312
+ */
313
+ public get sessionDescriptionHandlerOptionsReInvite(): SessionDescriptionHandlerOptions {
314
+ return this._sessionDescriptionHandlerOptionsReInvite || {};
315
+ }
316
+
317
+ public set sessionDescriptionHandlerOptionsReInvite(options: SessionDescriptionHandlerOptions) {
318
+ this._sessionDescriptionHandlerOptionsReInvite = { ...options };
319
+ }
320
+
321
+ /**
322
+ * Session state.
323
+ */
324
+ public get state(): SessionState {
325
+ return this._state;
326
+ }
327
+
328
+ /**
329
+ * Session state change emitter.
330
+ */
331
+ public get stateChange(): Emitter<SessionState> {
332
+ return this._stateEventEmitter;
333
+ }
334
+
335
+ /**
336
+ * The user agent.
337
+ */
338
+ public get userAgent(): UserAgent {
339
+ return this._userAgent;
340
+ }
341
+
342
+ /**
343
+ * End the {@link Session}. Sends a BYE.
344
+ * @param options - Options bucket. See {@link SessionByeOptions} for details.
345
+ */
346
+ public bye(options: SessionByeOptions = {}): Promise<OutgoingByeRequest> {
347
+ let message = "Session.bye() may only be called if established session.";
348
+
349
+ switch (this.state) {
350
+ case SessionState.Initial:
351
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
352
+ if (typeof (this as any).cancel === "function") {
353
+ message += " However Inviter.invite() has not yet been called.";
354
+ message += " Perhaps you should have called Inviter.cancel()?";
355
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
356
+ } else if (typeof (this as any).reject === "function") {
357
+ message += " However Invitation.accept() has not yet been called.";
358
+ message += " Perhaps you should have called Invitation.reject()?";
359
+ }
360
+ break;
361
+ case SessionState.Establishing:
362
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
363
+ if (typeof (this as any).cancel === "function") {
364
+ message += " However a dialog does not yet exist.";
365
+ message += " Perhaps you should have called Inviter.cancel()?";
366
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
367
+ } else if (typeof (this as any).reject === "function") {
368
+ message += " However Invitation.accept() has not yet been called (or not yet resolved).";
369
+ message += " Perhaps you should have called Invitation.reject()?";
370
+ }
371
+ break;
372
+ case SessionState.Established: {
373
+ const requestDelegate = options.requestDelegate;
374
+ const requestOptions = this.copyRequestOptions(options.requestOptions);
375
+ return this._bye(requestDelegate, requestOptions);
376
+ }
377
+ case SessionState.Terminating:
378
+ message += " However this session is already terminating.";
379
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
380
+ if (typeof (this as any).cancel === "function") {
381
+ message += " Perhaps you have already called Inviter.cancel()?";
382
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
383
+ } else if (typeof (this as any).reject === "function") {
384
+ message += " Perhaps you have already called Session.bye()?";
385
+ }
386
+ break;
387
+ case SessionState.Terminated:
388
+ message += " However this session is already terminated.";
389
+ break;
390
+ default:
391
+ throw new Error("Unknown state");
392
+ }
393
+
394
+ this.logger.error(message);
395
+ return Promise.reject(new Error(`Invalid session state ${this.state}`));
396
+ }
397
+
398
+ /**
399
+ * Share {@link Info} with peer. Sends an INFO.
400
+ * @param options - Options bucket. See {@link SessionInfoOptions} for details.
401
+ */
402
+ public info(options: SessionInfoOptions = {}): Promise<OutgoingInfoRequest> {
403
+ // guard session state
404
+ if (this.state !== SessionState.Established) {
405
+ const message = "Session.info() may only be called if established session.";
406
+ this.logger.error(message);
407
+ return Promise.reject(new Error(`Invalid session state ${this.state}`));
408
+ }
409
+
410
+ const requestDelegate = options.requestDelegate;
411
+ const requestOptions = this.copyRequestOptions(options.requestOptions);
412
+ return this._info(requestDelegate, requestOptions);
413
+ }
414
+
415
+ /**
416
+ * Renegotiate the session. Sends a re-INVITE.
417
+ * @param options - Options bucket. See {@link SessionInviteOptions} for details.
418
+ */
419
+ public invite(options: SessionInviteOptions = {}): Promise<OutgoingInviteRequest> {
420
+ this.logger.log("Session.invite");
421
+ if (this.state !== SessionState.Established) {
422
+ return Promise.reject(new Error(`Invalid session state ${this.state}`));
423
+ }
424
+ if (this.pendingReinvite) {
425
+ return Promise.reject(
426
+ new RequestPendingError("Reinvite in progress. Please wait until complete, then try again.")
427
+ );
428
+ }
429
+ this.pendingReinvite = true;
430
+
431
+ // Modifiers and options for initial INVITE transaction
432
+ if (options.sessionDescriptionHandlerModifiers) {
433
+ this.sessionDescriptionHandlerModifiersReInvite = options.sessionDescriptionHandlerModifiers;
434
+ }
435
+ if (options.sessionDescriptionHandlerOptions) {
436
+ this.sessionDescriptionHandlerOptionsReInvite = options.sessionDescriptionHandlerOptions;
437
+ }
438
+
439
+ const delegate: OutgoingInviteRequestDelegate = {
440
+ onAccept: (response): void => {
441
+ // A re-INVITE transaction has an offer/answer [RFC3264] exchange
442
+ // associated with it. The UAC (User Agent Client) generating a given
443
+ // re-INVITE can act as the offerer or as the answerer. A UAC willing
444
+ // to act as the offerer includes an offer in the re-INVITE. The UAS
445
+ // (User Agent Server) then provides an answer in a response to the
446
+ // re-INVITE. A UAC willing to act as answerer does not include an
447
+ // offer in the re-INVITE. The UAS then provides an offer in a response
448
+ // to the re-INVITE becoming, thus, the offerer.
449
+ // https://tools.ietf.org/html/rfc6141#section-1
450
+ const body = getBody(response.message);
451
+ if (!body) {
452
+ // No way to recover, so terminate session and mark as failed.
453
+ this.logger.error("Received 2xx response to re-INVITE without a session description");
454
+ this.ackAndBye(response, 400, "Missing session description");
455
+ this.stateTransition(SessionState.Terminated);
456
+ this.pendingReinvite = false;
457
+ return;
458
+ }
459
+
460
+ if (options.withoutSdp) {
461
+ // INVITE without SDP - set remote offer and send an answer in the ACK
462
+ const answerOptions = {
463
+ sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptionsReInvite,
464
+ sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiersReInvite
465
+ };
466
+ this.setOfferAndGetAnswer(body, answerOptions)
467
+ .then((answerBody) => {
468
+ response.ack({ body: answerBody });
469
+ })
470
+ .catch((error: Error) => {
471
+ // No way to recover, so terminate session and mark as failed.
472
+ this.logger.error("Failed to handle offer in 2xx response to re-INVITE");
473
+ this.logger.error(error.message);
474
+ if (this.state === SessionState.Terminated) {
475
+ // A BYE should not be sent if already terminated.
476
+ // For example, a BYE may be sent/received while re-INVITE is outstanding.
477
+ response.ack();
478
+ } else {
479
+ this.ackAndBye(response, 488, "Bad Media Description");
480
+ this.stateTransition(SessionState.Terminated);
481
+ }
482
+ })
483
+ .then(() => {
484
+ this.pendingReinvite = false;
485
+ if (options.requestDelegate && options.requestDelegate.onAccept) {
486
+ options.requestDelegate.onAccept(response);
487
+ }
488
+ });
489
+ } else {
490
+ // INVITE with SDP - set remote answer and send an ACK
491
+ const answerOptions = {
492
+ sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptionsReInvite,
493
+ sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiersReInvite
494
+ };
495
+ this.setAnswer(body, answerOptions)
496
+ .then(() => {
497
+ response.ack();
498
+ })
499
+ .catch((error: Error) => {
500
+ // No way to recover, so terminate session and mark as failed.
501
+ this.logger.error("Failed to handle answer in 2xx response to re-INVITE");
502
+ this.logger.error(error.message);
503
+ // A BYE should only be sent if session is not already terminated.
504
+ // For example, a BYE may be sent/received while re-INVITE is outstanding.
505
+ // The ACK needs to be sent regardless as it was not handled by the transaction.
506
+ if (this.state !== SessionState.Terminated) {
507
+ this.ackAndBye(response, 488, "Bad Media Description");
508
+ this.stateTransition(SessionState.Terminated);
509
+ } else {
510
+ response.ack();
511
+ }
512
+ })
513
+ .then(() => {
514
+ this.pendingReinvite = false;
515
+ if (options.requestDelegate && options.requestDelegate.onAccept) {
516
+ options.requestDelegate.onAccept(response);
517
+ }
518
+ });
519
+ }
520
+ },
521
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
522
+ onProgress: (response): void => {
523
+ return;
524
+ },
525
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
526
+ onRedirect: (response): void => {
527
+ return;
528
+ },
529
+ onReject: (response): void => {
530
+ this.logger.warn("Received a non-2xx response to re-INVITE");
531
+ this.pendingReinvite = false;
532
+ if (options.withoutSdp) {
533
+ if (options.requestDelegate && options.requestDelegate.onReject) {
534
+ options.requestDelegate.onReject(response);
535
+ }
536
+ } else {
537
+ this.rollbackOffer()
538
+ .catch((error: Error) => {
539
+ // No way to recover, so terminate session and mark as failed.
540
+ this.logger.error("Failed to rollback offer on non-2xx response to re-INVITE");
541
+ this.logger.error(error.message);
542
+ // A BYE should only be sent if session is not already terminated.
543
+ // For example, a BYE may be sent/received while re-INVITE is outstanding.
544
+ // Note that the ACK was already sent by the transaction, so just need to send BYE.
545
+ if (this.state !== SessionState.Terminated) {
546
+ if (!this.dialog) {
547
+ throw new Error("Dialog undefined.");
548
+ }
549
+ const extraHeaders: Array<string> = [];
550
+ extraHeaders.push("Reason: " + this.getReasonHeaderValue(500, "Internal Server Error"));
551
+ this.dialog.bye(undefined, { extraHeaders });
552
+ this.stateTransition(SessionState.Terminated);
553
+ }
554
+ })
555
+ .then(() => {
556
+ if (options.requestDelegate && options.requestDelegate.onReject) {
557
+ options.requestDelegate.onReject(response);
558
+ }
559
+ });
560
+ }
561
+ },
562
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
563
+ onTrying: (response): void => {
564
+ return;
565
+ }
566
+ };
567
+
568
+ const requestOptions = options.requestOptions || {};
569
+ requestOptions.extraHeaders = (requestOptions.extraHeaders || []).slice();
570
+ requestOptions.extraHeaders.push("Allow: " + AllowedMethods.toString());
571
+ requestOptions.extraHeaders.push("Contact: " + this._contact);
572
+
573
+ // Just send an INVITE with no sdp...
574
+ if (options.withoutSdp) {
575
+ if (!this.dialog) {
576
+ this.pendingReinvite = false;
577
+ throw new Error("Dialog undefined.");
578
+ }
579
+ return Promise.resolve(this.dialog.invite(delegate, requestOptions));
580
+ }
581
+
582
+ // Get an offer and send it in an INVITE
583
+ const offerOptions = {
584
+ sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptionsReInvite,
585
+ sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiersReInvite
586
+ };
587
+ return this.getOffer(offerOptions)
588
+ .then((offerBody) => {
589
+ if (!this.dialog) {
590
+ this.pendingReinvite = false;
591
+ throw new Error("Dialog undefined.");
592
+ }
593
+ requestOptions.body = offerBody;
594
+ return this.dialog.invite(delegate, requestOptions);
595
+ })
596
+ .catch((error: Error) => {
597
+ this.logger.error(error.message);
598
+ this.logger.error("Failed to send re-INVITE");
599
+ this.pendingReinvite = false;
600
+ throw error;
601
+ });
602
+ }
603
+
604
+ /**
605
+ * Deliver a {@link Message}. Sends a MESSAGE.
606
+ * @param options - Options bucket. See {@link SessionMessageOptions} for details.
607
+ */
608
+ public message(options: SessionMessageOptions = {}): Promise<OutgoingMessageRequest> {
609
+ // guard session state
610
+ if (this.state !== SessionState.Established) {
611
+ const message = "Session.message() may only be called if established session.";
612
+ this.logger.error(message);
613
+ return Promise.reject(new Error(`Invalid session state ${this.state}`));
614
+ }
615
+
616
+ const requestDelegate = options.requestDelegate;
617
+ const requestOptions = this.copyRequestOptions(options.requestOptions);
618
+ return this._message(requestDelegate, requestOptions);
619
+ }
620
+
621
+ /**
622
+ * Proffer a {@link Referral}. Send a REFER.
623
+ * @param referTo - The referral target. If a `Session`, a REFER w/Replaces is sent.
624
+ * @param options - Options bucket. See {@link SessionReferOptions} for details.
625
+ */
626
+ public refer(referTo: URI | Session, options: SessionReferOptions = {}): Promise<OutgoingReferRequest> {
627
+ // guard session state
628
+ if (this.state !== SessionState.Established) {
629
+ const message = "Session.refer() may only be called if established session.";
630
+ this.logger.error(message);
631
+ return Promise.reject(new Error(`Invalid session state ${this.state}`));
632
+ }
633
+
634
+ const requestDelegate = options.requestDelegate;
635
+ const requestOptions = this.copyRequestOptions(options.requestOptions);
636
+ requestOptions.extraHeaders = requestOptions.extraHeaders
637
+ ? requestOptions.extraHeaders.concat(this.referExtraHeaders(this.referToString(referTo)))
638
+ : this.referExtraHeaders(this.referToString(referTo));
639
+ return this._refer(options.onNotify, requestDelegate, requestOptions);
640
+ }
641
+
642
+ /**
643
+ * Send BYE.
644
+ * @param delegate - Request delegate.
645
+ * @param options - Request options bucket.
646
+ * @internal
647
+ */
648
+ public _bye(delegate?: OutgoingRequestDelegate, options?: RequestOptions): Promise<OutgoingByeRequest> {
649
+ // Using core session dialog
650
+ if (!this.dialog) {
651
+ return Promise.reject(new Error("Session dialog undefined."));
652
+ }
653
+ const dialog = this.dialog;
654
+
655
+ // The caller's UA MAY send a BYE for either confirmed or early dialogs,
656
+ // and the callee's UA MAY send a BYE on confirmed dialogs, but MUST NOT
657
+ // send a BYE on early dialogs. However, the callee's UA MUST NOT send a
658
+ // BYE on a confirmed dialog until it has received an ACK for its 2xx
659
+ // response or until the server transaction times out.
660
+ // https://tools.ietf.org/html/rfc3261#section-15
661
+ switch (dialog.sessionState) {
662
+ case SessionDialogState.Initial:
663
+ throw new Error(`Invalid dialog state ${dialog.sessionState}`);
664
+ case SessionDialogState.Early: // Implementation choice - not sending BYE for early dialogs.
665
+ throw new Error(`Invalid dialog state ${dialog.sessionState}`);
666
+ case SessionDialogState.AckWait: {
667
+ // This state only occurs if we are the callee.
668
+ this.stateTransition(SessionState.Terminating); // We're terminating
669
+ return new Promise((resolve) => {
670
+ dialog.delegate = {
671
+ // When ACK shows up, say BYE.
672
+ onAck: (): Promise<void> => {
673
+ const request = dialog.bye(delegate, options);
674
+ this.stateTransition(SessionState.Terminated);
675
+ resolve(request);
676
+ return Promise.resolve();
677
+ },
678
+ // Or the server transaction times out before the ACK arrives.
679
+ onAckTimeout: (): void => {
680
+ const request = dialog.bye(delegate, options);
681
+ this.stateTransition(SessionState.Terminated);
682
+ resolve(request);
683
+ }
684
+ };
685
+ });
686
+ }
687
+ case SessionDialogState.Confirmed: {
688
+ const request = dialog.bye(delegate, options);
689
+ this.stateTransition(SessionState.Terminated);
690
+ return Promise.resolve(request);
691
+ }
692
+ case SessionDialogState.Terminated:
693
+ throw new Error(`Invalid dialog state ${dialog.sessionState}`);
694
+ default:
695
+ throw new Error("Unrecognized state.");
696
+ }
697
+ }
698
+
699
+ /**
700
+ * Send INFO.
701
+ * @param delegate - Request delegate.
702
+ * @param options - Request options bucket.
703
+ * @internal
704
+ */
705
+ public _info(delegate?: OutgoingRequestDelegate, options?: RequestOptions): Promise<OutgoingInfoRequest> {
706
+ // Using core session dialog
707
+ if (!this.dialog) {
708
+ return Promise.reject(new Error("Session dialog undefined."));
709
+ }
710
+ return Promise.resolve(this.dialog.info(delegate, options));
711
+ }
712
+
713
+ /**
714
+ * Send MESSAGE.
715
+ * @param delegate - Request delegate.
716
+ * @param options - Request options bucket.
717
+ * @internal
718
+ */
719
+ public _message(delegate?: OutgoingRequestDelegate, options?: RequestOptions): Promise<OutgoingMessageRequest> {
720
+ // Using core session dialog
721
+ if (!this.dialog) {
722
+ return Promise.reject(new Error("Session dialog undefined."));
723
+ }
724
+ return Promise.resolve(this.dialog.message(delegate, options));
725
+ }
726
+
727
+ /**
728
+ * Send REFER.
729
+ * @param onNotify - Notification callback.
730
+ * @param delegate - Request delegate.
731
+ * @param options - Request options bucket.
732
+ * @internal
733
+ */
734
+ public _refer(
735
+ onNotify?: (notification: Notification) => void,
736
+ delegate?: OutgoingRequestDelegate,
737
+ options?: RequestOptions
738
+ ): Promise<OutgoingByeRequest> {
739
+ // Using core session dialog
740
+ if (!this.dialog) {
741
+ return Promise.reject(new Error("Session dialog undefined."));
742
+ }
743
+ // If set, deliver any in-dialog NOTIFY requests here...
744
+ this.onNotify = onNotify;
745
+ return Promise.resolve(this.dialog.refer(delegate, options));
746
+ }
747
+
748
+ /**
749
+ * Send ACK and then BYE. There are unrecoverable errors which can occur
750
+ * while handling dialog forming and in-dialog INVITE responses and when
751
+ * they occur we ACK the response and send a BYE.
752
+ * Note that the BYE is sent in the dialog associated with the response
753
+ * which is not necessarily `this.dialog`. And, accordingly, the
754
+ * session state is not transitioned to terminated and session is not closed.
755
+ * @param inviteResponse - The response causing the error.
756
+ * @param statusCode - Status code for he reason phrase.
757
+ * @param reasonPhrase - Reason phrase for the BYE.
758
+ * @internal
759
+ */
760
+ protected ackAndBye(response: AckableIncomingResponseWithSession, statusCode?: number, reasonPhrase?: string): void {
761
+ response.ack();
762
+ const extraHeaders: Array<string> = [];
763
+ if (statusCode) {
764
+ extraHeaders.push("Reason: " + this.getReasonHeaderValue(statusCode, reasonPhrase));
765
+ }
766
+ // Using the dialog session associate with the response (which might not be this.dialog)
767
+ response.session.bye(undefined, { extraHeaders });
768
+ }
769
+
770
+ /**
771
+ * Handle in dialog ACK request.
772
+ * @internal
773
+ */
774
+ protected onAckRequest(request: IncomingAckRequest): Promise<void> {
775
+ this.logger.log("Session.onAckRequest");
776
+ if (this.state !== SessionState.Established && this.state !== SessionState.Terminating) {
777
+ this.logger.error(`ACK received while in state ${this.state}, dropping request`);
778
+ return Promise.resolve();
779
+ }
780
+
781
+ const dialog = this.dialog;
782
+ if (!dialog) {
783
+ throw new Error("Dialog undefined.");
784
+ }
785
+
786
+ // if received answer in ACK.
787
+ const answerOptions = {
788
+ sessionDescriptionHandlerOptions: this.pendingReinviteAck
789
+ ? this.sessionDescriptionHandlerOptionsReInvite
790
+ : this.sessionDescriptionHandlerOptions,
791
+ sessionDescriptionHandlerModifiers: this.pendingReinviteAck
792
+ ? this._sessionDescriptionHandlerModifiersReInvite
793
+ : this._sessionDescriptionHandlerModifiers
794
+ };
795
+
796
+ // reset pending ACK flag
797
+ this.pendingReinviteAck = false;
798
+
799
+ switch (dialog.signalingState) {
800
+ case SignalingState.Initial: {
801
+ // State should never be reached as first reliable response must have answer/offer.
802
+ // So we must have never has sent an offer.
803
+ this.logger.error(`Invalid signaling state ${dialog.signalingState}.`);
804
+ const extraHeaders = ["Reason: " + this.getReasonHeaderValue(488, "Bad Media Description")];
805
+ dialog.bye(undefined, { extraHeaders });
806
+ this.stateTransition(SessionState.Terminated);
807
+ return Promise.resolve();
808
+ }
809
+ case SignalingState.Stable: {
810
+ // State we should be in.
811
+ // Either the ACK has the answer that got us here, or we were in this state prior to the ACK.
812
+ const body = getBody(request.message);
813
+ // If the ACK doesn't have an answer, nothing to be done.
814
+ if (!body) {
815
+ return Promise.resolve();
816
+ }
817
+ if (body.contentDisposition === "render") {
818
+ this._renderbody = body.content;
819
+ this._rendertype = body.contentType;
820
+ return Promise.resolve();
821
+ }
822
+ if (body.contentDisposition !== "session") {
823
+ return Promise.resolve();
824
+ }
825
+ return this.setAnswer(body, answerOptions).catch((error: Error) => {
826
+ this.logger.error(error.message);
827
+ const extraHeaders = ["Reason: " + this.getReasonHeaderValue(488, "Bad Media Description")];
828
+ dialog.bye(undefined, { extraHeaders });
829
+ this.stateTransition(SessionState.Terminated);
830
+ });
831
+ }
832
+ case SignalingState.HaveLocalOffer: {
833
+ // State should never be reached as local offer would be answered by this ACK.
834
+ // So we must have received an ACK without an answer.
835
+ this.logger.error(`Invalid signaling state ${dialog.signalingState}.`);
836
+ const extraHeaders = ["Reason: " + this.getReasonHeaderValue(488, "Bad Media Description")];
837
+ dialog.bye(undefined, { extraHeaders });
838
+ this.stateTransition(SessionState.Terminated);
839
+ return Promise.resolve();
840
+ }
841
+ case SignalingState.HaveRemoteOffer: {
842
+ // State should never be reached as remote offer would be answered in first reliable response.
843
+ // So we must have never has sent an answer.
844
+ this.logger.error(`Invalid signaling state ${dialog.signalingState}.`);
845
+ const extraHeaders = ["Reason: " + this.getReasonHeaderValue(488, "Bad Media Description")];
846
+ dialog.bye(undefined, { extraHeaders });
847
+ this.stateTransition(SessionState.Terminated);
848
+ return Promise.resolve();
849
+ }
850
+ case SignalingState.Closed:
851
+ throw new Error(`Invalid signaling state ${dialog.signalingState}.`);
852
+ default:
853
+ throw new Error(`Invalid signaling state ${dialog.signalingState}.`);
854
+ }
855
+ }
856
+
857
+ /**
858
+ * Handle in dialog BYE request.
859
+ * @internal
860
+ */
861
+ protected onByeRequest(request: IncomingByeRequest): void {
862
+ this.logger.log("Session.onByeRequest");
863
+ if (this.state !== SessionState.Established) {
864
+ this.logger.error(`BYE received while in state ${this.state}, dropping request`);
865
+ return;
866
+ }
867
+ if (this.delegate && this.delegate.onBye) {
868
+ const bye = new Bye(request);
869
+ this.delegate.onBye(bye);
870
+ } else {
871
+ request.accept();
872
+ }
873
+ this.stateTransition(SessionState.Terminated);
874
+ }
875
+
876
+ /**
877
+ * Handle in dialog INFO request.
878
+ * @internal
879
+ */
880
+ protected onInfoRequest(request: IncomingInfoRequest): void {
881
+ this.logger.log("Session.onInfoRequest");
882
+ if (this.state !== SessionState.Established) {
883
+ this.logger.error(`INFO received while in state ${this.state}, dropping request`);
884
+ return;
885
+ }
886
+
887
+ if (this.delegate && this.delegate.onInfo) {
888
+ const info = new Info(request);
889
+ this.delegate.onInfo(info);
890
+ } else {
891
+ // FIXME: TODO: We should reject request...
892
+ //
893
+ // If a UA receives an INFO request associated with an Info Package that
894
+ // the UA has not indicated willingness to receive, the UA MUST send a
895
+ // 469 (Bad Info Package) response (see Section 11.6), which contains a
896
+ // Recv-Info header field with Info Packages for which the UA is willing
897
+ // to receive INFO requests.
898
+ // https://tools.ietf.org/html/rfc6086#section-4.2.2
899
+ request.accept();
900
+ }
901
+ }
902
+
903
+ /**
904
+ * Handle in dialog INVITE request.
905
+ * @internal
906
+ */
907
+ protected onInviteRequest(request: IncomingInviteRequest): void {
908
+ this.logger.log("Session.onInviteRequest");
909
+ if (this.state !== SessionState.Established) {
910
+ this.logger.error(`INVITE received while in state ${this.state}, dropping request`);
911
+ return;
912
+ }
913
+
914
+ // set pending ACK flag
915
+ this.pendingReinviteAck = true;
916
+
917
+ // TODO: would be nice to have core track and set the Contact header,
918
+ // but currently the session which is setting it is holding onto it.
919
+ const extraHeaders = ["Contact: " + this._contact];
920
+
921
+ // Handle P-Asserted-Identity
922
+ if (request.message.hasHeader("P-Asserted-Identity")) {
923
+ const header = request.message.getHeader("P-Asserted-Identity");
924
+ if (!header) {
925
+ throw new Error("Header undefined.");
926
+ }
927
+ this._assertedIdentity = Grammar.nameAddrHeaderParse(header);
928
+ }
929
+
930
+ const options = {
931
+ sessionDescriptionHandlerOptions: this.sessionDescriptionHandlerOptionsReInvite,
932
+ sessionDescriptionHandlerModifiers: this.sessionDescriptionHandlerModifiersReInvite
933
+ };
934
+ this.generateResponseOfferAnswerInDialog(options)
935
+ .then((body) => {
936
+ const outgoingResponse = request.accept({ statusCode: 200, extraHeaders, body });
937
+ if (this.delegate && this.delegate.onInvite) {
938
+ this.delegate.onInvite(request.message, outgoingResponse.message, 200);
939
+ }
940
+ })
941
+ .catch((error: Error) => {
942
+ this.logger.error(error.message);
943
+ this.logger.error("Failed to handle to re-INVITE request");
944
+ if (!this.dialog) {
945
+ throw new Error("Dialog undefined.");
946
+ }
947
+ this.logger.error(this.dialog.signalingState);
948
+ // If we don't have a local/remote offer...
949
+ if (this.dialog.signalingState === SignalingState.Stable) {
950
+ const outgoingResponse = request.reject({ statusCode: 488 }); // Not Acceptable Here
951
+ if (this.delegate && this.delegate.onInvite) {
952
+ this.delegate.onInvite(request.message, outgoingResponse.message, 488);
953
+ }
954
+ return;
955
+ }
956
+ // Otherwise rollback
957
+ this.rollbackOffer()
958
+ .then(() => {
959
+ const outgoingResponse = request.reject({ statusCode: 488 }); // Not Acceptable Here
960
+ if (this.delegate && this.delegate.onInvite) {
961
+ this.delegate.onInvite(request.message, outgoingResponse.message, 488);
962
+ }
963
+ })
964
+ .catch((errorRollback: Error) => {
965
+ // No way to recover, so terminate session and mark as failed.
966
+ this.logger.error(errorRollback.message);
967
+ this.logger.error("Failed to rollback offer on re-INVITE request");
968
+ const outgoingResponse = request.reject({ statusCode: 488 }); // Not Acceptable Here
969
+ // A BYE should only be sent if session is not already terminated.
970
+ // For example, a BYE may be sent/received while re-INVITE is outstanding.
971
+ // Note that the ACK was already sent by the transaction, so just need to send BYE.
972
+ if (this.state !== SessionState.Terminated) {
973
+ if (!this.dialog) {
974
+ throw new Error("Dialog undefined.");
975
+ }
976
+ const extraHeadersBye: Array<string> = [];
977
+ extraHeadersBye.push("Reason: " + this.getReasonHeaderValue(500, "Internal Server Error"));
978
+ this.dialog.bye(undefined, { extraHeaders });
979
+ this.stateTransition(SessionState.Terminated);
980
+ }
981
+ if (this.delegate && this.delegate.onInvite) {
982
+ this.delegate.onInvite(request.message, outgoingResponse.message, 488);
983
+ }
984
+ });
985
+ });
986
+ }
987
+
988
+ /**
989
+ * Handle in dialog MESSAGE request.
990
+ * @internal
991
+ */
992
+ protected onMessageRequest(request: IncomingMessageRequest): void {
993
+ this.logger.log("Session.onMessageRequest");
994
+ if (this.state !== SessionState.Established) {
995
+ this.logger.error(`MESSAGE received while in state ${this.state}, dropping request`);
996
+ return;
997
+ }
998
+
999
+ if (this.delegate && this.delegate.onMessage) {
1000
+ const message = new Message(request);
1001
+ this.delegate.onMessage(message);
1002
+ } else {
1003
+ request.accept();
1004
+ }
1005
+ }
1006
+
1007
+ /**
1008
+ * Handle in dialog NOTIFY request.
1009
+ * @internal
1010
+ */
1011
+ protected onNotifyRequest(request: IncomingNotifyRequest): void {
1012
+ this.logger.log("Session.onNotifyRequest");
1013
+ if (this.state !== SessionState.Established) {
1014
+ this.logger.error(`NOTIFY received while in state ${this.state}, dropping request`);
1015
+ return;
1016
+ }
1017
+
1018
+ // If this a NOTIFY associated with the progress of a REFER,
1019
+ // look to delegate handling to the associated callback.
1020
+ if (this.onNotify) {
1021
+ const notification = new Notification(request);
1022
+ this.onNotify(notification);
1023
+ return;
1024
+ }
1025
+
1026
+ // Otherwise accept the NOTIFY.
1027
+ if (this.delegate && this.delegate.onNotify) {
1028
+ const notification = new Notification(request);
1029
+ this.delegate.onNotify(notification);
1030
+ } else {
1031
+ request.accept();
1032
+ }
1033
+ }
1034
+
1035
+ /**
1036
+ * Handle in dialog PRACK request.
1037
+ * @internal
1038
+ */
1039
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1040
+ protected onPrackRequest(request: IncomingPrackRequest): void {
1041
+ this.logger.log("Session.onPrackRequest");
1042
+ if (this.state !== SessionState.Established) {
1043
+ this.logger.error(`PRACK received while in state ${this.state}, dropping request`);
1044
+ return;
1045
+ }
1046
+
1047
+ throw new Error("Unimplemented.");
1048
+ }
1049
+
1050
+ /**
1051
+ * Handle in dialog REFER request.
1052
+ * @internal
1053
+ */
1054
+ protected onReferRequest(request: IncomingReferRequest): void {
1055
+ this.logger.log("Session.onReferRequest");
1056
+ if (this.state !== SessionState.Established) {
1057
+ this.logger.error(`REFER received while in state ${this.state}, dropping request`);
1058
+ return;
1059
+ }
1060
+
1061
+ // REFER is a SIP request and is constructed as defined in [1]. A REFER
1062
+ // request MUST contain exactly one Refer-To header field value.
1063
+ // https://tools.ietf.org/html/rfc3515#section-2.4.1
1064
+ if (!request.message.hasHeader("refer-to")) {
1065
+ this.logger.warn("Invalid REFER packet. A refer-to header is required. Rejecting.");
1066
+ request.reject();
1067
+ return;
1068
+ }
1069
+
1070
+ const referral = new Referral(request, this);
1071
+
1072
+ if (this.delegate && this.delegate.onRefer) {
1073
+ this.delegate.onRefer(referral);
1074
+ } else {
1075
+ this.logger.log("No delegate available to handle REFER, automatically accepting and following.");
1076
+ referral
1077
+ .accept()
1078
+ .then(() => referral.makeInviter(this._referralInviterOptions).invite())
1079
+ .catch((error: Error) => {
1080
+ // FIXME: logging and eating error...
1081
+ this.logger.error(error.message);
1082
+ });
1083
+ }
1084
+ }
1085
+
1086
+ /**
1087
+ * Generate an offer or answer for a response to an INVITE request.
1088
+ * If a remote offer was provided in the request, set the remote
1089
+ * description and get a local answer. If a remote offer was not
1090
+ * provided, generates a local offer.
1091
+ * @internal
1092
+ */
1093
+ protected generateResponseOfferAnswer(
1094
+ request: IncomingInviteRequest,
1095
+ options: {
1096
+ sessionDescriptionHandlerOptions?: SessionDescriptionHandlerOptions;
1097
+ sessionDescriptionHandlerModifiers?: Array<SessionDescriptionHandlerModifier>;
1098
+ }
1099
+ ): Promise<Body | undefined> {
1100
+ if (this.dialog) {
1101
+ return this.generateResponseOfferAnswerInDialog(options);
1102
+ }
1103
+ const body = getBody(request.message);
1104
+ if (!body || body.contentDisposition !== "session") {
1105
+ return this.getOffer(options);
1106
+ } else {
1107
+ return this.setOfferAndGetAnswer(body, options);
1108
+ }
1109
+ }
1110
+
1111
+ /**
1112
+ * Generate an offer or answer for a response to an INVITE request
1113
+ * when a dialog (early or otherwise) has already been established.
1114
+ * This method may NOT be called if a dialog has yet to be established.
1115
+ * @internal
1116
+ */
1117
+ protected generateResponseOfferAnswerInDialog(options: {
1118
+ sessionDescriptionHandlerOptions?: SessionDescriptionHandlerOptions;
1119
+ sessionDescriptionHandlerModifiers?: Array<SessionDescriptionHandlerModifier>;
1120
+ }): Promise<Body | undefined> {
1121
+ if (!this.dialog) {
1122
+ throw new Error("Dialog undefined.");
1123
+ }
1124
+ switch (this.dialog.signalingState) {
1125
+ case SignalingState.Initial:
1126
+ return this.getOffer(options);
1127
+ case SignalingState.HaveLocalOffer:
1128
+ // o Once the UAS has sent or received an answer to the initial
1129
+ // offer, it MUST NOT generate subsequent offers in any responses
1130
+ // to the initial INVITE. This means that a UAS based on this
1131
+ // specification alone can never generate subsequent offers until
1132
+ // completion of the initial transaction.
1133
+ // https://tools.ietf.org/html/rfc3261#section-13.2.1
1134
+ return Promise.resolve(undefined);
1135
+ case SignalingState.HaveRemoteOffer:
1136
+ if (!this.dialog.offer) {
1137
+ throw new Error(`Session offer undefined in signaling state ${this.dialog.signalingState}.`);
1138
+ }
1139
+ return this.setOfferAndGetAnswer(this.dialog.offer, options);
1140
+ case SignalingState.Stable:
1141
+ // o Once the UAS has sent or received an answer to the initial
1142
+ // offer, it MUST NOT generate subsequent offers in any responses
1143
+ // to the initial INVITE. This means that a UAS based on this
1144
+ // specification alone can never generate subsequent offers until
1145
+ // completion of the initial transaction.
1146
+ // https://tools.ietf.org/html/rfc3261#section-13.2.1
1147
+ if (this.state !== SessionState.Established) {
1148
+ return Promise.resolve(undefined);
1149
+ }
1150
+ // In dialog INVITE without offer, get an offer for the response.
1151
+ return this.getOffer(options);
1152
+ case SignalingState.Closed:
1153
+ throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);
1154
+ default:
1155
+ throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);
1156
+ }
1157
+ }
1158
+
1159
+ /**
1160
+ * Get local offer.
1161
+ * @internal
1162
+ */
1163
+ protected getOffer(options: {
1164
+ sessionDescriptionHandlerOptions?: SessionDescriptionHandlerOptions;
1165
+ sessionDescriptionHandlerModifiers?: Array<SessionDescriptionHandlerModifier>;
1166
+ }): Promise<Body> {
1167
+ const sdh = this.setupSessionDescriptionHandler();
1168
+ const sdhOptions = options.sessionDescriptionHandlerOptions;
1169
+ const sdhModifiers = options.sessionDescriptionHandlerModifiers;
1170
+ // This is intentionally written very defensively. Don't trust SDH to behave.
1171
+ try {
1172
+ return sdh
1173
+ .getDescription(sdhOptions, sdhModifiers)
1174
+ .then((bodyAndContentType) => fromBodyLegacy(bodyAndContentType))
1175
+ .catch((error: unknown) => {
1176
+ // don't trust SDH to reject with Error
1177
+ this.logger.error("Session.getOffer: SDH getDescription rejected...");
1178
+ const e = error instanceof Error ? error : new Error("Session.getOffer unknown error.");
1179
+ this.logger.error(e.message);
1180
+ throw e;
1181
+ });
1182
+ } catch (error) {
1183
+ // don't trust SDH to throw an Error
1184
+ this.logger.error("Session.getOffer: SDH getDescription threw...");
1185
+ const e = error instanceof Error ? error : new Error(error);
1186
+ this.logger.error(e.message);
1187
+ return Promise.reject(e);
1188
+ }
1189
+ }
1190
+
1191
+ /**
1192
+ * Rollback local/remote offer.
1193
+ * @internal
1194
+ */
1195
+ protected rollbackOffer(): Promise<void> {
1196
+ const sdh = this.setupSessionDescriptionHandler();
1197
+ if (sdh.rollbackDescription === undefined) {
1198
+ return Promise.resolve();
1199
+ }
1200
+ // This is intentionally written very defensively. Don't trust SDH to behave.
1201
+ try {
1202
+ return sdh.rollbackDescription().catch((error: unknown) => {
1203
+ // don't trust SDH to reject with Error
1204
+ this.logger.error("Session.rollbackOffer: SDH rollbackDescription rejected...");
1205
+ const e = error instanceof Error ? error : new Error("Session.rollbackOffer unknown error.");
1206
+ this.logger.error(e.message);
1207
+ throw e;
1208
+ });
1209
+ } catch (error) {
1210
+ // don't trust SDH to throw an Error
1211
+ this.logger.error("Session.rollbackOffer: SDH rollbackDescription threw...");
1212
+ const e = error instanceof Error ? error : new Error(error);
1213
+ this.logger.error(e.message);
1214
+ return Promise.reject(e);
1215
+ }
1216
+ }
1217
+
1218
+ /**
1219
+ * Set remote answer.
1220
+ * @internal
1221
+ */
1222
+ protected setAnswer(
1223
+ answer: Body,
1224
+ options: {
1225
+ sessionDescriptionHandlerOptions?: SessionDescriptionHandlerOptions;
1226
+ sessionDescriptionHandlerModifiers?: Array<SessionDescriptionHandlerModifier>;
1227
+ }
1228
+ ): Promise<void> {
1229
+ const sdh = this.setupSessionDescriptionHandler();
1230
+ const sdhOptions = options.sessionDescriptionHandlerOptions;
1231
+ const sdhModifiers = options.sessionDescriptionHandlerModifiers;
1232
+ // This is intentionally written very defensively. Don't trust SDH to behave.
1233
+ try {
1234
+ if (!sdh.hasDescription(answer.contentType)) {
1235
+ return Promise.reject(new ContentTypeUnsupportedError());
1236
+ }
1237
+ } catch (error) {
1238
+ this.logger.error("Session.setAnswer: SDH hasDescription threw...");
1239
+ const e = error instanceof Error ? error : new Error(error);
1240
+ this.logger.error(e.message);
1241
+ return Promise.reject(e);
1242
+ }
1243
+ try {
1244
+ return sdh.setDescription(answer.content, sdhOptions, sdhModifiers).catch((error: unknown) => {
1245
+ // don't trust SDH to reject with Error
1246
+ this.logger.error("Session.setAnswer: SDH setDescription rejected...");
1247
+ const e = error instanceof Error ? error : new Error("Session.setAnswer unknown error.");
1248
+ this.logger.error(e.message);
1249
+ throw e;
1250
+ });
1251
+ } catch (error) {
1252
+ // don't trust SDH to throw an Error
1253
+ this.logger.error("Session.setAnswer: SDH setDescription threw...");
1254
+ const e = error instanceof Error ? error : new Error(error);
1255
+ this.logger.error(e.message);
1256
+ return Promise.reject(e);
1257
+ }
1258
+ }
1259
+
1260
+ /**
1261
+ * Set remote offer and get local answer.
1262
+ * @internal
1263
+ */
1264
+ protected setOfferAndGetAnswer(
1265
+ offer: Body,
1266
+ options: {
1267
+ sessionDescriptionHandlerOptions?: SessionDescriptionHandlerOptions;
1268
+ sessionDescriptionHandlerModifiers?: Array<SessionDescriptionHandlerModifier>;
1269
+ }
1270
+ ): Promise<Body> {
1271
+ const sdh = this.setupSessionDescriptionHandler();
1272
+ const sdhOptions = options.sessionDescriptionHandlerOptions;
1273
+ const sdhModifiers = options.sessionDescriptionHandlerModifiers;
1274
+ // This is intentionally written very defensively. Don't trust SDH to behave.
1275
+ try {
1276
+ if (!sdh.hasDescription(offer.contentType)) {
1277
+ return Promise.reject(new ContentTypeUnsupportedError());
1278
+ }
1279
+ } catch (error) {
1280
+ this.logger.error("Session.setOfferAndGetAnswer: SDH hasDescription threw...");
1281
+ const e = error instanceof Error ? error : new Error(error);
1282
+ this.logger.error(e.message);
1283
+ return Promise.reject(e);
1284
+ }
1285
+ try {
1286
+ return sdh
1287
+ .setDescription(offer.content, sdhOptions, sdhModifiers)
1288
+ .then(() => sdh.getDescription(sdhOptions, sdhModifiers))
1289
+ .then((bodyAndContentType) => fromBodyLegacy(bodyAndContentType))
1290
+ .catch((error: unknown) => {
1291
+ // don't trust SDH to reject with Error
1292
+ this.logger.error("Session.setOfferAndGetAnswer: SDH setDescription or getDescription rejected...");
1293
+ const e = error instanceof Error ? error : new Error("Session.setOfferAndGetAnswer unknown error.");
1294
+ this.logger.error(e.message);
1295
+ throw e;
1296
+ });
1297
+ } catch (error) {
1298
+ // don't trust SDH to throw an Error
1299
+ this.logger.error("Session.setOfferAndGetAnswer: SDH setDescription or getDescription threw...");
1300
+ const e = error instanceof Error ? error : new Error(error);
1301
+ this.logger.error(e.message);
1302
+ return Promise.reject(e);
1303
+ }
1304
+ }
1305
+
1306
+ /**
1307
+ * SDH for confirmed dialog.
1308
+ * @internal
1309
+ */
1310
+ protected setSessionDescriptionHandler(sdh: SessionDescriptionHandler): void {
1311
+ if (this._sessionDescriptionHandler) {
1312
+ throw new Error("Session description handler defined.");
1313
+ }
1314
+ this._sessionDescriptionHandler = sdh;
1315
+ }
1316
+
1317
+ /**
1318
+ * SDH for confirmed dialog.
1319
+ * @internal
1320
+ */
1321
+ protected setupSessionDescriptionHandler(): SessionDescriptionHandler {
1322
+ if (this._sessionDescriptionHandler) {
1323
+ return this._sessionDescriptionHandler;
1324
+ }
1325
+ this._sessionDescriptionHandler = this.sessionDescriptionHandlerFactory(
1326
+ this,
1327
+ this.userAgent.configuration.sessionDescriptionHandlerFactoryOptions
1328
+ );
1329
+ if (this.delegate?.onSessionDescriptionHandler) {
1330
+ this.delegate.onSessionDescriptionHandler(this._sessionDescriptionHandler, false);
1331
+ }
1332
+ return this._sessionDescriptionHandler;
1333
+ }
1334
+
1335
+ /**
1336
+ * Transition session state.
1337
+ * @internal
1338
+ */
1339
+ protected stateTransition(newState: SessionState): void {
1340
+ const invalidTransition = (): void => {
1341
+ throw new Error(`Invalid state transition from ${this._state} to ${newState}`);
1342
+ };
1343
+
1344
+ // Validate transition
1345
+ switch (this._state) {
1346
+ case SessionState.Initial:
1347
+ if (
1348
+ newState !== SessionState.Establishing &&
1349
+ newState !== SessionState.Established &&
1350
+ newState !== SessionState.Terminating &&
1351
+ newState !== SessionState.Terminated
1352
+ ) {
1353
+ invalidTransition();
1354
+ }
1355
+ break;
1356
+ case SessionState.Establishing:
1357
+ if (
1358
+ newState !== SessionState.Established &&
1359
+ newState !== SessionState.Terminating &&
1360
+ newState !== SessionState.Terminated
1361
+ ) {
1362
+ invalidTransition();
1363
+ }
1364
+ break;
1365
+ case SessionState.Established:
1366
+ if (newState !== SessionState.Terminating && newState !== SessionState.Terminated) {
1367
+ invalidTransition();
1368
+ }
1369
+ break;
1370
+ case SessionState.Terminating:
1371
+ if (newState !== SessionState.Terminated) {
1372
+ invalidTransition();
1373
+ }
1374
+ break;
1375
+ case SessionState.Terminated:
1376
+ invalidTransition();
1377
+ break;
1378
+ default:
1379
+ throw new Error("Unrecognized state.");
1380
+ }
1381
+
1382
+ // Transition
1383
+ this._state = newState;
1384
+ this.logger.log(`Session ${this.id} transitioned to state ${this._state}`);
1385
+ this._stateEventEmitter.emit(this._state);
1386
+
1387
+ // Dispose
1388
+ if (newState === SessionState.Terminated) {
1389
+ this.dispose();
1390
+ }
1391
+ }
1392
+
1393
+ private copyRequestOptions(requestOptions: RequestOptions = {}): RequestOptions {
1394
+ const extraHeaders = requestOptions.extraHeaders ? requestOptions.extraHeaders.slice() : undefined;
1395
+ const body = requestOptions.body
1396
+ ? {
1397
+ contentDisposition: requestOptions.body.contentDisposition || "render",
1398
+ contentType: requestOptions.body.contentType || "text/plain",
1399
+ content: requestOptions.body.content || ""
1400
+ }
1401
+ : undefined;
1402
+ return {
1403
+ extraHeaders,
1404
+ body
1405
+ };
1406
+ }
1407
+
1408
+ private getReasonHeaderValue(code: number, reason?: string): string {
1409
+ const cause = code;
1410
+ let text = getReasonPhrase(code);
1411
+ if (!text && reason) {
1412
+ text = reason;
1413
+ }
1414
+ return "SIP;cause=" + cause + ';text="' + text + '"';
1415
+ }
1416
+
1417
+ private referExtraHeaders(referTo: string): Array<string> {
1418
+ const extraHeaders: Array<string> = [];
1419
+ extraHeaders.push("Referred-By: <" + this.userAgent.configuration.uri + ">");
1420
+ extraHeaders.push("Contact: " + this._contact);
1421
+ extraHeaders.push(
1422
+ "Allow: " + ["ACK", "CANCEL", "INVITE", "MESSAGE", "BYE", "OPTIONS", "INFO", "NOTIFY", "REFER"].toString()
1423
+ );
1424
+ extraHeaders.push("Refer-To: " + referTo);
1425
+ return extraHeaders;
1426
+ }
1427
+
1428
+ private referToString(target: URI | Session): string {
1429
+ let referTo: string;
1430
+ if (target instanceof URI) {
1431
+ // REFER without Replaces (Blind Transfer)
1432
+ referTo = target.toString();
1433
+ } else {
1434
+ // REFER with Replaces (Attended Transfer)
1435
+ if (!target.dialog) {
1436
+ throw new Error("Dialog undefined.");
1437
+ }
1438
+ const displayName = target.remoteIdentity.friendlyName;
1439
+ const remoteTarget = target.dialog.remoteTarget.toString();
1440
+ const callId = target.dialog.callId;
1441
+ const remoteTag = target.dialog.remoteTag;
1442
+ const localTag = target.dialog.localTag;
1443
+ const replaces = encodeURIComponent(`${callId};to-tag=${remoteTag};from-tag=${localTag}`);
1444
+ referTo = `"${displayName}" <${remoteTarget}?Replaces=${replaces}>`;
1445
+ }
1446
+ return referTo;
1447
+ }
1448
+ }