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