@techsee/techsee-media-service 0.6.0 → 0.6.1-alpha.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/lib/LocalStreamManager.d.ts +21 -0
- package/lib/LocalStreamManager.d.ts.map +1 -0
- package/lib/LocalStreamManager.js +268 -0
- package/lib/LocalStreamManager.js.map +1 -0
- package/lib/MediaConstants.d.ts +52 -0
- package/lib/MediaConstants.d.ts.map +1 -0
- package/lib/MediaConstants.js +68 -0
- package/lib/MediaConstants.js.map +1 -0
- package/lib/MediaContracts.d.ts +122 -0
- package/lib/MediaContracts.d.ts.map +1 -0
- package/lib/MediaContracts.js +6 -0
- package/lib/MediaContracts.js.map +1 -0
- package/lib/MediaPublisher.d.ts +14 -0
- package/lib/MediaPublisher.d.ts.map +1 -0
- package/lib/MediaPublisher.js +43 -0
- package/lib/MediaPublisher.js.map +1 -0
- package/lib/MediaServiceBase.d.ts +64 -0
- package/lib/MediaServiceBase.d.ts.map +1 -0
- package/lib/MediaServiceBase.js +591 -0
- package/lib/MediaServiceBase.js.map +1 -0
- package/lib/MediaSubscriber.d.ts +35 -0
- package/lib/MediaSubscriber.d.ts.map +1 -0
- package/lib/MediaSubscriber.js +202 -0
- package/lib/MediaSubscriber.js.map +1 -0
- package/lib/Session/SessionOpentok.v3.d.ts +33 -0
- package/lib/Session/SessionOpentok.v3.d.ts.map +1 -0
- package/lib/Session/SessionOpentok.v3.js +287 -0
- package/lib/Session/SessionOpentok.v3.js.map +1 -0
- package/lib/Session/SessionTurn.v3.d.ts +42 -0
- package/lib/Session/SessionTurn.v3.d.ts.map +1 -0
- package/lib/Session/SessionTurn.v3.js +442 -0
- package/lib/Session/SessionTurn.v3.js.map +1 -0
- package/lib/Session/TurnConstants.d.ts +18 -0
- package/lib/Session/TurnConstants.d.ts.map +1 -0
- package/lib/Session/TurnConstants.js +36 -0
- package/lib/Session/TurnConstants.js.map +1 -0
- package/lib/TechseeMediaStream.d.ts +14 -0
- package/lib/TechseeMediaStream.d.ts.map +1 -0
- package/lib/TechseeMediaStream.js +58 -0
- package/lib/TechseeMediaStream.js.map +1 -0
- package/lib/Utils/Compatibility.d.ts +11 -0
- package/lib/Utils/Compatibility.d.ts.map +1 -0
- package/lib/Utils/Compatibility.js +71 -0
- package/lib/Utils/Compatibility.js.map +1 -0
- package/lib/Utils/MediaDomUtils.d.ts +4 -0
- package/lib/Utils/MediaDomUtils.d.ts.map +1 -0
- package/lib/Utils/MediaDomUtils.js +200 -0
- package/lib/Utils/MediaDomUtils.js.map +1 -0
- package/lib/Utils/MediaTracer.d.ts +3 -0
- package/lib/Utils/MediaTracer.d.ts.map +1 -0
- package/lib/Utils/MediaTracer.js +12 -0
- package/lib/Utils/MediaTracer.js.map +1 -0
- package/lib/oldCode/constants.js.map +1 -0
- package/lib/oldCode/event-emitter.js.map +1 -0
- package/lib/oldCode/index.js.map +1 -0
- package/lib/oldCode/opentok/session.js.map +1 -0
- package/lib/oldCode/opentok/stream.js.map +1 -0
- package/lib/oldCode/publisher.js.map +1 -0
- package/lib/oldCode/qos/raw-qos.js.map +1 -0
- package/lib/oldCode/service.js.map +1 -0
- package/lib/oldCode/session.js.map +1 -0
- package/lib/oldCode/stream.js.map +1 -0
- package/lib/oldCode/subscriber.js.map +1 -0
- package/lib/oldCode/tracer.d.ts.map +1 -0
- package/lib/oldCode/tracer.js.map +1 -0
- package/lib/oldCode/utils/ImageFixer.d.ts.map +1 -0
- package/lib/oldCode/utils/ImageFixer.js.map +1 -0
- package/lib/oldCode/webrtc/constants.js.map +1 -0
- package/lib/oldCode/webrtc/helper.js.map +1 -0
- package/lib/oldCode/webrtc/session-kms.js.map +1 -0
- package/lib/oldCode/webrtc/session-loopback.js.map +1 -0
- package/lib/oldCode/webrtc/session-turn.js.map +1 -0
- package/lib/{webrtc → oldCode/webrtc}/session-turn.v2.js +0 -2
- package/lib/oldCode/webrtc/session-turn.v2.js.map +1 -0
- package/lib/oldCode/webrtc/session.js.map +1 -0
- package/lib/oldCode/webrtc/stream.js.map +1 -0
- package/lib/oldCode/webrtc/temasys/adapter-loader.js.map +1 -0
- package/lib/oldCode/webrtc/temasys/adapter.js.map +1 -0
- package/lib/oldCode/webrtc/webrtc-ie-shim.js.map +1 -0
- package/lib/webrtc-ie-shim.js +3218 -0
- package/lib/webrtc-ie-shim.js.map +1 -0
- package/package.json +4 -4
- package/lib/constants.js.map +0 -1
- package/lib/event-emitter.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/opentok/session.js.map +0 -1
- package/lib/opentok/stream.js.map +0 -1
- package/lib/publisher.js.map +0 -1
- package/lib/qos/raw-qos.js.map +0 -1
- package/lib/service.js.map +0 -1
- package/lib/session.js.map +0 -1
- package/lib/stream.js.map +0 -1
- package/lib/subscriber.js.map +0 -1
- package/lib/tracer.d.ts.map +0 -1
- package/lib/tracer.js.map +0 -1
- package/lib/utils/ImageFixer.d.ts.map +0 -1
- package/lib/utils/ImageFixer.js.map +0 -1
- package/lib/webrtc/constants.js.map +0 -1
- package/lib/webrtc/helper.js.map +0 -1
- package/lib/webrtc/session-kms.js.map +0 -1
- package/lib/webrtc/session-loopback.js.map +0 -1
- package/lib/webrtc/session-turn.js.map +0 -1
- package/lib/webrtc/session-turn.v2.js.map +0 -1
- package/lib/webrtc/session.js.map +0 -1
- package/lib/webrtc/stream.js.map +0 -1
- package/lib/webrtc/temasys/adapter-loader.js.map +0 -1
- package/lib/webrtc/temasys/adapter.js.map +0 -1
- package/lib/webrtc/webrtc-ie-shim.js.map +0 -1
- /package/lib/{constants.js → oldCode/constants.js} +0 -0
- /package/lib/{event-emitter.js → oldCode/event-emitter.js} +0 -0
- /package/lib/{index.js → oldCode/index.js} +0 -0
- /package/lib/{opentok → oldCode/opentok}/session.js +0 -0
- /package/lib/{opentok → oldCode/opentok}/stream.js +0 -0
- /package/lib/{publisher.js → oldCode/publisher.js} +0 -0
- /package/lib/{qos → oldCode/qos}/raw-qos.js +0 -0
- /package/lib/{service.js → oldCode/service.js} +0 -0
- /package/lib/{session.js → oldCode/session.js} +0 -0
- /package/lib/{stream.js → oldCode/stream.js} +0 -0
- /package/lib/{subscriber.js → oldCode/subscriber.js} +0 -0
- /package/lib/{tracer.d.ts → oldCode/tracer.d.ts} +0 -0
- /package/lib/{tracer.js → oldCode/tracer.js} +0 -0
- /package/lib/{utils → oldCode/utils}/ImageFixer.d.ts +0 -0
- /package/lib/{utils → oldCode/utils}/ImageFixer.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/constants.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/helper.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/session-kms.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/session-loopback.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/session-turn.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/session.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/stream.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/temasys/adapter-loader.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/temasys/adapter.js +0 -0
- /package/lib/{webrtc → oldCode/webrtc}/webrtc-ie-shim.js +0 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
var MediaConstants_1 = require("../MediaConstants");
|
|
5
|
+
var MediaTracer_1 = require("../Utils/MediaTracer");
|
|
6
|
+
var guards_1 = require("@techsee/techsee-common/lib/core/guards");
|
|
7
|
+
var trace = MediaTracer_1.getMediaTracer('OpenTokSession');
|
|
8
|
+
//Currently this version supports subscribing only. Publishing will be implemented as needed.
|
|
9
|
+
var OpentokSessionV3 = /** @class */function () {
|
|
10
|
+
function OpentokSessionV3(sessionParams, streamFactory) {
|
|
11
|
+
this._peerConnections = new Map();
|
|
12
|
+
this._session = null;
|
|
13
|
+
this._sessionParams = sessionParams;
|
|
14
|
+
this._sessionStreamsManager = streamFactory;
|
|
15
|
+
this._credentials = sessionParams.credentials;
|
|
16
|
+
this.connect = this.connect.bind(this);
|
|
17
|
+
this.disconnect = this.disconnect.bind(this);
|
|
18
|
+
this.onMediaStreamDestroyed = this.onMediaStreamDestroyed.bind(this);
|
|
19
|
+
this.onMediaStreamRenewed = this.onMediaStreamRenewed.bind(this);
|
|
20
|
+
this.createStreamForPublishing = this.createStreamForPublishing.bind(this);
|
|
21
|
+
this.createMediaPublisher = this.createMediaPublisher.bind(this);
|
|
22
|
+
this.clearPeerConnections = this.clearPeerConnections.bind(this);
|
|
23
|
+
this.connectionCreatedHandler = this.connectionCreatedHandler.bind(this);
|
|
24
|
+
this.connectionDestroyedHandler = this.connectionDestroyedHandler.bind(this);
|
|
25
|
+
this.streamCreatedHandler = this.streamCreatedHandler.bind(this);
|
|
26
|
+
this.streamDestroyedHandler = this.streamDestroyedHandler.bind(this);
|
|
27
|
+
}
|
|
28
|
+
Object.defineProperty(OpentokSessionV3.prototype, "id", {
|
|
29
|
+
get: function get() {
|
|
30
|
+
return this._session && this._session.sessionId ? this._session.sessionId : '';
|
|
31
|
+
},
|
|
32
|
+
enumerable: true,
|
|
33
|
+
configurable: true
|
|
34
|
+
});
|
|
35
|
+
Object.defineProperty(OpentokSessionV3.prototype, "ownPeerId", {
|
|
36
|
+
get: function get() {
|
|
37
|
+
return this._session && this._session.connection ? this._session.connection.connectionId : '';
|
|
38
|
+
},
|
|
39
|
+
enumerable: true,
|
|
40
|
+
configurable: true
|
|
41
|
+
});
|
|
42
|
+
OpentokSessionV3.prototype.connect = function () {
|
|
43
|
+
var _this = this;
|
|
44
|
+
trace.info('Connect to session');
|
|
45
|
+
if (this._session) {
|
|
46
|
+
trace.error('Session already exists');
|
|
47
|
+
return Promise.reject('Cannot connect to session while another session is active');
|
|
48
|
+
}
|
|
49
|
+
return new Promise(function (resolve, reject) {
|
|
50
|
+
var handleError = function handleError(error) {
|
|
51
|
+
_this._session && _this._session.off();
|
|
52
|
+
_this._session = null;
|
|
53
|
+
trace.error('handleConnect error:', error);
|
|
54
|
+
reject(error);
|
|
55
|
+
};
|
|
56
|
+
var _a = _this._sessionParams.credentials,
|
|
57
|
+
apiKey = _a.apiKey,
|
|
58
|
+
sessionId = _a.sessionId;
|
|
59
|
+
_this._session = window.OTSESSION = window.OT.initSession(apiKey, sessionId);
|
|
60
|
+
_this._session.on('connectionCreated', _this.connectionCreatedHandler);
|
|
61
|
+
_this._session.on('connectionDestroyed', _this.connectionDestroyedHandler);
|
|
62
|
+
_this._session.on('streamCreated', _this.streamCreatedHandler);
|
|
63
|
+
_this._session.on('streamDestroyed', _this.streamDestroyedHandler);
|
|
64
|
+
var connectHandler = function connectHandler(error) {
|
|
65
|
+
if (error) {
|
|
66
|
+
handleError(error);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
resolve();
|
|
70
|
+
};
|
|
71
|
+
_this._session.connect(_this._credentials.token, connectHandler);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
OpentokSessionV3.prototype.disconnect = function () {
|
|
75
|
+
var _this = this;
|
|
76
|
+
//TODO - Alex: Implement destroying all publishers (by opentok docs)
|
|
77
|
+
//Create a method destroy publisher (or publishers can treated the same as "peerConnections"?
|
|
78
|
+
return new Promise(function (resolve) {
|
|
79
|
+
var currentSession = _this._session;
|
|
80
|
+
_this._session = null;
|
|
81
|
+
_this._peerConnections.forEach(function (peerConnection) {
|
|
82
|
+
_this.destroyPeerConnection(peerConnection);
|
|
83
|
+
});
|
|
84
|
+
if (!currentSession) {
|
|
85
|
+
trace.info('No active session - resolving');
|
|
86
|
+
resolve();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
currentSession.off();
|
|
90
|
+
currentSession.disconnect();
|
|
91
|
+
resolve();
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
OpentokSessionV3.prototype.onMediaStreamDestroyed = function (clientRole) {
|
|
95
|
+
var _this = this;
|
|
96
|
+
this._peerConnections.forEach(function (peerConnection) {
|
|
97
|
+
if (peerConnection.peerRole === clientRole) {
|
|
98
|
+
_this.destroyPublisherOnPeerConnection(peerConnection);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return Promise.resolve();
|
|
102
|
+
};
|
|
103
|
+
OpentokSessionV3.prototype.onMediaStreamRenewed = function (clientRole, mediaStream) {
|
|
104
|
+
//TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation (in OT API)
|
|
105
|
+
return Promise.resolve();
|
|
106
|
+
};
|
|
107
|
+
OpentokSessionV3.prototype.getRemoteTrackStats = function (mediaTrack) {
|
|
108
|
+
//https://tokbox.com/developer/sdks/js/reference/Subscriber.html (getStats)
|
|
109
|
+
return Promise.reject(new Error('Not implemented yet'));
|
|
110
|
+
};
|
|
111
|
+
//#region OpenTok Events Handlers
|
|
112
|
+
OpentokSessionV3.prototype.connectionCreatedHandler = function (event) {
|
|
113
|
+
var _this = this;
|
|
114
|
+
trace.info('connectionCreatedHandler', event);
|
|
115
|
+
var connection = event.connection;
|
|
116
|
+
if (!this.sessionExistsGuard(false) || !connection) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
//In case we got our own connection, we have nothing to do with it
|
|
120
|
+
if (connection.connectionId === this.ownPeerId) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
var destinationRole = this.calculateDestinationRole();
|
|
124
|
+
this.createStreamForPublishing(destinationRole).then(function (streams) {
|
|
125
|
+
var peerConnection = {
|
|
126
|
+
peerId: connection.connectionId,
|
|
127
|
+
peerRole: destinationRole,
|
|
128
|
+
peerType: _this._sessionParams.clientType === MediaConstants_1.SessionClientType.INITIATOR ? MediaConstants_1.SessionClientType.GUEST : MediaConstants_1.SessionClientType.INITIATOR,
|
|
129
|
+
connection: connection,
|
|
130
|
+
publisher: null,
|
|
131
|
+
remoteMediaTracks: [],
|
|
132
|
+
localStream: streams
|
|
133
|
+
};
|
|
134
|
+
if (!streams.videoSource && !streams.audioSource) {
|
|
135
|
+
trace.info('Peer connection without publisher was created', peerConnection);
|
|
136
|
+
return peerConnection;
|
|
137
|
+
}
|
|
138
|
+
var streamName = destinationRole === MediaConstants_1.SessionClientRole.USER ? MediaConstants_1.KnownMediaStream.AGENT_AUDIO_STREAM : MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM;
|
|
139
|
+
return _this.createMediaPublisher(streams, streamName).then(function (publisher) {
|
|
140
|
+
peerConnection.publisher = publisher;
|
|
141
|
+
trace.info('Peer connection with publisher was created', peerConnection);
|
|
142
|
+
return peerConnection;
|
|
143
|
+
});
|
|
144
|
+
}).then(function (peerConnection) {
|
|
145
|
+
_this._peerConnections.set(peerConnection.peerId, peerConnection);
|
|
146
|
+
if (peerConnection.publisher) {
|
|
147
|
+
return new Promise(function (resolve, reject) {
|
|
148
|
+
trace.info('Starting publish to peerConnection.publisher');
|
|
149
|
+
_this._session.publish(peerConnection.publisher, function (error) {
|
|
150
|
+
if (error) {
|
|
151
|
+
trace.error('Publish to peerConnection error', error);
|
|
152
|
+
return reject(error);
|
|
153
|
+
}
|
|
154
|
+
trace.info('Publish to peerConnection success');
|
|
155
|
+
return resolve();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return Promise.resolve();
|
|
160
|
+
}).catch(function (error) {
|
|
161
|
+
//Need to handle fail cases during reliability
|
|
162
|
+
trace.error('Error handling new peer connection', error);
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
OpentokSessionV3.prototype.connectionDestroyedHandler = function (event) {
|
|
166
|
+
trace.info('connectionDestroyedHandler', event);
|
|
167
|
+
var connection = event.connection;
|
|
168
|
+
if (!this.sessionExistsGuard(false) || !connection) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (this._peerConnections.has(connection.connectionId)) {
|
|
172
|
+
this.destroyPeerConnection(this._peerConnections.get(connection.connectionId));
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
OpentokSessionV3.prototype.streamCreatedHandler = function (event) {
|
|
176
|
+
trace.info('streamCreatedHandler', event.stream);
|
|
177
|
+
var stream = event.stream;
|
|
178
|
+
var connection = (stream || { connection: null }).connection;
|
|
179
|
+
if (!this.sessionExistsGuard(false) || !stream) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (!this._peerConnections.has(connection.connectionId)) {
|
|
183
|
+
trace.warn('Unexpected case, connection should exist on this stage');
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
var peerConnection = this._peerConnections.get(connection.connectionId);
|
|
187
|
+
if (!peerConnection) {
|
|
188
|
+
trace.warn('Unexpected PeerConnection not found');
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
//Find peerConnection by connectionId, add all tracks to remoteTracks (check if it exists before)
|
|
192
|
+
//We cannot have to tracks with the same id or with the same meaning
|
|
193
|
+
//Register each track using addRemoteTrack
|
|
194
|
+
};
|
|
195
|
+
OpentokSessionV3.prototype.streamDestroyedHandler = function (event) {
|
|
196
|
+
trace.info('streamDestroyedHandler', event);
|
|
197
|
+
var stream = event.stream;
|
|
198
|
+
if (!this.sessionExistsGuard(false) || !stream) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
//Find peerConnection by connectionId, add remove tracks from stream
|
|
202
|
+
//Register each track using addRemoteTrack
|
|
203
|
+
};
|
|
204
|
+
//#endregion
|
|
205
|
+
OpentokSessionV3.prototype.createStreamForPublishing = function (destinationRole) {
|
|
206
|
+
var _this = this;
|
|
207
|
+
trace.info('createStreamForPublishing');
|
|
208
|
+
return this._sessionStreamsManager.getMediaStreamForRole(destinationRole).then(function (mediaStream) {
|
|
209
|
+
var stream = { videoSource: null, audioSource: null };
|
|
210
|
+
if (mediaStream) {
|
|
211
|
+
trace.info('Media stream found for publishing', mediaStream);
|
|
212
|
+
mediaStream.getTracks().forEach(function (track) {
|
|
213
|
+
if (track.kind === 'video') {
|
|
214
|
+
stream.videoSource = track;
|
|
215
|
+
} else if (track.kind === 'audio') {
|
|
216
|
+
stream.audioSource = track;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
} else if (_this._sessionParams.clientRole === MediaConstants_1.SessionClientRole.USER) {
|
|
220
|
+
trace.warn('No local media was found for publishing to destinationRole:', destinationRole);
|
|
221
|
+
}
|
|
222
|
+
return stream;
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
OpentokSessionV3.prototype.calculateDestinationRole = function () {
|
|
226
|
+
if (this._sessionParams.clientRole === MediaConstants_1.SessionClientRole.USER) {
|
|
227
|
+
var isAgentConnected = false;
|
|
228
|
+
return !isAgentConnected ? MediaConstants_1.SessionClientRole.AGENT : MediaConstants_1.SessionClientRole.OBSERVER;
|
|
229
|
+
}
|
|
230
|
+
return MediaConstants_1.SessionClientRole.USER;
|
|
231
|
+
};
|
|
232
|
+
OpentokSessionV3.prototype.createMediaPublisher = function (stream, streamName) {
|
|
233
|
+
var otParams = {
|
|
234
|
+
videoSource: stream.videoSource ? stream.videoSource : false,
|
|
235
|
+
audioSource: stream.audioSource ? stream.audioSource : false,
|
|
236
|
+
publishAudio: !!stream.audioSource,
|
|
237
|
+
publishVideo: !!stream.videoSource,
|
|
238
|
+
showControls: false,
|
|
239
|
+
name: streamName
|
|
240
|
+
};
|
|
241
|
+
return new Promise(function (resolve, reject) {
|
|
242
|
+
var otPublisher = window.OT.initPublisher(undefined, otParams, function (error) {
|
|
243
|
+
if (error) {
|
|
244
|
+
reject(error);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
resolve(otPublisher);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
OpentokSessionV3.prototype.clearPeerConnections = function () {
|
|
252
|
+
return Promise.resolve();
|
|
253
|
+
};
|
|
254
|
+
OpentokSessionV3.prototype.sessionExistsGuard = function (shouldThrow) {
|
|
255
|
+
if (shouldThrow === void 0) {
|
|
256
|
+
shouldThrow = true;
|
|
257
|
+
}
|
|
258
|
+
var connected = !!(this._session && this._session.connection && this._session.connection.connectionId);
|
|
259
|
+
return guards_1.throwableGuard(connected, 'There no active session', shouldThrow);
|
|
260
|
+
};
|
|
261
|
+
OpentokSessionV3.prototype.destroyPeerConnection = function (peerConnection) {
|
|
262
|
+
var _this = this;
|
|
263
|
+
this._peerConnections.delete(peerConnection.peerId);
|
|
264
|
+
this.destroyPublisherOnPeerConnection(peerConnection);
|
|
265
|
+
peerConnection.remoteMediaTracks.forEach(function (mediaTrack) {
|
|
266
|
+
_this._sessionStreamsManager.removeMediaTrack(mediaTrack.mediaTrack).catch(function (error) {
|
|
267
|
+
trace.warn('Error removing media track', error);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
OpentokSessionV3.prototype.destroyPublisherOnPeerConnection = function (peerConnection) {
|
|
272
|
+
if (peerConnection.publisher) {
|
|
273
|
+
//TODO - Alex: When destroying the publisher, OT closes the stream by himself, without we ask him.
|
|
274
|
+
//So we not destroying the OT publisher right now in order to preserve our stream alive.
|
|
275
|
+
//Later, we can recreate our stream as new, or manually delete "video" element that created by OT.
|
|
276
|
+
// or we just can leave it as is :)
|
|
277
|
+
//peerConnection.publisher.destroy();
|
|
278
|
+
peerConnection.publisher = null;
|
|
279
|
+
peerConnection.localStream = null;
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
return OpentokSessionV3;
|
|
283
|
+
}();
|
|
284
|
+
exports.OpentokSessionV3 = OpentokSessionV3;
|
|
285
|
+
|
|
286
|
+
//# sourceMappingURL=SessionOpentok.v3.js.map
|
|
287
|
+
//# sourceMappingURL=SessionOpentok.v3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["Session/SessionOpentok.v3.js"],"names":["Object","defineProperty","exports","value","MediaConstants_1","require","MediaTracer_1","guards_1","trace","getMediaTracer","OpentokSessionV3","sessionParams","streamFactory","_peerConnections","Map","_session","_sessionParams","_sessionStreamsManager","_credentials","credentials","connect","bind","disconnect","onMediaStreamDestroyed","onMediaStreamRenewed","createStreamForPublishing","createMediaPublisher","clearPeerConnections","connectionCreatedHandler","connectionDestroyedHandler","streamCreatedHandler","streamDestroyedHandler","prototype","get","sessionId","enumerable","configurable","connection","connectionId","_this","info","error","Promise","reject","resolve","handleError","off","_a","apiKey","window","OTSESSION","OT","initSession","on","connectHandler","token","currentSession","forEach","peerConnection","destroyPeerConnection","clientRole","peerRole","destroyPublisherOnPeerConnection","mediaStream","getRemoteTrackStats","mediaTrack","Error","event","sessionExistsGuard","ownPeerId","destinationRole","calculateDestinationRole","then","streams","peerId","peerType","clientType","SessionClientType","INITIATOR","GUEST","publisher","remoteMediaTracks","localStream","videoSource","audioSource","streamName","SessionClientRole","USER","KnownMediaStream","AGENT_AUDIO_STREAM","USER_VIDEO_STREAM","set","publish","catch","has","stream","warn","getMediaStreamForRole","getTracks","track","kind","isAgentConnected","AGENT","OBSERVER","otParams","publishAudio","publishVideo","showControls","name","otPublisher","initPublisher","undefined","shouldThrow","connected","throwableGuard","delete","removeMediaTrack"],"mappings":"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","file":"SessionOpentok.v3.js","sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar MediaConstants_1 = require(\"../MediaConstants\");\nvar MediaTracer_1 = require(\"../Utils/MediaTracer\");\nvar guards_1 = require(\"@techsee/techsee-common/lib/core/guards\");\nvar trace = MediaTracer_1.getMediaTracer('OpenTokSession');\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nvar OpentokSessionV3 = /** @class */ (function () {\n function OpentokSessionV3(sessionParams, streamFactory) {\n this._peerConnections = new Map();\n this._session = null;\n this._sessionParams = sessionParams;\n this._sessionStreamsManager = streamFactory;\n this._credentials = sessionParams.credentials;\n this.connect = this.connect.bind(this);\n this.disconnect = this.disconnect.bind(this);\n this.onMediaStreamDestroyed = this.onMediaStreamDestroyed.bind(this);\n this.onMediaStreamRenewed = this.onMediaStreamRenewed.bind(this);\n this.createStreamForPublishing = this.createStreamForPublishing.bind(this);\n this.createMediaPublisher = this.createMediaPublisher.bind(this);\n this.clearPeerConnections = this.clearPeerConnections.bind(this);\n this.connectionCreatedHandler = this.connectionCreatedHandler.bind(this);\n this.connectionDestroyedHandler = this.connectionDestroyedHandler.bind(this);\n this.streamCreatedHandler = this.streamCreatedHandler.bind(this);\n this.streamDestroyedHandler = this.streamDestroyedHandler.bind(this);\n }\n Object.defineProperty(OpentokSessionV3.prototype, \"id\", {\n get: function () {\n return this._session && this._session.sessionId ? this._session.sessionId : '';\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(OpentokSessionV3.prototype, \"ownPeerId\", {\n get: function () {\n return this._session && this._session.connection ? this._session.connection.connectionId : '';\n },\n enumerable: true,\n configurable: true\n });\n OpentokSessionV3.prototype.connect = function () {\n var _this = this;\n trace.info('Connect to session');\n if (this._session) {\n trace.error('Session already exists');\n return Promise.reject('Cannot connect to session while another session is active');\n }\n return new Promise(function (resolve, reject) {\n var handleError = function (error) {\n _this._session && _this._session.off();\n _this._session = null;\n trace.error('handleConnect error:', error);\n reject(error);\n };\n var _a = _this._sessionParams.credentials, apiKey = _a.apiKey, sessionId = _a.sessionId;\n _this._session = window.OTSESSION = window.OT.initSession(apiKey, sessionId);\n _this._session.on('connectionCreated', _this.connectionCreatedHandler);\n _this._session.on('connectionDestroyed', _this.connectionDestroyedHandler);\n _this._session.on('streamCreated', _this.streamCreatedHandler);\n _this._session.on('streamDestroyed', _this.streamDestroyedHandler);\n var connectHandler = function (error) {\n if (error) {\n handleError(error);\n return;\n }\n resolve();\n };\n _this._session.connect(_this._credentials.token, connectHandler);\n });\n };\n OpentokSessionV3.prototype.disconnect = function () {\n var _this = this;\n //TODO - Alex: Implement destroying all publishers (by opentok docs)\n //Create a method destroy publisher (or publishers can treated the same as \"peerConnections\"?\n return new Promise(function (resolve) {\n var currentSession = _this._session;\n _this._session = null;\n _this._peerConnections.forEach(function (peerConnection) {\n _this.destroyPeerConnection(peerConnection);\n });\n if (!currentSession) {\n trace.info('No active session - resolving');\n resolve();\n return;\n }\n currentSession.off();\n currentSession.disconnect();\n resolve();\n });\n };\n OpentokSessionV3.prototype.onMediaStreamDestroyed = function (clientRole) {\n var _this = this;\n this._peerConnections.forEach(function (peerConnection) {\n if (peerConnection.peerRole === clientRole) {\n _this.destroyPublisherOnPeerConnection(peerConnection);\n }\n });\n return Promise.resolve();\n };\n OpentokSessionV3.prototype.onMediaStreamRenewed = function (clientRole, mediaStream) {\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation (in OT API)\n return Promise.resolve();\n };\n OpentokSessionV3.prototype.getRemoteTrackStats = function (mediaTrack) {\n //https://tokbox.com/developer/sdks/js/reference/Subscriber.html (getStats)\n return Promise.reject(new Error('Not implemented yet'));\n };\n //#region OpenTok Events Handlers\n OpentokSessionV3.prototype.connectionCreatedHandler = function (event) {\n var _this = this;\n trace.info('connectionCreatedHandler', event);\n var connection = event.connection;\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n //In case we got our own connection, we have nothing to do with it\n if (connection.connectionId === this.ownPeerId) {\n return;\n }\n var destinationRole = this.calculateDestinationRole();\n this.createStreamForPublishing(destinationRole)\n .then(function (streams) {\n var peerConnection = {\n peerId: connection.connectionId,\n peerRole: destinationRole,\n peerType: _this._sessionParams.clientType === MediaConstants_1.SessionClientType.INITIATOR\n ? MediaConstants_1.SessionClientType.GUEST : MediaConstants_1.SessionClientType.INITIATOR,\n connection: connection,\n publisher: null,\n remoteMediaTracks: [],\n localStream: streams\n };\n if (!streams.videoSource && !streams.audioSource) {\n trace.info('Peer connection without publisher was created', peerConnection);\n return peerConnection;\n }\n var streamName = destinationRole === MediaConstants_1.SessionClientRole.USER\n ? MediaConstants_1.KnownMediaStream.AGENT_AUDIO_STREAM : MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM;\n return _this.createMediaPublisher(streams, streamName)\n .then(function (publisher) {\n peerConnection.publisher = publisher;\n trace.info('Peer connection with publisher was created', peerConnection);\n return peerConnection;\n });\n })\n .then(function (peerConnection) {\n _this._peerConnections.set(peerConnection.peerId, peerConnection);\n if (peerConnection.publisher) {\n return new Promise(function (resolve, reject) {\n trace.info('Starting publish to peerConnection.publisher');\n _this._session.publish(peerConnection.publisher, function (error) {\n if (error) {\n trace.error('Publish to peerConnection error', error);\n return reject(error);\n }\n trace.info('Publish to peerConnection success');\n return resolve();\n });\n });\n }\n return Promise.resolve();\n })\n .catch(function (error) {\n //Need to handle fail cases during reliability\n trace.error('Error handling new peer connection', error);\n });\n };\n OpentokSessionV3.prototype.connectionDestroyedHandler = function (event) {\n trace.info('connectionDestroyedHandler', event);\n var connection = event.connection;\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n if (this._peerConnections.has(connection.connectionId)) {\n this.destroyPeerConnection(this._peerConnections.get(connection.connectionId));\n }\n };\n OpentokSessionV3.prototype.streamCreatedHandler = function (event) {\n trace.info('streamCreatedHandler', event.stream);\n var stream = event.stream;\n var connection = (stream || { connection: null }).connection;\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n if (!this._peerConnections.has(connection.connectionId)) {\n trace.warn('Unexpected case, connection should exist on this stage');\n return;\n }\n var peerConnection = this._peerConnections.get(connection.connectionId);\n if (!peerConnection) {\n trace.warn('Unexpected PeerConnection not found');\n return;\n }\n //Find peerConnection by connectionId, add all tracks to remoteTracks (check if it exists before)\n //We cannot have to tracks with the same id or with the same meaning\n //Register each track using addRemoteTrack\n };\n OpentokSessionV3.prototype.streamDestroyedHandler = function (event) {\n trace.info('streamDestroyedHandler', event);\n var stream = event.stream;\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n //Find peerConnection by connectionId, add remove tracks from stream\n //Register each track using addRemoteTrack\n };\n //#endregion\n OpentokSessionV3.prototype.createStreamForPublishing = function (destinationRole) {\n var _this = this;\n trace.info('createStreamForPublishing');\n return this._sessionStreamsManager.getMediaStreamForRole(destinationRole)\n .then(function (mediaStream) {\n var stream = { videoSource: null, audioSource: null };\n if (mediaStream) {\n trace.info('Media stream found for publishing', mediaStream);\n mediaStream.getTracks().forEach(function (track) {\n if (track.kind === 'video') {\n stream.videoSource = track;\n }\n else if (track.kind === 'audio') {\n stream.audioSource = track;\n }\n });\n }\n else if (_this._sessionParams.clientRole === MediaConstants_1.SessionClientRole.USER) {\n trace.warn('No local media was found for publishing to destinationRole:', destinationRole);\n }\n return stream;\n });\n };\n OpentokSessionV3.prototype.calculateDestinationRole = function () {\n if (this._sessionParams.clientRole === MediaConstants_1.SessionClientRole.USER) {\n var isAgentConnected = false;\n return !isAgentConnected ? MediaConstants_1.SessionClientRole.AGENT : MediaConstants_1.SessionClientRole.OBSERVER;\n }\n return MediaConstants_1.SessionClientRole.USER;\n };\n OpentokSessionV3.prototype.createMediaPublisher = function (stream, streamName) {\n var otParams = {\n videoSource: stream.videoSource ? stream.videoSource : false,\n audioSource: stream.audioSource ? stream.audioSource : false,\n publishAudio: !!stream.audioSource,\n publishVideo: !!stream.videoSource,\n showControls: false,\n name: streamName\n };\n return new Promise(function (resolve, reject) {\n var otPublisher = window.OT.initPublisher(undefined, otParams, function (error) {\n if (error) {\n reject(error);\n return;\n }\n resolve(otPublisher);\n });\n });\n };\n OpentokSessionV3.prototype.clearPeerConnections = function () {\n return Promise.resolve();\n };\n OpentokSessionV3.prototype.sessionExistsGuard = function (shouldThrow) {\n if (shouldThrow === void 0) { shouldThrow = true; }\n var connected = !!(this._session && this._session.connection && this._session.connection.connectionId);\n return guards_1.throwableGuard(connected, 'There no active session', shouldThrow);\n };\n OpentokSessionV3.prototype.destroyPeerConnection = function (peerConnection) {\n var _this = this;\n this._peerConnections.delete(peerConnection.peerId);\n this.destroyPublisherOnPeerConnection(peerConnection);\n peerConnection.remoteMediaTracks.forEach(function (mediaTrack) {\n _this._sessionStreamsManager.removeMediaTrack(mediaTrack.mediaTrack)\n .catch(function (error) {\n trace.warn('Error removing media track', error);\n });\n });\n };\n OpentokSessionV3.prototype.destroyPublisherOnPeerConnection = function (peerConnection) {\n if (peerConnection.publisher) {\n //TODO - Alex: When destroying the publisher, OT closes the stream by himself, without we ask him.\n //So we not destroying the OT publisher right now in order to preserve our stream alive.\n //Later, we can recreate our stream as new, or manually delete \"video\" element that created by OT.\n // or we just can leave it as is :)\n //peerConnection.publisher.destroy();\n peerConnection.publisher = null;\n peerConnection.localStream = null;\n }\n };\n return OpentokSessionV3;\n}());\nexports.OpentokSessionV3 = OpentokSessionV3;\n\n//# sourceMappingURL=SessionOpentok.v3.js.map\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { IMediaSession, ISessionStreamsManager, MediaSessionHandlers, MediaSessionParams, RemoteMediaTrack, RemoteTrackStats } from '../MediaContracts';
|
|
2
|
+
import { SessionClientRole, SessionClientType } from '../MediaConstants';
|
|
3
|
+
declare global {
|
|
4
|
+
interface RTCPeerConnection {
|
|
5
|
+
peerId: any;
|
|
6
|
+
peerType: SessionClientType;
|
|
7
|
+
peerRole: SessionClientRole;
|
|
8
|
+
remoteMediaTracks: RemoteMediaTrack[];
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export declare class TurnWebRtcSessionV3 implements IMediaSession {
|
|
12
|
+
private readonly _sessionStreamsManager;
|
|
13
|
+
private readonly _sessionParams;
|
|
14
|
+
private readonly _sessionHandlers;
|
|
15
|
+
private readonly _pendingPeersIce;
|
|
16
|
+
private readonly _peerConnections;
|
|
17
|
+
private readonly _configuration;
|
|
18
|
+
private _socket;
|
|
19
|
+
readonly id: string;
|
|
20
|
+
constructor(sessionParams: MediaSessionParams, sessionHandlers: MediaSessionHandlers, streamFactory: ISessionStreamsManager);
|
|
21
|
+
connect(connectOnly?: boolean): Promise<void>;
|
|
22
|
+
disconnect(): Promise<void>;
|
|
23
|
+
_connectSocket(url: string, connectOnly: boolean): Promise<void>;
|
|
24
|
+
_onSocketDisconnectedHandler(reason: string): void;
|
|
25
|
+
_sendOfferHandler(sendOfferEventData: any): void;
|
|
26
|
+
_joinResponseHandler(joinResponseData: any): void;
|
|
27
|
+
_peerDisconnectedHandler(peerDisconnectedEvent: any): void;
|
|
28
|
+
_sdpOfferHandler(sdpOfferEvent: any): void;
|
|
29
|
+
_userPeerReconnectHandler(): void;
|
|
30
|
+
onMediaStreamDestroyed(clientRole: SessionClientRole): Promise<void>;
|
|
31
|
+
onMediaStreamRenewed(clientRole: SessionClientRole, mediaStream: MediaStream): Promise<void>;
|
|
32
|
+
getRemoteTrackStats(mediaTrack: MediaStreamTrack): Promise<RemoteTrackStats>;
|
|
33
|
+
private _disconnectInternal;
|
|
34
|
+
private _createPeerConnection;
|
|
35
|
+
private _destroyPeerConnection;
|
|
36
|
+
private _withPeerConnection;
|
|
37
|
+
_iceCandidateReceivedHandler(iceCandidateData: any): void;
|
|
38
|
+
_addIceCandidateToPeer(iceCandidate: RTCIceCandidate, peerConnection: RTCPeerConnection): Promise<void>;
|
|
39
|
+
_processQueuedIceCandidates(peerId: string): void;
|
|
40
|
+
_queueIceCandidate(iceCandidate: RTCIceCandidate, peerId: string): void;
|
|
41
|
+
_iceStateDisconnected(peerConnection: RTCPeerConnection): void;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Session/SessionTurn.v3.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,aAAa,EACb,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAAE,gBAAgB,EACrC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAGH,iBAAiB,EACjB,iBAAiB,EACpB,MAAM,mBAAmB,CAAC;AAc3B,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,iBAAiB;QACvB,MAAM,EAAE,GAAG,CAAC;QACZ,QAAQ,EAAE,iBAAiB,CAAC;QAC5B,QAAQ,EAAE,iBAAiB,CAAC;QAC5B,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;KACzC;CACJ;AAGD,qBAAa,mBAAoB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAChE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAuB;IACxD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAM;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAM;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;IACrC,OAAO,CAAC,OAAO,CAAM;aAEjB,EAAE,EAAI,MAAM;gBAIJ,aAAa,EAAE,kBAAkB,EAAE,eAAe,EAAE,oBAAoB,EAAE,aAAa,EAAE,sBAAsB;IA8B3H,OAAO,CAAC,WAAW,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB3C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAkChE,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAgBlD,iBAAiB,CAAC,kBAAkB,EAAE,GAAG,GAAG,IAAI;IAmEhD,oBAAoB,CAAC,gBAAgB,EAAE,GAAG,GAAG,IAAI;IAwBjD,wBAAwB,CAAC,qBAAqB,EAAE,GAAG,GAAG,IAAI;IAe1D,gBAAgB,CAAC,aAAa,EAAE,GAAG,GAAG,IAAI;IA2E1C,yBAAyB,IAAI,IAAI;IAcjC,sBAAsB,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IASpE,oBAAoB,CAAC,UAAU,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5F,mBAAmB,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoB5E,OAAO,CAAC,mBAAmB;IAkB3B,OAAO,CAAC,qBAAqB;IA8C7B,OAAO,CAAC,sBAAsB;IAmB9B,OAAO,CAAC,mBAAmB;IAY3B,4BAA4B,CAAC,gBAAgB,EAAE,GAAG,GAAG,IAAI;IAuBzD,sBAAsB,CAAC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvG,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAejD,kBAAkB,CAAC,YAAY,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAQvE,qBAAqB,CAAC,cAAc,EAAE,iBAAiB,GAAG,IAAI;CAKjE","file":"SessionTurn.v3.d.ts","sourcesContent":["import * as io from 'socket.io-client';\nimport once from 'lodash/once';\nimport {Nullable} from '@techsee/techsee-common';\n\nimport {\n IMediaSession,\n ISessionStreamsManager,\n MediaSessionHandlers,\n MediaSessionParams,\n RemoteMediaTrack, RemoteTrackStats\n} from '../MediaContracts';\n\nimport {\n KnownMediaStream,\n MediaSessionDisconnectReason,\n SessionClientRole,\n SessionClientType\n} from '../MediaConstants';\n\nimport {\n SOCKET_EVENTS, SOCKET_PATH,\n SOCKET_RECONNECTION_ATTEMPTS,\n SOCKET_RECONNECTION_DELAY,\n SOCKET_RECONNECTION_DELAY_MAX\n} from './TurnConstants';\n\nimport {getMediaTracer} from '../Utils/MediaTracer';\n\nconst trace = getMediaTracer('TurnSessionV3');\n\n\ndeclare global {\n interface RTCPeerConnection {\n peerId: any;\n peerType: SessionClientType;\n peerRole: SessionClientRole;\n remoteMediaTracks: RemoteMediaTrack[];\n }\n}\n\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nexport class TurnWebRtcSessionV3 implements IMediaSession {\n private readonly _sessionStreamsManager: ISessionStreamsManager;\n private readonly _sessionParams: MediaSessionParams;\n private readonly _sessionHandlers: MediaSessionHandlers;\n private readonly _pendingPeersIce: any;\n private readonly _peerConnections: any;\n private readonly _configuration: any;\n private _socket: any;\n\n get id(): string {\n return this._sessionParams.sessionId;\n }\n\n constructor(sessionParams: MediaSessionParams, sessionHandlers: MediaSessionHandlers, streamFactory: ISessionStreamsManager) {\n this._sessionParams = sessionParams;\n this._sessionStreamsManager = streamFactory;\n this._sessionHandlers = sessionHandlers;\n this._socket = null;\n this._pendingPeersIce = {};\n this._peerConnections = new Map();\n\n const iceServers = sessionParams.credentials.ice.map((item: any) => ({\n urls: item.url,\n username: item.login,\n credential: item.password\n }));\n\n this._configuration = {\n iceServers,\n iceTransportPolicy: 'relay'\n };\n\n this._joinResponseHandler = this._joinResponseHandler.bind(this);\n this._iceCandidateReceivedHandler = this._iceCandidateReceivedHandler.bind(this);\n this._sendOfferHandler = this._sendOfferHandler.bind(this);\n this._sdpOfferHandler = this._sdpOfferHandler.bind(this);\n this._userPeerReconnectHandler = this._userPeerReconnectHandler.bind(this);\n this._peerDisconnectedHandler = this._peerDisconnectedHandler.bind(this);\n this._onSocketDisconnectedHandler = this._onSocketDisconnectedHandler.bind(this);\n }\n\n //#region Socket Connectivity\n\n connect(connectOnly = false): Promise<void> {\n trace.info('Connect to session');\n\n return this._connectSocket(this._sessionParams.credentials.url, connectOnly)\n .then(() => {\n trace.info('Joining SessionId: ' + this._sessionParams.sessionId);\n\n this._socket.emit(SOCKET_EVENTS.OUTGOING.JOIN_ROOM, {\n clientType: this._sessionParams.clientType,\n sessionId: this._sessionParams.sessionId\n });\n })\n .catch((error) => {\n throw error;\n });\n }\n\n disconnect(): Promise<void> {\n return this._disconnectInternal(MediaSessionDisconnectReason.ForcedByConsumer);\n }\n\n _connectSocket(url: string, connectOnly: boolean): Promise<void> {\n return new Promise((resolve, reject) => {\n const socket = this._socket = io.connect(url, {\n 'forceNew': true,\n 'reconnectionDelay': SOCKET_RECONNECTION_DELAY,\n 'reconnectionDelayMax': SOCKET_RECONNECTION_DELAY_MAX,\n 'reconnectionAttempts': SOCKET_RECONNECTION_ATTEMPTS,\n 'path': SOCKET_PATH\n });\n\n const done = once((err?: any) => {\n err ? reject(err) : resolve();\n });\n\n socket.once('connect', () => done());\n socket.on(SOCKET_EVENTS.INCOMING.ERROR, done);\n socket.on('connect_error', done);\n socket.on('connect_timeout', done);\n socket.on('disconnect', this._onSocketDisconnectedHandler);\n\n if (!connectOnly) {\n trace.info('Subscribing socket events');\n\n //PUBLISHING NOT SUPPORTED YET\n socket.on(SOCKET_EVENTS.INCOMING.SEND_OFFER, this._sendOfferHandler);\n socket.on(SOCKET_EVENTS.INCOMING.JOIN_RESPONSE, this._joinResponseHandler);\n socket.on(SOCKET_EVENTS.INCOMING.PEER_DISCONNECTED, this._peerDisconnectedHandler);\n socket.on(SOCKET_EVENTS.INCOMING.SDP_OFFER, this._sdpOfferHandler);\n socket.on(SOCKET_EVENTS.INCOMING.PUBLISHER_RECONNECT, this._userPeerReconnectHandler);\n socket.on(SOCKET_EVENTS.INCOMING.ICE_CANDIDATE, this._iceCandidateReceivedHandler);\n }\n });\n }\n\n _onSocketDisconnectedHandler(reason: string): void {\n if (this._socket) {\n // The initial example of differentiating between \"forced\" disconnect and \"network\" disconnect is taken from:\n // https://socket.io/docs/client-api/#Event-%E2%80%98disconnect%E2%80%99\n if (reason !== 'io server disconnect' && reason !== 'io client disconnect') {\n // the disconnection was initiated by the server or by client, you need to call (connect) manually\n this._disconnectInternal(MediaSessionDisconnectReason.SignalingChannelDisconnect).catch(() => undefined);\n }\n }\n }\n\n //#endregion\n\n //#region WebRTC Initiator - session Initiator (User on mobile device)\n\n // Received by Initiator, causing him to emit SDP_OFFER\n _sendOfferHandler(sendOfferEventData: any): void {\n const {uid, peerId} = sendOfferEventData;\n\n trace.info('_sendOfferHandler');\n\n //Currently we not support of passing role through signaling, so we assume every connection is \"AGENT\" like\n const peerConnection = this._createPeerConnection(peerId, SessionClientType.GUEST, SessionClientRole.AGENT);\n const offerParams = {offerToReceiveAudio: true, offerToReceiveVideo: true};\n\n peerConnection.ontrack = (trackEvent: any) => {\n const track: MediaStreamTrack = trackEvent.track;\n\n trace.info(`MediaStreamTrack arrived from peerConnection: ${track.kind}`, track);\n\n //We only support to stream audio from dashboard\n if (track.kind.toLowerCase() === 'audio') {\n const remoteMediaTrack: RemoteMediaTrack = {\n mediaTrack: track,\n trackType: KnownMediaStream.AGENT_AUDIO_STREAM\n };\n\n peerConnection.remoteMediaTracks.push(remoteMediaTrack);\n this._sessionStreamsManager.addRemoteMediaTrack(remoteMediaTrack)\n .catch((error: any) => {\n trace.warn('Error adding remote media track to available streams', error);\n });\n }\n };\n\n //TODO - Alex: Currently we not sending \"role\" through signaling, and by default we assume that the one who asks fot offer, is agent.\n //On later stages we can send or the client \"role\" or the list of \"streams\" that peer is interested in.\n this._sessionStreamsManager.getMediaStreamForRole(SessionClientRole.AGENT)\n .then((mediaStream: Nullable<MediaStream>) => {\n trace.info('_sendOfferHandler stream and peer created');\n\n if (mediaStream) {\n trace.info('Adding local tracks to peer connection');\n mediaStream.getTracks().forEach((track) => {\n peerConnection.addTrack(track, mediaStream);\n trace.info(`Local ${track.kind} track added to peer connection`);\n });\n } else {\n trace.info('No media stream was found for publishing');\n }\n })\n .then(() => peerConnection.createOffer(offerParams))\n .then((offerDesc) => {\n trace.info('Initiator has created sdp offer', {offerDesc});\n\n this._socket.emit(SOCKET_EVENTS.OUTGOING.SDP_OFFER, {\n uid,\n peerId,\n sessionId: this._sessionParams.sessionId,\n sdpOffer: offerDesc.sdp\n });\n\n return peerConnection.setLocalDescription(offerDesc)\n .then(() => {\n trace.info('Local description was set on peerConnection', peerConnection);\n });\n })\n .catch((e) => {\n trace.warn('Error', e);\n });\n }\n\n // Received by the Initiator: Indicates that publish should be started\n _joinResponseHandler(joinResponseData: any): void {\n const {sdpAnswer, uid, peerId} = joinResponseData;\n\n trace.info('joinResponse Received', {sdpAnswer});\n\n this._withPeerConnection(peerId, (peerConnection: RTCPeerConnection) => {\n const answer = new RTCSessionDescription({\n type: 'answer',\n sdp: sdpAnswer\n });\n\n peerConnection.setRemoteDescription(answer)\n .then(() => {\n trace.info('Remote description was set', answer);\n\n this._processQueuedIceCandidates(peerId);\n })\n .catch((e) => {\n trace.warn('Error', e);\n });\n });\n }\n\n // Received by Initiator after a guests socket has been disconnected\n _peerDisconnectedHandler(peerDisconnectedEvent: any): void {\n const {peerId} = peerDisconnectedEvent;\n\n trace.info('_peerDisconnectedHandler');\n\n this._withPeerConnection(peerId, (peerConnection: any) => {\n this._disconnectInternal(MediaSessionDisconnectReason.PeerDisconnected).catch(() => undefined);\n });\n }\n\n //#endregion WebRTC Initiator - session Initiator (User on mobile device)\n\n //#region WebRTC Guest - session Guest (Agent on dashboard platform)\n\n // Received by Guest, causing him to emit SDP_ANSWER\n _sdpOfferHandler(sdpOfferEvent: any): void {\n const {sdpOffer, peerId, uid} = sdpOfferEvent;\n\n trace.info('sdpOffer Received', {sdpOffer});\n\n const peerConnection = this._createPeerConnection(peerId, SessionClientType.INITIATOR, SessionClientRole.USER);\n\n peerConnection.ontrack = (trackEvent: any) => {\n const {track} = trackEvent;\n\n trace.info(`MediaStreamTrack arrived from peerConnection: ${track.kind}`, track);\n\n const remoteTrack: RemoteMediaTrack = {\n mediaTrack: track,\n trackType: track.kind === 'video'\n //Although we can have desktop share stream, we still name it USER_VIDEO_STREAM in dashboard.\n //Because currently we support only one video stream to be streamed at the time, it's not an issue.\n //But when we will need to stream more than one stream of a kind from single peer, this will be need to change.\n ? KnownMediaStream.USER_VIDEO_STREAM : KnownMediaStream.USER_AUDIO_STREAM\n };\n\n peerConnection.remoteMediaTracks.push(remoteTrack);\n this._sessionStreamsManager.addRemoteMediaTrack(remoteTrack)\n .catch(() => {\n trace.warn('Error adding remote track to stream manager', remoteTrack);\n });\n };\n\n this._sessionStreamsManager.getMediaStreamForRole(SessionClientRole.USER)\n .then((mediaStream: Nullable<MediaStream>) => {\n if (mediaStream) {\n trace.info('Adding local tracks to peer connection');\n mediaStream.getTracks().forEach((track) => {\n peerConnection.addTrack(track, mediaStream);\n trace.info(`Local ${track.kind} track added to peer connection`);\n });\n } else {\n trace.info('No media stream was found for publishing');\n }\n })\n .then(() => {\n const remoteDesc = new RTCSessionDescription({type: 'offer', sdp: sdpOffer});\n\n return peerConnection.setRemoteDescription(remoteDesc)\n .then(() => {\n trace.info('Remote description was set', remoteDesc);\n\n return peerConnection.createAnswer()\n .then((sdpAnswer) => {\n trace.info('_sdpOfferHandler answer created', sdpAnswer);\n\n this._socket.emit(SOCKET_EVENTS.OUTGOING.SDP_ANSWER, {\n uid,\n peerId,\n sessionId: this._sessionParams.sessionId,\n sdpAnswer: sdpAnswer.sdp\n });\n\n return peerConnection.setLocalDescription(sdpAnswer)\n .then(() => {\n trace.info('_sdpOfferHandler local desc was set');\n\n this._processQueuedIceCandidates(peerId);\n });\n });\n });\n\n })\n .catch((e) => {\n trace.error('Error in _sdpOfferHandler', e);\n throw e;\n });\n }\n\n // Received by Guest after an Initiator reconnects to room\n _userPeerReconnectHandler(): void {\n trace.info('_userPeerReconnectHandler');\n this._disconnectInternal(MediaSessionDisconnectReason.UserPeerReconnected)\n .catch((error: any) => {\n trace.warn('Error while disconnecting during userPeerReconnectHandler.', error);\n });\n }\n\n //#endregion WebRTC Guest - session Guest (Agent on dashboard platform)\n\n //#region Peer Connection\n\n //#region Streams Handling\n\n onMediaStreamDestroyed(clientRole: SessionClientRole): Promise<void> {\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation\n this._peerConnections.forEach((peerConnection: RTCPeerConnection) => {\n this._disconnectInternal(MediaSessionDisconnectReason.PublishedStreamDestroyed).catch(() => undefined);\n });\n\n return Promise.resolve();\n }\n\n onMediaStreamRenewed(clientRole: SessionClientRole, mediaStream: MediaStream): Promise<void> {\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation\n return Promise.resolve();\n }\n\n getRemoteTrackStats(mediaTrack: MediaStreamTrack): Promise<RemoteTrackStats> {\n let peerConnectionOfTrack: Nullable<RTCPeerConnection> = null;\n\n this._peerConnections.forEach((peerConnection: RTCPeerConnection) => {\n const remoteTrack = peerConnection.remoteMediaTracks.filter((track) => track.mediaTrack.id === mediaTrack.id);\n\n if (remoteTrack.length === 1) {\n peerConnectionOfTrack = peerConnection;\n }\n });\n\n if (peerConnectionOfTrack !== null) {\n return (peerConnectionOfTrack as any).getStats(mediaTrack);\n }\n\n return Promise.reject(new Error('Provided track is not remote track'));\n }\n\n //#endregion\n\n private _disconnectInternal(reason: MediaSessionDisconnectReason): Promise<void> {\n this._peerConnections.forEach((peerConnection: RTCPeerConnection) => {\n this._destroyPeerConnection(peerConnection);\n });\n\n trace.info('Disconnecting from session', reason);\n\n if (this._socket) {\n this._socket.off();\n this._socket.disconnect();\n }\n\n this._socket = null;\n setTimeout(() => this._sessionHandlers.onDisconnectedHandler(reason));\n\n return Promise.resolve();\n }\n\n private _createPeerConnection(peerId: string, peerConnectionType: SessionClientType, peerConnectionRole: SessionClientRole): RTCPeerConnection {\n if (this._peerConnections.get(peerId)) {\n throw new Error(`${this._sessionParams.clientType} peer connection for ${peerId} already exists`);\n }\n\n const peerConnection: any = new RTCPeerConnection(this._configuration);\n\n peerConnection.peerId = peerId;\n peerConnection.peerType = peerConnectionType;\n peerConnection.remoteMediaTracks = [];\n peerConnection.peerRole = peerConnectionRole;\n\n peerConnection.onconnectionstatechange = () => {\n trace.info('onconnectionstatechange', peerConnection);\n };\n\n peerConnection.oniceconnectionstatechange = (state: any) => {\n trace.info(`ICE Connection state for peer ${peerId} was changed to: ${state.currentTarget.iceConnectionState}`, state);\n const cnState = state.currentTarget.iceConnectionState;\n\n if (['closed', 'disconnected', 'failed'].indexOf(cnState) > -1) {\n this._iceStateDisconnected(peerConnection);\n }\n };\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n trace.info(`${this._sessionParams.clientType} peerConn.onicecandidate`, event.candidate);\n this._socket.emit(SOCKET_EVENTS.OUTGOING.ICE_CANDIDATE, {\n sessionId: this._sessionParams.sessionId,\n peerId: peerId,\n candidate: event.candidate,\n clientType: this._sessionParams.clientType\n });\n } else {\n trace.info('ICE Candidate is null in peerConnection', event);\n }\n };\n\n this._peerConnections.set(peerId, peerConnection);\n\n trace.info(`${peerConnectionType} peerConnection created`);\n\n return peerConnection;\n }\n\n private _destroyPeerConnection(peerConnection: RTCPeerConnection): void {\n trace.info('Destroying PeerConnection', peerConnection.peerType);\n peerConnection.ontrack = null;\n peerConnection.onicecandidate = null;\n peerConnection.onconnectionstatechange = null;\n peerConnection.oniceconnectionstatechange = null;\n peerConnection.onicegatheringstatechange = null;\n\n peerConnection.remoteMediaTracks.forEach((remoteMediaTrack) => {\n this._sessionStreamsManager.removeMediaTrack(remoteMediaTrack.mediaTrack)\n .catch(() => {\n trace.warn('Error while removing remote media track', remoteMediaTrack);\n });\n });\n\n this._peerConnections.delete(peerConnection.peerId);\n peerConnection.close();\n }\n\n private _withPeerConnection(peerId: any, callback: any): void | undefined {\n if (this._peerConnections.get(peerId)) {\n return callback(this._peerConnections.get(peerId));\n }\n\n return undefined;\n }\n\n //#endregion\n\n //#region ICE Candidates\n\n _iceCandidateReceivedHandler(iceCandidateData: any): void {\n const {candidate, peerId} = iceCandidateData;\n\n trace.info('_iceCandidateReceivedHandler', candidate);\n if (!candidate) {\n trace.info('Unexpected case, iceCandidate message arrived without candidate');\n\n return;\n }\n\n const peerConnection = this._peerConnections.get(peerId);\n\n if (!peerConnection || !peerConnection.remoteDescription) {\n trace.info('Queueing iceCandidate', candidate);\n this._queueIceCandidate(candidate, peerId);\n\n return;\n }\n\n trace.info('Going to add iceCandidate', candidate);\n this._addIceCandidateToPeer(candidate, peerConnection).catch(() => undefined);\n }\n\n _addIceCandidateToPeer(iceCandidate: RTCIceCandidate, peerConnection: RTCPeerConnection): Promise<void> {\n return peerConnection.addIceCandidate(iceCandidate)\n .then(() => {\n trace.info('ICE Candidate add to peer connection');\n })\n .catch((e) => {\n trace.warn('Error adding ICE Candidate to peer connection', e);\n throw e;\n });\n }\n\n _processQueuedIceCandidates(peerId: string): void {\n this._withPeerConnection(peerId, (peerConnection: RTCPeerConnection) => {\n const pendingIces = this._pendingPeersIce[peerId];\n\n if (pendingIces) {\n pendingIces.forEach((pendingIce: RTCIceCandidate) => {\n trace.info('Adding pending ICE to peer connections');\n this._addIceCandidateToPeer(pendingIce, peerConnection).catch(() => undefined);\n });\n } else {\n trace.info('No pending ICE found for peer', peerId);\n }\n });\n }\n\n _queueIceCandidate(iceCandidate: RTCIceCandidate, peerId: string): void {\n if (!this._pendingPeersIce[peerId]) {\n this._pendingPeersIce[peerId] = [];\n }\n\n this._pendingPeersIce[peerId].push(iceCandidate);\n }\n\n _iceStateDisconnected(peerConnection: RTCPeerConnection): void {\n this._disconnectInternal(MediaSessionDisconnectReason.PeerConnectionInterrupted).catch(() => undefined);\n }\n\n //#endregion\n}\n"]}
|