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