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