@wazo/sdk 0.38.22 → 0.39.0-beta.10
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.
- package/README.md +62 -293
- package/dist/wazo-sdk.js +9 -25
- package/esm/__tests__/api-client.test.js +183 -5059
- package/esm/__tests__/web-rtc-client.test.js +177 -7930
- package/esm/api/agentd.js +23 -832
- package/esm/api/amid.js +9 -411
- package/esm/api/application.js +60 -829
- package/esm/api/auth.js +164 -1213
- package/esm/api/call-logd.js +24 -733
- package/esm/api/calld.js +114 -1469
- package/esm/api/chatd.js +48 -1311
- package/esm/api/confd.js +67 -1580
- package/esm/api/ctid-ng.js +92 -1343
- package/esm/api/dird.js +100 -1590
- package/esm/api/webhookd.js +7 -513
- package/esm/api-client.js +143 -4880
- package/esm/checker/Checker.js +45 -8727
- package/esm/checker/checks/aor.js +24 -4924
- package/esm/checker/checks/api.js +70 -4968
- package/esm/checker/checks/ice-ipv4.js +63 -117
- package/esm/checker/checks/index.js +8 -8677
- package/esm/checker/checks/symmetric-nat.js +54 -102
- package/esm/checker/checks/wazo-websocket.js +34 -999
- package/esm/checker/checks/webrtc-transport.js +28 -7845
- package/esm/checker/checks/webrtc.js +31 -7852
- package/esm/domain/AdHocAPIConference.js +86 -5115
- package/esm/domain/Agent.js +27 -61
- package/esm/domain/BadResponse.js +20 -43
- package/esm/domain/Call.js +120 -210
- package/esm/domain/CallLog.js +123 -305
- package/esm/domain/CallSession.js +251 -423
- package/esm/domain/ChatMessage.js +52 -105
- package/esm/domain/ChatRoom.js +28 -60
- package/esm/domain/Contact.js +435 -741
- package/esm/domain/Country.js +17 -19
- package/esm/domain/Device/DebugDevice.js +31 -47
- package/esm/domain/Device/Device.js +1 -1
- package/esm/domain/DirectorySource.js +1 -1
- package/esm/domain/ExternalApp.js +23 -56
- package/esm/domain/Features.js +57 -5009
- package/esm/domain/ForwardOption.js +35 -70
- package/esm/domain/IndirectTransfer.js +38 -97
- package/esm/domain/Line.js +37 -88
- package/esm/domain/Meeting.js +58 -113
- package/esm/domain/MeetingAuthorization.js +38 -68
- package/esm/domain/MeetingStatus.js +13 -28
- package/esm/domain/NotificationOptions.js +43 -77
- package/esm/domain/Phone/CTIPhone.js +245 -5743
- package/esm/domain/Phone/Phone.js +1 -2
- package/esm/domain/Phone/WebRTCPhone.js +1457 -2671
- package/esm/domain/Profile.js +120 -405
- package/esm/domain/Recording.js +27 -51
- package/esm/domain/Relocation.js +16 -40
- package/esm/domain/Room.js +90 -133
- package/esm/domain/SFUNotAvailableError.js +5 -8
- package/esm/domain/ServerError.js +8 -61
- package/esm/domain/Session.js +125 -251
- package/esm/domain/SipLine.js +78 -155
- package/esm/domain/Subscription.js +39 -83
- package/esm/domain/SwitchboardCall.js +51 -143
- package/esm/domain/Voicemail.js +57 -122
- package/esm/domain/__tests__/Agent.test.js +31 -101
- package/esm/domain/__tests__/Call.test.js +24 -232
- package/esm/domain/__tests__/CallLog.test.js +60 -386
- package/esm/domain/__tests__/CallSession.test.js +74 -502
- package/esm/domain/__tests__/Contact.test.js +220 -902
- package/esm/domain/__tests__/IndirectTransfer.test.js +63 -546
- package/esm/domain/__tests__/Line.test.js +48 -156
- package/esm/domain/__tests__/Meeting.test.js +73 -226
- package/esm/domain/__tests__/MeetingAuthorization.test.js +45 -105
- package/esm/domain/__tests__/Profile.test.js +135 -496
- package/esm/domain/__tests__/Room.test.js +227 -719
- package/esm/domain/__tests__/Session.test.js +357 -1025
- package/esm/domain/__tests__/SipLine.test.js +24 -179
- package/esm/domain/__tests__/Voicemail.test.js +82 -200
- package/esm/domain/types.js +1 -1
- package/esm/index.js +63 -14985
- package/esm/lib/WazoSessionDescriptionHandler.js +406 -890
- package/esm/pubkey.js +10 -0
- package/esm/service/CallApi.js +42 -5014
- package/esm/service/IssueReporter.js +278 -360
- package/esm/service/__tests__/IssueReporter.test.js +92 -494
- package/esm/service/getApiClient.js +53 -4972
- package/esm/simple/Auth.js +212 -14747
- package/esm/simple/Configuration.js +8 -14796
- package/esm/simple/Directory.js +6 -4964
- package/esm/simple/Phone.js +309 -14727
- package/esm/simple/Websocket.js +68 -1112
- package/esm/simple/index.js +125 -14792
- package/esm/simple/room/LocalParticipant.js +1 -14797
- package/esm/simple/room/Participant.js +274 -14760
- package/esm/simple/room/RemoteParticipant.js +6 -14796
- package/esm/simple/room/Room.js +648 -14736
- package/esm/simple/room/SipRoom.js +111 -14790
- package/esm/simple/room/Stream.js +40 -14792
- package/esm/simple/room/__tests__/Participant.test.js +68 -14872
- package/esm/simple/room/__tests__/RemoteParticipant.test.js +10 -14805
- package/esm/simple/utils.js +9 -14799
- package/esm/types/WebSocketMessage.js +1 -1
- package/esm/types/__tests__/api-client.test.d.ts +2 -0
- package/esm/types/__tests__/api-client.test.d.ts.map +1 -0
- package/esm/types/__tests__/web-rtc-client.test.d.ts +2 -0
- package/esm/types/__tests__/web-rtc-client.test.d.ts.map +1 -0
- package/esm/types/api/agentd.d.ts +17 -0
- package/esm/types/api/agentd.d.ts.map +1 -0
- package/esm/types/api/amid.d.ts +8 -0
- package/esm/types/api/amid.d.ts.map +1 -0
- package/esm/types/api/application.d.ts +34 -0
- package/esm/types/api/application.d.ts.map +1 -0
- package/esm/types/api/auth.d.ts +64 -0
- package/esm/types/api/auth.d.ts.map +1 -0
- package/esm/types/api/call-logd.d.ts +12 -0
- package/esm/types/api/call-logd.d.ts.map +1 -0
- package/esm/types/api/calld.d.ts +51 -0
- package/esm/types/api/calld.d.ts.map +1 -0
- package/esm/types/api/chatd.d.ts +42 -0
- package/esm/types/api/chatd.d.ts.map +1 -0
- package/esm/types/api/confd.d.ts +39 -0
- package/esm/types/api/confd.d.ts.map +1 -0
- package/esm/types/api/ctid-ng.d.ts +36 -0
- package/esm/types/api/ctid-ng.d.ts.map +1 -0
- package/esm/types/api/dird.d.ts +38 -0
- package/esm/types/api/dird.d.ts.map +1 -0
- package/esm/types/api/webhookd.d.ts +24 -0
- package/esm/types/api/webhookd.d.ts.map +1 -0
- package/esm/types/api-client.d.ts +63 -0
- package/esm/types/api-client.d.ts.map +1 -0
- package/esm/types/checker/Checker.d.ts +13 -0
- package/esm/types/checker/Checker.d.ts.map +1 -0
- package/esm/types/checker/checks/aor.d.ts +6 -0
- package/esm/types/checker/checks/aor.d.ts.map +1 -0
- package/esm/types/checker/checks/api.d.ts +6 -0
- package/esm/types/checker/checks/api.d.ts.map +1 -0
- package/esm/types/checker/checks/ice-ipv4.d.ts +6 -0
- package/esm/types/checker/checks/ice-ipv4.d.ts.map +1 -0
- package/esm/types/checker/checks/index.d.ts +9 -0
- package/esm/types/checker/checks/index.d.ts.map +1 -0
- package/esm/types/checker/checks/symmetric-nat.d.ts +6 -0
- package/esm/types/checker/checks/symmetric-nat.d.ts.map +1 -0
- package/esm/types/checker/checks/wazo-websocket.d.ts +6 -0
- package/esm/types/checker/checks/wazo-websocket.d.ts.map +1 -0
- package/esm/types/checker/checks/webrtc-transport.d.ts +7 -0
- package/esm/types/checker/checks/webrtc-transport.d.ts.map +1 -0
- package/esm/types/checker/checks/webrtc.d.ts +6 -0
- package/esm/types/checker/checks/webrtc.d.ts.map +1 -0
- package/esm/types/domain/AdHocAPIConference.d.ts +54 -0
- package/esm/types/domain/AdHocAPIConference.d.ts.map +1 -0
- package/esm/types/domain/Agent.d.ts +31 -0
- package/esm/types/domain/Agent.d.ts.map +1 -0
- package/esm/types/domain/BadResponse.d.ts +11 -0
- package/esm/types/domain/BadResponse.d.ts.map +1 -0
- package/esm/types/domain/Call.d.ts +79 -0
- package/esm/types/domain/Call.d.ts.map +1 -0
- package/esm/types/domain/CallLog.d.ts +91 -0
- package/esm/types/domain/CallLog.d.ts.map +1 -0
- package/esm/types/domain/CallSession.d.ts +120 -0
- package/esm/types/domain/CallSession.d.ts.map +1 -0
- package/esm/types/domain/ChatMessage.d.ts +41 -0
- package/esm/types/domain/ChatMessage.d.ts.map +1 -0
- package/esm/types/domain/ChatRoom.d.ts +22 -0
- package/esm/types/domain/ChatRoom.d.ts.map +1 -0
- package/esm/types/domain/Contact.d.ts +316 -0
- package/esm/types/domain/Contact.d.ts.map +1 -0
- package/esm/types/domain/Country.d.ts +20 -0
- package/esm/types/domain/Country.d.ts.map +1 -0
- package/esm/types/domain/Device/DebugDevice.d.ts +14 -0
- package/esm/types/domain/Device/DebugDevice.d.ts.map +1 -0
- package/esm/types/domain/Device/Device.d.ts +13 -0
- package/esm/types/domain/Device/Device.d.ts.map +1 -0
- package/esm/types/domain/DirectorySource.d.ts +13 -0
- package/esm/types/domain/DirectorySource.d.ts.map +1 -0
- package/esm/types/domain/ExternalApp.d.ts +22 -0
- package/esm/types/domain/ExternalApp.d.ts.map +1 -0
- package/esm/types/domain/Features.d.ts +24 -0
- package/esm/types/domain/Features.d.ts.map +1 -0
- package/esm/types/domain/ForwardOption.d.ts +27 -0
- package/esm/types/domain/ForwardOption.d.ts.map +1 -0
- package/esm/types/domain/IndirectTransfer.d.ts +31 -0
- package/esm/types/domain/IndirectTransfer.d.ts.map +1 -0
- package/esm/types/domain/Line.d.ts +46 -0
- package/esm/types/domain/Line.d.ts.map +1 -0
- package/esm/types/domain/Meeting.d.ts +45 -0
- package/esm/types/domain/Meeting.d.ts.map +1 -0
- package/esm/types/domain/MeetingAuthorization.d.ts +26 -0
- package/esm/types/domain/MeetingAuthorization.d.ts.map +1 -0
- package/esm/types/domain/MeetingStatus.d.ts +10 -0
- package/esm/types/domain/MeetingStatus.d.ts.map +1 -0
- package/esm/types/domain/NotificationOptions.d.ts +22 -0
- package/esm/types/domain/NotificationOptions.d.ts.map +1 -0
- package/esm/types/domain/Phone/CTIPhone.d.ts +76 -0
- package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -0
- package/esm/types/domain/Phone/Phone.d.ts +71 -0
- package/esm/types/domain/Phone/Phone.d.ts.map +1 -0
- package/esm/types/domain/Phone/WebRTCPhone.d.ts +179 -0
- package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -0
- package/esm/types/domain/Profile.d.ts +151 -0
- package/esm/types/domain/Profile.d.ts.map +1 -0
- package/esm/types/domain/Recording.d.ts +26 -0
- package/esm/types/domain/Recording.d.ts.map +1 -0
- package/esm/types/domain/Relocation.d.ts +23 -0
- package/esm/types/domain/Relocation.d.ts.map +1 -0
- package/esm/types/domain/Room.d.ts +35 -0
- package/esm/types/domain/Room.d.ts.map +1 -0
- package/esm/types/domain/SFUNotAvailableError.d.ts +4 -0
- package/esm/types/domain/SFUNotAvailableError.d.ts.map +1 -0
- package/esm/types/domain/ServerError.d.ts +6 -0
- package/esm/types/domain/ServerError.d.ts.map +1 -0
- package/esm/types/domain/Session.d.ts +90 -0
- package/esm/types/domain/Session.d.ts.map +1 -0
- package/esm/types/domain/SipLine.d.ts +54 -0
- package/esm/types/domain/SipLine.d.ts.map +1 -0
- package/esm/types/domain/Subscription.d.ts +43 -0
- package/esm/types/domain/Subscription.d.ts.map +1 -0
- package/esm/types/domain/SwitchboardCall.d.ts +62 -0
- package/esm/types/domain/SwitchboardCall.d.ts.map +1 -0
- package/esm/types/domain/Voicemail.d.ts +50 -0
- package/esm/types/domain/Voicemail.d.ts.map +1 -0
- package/esm/types/domain/__tests__/Agent.test.d.ts +2 -0
- package/esm/types/domain/__tests__/Agent.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/Call.test.d.ts +2 -0
- package/esm/types/domain/__tests__/Call.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/CallLog.test.d.ts +2 -0
- package/esm/types/domain/__tests__/CallLog.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/CallSession.test.d.ts +2 -0
- package/esm/types/domain/__tests__/CallSession.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/Contact.test.d.ts +2 -0
- package/esm/types/domain/__tests__/Contact.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/IndirectTransfer.test.d.ts +2 -0
- package/esm/types/domain/__tests__/IndirectTransfer.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/Line.test.d.ts +2 -0
- package/esm/types/domain/__tests__/Line.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/Meeting.test.d.ts +2 -0
- package/esm/types/domain/__tests__/Meeting.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/MeetingAuthorization.test.d.ts +2 -0
- package/esm/types/domain/__tests__/MeetingAuthorization.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/Profile.test.d.ts +2 -0
- package/esm/types/domain/__tests__/Profile.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/Room.test.d.ts +2 -0
- package/esm/types/domain/__tests__/Room.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/Session.test.d.ts +2 -0
- package/esm/types/domain/__tests__/Session.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/SipLine.test.d.ts +2 -0
- package/esm/types/domain/__tests__/SipLine.test.d.ts.map +1 -0
- package/esm/types/domain/__tests__/Voicemail.test.d.ts +2 -0
- package/esm/types/domain/__tests__/Voicemail.test.d.ts.map +1 -0
- package/esm/types/domain/types.d.ts +217 -0
- package/esm/types/domain/types.d.ts.map +1 -0
- package/esm/types/index.d.ts +304 -0
- package/esm/types/index.d.ts.map +1 -0
- package/esm/types/lib/WazoSessionDescriptionHandler.d.ts +30 -0
- package/esm/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -0
- package/esm/types/pubkey.d.ts +3 -0
- package/esm/types/pubkey.d.ts.map +1 -0
- package/esm/types/service/CallApi.d.ts +28 -0
- package/esm/types/service/CallApi.d.ts.map +1 -0
- package/esm/types/service/IssueReporter.d.ts +40 -0
- package/esm/types/service/IssueReporter.d.ts.map +1 -0
- package/esm/types/service/__tests__/IssueReporter.test.d.ts +2 -0
- package/esm/types/service/__tests__/IssueReporter.test.d.ts.map +1 -0
- package/esm/types/service/getApiClient.d.ts +16 -0
- package/esm/types/service/getApiClient.d.ts.map +1 -0
- package/esm/types/simple/Auth.d.ts +51 -0
- package/esm/types/simple/Auth.d.ts.map +1 -0
- package/esm/types/simple/Configuration.d.ts +3 -0
- package/esm/types/simple/Configuration.d.ts.map +1 -0
- package/esm/types/simple/Directory.d.ts +3 -0
- package/esm/types/simple/Directory.d.ts.map +1 -0
- package/esm/types/simple/Phone.d.ts +115 -0
- package/esm/types/simple/Phone.d.ts.map +1 -0
- package/esm/types/simple/Websocket.d.ts +19 -0
- package/esm/types/simple/Websocket.d.ts.map +1 -0
- package/esm/types/simple/index.d.ts +147 -0
- package/esm/types/simple/index.d.ts.map +1 -0
- package/esm/types/simple/room/LocalParticipant.d.ts +5 -0
- package/esm/types/simple/room/LocalParticipant.d.ts.map +1 -0
- package/esm/types/simple/room/Participant.d.ts +76 -0
- package/esm/types/simple/room/Participant.d.ts.map +1 -0
- package/esm/types/simple/room/RemoteParticipant.d.ts +7 -0
- package/esm/types/simple/room/RemoteParticipant.d.ts.map +1 -0
- package/esm/types/simple/room/Room.d.ts +116 -0
- package/esm/types/simple/room/Room.d.ts.map +1 -0
- package/esm/types/simple/room/SipRoom.d.ts +14 -0
- package/esm/types/simple/room/SipRoom.d.ts.map +1 -0
- package/esm/types/simple/room/Stream.d.ts +13 -0
- package/esm/types/simple/room/Stream.d.ts.map +1 -0
- package/esm/types/simple/room/__tests__/Participant.test.d.ts +2 -0
- package/esm/types/simple/room/__tests__/Participant.test.d.ts.map +1 -0
- package/esm/types/simple/room/__tests__/RemoteParticipant.test.d.ts +2 -0
- package/esm/types/simple/room/__tests__/RemoteParticipant.test.d.ts.map +1 -0
- package/esm/types/simple/utils.d.ts +3 -0
- package/esm/types/simple/utils.d.ts.map +1 -0
- package/esm/types/types/WebSocketMessage.d.ts +285 -0
- package/esm/types/types/WebSocketMessage.d.ts.map +1 -0
- package/esm/types/utils/Emitter.d.ts +18 -0
- package/esm/types/utils/Emitter.d.ts.map +1 -0
- package/esm/types/utils/Heartbeat.d.ts +21 -0
- package/esm/types/utils/Heartbeat.d.ts.map +1 -0
- package/esm/types/utils/PhoneNumberUtil.d.ts +8 -0
- package/esm/types/utils/PhoneNumberUtil.d.ts.map +1 -0
- package/esm/types/utils/__tests__/Heartbeat.test.d.ts +2 -0
- package/esm/types/utils/__tests__/Heartbeat.test.d.ts.map +1 -0
- package/esm/types/utils/__tests__/PhoneNumberUtil.test.d.ts +2 -0
- package/esm/types/utils/__tests__/PhoneNumberUtil.test.d.ts.map +1 -0
- package/esm/types/utils/__tests__/api-requester.test.d.ts +2 -0
- package/esm/types/utils/__tests__/api-requester.test.d.ts.map +1 -0
- package/esm/types/utils/__tests__/array.test.d.ts +2 -0
- package/esm/types/utils/__tests__/array.test.d.ts.map +1 -0
- package/esm/types/utils/__tests__/compare-version.test.d.ts +2 -0
- package/esm/types/utils/__tests__/compare-version.test.d.ts.map +1 -0
- package/esm/types/utils/__tests__/object.test.d.ts +2 -0
- package/esm/types/utils/__tests__/object.test.d.ts.map +1 -0
- package/esm/types/utils/__tests__/sdp.test.d.ts +2 -0
- package/esm/types/utils/__tests__/sdp.test.d.ts.map +1 -0
- package/esm/types/utils/__tests__/string.test.d.ts +2 -0
- package/esm/types/utils/__tests__/string.test.d.ts.map +1 -0
- package/esm/types/utils/api-requester.d.ts +45 -0
- package/esm/types/utils/api-requester.d.ts.map +1 -0
- package/esm/types/utils/array.d.ts +2 -0
- package/esm/types/utils/array.d.ts.map +1 -0
- package/esm/types/utils/compare-version.d.ts +3 -0
- package/esm/types/utils/compare-version.d.ts.map +1 -0
- package/esm/types/utils/isMobile.d.ts +3 -0
- package/esm/types/utils/isMobile.d.ts.map +1 -0
- package/esm/types/utils/new-from.d.ts +3 -0
- package/esm/types/utils/new-from.d.ts.map +1 -0
- package/esm/types/utils/object.d.ts +2 -0
- package/esm/types/utils/object.d.ts.map +1 -0
- package/esm/types/utils/once.d.ts +2 -0
- package/esm/types/utils/once.d.ts.map +1 -0
- package/esm/types/utils/sdp.d.ts +13 -0
- package/esm/types/utils/sdp.d.ts.map +1 -0
- package/esm/types/utils/string.d.ts +2 -0
- package/esm/types/utils/string.d.ts.map +1 -0
- package/esm/types/utils/update-from.d.ts +3 -0
- package/esm/types/utils/update-from.d.ts.map +1 -0
- package/esm/types/utils/webrtc.d.ts +15 -0
- package/esm/types/utils/webrtc.d.ts.map +1 -0
- package/esm/types/web-rtc-client.d.ts +220 -0
- package/esm/types/web-rtc-client.d.ts.map +1 -0
- package/esm/types/websocket-client.d.ts +134 -0
- package/esm/types/websocket-client.d.ts.map +1 -0
- package/esm/utils/Emitter.js +17 -27
- package/esm/utils/Heartbeat.js +60 -83
- package/esm/utils/PhoneNumberUtil.js +48 -63
- package/esm/utils/__tests__/Heartbeat.test.js +59 -168
- package/esm/utils/__tests__/PhoneNumberUtil.test.js +55 -125
- package/esm/utils/__tests__/api-requester.test.js +127 -780
- package/esm/utils/__tests__/array.test.js +16 -19
- package/esm/utils/__tests__/compare-version.test.js +8 -26
- package/esm/utils/__tests__/object.test.js +73 -54
- package/esm/utils/__tests__/sdp.test.js +87 -216
- package/esm/utils/__tests__/string.test.js +21 -27
- package/esm/utils/api-requester.js +197 -675
- package/esm/utils/array.js +7 -11
- package/esm/utils/compare-version.js +12 -15
- package/esm/utils/isMobile.js +0 -2
- package/esm/utils/new-from.js +7 -12
- package/esm/utils/object.js +9 -23
- package/esm/utils/once.js +12 -13
- package/esm/utils/sdp.js +87 -131
- package/esm/utils/string.js +5 -9
- package/esm/utils/update-from.js +9 -16
- package/esm/utils/webrtc.js +35 -36
- package/esm/web-rtc-client.js +2038 -7677
- package/esm/websocket-client.js +352 -944
- package/lib/__tests__/api-client.test.js +199 -5067
- package/lib/__tests__/web-rtc-client.test.js +191 -7941
- package/lib/api/agentd.js +27 -837
- package/lib/api/amid.js +18 -415
- package/lib/api/application.js +64 -834
- package/lib/api/auth.js +166 -1222
- package/lib/api/call-logd.js +28 -738
- package/lib/api/calld.js +126 -1473
- package/lib/api/chatd.js +65 -1316
- package/lib/api/confd.js +79 -1584
- package/lib/api/ctid-ng.js +96 -1348
- package/lib/api/dird.js +105 -1596
- package/lib/api/webhookd.js +11 -518
- package/lib/api-client.js +139 -4884
- package/lib/checker/Checker.js +61 -8739
- package/lib/checker/checks/aor.js +37 -4929
- package/lib/checker/checks/api.js +81 -4971
- package/lib/checker/checks/ice-ipv4.js +66 -118
- package/lib/checker/checks/index.js +13 -8687
- package/lib/checker/checks/symmetric-nat.js +56 -104
- package/lib/checker/checks/wazo-websocket.js +58 -1006
- package/lib/checker/checks/webrtc-transport.js +41 -7853
- package/lib/checker/checks/webrtc.js +42 -7858
- package/lib/domain/AdHocAPIConference.js +80 -5116
- package/lib/domain/Agent.js +23 -64
- package/lib/domain/BadResponse.js +17 -44
- package/lib/domain/Call.js +108 -215
- package/lib/domain/CallLog.js +117 -311
- package/lib/domain/CallSession.js +221 -424
- package/lib/domain/ChatMessage.js +49 -110
- package/lib/domain/ChatRoom.js +28 -60
- package/lib/domain/Contact.js +409 -742
- package/lib/domain/Country.js +19 -21
- package/lib/domain/Device/DebugDevice.js +34 -49
- package/lib/domain/Device/Device.js +2 -2
- package/lib/domain/DirectorySource.js +2 -2
- package/lib/domain/ExternalApp.js +24 -56
- package/lib/domain/Features.js +68 -5018
- package/lib/domain/ForwardOption.js +36 -71
- package/lib/domain/IndirectTransfer.js +39 -98
- package/lib/domain/Line.js +35 -88
- package/lib/domain/Meeting.js +51 -118
- package/lib/domain/MeetingAuthorization.js +35 -75
- package/lib/domain/MeetingStatus.js +13 -29
- package/lib/domain/NotificationOptions.js +45 -77
- package/lib/domain/Phone/CTIPhone.js +283 -5755
- package/lib/domain/Phone/Phone.js +2 -5
- package/lib/domain/Phone/WebRTCPhone.js +1457 -2716
- package/lib/domain/Profile.js +127 -406
- package/lib/domain/Recording.js +28 -57
- package/lib/domain/Relocation.js +15 -43
- package/lib/domain/Room.js +73 -134
- package/lib/domain/SFUNotAvailableError.js +7 -9
- package/lib/domain/ServerError.js +14 -63
- package/lib/domain/Session.js +118 -251
- package/lib/domain/SipLine.js +70 -155
- package/lib/domain/Subscription.js +32 -86
- package/lib/domain/SwitchboardCall.js +45 -145
- package/lib/domain/Voicemail.js +56 -127
- package/lib/domain/__tests__/Agent.test.js +36 -103
- package/lib/domain/__tests__/Call.test.js +28 -237
- package/lib/domain/__tests__/CallLog.test.js +65 -392
- package/lib/domain/__tests__/CallSession.test.js +78 -503
- package/lib/domain/__tests__/Contact.test.js +224 -903
- package/lib/domain/__tests__/IndirectTransfer.test.js +75 -546
- package/lib/domain/__tests__/Line.test.js +52 -157
- package/lib/domain/__tests__/Meeting.test.js +78 -232
- package/lib/domain/__tests__/MeetingAuthorization.test.js +50 -107
- package/lib/domain/__tests__/Profile.test.js +161 -496
- package/lib/domain/__tests__/Room.test.js +239 -719
- package/lib/domain/__tests__/Session.test.js +350 -1024
- package/lib/domain/__tests__/SipLine.test.js +28 -180
- package/lib/domain/__tests__/Voicemail.test.js +86 -205
- package/lib/domain/types.js +2 -2
- package/lib/index.js +105 -15010
- package/lib/lib/WazoSessionDescriptionHandler.js +409 -898
- package/lib/pubkey.js +12 -0
- package/lib/service/CallApi.js +88 -5015
- package/lib/service/IssueReporter.js +264 -366
- package/lib/service/__tests__/IssueReporter.test.js +97 -500
- package/lib/service/getApiClient.js +70 -4990
- package/lib/simple/Auth.js +272 -14777
- package/lib/simple/Configuration.js +23 -14805
- package/lib/simple/Directory.js +18 -4966
- package/lib/simple/Phone.js +345 -14746
- package/lib/simple/Websocket.js +98 -1117
- package/lib/simple/index.js +151 -14800
- package/lib/simple/room/LocalParticipant.js +7 -14808
- package/lib/simple/room/Participant.js +269 -14778
- package/lib/simple/room/RemoteParticipant.js +11 -14806
- package/lib/simple/room/Room.js +655 -14761
- package/lib/simple/room/SipRoom.js +136 -14805
- package/lib/simple/room/Stream.js +43 -14802
- package/lib/simple/room/__tests__/Participant.test.js +79 -14879
- package/lib/simple/room/__tests__/RemoteParticipant.test.js +14 -14814
- package/lib/simple/utils.js +22 -14808
- package/lib/types/WebSocketMessage.js +2 -4
- package/lib/types/__tests__/api-client.test.d.ts +2 -0
- package/lib/types/__tests__/api-client.test.d.ts.map +1 -0
- package/lib/types/__tests__/web-rtc-client.test.d.ts +2 -0
- package/lib/types/__tests__/web-rtc-client.test.d.ts.map +1 -0
- package/lib/types/api/agentd.d.ts +17 -0
- package/lib/types/api/agentd.d.ts.map +1 -0
- package/lib/types/api/amid.d.ts +8 -0
- package/lib/types/api/amid.d.ts.map +1 -0
- package/lib/types/api/application.d.ts +34 -0
- package/lib/types/api/application.d.ts.map +1 -0
- package/lib/types/api/auth.d.ts +64 -0
- package/lib/types/api/auth.d.ts.map +1 -0
- package/lib/types/api/call-logd.d.ts +12 -0
- package/lib/types/api/call-logd.d.ts.map +1 -0
- package/lib/types/api/calld.d.ts +51 -0
- package/lib/types/api/calld.d.ts.map +1 -0
- package/lib/types/api/chatd.d.ts +42 -0
- package/lib/types/api/chatd.d.ts.map +1 -0
- package/lib/types/api/confd.d.ts +39 -0
- package/lib/types/api/confd.d.ts.map +1 -0
- package/lib/types/api/ctid-ng.d.ts +36 -0
- package/lib/types/api/ctid-ng.d.ts.map +1 -0
- package/lib/types/api/dird.d.ts +38 -0
- package/lib/types/api/dird.d.ts.map +1 -0
- package/lib/types/api/webhookd.d.ts +24 -0
- package/lib/types/api/webhookd.d.ts.map +1 -0
- package/lib/types/api-client.d.ts +63 -0
- package/lib/types/api-client.d.ts.map +1 -0
- package/lib/types/checker/Checker.d.ts +13 -0
- package/lib/types/checker/Checker.d.ts.map +1 -0
- package/lib/types/checker/checks/aor.d.ts +6 -0
- package/lib/types/checker/checks/aor.d.ts.map +1 -0
- package/lib/types/checker/checks/api.d.ts +6 -0
- package/lib/types/checker/checks/api.d.ts.map +1 -0
- package/lib/types/checker/checks/ice-ipv4.d.ts +6 -0
- package/lib/types/checker/checks/ice-ipv4.d.ts.map +1 -0
- package/lib/types/checker/checks/index.d.ts +9 -0
- package/lib/types/checker/checks/index.d.ts.map +1 -0
- package/lib/types/checker/checks/symmetric-nat.d.ts +6 -0
- package/lib/types/checker/checks/symmetric-nat.d.ts.map +1 -0
- package/lib/types/checker/checks/wazo-websocket.d.ts +6 -0
- package/lib/types/checker/checks/wazo-websocket.d.ts.map +1 -0
- package/lib/types/checker/checks/webrtc-transport.d.ts +7 -0
- package/lib/types/checker/checks/webrtc-transport.d.ts.map +1 -0
- package/lib/types/checker/checks/webrtc.d.ts +6 -0
- package/lib/types/checker/checks/webrtc.d.ts.map +1 -0
- package/lib/types/domain/AdHocAPIConference.d.ts +54 -0
- package/lib/types/domain/AdHocAPIConference.d.ts.map +1 -0
- package/lib/types/domain/Agent.d.ts +31 -0
- package/lib/types/domain/Agent.d.ts.map +1 -0
- package/lib/types/domain/BadResponse.d.ts +11 -0
- package/lib/types/domain/BadResponse.d.ts.map +1 -0
- package/lib/types/domain/Call.d.ts +79 -0
- package/lib/types/domain/Call.d.ts.map +1 -0
- package/lib/types/domain/CallLog.d.ts +91 -0
- package/lib/types/domain/CallLog.d.ts.map +1 -0
- package/lib/types/domain/CallSession.d.ts +120 -0
- package/lib/types/domain/CallSession.d.ts.map +1 -0
- package/lib/types/domain/ChatMessage.d.ts +41 -0
- package/lib/types/domain/ChatMessage.d.ts.map +1 -0
- package/lib/types/domain/ChatRoom.d.ts +22 -0
- package/lib/types/domain/ChatRoom.d.ts.map +1 -0
- package/lib/types/domain/Contact.d.ts +316 -0
- package/lib/types/domain/Contact.d.ts.map +1 -0
- package/lib/types/domain/Country.d.ts +20 -0
- package/lib/types/domain/Country.d.ts.map +1 -0
- package/lib/types/domain/Device/DebugDevice.d.ts +14 -0
- package/lib/types/domain/Device/DebugDevice.d.ts.map +1 -0
- package/lib/types/domain/Device/Device.d.ts +13 -0
- package/lib/types/domain/Device/Device.d.ts.map +1 -0
- package/lib/types/domain/DirectorySource.d.ts +13 -0
- package/lib/types/domain/DirectorySource.d.ts.map +1 -0
- package/lib/types/domain/ExternalApp.d.ts +22 -0
- package/lib/types/domain/ExternalApp.d.ts.map +1 -0
- package/lib/types/domain/Features.d.ts +24 -0
- package/lib/types/domain/Features.d.ts.map +1 -0
- package/lib/types/domain/ForwardOption.d.ts +27 -0
- package/lib/types/domain/ForwardOption.d.ts.map +1 -0
- package/lib/types/domain/IndirectTransfer.d.ts +31 -0
- package/lib/types/domain/IndirectTransfer.d.ts.map +1 -0
- package/lib/types/domain/Line.d.ts +46 -0
- package/lib/types/domain/Line.d.ts.map +1 -0
- package/lib/types/domain/Meeting.d.ts +45 -0
- package/lib/types/domain/Meeting.d.ts.map +1 -0
- package/lib/types/domain/MeetingAuthorization.d.ts +26 -0
- package/lib/types/domain/MeetingAuthorization.d.ts.map +1 -0
- package/lib/types/domain/MeetingStatus.d.ts +10 -0
- package/lib/types/domain/MeetingStatus.d.ts.map +1 -0
- package/lib/types/domain/NotificationOptions.d.ts +22 -0
- package/lib/types/domain/NotificationOptions.d.ts.map +1 -0
- package/lib/types/domain/Phone/CTIPhone.d.ts +76 -0
- package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -0
- package/lib/types/domain/Phone/Phone.d.ts +71 -0
- package/lib/types/domain/Phone/Phone.d.ts.map +1 -0
- package/lib/types/domain/Phone/WebRTCPhone.d.ts +179 -0
- package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -0
- package/lib/types/domain/Profile.d.ts +151 -0
- package/lib/types/domain/Profile.d.ts.map +1 -0
- package/lib/types/domain/Recording.d.ts +26 -0
- package/lib/types/domain/Recording.d.ts.map +1 -0
- package/lib/types/domain/Relocation.d.ts +23 -0
- package/lib/types/domain/Relocation.d.ts.map +1 -0
- package/lib/types/domain/Room.d.ts +35 -0
- package/lib/types/domain/Room.d.ts.map +1 -0
- package/lib/types/domain/SFUNotAvailableError.d.ts +4 -0
- package/lib/types/domain/SFUNotAvailableError.d.ts.map +1 -0
- package/lib/types/domain/ServerError.d.ts +6 -0
- package/lib/types/domain/ServerError.d.ts.map +1 -0
- package/lib/types/domain/Session.d.ts +90 -0
- package/lib/types/domain/Session.d.ts.map +1 -0
- package/lib/types/domain/SipLine.d.ts +54 -0
- package/lib/types/domain/SipLine.d.ts.map +1 -0
- package/lib/types/domain/Subscription.d.ts +43 -0
- package/lib/types/domain/Subscription.d.ts.map +1 -0
- package/lib/types/domain/SwitchboardCall.d.ts +62 -0
- package/lib/types/domain/SwitchboardCall.d.ts.map +1 -0
- package/lib/types/domain/Voicemail.d.ts +50 -0
- package/lib/types/domain/Voicemail.d.ts.map +1 -0
- package/lib/types/domain/__tests__/Agent.test.d.ts +2 -0
- package/lib/types/domain/__tests__/Agent.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/Call.test.d.ts +2 -0
- package/lib/types/domain/__tests__/Call.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/CallLog.test.d.ts +2 -0
- package/lib/types/domain/__tests__/CallLog.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/CallSession.test.d.ts +2 -0
- package/lib/types/domain/__tests__/CallSession.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/Contact.test.d.ts +2 -0
- package/lib/types/domain/__tests__/Contact.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/IndirectTransfer.test.d.ts +2 -0
- package/lib/types/domain/__tests__/IndirectTransfer.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/Line.test.d.ts +2 -0
- package/lib/types/domain/__tests__/Line.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/Meeting.test.d.ts +2 -0
- package/lib/types/domain/__tests__/Meeting.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/MeetingAuthorization.test.d.ts +2 -0
- package/lib/types/domain/__tests__/MeetingAuthorization.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/Profile.test.d.ts +2 -0
- package/lib/types/domain/__tests__/Profile.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/Room.test.d.ts +2 -0
- package/lib/types/domain/__tests__/Room.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/Session.test.d.ts +2 -0
- package/lib/types/domain/__tests__/Session.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/SipLine.test.d.ts +2 -0
- package/lib/types/domain/__tests__/SipLine.test.d.ts.map +1 -0
- package/lib/types/domain/__tests__/Voicemail.test.d.ts +2 -0
- package/lib/types/domain/__tests__/Voicemail.test.d.ts.map +1 -0
- package/lib/types/domain/types.d.ts +217 -0
- package/lib/types/domain/types.d.ts.map +1 -0
- package/lib/types/index.d.ts +304 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/lib/WazoSessionDescriptionHandler.d.ts +30 -0
- package/lib/types/lib/WazoSessionDescriptionHandler.d.ts.map +1 -0
- package/lib/types/pubkey.d.ts +3 -0
- package/lib/types/pubkey.d.ts.map +1 -0
- package/lib/types/service/CallApi.d.ts +28 -0
- package/lib/types/service/CallApi.d.ts.map +1 -0
- package/lib/types/service/IssueReporter.d.ts +40 -0
- package/lib/types/service/IssueReporter.d.ts.map +1 -0
- package/lib/types/service/__tests__/IssueReporter.test.d.ts +2 -0
- package/lib/types/service/__tests__/IssueReporter.test.d.ts.map +1 -0
- package/lib/types/service/getApiClient.d.ts +16 -0
- package/lib/types/service/getApiClient.d.ts.map +1 -0
- package/lib/types/simple/Auth.d.ts +51 -0
- package/lib/types/simple/Auth.d.ts.map +1 -0
- package/lib/types/simple/Configuration.d.ts +3 -0
- package/lib/types/simple/Configuration.d.ts.map +1 -0
- package/lib/types/simple/Directory.d.ts +3 -0
- package/lib/types/simple/Directory.d.ts.map +1 -0
- package/lib/types/simple/Phone.d.ts +115 -0
- package/lib/types/simple/Phone.d.ts.map +1 -0
- package/lib/types/simple/Websocket.d.ts +19 -0
- package/lib/types/simple/Websocket.d.ts.map +1 -0
- package/lib/types/simple/index.d.ts +147 -0
- package/lib/types/simple/index.d.ts.map +1 -0
- package/lib/types/simple/room/LocalParticipant.d.ts +5 -0
- package/lib/types/simple/room/LocalParticipant.d.ts.map +1 -0
- package/lib/types/simple/room/Participant.d.ts +76 -0
- package/lib/types/simple/room/Participant.d.ts.map +1 -0
- package/lib/types/simple/room/RemoteParticipant.d.ts +7 -0
- package/lib/types/simple/room/RemoteParticipant.d.ts.map +1 -0
- package/lib/types/simple/room/Room.d.ts +116 -0
- package/lib/types/simple/room/Room.d.ts.map +1 -0
- package/lib/types/simple/room/SipRoom.d.ts +14 -0
- package/lib/types/simple/room/SipRoom.d.ts.map +1 -0
- package/lib/types/simple/room/Stream.d.ts +13 -0
- package/lib/types/simple/room/Stream.d.ts.map +1 -0
- package/lib/types/simple/room/__tests__/Participant.test.d.ts +2 -0
- package/lib/types/simple/room/__tests__/Participant.test.d.ts.map +1 -0
- package/lib/types/simple/room/__tests__/RemoteParticipant.test.d.ts +2 -0
- package/lib/types/simple/room/__tests__/RemoteParticipant.test.d.ts.map +1 -0
- package/lib/types/simple/utils.d.ts +3 -0
- package/lib/types/simple/utils.d.ts.map +1 -0
- package/lib/types/types/WebSocketMessage.d.ts +285 -0
- package/lib/types/types/WebSocketMessage.d.ts.map +1 -0
- package/lib/types/utils/Emitter.d.ts +18 -0
- package/lib/types/utils/Emitter.d.ts.map +1 -0
- package/lib/types/utils/Heartbeat.d.ts +21 -0
- package/lib/types/utils/Heartbeat.d.ts.map +1 -0
- package/lib/types/utils/PhoneNumberUtil.d.ts +8 -0
- package/lib/types/utils/PhoneNumberUtil.d.ts.map +1 -0
- package/lib/types/utils/__tests__/Heartbeat.test.d.ts +2 -0
- package/lib/types/utils/__tests__/Heartbeat.test.d.ts.map +1 -0
- package/lib/types/utils/__tests__/PhoneNumberUtil.test.d.ts +2 -0
- package/lib/types/utils/__tests__/PhoneNumberUtil.test.d.ts.map +1 -0
- package/lib/types/utils/__tests__/api-requester.test.d.ts +2 -0
- package/lib/types/utils/__tests__/api-requester.test.d.ts.map +1 -0
- package/lib/types/utils/__tests__/array.test.d.ts +2 -0
- package/lib/types/utils/__tests__/array.test.d.ts.map +1 -0
- package/lib/types/utils/__tests__/compare-version.test.d.ts +2 -0
- package/lib/types/utils/__tests__/compare-version.test.d.ts.map +1 -0
- package/lib/types/utils/__tests__/object.test.d.ts +2 -0
- package/lib/types/utils/__tests__/object.test.d.ts.map +1 -0
- package/lib/types/utils/__tests__/sdp.test.d.ts +2 -0
- package/lib/types/utils/__tests__/sdp.test.d.ts.map +1 -0
- package/lib/types/utils/__tests__/string.test.d.ts +2 -0
- package/lib/types/utils/__tests__/string.test.d.ts.map +1 -0
- package/lib/types/utils/api-requester.d.ts +45 -0
- package/lib/types/utils/api-requester.d.ts.map +1 -0
- package/lib/types/utils/array.d.ts +2 -0
- package/lib/types/utils/array.d.ts.map +1 -0
- package/lib/types/utils/compare-version.d.ts +3 -0
- package/lib/types/utils/compare-version.d.ts.map +1 -0
- package/lib/types/utils/isMobile.d.ts +3 -0
- package/lib/types/utils/isMobile.d.ts.map +1 -0
- package/lib/types/utils/new-from.d.ts +3 -0
- package/lib/types/utils/new-from.d.ts.map +1 -0
- package/lib/types/utils/object.d.ts +2 -0
- package/lib/types/utils/object.d.ts.map +1 -0
- package/lib/types/utils/once.d.ts +2 -0
- package/lib/types/utils/once.d.ts.map +1 -0
- package/lib/types/utils/sdp.d.ts +13 -0
- package/lib/types/utils/sdp.d.ts.map +1 -0
- package/lib/types/utils/string.d.ts +2 -0
- package/lib/types/utils/string.d.ts.map +1 -0
- package/lib/types/utils/update-from.d.ts +3 -0
- package/lib/types/utils/update-from.d.ts.map +1 -0
- package/lib/types/utils/webrtc.d.ts +15 -0
- package/lib/types/utils/webrtc.d.ts.map +1 -0
- package/lib/types/web-rtc-client.d.ts +220 -0
- package/lib/types/web-rtc-client.d.ts.map +1 -0
- package/lib/types/websocket-client.d.ts +134 -0
- package/lib/types/websocket-client.d.ts.map +1 -0
- package/lib/utils/Emitter.js +22 -33
- package/lib/utils/Heartbeat.js +54 -86
- package/lib/utils/PhoneNumberUtil.js +60 -77
- package/lib/utils/__tests__/Heartbeat.test.js +73 -170
- package/lib/utils/__tests__/PhoneNumberUtil.test.js +57 -131
- package/lib/utils/__tests__/api-requester.test.js +139 -784
- package/lib/utils/__tests__/array.test.js +18 -21
- package/lib/utils/__tests__/compare-version.test.js +12 -27
- package/lib/utils/__tests__/object.test.js +75 -56
- package/lib/utils/__tests__/sdp.test.js +99 -220
- package/lib/utils/__tests__/string.test.js +23 -29
- package/lib/utils/api-requester.js +191 -685
- package/lib/utils/array.js +10 -14
- package/lib/utils/compare-version.js +15 -18
- package/lib/utils/isMobile.js +3 -5
- package/lib/utils/new-from.js +9 -14
- package/lib/utils/object.js +12 -26
- package/lib/utils/once.js +15 -15
- package/lib/utils/sdp.js +97 -150
- package/lib/utils/string.js +8 -12
- package/lib/utils/update-from.js +11 -18
- package/lib/utils/webrtc.js +38 -39
- package/lib/web-rtc-client.js +2070 -7694
- package/lib/websocket-client.js +357 -1021
- package/package.json +41 -34
- package/src/__tests__/{api-client.test.js → api-client.test.ts} +71 -29
- package/src/__tests__/{web-rtc-client.test.js → web-rtc-client.test.ts} +95 -35
- package/src/api/agentd.ts +37 -0
- package/src/api/amid.ts +16 -0
- package/src/api/application.ts +96 -0
- package/src/api/auth.ts +259 -0
- package/src/api/call-logd.ts +38 -0
- package/src/api/calld.ts +183 -0
- package/src/api/chatd.ts +101 -0
- package/src/api/confd.ts +110 -0
- package/src/api/ctid-ng.ts +152 -0
- package/src/api/dird.ts +146 -0
- package/src/api/webhookd.ts +30 -0
- package/src/{api-client.js → api-client.ts} +103 -67
- package/src/checker/{Checker.js → Checker.ts} +27 -20
- package/src/checker/checks/{aor.js → aor.ts} +10 -6
- package/src/checker/checks/{api.js → api.ts} +18 -17
- package/src/checker/checks/{ice-ipv4.js → ice-ipv4.ts} +23 -26
- package/src/checker/checks/{index.js → index.ts} +1 -9
- package/src/checker/checks/{symmetric-nat.js → symmetric-nat.ts} +14 -15
- package/src/checker/checks/{wazo-websocket.js → wazo-websocket.ts} +7 -5
- package/src/checker/checks/{webrtc-transport.js → webrtc-transport.ts} +3 -2
- package/src/checker/checks/{webrtc.js → webrtc.ts} +3 -4
- package/src/domain/{AdHocAPIConference.js → AdHocAPIConference.ts} +38 -54
- package/src/domain/{Agent.js → Agent.ts} +11 -7
- package/src/domain/BadResponse.ts +29 -0
- package/src/domain/{Call.js → Call.ts} +62 -46
- package/src/domain/{CallLog.js → CallLog.ts} +61 -63
- package/src/domain/{CallSession.js → CallSession.ts} +55 -52
- package/src/domain/{ChatMessage.js → ChatMessage.ts} +32 -21
- package/src/domain/{ChatRoom.js → ChatRoom.ts} +15 -11
- package/src/domain/{Contact.js → Contact.ts} +380 -262
- package/src/domain/Device/{DebugDevice.js → DebugDevice.ts} +3 -5
- package/src/domain/Device/{Device.js → Device.ts} +0 -11
- package/src/domain/DirectorySource.ts +13 -0
- package/src/domain/{ExternalApp.js → ExternalApp.ts} +14 -13
- package/src/domain/{Features.js → Features.ts} +43 -17
- package/src/domain/{ForwardOption.js → ForwardOption.ts} +16 -16
- package/src/domain/{IndirectTransfer.js → IndirectTransfer.ts} +21 -19
- package/src/domain/{Line.js → Line.ts} +39 -26
- package/src/domain/{Meeting.js → Meeting.ts} +36 -29
- package/src/domain/{MeetingAuthorization.js → MeetingAuthorization.ts} +13 -12
- package/src/domain/{MeetingStatus.js → MeetingStatus.ts} +2 -6
- package/src/domain/{NotificationOptions.js → NotificationOptions.ts} +14 -13
- package/src/domain/Phone/{CTIPhone.js → CTIPhone.ts} +90 -60
- package/src/domain/Phone/{Phone.js → Phone.ts} +27 -72
- package/src/domain/Phone/{WebRTCPhone.js → WebRTCPhone.ts} +456 -422
- package/src/domain/{Profile.js → Profile.ts} +117 -100
- package/src/domain/{Recording.js → Recording.ts} +25 -16
- package/src/domain/{Relocation.js → Relocation.ts} +15 -14
- package/src/domain/{Room.js → Room.ts} +58 -27
- package/src/domain/{SFUNotAvailableError.js → SFUNotAvailableError.ts} +2 -2
- package/src/domain/ServerError.ts +12 -0
- package/src/domain/{Session.js → Session.ts} +89 -67
- package/src/domain/{SipLine.js → SipLine.ts} +52 -45
- package/src/domain/{Subscription.js → Subscription.ts} +22 -13
- package/src/domain/{SwitchboardCall.js → SwitchboardCall.ts} +48 -43
- package/src/domain/{Voicemail.js → Voicemail.ts} +38 -34
- package/src/domain/__tests__/{Agent.test.js → Agent.test.ts} +11 -19
- package/src/domain/__tests__/{Call.test.js → Call.test.ts} +12 -9
- package/src/domain/__tests__/CallLog.test.ts +65 -0
- package/src/domain/__tests__/{CallSession.test.js → CallSession.test.ts} +15 -19
- package/src/domain/__tests__/Contact.test.ts +238 -0
- package/src/domain/__tests__/{IndirectTransfer.test.js → IndirectTransfer.test.ts} +38 -31
- package/src/domain/__tests__/Line.test.ts +53 -0
- package/src/domain/__tests__/{Meeting.test.js → Meeting.test.ts} +12 -38
- package/src/domain/__tests__/{MeetingAuthorization.test.js → MeetingAuthorization.test.ts} +13 -21
- package/src/domain/__tests__/Profile.test.ts +139 -0
- package/src/domain/__tests__/{Room.test.js → Room.test.ts} +114 -76
- package/src/domain/__tests__/{Session.test.js → Session.test.ts} +137 -162
- package/src/domain/__tests__/{SipLine.test.js → SipLine.test.ts} +7 -3
- package/src/domain/__tests__/{Voicemail.test.js → Voicemail.test.ts} +26 -20
- package/src/domain/types.ts +227 -0
- package/src/{index.js → index.ts} +4 -28
- package/src/lib/WazoSessionDescriptionHandler.ts +534 -0
- package/{config.js → src/pubkey.ts} +3 -3
- package/src/service/{CallApi.js → CallApi.ts} +14 -18
- package/src/service/{IssueReporter.js → IssueReporter.ts} +105 -56
- package/src/service/__tests__/{IssueReporter.test.js → IssueReporter.test.ts} +27 -23
- package/src/service/getApiClient.ts +94 -0
- package/src/simple/{Auth.js → Auth.ts} +130 -101
- package/src/simple/{Configuration.js → Configuration.ts} +2 -3
- package/src/simple/{Directory.js → Directory.ts} +2 -3
- package/src/simple/Phone.ts +623 -0
- package/src/simple/Websocket.ts +119 -0
- package/src/simple/{index.js → index.ts} +51 -21
- package/src/simple/room/{LocalParticipant.js → LocalParticipant.ts} +1 -3
- package/src/simple/room/{Participant.js → Participant.ts} +108 -46
- package/src/simple/room/{RemoteParticipant.js → RemoteParticipant.ts} +5 -4
- package/src/simple/room/{Room.js → Room.ts} +266 -183
- package/src/simple/room/{SipRoom.js → SipRoom.ts} +46 -29
- package/src/simple/room/{Stream.js → Stream.ts} +8 -6
- package/src/simple/room/__tests__/{Participant.test.js → Participant.test.ts} +9 -15
- package/src/simple/room/__tests__/{RemoteParticipant.test.js → RemoteParticipant.test.ts} +5 -1
- package/src/simple/utils.ts +12 -0
- package/src/types/WebSocketMessage.ts +335 -0
- package/src/types/global.d.ts +26 -0
- package/src/utils/Emitter.ts +34 -0
- package/src/utils/{Heartbeat.js → Heartbeat.ts} +17 -11
- package/src/utils/{PhoneNumberUtil.js → PhoneNumberUtil.ts} +12 -18
- package/src/utils/__tests__/{Heartbeat.test.js → Heartbeat.test.ts} +0 -15
- package/src/utils/__tests__/{PhoneNumberUtil.test.js → PhoneNumberUtil.test.ts} +6 -4
- package/src/utils/__tests__/{api-requester.test.js → api-requester.test.ts} +75 -24
- package/src/utils/__tests__/{array.test.js → array.test.ts} +10 -2
- package/src/utils/__tests__/object.test.ts +77 -0
- package/src/utils/__tests__/{sdp.test.js → sdp.test.ts} +15 -37
- package/src/utils/__tests__/{string.test.js → string.test.ts} +4 -2
- package/src/utils/{api-requester.js → api-requester.ts} +104 -83
- package/src/utils/{array.js → array.ts} +2 -2
- package/src/utils/{compare-version.js → compare-version.ts} +3 -2
- package/src/utils/{isMobile.js → isMobile.ts} +1 -1
- package/src/utils/{new-from.js → new-from.ts} +3 -6
- package/src/utils/{object.js → object.ts} +3 -6
- package/src/utils/{once.js → once.ts} +5 -5
- package/src/utils/sdp.ts +119 -0
- package/src/utils/{string.js → string.ts} +2 -3
- package/src/utils/update-from.ts +11 -0
- package/src/utils/{webrtc.js → webrtc.ts} +21 -3
- package/src/{web-rtc-client.js → web-rtc-client.ts} +879 -476
- package/src/{websocket-client.js → websocket-client.ts} +146 -144
- package/esm/simple/Softphone.js +0 -394
- package/lib/simple/Softphone.js +0 -396
- package/src/api/agentd.js +0 -74
- package/src/api/amid.js +0 -13
- package/src/api/application.js +0 -137
- package/src/api/auth.js +0 -279
- package/src/api/call-logd.js +0 -20
- package/src/api/calld.js +0 -214
- package/src/api/chatd.js +0 -80
- package/src/api/confd.js +0 -127
- package/src/api/ctid-ng.js +0 -153
- package/src/api/dird.js +0 -159
- package/src/api/webhookd.js +0 -31
- package/src/domain/BadResponse.js +0 -42
- package/src/domain/DirectorySource.js +0 -16
- package/src/domain/ServerError.js +0 -18
- package/src/domain/__tests__/CallLog.test.js +0 -75
- package/src/domain/__tests__/Contact.test.js +0 -170
- package/src/domain/__tests__/Line.test.js +0 -73
- package/src/domain/__tests__/Profile.test.js +0 -104
- package/src/domain/types.js +0 -248
- package/src/lib/WazoSessionDescriptionHandler.js +0 -467
- package/src/service/getApiClient.js +0 -122
- package/src/simple/Phone.js +0 -425
- package/src/simple/Softphone.js +0 -392
- package/src/simple/Websocket.js +0 -86
- package/src/simple/utils.js +0 -17
- package/src/types/WebSocketMessage.js +0 -232
- package/src/utils/Emitter.js +0 -26
- package/src/utils/__tests__/object.test.js +0 -35
- package/src/utils/sdp.js +0 -140
- package/src/utils/update-from.js +0 -15
- /package/src/domain/{Country.js → Country.ts} +0 -0
- /package/src/utils/__tests__/{compare-version.test.js → compare-version.test.ts} +0 -0
|
@@ -1,37 +1,36 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
/* eslint-disable class-methods-use-this, no-param-reassign, max-classes-per-file, no-underscore-dangle */
|
|
2
|
+
|
|
3
3
|
/* global window, document, navigator */
|
|
4
4
|
import 'webrtc-adapter';
|
|
5
|
-
import type InviterInviteOptions from 'sip.js/lib/api/inviter-invite-options';
|
|
6
|
-
import type Invitation from 'sip.js/lib/api/invitation';
|
|
5
|
+
import type { InviterInviteOptions } from 'sip.js/lib/api/inviter-invite-options';
|
|
7
6
|
import type { IncomingResponse } from 'sip.js/lib/core/messages/incoming-response';
|
|
8
|
-
import type {
|
|
7
|
+
import type { InvitationRejectOptions } from 'sip.js/lib/api/invitation-reject-options';
|
|
8
|
+
import type { InviterCancelOptions } from 'sip.js/lib/api/inviter-cancel-options';
|
|
9
|
+
import type { SessionByeOptions } from 'sip.js/lib/api/session-bye-options';
|
|
10
|
+
import type { InvitationAcceptOptions } from 'sip.js/lib/api/invitation-accept-options';
|
|
11
|
+
|
|
9
12
|
import type { SessionDialog } from 'sip.js/lib/core/dialogs/session-dialog';
|
|
10
13
|
import type { IncomingRequestMessage } from 'sip.js/lib/core/messages/incoming-request-message';
|
|
11
|
-
import type { SessionDescriptionHandlerFactoryOptions }
|
|
12
|
-
|
|
13
|
-
import type
|
|
14
|
-
from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-configuration';
|
|
15
|
-
import type SessionDescriptionHandler
|
|
16
|
-
from 'sip.js/lib/platform/web/session-description-handler/session-description-handler';
|
|
14
|
+
import type { SessionDescriptionHandlerFactoryOptions } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-factory-options';
|
|
15
|
+
import type { SessionDescriptionHandlerConfiguration } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-configuration';
|
|
16
|
+
import type { SessionDescriptionHandler } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler';
|
|
17
17
|
import { UserAgentState } from 'sip.js/lib/api/user-agent-state';
|
|
18
18
|
import { Parser } from 'sip.js/lib/core/messages/parser';
|
|
19
19
|
import { C } from 'sip.js/lib/core/messages/methods/constants';
|
|
20
20
|
import { URI } from 'sip.js/lib/grammar/uri';
|
|
21
21
|
import { UserAgent } from 'sip.js/lib/api/user-agent';
|
|
22
22
|
import { holdModifier, stripVideo } from 'sip.js/lib/platform/web/modifiers/modifiers';
|
|
23
|
-
|
|
24
|
-
import { Inviter } from 'sip.js/lib/api/inviter';
|
|
23
|
+
|
|
25
24
|
import { Messager } from 'sip.js/lib/api/messager';
|
|
26
25
|
import { RegistererState } from 'sip.js/lib/api/registerer-state';
|
|
27
26
|
import { SessionState } from 'sip.js/lib/api/session-state';
|
|
28
27
|
import { TransportState } from 'sip.js/lib/api/transport-state';
|
|
29
|
-
import { defaultPeerConnectionConfiguration }
|
|
30
|
-
from 'sip.js/lib/platform/web/session-description-handler/peer-connection-configuration-default';
|
|
28
|
+
import { defaultPeerConnectionConfiguration } from 'sip.js/lib/platform/web/session-description-handler/peer-connection-configuration-default';
|
|
31
29
|
import getStats from 'getstats';
|
|
32
30
|
|
|
31
|
+
import { OutgoingByeRequest, OutgoingInviteRequest, OutgoingRequest } from 'sip.js/lib/core';
|
|
32
|
+
import { Inviter, Invitation, Registerer } from 'sip.js/lib/api';
|
|
33
33
|
import WazoSessionDescriptionHandler, { wazoMediaStreamFactory } from './lib/WazoSessionDescriptionHandler';
|
|
34
|
-
|
|
35
34
|
import Emitter from './utils/Emitter';
|
|
36
35
|
import ApiClient from './api-client';
|
|
37
36
|
import IssueReporter from './service/IssueReporter';
|
|
@@ -40,19 +39,16 @@ import { getVideoDirection, hasAnActiveVideo } from './utils/sdp';
|
|
|
40
39
|
import { lastIndexOf } from './utils/array';
|
|
41
40
|
|
|
42
41
|
// We need to replace 0.0.0.0 to 127.0.0.1 in the sdp to avoid MOH during a createOffer.
|
|
43
|
-
export const replaceLocalIpModifier = (description:
|
|
44
|
-
// description is immutable... so we have to clone it or the `type` attribute won't be returned.
|
|
42
|
+
export const replaceLocalIpModifier = (description: Record<string, any>) => Promise.resolve({ // description is immutable... so we have to clone it or the `type` attribute won't be returned.
|
|
45
43
|
...JSON.parse(JSON.stringify(description)),
|
|
46
44
|
sdp: description.sdp.replace('c=IN IP4 0.0.0.0', 'c=IN IP4 127.0.0.1'),
|
|
47
45
|
});
|
|
48
|
-
|
|
46
|
+
const SIP_ID_LENGTH = 36;
|
|
49
47
|
const DEFAULT_ICE_TIMEOUT = 3000;
|
|
50
48
|
const SEND_STATS_DELAY = 5000;
|
|
51
|
-
|
|
52
49
|
const states = ['STATUS_NULL', 'STATUS_NEW', 'STATUS_CONNECTING', 'STATUS_CONNECTED', 'STATUS_COMPLETED'];
|
|
53
50
|
const logger = IssueReporter ? IssueReporter.loggerFor('webrtc-client') : console;
|
|
54
51
|
const statsLogger = IssueReporter ? IssueReporter.loggerFor('webrtc-stats') : console;
|
|
55
|
-
|
|
56
52
|
// events
|
|
57
53
|
const REGISTERED = 'registered';
|
|
58
54
|
const UNREGISTERED = 'unregistered';
|
|
@@ -71,84 +67,121 @@ const ON_ERROR = 'onError';
|
|
|
71
67
|
const ON_SCREEN_SHARING_REINVITE = 'onScreenSharingReinvite';
|
|
72
68
|
const ON_NETWORK_STATS = 'onNetworkStats';
|
|
73
69
|
const ON_DISCONNECTED = 'onDisconnected';
|
|
74
|
-
|
|
75
70
|
export const events = [REGISTERED, UNREGISTERED, REGISTRATION_FAILED, INVITE];
|
|
76
71
|
export const transportEvents = [CONNECTED, DISCONNECTED, TRANSPORT_ERROR, MESSAGE];
|
|
77
72
|
export class CanceledCallError extends Error {}
|
|
78
|
-
|
|
79
73
|
const MAX_REGISTER_TRIES = 5;
|
|
80
|
-
|
|
81
74
|
type MediaConfig = {
|
|
82
|
-
audio:
|
|
83
|
-
video
|
|
84
|
-
localVideo?:
|
|
75
|
+
audio: Record<string, any> | boolean;
|
|
76
|
+
video?: Record<string, any> | boolean;
|
|
77
|
+
localVideo?: Record<string, any> | boolean;
|
|
85
78
|
};
|
|
86
|
-
|
|
87
79
|
type WebRtcConfig = {
|
|
88
|
-
displayName
|
|
89
|
-
host: string
|
|
90
|
-
port?: number
|
|
91
|
-
websocketSip?:
|
|
92
|
-
authorizationUser
|
|
93
|
-
password
|
|
94
|
-
uri
|
|
95
|
-
media
|
|
96
|
-
iceCheckingTimeout
|
|
97
|
-
log?:
|
|
98
|
-
audioOutputDeviceId?: string
|
|
80
|
+
displayName?: string;
|
|
81
|
+
host: string;
|
|
82
|
+
port?: number;
|
|
83
|
+
websocketSip?: string;
|
|
84
|
+
authorizationUser?: string;
|
|
85
|
+
password?: string;
|
|
86
|
+
uri?: string;
|
|
87
|
+
media?: MediaConfig;
|
|
88
|
+
iceCheckingTimeout?: number;
|
|
89
|
+
log?: Record<string, any>;
|
|
90
|
+
audioOutputDeviceId?: string;
|
|
99
91
|
audioOutputVolume?: number;
|
|
100
|
-
userAgentString?: string
|
|
101
|
-
heartbeatDelay
|
|
102
|
-
heartbeatTimeout
|
|
103
|
-
maxHeartbeats
|
|
104
|
-
skipRegister
|
|
105
|
-
};
|
|
92
|
+
userAgentString?: string;
|
|
93
|
+
heartbeatDelay?: number;
|
|
94
|
+
heartbeatTimeout?: number;
|
|
95
|
+
maxHeartbeats?: number;
|
|
96
|
+
skipRegister?: boolean;
|
|
97
|
+
}; // @see https://github.com/onsip/SIP.js/blob/master/src/Web/Simple.js
|
|
106
98
|
|
|
107
|
-
// @see https://github.com/onsip/SIP.js/blob/master/src/Web/Simple.js
|
|
108
99
|
export default class WebRTCClient extends Emitter {
|
|
100
|
+
clientId: number;
|
|
101
|
+
|
|
109
102
|
config: WebRtcConfig;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
103
|
+
|
|
104
|
+
uaConfigOverrides: Record<string, any> | null | undefined;
|
|
105
|
+
|
|
106
|
+
userAgent: UserAgent | null;
|
|
107
|
+
|
|
108
|
+
registerer: Registerer | null;
|
|
109
|
+
|
|
113
110
|
hasAudio: boolean;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
|
|
112
|
+
audio: MediaTrackConstraints | boolean | undefined;
|
|
113
|
+
|
|
114
|
+
audioElements: Record<string, HTMLAudioElement>;
|
|
115
|
+
|
|
116
|
+
video: MediaTrackConstraints | boolean | undefined;
|
|
117
|
+
|
|
118
|
+
audioStreams: Record<string, any>;
|
|
119
|
+
|
|
120
|
+
audioOutputDeviceId: string | null | undefined;
|
|
121
|
+
|
|
119
122
|
audioOutputVolume: number;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
|
|
124
|
+
heldSessions: Record<string, any>;
|
|
125
|
+
|
|
126
|
+
connectionPromise: Promise<void> | null | undefined;
|
|
127
|
+
|
|
128
|
+
_boundOnHeartbeat: (...args: Array<any>) => any;
|
|
129
|
+
|
|
123
130
|
heartbeat: Heartbeat;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
|
|
132
|
+
heartbeatTimeoutCb: ((...args: Array<any>) => any) | null | undefined;
|
|
133
|
+
|
|
134
|
+
heartbeatCb: ((...args: Array<any>) => any) | null | undefined;
|
|
135
|
+
|
|
136
|
+
statsIntervals: Record<string, any>;
|
|
137
|
+
|
|
138
|
+
sipSessions: Record<string, Invitation | Inviter>;
|
|
139
|
+
|
|
140
|
+
conferences: Record<string, boolean>;
|
|
141
|
+
|
|
129
142
|
skipRegister: boolean;
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
|
|
144
|
+
networkMonitoringInterval: Record<string, any>;
|
|
145
|
+
|
|
146
|
+
sessionNetworkStats: Record<string, Record<string, any>>;
|
|
147
|
+
|
|
132
148
|
forceClosed: boolean;
|
|
133
149
|
|
|
134
150
|
// sugar
|
|
135
151
|
ON_USER_AGENT: string;
|
|
152
|
+
|
|
136
153
|
REGISTERED: string;
|
|
154
|
+
|
|
137
155
|
UNREGISTERED: string;
|
|
156
|
+
|
|
138
157
|
REGISTRATION_FAILED: string;
|
|
158
|
+
|
|
139
159
|
INVITE: string;
|
|
160
|
+
|
|
140
161
|
CONNECTED: string;
|
|
162
|
+
|
|
141
163
|
DISCONNECTED: string;
|
|
164
|
+
|
|
142
165
|
TRANSPORT_ERROR: string;
|
|
166
|
+
|
|
143
167
|
MESSAGE: string;
|
|
168
|
+
|
|
144
169
|
ACCEPTED: string;
|
|
170
|
+
|
|
145
171
|
REJECTED: string;
|
|
172
|
+
|
|
146
173
|
ON_TRACK: string;
|
|
174
|
+
|
|
147
175
|
ON_REINVITE: string;
|
|
176
|
+
|
|
148
177
|
ON_ERROR: string;
|
|
178
|
+
|
|
149
179
|
ON_SCREEN_SHARING_REINVITE: string;
|
|
180
|
+
|
|
150
181
|
ON_NETWORK_STATS: string;
|
|
182
|
+
|
|
151
183
|
ON_EARLY_MEDIA: string;
|
|
184
|
+
|
|
152
185
|
ON_DISCONNECTED: string;
|
|
153
186
|
|
|
154
187
|
static isAPrivateIp(ip: string): boolean {
|
|
@@ -156,22 +189,28 @@ export default class WebRTCClient extends Emitter {
|
|
|
156
189
|
return regex.exec(ip) == null;
|
|
157
190
|
}
|
|
158
191
|
|
|
159
|
-
static getIceServers(ip: string): Array<{
|
|
192
|
+
static getIceServers(ip: string): Array<{
|
|
193
|
+
urls: Array<string>;
|
|
194
|
+
}> {
|
|
160
195
|
if (WebRTCClient.isAPrivateIp(ip)) {
|
|
161
|
-
return [
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
},
|
|
165
|
-
];
|
|
196
|
+
return [{
|
|
197
|
+
urls: ['stun:stun.l.google.com:19302', 'stun:stun4.l.google.com:19302'],
|
|
198
|
+
}];
|
|
166
199
|
}
|
|
200
|
+
|
|
167
201
|
return [];
|
|
168
202
|
}
|
|
169
203
|
|
|
170
|
-
constructor(config: WebRtcConfig, session:
|
|
204
|
+
constructor(config: WebRtcConfig, session: Invitation | Inviter | null | undefined, uaConfigOverrides: Record<string, any> | null | undefined = undefined) {
|
|
171
205
|
super();
|
|
206
|
+
|
|
207
|
+
// For debug purpose
|
|
208
|
+
this.clientId = Math.ceil(Math.random() * 1000);
|
|
209
|
+
logger.info('sdk webrtc constructor', { clientId: this.clientId });
|
|
210
|
+
|
|
172
211
|
this.uaConfigOverrides = uaConfigOverrides;
|
|
173
212
|
this.config = config;
|
|
174
|
-
this.skipRegister = config.skipRegister;
|
|
213
|
+
this.skipRegister = config.skipRegister as boolean;
|
|
175
214
|
|
|
176
215
|
this._buildConfig(config, session).then((newConfig: WebRtcConfig) => {
|
|
177
216
|
this.config = newConfig;
|
|
@@ -183,7 +222,10 @@ export default class WebRTCClient extends Emitter {
|
|
|
183
222
|
|
|
184
223
|
if (config.media) {
|
|
185
224
|
this.configureMedia(config.media);
|
|
186
|
-
this.setMediaConstraints({
|
|
225
|
+
this.setMediaConstraints({
|
|
226
|
+
audio: config.media.audio,
|
|
227
|
+
video: config.media.video,
|
|
228
|
+
});
|
|
187
229
|
}
|
|
188
230
|
|
|
189
231
|
this.heldSessions = {};
|
|
@@ -194,12 +236,10 @@ export default class WebRTCClient extends Emitter {
|
|
|
194
236
|
this.networkMonitoringInterval = {};
|
|
195
237
|
this.sessionNetworkStats = {};
|
|
196
238
|
this.forceClosed = false;
|
|
197
|
-
|
|
198
239
|
this._boundOnHeartbeat = this._onHeartbeat.bind(this);
|
|
199
240
|
this.heartbeat = new Heartbeat(config.heartbeatDelay, config.heartbeatTimeout, config.maxHeartbeats);
|
|
200
241
|
this.heartbeat.setSendHeartbeat(this.pingServer.bind(this));
|
|
201
242
|
this.heartbeat.setOnHeartbeatTimeout(this._onHeartbeatTimeout.bind(this));
|
|
202
|
-
|
|
203
243
|
// sugar
|
|
204
244
|
this.REGISTERED = REGISTERED;
|
|
205
245
|
this.UNREGISTERED = UNREGISTERED;
|
|
@@ -231,36 +271,38 @@ export default class WebRTCClient extends Emitter {
|
|
|
231
271
|
this.audio = media.audio;
|
|
232
272
|
}
|
|
233
273
|
|
|
234
|
-
createUserAgent(configOverrides:
|
|
274
|
+
createUserAgent(configOverrides: Record<string, any> | null | undefined): UserAgent {
|
|
235
275
|
const webRTCConfiguration = this._createWebRTCConfiguration(configOverrides);
|
|
236
|
-
logger.info('sdk webrtc, creating UA', { webRTCConfiguration });
|
|
237
276
|
|
|
277
|
+
logger.info('sdk webrtc, creating UA', { webRTCConfiguration, clientId: this.clientId });
|
|
238
278
|
webRTCConfiguration.delegate = {
|
|
239
279
|
onConnect: this.onConnect.bind(this),
|
|
240
280
|
onDisconnect: this.onDisconnect.bind(this),
|
|
241
281
|
onInvite: (invitation: Invitation) => {
|
|
242
282
|
logger.info('sdk webrtc on invite', {
|
|
243
283
|
method: 'delegate.onInvite',
|
|
284
|
+
clientId: this.clientId,
|
|
244
285
|
id: invitation.id,
|
|
286
|
+
// @ts-ignore
|
|
245
287
|
remoteURI: invitation.remoteURI,
|
|
246
288
|
});
|
|
289
|
+
|
|
247
290
|
this._setupSession(invitation);
|
|
248
|
-
const shouldAutoAnswer = !!invitation.request.getHeader('alert-info');
|
|
249
291
|
|
|
292
|
+
const shouldAutoAnswer = !!invitation.request.getHeader('alert-info');
|
|
250
293
|
this.eventEmitter.emit(INVITE, invitation, this.sessionWantsToDoVideo(invitation), shouldAutoAnswer);
|
|
251
294
|
},
|
|
252
295
|
};
|
|
296
|
+
const ua: any = new UserAgent(webRTCConfiguration);
|
|
253
297
|
|
|
254
|
-
const ua = new UserAgent(webRTCConfiguration);
|
|
255
298
|
if (ua.transport && ua.transport.connectPromise) {
|
|
256
|
-
ua.transport.connectPromise.catch((e => {
|
|
299
|
+
ua.transport.connectPromise.catch((e: any) => {
|
|
257
300
|
logger.warn('Transport connect error', e);
|
|
258
|
-
})
|
|
301
|
+
});
|
|
259
302
|
}
|
|
260
303
|
|
|
261
304
|
ua.transport.onMessage = (rawMessage: string) => {
|
|
262
305
|
const message = Parser.parseMessage(rawMessage, ua.transport.logger);
|
|
263
|
-
|
|
264
306
|
// We have to re-sent the message to the UA ...
|
|
265
307
|
ua.onTransportMessage(rawMessage);
|
|
266
308
|
// And now do what we want with the message
|
|
@@ -268,7 +310,9 @@ export default class WebRTCClient extends Emitter {
|
|
|
268
310
|
|
|
269
311
|
if (message && message.method === C.MESSAGE) {
|
|
270
312
|
// We have to manually reply to MESSAGE with a 200 OK or Asterisk will hangup.
|
|
271
|
-
ua.userAgentCore.replyStateless(message, {
|
|
313
|
+
ua.userAgentCore.replyStateless(message, {
|
|
314
|
+
statusCode: 200,
|
|
315
|
+
});
|
|
272
316
|
}
|
|
273
317
|
};
|
|
274
318
|
|
|
@@ -276,51 +320,61 @@ export default class WebRTCClient extends Emitter {
|
|
|
276
320
|
}
|
|
277
321
|
|
|
278
322
|
isConnected(): boolean {
|
|
279
|
-
return this.userAgent
|
|
323
|
+
return Boolean(this.userAgent?.isConnected());
|
|
280
324
|
}
|
|
281
325
|
|
|
282
326
|
isConnecting(): boolean {
|
|
283
|
-
return this.userAgent
|
|
327
|
+
return this.userAgent?.transport?.state === TransportState.Connecting;
|
|
284
328
|
}
|
|
285
329
|
|
|
286
330
|
isRegistered(): boolean {
|
|
287
|
-
return this.registerer && this.registerer.state === RegistererState.Registered;
|
|
331
|
+
return Boolean(this.registerer && this.registerer.state === RegistererState.Registered);
|
|
288
332
|
}
|
|
289
333
|
|
|
290
334
|
onConnect() {
|
|
291
|
-
logger.info('sdk webrtc connected', { method: 'delegate.onConnect' });
|
|
335
|
+
logger.info('sdk webrtc connected', { method: 'delegate.onConnect', clientId: this.clientId });
|
|
292
336
|
this.eventEmitter.emit(CONNECTED);
|
|
293
|
-
|
|
337
|
+
|
|
338
|
+
// @ts-ignore
|
|
339
|
+
if (!this.isRegistered() && this.registerer?.waiting) {
|
|
340
|
+
// @ts-ignore
|
|
294
341
|
this.registerer.waitingToggle(false);
|
|
295
342
|
}
|
|
343
|
+
|
|
296
344
|
return this.register();
|
|
297
345
|
}
|
|
298
346
|
|
|
299
347
|
async onDisconnect(error?: Error) {
|
|
300
|
-
logger.info('sdk webrtc disconnected', { method: 'delegate.onConnect', error });
|
|
348
|
+
logger.info('sdk webrtc disconnected', { method: 'delegate.onConnect', clientId: this.clientId, error });
|
|
301
349
|
this.connectionPromise = null;
|
|
302
350
|
// The UA will attempt to reconnect automatically when an error occurred
|
|
303
351
|
this.eventEmitter.emit(DISCONNECTED, error);
|
|
352
|
+
|
|
304
353
|
if (this.isRegistered()) {
|
|
305
354
|
await this.unregister();
|
|
306
|
-
|
|
355
|
+
|
|
356
|
+
// @ts-ignore
|
|
357
|
+
if (this.registerer?.waiting) {
|
|
358
|
+
// @ts-ignore
|
|
307
359
|
this.registerer.waitingToggle(false);
|
|
308
360
|
}
|
|
361
|
+
|
|
309
362
|
this.eventEmitter.emit(UNREGISTERED);
|
|
310
363
|
}
|
|
311
364
|
}
|
|
312
365
|
|
|
313
|
-
register(tries
|
|
366
|
+
async register(tries = 0): Promise<void> {
|
|
314
367
|
const logInfo = {
|
|
368
|
+
clientId: this.clientId,
|
|
315
369
|
userAgent: !!this.userAgent,
|
|
316
370
|
registered: this.isRegistered(),
|
|
317
371
|
connectionPromise: !!this.connectionPromise,
|
|
318
372
|
registerer: !!this.registerer,
|
|
373
|
+
// @ts-ignore
|
|
319
374
|
waiting: this.registerer && this.registerer.waiting,
|
|
320
375
|
tries,
|
|
321
376
|
skipRegister: this.skipRegister,
|
|
322
377
|
};
|
|
323
|
-
|
|
324
378
|
this.forceClosed = false;
|
|
325
379
|
|
|
326
380
|
if (this.skipRegister) {
|
|
@@ -334,35 +388,44 @@ export default class WebRTCClient extends Emitter {
|
|
|
334
388
|
logger.info('sdk webrtc recreating User Agent');
|
|
335
389
|
this.userAgent = this.createUserAgent(this.uaConfigOverrides);
|
|
336
390
|
}
|
|
391
|
+
|
|
337
392
|
if (!this.userAgent || this.isRegistered()) {
|
|
338
393
|
logger.info('sdk webrtc registering aborted, already registered or no UA can be created');
|
|
339
394
|
return Promise.resolve();
|
|
340
395
|
}
|
|
341
396
|
|
|
342
|
-
|
|
343
|
-
|
|
397
|
+
// @ts-ignore
|
|
398
|
+
if (this.connectionPromise || this.registerer?.waiting) {
|
|
399
|
+
logger.info('sdk webrtc registering aborted due to a registration in progress.', { clientId: this.clientId });
|
|
344
400
|
return Promise.resolve();
|
|
345
401
|
}
|
|
346
402
|
|
|
347
|
-
const registerOptions = this._isWeb() ? {} : {
|
|
403
|
+
const registerOptions = this._isWeb() ? {} : {
|
|
404
|
+
extraContactHeaderParams: ['mobility=mobile'],
|
|
405
|
+
};
|
|
348
406
|
|
|
349
407
|
const onRegisterFailed = () => {
|
|
350
408
|
logger.info('sdk webrtc registering failed', {
|
|
351
409
|
tries,
|
|
410
|
+
clientId: this.clientId,
|
|
352
411
|
registerer: !!this.registerer,
|
|
353
412
|
forceClosed: this.forceClosed,
|
|
354
413
|
});
|
|
414
|
+
|
|
355
415
|
if (this.forceClosed) {
|
|
356
416
|
return;
|
|
357
417
|
}
|
|
358
418
|
|
|
359
419
|
this.connectionPromise = null;
|
|
420
|
+
|
|
421
|
+
// @ts-ignore
|
|
360
422
|
if (this.registerer && this.registerer.waiting) {
|
|
423
|
+
// @ts-ignore
|
|
361
424
|
this.registerer.waitingToggle(false);
|
|
362
425
|
}
|
|
363
426
|
|
|
364
427
|
if (tries <= MAX_REGISTER_TRIES) {
|
|
365
|
-
logger.info('sdk webrtc registering, retrying...', { tries });
|
|
428
|
+
logger.info('sdk webrtc registering, retrying...', { clientId: this.clientId, tries });
|
|
366
429
|
setTimeout(() => this.register(tries + 1), 300);
|
|
367
430
|
}
|
|
368
431
|
};
|
|
@@ -375,36 +438,32 @@ export default class WebRTCClient extends Emitter {
|
|
|
375
438
|
this.userAgent = this.createUserAgent(this.uaConfigOverrides);
|
|
376
439
|
}
|
|
377
440
|
|
|
378
|
-
logger.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent });
|
|
441
|
+
logger.info('sdk webrtc registering, transport connected', { registerOptions, ua: !!this.userAgent, clientId: this.clientId });
|
|
379
442
|
this.registerer = new Registerer(this.userAgent, registerOptions);
|
|
380
443
|
this.connectionPromise = null;
|
|
444
|
+
|
|
381
445
|
this._monkeyPatchRegisterer(this.registerer);
|
|
382
446
|
|
|
383
447
|
// Bind registerer events
|
|
384
448
|
this.registerer.stateChange.addListener(newState => {
|
|
385
|
-
logger.info('sdk webrtc registering, state changed', { newState });
|
|
449
|
+
logger.info('sdk webrtc registering, state changed', { newState, clientId: this.clientId });
|
|
386
450
|
|
|
387
|
-
if (newState === RegistererState.Registered && this.registerer
|
|
388
|
-
&& this.registerer.state === RegistererState.Registered) {
|
|
451
|
+
if (newState === RegistererState.Registered && this.registerer && this.registerer.state === RegistererState.Registered) {
|
|
389
452
|
this.eventEmitter.emit(REGISTERED);
|
|
390
453
|
} else if (newState === RegistererState.Unregistered) {
|
|
391
454
|
this.eventEmitter.emit(UNREGISTERED);
|
|
392
455
|
}
|
|
393
456
|
});
|
|
394
|
-
|
|
395
457
|
const options = {
|
|
396
458
|
requestDelegate: {
|
|
397
|
-
onReject: response => {
|
|
398
|
-
logger.error('sdk webrtc registering, rejected', { response });
|
|
399
|
-
|
|
459
|
+
onReject: (response: any) => {
|
|
460
|
+
logger.error('sdk webrtc registering, rejected', { clientId: this.clientId, response });
|
|
400
461
|
onRegisterFailed();
|
|
401
462
|
},
|
|
402
463
|
},
|
|
403
464
|
};
|
|
404
|
-
|
|
405
|
-
return this.registerer.register(options).catch((e) => {
|
|
465
|
+
return this.registerer.register(options).catch(e => {
|
|
406
466
|
logger.error('sdk webrtc registering, error', e);
|
|
407
|
-
|
|
408
467
|
this.eventEmitter.emit(REGISTRATION_FAILED);
|
|
409
468
|
return e;
|
|
410
469
|
});
|
|
@@ -415,52 +474,69 @@ export default class WebRTCClient extends Emitter {
|
|
|
415
474
|
}
|
|
416
475
|
|
|
417
476
|
// Monkey patching sip.js to avoid issues during register.onReject
|
|
418
|
-
_monkeyPatchRegisterer(registerer:
|
|
477
|
+
_monkeyPatchRegisterer(registerer: Registerer | null | undefined): void {
|
|
419
478
|
if (!registerer) {
|
|
420
479
|
return;
|
|
421
480
|
}
|
|
481
|
+
|
|
482
|
+
// @ts-ignore
|
|
422
483
|
const oldWaitingToggle = registerer.waitingToggle.bind(registerer);
|
|
484
|
+
// @ts-ignore
|
|
423
485
|
const oldUnregistered = registerer.unregistered.bind(registerer);
|
|
424
486
|
|
|
487
|
+
// @ts-ignore
|
|
425
488
|
registerer.waitingToggle = (waiting: boolean) => {
|
|
489
|
+
// @ts-ignore
|
|
426
490
|
if (!registerer || registerer.waiting === waiting) {
|
|
427
491
|
return;
|
|
428
492
|
}
|
|
493
|
+
|
|
429
494
|
oldWaitingToggle(waiting);
|
|
430
495
|
};
|
|
431
496
|
|
|
497
|
+
// @ts-ignore
|
|
432
498
|
registerer.unregistered = () => {
|
|
433
499
|
if (!registerer || registerer.state === RegistererState.Terminated) {
|
|
434
500
|
return;
|
|
435
501
|
}
|
|
502
|
+
|
|
436
503
|
oldUnregistered();
|
|
437
504
|
};
|
|
438
505
|
}
|
|
439
506
|
|
|
440
|
-
unregister() {
|
|
441
|
-
logger.info('sdk webrtc unregistering..', {
|
|
507
|
+
async unregister(): Promise<void> {
|
|
508
|
+
logger.info('sdk webrtc unregistering..', {
|
|
509
|
+
clientId: this.clientId,
|
|
510
|
+
userAgent: !!this.userAgent,
|
|
511
|
+
registerer: !!this.registerer,
|
|
512
|
+
});
|
|
513
|
+
|
|
442
514
|
if (!this.registerer) {
|
|
443
515
|
return Promise.resolve();
|
|
444
516
|
}
|
|
445
517
|
|
|
446
518
|
try {
|
|
447
519
|
return this.registerer.unregister().then(() => {
|
|
448
|
-
logger.info('sdk webrtc unregistered');
|
|
520
|
+
logger.info('sdk webrtc unregistered', { clientId: this.clientId });
|
|
521
|
+
|
|
449
522
|
this._cleanupRegister();
|
|
450
523
|
}).catch(e => {
|
|
451
524
|
logger.error('sdk webrtc unregistering, promise error', e);
|
|
525
|
+
|
|
452
526
|
this._cleanupRegister();
|
|
453
527
|
});
|
|
454
|
-
} catch (e) {
|
|
528
|
+
} catch (e: any) {
|
|
455
529
|
logger.error('sdk webrtc unregistering, error', e);
|
|
530
|
+
|
|
456
531
|
// Avoid issue with `undefined is not an object (evaluating 'new.target.prototype')` when triggering a new
|
|
457
532
|
// error when the registerer is in a bad state
|
|
458
533
|
this._cleanupRegister();
|
|
459
534
|
}
|
|
460
535
|
}
|
|
461
536
|
|
|
462
|
-
stop(): Promise<
|
|
463
|
-
logger.info('sdk webrtc stop', { userAgent: !!this.userAgent });
|
|
537
|
+
stop(): Promise<void> {
|
|
538
|
+
logger.info('sdk webrtc stop', { clientId: this.clientId, userAgent: !!this.userAgent });
|
|
539
|
+
|
|
464
540
|
if (!this.userAgent) {
|
|
465
541
|
return Promise.resolve();
|
|
466
542
|
}
|
|
@@ -468,13 +544,22 @@ export default class WebRTCClient extends Emitter {
|
|
|
468
544
|
return this.userAgent.stop().then(() => {
|
|
469
545
|
return this._cleanupRegister();
|
|
470
546
|
}).catch(e => {
|
|
471
|
-
logger.warn('sdk webrtc stop, error', {
|
|
547
|
+
logger.warn('sdk webrtc stop, error', {
|
|
548
|
+
message: e.message,
|
|
549
|
+
stack: e.stack,
|
|
550
|
+
});
|
|
472
551
|
});
|
|
473
552
|
}
|
|
474
553
|
|
|
475
|
-
call(number: string, enableVideo?: boolean, audioOnly
|
|
476
|
-
logger.info('sdk webrtc creating call', {
|
|
477
|
-
|
|
554
|
+
call(number: string, enableVideo?: boolean, audioOnly = false, conference = false): Inviter | Invitation {
|
|
555
|
+
logger.info('sdk webrtc creating call', {
|
|
556
|
+
clientId: this.clientId,
|
|
557
|
+
number,
|
|
558
|
+
enableVideo,
|
|
559
|
+
audioOnly,
|
|
560
|
+
conference,
|
|
561
|
+
});
|
|
562
|
+
const inviterOptions: Record<string, any> = {
|
|
478
563
|
sessionDescriptionHandlerOptionsReInvite: {
|
|
479
564
|
conference,
|
|
480
565
|
audioOnly,
|
|
@@ -486,11 +571,20 @@ export default class WebRTCClient extends Emitter {
|
|
|
486
571
|
inviterOptions.sessionDescriptionHandlerModifiersReInvite = [stripVideo];
|
|
487
572
|
}
|
|
488
573
|
|
|
489
|
-
const
|
|
574
|
+
const uri = this._makeURI(number);
|
|
575
|
+
let session: any;
|
|
490
576
|
|
|
491
|
-
|
|
577
|
+
if (uri) {
|
|
578
|
+
session = this.userAgent ? new Inviter(this.userAgent, uri, inviterOptions) : null;
|
|
579
|
+
} else {
|
|
580
|
+
logger.error('Null URI');
|
|
581
|
+
}
|
|
492
582
|
|
|
493
|
-
|
|
583
|
+
if (session) {
|
|
584
|
+
this.storeSipSession(session);
|
|
585
|
+
|
|
586
|
+
this._setupSession(session);
|
|
587
|
+
}
|
|
494
588
|
|
|
495
589
|
if (conference) {
|
|
496
590
|
this.conferences[this.getSipSessionId(session)] = true;
|
|
@@ -499,71 +593,93 @@ export default class WebRTCClient extends Emitter {
|
|
|
499
593
|
const inviteOptions: InviterInviteOptions = {
|
|
500
594
|
requestDelegate: {
|
|
501
595
|
onAccept: (response: IncomingResponse) => {
|
|
502
|
-
|
|
596
|
+
// @ts-ignore
|
|
597
|
+
if (session.sessionDescriptionHandler?.peerConnection) {
|
|
598
|
+
// @ts-ignore
|
|
503
599
|
session.sessionDescriptionHandler.peerConnection.sfu = conference;
|
|
504
600
|
}
|
|
601
|
+
// @ts-ignore
|
|
505
602
|
this._onAccepted(session, response.session, true);
|
|
506
603
|
},
|
|
507
|
-
onProgress:
|
|
604
|
+
onProgress: payload => {
|
|
508
605
|
if (payload.message.statusCode === 183) {
|
|
606
|
+
// @ts-ignore
|
|
509
607
|
this._onEarlyProgress(payload.session);
|
|
510
608
|
}
|
|
511
609
|
},
|
|
512
610
|
onReject: (response: IncomingResponse) => {
|
|
513
|
-
logger.info('on call rejected', {
|
|
611
|
+
logger.info('on call rejected', {
|
|
612
|
+
id: session.id,
|
|
613
|
+
// @ts-ignore
|
|
614
|
+
fromTag: session.fromTag,
|
|
615
|
+
});
|
|
616
|
+
|
|
514
617
|
this._stopSendingStats(session);
|
|
515
|
-
this.stopNetworkMonitoring(session);
|
|
516
618
|
|
|
619
|
+
this.stopNetworkMonitoring(session);
|
|
517
620
|
this.eventEmitter.emit(REJECTED, session, response);
|
|
518
621
|
},
|
|
519
622
|
},
|
|
520
623
|
sessionDescriptionHandlerOptions: this.getMediaConfiguration(enableVideo || false, conference),
|
|
521
624
|
};
|
|
522
625
|
|
|
523
|
-
inviteOptions.sessionDescriptionHandlerOptions
|
|
524
|
-
|
|
626
|
+
if (inviteOptions.sessionDescriptionHandlerOptions) {
|
|
627
|
+
// @ts-ignore
|
|
628
|
+
inviteOptions.sessionDescriptionHandlerOptions.audioOnly = audioOnly;
|
|
629
|
+
}
|
|
525
630
|
inviteOptions.sessionDescriptionHandlerModifiers = [replaceLocalIpModifier];
|
|
631
|
+
|
|
526
632
|
if (audioOnly) {
|
|
527
633
|
inviteOptions.sessionDescriptionHandlerModifiers.push(stripVideo);
|
|
528
634
|
}
|
|
529
635
|
|
|
530
636
|
// Do not await invite here or we'll miss the Establishing state transition
|
|
531
|
-
session.invitePromise = session.invite(inviteOptions)
|
|
637
|
+
session.invitePromise = session.invite(inviteOptions).catch((e: Error) => {
|
|
638
|
+
logger.warn('sdk webrtc creating call, error', e);
|
|
639
|
+
});
|
|
640
|
+
|
|
532
641
|
return session;
|
|
533
642
|
}
|
|
534
643
|
|
|
535
|
-
answer(session: Invitation, enableVideo?: boolean) {
|
|
536
|
-
logger.info('sdk webrtc answer call', {
|
|
644
|
+
answer(session: Invitation, enableVideo?: boolean): Promise<void> {
|
|
645
|
+
logger.info('sdk webrtc answer call', {
|
|
646
|
+
clientId: this.clientId,
|
|
647
|
+
id: session.id,
|
|
648
|
+
enableVideo,
|
|
649
|
+
});
|
|
537
650
|
|
|
538
651
|
if (!session || !session.accept) {
|
|
539
652
|
const error = 'No session to answer, or not an invitation';
|
|
540
653
|
logger.warn(error);
|
|
541
654
|
return Promise.reject(new Error(error));
|
|
542
655
|
}
|
|
656
|
+
|
|
543
657
|
const options = {
|
|
544
658
|
sessionDescriptionHandlerOptions: this.getMediaConfiguration(enableVideo || false),
|
|
545
659
|
};
|
|
546
|
-
|
|
547
|
-
|
|
660
|
+
return this._accept(session, options).then(() => {
|
|
661
|
+
// @ts-ignore
|
|
548
662
|
if (session.isCanceled) {
|
|
549
663
|
const message = 'accepted a canceled session (or was canceled during the accept phase).';
|
|
550
|
-
logger.error(message, {
|
|
664
|
+
logger.error(message, {
|
|
665
|
+
id: session.id,
|
|
666
|
+
});
|
|
551
667
|
this.onCallEnded(session);
|
|
552
|
-
|
|
553
668
|
throw new CanceledCallError(message);
|
|
554
669
|
}
|
|
670
|
+
|
|
555
671
|
logger.info('sdk webrtc answer, accepted.');
|
|
672
|
+
|
|
556
673
|
this._onAccepted(session);
|
|
557
674
|
}).catch(e => {
|
|
558
675
|
logger.error(`answer call error for ${session ? session.id : 'n/a'}`, e);
|
|
559
|
-
|
|
560
676
|
throw e;
|
|
561
677
|
});
|
|
562
678
|
}
|
|
563
679
|
|
|
564
|
-
hangup(session:
|
|
565
|
-
const { state, id } = session;
|
|
566
|
-
logger.info('sdk webrtc hangup call', { id, state });
|
|
680
|
+
async hangup(session: Invitation | Inviter): Promise<OutgoingByeRequest | null> {
|
|
681
|
+
const { state, id }: any = session;
|
|
682
|
+
logger.info('sdk webrtc hangup call', { clientId: this.clientId, id, state });
|
|
567
683
|
|
|
568
684
|
try {
|
|
569
685
|
this._stopSendingStats(session);
|
|
@@ -571,35 +687,33 @@ export default class WebRTCClient extends Emitter {
|
|
|
571
687
|
this._cleanupMedia(session);
|
|
572
688
|
|
|
573
689
|
delete this.sipSessions[this.getSipSessionId(session)];
|
|
574
|
-
|
|
575
690
|
// Check if Invitation or Inviter (Invitation = incoming call)
|
|
576
691
|
const isInviter = session instanceof Inviter;
|
|
577
|
-
const cancel = () => session.cancel();
|
|
578
|
-
const reject = () => session.reject();
|
|
579
|
-
const bye = () => session.bye && session.bye();
|
|
580
692
|
|
|
581
693
|
// @see github.com/onsip/SIP.js/blob/f11dfd584bc9788ccfc94e03034020672b738975/src/platform/web/simple-user/simple-user.ts#L1004
|
|
582
|
-
const actions = {
|
|
583
|
-
[SessionState.Initial]: isInviter ?
|
|
584
|
-
[SessionState.Establishing]: isInviter ?
|
|
585
|
-
[SessionState.Established]:
|
|
694
|
+
const actions: Record<string, any> = {
|
|
695
|
+
[SessionState.Initial]: isInviter ? this._cancel.bind(this, session) : this._reject.bind(this, session),
|
|
696
|
+
[SessionState.Establishing]: isInviter ? this._cancel.bind(this, session) : this._reject.bind(this, session),
|
|
697
|
+
[SessionState.Established]: this._bye.bind(this, session),
|
|
586
698
|
};
|
|
587
699
|
|
|
588
700
|
// Handle different session status
|
|
589
701
|
if (actions[state]) {
|
|
590
|
-
return actions[state]();
|
|
702
|
+
return await actions[state]();
|
|
591
703
|
}
|
|
592
704
|
|
|
593
|
-
return
|
|
594
|
-
} catch (error) {
|
|
705
|
+
return await this._bye(session);
|
|
706
|
+
} catch (error: any) {
|
|
595
707
|
logger.warn('sdk webrtc hangup, error', error);
|
|
596
708
|
}
|
|
597
709
|
|
|
598
|
-
return null;
|
|
710
|
+
return Promise.resolve(null);
|
|
599
711
|
}
|
|
600
712
|
|
|
601
|
-
async getStats(session:
|
|
602
|
-
|
|
713
|
+
async getStats(session: Invitation | Inviter): Promise<RTCStatsReport | null> {
|
|
714
|
+
// @ts-ignore
|
|
715
|
+
const pc: RTCPeerConnection = session.sessionDescriptionHandler.peerConnection;
|
|
716
|
+
|
|
603
717
|
if (!pc) {
|
|
604
718
|
return null;
|
|
605
719
|
}
|
|
@@ -608,101 +722,131 @@ export default class WebRTCClient extends Emitter {
|
|
|
608
722
|
}
|
|
609
723
|
|
|
610
724
|
// Fetch and emit an event at `interval` with session network stats
|
|
611
|
-
startNetworkMonitoring(session:
|
|
725
|
+
startNetworkMonitoring(session: Inviter | Invitation, interval = 1000): void {
|
|
612
726
|
const sessionId = this.getSipSessionId(session);
|
|
613
|
-
logger.info('starting network inspection', {
|
|
614
|
-
|
|
727
|
+
logger.info('starting network inspection', {
|
|
728
|
+
id: sessionId,
|
|
729
|
+
clientId: this.clientId,
|
|
730
|
+
});
|
|
615
731
|
this.sessionNetworkStats[sessionId] = [];
|
|
616
|
-
|
|
617
732
|
this.networkMonitoringInterval[sessionId] = setInterval(() => this._fetchNetworkStats(sessionId), interval);
|
|
618
733
|
}
|
|
619
734
|
|
|
620
|
-
stopNetworkMonitoring(session:
|
|
735
|
+
stopNetworkMonitoring(session: Inviter | Invitation): void {
|
|
621
736
|
const sessionId = this.getSipSessionId(session);
|
|
622
|
-
const exists = sessionId in this.networkMonitoringInterval;
|
|
623
|
-
logger.info('stopping network inspection', {
|
|
737
|
+
const exists = (sessionId in this.networkMonitoringInterval);
|
|
738
|
+
logger.info('stopping network inspection', {
|
|
739
|
+
clientId: this.clientId,
|
|
740
|
+
id: sessionId,
|
|
741
|
+
exists,
|
|
742
|
+
});
|
|
624
743
|
|
|
625
744
|
if (exists) {
|
|
626
|
-
clearInterval(this.networkMonitoringInterval[sessionId]);
|
|
745
|
+
clearInterval(this.networkMonitoringInterval[sessionId] as string);
|
|
627
746
|
delete this.networkMonitoringInterval[sessionId];
|
|
628
747
|
delete this.sessionNetworkStats[sessionId];
|
|
629
748
|
}
|
|
630
749
|
}
|
|
631
750
|
|
|
632
|
-
reject(session: Inviter) {
|
|
633
|
-
logger.info('sdk webrtc reject call', {
|
|
751
|
+
async reject(session: Invitation | Inviter): Promise<void> {
|
|
752
|
+
logger.info('sdk webrtc reject call', {
|
|
753
|
+
clientId: this.clientId,
|
|
754
|
+
id: session.id,
|
|
755
|
+
});
|
|
634
756
|
|
|
635
757
|
try {
|
|
636
|
-
|
|
637
|
-
|
|
758
|
+
if (session instanceof Invitation) {
|
|
759
|
+
return this._reject(session);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if (session instanceof Inviter) {
|
|
763
|
+
return this._cancel(session);
|
|
764
|
+
}
|
|
765
|
+
} catch (e: any) {
|
|
638
766
|
logger.warn('Error when rejecting call', e.message, e.stack);
|
|
639
767
|
}
|
|
640
768
|
}
|
|
641
769
|
|
|
642
|
-
async close(force
|
|
643
|
-
logger.info('sdk webrtc closing client', {
|
|
770
|
+
async close(force = false): Promise<void> {
|
|
771
|
+
logger.info('sdk webrtc closing client', {
|
|
772
|
+
clientId: this.clientId,
|
|
773
|
+
userAgent: !!this.userAgent,
|
|
774
|
+
force,
|
|
775
|
+
});
|
|
644
776
|
this.forceClosed = force;
|
|
777
|
+
|
|
645
778
|
this._cleanupMedia();
|
|
646
|
-
this.connectionPromise = null;
|
|
647
779
|
|
|
648
|
-
|
|
780
|
+
this.connectionPromise = null;
|
|
781
|
+
(Object.values(this.audioElements) as any).forEach((audioElement: HTMLAudioElement) => {
|
|
649
782
|
// eslint-disable-next-line
|
|
650
783
|
audioElement.srcObject = null;
|
|
651
784
|
audioElement.pause();
|
|
652
785
|
});
|
|
653
|
-
|
|
654
786
|
this.audioElements = {};
|
|
787
|
+
|
|
655
788
|
if (!this.userAgent) {
|
|
656
|
-
return
|
|
789
|
+
return;
|
|
657
790
|
}
|
|
658
791
|
|
|
659
792
|
this.stopHeartbeat();
|
|
660
|
-
this.userAgent
|
|
793
|
+
if (this.userAgent) {
|
|
794
|
+
this.userAgent.delegate = undefined;
|
|
795
|
+
}
|
|
796
|
+
// @ts-ignore: this is odd, may want to validate
|
|
661
797
|
this.userAgent.stateChange.removeAllListeners();
|
|
662
|
-
|
|
663
798
|
await this._disconnectTransport(force);
|
|
664
799
|
|
|
665
800
|
this._cleanupRegister();
|
|
666
801
|
|
|
667
802
|
try {
|
|
803
|
+
// Prevent `Connect aborted.` error when disconnecting
|
|
804
|
+
// @ts-ignore
|
|
805
|
+
this.userAgent.transport.connectReject = () => {};
|
|
668
806
|
// Don't wait here, It can take ~30s to stop ...
|
|
669
807
|
this.userAgent.stop().catch(console.error);
|
|
670
|
-
} catch (_) {
|
|
671
|
-
// Avoid to raise exception when trying to close with hanged-up sessions remaining
|
|
808
|
+
} catch (_) { // Avoid to raise exception when trying to close with hanged-up sessions remaining
|
|
672
809
|
// eg: "INVITE not rejectable in state Completed"
|
|
673
810
|
}
|
|
811
|
+
|
|
674
812
|
this.userAgent = null;
|
|
675
|
-
logger.info('sdk webrtc client closed');
|
|
813
|
+
logger.info('sdk webrtc client closed', { clientId: this.clientId });
|
|
676
814
|
}
|
|
677
815
|
|
|
678
|
-
getNumber(session: Inviter):
|
|
816
|
+
getNumber(session: Inviter): string | null | undefined {
|
|
679
817
|
if (!session) {
|
|
680
818
|
return null;
|
|
681
819
|
}
|
|
682
820
|
|
|
683
|
-
//
|
|
821
|
+
// @ts-ignore
|
|
684
822
|
return session.remoteIdentity.uri._normal.user;
|
|
685
823
|
}
|
|
686
824
|
|
|
687
|
-
mute(session: Inviter) {
|
|
688
|
-
logger.info('sdk webrtc mute', {
|
|
825
|
+
mute(session: Inviter | Invitation): void {
|
|
826
|
+
logger.info('sdk webrtc mute', {
|
|
827
|
+
id: session.id,
|
|
828
|
+
});
|
|
689
829
|
|
|
690
830
|
this._toggleAudio(session, true);
|
|
691
831
|
}
|
|
692
832
|
|
|
693
|
-
unmute(session: Inviter) {
|
|
694
|
-
logger.info('sdk webrtc unmute', {
|
|
833
|
+
unmute(session: Inviter | Invitation): void {
|
|
834
|
+
logger.info('sdk webrtc unmute', {
|
|
835
|
+
id: session.id,
|
|
836
|
+
});
|
|
695
837
|
|
|
696
838
|
this._toggleAudio(session, false);
|
|
697
839
|
}
|
|
698
840
|
|
|
699
|
-
isAudioMuted(session: Inviter): boolean {
|
|
841
|
+
isAudioMuted(session: Inviter | Invitation): boolean {
|
|
700
842
|
if (!session || !session.sessionDescriptionHandler) {
|
|
701
843
|
return false;
|
|
702
844
|
}
|
|
703
845
|
|
|
704
846
|
let muted = true;
|
|
847
|
+
// @ts-ignore
|
|
705
848
|
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
849
|
+
|
|
706
850
|
if (!pc) {
|
|
707
851
|
return false;
|
|
708
852
|
}
|
|
@@ -711,7 +855,8 @@ export default class WebRTCClient extends Emitter {
|
|
|
711
855
|
if (!pc.getSenders().length) {
|
|
712
856
|
return false;
|
|
713
857
|
}
|
|
714
|
-
|
|
858
|
+
|
|
859
|
+
pc.getSenders().forEach((sender: any) => {
|
|
715
860
|
if (sender && sender.track && sender.track.kind === 'audio') {
|
|
716
861
|
muted = muted && !sender.track.enabled;
|
|
717
862
|
}
|
|
@@ -720,7 +865,8 @@ export default class WebRTCClient extends Emitter {
|
|
|
720
865
|
if (!pc.getLocalStreams().length) {
|
|
721
866
|
return false;
|
|
722
867
|
}
|
|
723
|
-
|
|
868
|
+
|
|
869
|
+
pc.getLocalStreams().forEach((stream: MediaStream) => {
|
|
724
870
|
stream.getAudioTracks().forEach(track => {
|
|
725
871
|
muted = muted && !track.enabled;
|
|
726
872
|
});
|
|
@@ -730,25 +876,29 @@ export default class WebRTCClient extends Emitter {
|
|
|
730
876
|
return muted;
|
|
731
877
|
}
|
|
732
878
|
|
|
733
|
-
toggleCameraOn(session: Inviter) {
|
|
734
|
-
logger.info('sdk webrtc toggle camera on', {
|
|
879
|
+
toggleCameraOn(session: Inviter | Invitation): void {
|
|
880
|
+
logger.info('sdk webrtc toggle camera on', {
|
|
881
|
+
id: session.id,
|
|
882
|
+
});
|
|
735
883
|
|
|
736
884
|
this._toggleVideo(session, false);
|
|
737
885
|
}
|
|
738
886
|
|
|
739
|
-
toggleCameraOff(session: Inviter) {
|
|
740
|
-
logger.info('sdk webrtc toggle camera off', {
|
|
887
|
+
toggleCameraOff(session: Inviter | Invitation): void {
|
|
888
|
+
logger.info('sdk webrtc toggle camera off', {
|
|
889
|
+
id: session.id,
|
|
890
|
+
});
|
|
741
891
|
|
|
742
892
|
this._toggleVideo(session, true);
|
|
743
893
|
}
|
|
744
894
|
|
|
745
|
-
hold(session: Inviter, isConference
|
|
895
|
+
hold(session: Inviter | Invitation, isConference = false, hadVideo = false): Promise<OutgoingInviteRequest | void> {
|
|
746
896
|
const sessionId = this.getSipSessionId(session);
|
|
747
897
|
const hasVideo = hadVideo || this.hasLocalVideo(sessionId);
|
|
748
|
-
|
|
749
898
|
logger.info('sdk webrtc hold', {
|
|
750
899
|
sessionId,
|
|
751
900
|
keys: Object.keys(this.heldSessions),
|
|
901
|
+
// @ts-ignore
|
|
752
902
|
pendingReinvite: !!session.pendingReinvite,
|
|
753
903
|
isConference,
|
|
754
904
|
hasVideo,
|
|
@@ -757,9 +907,12 @@ export default class WebRTCClient extends Emitter {
|
|
|
757
907
|
if (sessionId in this.heldSessions) {
|
|
758
908
|
return Promise.resolve();
|
|
759
909
|
}
|
|
910
|
+
|
|
911
|
+
// @ts-ignore
|
|
760
912
|
if (session.pendingReinvite) {
|
|
761
913
|
return Promise.resolve();
|
|
762
914
|
}
|
|
915
|
+
|
|
763
916
|
this.heldSessions[sessionId] = {
|
|
764
917
|
hasVideo,
|
|
765
918
|
isConference,
|
|
@@ -770,14 +923,16 @@ export default class WebRTCClient extends Emitter {
|
|
|
770
923
|
}
|
|
771
924
|
|
|
772
925
|
session.sessionDescriptionHandlerOptionsReInvite = {
|
|
926
|
+
// @ts-ignore
|
|
773
927
|
hold: true,
|
|
774
928
|
conference: isConference,
|
|
775
929
|
};
|
|
776
|
-
|
|
777
930
|
const options = this.getMediaConfiguration(false, isConference);
|
|
931
|
+
|
|
778
932
|
if (!this._isWeb()) {
|
|
779
933
|
options.sessionDescriptionHandlerModifiers = [holdModifier];
|
|
780
934
|
}
|
|
935
|
+
|
|
781
936
|
options.sessionDescriptionHandlerOptions = {
|
|
782
937
|
constraints: options.constraints,
|
|
783
938
|
hold: true,
|
|
@@ -786,25 +941,29 @@ export default class WebRTCClient extends Emitter {
|
|
|
786
941
|
|
|
787
942
|
// Avoid sdh to create a new stream
|
|
788
943
|
if (session.sessionDescriptionHandler) {
|
|
944
|
+
// @ts-ignore
|
|
789
945
|
session.sessionDescriptionHandler.localMediaStreamConstraints = options.constraints;
|
|
790
946
|
}
|
|
791
947
|
|
|
792
948
|
// Send re-INVITE
|
|
793
|
-
return session.invite(options)
|
|
949
|
+
return session.invite(options).catch((e: Error) => {
|
|
950
|
+
logger.warn('sdk webrtc re-invite during hold, error', e);
|
|
951
|
+
});
|
|
794
952
|
}
|
|
795
953
|
|
|
796
|
-
unhold(session: Inviter, isConference
|
|
954
|
+
unhold(session: Inviter | Invitation, isConference = false): Promise<OutgoingInviteRequest | void> {
|
|
797
955
|
const sessionId = this.getSipSessionId(session);
|
|
798
956
|
const hasVideo = sessionId in this.heldSessions && this.heldSessions[sessionId].hasVideo;
|
|
799
|
-
|
|
800
957
|
logger.info('sdk webrtc unhold', {
|
|
801
958
|
sessionId,
|
|
802
959
|
keys: Object.keys(this.heldSessions),
|
|
960
|
+
// @ts-ignore
|
|
803
961
|
pendingReinvite: !!session.pendingReinvite,
|
|
804
962
|
isConference,
|
|
805
963
|
hasVideo,
|
|
806
964
|
});
|
|
807
965
|
|
|
966
|
+
// @ts-ignore
|
|
808
967
|
if (session.pendingReinvite) {
|
|
809
968
|
return Promise.resolve();
|
|
810
969
|
}
|
|
@@ -815,111 +974,119 @@ export default class WebRTCClient extends Emitter {
|
|
|
815
974
|
|
|
816
975
|
delete this.heldSessions[this.getSipSessionId(session)];
|
|
817
976
|
session.sessionDescriptionHandlerOptionsReInvite = {
|
|
977
|
+
// @ts-ignore
|
|
818
978
|
hold: false,
|
|
819
979
|
conference: isConference,
|
|
820
980
|
};
|
|
821
|
-
|
|
822
981
|
const options = this.getMediaConfiguration(false, isConference);
|
|
982
|
+
|
|
823
983
|
if (!this._isWeb()) {
|
|
824
984
|
// We should sent an empty `sessionDescriptionHandlerModifiers` or sip.js will take the last sent modifiers
|
|
825
985
|
// (eg: holdModifier)
|
|
826
986
|
options.sessionDescriptionHandlerModifiers = [];
|
|
827
987
|
}
|
|
988
|
+
|
|
828
989
|
options.sessionDescriptionHandlerOptions = {
|
|
829
990
|
constraints: options.constraints,
|
|
830
991
|
hold: false,
|
|
831
992
|
conference: isConference,
|
|
832
993
|
};
|
|
833
|
-
|
|
834
994
|
// Send re-INVITE
|
|
835
|
-
return session.invite(options)
|
|
995
|
+
return session.invite(options).catch((e: Error) => {
|
|
996
|
+
logger.warn('sdk webrtc re-invite during resume, error', e);
|
|
997
|
+
});
|
|
836
998
|
}
|
|
837
999
|
|
|
838
1000
|
// Returns true if a re-INVITE is required
|
|
839
|
-
async upgradeToVideo(session:
|
|
1001
|
+
async upgradeToVideo(session: Inviter | Invitation, constraints: Record<string, any>, isConference: boolean): Promise<MediaStream | undefined> {
|
|
1002
|
+
// @ts-ignore
|
|
840
1003
|
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
841
|
-
|
|
842
1004
|
// Check if a video sender already exists
|
|
843
1005
|
let videoSender;
|
|
1006
|
+
|
|
844
1007
|
if (isConference) {
|
|
845
1008
|
// We search for the last transceiver without `video-` in the mid (video- means remote transceiver)
|
|
846
1009
|
const transceivers = pc.getTransceivers();
|
|
847
|
-
const transceiverIdx = lastIndexOf(transceivers, transceiver =>
|
|
848
|
-
transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
849
|
-
|
|
1010
|
+
const transceiverIdx = lastIndexOf(transceivers, transceiver => transceiver.sender.track === null && transceiver.mid && transceiver.mid.indexOf('video') === -1);
|
|
850
1011
|
videoSender = transceiverIdx !== -1 ? transceivers[transceiverIdx].sender : null;
|
|
851
1012
|
} else {
|
|
852
|
-
videoSender = pc && pc.getSenders && pc.getSenders().find(sender => sender.track === null);
|
|
1013
|
+
videoSender = pc && pc.getSenders && pc.getSenders().find((sender: any) => sender.track === null);
|
|
853
1014
|
}
|
|
854
1015
|
|
|
855
1016
|
if (!videoSender) {
|
|
856
1017
|
// When no video sender found, it means that we're in the first video upgrade in 1:1
|
|
857
|
-
return
|
|
1018
|
+
return;
|
|
858
1019
|
}
|
|
859
1020
|
|
|
860
1021
|
// Reuse bidirectional video stream
|
|
861
1022
|
const newStream = await this.getStreamFromConstraints(constraints);
|
|
1023
|
+
|
|
862
1024
|
if (!newStream) {
|
|
863
1025
|
console.warn(`Can't create media stream with: ${JSON.stringify(constraints || {})}`);
|
|
864
|
-
return
|
|
1026
|
+
return;
|
|
865
1027
|
}
|
|
866
1028
|
|
|
867
1029
|
// Add previous local audio track
|
|
868
1030
|
if (constraints && !constraints.audio) {
|
|
869
|
-
|
|
1031
|
+
// @ts-ignore
|
|
1032
|
+
const localVideoStream: MediaStream = session.sessionDescriptionHandler.localMediaStream;
|
|
870
1033
|
const localAudioTrack = localVideoStream.getTracks().find(track => track.kind === 'audio');
|
|
1034
|
+
|
|
871
1035
|
if (localAudioTrack) {
|
|
872
1036
|
newStream.addTrack(localAudioTrack);
|
|
873
1037
|
}
|
|
874
1038
|
}
|
|
875
1039
|
|
|
876
1040
|
const videoTrack = newStream.getVideoTracks()[0];
|
|
1041
|
+
|
|
877
1042
|
if (videoTrack) {
|
|
878
1043
|
videoSender.replaceTrack(videoTrack);
|
|
879
1044
|
}
|
|
880
1045
|
|
|
881
1046
|
this.setLocalMediaStream(this.getSipSessionId(session), newStream);
|
|
882
|
-
|
|
883
1047
|
return newStream;
|
|
884
1048
|
}
|
|
885
1049
|
|
|
886
|
-
downgradeToAudio(session:
|
|
1050
|
+
downgradeToAudio(session: Invitation | Inviter): void {
|
|
887
1051
|
// Release local video stream when downgrading to audio
|
|
1052
|
+
// @ts-ignore
|
|
888
1053
|
const localStream = session.sessionDescriptionHandler.localMediaStream;
|
|
1054
|
+
// @ts-ignore
|
|
889
1055
|
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
890
1056
|
const videoTracks = localStream.getVideoTracks();
|
|
891
1057
|
|
|
892
1058
|
// Remove video senders
|
|
893
1059
|
if (pc.getSenders) {
|
|
894
|
-
pc.getSenders().filter(sender => sender.track && sender.track.kind === 'video').forEach(videoSender => {
|
|
1060
|
+
pc.getSenders().filter((sender: any) => sender.track && sender.track.kind === 'video').forEach((videoSender: any) => {
|
|
895
1061
|
videoSender.replaceTrack(null);
|
|
896
1062
|
});
|
|
897
1063
|
}
|
|
898
1064
|
|
|
899
|
-
videoTracks.forEach(videoTrack => {
|
|
1065
|
+
videoTracks.forEach((videoTrack: MediaStreamTrack) => {
|
|
900
1066
|
videoTrack.enabled = false;
|
|
901
1067
|
videoTrack.stop();
|
|
902
1068
|
localStream.removeTrack(videoTrack);
|
|
903
1069
|
});
|
|
904
1070
|
}
|
|
905
1071
|
|
|
906
|
-
async getStreamFromConstraints(constraints:
|
|
1072
|
+
async getStreamFromConstraints(constraints: Record<string, any>, conference = false): Promise<MediaStream | null | undefined> {
|
|
907
1073
|
const video = constraints && constraints.video;
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
1074
|
+
const {
|
|
1075
|
+
constraints: newConstraints,
|
|
1076
|
+
} = this.getMediaConfiguration(video, conference, constraints);
|
|
911
1077
|
let newStream;
|
|
1078
|
+
|
|
912
1079
|
try {
|
|
913
1080
|
newStream = await wazoMediaStreamFactory(newConstraints);
|
|
914
|
-
} catch (e) {
|
|
915
|
-
// Nothing to do when the user cancel the screensharing prompt
|
|
1081
|
+
} catch (e: any) { // Nothing to do when the user cancel the screensharing prompt
|
|
916
1082
|
}
|
|
1083
|
+
|
|
917
1084
|
if (!newStream) {
|
|
918
1085
|
return null;
|
|
919
1086
|
}
|
|
920
|
-
// $FlowFixMe
|
|
921
|
-
newStream.local = true;
|
|
922
1087
|
|
|
1088
|
+
// @ts-ignore
|
|
1089
|
+
newStream.local = true;
|
|
923
1090
|
return newStream;
|
|
924
1091
|
}
|
|
925
1092
|
|
|
@@ -927,26 +1094,27 @@ export default class WebRTCClient extends Emitter {
|
|
|
927
1094
|
return this.heldSessions[sessionId];
|
|
928
1095
|
}
|
|
929
1096
|
|
|
930
|
-
isCallHeld(session: Inviter) {
|
|
1097
|
+
isCallHeld(session: Inviter | Invitation): boolean {
|
|
931
1098
|
return this.getSipSessionId(session) in this.heldSessions;
|
|
932
1099
|
}
|
|
933
1100
|
|
|
934
|
-
isVideoRemotelyHeld(sessionId: string) {
|
|
1101
|
+
isVideoRemotelyHeld(sessionId: string): boolean {
|
|
935
1102
|
const pc = this.getPeerConnection(sessionId);
|
|
936
1103
|
const sdp = pc && pc.remoteDescription ? pc.remoteDescription.sdp : null;
|
|
1104
|
+
|
|
937
1105
|
if (!sdp) {
|
|
938
1106
|
return false;
|
|
939
1107
|
}
|
|
940
1108
|
|
|
941
1109
|
const videoDirection = getVideoDirection(sdp);
|
|
942
|
-
|
|
943
1110
|
return videoDirection === 'sendonly';
|
|
944
1111
|
}
|
|
945
1112
|
|
|
946
|
-
sendDTMF(session: Inviter, tone: string) {
|
|
1113
|
+
sendDTMF(session: Inviter | Invitation, tone: string): boolean {
|
|
947
1114
|
if (!session.sessionDescriptionHandler) {
|
|
948
|
-
return;
|
|
1115
|
+
return false;
|
|
949
1116
|
}
|
|
1117
|
+
|
|
950
1118
|
logger.info('Sending DTMF', {
|
|
951
1119
|
id: this.getSipSessionId(session),
|
|
952
1120
|
tone,
|
|
@@ -954,20 +1122,22 @@ export default class WebRTCClient extends Emitter {
|
|
|
954
1122
|
return session.sessionDescriptionHandler.sendDtmf(tone);
|
|
955
1123
|
}
|
|
956
1124
|
|
|
957
|
-
message(destination: string, message: string) {
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
|
|
1125
|
+
message(destination: string, message: string): void {
|
|
1126
|
+
const uri = this._makeURI(destination);
|
|
1127
|
+
if (!this.userAgent || !uri) {
|
|
1128
|
+
logger.warn('Null value on message', { uri, userAgent: this.userAgent });
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
const messager = new Messager(this.userAgent, uri, message);
|
|
1132
|
+
messager.message();
|
|
961
1133
|
}
|
|
962
1134
|
|
|
963
|
-
transfer(session: Inviter, target: string) {
|
|
1135
|
+
transfer(session: Inviter | Invitation, target: string): void {
|
|
964
1136
|
this.hold(session);
|
|
965
|
-
|
|
966
1137
|
logger.info('Transfering a session', {
|
|
967
1138
|
id: this.getSipSessionId(session),
|
|
968
1139
|
target,
|
|
969
1140
|
});
|
|
970
|
-
|
|
971
1141
|
const options = {
|
|
972
1142
|
requestDelegate: {
|
|
973
1143
|
onAccept: () => {
|
|
@@ -975,23 +1145,29 @@ export default class WebRTCClient extends Emitter {
|
|
|
975
1145
|
},
|
|
976
1146
|
},
|
|
977
1147
|
};
|
|
978
|
-
|
|
979
1148
|
setTimeout(() => {
|
|
980
|
-
|
|
1149
|
+
const uri = this._makeURI(target);
|
|
1150
|
+
if (!uri) {
|
|
1151
|
+
logger.warn('transfer timeout: null URI');
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
session.refer(uri, options);
|
|
981
1155
|
}, 50);
|
|
982
1156
|
}
|
|
983
1157
|
|
|
984
1158
|
// check https://sipjs.com/api/0.12.0/refer/referClientContext/
|
|
985
|
-
atxfer(session: Inviter) {
|
|
1159
|
+
atxfer(session: Inviter | Invitation): Record<string, any> {
|
|
986
1160
|
this.hold(session);
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
const result:
|
|
1161
|
+
logger.info('webrtc transfer started', {
|
|
1162
|
+
id: this.getSipSessionId(session),
|
|
1163
|
+
});
|
|
1164
|
+
const result: Record<string, any> = {
|
|
991
1165
|
newSession: null,
|
|
992
1166
|
init: async (target: string) => {
|
|
993
|
-
logger.info('webrtc transfer initialized', {
|
|
994
|
-
|
|
1167
|
+
logger.info('webrtc transfer initialized', {
|
|
1168
|
+
id: this.getSipSessionId(session),
|
|
1169
|
+
target,
|
|
1170
|
+
});
|
|
995
1171
|
result.newSession = await this.call(target);
|
|
996
1172
|
},
|
|
997
1173
|
complete: () => {
|
|
@@ -999,7 +1175,6 @@ export default class WebRTCClient extends Emitter {
|
|
|
999
1175
|
id: this.getSipSessionId(session),
|
|
1000
1176
|
referId: this.getSipSessionId(result.newSession),
|
|
1001
1177
|
});
|
|
1002
|
-
|
|
1003
1178
|
session.refer(result.newSession);
|
|
1004
1179
|
},
|
|
1005
1180
|
cancel: () => {
|
|
@@ -1007,16 +1182,19 @@ export default class WebRTCClient extends Emitter {
|
|
|
1007
1182
|
this.unhold(session);
|
|
1008
1183
|
},
|
|
1009
1184
|
};
|
|
1010
|
-
|
|
1011
1185
|
return result;
|
|
1012
1186
|
}
|
|
1013
1187
|
|
|
1014
|
-
|
|
1188
|
+
// eslint-disable-next-line @typescript-eslint/default-param-last
|
|
1189
|
+
sendMessage(sipSession: Inviter | Invitation | null = null, body: string, contentType = 'text/plain'): void {
|
|
1015
1190
|
if (!sipSession) {
|
|
1016
1191
|
return;
|
|
1017
1192
|
}
|
|
1018
1193
|
|
|
1019
|
-
logger.info('send WebRTC message', {
|
|
1194
|
+
logger.info('send WebRTC message', {
|
|
1195
|
+
sipId: sipSession.id,
|
|
1196
|
+
contentType,
|
|
1197
|
+
});
|
|
1020
1198
|
|
|
1021
1199
|
try {
|
|
1022
1200
|
sipSession.message({
|
|
@@ -1024,32 +1202,44 @@ export default class WebRTCClient extends Emitter {
|
|
|
1024
1202
|
body: {
|
|
1025
1203
|
content: body,
|
|
1026
1204
|
contentType,
|
|
1205
|
+
// @HEADSUP: contentDisposition is a required string, setting it to '' arbitrarily
|
|
1206
|
+
contentDisposition: '',
|
|
1027
1207
|
},
|
|
1028
1208
|
},
|
|
1029
1209
|
});
|
|
1030
|
-
} catch (e) {
|
|
1210
|
+
} catch (e: any) {
|
|
1031
1211
|
console.warn(e);
|
|
1032
1212
|
}
|
|
1033
1213
|
}
|
|
1034
1214
|
|
|
1035
|
-
pingServer() {
|
|
1215
|
+
pingServer(): OutgoingRequest | void {
|
|
1036
1216
|
if (!this.isConnected()) {
|
|
1037
1217
|
return;
|
|
1038
1218
|
}
|
|
1039
1219
|
|
|
1040
|
-
const core = this.userAgent
|
|
1220
|
+
const core = this.userAgent?.userAgentCore;
|
|
1221
|
+
|
|
1041
1222
|
const fromURI = this._makeURI(this.config.authorizationUser || '');
|
|
1223
|
+
|
|
1042
1224
|
const toURI = new URI('sip', '', this.config.host);
|
|
1043
|
-
|
|
1225
|
+
if (fromURI) {
|
|
1226
|
+
const message = core?.makeOutgoingRequestMessage('OPTIONS', toURI, fromURI, toURI, {});
|
|
1044
1227
|
|
|
1045
|
-
|
|
1228
|
+
if (message) {
|
|
1229
|
+
return core?.request(message);
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
logger.warn('pingServer: null message');
|
|
1233
|
+
}
|
|
1234
|
+
logger.warn('pingServer: null fromURI');
|
|
1046
1235
|
}
|
|
1047
1236
|
|
|
1048
|
-
getState() {
|
|
1237
|
+
getState(): UserAgentState {
|
|
1238
|
+
// @ts-ignore
|
|
1049
1239
|
return this.userAgent ? states[this.userAgent.state] : UserAgentState.Stopped;
|
|
1050
1240
|
}
|
|
1051
1241
|
|
|
1052
|
-
getContactIdentifier() {
|
|
1242
|
+
getContactIdentifier(): string | null {
|
|
1053
1243
|
return this.userAgent ? `${this.userAgent.configuration.contactName}/${this.userAgent.contact.uri}` : null;
|
|
1054
1244
|
}
|
|
1055
1245
|
|
|
@@ -1057,9 +1247,10 @@ export default class WebRTCClient extends Emitter {
|
|
|
1057
1247
|
return this._isWeb() && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
|
1058
1248
|
}
|
|
1059
1249
|
|
|
1060
|
-
changeAudioOutputVolume(volume: number) {
|
|
1061
|
-
logger.info('Changing audio output volume', {
|
|
1062
|
-
|
|
1250
|
+
changeAudioOutputVolume(volume: number): void {
|
|
1251
|
+
logger.info('Changing audio output volume', {
|
|
1252
|
+
volume,
|
|
1253
|
+
});
|
|
1063
1254
|
Object.values(this.audioElements).forEach(audioElement => {
|
|
1064
1255
|
if (audioElement instanceof HTMLAudioElement) {
|
|
1065
1256
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -1070,25 +1261,30 @@ export default class WebRTCClient extends Emitter {
|
|
|
1070
1261
|
}
|
|
1071
1262
|
|
|
1072
1263
|
changeAudioOutputDevice(id: string) {
|
|
1073
|
-
logger.info('Changing audio output device', {
|
|
1264
|
+
logger.info('Changing audio output device', {
|
|
1265
|
+
id,
|
|
1266
|
+
});
|
|
1074
1267
|
this.audioOutputDeviceId = id;
|
|
1075
|
-
|
|
1076
1268
|
Object.values(this.audioElements).forEach(audioElement => {
|
|
1077
1269
|
// `setSinkId` method is not included in any flow type definitions for HTMLAudioElements but is a valid method
|
|
1078
1270
|
// audioElement is an array of HTMLAudioElements, and HTMLAudioElement inherits the method from HTMLMediaElement
|
|
1079
1271
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement
|
|
1080
1272
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId
|
|
1081
|
-
|
|
1082
|
-
// $FlowFixMe
|
|
1273
|
+
// @ts-ignore
|
|
1083
1274
|
if (audioElement.setSinkId) {
|
|
1275
|
+
// @ts-ignore
|
|
1084
1276
|
audioElement.setSinkId(id);
|
|
1085
1277
|
}
|
|
1086
1278
|
});
|
|
1087
1279
|
}
|
|
1088
1280
|
|
|
1089
|
-
async changeAudioInputDevice(id: string, session:
|
|
1281
|
+
async changeAudioInputDevice(id: string, session: Inviter | Invitation | null | undefined, force: boolean | null | undefined): Promise<MediaStream | null> {
|
|
1090
1282
|
const currentId = this.getAudioDeviceId();
|
|
1091
|
-
logger.info('setting audio input device', {
|
|
1283
|
+
logger.info('setting audio input device', {
|
|
1284
|
+
id,
|
|
1285
|
+
currentId,
|
|
1286
|
+
session: !!session,
|
|
1287
|
+
});
|
|
1092
1288
|
|
|
1093
1289
|
if (!force && id === currentId) {
|
|
1094
1290
|
return null;
|
|
@@ -1097,14 +1293,18 @@ export default class WebRTCClient extends Emitter {
|
|
|
1097
1293
|
// in order to handle an audio track change for default devices
|
|
1098
1294
|
// we need the actual id of the device (not 'default')
|
|
1099
1295
|
let deviceId = id;
|
|
1296
|
+
|
|
1100
1297
|
if (id === 'default' && navigator.mediaDevices) {
|
|
1101
1298
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
1102
1299
|
const defaultDevice = devices.find(device => device.deviceId === 'default');
|
|
1300
|
+
|
|
1103
1301
|
if (defaultDevice) {
|
|
1104
1302
|
const deviceLabel = defaultDevice.label.replace('Default - ', '');
|
|
1105
1303
|
const targetDevice = devices.find(device => device.label === deviceLabel);
|
|
1304
|
+
|
|
1106
1305
|
if (targetDevice) {
|
|
1107
1306
|
deviceId = targetDevice.deviceId;
|
|
1307
|
+
|
|
1108
1308
|
if (!force && deviceId === currentId) {
|
|
1109
1309
|
return null;
|
|
1110
1310
|
}
|
|
@@ -1123,26 +1323,34 @@ export default class WebRTCClient extends Emitter {
|
|
|
1123
1323
|
|
|
1124
1324
|
if (session && navigator.mediaDevices) {
|
|
1125
1325
|
const sdh = session.sessionDescriptionHandler;
|
|
1326
|
+
// @ts-ignore
|
|
1126
1327
|
const pc = sdh.peerConnection;
|
|
1127
|
-
|
|
1128
|
-
|
|
1328
|
+
const constraints = {
|
|
1329
|
+
audio: {
|
|
1330
|
+
deviceId: {
|
|
1331
|
+
exact: deviceId,
|
|
1332
|
+
},
|
|
1333
|
+
},
|
|
1334
|
+
};
|
|
1129
1335
|
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
1130
1336
|
const audioTrack = stream.getAudioTracks()[0];
|
|
1131
|
-
const sender = pc && pc.getSenders
|
|
1132
|
-
&& pc.getSenders().find(s => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
1337
|
+
const sender = pc && pc.getSenders && pc.getSenders().find((s: any) => audioTrack && s && s.track && s.track.kind === audioTrack.kind);
|
|
1133
1338
|
|
|
1134
1339
|
if (sender) {
|
|
1135
1340
|
if (sender.track) {
|
|
1136
1341
|
audioTrack.enabled = sender.track.enabled;
|
|
1137
1342
|
}
|
|
1343
|
+
|
|
1138
1344
|
sender.replaceTrack(audioTrack);
|
|
1139
1345
|
}
|
|
1140
1346
|
|
|
1141
1347
|
return stream;
|
|
1142
1348
|
}
|
|
1349
|
+
|
|
1350
|
+
return null;
|
|
1143
1351
|
}
|
|
1144
1352
|
|
|
1145
|
-
changeVideoInputDevice(id:
|
|
1353
|
+
async changeVideoInputDevice(id: string, session?: Inviter | Invitation): Promise<MediaStream | void> {
|
|
1146
1354
|
this.setVideoInputDevice(id);
|
|
1147
1355
|
|
|
1148
1356
|
if (session) {
|
|
@@ -1150,9 +1358,12 @@ export default class WebRTCClient extends Emitter {
|
|
|
1150
1358
|
}
|
|
1151
1359
|
}
|
|
1152
1360
|
|
|
1153
|
-
setVideoInputDevice(id:
|
|
1361
|
+
setVideoInputDevice(id: string) {
|
|
1154
1362
|
const currentId = this.getVideoDeviceId();
|
|
1155
|
-
logger.info('setting video input device', {
|
|
1363
|
+
logger.info('setting video input device', {
|
|
1364
|
+
id,
|
|
1365
|
+
currentId,
|
|
1366
|
+
});
|
|
1156
1367
|
|
|
1157
1368
|
if (id === currentId) {
|
|
1158
1369
|
return null;
|
|
@@ -1160,24 +1371,27 @@ export default class WebRTCClient extends Emitter {
|
|
|
1160
1371
|
|
|
1161
1372
|
// let's make sure we don't lose other video constraints settings -- width, height, frameRate...
|
|
1162
1373
|
const videoObject = typeof this.video === 'object' ? this.video : {};
|
|
1163
|
-
this.video = {
|
|
1164
|
-
...videoObject,
|
|
1374
|
+
this.video = { ...videoObject,
|
|
1165
1375
|
deviceId: {
|
|
1166
1376
|
exact: id,
|
|
1167
1377
|
},
|
|
1168
1378
|
};
|
|
1169
1379
|
}
|
|
1170
1380
|
|
|
1171
|
-
changeSessionVideoInputDevice(id:
|
|
1381
|
+
changeSessionVideoInputDevice(id: string | null | undefined, session: Inviter | Invitation): Promise<MediaStream | void> {
|
|
1172
1382
|
if (!this.sessionWantsToDoVideo(session)) {
|
|
1173
|
-
return;
|
|
1383
|
+
return Promise.resolve();
|
|
1174
1384
|
}
|
|
1385
|
+
|
|
1175
1386
|
const sdh = session.sessionDescriptionHandler;
|
|
1387
|
+
// @ts-ignore
|
|
1176
1388
|
const pc = sdh.peerConnection;
|
|
1177
1389
|
const sessionId = this.getSipSessionId(session);
|
|
1178
1390
|
const localStream = this.getLocalStream(sessionId);
|
|
1179
|
-
|
|
1180
|
-
|
|
1391
|
+
logger.info('changing video input device', {
|
|
1392
|
+
id,
|
|
1393
|
+
sessionId,
|
|
1394
|
+
});
|
|
1181
1395
|
|
|
1182
1396
|
// Release old video stream
|
|
1183
1397
|
if (localStream) {
|
|
@@ -1187,16 +1401,19 @@ export default class WebRTCClient extends Emitter {
|
|
|
1187
1401
|
}
|
|
1188
1402
|
|
|
1189
1403
|
const constraints = {
|
|
1190
|
-
video: id ? {
|
|
1404
|
+
video: id ? {
|
|
1405
|
+
deviceId: {
|
|
1406
|
+
exact: id,
|
|
1407
|
+
},
|
|
1408
|
+
} : true,
|
|
1191
1409
|
};
|
|
1192
|
-
// $FlowFixMe
|
|
1193
1410
|
return navigator.mediaDevices.getUserMedia(constraints).then(async stream => {
|
|
1194
1411
|
const videoTrack = stream.getVideoTracks()[0];
|
|
1195
|
-
let sender = pc && pc.getSenders
|
|
1196
|
-
&& pc.getSenders().find(s => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
1412
|
+
let sender = pc && pc.getSenders && pc.getSenders().find((s: any) => videoTrack && s && s.track && s.track.kind === videoTrack.kind);
|
|
1197
1413
|
let wasTrackEnabled = false;
|
|
1414
|
+
|
|
1198
1415
|
if (!sender) {
|
|
1199
|
-
sender = pc && pc.getSenders && pc.getSenders().find(s => !s.track);
|
|
1416
|
+
sender = pc && pc.getSenders && pc.getSenders().find((s: any) => !s.track);
|
|
1200
1417
|
}
|
|
1201
1418
|
|
|
1202
1419
|
if (sender) {
|
|
@@ -1214,39 +1431,36 @@ export default class WebRTCClient extends Emitter {
|
|
|
1214
1431
|
// let's update the local stream
|
|
1215
1432
|
this.eventEmitter.emit('onVideoInputChange', stream);
|
|
1216
1433
|
this.setLocalMediaStream(sessionId, stream);
|
|
1217
|
-
|
|
1218
1434
|
return stream;
|
|
1219
1435
|
});
|
|
1220
1436
|
}
|
|
1221
1437
|
|
|
1222
|
-
getAudioDeviceId():
|
|
1223
|
-
//
|
|
1224
|
-
return this.audio && typeof this.audio === 'object' && 'deviceId' in this.audio
|
|
1225
|
-
? this.audio.deviceId.exact : undefined;
|
|
1438
|
+
getAudioDeviceId(): string | null | undefined {
|
|
1439
|
+
// @ts-ignore
|
|
1440
|
+
return this.audio && typeof this.audio === 'object' && 'deviceId' in this.audio ? this.audio.deviceId.exact : undefined;
|
|
1226
1441
|
}
|
|
1227
1442
|
|
|
1228
|
-
getVideoDeviceId():
|
|
1229
|
-
//
|
|
1230
|
-
return this.video && typeof this.video === 'object' && 'deviceId' in this.video
|
|
1231
|
-
? this.video.deviceId.exact : undefined;
|
|
1443
|
+
getVideoDeviceId(): string | null {
|
|
1444
|
+
// @ts-ignore
|
|
1445
|
+
return this.video && typeof this.video === 'object' && 'deviceId' in this.video ? this.video.deviceId.exact : undefined;
|
|
1232
1446
|
}
|
|
1233
1447
|
|
|
1234
|
-
reinvite(sipSession:
|
|
1235
|
-
audioOnly: boolean = false, iceRestart: boolean = false) {
|
|
1448
|
+
reinvite(sipSession: Inviter | Invitation, newConstraints: Record<string, any> | null | undefined = null, conference = false, audioOnly = false, iceRestart = false): Promise<OutgoingInviteRequest | void> {
|
|
1236
1449
|
if (!sipSession) {
|
|
1237
|
-
return
|
|
1450
|
+
return Promise.resolve();
|
|
1238
1451
|
}
|
|
1239
1452
|
|
|
1453
|
+
// @ts-ignore
|
|
1240
1454
|
if (sipSession.pendingReinvite) {
|
|
1241
|
-
return
|
|
1455
|
+
return Promise.resolve();
|
|
1242
1456
|
}
|
|
1243
1457
|
|
|
1244
1458
|
const wasMuted = this.isAudioMuted(sipSession);
|
|
1245
1459
|
const shouldDoVideo = newConstraints ? newConstraints.video : this.sessionWantsToDoVideo(sipSession);
|
|
1246
1460
|
const shouldDoScreenSharing = newConstraints && newConstraints.screen;
|
|
1247
1461
|
const desktop = newConstraints && newConstraints.desktop;
|
|
1248
|
-
|
|
1249
1462
|
logger.info('Sending reinvite', {
|
|
1463
|
+
clientId: this.clientId,
|
|
1250
1464
|
id: this.getSipSessionId(sipSession),
|
|
1251
1465
|
newConstraints,
|
|
1252
1466
|
conference,
|
|
@@ -1260,27 +1474,28 @@ export default class WebRTCClient extends Emitter {
|
|
|
1260
1474
|
// When upgrading to video, remove the `stripVideo` modifiers
|
|
1261
1475
|
if (newConstraints && newConstraints.video) {
|
|
1262
1476
|
const modifiers = sipSession.sessionDescriptionHandlerModifiersReInvite;
|
|
1263
|
-
sipSession.sessionDescriptionHandlerModifiersReInvite = modifiers.filter(modifier =>
|
|
1264
|
-
modifier !== stripVideo);
|
|
1477
|
+
sipSession.sessionDescriptionHandlerModifiersReInvite = modifiers.filter(modifier => modifier !== stripVideo);
|
|
1265
1478
|
}
|
|
1266
1479
|
|
|
1267
|
-
sipSession.sessionDescriptionHandlerOptionsReInvite = {
|
|
1268
|
-
|
|
1480
|
+
sipSession.sessionDescriptionHandlerOptionsReInvite = { ...sipSession.sessionDescriptionHandlerOptionsReInvite,
|
|
1481
|
+
// @ts-ignore
|
|
1269
1482
|
conference,
|
|
1270
1483
|
audioOnly,
|
|
1271
1484
|
};
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1485
|
+
const {
|
|
1486
|
+
constraints,
|
|
1487
|
+
} = this.getMediaConfiguration(shouldDoVideo, conference, newConstraints);
|
|
1276
1488
|
return sipSession.invite({
|
|
1277
1489
|
requestDelegate: {
|
|
1278
1490
|
onAccept: (response: IncomingResponse) => {
|
|
1279
1491
|
// Update the SDP body to be able to call sessionWantsToDoVideo correctly in `_setup[Local|Remote]Media`.
|
|
1280
1492
|
// Can't set directly sipSession.body because it's a getter.
|
|
1281
|
-
|
|
1493
|
+
// @ts-ignore
|
|
1494
|
+
if (sipSession instanceof Inviter && sipSession.outgoingRequestMessage.body) {
|
|
1495
|
+
// @ts-ignore
|
|
1282
1496
|
sipSession.outgoingRequestMessage.body.body = response.message.body;
|
|
1283
|
-
} else {
|
|
1497
|
+
} else if (sipSession instanceof Invitation) {
|
|
1498
|
+
// @ts-ignore
|
|
1284
1499
|
sipSession.incomingInviteRequest.message.body = response.message.body;
|
|
1285
1500
|
}
|
|
1286
1501
|
|
|
@@ -1289,13 +1504,13 @@ export default class WebRTCClient extends Emitter {
|
|
|
1289
1504
|
wasMuted,
|
|
1290
1505
|
shouldDoScreenSharing,
|
|
1291
1506
|
});
|
|
1292
|
-
|
|
1293
1507
|
this.updateRemoteStream(this.getSipSessionId(sipSession));
|
|
1294
1508
|
|
|
1295
1509
|
if (wasMuted) {
|
|
1296
1510
|
this.mute(sipSession);
|
|
1297
1511
|
}
|
|
1298
1512
|
|
|
1513
|
+
// @ts-ignore
|
|
1299
1514
|
this._onAccepted(sipSession, response.session, false);
|
|
1300
1515
|
|
|
1301
1516
|
if (shouldDoScreenSharing) {
|
|
@@ -1311,6 +1526,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
1311
1526
|
},
|
|
1312
1527
|
sessionDescriptionHandlerOptions: {
|
|
1313
1528
|
constraints,
|
|
1529
|
+
// @ts-ignore
|
|
1314
1530
|
conference,
|
|
1315
1531
|
audioOnly,
|
|
1316
1532
|
offerOptions: {
|
|
@@ -1320,35 +1536,35 @@ export default class WebRTCClient extends Emitter {
|
|
|
1320
1536
|
});
|
|
1321
1537
|
}
|
|
1322
1538
|
|
|
1323
|
-
async getUserMedia(constraints:
|
|
1539
|
+
async getUserMedia(constraints: Record<string, any>): Promise<MediaStream> {
|
|
1324
1540
|
const newConstraints = {
|
|
1325
1541
|
audio: this._getAudioConstraints(),
|
|
1326
1542
|
video: this._getVideoConstraints(constraints.video),
|
|
1327
1543
|
};
|
|
1328
|
-
|
|
1329
|
-
// $FlowFixMe
|
|
1330
1544
|
return navigator.mediaDevices.getUserMedia(newConstraints);
|
|
1331
1545
|
}
|
|
1332
1546
|
|
|
1333
1547
|
getPeerConnection(sessionId: string) {
|
|
1334
1548
|
const sipSession = this.sipSessions[sessionId];
|
|
1549
|
+
|
|
1335
1550
|
if (!sipSession) {
|
|
1336
1551
|
return null;
|
|
1337
1552
|
}
|
|
1338
1553
|
|
|
1554
|
+
// @ts-ignore
|
|
1339
1555
|
return sipSession.sessionDescriptionHandler ? sipSession.sessionDescriptionHandler.peerConnection : null;
|
|
1340
1556
|
}
|
|
1341
1557
|
|
|
1342
1558
|
// Local streams
|
|
1343
|
-
getLocalStream(sessionId: string):
|
|
1559
|
+
getLocalStream(sessionId: string): MediaStream | null {
|
|
1344
1560
|
const sipSession = this.sipSessions[sessionId];
|
|
1345
|
-
|
|
1346
|
-
return sipSession
|
|
1347
|
-
? sipSession.sessionDescriptionHandler.localMediaStream : null;
|
|
1561
|
+
// @ts-ignore
|
|
1562
|
+
return sipSession?.sessionDescriptionHandler?.localMediaStream || null;
|
|
1348
1563
|
}
|
|
1349
1564
|
|
|
1350
1565
|
getLocalTracks(sessionId: string): MediaStreamTrack[] {
|
|
1351
1566
|
const localStream = this.getLocalStream(sessionId);
|
|
1567
|
+
|
|
1352
1568
|
if (!localStream) {
|
|
1353
1569
|
return [];
|
|
1354
1570
|
}
|
|
@@ -1365,20 +1581,20 @@ export default class WebRTCClient extends Emitter {
|
|
|
1365
1581
|
return this.getLocalTracks(sessionId).some(track => track.kind === 'video');
|
|
1366
1582
|
}
|
|
1367
1583
|
|
|
1368
|
-
getLocalVideoStream(sessionId: string):
|
|
1584
|
+
getLocalVideoStream(sessionId: string): MediaStream | null | undefined {
|
|
1369
1585
|
return this.hasLocalVideo(sessionId) ? this.getLocalStream(sessionId) : null;
|
|
1370
1586
|
}
|
|
1371
1587
|
|
|
1372
1588
|
// Remote streams
|
|
1373
|
-
getRemoteStream(sessionId: string):
|
|
1589
|
+
getRemoteStream(sessionId: string): MediaStream | null {
|
|
1374
1590
|
const sipSession = this.sipSessions[sessionId];
|
|
1375
|
-
|
|
1376
|
-
return sipSession
|
|
1377
|
-
? sipSession.sessionDescriptionHandler.remoteMediaStream : null;
|
|
1591
|
+
// @ts-ignore
|
|
1592
|
+
return sipSession?.sessionDescriptionHandler?.remoteMediaStream || null;
|
|
1378
1593
|
}
|
|
1379
1594
|
|
|
1380
1595
|
getRemoteTracks(sessionId: string): MediaStreamTrack[] {
|
|
1381
1596
|
const remoteStream = this.getRemoteStream(sessionId);
|
|
1597
|
+
|
|
1382
1598
|
if (!remoteStream) {
|
|
1383
1599
|
return [];
|
|
1384
1600
|
}
|
|
@@ -1395,7 +1611,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
1395
1611
|
return this.getRemoteTracks(sessionId).some(track => track.kind === 'video');
|
|
1396
1612
|
}
|
|
1397
1613
|
|
|
1398
|
-
getRemoteVideoStream(sessionId: string):
|
|
1614
|
+
getRemoteVideoStream(sessionId: string): MediaStream | null | undefined {
|
|
1399
1615
|
if (this.isVideoRemotelyHeld(sessionId)) {
|
|
1400
1616
|
return null;
|
|
1401
1617
|
}
|
|
@@ -1404,13 +1620,14 @@ export default class WebRTCClient extends Emitter {
|
|
|
1404
1620
|
}
|
|
1405
1621
|
|
|
1406
1622
|
// Useful in a react-native environment when remoteMediaStream is not updated
|
|
1407
|
-
getRemoteVideoStreamFromPc(sessionId: string):
|
|
1623
|
+
getRemoteVideoStreamFromPc(sessionId: string): MediaStream | null | undefined {
|
|
1408
1624
|
const pc = this.getPeerConnection(sessionId);
|
|
1625
|
+
|
|
1409
1626
|
if (!pc) {
|
|
1410
1627
|
return null;
|
|
1411
1628
|
}
|
|
1412
1629
|
|
|
1413
|
-
return pc.getRemoteStreams().find(stream => !!stream.getVideoTracks().length);
|
|
1630
|
+
return pc.getRemoteStreams().find((stream: MediaStream) => !!stream.getVideoTracks().length);
|
|
1414
1631
|
}
|
|
1415
1632
|
|
|
1416
1633
|
hasVideo(sessionId: string): boolean {
|
|
@@ -1421,45 +1638,53 @@ export default class WebRTCClient extends Emitter {
|
|
|
1421
1638
|
return this.hasALocalVideoTrack(sessionId) || this.hasARemoteVideoTrack(sessionId);
|
|
1422
1639
|
}
|
|
1423
1640
|
|
|
1424
|
-
getSipSessionId(sipSession:
|
|
1641
|
+
getSipSessionId(sipSession: Inviter | Invitation | null | undefined): string {
|
|
1425
1642
|
if (!sipSession) {
|
|
1426
1643
|
return '';
|
|
1427
1644
|
}
|
|
1428
|
-
|
|
1429
|
-
|
|
1645
|
+
|
|
1646
|
+
// @ts-ignore
|
|
1647
|
+
if (sipSession.message?.callId) {
|
|
1648
|
+
// @ts-ignore
|
|
1649
|
+
return sipSession.message.callId.substring(0, SIP_ID_LENGTH);
|
|
1430
1650
|
}
|
|
1431
1651
|
|
|
1432
1652
|
// For Inviter
|
|
1433
|
-
|
|
1434
|
-
|
|
1653
|
+
// @ts-ignore
|
|
1654
|
+
if (sipSession instanceof Inviter && sipSession.outgoingRequestMessage) {
|
|
1655
|
+
// @ts-ignore
|
|
1656
|
+
return sipSession.outgoingRequestMessage.callId.substring(0, SIP_ID_LENGTH);
|
|
1435
1657
|
}
|
|
1436
1658
|
|
|
1437
1659
|
// For Invitation
|
|
1438
|
-
return (sipSession.id || '').
|
|
1660
|
+
return (sipSession.id || '').substring(0, SIP_ID_LENGTH);
|
|
1439
1661
|
}
|
|
1440
1662
|
|
|
1441
|
-
async waitForRegister() {
|
|
1663
|
+
async waitForRegister(): Promise<void> {
|
|
1442
1664
|
return new Promise(resolve => this.on(REGISTERED, resolve));
|
|
1443
1665
|
}
|
|
1444
1666
|
|
|
1445
1667
|
// eslint-disable-next-line no-unused-vars
|
|
1446
|
-
sessionWantsToDoVideo(session: Inviter) {
|
|
1668
|
+
sessionWantsToDoVideo(session: Inviter | Invitation): boolean {
|
|
1447
1669
|
if (!session) {
|
|
1448
1670
|
return false;
|
|
1449
1671
|
}
|
|
1450
|
-
|
|
1672
|
+
|
|
1673
|
+
const {
|
|
1674
|
+
body,
|
|
1675
|
+
} = session.request || session;
|
|
1451
1676
|
// Sometimes with InviteClientContext the body is in the body attribute ...
|
|
1452
1677
|
const sdp = typeof body === 'object' && body ? body.body : body;
|
|
1453
|
-
|
|
1454
1678
|
return hasAnActiveVideo(sdp);
|
|
1455
1679
|
}
|
|
1456
1680
|
|
|
1457
|
-
hasHeartbeat() {
|
|
1681
|
+
hasHeartbeat(): boolean {
|
|
1458
1682
|
return this.heartbeat.hasHeartbeat;
|
|
1459
1683
|
}
|
|
1460
1684
|
|
|
1461
|
-
startHeartbeat() {
|
|
1462
|
-
logger.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent });
|
|
1685
|
+
startHeartbeat(): void {
|
|
1686
|
+
logger.info('sdk webrtc start heartbeat', { userAgent: !!this.userAgent, clientId: this.clientId });
|
|
1687
|
+
|
|
1463
1688
|
if (!this.userAgent) {
|
|
1464
1689
|
this.heartbeat.stop();
|
|
1465
1690
|
return;
|
|
@@ -1467,53 +1692,61 @@ export default class WebRTCClient extends Emitter {
|
|
|
1467
1692
|
|
|
1468
1693
|
this.eventEmitter.off(MESSAGE, this._boundOnHeartbeat);
|
|
1469
1694
|
this.eventEmitter.on(MESSAGE, this._boundOnHeartbeat);
|
|
1470
|
-
|
|
1471
1695
|
this.heartbeat.start();
|
|
1472
1696
|
}
|
|
1473
1697
|
|
|
1474
|
-
stopHeartbeat() {
|
|
1475
|
-
logger.info('sdk webrtc stop heartbeat');
|
|
1698
|
+
stopHeartbeat(): void {
|
|
1699
|
+
logger.info('sdk webrtc stop heartbeat', { clientId: this.clientId });
|
|
1476
1700
|
this.heartbeat.stop();
|
|
1477
1701
|
}
|
|
1478
1702
|
|
|
1479
|
-
setOnHeartbeatTimeout(cb:
|
|
1703
|
+
setOnHeartbeatTimeout(cb: (...args: Array<any>) => any): void {
|
|
1480
1704
|
this.heartbeatTimeoutCb = cb;
|
|
1481
1705
|
}
|
|
1482
1706
|
|
|
1483
|
-
setOnHeartbeatCallback(cb:
|
|
1707
|
+
setOnHeartbeatCallback(cb: (...args: Array<any>) => any): void {
|
|
1484
1708
|
this.heartbeatCb = cb;
|
|
1485
1709
|
}
|
|
1486
1710
|
|
|
1487
|
-
onCallEnded(session:
|
|
1711
|
+
onCallEnded(session: Inviter | Invitation): void {
|
|
1488
1712
|
this._cleanupMedia(session);
|
|
1713
|
+
|
|
1489
1714
|
delete this.sipSessions[this.getSipSessionId(session)];
|
|
1490
1715
|
|
|
1491
1716
|
this._stopSendingStats(session);
|
|
1717
|
+
|
|
1492
1718
|
this.stopNetworkMonitoring(session);
|
|
1493
1719
|
}
|
|
1494
1720
|
|
|
1495
1721
|
attemptReconnection(): void {
|
|
1496
|
-
logger.info('attempt reconnection', { userAgent: !!this.userAgent });
|
|
1722
|
+
logger.info('attempt reconnection', { clientId: this.clientId, userAgent: !!this.userAgent });
|
|
1723
|
+
|
|
1497
1724
|
if (!this.userAgent) {
|
|
1498
1725
|
return;
|
|
1499
1726
|
}
|
|
1727
|
+
|
|
1728
|
+
// @ts-ignore
|
|
1500
1729
|
this.userAgent.attemptReconnection();
|
|
1501
1730
|
}
|
|
1502
1731
|
|
|
1503
|
-
storeSipSession(session:
|
|
1504
|
-
this.
|
|
1732
|
+
storeSipSession(session: Invitation | Inviter): void {
|
|
1733
|
+
const id = this.getSipSessionId(session);
|
|
1734
|
+
logger.info('storing sip session', { id, clientId: this.clientId });
|
|
1735
|
+
|
|
1736
|
+
this.sipSessions[id] = session;
|
|
1505
1737
|
}
|
|
1506
1738
|
|
|
1507
|
-
getSipSession(id: string):
|
|
1508
|
-
return id in this.sipSessions ? this.sipSessions[id] : null;
|
|
1739
|
+
getSipSession(id: string): Invitation | Inviter | null | undefined {
|
|
1740
|
+
return id in this.sipSessions ? this.sipSessions[id.substring(0, SIP_ID_LENGTH)] : null;
|
|
1509
1741
|
}
|
|
1510
1742
|
|
|
1511
1743
|
getSipSessionIds(): string[] {
|
|
1512
1744
|
return Object.keys(this.sipSessions);
|
|
1513
1745
|
}
|
|
1514
1746
|
|
|
1515
|
-
setLocalMediaStream(sipSessionId: string, newStream: MediaStream) {
|
|
1747
|
+
setLocalMediaStream(sipSessionId: string, newStream: MediaStream): void {
|
|
1516
1748
|
const sipSession = this.sipSessions[sipSessionId];
|
|
1749
|
+
|
|
1517
1750
|
if (!sipSession) {
|
|
1518
1751
|
return;
|
|
1519
1752
|
}
|
|
@@ -1522,19 +1755,21 @@ export default class WebRTCClient extends Emitter {
|
|
|
1522
1755
|
sipSessionId,
|
|
1523
1756
|
tracks: newStream ? newStream.getTracks() : null,
|
|
1524
1757
|
});
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1758
|
+
if (sipSession.sessionDescriptionHandler) {
|
|
1759
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
1760
|
+
// @ts-ignore
|
|
1761
|
+
sipSession.sessionDescriptionHandler._localMediaStream = newStream;
|
|
1762
|
+
}
|
|
1528
1763
|
}
|
|
1529
1764
|
|
|
1530
|
-
updateLocalStream(sipSessionId: string, newStream: MediaStream) {
|
|
1765
|
+
updateLocalStream(sipSessionId: string, newStream: MediaStream): void {
|
|
1531
1766
|
const sipSession = this.sipSessions[sipSessionId];
|
|
1767
|
+
|
|
1532
1768
|
if (!sipSession) {
|
|
1533
1769
|
return;
|
|
1534
1770
|
}
|
|
1535
1771
|
|
|
1536
1772
|
const oldStream = this.getLocalStream(sipSessionId);
|
|
1537
|
-
|
|
1538
1773
|
logger.info('updating local stream', {
|
|
1539
1774
|
sipSessionId,
|
|
1540
1775
|
oldStream: !!oldStream,
|
|
@@ -1551,14 +1786,13 @@ export default class WebRTCClient extends Emitter {
|
|
|
1551
1786
|
this._setupMedias(sipSession, newStream);
|
|
1552
1787
|
}
|
|
1553
1788
|
|
|
1554
|
-
updateRemoteStream(sessionId: string) {
|
|
1789
|
+
updateRemoteStream(sessionId: string): void {
|
|
1555
1790
|
const remoteStream = this.getRemoteStream(sessionId);
|
|
1556
1791
|
const pc = this.getPeerConnection(sessionId);
|
|
1557
|
-
|
|
1558
1792
|
logger.info('Updating remote stream', {
|
|
1559
1793
|
sessionId,
|
|
1560
1794
|
tracks: remoteStream ? remoteStream.getTracks() : null,
|
|
1561
|
-
receiverTracks: pc && pc.getReceivers ? pc.getReceivers().map(receiver => receiver.track) : null,
|
|
1795
|
+
receiverTracks: pc && pc.getReceivers ? pc.getReceivers().map((receiver: any) => receiver.track) : null,
|
|
1562
1796
|
});
|
|
1563
1797
|
|
|
1564
1798
|
if (!pc || !remoteStream) {
|
|
@@ -1570,27 +1804,36 @@ export default class WebRTCClient extends Emitter {
|
|
|
1570
1804
|
});
|
|
1571
1805
|
|
|
1572
1806
|
if (pc.getReceivers) {
|
|
1573
|
-
pc.getReceivers().forEach(receiver => {
|
|
1807
|
+
pc.getReceivers().forEach((receiver: any) => {
|
|
1574
1808
|
remoteStream.addTrack(receiver.track);
|
|
1575
1809
|
});
|
|
1576
1810
|
}
|
|
1577
1811
|
}
|
|
1578
1812
|
|
|
1579
|
-
getMediaConfiguration(enableVideo: boolean, conference
|
|
1813
|
+
getMediaConfiguration(enableVideo: boolean, conference = false, constraints: Record<string, any> | null | undefined = null): Record<string, any> {
|
|
1580
1814
|
const screenSharing = constraints && 'screen' in constraints ? constraints.screen : false;
|
|
1581
1815
|
const isDesktop = constraints && 'desktop' in constraints ? constraints.desktop : false;
|
|
1582
1816
|
const withAudio = constraints && 'audio' in constraints ? constraints.audio : true;
|
|
1583
1817
|
const mandatoryVideo = constraints && typeof constraints.video === 'object' ? constraints.video.mandatory : {};
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1818
|
+
logger.info('Retrieving media a configuration', {
|
|
1819
|
+
enableVideo,
|
|
1820
|
+
screenSharing,
|
|
1821
|
+
isDesktop,
|
|
1822
|
+
withAudio,
|
|
1823
|
+
constraints,
|
|
1824
|
+
});
|
|
1587
1825
|
return {
|
|
1588
1826
|
constraints: {
|
|
1589
1827
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
1590
|
-
audio: screenSharing ? !isDesktop :
|
|
1591
|
-
video: screenSharing ?
|
|
1592
|
-
|
|
1593
|
-
|
|
1828
|
+
audio: screenSharing ? !isDesktop : withAudio ? this._getAudioConstraints() : false,
|
|
1829
|
+
video: screenSharing ? isDesktop ? {
|
|
1830
|
+
mandatory: {
|
|
1831
|
+
chromeMediaSource: 'desktop',
|
|
1832
|
+
...(mandatoryVideo || {}),
|
|
1833
|
+
},
|
|
1834
|
+
} : {
|
|
1835
|
+
cursor: 'always',
|
|
1836
|
+
} : this._getVideoConstraints(enableVideo),
|
|
1594
1837
|
screen: screenSharing,
|
|
1595
1838
|
desktop: isDesktop,
|
|
1596
1839
|
conference,
|
|
@@ -1608,42 +1851,44 @@ export default class WebRTCClient extends Emitter {
|
|
|
1608
1851
|
};
|
|
1609
1852
|
}
|
|
1610
1853
|
|
|
1611
|
-
isConference(sessionId: string) {
|
|
1854
|
+
isConference(sessionId: string): boolean {
|
|
1612
1855
|
return sessionId in this.conferences;
|
|
1613
1856
|
}
|
|
1614
1857
|
|
|
1615
|
-
createAudioElementFor(sessionId: string) {
|
|
1616
|
-
const audio:
|
|
1858
|
+
createAudioElementFor(sessionId: string): HTMLAudioElement {
|
|
1859
|
+
const audio: HTMLAudioElement = document.createElement('audio');
|
|
1617
1860
|
audio.setAttribute('id', `audio-${sessionId}`);
|
|
1618
1861
|
|
|
1619
|
-
if (audio.setSinkId && this.audioOutputDeviceId) {
|
|
1620
|
-
audio.setSinkId(this.audioOutputDeviceId);
|
|
1862
|
+
if ((audio as any).setSinkId && this.audioOutputDeviceId) {
|
|
1863
|
+
(audio as any).setSinkId(this.audioOutputDeviceId);
|
|
1621
1864
|
}
|
|
1622
1865
|
|
|
1623
1866
|
if (document.body) {
|
|
1624
1867
|
document.body.appendChild(audio);
|
|
1625
1868
|
}
|
|
1626
|
-
this.audioElements[sessionId] = audio;
|
|
1627
1869
|
|
|
1870
|
+
this.audioElements[sessionId] = audio;
|
|
1628
1871
|
audio.volume = this.audioOutputVolume;
|
|
1629
1872
|
audio.autoplay = true;
|
|
1630
|
-
|
|
1631
1873
|
return audio;
|
|
1632
1874
|
}
|
|
1633
1875
|
|
|
1634
|
-
_onTransportError() {
|
|
1876
|
+
_onTransportError(): void {
|
|
1635
1877
|
logger.error('on transport error');
|
|
1636
1878
|
this.eventEmitter.emit(TRANSPORT_ERROR);
|
|
1637
1879
|
this.attemptReconnection();
|
|
1638
1880
|
}
|
|
1639
1881
|
|
|
1640
|
-
_onHeartbeat(message: string |
|
|
1882
|
+
_onHeartbeat(message: string | Record<string, any>): void {
|
|
1641
1883
|
const body = message && typeof message === 'object' ? message.data : message;
|
|
1884
|
+
|
|
1642
1885
|
if (body && body.indexOf('200 OK') !== -1) {
|
|
1643
1886
|
if (this.hasHeartbeat()) {
|
|
1644
|
-
logger.info('on heartbeat received from Asterisk', {
|
|
1645
|
-
|
|
1887
|
+
logger.info('on heartbeat received from Asterisk', {
|
|
1888
|
+
hasHeartbeat: this.hasHeartbeat(),
|
|
1889
|
+
});
|
|
1646
1890
|
this.heartbeat.onHeartbeat();
|
|
1891
|
+
|
|
1647
1892
|
if (this.heartbeatCb) {
|
|
1648
1893
|
this.heartbeatCb();
|
|
1649
1894
|
}
|
|
@@ -1651,8 +1896,11 @@ export default class WebRTCClient extends Emitter {
|
|
|
1651
1896
|
}
|
|
1652
1897
|
}
|
|
1653
1898
|
|
|
1654
|
-
async _onHeartbeatTimeout() {
|
|
1655
|
-
logger.warn('sdk webrtc heartbeat timed out', {
|
|
1899
|
+
async _onHeartbeatTimeout(): Promise<void> {
|
|
1900
|
+
logger.warn('sdk webrtc heartbeat timed out', {
|
|
1901
|
+
userAgent: !!this.userAgent,
|
|
1902
|
+
cb: !!this.heartbeatTimeoutCb,
|
|
1903
|
+
});
|
|
1656
1904
|
|
|
1657
1905
|
if (this.heartbeatTimeoutCb) {
|
|
1658
1906
|
this.heartbeatTimeoutCb();
|
|
@@ -1660,10 +1908,11 @@ export default class WebRTCClient extends Emitter {
|
|
|
1660
1908
|
|
|
1661
1909
|
if (this.userAgent && this.userAgent.transport) {
|
|
1662
1910
|
// Disconnect from WS and triggers events, but do not trigger disconnect if already disconnecting...
|
|
1911
|
+
// @ts-ignore
|
|
1663
1912
|
if (!this.userAgent.transport.transitioningState && !this.userAgent.transport.disconnectPromise) {
|
|
1664
1913
|
try {
|
|
1665
1914
|
await this.userAgent.transport.disconnect();
|
|
1666
|
-
} catch (e) {
|
|
1915
|
+
} catch (e: any) {
|
|
1667
1916
|
logger.error('Transport disconnection after heartbeat timeout, error', e);
|
|
1668
1917
|
}
|
|
1669
1918
|
}
|
|
@@ -1673,31 +1922,35 @@ export default class WebRTCClient extends Emitter {
|
|
|
1673
1922
|
}
|
|
1674
1923
|
}
|
|
1675
1924
|
|
|
1676
|
-
_isWeb() {
|
|
1925
|
+
_isWeb(): boolean {
|
|
1677
1926
|
return typeof window === 'object' && typeof document === 'object';
|
|
1678
1927
|
}
|
|
1679
1928
|
|
|
1680
|
-
_isVideoTrack(track: MediaStreamTrack) {
|
|
1929
|
+
_isVideoTrack(track: MediaStreamTrack): boolean {
|
|
1681
1930
|
return track.kind === 'video' && track.readyState === 'live';
|
|
1682
1931
|
}
|
|
1683
1932
|
|
|
1684
|
-
_hasAudio() {
|
|
1933
|
+
_hasAudio(): boolean {
|
|
1685
1934
|
return this.hasAudio;
|
|
1686
1935
|
}
|
|
1687
1936
|
|
|
1688
|
-
_getAudioConstraints() {
|
|
1689
|
-
|
|
1937
|
+
_getAudioConstraints(): MediaTrackConstraints | boolean {
|
|
1938
|
+
// @ts-ignore
|
|
1939
|
+
return this.audio?.deviceId?.exact ? this.audio : true;
|
|
1690
1940
|
}
|
|
1691
1941
|
|
|
1692
|
-
_getVideoConstraints(video
|
|
1942
|
+
_getVideoConstraints(video = false): MediaTrackConstraints | boolean {
|
|
1693
1943
|
if (!video) {
|
|
1694
1944
|
return false;
|
|
1695
1945
|
}
|
|
1696
|
-
|
|
1946
|
+
|
|
1947
|
+
// @ts-ignore
|
|
1948
|
+
return this.video?.deviceId?.exact ? this.video : true;
|
|
1697
1949
|
}
|
|
1698
1950
|
|
|
1699
|
-
_connectIfNeeded(): Promise<
|
|
1700
|
-
logger.info('connect if needed, checking', { connected: this.isConnected() });
|
|
1951
|
+
_connectIfNeeded(): Promise<any> {
|
|
1952
|
+
logger.info('connect if needed, checking', { connected: this.isConnected(), clientId: this.clientId });
|
|
1953
|
+
|
|
1701
1954
|
if (!this.userAgent) {
|
|
1702
1955
|
logger.info('need to recreate User Agent');
|
|
1703
1956
|
this.userAgent = this.createUserAgent(this.uaConfigOverrides);
|
|
@@ -1710,14 +1963,13 @@ export default class WebRTCClient extends Emitter {
|
|
|
1710
1963
|
|
|
1711
1964
|
if (this.isConnecting()) {
|
|
1712
1965
|
logger.info('webrtc sdk, already connecting...');
|
|
1713
|
-
|
|
1966
|
+
// @ts-ignore
|
|
1714
1967
|
this.connectionPromise = this.userAgent.transport.connectPromise;
|
|
1715
|
-
return this.connectionPromise;
|
|
1968
|
+
return Promise.resolve(this.connectionPromise);
|
|
1716
1969
|
}
|
|
1717
1970
|
|
|
1718
1971
|
if (this.connectionPromise) {
|
|
1719
1972
|
logger.info('webrtc sdk, connection promise connecting...');
|
|
1720
|
-
// $FlowFixMe
|
|
1721
1973
|
return this.connectionPromise;
|
|
1722
1974
|
}
|
|
1723
1975
|
|
|
@@ -1725,26 +1977,34 @@ export default class WebRTCClient extends Emitter {
|
|
|
1725
1977
|
|
|
1726
1978
|
// Force UA to reconnect
|
|
1727
1979
|
if (this.userAgent && this.userAgent.state !== UserAgentState.Stopped) {
|
|
1980
|
+
// @ts-ignore
|
|
1728
1981
|
this.userAgent.transitionState(UserAgentState.Stopped);
|
|
1729
1982
|
}
|
|
1983
|
+
|
|
1730
1984
|
if (this.userAgent.transport && this.userAgent.transport.state !== TransportState.Disconnected) {
|
|
1985
|
+
// @ts-ignore
|
|
1731
1986
|
this.userAgent.transport.transitionState(TransportState.Disconnected);
|
|
1732
1987
|
}
|
|
1733
|
-
this.connectionPromise = this.userAgent.start().catch(console.error);
|
|
1734
1988
|
|
|
1989
|
+
this.connectionPromise = this.userAgent.start().catch(console.error);
|
|
1735
1990
|
return this.connectionPromise;
|
|
1736
1991
|
}
|
|
1737
1992
|
|
|
1738
|
-
_buildConfig(config: WebRtcConfig, session:
|
|
1993
|
+
_buildConfig(config: WebRtcConfig, session: Invitation | Inviter | null | undefined): Promise<WebRtcConfig> {
|
|
1739
1994
|
// If no session provided, return the configuration directly
|
|
1740
1995
|
if (!session) {
|
|
1741
1996
|
return new Promise(resolve => resolve(config));
|
|
1742
1997
|
}
|
|
1743
1998
|
|
|
1744
|
-
const client = new ApiClient({
|
|
1999
|
+
const client = new ApiClient({
|
|
2000
|
+
server: config.host,
|
|
2001
|
+
});
|
|
2002
|
+
// @ts-ignore
|
|
1745
2003
|
client.setToken(session.token);
|
|
2004
|
+
// @ts-ignore
|
|
1746
2005
|
client.setRefreshToken(session.refreshToken);
|
|
1747
2006
|
|
|
2007
|
+
// @ts-ignore
|
|
1748
2008
|
return client.confd.getUserLineSipFromToken(session.uuid).then(sipLine => ({
|
|
1749
2009
|
authorizationUser: sipLine.username,
|
|
1750
2010
|
password: sipLine.secret,
|
|
@@ -1753,15 +2013,19 @@ export default class WebRTCClient extends Emitter {
|
|
|
1753
2013
|
}));
|
|
1754
2014
|
}
|
|
1755
2015
|
|
|
1756
|
-
_createWebRTCConfiguration(configOverrides:
|
|
1757
|
-
let {
|
|
1758
|
-
|
|
2016
|
+
_createWebRTCConfiguration(configOverrides: Record<string, any> | null = {}): Record<string, any> {
|
|
2017
|
+
let {
|
|
2018
|
+
host,
|
|
2019
|
+
} = this.config;
|
|
2020
|
+
let port: number = this.config.port || 443;
|
|
1759
2021
|
|
|
1760
2022
|
if (this.config.websocketSip) {
|
|
1761
|
-
|
|
2023
|
+
const webSocketSip = this.config.websocketSip.split(':');
|
|
2024
|
+
[host] = webSocketSip;
|
|
2025
|
+
port = Number(webSocketSip[1]);
|
|
1762
2026
|
}
|
|
1763
2027
|
|
|
1764
|
-
const config:
|
|
2028
|
+
const config: Record<string, any> = {
|
|
1765
2029
|
authorizationUsername: this.config.authorizationUser,
|
|
1766
2030
|
authorizationPassword: this.config.password,
|
|
1767
2031
|
displayName: this.config.displayName,
|
|
@@ -1777,25 +2041,23 @@ export default class WebRTCClient extends Emitter {
|
|
|
1777
2041
|
userAgentString: this.config.userAgentString || 'wazo-sdk',
|
|
1778
2042
|
reconnectionAttempts: 10000,
|
|
1779
2043
|
reconnectionDelay: 5,
|
|
1780
|
-
sessionDescriptionHandlerFactory: (session:
|
|
2044
|
+
sessionDescriptionHandlerFactory: (session: Inviter | Invitation, options: SessionDescriptionHandlerFactoryOptions = {}) => {
|
|
1781
2045
|
const uaLogger = session.userAgent.getLogger('sip.WazoSessionDescriptionHandler');
|
|
2046
|
+
|
|
1782
2047
|
const isWeb = this._isWeb();
|
|
1783
|
-
const iceGatheringTimeout = 'peerConnectionOptions' in options
|
|
1784
|
-
? options.peerConnectionOptions.iceGatheringTimeout || DEFAULT_ICE_TIMEOUT : DEFAULT_ICE_TIMEOUT;
|
|
1785
2048
|
|
|
1786
|
-
|
|
1787
|
-
|
|
2049
|
+
// @ts-ignore
|
|
2050
|
+
const iceGatheringTimeout = 'peerConnectionOptions' in options ? options.peerConnectionOptions.iceGatheringTimeout || DEFAULT_ICE_TIMEOUT : DEFAULT_ICE_TIMEOUT;
|
|
2051
|
+
const sdhOptions: SessionDescriptionHandlerConfiguration = { ...options,
|
|
1788
2052
|
iceGatheringTimeout,
|
|
1789
|
-
peerConnectionConfiguration: {
|
|
1790
|
-
...defaultPeerConnectionConfiguration(),
|
|
2053
|
+
peerConnectionConfiguration: { ...defaultPeerConnectionConfiguration(),
|
|
1791
2054
|
...(options.peerConnectionConfiguration || {}),
|
|
1792
2055
|
},
|
|
1793
2056
|
};
|
|
1794
|
-
|
|
1795
2057
|
return new WazoSessionDescriptionHandler(uaLogger, wazoMediaStreamFactory, sdhOptions, isWeb, session);
|
|
1796
2058
|
},
|
|
1797
2059
|
transportOptions: {
|
|
1798
|
-
traceSip: configOverrides
|
|
2060
|
+
traceSip: configOverrides?.traceSip || false,
|
|
1799
2061
|
wsServers: `wss://${host}:${port}/api/asterisk/ws`,
|
|
1800
2062
|
},
|
|
1801
2063
|
sessionDescriptionHandlerFactoryOptions: {
|
|
@@ -1812,19 +2074,20 @@ export default class WebRTCClient extends Emitter {
|
|
|
1812
2074
|
rtcpMuxPolicy: 'require',
|
|
1813
2075
|
iceServers: WebRTCClient.getIceServers(this.config.host),
|
|
1814
2076
|
...this._getRtcOptions(),
|
|
1815
|
-
...configOverrides
|
|
2077
|
+
...(configOverrides?.peerConnectionOptions || {}),
|
|
1816
2078
|
},
|
|
1817
2079
|
},
|
|
1818
2080
|
// Configuration used in SDH to create the PeerConnection
|
|
1819
2081
|
peerConnectionConfiguration: {
|
|
1820
2082
|
rtcpMuxPolicy: 'require',
|
|
1821
2083
|
iceServers: WebRTCClient.getIceServers(this.config.host),
|
|
1822
|
-
...configOverrides
|
|
2084
|
+
...(configOverrides?.peerConnectionOptions || {}),
|
|
1823
2085
|
},
|
|
1824
2086
|
},
|
|
1825
2087
|
};
|
|
1826
|
-
|
|
1827
|
-
|
|
2088
|
+
return { ...config,
|
|
2089
|
+
...configOverrides,
|
|
2090
|
+
};
|
|
1828
2091
|
}
|
|
1829
2092
|
|
|
1830
2093
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -1838,7 +2101,7 @@ export default class WebRTCClient extends Emitter {
|
|
|
1838
2101
|
}
|
|
1839
2102
|
|
|
1840
2103
|
// Invitation and Inviter extends Session
|
|
1841
|
-
_setupSession(session:
|
|
2104
|
+
_setupSession(session: Inviter | Invitation): void {
|
|
1842
2105
|
const sipSessionId = this.getSipSessionId(session);
|
|
1843
2106
|
|
|
1844
2107
|
// When receiving an Invitation, the delegate is not defined.
|
|
@@ -1847,12 +2110,12 @@ export default class WebRTCClient extends Emitter {
|
|
|
1847
2110
|
}
|
|
1848
2111
|
|
|
1849
2112
|
session.delegate.onSessionDescriptionHandler = (sdh: SessionDescriptionHandler) => {
|
|
2113
|
+
// @ts-ignore
|
|
1850
2114
|
sdh.on('error', e => {
|
|
1851
2115
|
this.eventEmitter.emit(ON_ERROR, e);
|
|
1852
2116
|
});
|
|
1853
|
-
|
|
1854
2117
|
sdh.peerConnectionDelegate = {
|
|
1855
|
-
onicecandidateerror: (error:
|
|
2118
|
+
onicecandidateerror: (error: Record<string, any>) => {
|
|
1856
2119
|
logger.error('on icecandidate error', {
|
|
1857
2120
|
address: error.address,
|
|
1858
2121
|
port: error.port,
|
|
@@ -1864,33 +2127,43 @@ export default class WebRTCClient extends Emitter {
|
|
|
1864
2127
|
};
|
|
1865
2128
|
};
|
|
1866
2129
|
|
|
2130
|
+
// @ts-ignore
|
|
1867
2131
|
const oldInviteRequest = session.onInviteRequest.bind(session);
|
|
1868
2132
|
let hadRemoteVideo = false;
|
|
1869
2133
|
|
|
1870
2134
|
// Monkey patch `onInviteRequest` to be able to know if there was a remote video stream before `onInvite` is called
|
|
1871
2135
|
// Because when `onInvite` is called we already got the video track
|
|
1872
|
-
|
|
2136
|
+
// @ts-ignore
|
|
2137
|
+
session.onInviteRequest = request => {
|
|
1873
2138
|
hadRemoteVideo = this.hasARemoteVideoTrack(sipSessionId);
|
|
1874
|
-
|
|
1875
2139
|
oldInviteRequest(request);
|
|
1876
2140
|
};
|
|
1877
2141
|
|
|
1878
2142
|
session.delegate.onInvite = (request: IncomingRequestMessage) => {
|
|
1879
|
-
let updatedCalleeName = null;
|
|
2143
|
+
let updatedCalleeName: string | null = null;
|
|
1880
2144
|
let updatedNumber = null;
|
|
2145
|
+
|
|
1881
2146
|
if (session.assertedIdentity) {
|
|
2147
|
+
// @ts-ignore
|
|
1882
2148
|
updatedNumber = session.assertedIdentity.uri.normal.user;
|
|
1883
2149
|
updatedCalleeName = session.assertedIdentity.displayName || updatedNumber;
|
|
1884
2150
|
}
|
|
1885
|
-
logger.info('re-invite received', { updatedCalleeName, updatedNumber, hadRemoteVideo });
|
|
1886
2151
|
|
|
1887
|
-
|
|
2152
|
+
logger.info('re-invite received', {
|
|
2153
|
+
updatedCalleeName,
|
|
2154
|
+
updatedNumber,
|
|
2155
|
+
hadRemoteVideo,
|
|
2156
|
+
});
|
|
1888
2157
|
|
|
2158
|
+
// Useful to know if it's a video upgrade or an unhold from a remote peer with a video stream
|
|
1889
2159
|
// Update SDP
|
|
1890
2160
|
// Remote video is handled by the `track` event. Here we're dealing with video stream removal.
|
|
1891
|
-
if (session
|
|
2161
|
+
if (session instanceof Invitation) {
|
|
2162
|
+
// @ts-ignore
|
|
1892
2163
|
session.incomingInviteRequest.message.body = request.body;
|
|
1893
|
-
|
|
2164
|
+
// @ts-ignore
|
|
2165
|
+
} else if (session instanceof Inviter && session.outgoingInviteRequest.message.body) {
|
|
2166
|
+
// @ts-ignore
|
|
1894
2167
|
session.outgoingInviteRequest.message.body.body = request.body;
|
|
1895
2168
|
}
|
|
1896
2169
|
|
|
@@ -1902,31 +2175,50 @@ export default class WebRTCClient extends Emitter {
|
|
|
1902
2175
|
};
|
|
1903
2176
|
}
|
|
1904
2177
|
|
|
1905
|
-
_onEarlyProgress(session:
|
|
2178
|
+
_onEarlyProgress(session: any): void {
|
|
1906
2179
|
this._setupMedias(session);
|
|
1907
2180
|
|
|
1908
2181
|
const sessionId = this.getSipSessionId(session).substr(0, 20);
|
|
1909
2182
|
this.updateRemoteStream(sessionId);
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
2183
|
+
logger.info('Early media progress progress received', {
|
|
2184
|
+
sessionId,
|
|
2185
|
+
});
|
|
1913
2186
|
this.eventEmitter.emit(ON_EARLY_MEDIA, session);
|
|
1914
2187
|
}
|
|
1915
2188
|
|
|
1916
|
-
_onAccepted(session:
|
|
1917
|
-
logger.info('on call accepted', {
|
|
1918
|
-
|
|
2189
|
+
_onAccepted(session: Inviter | Invitation, sessionDialog?: SessionDialog, withEvent = true): void {
|
|
2190
|
+
logger.info('on call accepted', {
|
|
2191
|
+
id: session.id,
|
|
2192
|
+
clientId: this.clientId,
|
|
2193
|
+
// @ts-ignore
|
|
2194
|
+
remoteTag: session.remoteTag,
|
|
2195
|
+
});
|
|
1919
2196
|
this.storeSipSession(session);
|
|
1920
2197
|
|
|
1921
2198
|
this._setupMedias(session);
|
|
1922
2199
|
|
|
1923
2200
|
this.updateRemoteStream(this.getSipSessionId(session));
|
|
2201
|
+
// @ts-ignore
|
|
2202
|
+
const pc = session.sessionDescriptionHandler?.peerConnection;
|
|
1924
2203
|
|
|
1925
|
-
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
1926
2204
|
const onTrack = (event: any) => {
|
|
1927
2205
|
const isAudioOnly = this._isAudioOnly(session);
|
|
1928
|
-
|
|
1929
|
-
|
|
2206
|
+
|
|
2207
|
+
const {
|
|
2208
|
+
kind,
|
|
2209
|
+
label,
|
|
2210
|
+
readyState,
|
|
2211
|
+
id,
|
|
2212
|
+
muted,
|
|
2213
|
+
} = event.track;
|
|
2214
|
+
logger.info('on track event', {
|
|
2215
|
+
isAudioOnly,
|
|
2216
|
+
kind,
|
|
2217
|
+
label,
|
|
2218
|
+
readyState,
|
|
2219
|
+
id,
|
|
2220
|
+
muted,
|
|
2221
|
+
});
|
|
1930
2222
|
|
|
1931
2223
|
// Stop video track in audio only mode
|
|
1932
2224
|
if (isAudioOnly && kind === 'video') {
|
|
@@ -1936,15 +2228,21 @@ export default class WebRTCClient extends Emitter {
|
|
|
1936
2228
|
this.eventEmitter.emit(ON_TRACK, session, event);
|
|
1937
2229
|
};
|
|
1938
2230
|
|
|
2231
|
+
// @ts-ignore
|
|
1939
2232
|
if (session.sessionDescriptionHandler.peerConnection) {
|
|
2233
|
+
// @ts-ignore
|
|
1940
2234
|
session.sessionDescriptionHandler.peerConnection.addEventListener('track', onTrack);
|
|
1941
2235
|
}
|
|
1942
2236
|
|
|
2237
|
+
// @ts-ignore
|
|
1943
2238
|
session.sessionDescriptionHandler.remoteMediaStream.onaddtrack = onTrack;
|
|
1944
2239
|
|
|
1945
2240
|
if (pc) {
|
|
1946
2241
|
pc.oniceconnectionstatechange = () => {
|
|
1947
|
-
logger.info('on ice connection state changed', {
|
|
2242
|
+
logger.info('on ice connection state changed', {
|
|
2243
|
+
state: pc.iceConnectionState,
|
|
2244
|
+
});
|
|
2245
|
+
|
|
1948
2246
|
if (pc.iceConnectionState === 'disconnected') {
|
|
1949
2247
|
this.eventEmitter.emit(ON_DISCONNECTED);
|
|
1950
2248
|
}
|
|
@@ -1958,17 +2256,19 @@ export default class WebRTCClient extends Emitter {
|
|
|
1958
2256
|
this._startSendingStats(session);
|
|
1959
2257
|
}
|
|
1960
2258
|
|
|
1961
|
-
_isAudioOnly(session:
|
|
1962
|
-
return session.sessionDescriptionHandlerModifiersReInvite.find(modifier => modifier === stripVideo);
|
|
2259
|
+
_isAudioOnly(session: Inviter | Invitation): boolean {
|
|
2260
|
+
return Boolean(session.sessionDescriptionHandlerModifiersReInvite.find(modifier => modifier === stripVideo));
|
|
1963
2261
|
}
|
|
1964
2262
|
|
|
1965
|
-
_setupMedias(session:
|
|
2263
|
+
_setupMedias(session: Inviter | Invitation, newStream: MediaStream | null | undefined = null): void {
|
|
1966
2264
|
// Safari hack, because you cannot call .play() from a non user action
|
|
1967
2265
|
const sessionId = this.getSipSessionId(session);
|
|
1968
2266
|
const isConference = this.isConference(sessionId);
|
|
1969
2267
|
|
|
1970
2268
|
if (sessionId in this.audioElements) {
|
|
1971
|
-
logger.info('html element already exists for session', {
|
|
2269
|
+
logger.info('html element already exists for session', {
|
|
2270
|
+
sessionId,
|
|
2271
|
+
});
|
|
1972
2272
|
return;
|
|
1973
2273
|
}
|
|
1974
2274
|
|
|
@@ -1977,10 +2277,11 @@ export default class WebRTCClient extends Emitter {
|
|
|
1977
2277
|
}
|
|
1978
2278
|
|
|
1979
2279
|
const audioElement = this.audioElements[sessionId];
|
|
2280
|
+
// @ts-ignore
|
|
1980
2281
|
const sipSession = this.sipSessions[session.callId];
|
|
1981
2282
|
const removeStream = this.getRemoteStream(sessionId);
|
|
1982
|
-
|
|
1983
|
-
|
|
2283
|
+
// @ts-ignore
|
|
2284
|
+
const earlyStream = sipSession && sipSession.sessionDescriptionHandler ? sipSession.sessionDescriptionHandler.remoteMediaStream : null;
|
|
1984
2285
|
const stream = newStream || removeStream || earlyStream;
|
|
1985
2286
|
|
|
1986
2287
|
if (!this._isWeb() || !stream) {
|
|
@@ -1995,30 +2296,34 @@ export default class WebRTCClient extends Emitter {
|
|
|
1995
2296
|
if (audioElement.currentTime > 0 && !audioElement.paused && !audioElement.ended && audioElement.readyState > 2) {
|
|
1996
2297
|
audioElement.pause();
|
|
1997
2298
|
}
|
|
2299
|
+
|
|
1998
2300
|
audioElement.srcObject = stream;
|
|
1999
2301
|
audioElement.volume = this.audioOutputVolume;
|
|
2000
2302
|
audioElement.play().catch(() => {});
|
|
2001
2303
|
}
|
|
2002
2304
|
|
|
2003
|
-
_cleanupMedia(session
|
|
2305
|
+
_cleanupMedia(session?: Inviter | Invitation): void {
|
|
2004
2306
|
const sessionId = this.getSipSessionId(session);
|
|
2005
2307
|
const localStream = this.getLocalStream(sessionId);
|
|
2308
|
+
|
|
2006
2309
|
if (localStream) {
|
|
2007
2310
|
this._cleanupStream(localStream);
|
|
2008
2311
|
}
|
|
2009
2312
|
|
|
2010
|
-
const cleanLocalElement = id => {
|
|
2313
|
+
const cleanLocalElement = (id: string) => {
|
|
2011
2314
|
const element = this.audioElements[id];
|
|
2315
|
+
|
|
2012
2316
|
if (!element) {
|
|
2013
2317
|
return;
|
|
2014
2318
|
}
|
|
2015
2319
|
|
|
2016
2320
|
element.pause();
|
|
2321
|
+
|
|
2017
2322
|
if (element.parentNode) {
|
|
2018
2323
|
element.parentNode.removeChild(element);
|
|
2019
2324
|
}
|
|
2020
|
-
element.srcObject = null;
|
|
2021
2325
|
|
|
2326
|
+
element.srcObject = null;
|
|
2022
2327
|
delete this.audioElements[id];
|
|
2023
2328
|
};
|
|
2024
2329
|
|
|
@@ -2031,25 +2336,27 @@ export default class WebRTCClient extends Emitter {
|
|
|
2031
2336
|
}
|
|
2032
2337
|
}
|
|
2033
2338
|
|
|
2034
|
-
_cleanupStream(stream: MediaStream) {
|
|
2339
|
+
_cleanupStream(stream: MediaStream): void {
|
|
2035
2340
|
stream.getTracks().forEach(track => track.stop());
|
|
2036
2341
|
}
|
|
2037
2342
|
|
|
2038
|
-
_toggleAudio(session: Inviter, muteAudio: boolean) {
|
|
2343
|
+
_toggleAudio(session: Inviter | Invitation, muteAudio: boolean): void {
|
|
2344
|
+
// @ts-ignore
|
|
2039
2345
|
const pc = session.sessionDescriptionHandler ? session.sessionDescriptionHandler.peerConnection : null;
|
|
2346
|
+
|
|
2040
2347
|
if (!pc) {
|
|
2041
2348
|
return;
|
|
2042
2349
|
}
|
|
2043
2350
|
|
|
2044
2351
|
if (pc.getSenders) {
|
|
2045
|
-
pc.getSenders().forEach(sender => {
|
|
2352
|
+
pc.getSenders().forEach((sender: any) => {
|
|
2046
2353
|
if (sender && sender.track && sender.track.kind === 'audio') {
|
|
2047
2354
|
// eslint-disable-next-line
|
|
2048
2355
|
sender.track.enabled = !muteAudio;
|
|
2049
2356
|
}
|
|
2050
2357
|
});
|
|
2051
2358
|
} else {
|
|
2052
|
-
pc.getLocalStreams().forEach(stream => {
|
|
2359
|
+
pc.getLocalStreams().forEach((stream: MediaStream) => {
|
|
2053
2360
|
stream.getAudioTracks().forEach(track => {
|
|
2054
2361
|
// eslint-disable-next-line
|
|
2055
2362
|
track.enabled = !muteAudio;
|
|
@@ -2058,18 +2365,19 @@ export default class WebRTCClient extends Emitter {
|
|
|
2058
2365
|
}
|
|
2059
2366
|
}
|
|
2060
2367
|
|
|
2061
|
-
_toggleVideo(session: Inviter, muteCamera: boolean) {
|
|
2062
|
-
|
|
2368
|
+
_toggleVideo(session: Inviter | Invitation, muteCamera: boolean): void {
|
|
2369
|
+
// @ts-ignore
|
|
2370
|
+
const pc = session.sessionDescriptionHandler?.peerConnection;
|
|
2063
2371
|
|
|
2064
2372
|
if (pc.getSenders) {
|
|
2065
|
-
pc.getSenders().forEach(sender => {
|
|
2373
|
+
pc.getSenders().forEach((sender: any) => {
|
|
2066
2374
|
if (sender && sender.track && sender.track.kind === 'video') {
|
|
2067
2375
|
// eslint-disable-next-line
|
|
2068
2376
|
sender.track.enabled = !muteCamera;
|
|
2069
2377
|
}
|
|
2070
2378
|
});
|
|
2071
2379
|
} else {
|
|
2072
|
-
pc.getLocalStreams().forEach(stream => {
|
|
2380
|
+
pc.getLocalStreams().forEach((stream: MediaStream) => {
|
|
2073
2381
|
stream.getVideoTracks().forEach(track => {
|
|
2074
2382
|
// eslint-disable-next-line
|
|
2075
2383
|
track.enabled = !muteCamera;
|
|
@@ -2081,15 +2389,18 @@ export default class WebRTCClient extends Emitter {
|
|
|
2081
2389
|
/**
|
|
2082
2390
|
* @param pc RTCPeerConnection
|
|
2083
2391
|
*/
|
|
2084
|
-
_getRemoteStream(pc: any) {
|
|
2085
|
-
let remoteStream;
|
|
2392
|
+
_getRemoteStream(pc: any): MediaStream | null {
|
|
2393
|
+
let remoteStream: MediaStream | null = null;
|
|
2086
2394
|
|
|
2087
2395
|
if (pc && pc.getReceivers) {
|
|
2088
|
-
remoteStream = typeof global !== 'undefined' && global.window && global.window.MediaStream
|
|
2089
|
-
|
|
2090
|
-
pc.getReceivers().forEach(receiver => {
|
|
2091
|
-
const {
|
|
2092
|
-
|
|
2396
|
+
remoteStream = typeof global !== 'undefined' && global.window && global.window.MediaStream ? new global.window.MediaStream() : new window.MediaStream();
|
|
2397
|
+
|
|
2398
|
+
pc.getReceivers().forEach((receiver: any) => {
|
|
2399
|
+
const {
|
|
2400
|
+
track,
|
|
2401
|
+
} = receiver;
|
|
2402
|
+
|
|
2403
|
+
if (track && remoteStream) {
|
|
2093
2404
|
remoteStream.addTrack(track);
|
|
2094
2405
|
}
|
|
2095
2406
|
});
|
|
@@ -2100,24 +2411,31 @@ export default class WebRTCClient extends Emitter {
|
|
|
2100
2411
|
return remoteStream;
|
|
2101
2412
|
}
|
|
2102
2413
|
|
|
2103
|
-
_cleanupRegister() {
|
|
2414
|
+
_cleanupRegister(): void {
|
|
2104
2415
|
if (this.registerer) {
|
|
2416
|
+
// @ts-ignore
|
|
2105
2417
|
this.registerer.stateChange.removeAllListeners();
|
|
2106
2418
|
this.registerer = null;
|
|
2107
2419
|
}
|
|
2108
2420
|
}
|
|
2109
2421
|
|
|
2110
|
-
_startSendingStats(session:
|
|
2422
|
+
_startSendingStats(session: Inviter | Invitation): void {
|
|
2423
|
+
// @ts-ignore
|
|
2111
2424
|
const pc = session.sessionDescriptionHandler.peerConnection;
|
|
2425
|
+
|
|
2112
2426
|
if (!pc) {
|
|
2113
2427
|
return;
|
|
2114
2428
|
}
|
|
2115
|
-
const sessionId = this.getSipSessionId(session);
|
|
2116
2429
|
|
|
2117
|
-
|
|
2118
|
-
|
|
2430
|
+
const sessionId = this.getSipSessionId(session);
|
|
2431
|
+
getStats(pc, (result: Record<string, any>) => {
|
|
2432
|
+
const {
|
|
2433
|
+
results,
|
|
2434
|
+
internal,
|
|
2435
|
+
nomore,
|
|
2436
|
+
...stats
|
|
2437
|
+
} = result;
|
|
2119
2438
|
this.statsIntervals[sessionId] = nomore;
|
|
2120
|
-
|
|
2121
2439
|
statsLogger.trace('stats', {
|
|
2122
2440
|
sessionId,
|
|
2123
2441
|
...stats,
|
|
@@ -2125,27 +2443,35 @@ export default class WebRTCClient extends Emitter {
|
|
|
2125
2443
|
}, SEND_STATS_DELAY);
|
|
2126
2444
|
}
|
|
2127
2445
|
|
|
2128
|
-
_stopSendingStats(session:
|
|
2446
|
+
_stopSendingStats(session: Invitation | Inviter): void {
|
|
2129
2447
|
const sessionId = this.getSipSessionId(session);
|
|
2130
|
-
logger.trace('Check for stopping stats', {
|
|
2448
|
+
logger.trace('Check for stopping stats', {
|
|
2449
|
+
sessionId,
|
|
2450
|
+
ids: Object.keys(this.statsIntervals),
|
|
2451
|
+
});
|
|
2131
2452
|
|
|
2132
2453
|
if (sessionId in this.statsIntervals) {
|
|
2133
|
-
logger.trace('Stop sending stats for call', {
|
|
2454
|
+
logger.trace('Stop sending stats for call', {
|
|
2455
|
+
sessionId,
|
|
2456
|
+
});
|
|
2134
2457
|
this.statsIntervals[sessionId]();
|
|
2135
2458
|
delete this.statsIntervals[sessionId];
|
|
2136
2459
|
}
|
|
2137
2460
|
}
|
|
2138
2461
|
|
|
2139
|
-
_makeURI(target: string): URI {
|
|
2462
|
+
_makeURI(target: string): URI | undefined {
|
|
2140
2463
|
return UserAgent.makeURI(`sip:${target}@${this.config.host}`);
|
|
2141
2464
|
}
|
|
2142
2465
|
|
|
2143
|
-
async _disconnectTransport(force
|
|
2466
|
+
async _disconnectTransport(force = false) {
|
|
2144
2467
|
if (force && this.userAgent && this.userAgent.transport) {
|
|
2145
2468
|
// Bypass sip.js state machine that prevent to close WS with the state `Connecting`
|
|
2469
|
+
// @ts-ignore
|
|
2146
2470
|
this.userAgent.transport.disconnectResolve = () => {};
|
|
2147
2471
|
|
|
2472
|
+
// @ts-ignore
|
|
2148
2473
|
if (this.userAgent.transport._ws) {
|
|
2474
|
+
// @ts-ignore
|
|
2149
2475
|
this.userAgent.transport._ws.close(1000);
|
|
2150
2476
|
}
|
|
2151
2477
|
|
|
@@ -2153,24 +2479,25 @@ export default class WebRTCClient extends Emitter {
|
|
|
2153
2479
|
}
|
|
2154
2480
|
|
|
2155
2481
|
// Check if `disconnectPromise` is not present to avoid `Disconnect promise must not be defined` errors.
|
|
2482
|
+
// @ts-ignore
|
|
2156
2483
|
if (this.userAgent && this.userAgent.transport && !this.userAgent.transport.disconnectPromise) {
|
|
2157
2484
|
try {
|
|
2158
2485
|
await this.userAgent.transport.disconnect();
|
|
2159
|
-
} catch (e) {
|
|
2486
|
+
} catch (e: any) {
|
|
2160
2487
|
logger.error('WebRTC transport disconnect, error', e);
|
|
2161
2488
|
}
|
|
2162
2489
|
}
|
|
2163
2490
|
}
|
|
2164
2491
|
|
|
2165
|
-
async _fetchNetworkStats(sessionId: string) {
|
|
2492
|
+
async _fetchNetworkStats(sessionId: string): Promise<Record<string, any> | null | undefined> {
|
|
2166
2493
|
const session = this.getSipSession(sessionId);
|
|
2167
|
-
|
|
2168
2494
|
const stats = session ? await this.getStats(session) : null;
|
|
2495
|
+
|
|
2169
2496
|
if (!stats || !(sessionId in this.sessionNetworkStats)) {
|
|
2170
|
-
return;
|
|
2497
|
+
return Promise.resolve(null);
|
|
2171
2498
|
}
|
|
2172
2499
|
|
|
2173
|
-
const networkStats:
|
|
2500
|
+
const networkStats: Record<string, any> = {
|
|
2174
2501
|
audioBytesSent: 0,
|
|
2175
2502
|
videoBytesSent: 0,
|
|
2176
2503
|
videoBytesReceived: 0,
|
|
@@ -2187,70 +2514,77 @@ export default class WebRTCClient extends Emitter {
|
|
|
2187
2514
|
const lastTransportSent = lastNetworkStats ? lastNetworkStats.transportSent : 0;
|
|
2188
2515
|
const lastTransportReceived = lastNetworkStats ? lastNetworkStats.transportReceived : 0;
|
|
2189
2516
|
let audioBytesSent = 0; // content + header
|
|
2517
|
+
|
|
2190
2518
|
let audioBytesReceived = 0; // content + header
|
|
2519
|
+
|
|
2191
2520
|
let audioContentSent = 0; // useful to detect blank call
|
|
2521
|
+
|
|
2192
2522
|
let audioContentReceived = 0;
|
|
2193
2523
|
let videoBytesSent = 0;
|
|
2194
2524
|
let videoBytesReceived = 0;
|
|
2195
2525
|
let transportSent = 0;
|
|
2196
2526
|
let transportReceived = 0;
|
|
2197
2527
|
let packetsLost = 0;
|
|
2198
|
-
|
|
2199
2528
|
stats.forEach(report => {
|
|
2200
2529
|
if (report.type === 'outbound-rtp' && report.kind === 'audio') {
|
|
2201
2530
|
audioBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
2202
2531
|
audioContentSent += Number(report.bytesSent);
|
|
2203
2532
|
}
|
|
2533
|
+
|
|
2204
2534
|
if (report.type === 'remote-outbound-rtp' && report.kind === 'audio') {
|
|
2205
2535
|
audioBytesSent += Number(report.bytesSent);
|
|
2206
2536
|
}
|
|
2537
|
+
|
|
2207
2538
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
2208
2539
|
videoBytesSent += Number(report.bytesSent) + Number(report.headerBytesSent);
|
|
2209
2540
|
}
|
|
2541
|
+
|
|
2210
2542
|
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
|
|
2211
2543
|
packetsLost += Number(report.packetsLost);
|
|
2212
2544
|
networkStats.packetsReceived = Number(report.packetsReceived);
|
|
2213
2545
|
audioBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
2214
2546
|
audioContentReceived += Number(report.bytesReceived);
|
|
2215
2547
|
}
|
|
2548
|
+
|
|
2216
2549
|
if (report.type === 'inbound-rtp' && report.kind === 'video') {
|
|
2217
2550
|
videoBytesReceived += Number(report.bytesReceived) + Number(report.headerBytesReceived);
|
|
2218
2551
|
}
|
|
2552
|
+
|
|
2219
2553
|
if (report.type === 'outbound-rtp' && report.kind === 'video') {
|
|
2220
2554
|
if ('framesPerSecond' in report) {
|
|
2221
2555
|
networkStats.framesPerSecond = Number(report.framesPerSecond);
|
|
2222
2556
|
}
|
|
2557
|
+
|
|
2223
2558
|
if ('framerateMean' in report) {
|
|
2224
2559
|
// framerateMean is only available in FF
|
|
2225
2560
|
networkStats.framesPerSecond = Math.round(report.framerateMean);
|
|
2226
2561
|
}
|
|
2227
2562
|
}
|
|
2563
|
+
|
|
2228
2564
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'audio') {
|
|
2229
2565
|
packetsLost += Number(report.packetsLost);
|
|
2230
2566
|
networkStats.roundTripTime = Number(report.roundTripTime);
|
|
2231
2567
|
networkStats.jitter = Number(report.jitter);
|
|
2232
2568
|
}
|
|
2569
|
+
|
|
2233
2570
|
if (report.type === 'remote-inbound-rtp' && report.kind === 'video') {
|
|
2234
2571
|
packetsLost += Number(report.packetsLost);
|
|
2235
2572
|
}
|
|
2573
|
+
|
|
2236
2574
|
if (report.type === 'transport') {
|
|
2237
2575
|
transportSent += Number(report.bytesSent);
|
|
2238
2576
|
transportReceived += Number(report.bytesReceived);
|
|
2239
2577
|
}
|
|
2240
2578
|
});
|
|
2241
|
-
|
|
2242
2579
|
networkStats.packetsLost = packetsLost;
|
|
2243
|
-
|
|
2244
2580
|
networkStats.totalAudioBytesSent = audioBytesSent;
|
|
2245
2581
|
networkStats.audioBytesSent = audioBytesSent - lastAudioSent;
|
|
2246
2582
|
networkStats.totalAudioBytesReceived = audioBytesReceived - lastAudioReceived;
|
|
2247
2583
|
networkStats.audioBytesReceived = audioBytesReceived;
|
|
2248
|
-
|
|
2249
2584
|
networkStats.totalAudioContentSent = audioContentSent;
|
|
2250
2585
|
networkStats.audioContentSent = audioContentSent - lastAudioContentSent;
|
|
2251
2586
|
networkStats.totalAudioBytesReceived = audioContentReceived - lastAudioContentReceived;
|
|
2252
2587
|
networkStats.audioContentReceived = audioContentReceived;
|
|
2253
|
-
|
|
2254
2588
|
networkStats.totalVideoBytesSent = videoBytesSent;
|
|
2255
2589
|
networkStats.videoBytesSent = videoBytesSent - lastVideoSent;
|
|
2256
2590
|
networkStats.totalVideoBytesReceived = videoBytesReceived;
|
|
@@ -2259,13 +2593,82 @@ export default class WebRTCClient extends Emitter {
|
|
|
2259
2593
|
networkStats.transportSent = transportSent;
|
|
2260
2594
|
networkStats.totalTransportReceived = transportReceived;
|
|
2261
2595
|
networkStats.transportReceived = transportReceived - lastTransportReceived;
|
|
2262
|
-
|
|
2263
|
-
networkStats.bandwidth = networkStats.audioBytesSent + networkStats.audioBytesReceived
|
|
2264
|
-
+ networkStats.videoBytesSent + networkStats.videoBytesReceived + networkStats.transportReceived
|
|
2265
|
-
+ networkStats.transportSent;
|
|
2266
|
-
|
|
2596
|
+
networkStats.bandwidth = networkStats.audioBytesSent + networkStats.audioBytesReceived + networkStats.videoBytesSent + networkStats.videoBytesReceived + networkStats.transportReceived + networkStats.transportSent;
|
|
2267
2597
|
this.eventEmitter.emit(ON_NETWORK_STATS, session, networkStats, this.sessionNetworkStats[sessionId]);
|
|
2268
2598
|
this.sessionNetworkStats[sessionId].push(networkStats);
|
|
2269
2599
|
}
|
|
2270
2600
|
|
|
2601
|
+
async _accept(session: Invitation, options: InvitationAcceptOptions = {}) {
|
|
2602
|
+
if (session.state === SessionState.Terminated || session.state === SessionState.Terminating) {
|
|
2603
|
+
const error = 'Trying to accept a terminated sipSession.';
|
|
2604
|
+
logger.warn(error, { state: session.state, sessionId: session.id });
|
|
2605
|
+
throw new Error(error);
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
if (session.state !== SessionState.Initial) {
|
|
2609
|
+
const error = 'Trying to accept a non Initial sipSession.';
|
|
2610
|
+
logger.warn(error, { state: session.state, sessionId: session.id });
|
|
2611
|
+
throw new Error(error);
|
|
2612
|
+
}
|
|
2613
|
+
|
|
2614
|
+
// @ts-ignore
|
|
2615
|
+
if (!session.incomingInviteRequest.acceptable) {
|
|
2616
|
+
const error = 'Trying to reject a non `acceptable` session';
|
|
2617
|
+
logger.warn(error, { state: session.state, sessionId: session.id });
|
|
2618
|
+
throw new Error(error);
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
try {
|
|
2622
|
+
return await session.accept(options);
|
|
2623
|
+
} catch (e) {
|
|
2624
|
+
logger.warn('Session accept, error', e);
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
async _reject(session: Invitation, options: InvitationRejectOptions = {}) {
|
|
2629
|
+
if (session.state !== SessionState.Initial && session.state !== SessionState.Establishing) {
|
|
2630
|
+
logger.warn('Trying to reject a session in a wrong state', { state: session.state, sessionId: session.id });
|
|
2631
|
+
return;
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
// @ts-ignore
|
|
2635
|
+
if (!session.incomingInviteRequest.rejectable) {
|
|
2636
|
+
logger.warn('Trying to reject a non `rejectable` session', { state: session.state, sessionId: session.id });
|
|
2637
|
+
return;
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
try {
|
|
2641
|
+
return await session.reject(options);
|
|
2642
|
+
} catch (e) {
|
|
2643
|
+
logger.warn('Session reject, error', e);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
async _cancel(session: Inviter, options: InviterCancelOptions = {}) {
|
|
2648
|
+
if (session.state !== SessionState.Initial && session.state !== SessionState.Establishing) {
|
|
2649
|
+
logger.warn('Trying to cancel a session in a wrong state', { state: session.state, sessionId: session.id });
|
|
2650
|
+
return;
|
|
2651
|
+
}
|
|
2652
|
+
|
|
2653
|
+
try {
|
|
2654
|
+
return await session.cancel(options);
|
|
2655
|
+
} catch (e) {
|
|
2656
|
+
logger.warn('Session cancel, error', e);
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
async _bye(session: Invitation | Inviter, options: SessionByeOptions = {}) {
|
|
2661
|
+
if (session.state !== SessionState.Established) {
|
|
2662
|
+
logger.warn('Trying to end a session in a wrong state', { state: session.state, sessionId: session.id });
|
|
2663
|
+
return null;
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2666
|
+
try {
|
|
2667
|
+
return await session.bye(options);
|
|
2668
|
+
} catch (e) {
|
|
2669
|
+
logger.warn('Session bye, error', e);
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
return null;
|
|
2673
|
+
}
|
|
2271
2674
|
}
|