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