@techsee/techsee-media-service 0.6.1-alpha.3 → 0.6.1-alpha.4

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.
@@ -0,0 +1,19 @@
1
+ import { IMediaSessionPeer } from './MediaSessionBase';
2
+ import { SessionClientRole, SessionClientType } from '../MediaConstants';
3
+ import { ISessionStreamsManager, MediaSessionParams, RemoteMediaTrack } from '../MediaContracts';
4
+ export interface IMediaSessionPeer {
5
+ peerId: any;
6
+ peerType: SessionClientType;
7
+ peerRole: SessionClientRole;
8
+ remoteMediaTracks: RemoteMediaTrack[];
9
+ }
10
+ declare global {
11
+ interface RTCPeerConnection extends IMediaSessionPeer {
12
+ }
13
+ }
14
+ export declare abstract class MediaSessionBase {
15
+ protected readonly _sessionStreamsManager: ISessionStreamsManager;
16
+ protected readonly _sessionParams: MediaSessionParams;
17
+ protected constructor(sessionParams: MediaSessionParams, streamFactory: ISessionStreamsManager);
18
+ protected registerMediaTrackFromPeer(sourcePeerConnection: IMediaSessionPeer, mediaTrack: MediaStreamTrack): void;
19
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/MediaSession/MediaSessionBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAyC,iBAAiB,EAAE,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AAC/G,OAAO,EAAC,sBAAsB,EAAE,kBAAkB,EAAE,gBAAgB,EAAC,MAAM,mBAAmB,CAAC;AAK/F,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,GAAG,CAAC;IACZ,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;CACzC;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,iBAAkB,SAAQ,iBAAiB;KAEpD;CACJ;AAKD,8BAAsB,gBAAgB;IAClC,SAAS,CAAC,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB,CAAC;IAClE,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,kBAAkB,CAAC;IAEtD,SAAS,aAAa,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,sBAAsB;IAK9F,SAAS,CAAC,0BAA0B,CAAC,oBAAoB,EAAE,iBAAiB,EAAE,UAAU,EAAE,gBAAgB;CAyB7G","file":"MediaSessionBase.d.ts","sourcesContent":["import {IMediaSessionPeer} from './MediaSessionBase';\nimport {KnownMediaStream, KnownMediaStreamKind, SessionClientRole, SessionClientType} from '../MediaConstants';\nimport {ISessionStreamsManager, MediaSessionParams, RemoteMediaTrack} from '../MediaContracts';\n\nimport {getMediaTracer} from '../MediaUtils/MediaTracer';\nimport {Nullable} from '@techsee/techsee-common';\n\nexport interface IMediaSessionPeer {\n peerId: any;\n peerType: SessionClientType;\n peerRole: SessionClientRole;\n remoteMediaTracks: RemoteMediaTrack[];\n}\n\ndeclare global {\n interface RTCPeerConnection extends IMediaSessionPeer {\n\n }\n}\n\nconst trace = getMediaTracer('MediaSessionBase');\n\n\nexport abstract class MediaSessionBase {\n protected readonly _sessionStreamsManager: ISessionStreamsManager;\n protected readonly _sessionParams: MediaSessionParams;\n\n protected constructor(sessionParams: MediaSessionParams, streamFactory: ISessionStreamsManager) {\n this._sessionParams = sessionParams;\n this._sessionStreamsManager = streamFactory;\n }\n\n protected registerMediaTrackFromPeer(sourcePeerConnection: IMediaSessionPeer, mediaTrack: MediaStreamTrack) {\n if (mediaTrack.kind === KnownMediaStreamKind.Video &&\n sourcePeerConnection.peerRole === SessionClientRole.AGENT) {\n //Currently We don't support video streams from Agent side\n return;\n }\n\n let trackType: Nullable<KnownMediaStream> = null;\n\n if (mediaTrack.kind.toLowerCase() === KnownMediaStreamKind.Audio) {\n trackType = sourcePeerConnection.peerRole === SessionClientRole.AGENT\n ? KnownMediaStream.AGENT_AUDIO_STREAM : KnownMediaStream.USER_AUDIO_STREAM;\n\n } else {\n trackType = KnownMediaStream.USER_VIDEO_STREAM;\n }\n\n const remoteMediaTrack = {mediaTrack, trackType};\n\n sourcePeerConnection.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"]}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ var MediaConstants_1 = require("../MediaConstants");
5
+ var MediaTracer_1 = require("../MediaUtils/MediaTracer");
6
+ var trace = MediaTracer_1.getMediaTracer('MediaSessionBase');
7
+ var MediaSessionBase = /** @class */function () {
8
+ function MediaSessionBase(sessionParams, streamFactory) {
9
+ this._sessionParams = sessionParams;
10
+ this._sessionStreamsManager = streamFactory;
11
+ }
12
+ MediaSessionBase.prototype.registerMediaTrackFromPeer = function (sourcePeerConnection, mediaTrack) {
13
+ if (mediaTrack.kind === MediaConstants_1.KnownMediaStreamKind.Video && sourcePeerConnection.peerRole === MediaConstants_1.SessionClientRole.AGENT) {
14
+ //Currently We don't support video streams from Agent side
15
+ return;
16
+ }
17
+ var trackType = null;
18
+ if (mediaTrack.kind.toLowerCase() === MediaConstants_1.KnownMediaStreamKind.Audio) {
19
+ trackType = sourcePeerConnection.peerRole === MediaConstants_1.SessionClientRole.AGENT ? MediaConstants_1.KnownMediaStream.AGENT_AUDIO_STREAM : MediaConstants_1.KnownMediaStream.USER_AUDIO_STREAM;
20
+ } else {
21
+ trackType = MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM;
22
+ }
23
+ var remoteMediaTrack = { mediaTrack: mediaTrack, trackType: trackType };
24
+ sourcePeerConnection.remoteMediaTracks.push(remoteMediaTrack);
25
+ this._sessionStreamsManager.addRemoteMediaTrack(remoteMediaTrack).catch(function (error) {
26
+ trace.warn('Error adding remote media track to available streams', error);
27
+ });
28
+ };
29
+ return MediaSessionBase;
30
+ }();
31
+ exports.MediaSessionBase = MediaSessionBase;
32
+
33
+ //# sourceMappingURL=MediaSessionBase.js.map
34
+ //# sourceMappingURL=MediaSessionBase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["MediaSession/MediaSessionBase.js"],"names":["Object","defineProperty","exports","value","MediaConstants_1","require","MediaTracer_1","trace","getMediaTracer","MediaSessionBase","sessionParams","streamFactory","_sessionParams","_sessionStreamsManager","prototype","registerMediaTrackFromPeer","sourcePeerConnection","mediaTrack","kind","KnownMediaStreamKind","Video","peerRole","SessionClientRole","AGENT","trackType","toLowerCase","Audio","KnownMediaStream","AGENT_AUDIO_STREAM","USER_AUDIO_STREAM","USER_VIDEO_STREAM","remoteMediaTrack","remoteMediaTracks","push","addRemoteMediaTrack","catch","error","warn"],"mappings":"AAAA;;AACAA,OAAOC,cAAP,CAAsBC,OAAtB,EAA+B,YAA/B,EAA6C,EAAEC,OAAO,IAAT,EAA7C;AACA,IAAIC,mBAAmBC,QAAQ,mBAAR,CAAvB;AACA,IAAIC,gBAAgBD,QAAQ,2BAAR,CAApB;AACA,IAAIE,QAAQD,cAAcE,cAAd,CAA6B,kBAA7B,CAAZ;AACA,IAAIC,mBAAmB,aAAe,YAAY;AAC9C,aAASA,gBAAT,CAA0BC,aAA1B,EAAyCC,aAAzC,EAAwD;AACpD,aAAKC,cAAL,GAAsBF,aAAtB;AACA,aAAKG,sBAAL,GAA8BF,aAA9B;AACH;AACDF,qBAAiBK,SAAjB,CAA2BC,0BAA3B,GAAwD,UAAUC,oBAAV,EAAgCC,UAAhC,EAA4C;AAChG,YAAIA,WAAWC,IAAX,KAAoBd,iBAAiBe,oBAAjB,CAAsCC,KAA1D,IACAJ,qBAAqBK,QAArB,KAAkCjB,iBAAiBkB,iBAAjB,CAAmCC,KADzE,EACgF;AAC5E;AACA;AACH;AACD,YAAIC,YAAY,IAAhB;AACA,YAAIP,WAAWC,IAAX,CAAgBO,WAAhB,OAAkCrB,iBAAiBe,oBAAjB,CAAsCO,KAA5E,EAAmF;AAC/EF,wBAAYR,qBAAqBK,QAArB,KAAkCjB,iBAAiBkB,iBAAjB,CAAmCC,KAArE,GACNnB,iBAAiBuB,gBAAjB,CAAkCC,kBAD5B,GACiDxB,iBAAiBuB,gBAAjB,CAAkCE,iBAD/F;AAEH,SAHD,MAIK;AACDL,wBAAYpB,iBAAiBuB,gBAAjB,CAAkCG,iBAA9C;AACH;AACD,YAAIC,mBAAmB,EAAEd,YAAYA,UAAd,EAA0BO,WAAWA,SAArC,EAAvB;AACAR,6BAAqBgB,iBAArB,CAAuCC,IAAvC,CAA4CF,gBAA5C;AACA,aAAKlB,sBAAL,CAA4BqB,mBAA5B,CAAgDH,gBAAhD,EACKI,KADL,CACW,UAAUC,KAAV,EAAiB;AACxB7B,kBAAM8B,IAAN,CAAW,sDAAX,EAAmED,KAAnE;AACH,SAHD;AAIH,KApBD;AAqBA,WAAO3B,gBAAP;AACH,CA3BqC,EAAtC;AA4BAP,QAAQO,gBAAR,GAA2BA,gBAA3B;;AAEA","file":"MediaSessionBase.js","sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar MediaConstants_1 = require(\"../MediaConstants\");\nvar MediaTracer_1 = require(\"../MediaUtils/MediaTracer\");\nvar trace = MediaTracer_1.getMediaTracer('MediaSessionBase');\nvar MediaSessionBase = /** @class */ (function () {\n function MediaSessionBase(sessionParams, streamFactory) {\n this._sessionParams = sessionParams;\n this._sessionStreamsManager = streamFactory;\n }\n MediaSessionBase.prototype.registerMediaTrackFromPeer = function (sourcePeerConnection, mediaTrack) {\n if (mediaTrack.kind === MediaConstants_1.KnownMediaStreamKind.Video &&\n sourcePeerConnection.peerRole === MediaConstants_1.SessionClientRole.AGENT) {\n //Currently We don't support video streams from Agent side\n return;\n }\n var trackType = null;\n if (mediaTrack.kind.toLowerCase() === MediaConstants_1.KnownMediaStreamKind.Audio) {\n trackType = sourcePeerConnection.peerRole === MediaConstants_1.SessionClientRole.AGENT\n ? MediaConstants_1.KnownMediaStream.AGENT_AUDIO_STREAM : MediaConstants_1.KnownMediaStream.USER_AUDIO_STREAM;\n }\n else {\n trackType = MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM;\n }\n var remoteMediaTrack = { mediaTrack: mediaTrack, trackType: trackType };\n sourcePeerConnection.remoteMediaTracks.push(remoteMediaTrack);\n this._sessionStreamsManager.addRemoteMediaTrack(remoteMediaTrack)\n .catch(function (error) {\n trace.warn('Error adding remote media track to available streams', error);\n });\n };\n return MediaSessionBase;\n}());\nexports.MediaSessionBase = MediaSessionBase;\n\n//# sourceMappingURL=MediaSessionBase.js.map\n"]}
@@ -1,13 +1,12 @@
1
1
  import { IMediaSession, ISessionStreamsManager, MediaSessionParams, RemoteTrackStats } from '../MediaContracts';
2
2
  import { SessionClientRole } from '../MediaConstants';
3
+ import { MediaSessionBase } from './MediaSessionBase';
3
4
  declare global {
4
5
  interface Window {
5
6
  OT: any;
6
7
  }
7
8
  }
8
- export declare class OpentokSessionV3 implements IMediaSession {
9
- private readonly _sessionStreamsManager;
10
- private readonly _sessionParams;
9
+ export declare class OpentokSessionV3 extends MediaSessionBase implements IMediaSession {
11
10
  private readonly _peerConnections;
12
11
  private readonly _credentials;
13
12
  private _session;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MediaSession/SessionOpentok.v3.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,aAAa,EACb,sBAAsB,EACtB,kBAAkB,EACA,gBAAgB,EACrC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAEH,iBAAiB,EAEpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,EAAE,EAAE,GAAG,CAAC;KACX;CACJ;AAoDD,qBAAa,gBAAiB,YAAW,aAAa;IAClD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAChE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA8C;IAC/E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAM;IAEnC,OAAO,CAAC,QAAQ,CAA8B;aAE1C,EAAE,EAAI,MAAM;qBAIJ,SAAS;gBAIT,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,sBAAsB;IAmBpF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAwCxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB3B,sBAAsB,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpE,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;IAO5E,OAAO,CAAC,wBAAwB;IAyEhC,OAAO,CAAC,0BAA0B;IAalC,OAAO,CAAC,oBAAoB;IA4B5B,OAAO,CAAC,sBAAsB;IAc9B,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,oBAAoB;IAsB5B,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,gCAAgC;CAY3C","file":"SessionOpentok.v3.d.ts","sourcesContent":["import {Nullable} from '@techsee/techsee-common';\n\nimport {\n IMediaSession,\n ISessionStreamsManager,\n MediaSessionParams,\n RemoteMediaTrack, RemoteTrackStats\n} from '../MediaContracts';\n\nimport {\n KnownMediaStream,\n SessionClientRole,\n SessionClientType\n} from '../MediaConstants';\n\ndeclare global {\n interface Window {\n OT: any;\n }\n}\n\nimport {getMediaTracer} from '../MediaUtils/MediaTracer';\nimport {throwableGuard} from '@techsee/techsee-common/lib/core/guards';\n\nconst trace = getMediaTracer('OpenTokSession');\n\ninterface IOTSession {\n\n sessionId: string;\n\n connection: Nullable<OTConnection>;\n\n isConnected(): boolean;\n\n connect(token: string, cb: any): void;\n\n disconnect(): void;\n\n publish(publisher: any, cb: any): void;\n\n off(): void;\n\n on(param: string, cb: any): void;\n\n once(param: string, cb: any): void;\n}\n\ntype OTPublisher = any\n\ntype OTPeerId = any\n\ninterface OTConnection {\n connectionId: string;\n}\n\ninterface OTPeerConnection {\n peerId: OTPeerId;\n peerType: SessionClientType;\n peerRole: SessionClientRole;\n remoteMediaTracks: RemoteMediaTrack[];\n localStream: Nullable<OTStreamSource>;\n connection: OTConnection;\n publisher: Nullable<OTPublisher>;\n}\n\ninterface OTStreamSource {\n videoSource: any;\n audioSource: any;\n}\n\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nexport class OpentokSessionV3 implements IMediaSession {\n private readonly _sessionStreamsManager: ISessionStreamsManager;\n private readonly _sessionParams: MediaSessionParams;\n private readonly _peerConnections: Map<OTPeerId, OTPeerConnection> = new Map();\n private readonly _credentials: any;\n\n private _session: Nullable<IOTSession> = null;\n\n get id(): string {\n return this._session && this._session.sessionId ? this._session.sessionId : '';\n }\n\n private get ownPeerId(): string {\n return this._session && this._session.connection ? this._session.connection.connectionId : '';\n }\n\n constructor(sessionParams: MediaSessionParams, streamFactory: ISessionStreamsManager) {\n this._sessionParams = sessionParams;\n this._sessionStreamsManager = streamFactory;\n this._credentials = sessionParams.credentials;\n\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\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\n connect(): Promise<void> {\n trace.info('Connect to session');\n\n if (this._session) {\n trace.error('Session already exists');\n\n return Promise.reject('Cannot connect to session while another session is active');\n }\n\n return new Promise((resolve, reject) => {\n const handleError = (error: any): void => {\n this._session && this._session!.off();\n this._session = null;\n trace.error('handleConnect error:', error);\n reject(error);\n };\n\n const {apiKey, sessionId} = this._sessionParams.credentials;\n\n this._session = (window as any).OTSESSION = window.OT.initSession(apiKey, sessionId);\n\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\n const connectHandler = (error: any): void => {\n if (error) {\n handleError(error);\n\n return;\n }\n\n resolve();\n };\n\n this._session!.connect(this._credentials.token, connectHandler);\n });\n }\n\n disconnect(): Promise<void> {\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((resolve) => {\n const currentSession = this._session;\n\n this._session = null;\n\n this._peerConnections.forEach((peerConnection) => {\n this.destroyPeerConnection(peerConnection);\n });\n\n if (!currentSession) {\n trace.info('No active session - resolving');\n resolve();\n\n return;\n }\n currentSession.off();\n currentSession.disconnect();\n resolve();\n });\n }\n\n onMediaStreamDestroyed(clientRole: SessionClientRole): Promise<void> {\n this._peerConnections.forEach((peerConnection) => {\n if (peerConnection.peerRole === clientRole) {\n this.destroyPublisherOnPeerConnection(peerConnection);\n }\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 (in OT API)\n return Promise.resolve();\n }\n\n getRemoteTrackStats(mediaTrack: MediaStreamTrack): Promise<RemoteTrackStats> {\n //https://tokbox.com/developer/sdks/js/reference/Subscriber.html (getStats)\n return Promise.reject(new Error('Not implemented yet'));\n }\n\n //#region OpenTok Events Handlers\n\n private connectionCreatedHandler(event: any): void {\n trace.info('connectionCreatedHandler', event);\n const {connection} = event;\n\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\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\n const destinationRole = this.calculateDestinationRole();\n\n this.createStreamForPublishing(destinationRole)\n .then((streams: OTStreamSource) => {\n const peerConnection: OTPeerConnection = {\n peerId: connection.connectionId,\n peerRole: destinationRole,\n peerType: this._sessionParams.clientType === SessionClientType.INITIATOR\n ? SessionClientType.GUEST : SessionClientType.INITIATOR,\n connection: connection,\n publisher: null,\n remoteMediaTracks: [],\n localStream: streams\n };\n\n if (!streams.videoSource && !streams.audioSource) {\n trace.info('Peer connection without publisher was created', peerConnection);\n\n return peerConnection;\n }\n\n const streamName = destinationRole === SessionClientRole.USER\n ? KnownMediaStream.AGENT_AUDIO_STREAM : KnownMediaStream.USER_VIDEO_STREAM;\n\n\n return this.createMediaPublisher(streams, streamName)\n .then((publisher: OTPublisher) => {\n peerConnection.publisher = publisher;\n trace.info('Peer connection with publisher was created', peerConnection);\n\n return peerConnection;\n });\n })\n .then((peerConnection: OTPeerConnection) => {\n this._peerConnections.set(peerConnection.peerId, peerConnection);\n\n if (peerConnection.publisher) {\n return new Promise<void>((resolve, reject) => {\n trace.info('Starting publish to peerConnection.publisher');\n this._session!.publish(peerConnection.publisher, (error: any) => {\n if (error) {\n trace.error('Publish to peerConnection error', error);\n\n return reject(error);\n }\n trace.info('Publish to peerConnection success');\n\n return resolve();\n });\n });\n }\n\n return Promise.resolve();\n })\n .catch((error: any) => {\n //Need to handle fail cases during reliability\n trace.error('Error handling new peer connection', error);\n });\n }\n\n private connectionDestroyedHandler(event: any): void {\n trace.info('connectionDestroyedHandler', event);\n const {connection} = event;\n\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n\n if (this._peerConnections.has(connection.connectionId)) {\n this.destroyPeerConnection(this._peerConnections.get(connection.connectionId)!);\n }\n }\n\n private streamCreatedHandler(event: any): void {\n trace.info('streamCreatedHandler', event.stream);\n const {stream} = event;\n const {connection} = stream || {connection: null};\n\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n\n if (!this._peerConnections.has(connection.connectionId)) {\n trace.warn('Unexpected case, connection should exist on this stage');\n\n return;\n }\n\n const peerConnection = this._peerConnections.get(connection.connectionId);\n\n if (!peerConnection) {\n trace.warn('Unexpected PeerConnection not found');\n\n return;\n }\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\n private streamDestroyedHandler(event: any): void {\n trace.info('streamDestroyedHandler', event);\n const {stream} = event;\n\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n\n //Find peerConnection by connectionId, add remove tracks from stream\n //Register each track using addRemoteTrack\n }\n\n //#endregion\n\n private createStreamForPublishing(destinationRole: SessionClientRole): Promise<OTStreamSource> {\n trace.info('createStreamForPublishing');\n\n return this._sessionStreamsManager.getMediaStreamForRole(destinationRole)\n .then((mediaStream: Nullable<MediaStream>) => {\n\n const stream: OTStreamSource = {videoSource: null, audioSource: null};\n\n if (mediaStream) {\n trace.info('Media stream found for publishing', mediaStream);\n mediaStream.getTracks().forEach((track) => {\n if (track.kind === 'video') {\n stream.videoSource = track;\n } else if (track.kind === 'audio') {\n stream.audioSource = track;\n }\n });\n } else if (this._sessionParams.clientRole === SessionClientRole.USER) {\n trace.warn('No local media was found for publishing to destinationRole:', destinationRole);\n }\n\n return stream;\n });\n }\n\n private calculateDestinationRole(): SessionClientRole {\n if (this._sessionParams.clientRole === SessionClientRole.USER) {\n const isAgentConnected = false;\n\n\n return !isAgentConnected ? SessionClientRole.AGENT : SessionClientRole.OBSERVER;\n }\n\n return SessionClientRole.USER;\n }\n\n private createMediaPublisher(stream: OTStreamSource, streamName: string): Promise<OTPublisher> {\n const 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\n return new Promise((resolve, reject) => {\n const otPublisher = window.OT.initPublisher(undefined, otParams, (error: any) => {\n if (error) {\n reject(error);\n \n return;\n }\n resolve(otPublisher);\n });\n });\n }\n\n private clearPeerConnections(): Promise<void> {\n return Promise.resolve();\n }\n\n private sessionExistsGuard(shouldThrow = true): boolean {\n const connected = !!(this._session && this._session.connection && this._session.connection.connectionId);\n\n\n return throwableGuard(connected, 'There no active session', shouldThrow);\n }\n\n private destroyPeerConnection(peerConnection: OTPeerConnection): void {\n this._peerConnections.delete(peerConnection.peerId);\n this.destroyPublisherOnPeerConnection(peerConnection);\n peerConnection.remoteMediaTracks.forEach((mediaTrack) => {\n this._sessionStreamsManager.removeMediaTrack(mediaTrack.mediaTrack)\n .catch((error: any) => {\n trace.warn('Error removing media track', error);\n });\n });\n }\n\n private destroyPublisherOnPeerConnection(peerConnection: OTPeerConnection): void {\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\n}\n\n"]}
1
+ {"version":3,"sources":["../src/MediaSession/SessionOpentok.v3.ts"],"names":[],"mappings":"AAEA,OAAO,EACH,aAAa,EACb,sBAAsB,EACtB,kBAAkB,EAElB,gBAAgB,EACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAmB,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AAEzF,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAKpD,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,EAAE,EAAE,GAAG,CAAC;KACX;CACJ;AAoDD,qBAAa,gBAAiB,SAAQ,gBAAiB,YAAW,aAAa;IAC3E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA8C;IAC/E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAM;IAEnC,OAAO,CAAC,QAAQ,CAA8B;aAE1C,EAAE,EAAI,MAAM;qBAIJ,SAAS;gBAIT,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,sBAAsB;IAkBpF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAwCxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB3B,sBAAsB,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpE,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;IAO5E,OAAO,CAAC,wBAAwB;IA0EhC,OAAO,CAAC,0BAA0B;IAalC,OAAO,CAAC,oBAAoB;IAyD5B,OAAO,CAAC,sBAAsB;IAc9B,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,oBAAoB;IAsB5B,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,gCAAgC;CAY3C","file":"SessionOpentok.v3.d.ts","sourcesContent":["import {Nullable} from '@techsee/techsee-common';\n\nimport {\n IMediaSession,\n ISessionStreamsManager,\n MediaSessionParams,\n RemoteMediaTrack,\n RemoteTrackStats\n} from '../MediaContracts';\n\nimport {KnownMediaStream, SessionClientRole, SessionClientType} from '../MediaConstants';\nimport {throwableGuard} from '@techsee/techsee-common/lib/core/guards';\nimport {MediaSessionBase} from './MediaSessionBase';\nimport {getMediaTracer} from '../MediaUtils/MediaTracer';\n\nconst trace = getMediaTracer('OpentokSessionV3');\n\ndeclare global {\n interface Window {\n OT: any;\n }\n}\n\ninterface IOTSession {\n\n sessionId: string;\n\n connection: Nullable<OTConnection>;\n\n isConnected(): boolean;\n\n connect(token: string, cb: any): void;\n\n disconnect(): void;\n\n publish(publisher: any, cb: any): void;\n\n subscribe(stream: any, container: any, uiProps: any, doneCb: any): OTSubscriber;\n\n off(): void;\n\n on(param: string, cb: any): void;\n\n once(param: string, cb: any): void;\n}\n\ntype OTPublisher = any\n\ntype OTSubscriber = any\n\ntype OTPeerId = any\n\ninterface OTConnection {\n connectionId: string;\n}\n\ninterface OTPeerConnection {\n peerId: OTPeerId;\n peerType: SessionClientType;\n peerRole: SessionClientRole;\n remoteMediaTracks: RemoteMediaTrack[];\n localStream: Nullable<OTStreamSource>;\n connection: OTConnection;\n publisher: Nullable<OTPublisher>;\n subscriber: Nullable<OTSubscriber>;\n}\n\ninterface OTStreamSource {\n videoSource: any;\n audioSource: any;\n}\n\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nexport class OpentokSessionV3 extends MediaSessionBase implements IMediaSession {\n private readonly _peerConnections: Map<OTPeerId, OTPeerConnection> = new Map();\n private readonly _credentials: any;\n\n private _session: Nullable<IOTSession> = null;\n\n get id(): string {\n return this._session && this._session.sessionId ? this._session.sessionId : '';\n }\n\n private get ownPeerId(): string {\n return this._session && this._session.connection ? this._session.connection.connectionId : '';\n }\n\n constructor(sessionParams: MediaSessionParams, streamFactory: ISessionStreamsManager) {\n super(sessionParams, streamFactory);\n this._credentials = sessionParams.credentials;\n\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\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\n connect(): Promise<void> {\n trace.info('Connect to session');\n\n if (this._session) {\n trace.error('Session already exists');\n\n return Promise.reject('Cannot connect to session while another session is active');\n }\n\n return new Promise((resolve, reject) => {\n const handleError = (error: any): void => {\n this._session && this._session!.off();\n this._session = null;\n trace.error('handleConnect error:', error);\n reject(error);\n };\n\n const {apiKey, sessionId} = this._sessionParams.credentials;\n\n this._session = (window as any).OTSESSION = window.OT.initSession(apiKey, sessionId);\n\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\n const connectHandler = (error: any): void => {\n if (error) {\n handleError(error);\n\n return;\n }\n\n resolve();\n };\n\n this._session!.connect(this._credentials.token, connectHandler);\n });\n }\n\n disconnect(): Promise<void> {\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((resolve) => {\n trace.info('Disconnecting from session');\n const currentSession = this._session;\n\n this._session = null;\n\n this._peerConnections.forEach((peerConnection) => {\n this.destroyPeerConnection(peerConnection);\n });\n\n if (!currentSession) {\n trace.info('No active session - resolving');\n resolve();\n\n return;\n }\n currentSession.off();\n currentSession.disconnect();\n resolve();\n });\n }\n\n onMediaStreamDestroyed(clientRole: SessionClientRole): Promise<void> {\n this._peerConnections.forEach((peerConnection) => {\n if (peerConnection.peerRole === clientRole) {\n this.destroyPublisherOnPeerConnection(peerConnection);\n }\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 (in OT API)\n return Promise.resolve();\n }\n\n getRemoteTrackStats(mediaTrack: MediaStreamTrack): Promise<RemoteTrackStats> {\n //https://tokbox.com/developer/sdks/js/reference/Subscriber.html (getStats)\n return Promise.reject(new Error('Not implemented yet'));\n }\n\n //#region OpenTok Events Handlers\n\n private connectionCreatedHandler(event: any): void {\n trace.info('connectionCreatedHandler', event);\n const {connection} = event;\n\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\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\n const destinationRole = this.calculateDestinationRole();\n\n this.createStreamForPublishing(destinationRole)\n .then((streams: OTStreamSource) => {\n const peerConnection: OTPeerConnection = {\n peerId: connection.connectionId,\n peerRole: destinationRole,\n peerType: this._sessionParams.clientType === SessionClientType.INITIATOR\n ? SessionClientType.GUEST : SessionClientType.INITIATOR,\n connection: connection,\n publisher: null,\n subscriber: null,\n remoteMediaTracks: [],\n localStream: streams\n };\n\n if (!streams.videoSource && !streams.audioSource) {\n trace.info('Peer connection without publisher was created', peerConnection);\n\n return peerConnection;\n }\n\n const streamName = destinationRole === SessionClientRole.USER\n ? KnownMediaStream.AGENT_AUDIO_STREAM : KnownMediaStream.USER_VIDEO_STREAM;\n\n\n return this.createMediaPublisher(streams, streamName)\n .then((publisher: OTPublisher) => {\n peerConnection.publisher = publisher;\n trace.info('Peer connection with publisher was created', peerConnection);\n\n return peerConnection;\n });\n })\n .then((peerConnection: OTPeerConnection) => {\n this._peerConnections.set(peerConnection.peerId, peerConnection);\n\n if (peerConnection.publisher) {\n return new Promise<void>((resolve, reject) => {\n trace.info('Starting publish to peerConnection.publisher');\n this._session!.publish(peerConnection.publisher, (error: any) => {\n if (error) {\n trace.error('Publish to peerConnection error', error);\n\n return reject(error);\n }\n trace.info('Publish to peerConnection success');\n\n return resolve();\n });\n });\n }\n\n return Promise.resolve();\n })\n .catch((error: any) => {\n //Need to handle fail cases during reliability\n trace.error('Error handling new peer connection', error);\n });\n }\n\n private connectionDestroyedHandler(event: any): void {\n trace.info('connectionDestroyedHandler', event);\n const {connection} = event;\n\n if (!this.sessionExistsGuard(false) || !connection) {\n return;\n }\n\n if (this._peerConnections.has(connection.connectionId)) {\n this.destroyPeerConnection(this._peerConnections.get(connection.connectionId)!);\n }\n }\n\n private streamCreatedHandler(event: any): void {\n trace.info('streamCreatedHandler', event.stream);\n const {stream} = event;\n const {connection} = stream || {connection: null};\n\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n\n if (!this._peerConnections.has(connection.connectionId)) {\n trace.warn('Unexpected case, connection should exist on this stage');\n\n return;\n }\n\n const peerConnection = this._peerConnections.get(connection.connectionId)!;\n\n if (peerConnection.peerId === this.ownPeerId) {\n trace.warn('There nothing to do with stream from our own peer.');\n\n return;\n }\n\n trace.info('Subscribing the stream');\n peerConnection.subscriber = this._session!.subscribe(stream, null, null, (err: any) => {\n if (err) {\n peerConnection.subscriber = null;\n trace.warn('Error in subscriber', err);\n \n return;\n }\n\n const videoElQuery = `#${peerConnection.subscriber.id} .OT_video-element`;\n const otVideoEl = document.querySelector(videoElQuery);\n\n if (!otVideoEl) {\n trace.warn('Cannot fined OT video element');\n \n return;\n }\n\n document.getElementById(peerConnection.subscriber.id)!.style.display = 'none';\n const otMediaStream: MediaStream = (otVideoEl as any).srcObject;\n\n if (!otMediaStream) {\n trace.warn('MediaStream not found in OT video element');\n \n return;\n }\n\n trace.info('Registering remote media tracks', peerConnection.subscriber);\n otMediaStream.getTracks().forEach((mediaTrack: MediaStreamTrack) => {\n this.registerMediaTrackFromPeer(peerConnection, mediaTrack);\n });\n });\n }\n\n private streamDestroyedHandler(event: any): void {\n trace.info('streamDestroyedHandler', event);\n const {stream} = event;\n\n if (!this.sessionExistsGuard(false) || !stream) {\n return;\n }\n\n //Find peerConnection by connectionId, add remove tracks from stream\n //Register each track using addRemoteTrack\n }\n\n //#endregion\n\n private createStreamForPublishing(destinationRole: SessionClientRole): Promise<OTStreamSource> {\n trace.info('createStreamForPublishing');\n\n return this._sessionStreamsManager.getMediaStreamForRole(destinationRole)\n .then((mediaStream: Nullable<MediaStream>) => {\n\n const stream: OTStreamSource = {videoSource: null, audioSource: null};\n\n if (mediaStream) {\n trace.info('Media stream found for publishing', mediaStream);\n mediaStream.getTracks().forEach((track) => {\n if (track.kind === 'video') {\n stream.videoSource = track;\n } else if (track.kind === 'audio') {\n stream.audioSource = track;\n }\n });\n } else if (this._sessionParams.clientRole === SessionClientRole.USER) {\n trace.warn('No local media was found for publishing to destinationRole:', destinationRole);\n }\n\n return stream;\n });\n }\n\n private calculateDestinationRole(): SessionClientRole {\n if (this._sessionParams.clientRole === SessionClientRole.USER) {\n const isAgentConnected = false;\n\n\n return !isAgentConnected ? SessionClientRole.AGENT : SessionClientRole.OBSERVER;\n }\n\n return SessionClientRole.USER;\n }\n\n private createMediaPublisher(stream: OTStreamSource, streamName: string): Promise<OTPublisher> {\n const 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\n return new Promise((resolve, reject) => {\n const otPublisher = window.OT.initPublisher(undefined, otParams, (error: any) => {\n if (error) {\n reject(error);\n\n return;\n }\n resolve(otPublisher);\n });\n });\n }\n\n private clearPeerConnections(): Promise<void> {\n return Promise.resolve();\n }\n\n private sessionExistsGuard(shouldThrow = true): boolean {\n const connected = !!(this._session && this._session.connection && this._session.connection.connectionId);\n\n\n return throwableGuard(connected, 'There no active session', shouldThrow);\n }\n\n private destroyPeerConnection(peerConnection: OTPeerConnection): void {\n this._peerConnections.delete(peerConnection.peerId);\n this.destroyPublisherOnPeerConnection(peerConnection);\n peerConnection.remoteMediaTracks.forEach((mediaTrack) => {\n this._sessionStreamsManager.removeMediaTrack(mediaTrack.mediaTrack)\n .catch((error: any) => {\n trace.warn('Error removing media track', error);\n });\n });\n }\n\n private destroyPublisherOnPeerConnection(peerConnection: OTPeerConnection): void {\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\n}\n\n"]}
@@ -1,29 +1,50 @@
1
1
  "use strict";
2
2
 
3
+ var __extends = undefined && undefined.__extends || function () {
4
+ var _extendStatics = function extendStatics(d, b) {
5
+ _extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {
6
+ d.__proto__ = b;
7
+ } || function (d, b) {
8
+ for (var p in b) {
9
+ if (b.hasOwnProperty(p)) d[p] = b[p];
10
+ }
11
+ };
12
+ return _extendStatics(d, b);
13
+ };
14
+ return function (d, b) {
15
+ _extendStatics(d, b);
16
+ function __() {
17
+ this.constructor = d;
18
+ }
19
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
20
+ };
21
+ }();
3
22
  Object.defineProperty(exports, "__esModule", { value: true });
4
23
  var MediaConstants_1 = require("../MediaConstants");
5
- var MediaTracer_1 = require("../MediaUtils/MediaTracer");
6
24
  var guards_1 = require("@techsee/techsee-common/lib/core/guards");
7
- var trace = MediaTracer_1.getMediaTracer('OpenTokSession');
25
+ var MediaSessionBase_1 = require("./MediaSessionBase");
26
+ var MediaTracer_1 = require("../MediaUtils/MediaTracer");
27
+ var trace = MediaTracer_1.getMediaTracer('OpentokSessionV3');
8
28
  //Currently this version supports subscribing only. Publishing will be implemented as needed.
9
- var OpentokSessionV3 = /** @class */function () {
29
+ var OpentokSessionV3 = /** @class */function (_super) {
30
+ __extends(OpentokSessionV3, _super);
10
31
  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);
32
+ var _this = _super.call(this, sessionParams, streamFactory) || this;
33
+ _this._peerConnections = new Map();
34
+ _this._session = null;
35
+ _this._credentials = sessionParams.credentials;
36
+ _this.connect = _this.connect.bind(_this);
37
+ _this.disconnect = _this.disconnect.bind(_this);
38
+ _this.onMediaStreamDestroyed = _this.onMediaStreamDestroyed.bind(_this);
39
+ _this.onMediaStreamRenewed = _this.onMediaStreamRenewed.bind(_this);
40
+ _this.createStreamForPublishing = _this.createStreamForPublishing.bind(_this);
41
+ _this.createMediaPublisher = _this.createMediaPublisher.bind(_this);
42
+ _this.clearPeerConnections = _this.clearPeerConnections.bind(_this);
43
+ _this.connectionCreatedHandler = _this.connectionCreatedHandler.bind(_this);
44
+ _this.connectionDestroyedHandler = _this.connectionDestroyedHandler.bind(_this);
45
+ _this.streamCreatedHandler = _this.streamCreatedHandler.bind(_this);
46
+ _this.streamDestroyedHandler = _this.streamDestroyedHandler.bind(_this);
47
+ return _this;
27
48
  }
28
49
  Object.defineProperty(OpentokSessionV3.prototype, "id", {
29
50
  get: function get() {
@@ -76,6 +97,7 @@ var OpentokSessionV3 = /** @class */function () {
76
97
  //TODO - Alex: Implement destroying all publishers (by opentok docs)
77
98
  //Create a method destroy publisher (or publishers can treated the same as "peerConnections"?
78
99
  return new Promise(function (resolve) {
100
+ trace.info('Disconnecting from session');
79
101
  var currentSession = _this._session;
80
102
  _this._session = null;
81
103
  _this._peerConnections.forEach(function (peerConnection) {
@@ -128,6 +150,7 @@ var OpentokSessionV3 = /** @class */function () {
128
150
  peerType: _this._sessionParams.clientType === MediaConstants_1.SessionClientType.INITIATOR ? MediaConstants_1.SessionClientType.GUEST : MediaConstants_1.SessionClientType.INITIATOR,
129
151
  connection: connection,
130
152
  publisher: null,
153
+ subscriber: null,
131
154
  remoteMediaTracks: [],
132
155
  localStream: streams
133
156
  };
@@ -173,6 +196,7 @@ var OpentokSessionV3 = /** @class */function () {
173
196
  }
174
197
  };
175
198
  OpentokSessionV3.prototype.streamCreatedHandler = function (event) {
199
+ var _this = this;
176
200
  trace.info('streamCreatedHandler', event.stream);
177
201
  var stream = event.stream;
178
202
  var connection = (stream || { connection: null }).connection;
@@ -184,13 +208,34 @@ var OpentokSessionV3 = /** @class */function () {
184
208
  return;
185
209
  }
186
210
  var peerConnection = this._peerConnections.get(connection.connectionId);
187
- if (!peerConnection) {
188
- trace.warn('Unexpected PeerConnection not found');
211
+ if (peerConnection.peerId === this.ownPeerId) {
212
+ trace.warn('There nothing to do with stream from our own peer.');
189
213
  return;
190
214
  }
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
215
+ trace.info('Subscribing the stream');
216
+ peerConnection.subscriber = this._session.subscribe(stream, null, null, function (err) {
217
+ if (err) {
218
+ peerConnection.subscriber = null;
219
+ trace.warn('Error in subscriber', err);
220
+ return;
221
+ }
222
+ var videoElQuery = "#" + peerConnection.subscriber.id + " .OT_video-element";
223
+ var otVideoEl = document.querySelector(videoElQuery);
224
+ if (!otVideoEl) {
225
+ trace.warn('Cannot fined OT video element');
226
+ return;
227
+ }
228
+ document.getElementById(peerConnection.subscriber.id).style.display = 'none';
229
+ var otMediaStream = otVideoEl.srcObject;
230
+ if (!otMediaStream) {
231
+ trace.warn('MediaStream not found in OT video element');
232
+ return;
233
+ }
234
+ trace.info('Registering remote media tracks', peerConnection.subscriber);
235
+ otMediaStream.getTracks().forEach(function (mediaTrack) {
236
+ _this.registerMediaTrackFromPeer(peerConnection, mediaTrack);
237
+ });
238
+ });
194
239
  };
195
240
  OpentokSessionV3.prototype.streamDestroyedHandler = function (event) {
196
241
  trace.info('streamDestroyedHandler', event);
@@ -280,7 +325,7 @@ var OpentokSessionV3 = /** @class */function () {
280
325
  }
281
326
  };
282
327
  return OpentokSessionV3;
283
- }();
328
+ }(MediaSessionBase_1.MediaSessionBase);
284
329
  exports.OpentokSessionV3 = OpentokSessionV3;
285
330
 
286
331
  //# sourceMappingURL=SessionOpentok.v3.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["MediaSession/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(\"../MediaUtils/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"]}
1
+ {"version":3,"sources":["MediaSession/SessionOpentok.v3.js"],"names":["__extends","extendStatics","d","b","Object","setPrototypeOf","__proto__","Array","p","hasOwnProperty","__","constructor","prototype","create","defineProperty","exports","value","MediaConstants_1","require","guards_1","MediaSessionBase_1","MediaTracer_1","trace","getMediaTracer","OpentokSessionV3","_super","sessionParams","streamFactory","_this","call","_peerConnections","Map","_session","_credentials","credentials","connect","bind","disconnect","onMediaStreamDestroyed","onMediaStreamRenewed","createStreamForPublishing","createMediaPublisher","clearPeerConnections","connectionCreatedHandler","connectionDestroyedHandler","streamCreatedHandler","streamDestroyedHandler","get","sessionId","enumerable","configurable","connection","connectionId","info","error","Promise","reject","resolve","handleError","off","_a","_sessionParams","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","subscriber","remoteMediaTracks","localStream","videoSource","audioSource","streamName","SessionClientRole","USER","KnownMediaStream","AGENT_AUDIO_STREAM","USER_VIDEO_STREAM","set","publish","catch","has","stream","warn","subscribe","err","videoElQuery","id","otVideoEl","document","querySelector","getElementById","style","display","otMediaStream","srcObject","getTracks","registerMediaTrackFromPeer","_sessionStreamsManager","getMediaStreamForRole","track","kind","isAgentConnected","AGENT","OBSERVER","otParams","publishAudio","publishVideo","showControls","name","otPublisher","initPublisher","undefined","shouldThrow","connected","throwableGuard","delete","removeMediaTrack","MediaSessionBase"],"mappings":"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","file":"SessionOpentok.v3.js","sourcesContent":["\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar MediaConstants_1 = require(\"../MediaConstants\");\nvar guards_1 = require(\"@techsee/techsee-common/lib/core/guards\");\nvar MediaSessionBase_1 = require(\"./MediaSessionBase\");\nvar MediaTracer_1 = require(\"../MediaUtils/MediaTracer\");\nvar trace = MediaTracer_1.getMediaTracer('OpentokSessionV3');\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nvar OpentokSessionV3 = /** @class */ (function (_super) {\n __extends(OpentokSessionV3, _super);\n function OpentokSessionV3(sessionParams, streamFactory) {\n var _this = _super.call(this, sessionParams, streamFactory) || this;\n _this._peerConnections = new Map();\n _this._session = null;\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 return _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 trace.info('Disconnecting from session');\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 subscriber: 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 var _this = this;\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.peerId === this.ownPeerId) {\n trace.warn('There nothing to do with stream from our own peer.');\n return;\n }\n trace.info('Subscribing the stream');\n peerConnection.subscriber = this._session.subscribe(stream, null, null, function (err) {\n if (err) {\n peerConnection.subscriber = null;\n trace.warn('Error in subscriber', err);\n return;\n }\n var videoElQuery = \"#\" + peerConnection.subscriber.id + \" .OT_video-element\";\n var otVideoEl = document.querySelector(videoElQuery);\n if (!otVideoEl) {\n trace.warn('Cannot fined OT video element');\n return;\n }\n document.getElementById(peerConnection.subscriber.id).style.display = 'none';\n var otMediaStream = otVideoEl.srcObject;\n if (!otMediaStream) {\n trace.warn('MediaStream not found in OT video element');\n return;\n }\n trace.info('Registering remote media tracks', peerConnection.subscriber);\n otMediaStream.getTracks().forEach(function (mediaTrack) {\n _this.registerMediaTrackFromPeer(peerConnection, mediaTrack);\n });\n });\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}(MediaSessionBase_1.MediaSessionBase));\nexports.OpentokSessionV3 = OpentokSessionV3;\n\n//# sourceMappingURL=SessionOpentok.v3.js.map\n"]}
@@ -1,16 +1,7 @@
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;
1
+ import { IMediaSession, ISessionStreamsManager, MediaSessionHandlers, MediaSessionParams, RemoteTrackStats } from '../MediaContracts';
2
+ import { SessionClientRole } from '../MediaConstants';
3
+ import { MediaSessionBase } from './MediaSessionBase';
4
+ export declare class TurnWebRtcSessionV3 extends MediaSessionBase implements IMediaSession {
14
5
  private readonly _sessionHandlers;
15
6
  private readonly _pendingPeersIce;
16
7
  private readonly _peerConnections;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/MediaSession/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 '../MediaUtils/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"]}
1
+ {"version":3,"sources":["../src/MediaSession/SessionTurn.v3.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,aAAa,EACb,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EACA,gBAAgB,EACrC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAGH,iBAAiB,EAEpB,MAAM,mBAAmB,CAAC;AAU3B,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAKpD,qBAAa,mBAAoB,SAAQ,gBAAiB,YAAW,aAAa;IAC9E,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;IA6B3H,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;IAsDhD,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 '../MediaUtils/MediaTracer';\nimport {MediaSessionBase} from './MediaSessionBase';\n\nconst trace = getMediaTracer('TurnSessionV3');\n\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nexport class TurnWebRtcSessionV3 extends MediaSessionBase implements IMediaSession {\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 super(sessionParams, 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 this.registerMediaTrackFromPeer(peerConnection, track);\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"]}
@@ -1,5 +1,24 @@
1
1
  "use strict";
2
2
 
3
+ var __extends = undefined && undefined.__extends || function () {
4
+ var _extendStatics = function extendStatics(d, b) {
5
+ _extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {
6
+ d.__proto__ = b;
7
+ } || function (d, b) {
8
+ for (var p in b) {
9
+ if (b.hasOwnProperty(p)) d[p] = b[p];
10
+ }
11
+ };
12
+ return _extendStatics(d, b);
13
+ };
14
+ return function (d, b) {
15
+ _extendStatics(d, b);
16
+ function __() {
17
+ this.constructor = d;
18
+ }
19
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
20
+ };
21
+ }();
3
22
  var __importStar = undefined && undefined.__importStar || function (mod) {
4
23
  if (mod && mod.__esModule) return mod;
5
24
  var result = {};
@@ -17,16 +36,17 @@ var once_1 = __importDefault(require("lodash/once"));
17
36
  var MediaConstants_1 = require("../MediaConstants");
18
37
  var TurnConstants_1 = require("./TurnConstants");
19
38
  var MediaTracer_1 = require("../MediaUtils/MediaTracer");
39
+ var MediaSessionBase_1 = require("./MediaSessionBase");
20
40
  var trace = MediaTracer_1.getMediaTracer('TurnSessionV3');
21
41
  //Currently this version supports subscribing only. Publishing will be implemented as needed.
22
- var TurnWebRtcSessionV3 = /** @class */function () {
42
+ var TurnWebRtcSessionV3 = /** @class */function (_super) {
43
+ __extends(TurnWebRtcSessionV3, _super);
23
44
  function TurnWebRtcSessionV3(sessionParams, sessionHandlers, streamFactory) {
24
- this._sessionParams = sessionParams;
25
- this._sessionStreamsManager = streamFactory;
26
- this._sessionHandlers = sessionHandlers;
27
- this._socket = null;
28
- this._pendingPeersIce = {};
29
- this._peerConnections = new Map();
45
+ var _this = _super.call(this, sessionParams, streamFactory) || this;
46
+ _this._sessionHandlers = sessionHandlers;
47
+ _this._socket = null;
48
+ _this._pendingPeersIce = {};
49
+ _this._peerConnections = new Map();
30
50
  var iceServers = sessionParams.credentials.ice.map(function (item) {
31
51
  return {
32
52
  urls: item.url,
@@ -34,17 +54,18 @@ var TurnWebRtcSessionV3 = /** @class */function () {
34
54
  credential: item.password
35
55
  };
36
56
  });
37
- this._configuration = {
57
+ _this._configuration = {
38
58
  iceServers: iceServers,
39
59
  iceTransportPolicy: 'relay'
40
60
  };
41
- this._joinResponseHandler = this._joinResponseHandler.bind(this);
42
- this._iceCandidateReceivedHandler = this._iceCandidateReceivedHandler.bind(this);
43
- this._sendOfferHandler = this._sendOfferHandler.bind(this);
44
- this._sdpOfferHandler = this._sdpOfferHandler.bind(this);
45
- this._userPeerReconnectHandler = this._userPeerReconnectHandler.bind(this);
46
- this._peerDisconnectedHandler = this._peerDisconnectedHandler.bind(this);
47
- this._onSocketDisconnectedHandler = this._onSocketDisconnectedHandler.bind(this);
61
+ _this._joinResponseHandler = _this._joinResponseHandler.bind(_this);
62
+ _this._iceCandidateReceivedHandler = _this._iceCandidateReceivedHandler.bind(_this);
63
+ _this._sendOfferHandler = _this._sendOfferHandler.bind(_this);
64
+ _this._sdpOfferHandler = _this._sdpOfferHandler.bind(_this);
65
+ _this._userPeerReconnectHandler = _this._userPeerReconnectHandler.bind(_this);
66
+ _this._peerDisconnectedHandler = _this._peerDisconnectedHandler.bind(_this);
67
+ _this._onSocketDisconnectedHandler = _this._onSocketDisconnectedHandler.bind(_this);
68
+ return _this;
48
69
  }
49
70
  Object.defineProperty(TurnWebRtcSessionV3.prototype, "id", {
50
71
  get: function get() {
@@ -131,17 +152,7 @@ var TurnWebRtcSessionV3 = /** @class */function () {
131
152
  peerConnection.ontrack = function (trackEvent) {
132
153
  var track = trackEvent.track;
133
154
  trace.info("MediaStreamTrack arrived from peerConnection: " + track.kind, track);
134
- //We only support to stream audio from dashboard
135
- if (track.kind.toLowerCase() === 'audio') {
136
- var remoteMediaTrack = {
137
- mediaTrack: track,
138
- trackType: MediaConstants_1.KnownMediaStream.AGENT_AUDIO_STREAM
139
- };
140
- peerConnection.remoteMediaTracks.push(remoteMediaTrack);
141
- _this._sessionStreamsManager.addRemoteMediaTrack(remoteMediaTrack).catch(function (error) {
142
- trace.warn('Error adding remote media track to available streams', error);
143
- });
144
- }
155
+ _this.registerMediaTrackFromPeer(peerConnection, track);
145
156
  };
146
157
  //TODO - Alex: Currently we not sending "role" through signaling, and by default we assume that the one who asks fot offer, is agent.
147
158
  //On later stages we can send or the client "role" or the list of "streams" that peer is interested in.
@@ -435,7 +446,7 @@ var TurnWebRtcSessionV3 = /** @class */function () {
435
446
  });
436
447
  };
437
448
  return TurnWebRtcSessionV3;
438
- }();
449
+ }(MediaSessionBase_1.MediaSessionBase);
439
450
  exports.TurnWebRtcSessionV3 = TurnWebRtcSessionV3;
440
451
 
441
452
  //# sourceMappingURL=SessionTurn.v3.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["MediaSession/SessionTurn.v3.js"],"names":["__importStar","mod","__esModule","result","k","Object","hasOwnProperty","call","__importDefault","defineProperty","exports","value","io","require","once_1","MediaConstants_1","TurnConstants_1","MediaTracer_1","trace","getMediaTracer","TurnWebRtcSessionV3","sessionParams","sessionHandlers","streamFactory","_sessionParams","_sessionStreamsManager","_sessionHandlers","_socket","_pendingPeersIce","_peerConnections","Map","iceServers","credentials","ice","map","item","urls","url","username","login","credential","password","_configuration","iceTransportPolicy","_joinResponseHandler","bind","_iceCandidateReceivedHandler","_sendOfferHandler","_sdpOfferHandler","_userPeerReconnectHandler","_peerDisconnectedHandler","_onSocketDisconnectedHandler","prototype","get","sessionId","enumerable","configurable","connect","connectOnly","_this","info","_connectSocket","then","emit","SOCKET_EVENTS","OUTGOING","JOIN_ROOM","clientType","catch","error","disconnect","_disconnectInternal","MediaSessionDisconnectReason","ForcedByConsumer","Promise","resolve","reject","socket","SOCKET_RECONNECTION_DELAY","SOCKET_RECONNECTION_DELAY_MAX","SOCKET_RECONNECTION_ATTEMPTS","SOCKET_PATH","done","default","err","once","on","INCOMING","ERROR","SEND_OFFER","JOIN_RESPONSE","PEER_DISCONNECTED","SDP_OFFER","PUBLISHER_RECONNECT","ICE_CANDIDATE","reason","SignalingChannelDisconnect","undefined","sendOfferEventData","uid","peerId","peerConnection","_createPeerConnection","SessionClientType","GUEST","SessionClientRole","AGENT","offerParams","offerToReceiveAudio","offerToReceiveVideo","ontrack","trackEvent","track","kind","toLowerCase","remoteMediaTrack","mediaTrack","trackType","KnownMediaStream","AGENT_AUDIO_STREAM","remoteMediaTracks","push","addRemoteMediaTrack","warn","getMediaStreamForRole","mediaStream","getTracks","forEach","addTrack","createOffer","offerDesc","sdpOffer","sdp","setLocalDescription","e","joinResponseData","sdpAnswer","_withPeerConnection","answer","RTCSessionDescription","type","setRemoteDescription","_processQueuedIceCandidates","peerDisconnectedEvent","PeerDisconnected","sdpOfferEvent","INITIATOR","USER","remoteTrack","USER_VIDEO_STREAM","USER_AUDIO_STREAM","remoteDesc","createAnswer","SDP_ANSWER","UserPeerReconnected","onMediaStreamDestroyed","clientRole","PublishedStreamDestroyed","onMediaStreamRenewed","getRemoteTrackStats","peerConnectionOfTrack","filter","id","length","getStats","Error","_destroyPeerConnection","off","setTimeout","onDisconnectedHandler","peerConnectionType","peerConnectionRole","RTCPeerConnection","peerType","peerRole","onconnectionstatechange","oniceconnectionstatechange","state","currentTarget","iceConnectionState","cnState","indexOf","_iceStateDisconnected","onicecandidate","event","candidate","set","onicegatheringstatechange","removeMediaTrack","delete","close","callback","iceCandidateData","remoteDescription","_queueIceCandidate","_addIceCandidateToPeer","iceCandidate","addIceCandidate","pendingIces","pendingIce","PeerConnectionInterrupted"],"mappings":"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","file":"SessionTurn.v3.js","sourcesContent":["\"use strict\";\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\n result[\"default\"] = mod;\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar io = __importStar(require(\"socket.io-client\"));\nvar once_1 = __importDefault(require(\"lodash/once\"));\nvar MediaConstants_1 = require(\"../MediaConstants\");\nvar TurnConstants_1 = require(\"./TurnConstants\");\nvar MediaTracer_1 = require(\"../MediaUtils/MediaTracer\");\nvar trace = MediaTracer_1.getMediaTracer('TurnSessionV3');\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nvar TurnWebRtcSessionV3 = /** @class */ (function () {\n function TurnWebRtcSessionV3(sessionParams, sessionHandlers, streamFactory) {\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 var iceServers = sessionParams.credentials.ice.map(function (item) { return ({\n urls: item.url,\n username: item.login,\n credential: item.password\n }); });\n this._configuration = {\n iceServers: iceServers,\n iceTransportPolicy: 'relay'\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 Object.defineProperty(TurnWebRtcSessionV3.prototype, \"id\", {\n get: function () {\n return this._sessionParams.sessionId;\n },\n enumerable: true,\n configurable: true\n });\n //#region Socket Connectivity\n TurnWebRtcSessionV3.prototype.connect = function (connectOnly) {\n var _this = this;\n if (connectOnly === void 0) { connectOnly = false; }\n trace.info('Connect to session');\n return this._connectSocket(this._sessionParams.credentials.url, connectOnly)\n .then(function () {\n trace.info('Joining SessionId: ' + _this._sessionParams.sessionId);\n _this._socket.emit(TurnConstants_1.SOCKET_EVENTS.OUTGOING.JOIN_ROOM, {\n clientType: _this._sessionParams.clientType,\n sessionId: _this._sessionParams.sessionId\n });\n })\n .catch(function (error) {\n throw error;\n });\n };\n TurnWebRtcSessionV3.prototype.disconnect = function () {\n return this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.ForcedByConsumer);\n };\n TurnWebRtcSessionV3.prototype._connectSocket = function (url, connectOnly) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n var socket = _this._socket = io.connect(url, {\n 'forceNew': true,\n 'reconnectionDelay': TurnConstants_1.SOCKET_RECONNECTION_DELAY,\n 'reconnectionDelayMax': TurnConstants_1.SOCKET_RECONNECTION_DELAY_MAX,\n 'reconnectionAttempts': TurnConstants_1.SOCKET_RECONNECTION_ATTEMPTS,\n 'path': TurnConstants_1.SOCKET_PATH\n });\n var done = once_1.default(function (err) {\n err ? reject(err) : resolve();\n });\n socket.once('connect', function () { return done(); });\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.ERROR, done);\n socket.on('connect_error', done);\n socket.on('connect_timeout', done);\n socket.on('disconnect', _this._onSocketDisconnectedHandler);\n if (!connectOnly) {\n trace.info('Subscribing socket events');\n //PUBLISHING NOT SUPPORTED YET\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.SEND_OFFER, _this._sendOfferHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.JOIN_RESPONSE, _this._joinResponseHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.PEER_DISCONNECTED, _this._peerDisconnectedHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.SDP_OFFER, _this._sdpOfferHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.PUBLISHER_RECONNECT, _this._userPeerReconnectHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.ICE_CANDIDATE, _this._iceCandidateReceivedHandler);\n }\n });\n };\n TurnWebRtcSessionV3.prototype._onSocketDisconnectedHandler = function (reason) {\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(MediaConstants_1.MediaSessionDisconnectReason.SignalingChannelDisconnect).catch(function () { return undefined; });\n }\n }\n };\n //#endregion\n //#region WebRTC Initiator - session Initiator (User on mobile device)\n // Received by Initiator, causing him to emit SDP_OFFER\n TurnWebRtcSessionV3.prototype._sendOfferHandler = function (sendOfferEventData) {\n var _this = this;\n var uid = sendOfferEventData.uid, peerId = sendOfferEventData.peerId;\n trace.info('_sendOfferHandler');\n //Currently we not support of passing role through signaling, so we assume every connection is \"AGENT\" like\n var peerConnection = this._createPeerConnection(peerId, MediaConstants_1.SessionClientType.GUEST, MediaConstants_1.SessionClientRole.AGENT);\n var offerParams = { offerToReceiveAudio: true, offerToReceiveVideo: true };\n peerConnection.ontrack = function (trackEvent) {\n var track = trackEvent.track;\n trace.info(\"MediaStreamTrack arrived from peerConnection: \" + track.kind, track);\n //We only support to stream audio from dashboard\n if (track.kind.toLowerCase() === 'audio') {\n var remoteMediaTrack = {\n mediaTrack: track,\n trackType: MediaConstants_1.KnownMediaStream.AGENT_AUDIO_STREAM\n };\n peerConnection.remoteMediaTracks.push(remoteMediaTrack);\n _this._sessionStreamsManager.addRemoteMediaTrack(remoteMediaTrack)\n .catch(function (error) {\n trace.warn('Error adding remote media track to available streams', error);\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(MediaConstants_1.SessionClientRole.AGENT)\n .then(function (mediaStream) {\n trace.info('_sendOfferHandler stream and peer created');\n if (mediaStream) {\n trace.info('Adding local tracks to peer connection');\n mediaStream.getTracks().forEach(function (track) {\n peerConnection.addTrack(track, mediaStream);\n trace.info(\"Local \" + track.kind + \" track added to peer connection\");\n });\n }\n else {\n trace.info('No media stream was found for publishing');\n }\n })\n .then(function () { return peerConnection.createOffer(offerParams); })\n .then(function (offerDesc) {\n trace.info('Initiator has created sdp offer', { offerDesc: offerDesc });\n _this._socket.emit(TurnConstants_1.SOCKET_EVENTS.OUTGOING.SDP_OFFER, {\n uid: uid,\n peerId: peerId,\n sessionId: _this._sessionParams.sessionId,\n sdpOffer: offerDesc.sdp\n });\n return peerConnection.setLocalDescription(offerDesc)\n .then(function () {\n trace.info('Local description was set on peerConnection', peerConnection);\n });\n })\n .catch(function (e) {\n trace.warn('Error', e);\n });\n };\n // Received by the Initiator: Indicates that publish should be started\n TurnWebRtcSessionV3.prototype._joinResponseHandler = function (joinResponseData) {\n var _this = this;\n var sdpAnswer = joinResponseData.sdpAnswer, uid = joinResponseData.uid, peerId = joinResponseData.peerId;\n trace.info('joinResponse Received', { sdpAnswer: sdpAnswer });\n this._withPeerConnection(peerId, function (peerConnection) {\n var answer = new RTCSessionDescription({\n type: 'answer',\n sdp: sdpAnswer\n });\n peerConnection.setRemoteDescription(answer)\n .then(function () {\n trace.info('Remote description was set', answer);\n _this._processQueuedIceCandidates(peerId);\n })\n .catch(function (e) {\n trace.warn('Error', e);\n });\n });\n };\n // Received by Initiator after a guests socket has been disconnected\n TurnWebRtcSessionV3.prototype._peerDisconnectedHandler = function (peerDisconnectedEvent) {\n var _this = this;\n var peerId = peerDisconnectedEvent.peerId;\n trace.info('_peerDisconnectedHandler');\n this._withPeerConnection(peerId, function (peerConnection) {\n _this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.PeerDisconnected).catch(function () { return undefined; });\n });\n };\n //#endregion WebRTC Initiator - session Initiator (User on mobile device)\n //#region WebRTC Guest - session Guest (Agent on dashboard platform)\n // Received by Guest, causing him to emit SDP_ANSWER\n TurnWebRtcSessionV3.prototype._sdpOfferHandler = function (sdpOfferEvent) {\n var _this = this;\n var sdpOffer = sdpOfferEvent.sdpOffer, peerId = sdpOfferEvent.peerId, uid = sdpOfferEvent.uid;\n trace.info('sdpOffer Received', { sdpOffer: sdpOffer });\n var peerConnection = this._createPeerConnection(peerId, MediaConstants_1.SessionClientType.INITIATOR, MediaConstants_1.SessionClientRole.USER);\n peerConnection.ontrack = function (trackEvent) {\n var track = trackEvent.track;\n trace.info(\"MediaStreamTrack arrived from peerConnection: \" + track.kind, track);\n var remoteTrack = {\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 ? MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM : MediaConstants_1.KnownMediaStream.USER_AUDIO_STREAM\n };\n peerConnection.remoteMediaTracks.push(remoteTrack);\n _this._sessionStreamsManager.addRemoteMediaTrack(remoteTrack)\n .catch(function () {\n trace.warn('Error adding remote track to stream manager', remoteTrack);\n });\n };\n this._sessionStreamsManager.getMediaStreamForRole(MediaConstants_1.SessionClientRole.USER)\n .then(function (mediaStream) {\n if (mediaStream) {\n trace.info('Adding local tracks to peer connection');\n mediaStream.getTracks().forEach(function (track) {\n peerConnection.addTrack(track, mediaStream);\n trace.info(\"Local \" + track.kind + \" track added to peer connection\");\n });\n }\n else {\n trace.info('No media stream was found for publishing');\n }\n })\n .then(function () {\n var remoteDesc = new RTCSessionDescription({ type: 'offer', sdp: sdpOffer });\n return peerConnection.setRemoteDescription(remoteDesc)\n .then(function () {\n trace.info('Remote description was set', remoteDesc);\n return peerConnection.createAnswer()\n .then(function (sdpAnswer) {\n trace.info('_sdpOfferHandler answer created', sdpAnswer);\n _this._socket.emit(TurnConstants_1.SOCKET_EVENTS.OUTGOING.SDP_ANSWER, {\n uid: uid,\n peerId: peerId,\n sessionId: _this._sessionParams.sessionId,\n sdpAnswer: sdpAnswer.sdp\n });\n return peerConnection.setLocalDescription(sdpAnswer)\n .then(function () {\n trace.info('_sdpOfferHandler local desc was set');\n _this._processQueuedIceCandidates(peerId);\n });\n });\n });\n })\n .catch(function (e) {\n trace.error('Error in _sdpOfferHandler', e);\n throw e;\n });\n };\n // Received by Guest after an Initiator reconnects to room\n TurnWebRtcSessionV3.prototype._userPeerReconnectHandler = function () {\n trace.info('_userPeerReconnectHandler');\n this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.UserPeerReconnected)\n .catch(function (error) {\n trace.warn('Error while disconnecting during userPeerReconnectHandler.', error);\n });\n };\n //#endregion WebRTC Guest - session Guest (Agent on dashboard platform)\n //#region Peer Connection\n //#region Streams Handling\n TurnWebRtcSessionV3.prototype.onMediaStreamDestroyed = function (clientRole) {\n var _this = this;\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation\n this._peerConnections.forEach(function (peerConnection) {\n _this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.PublishedStreamDestroyed).catch(function () { return undefined; });\n });\n return Promise.resolve();\n };\n TurnWebRtcSessionV3.prototype.onMediaStreamRenewed = function (clientRole, mediaStream) {\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation\n return Promise.resolve();\n };\n TurnWebRtcSessionV3.prototype.getRemoteTrackStats = function (mediaTrack) {\n var peerConnectionOfTrack = null;\n this._peerConnections.forEach(function (peerConnection) {\n var remoteTrack = peerConnection.remoteMediaTracks.filter(function (track) { return track.mediaTrack.id === mediaTrack.id; });\n if (remoteTrack.length === 1) {\n peerConnectionOfTrack = peerConnection;\n }\n });\n if (peerConnectionOfTrack !== null) {\n return peerConnectionOfTrack.getStats(mediaTrack);\n }\n return Promise.reject(new Error('Provided track is not remote track'));\n };\n //#endregion\n TurnWebRtcSessionV3.prototype._disconnectInternal = function (reason) {\n var _this = this;\n this._peerConnections.forEach(function (peerConnection) {\n _this._destroyPeerConnection(peerConnection);\n });\n trace.info('Disconnecting from session', reason);\n if (this._socket) {\n this._socket.off();\n this._socket.disconnect();\n }\n this._socket = null;\n setTimeout(function () { return _this._sessionHandlers.onDisconnectedHandler(reason); });\n return Promise.resolve();\n };\n TurnWebRtcSessionV3.prototype._createPeerConnection = function (peerId, peerConnectionType, peerConnectionRole) {\n var _this = this;\n if (this._peerConnections.get(peerId)) {\n throw new Error(this._sessionParams.clientType + \" peer connection for \" + peerId + \" already exists\");\n }\n var peerConnection = new RTCPeerConnection(this._configuration);\n peerConnection.peerId = peerId;\n peerConnection.peerType = peerConnectionType;\n peerConnection.remoteMediaTracks = [];\n peerConnection.peerRole = peerConnectionRole;\n peerConnection.onconnectionstatechange = function () {\n trace.info('onconnectionstatechange', peerConnection);\n };\n peerConnection.oniceconnectionstatechange = function (state) {\n trace.info(\"ICE Connection state for peer \" + peerId + \" was changed to: \" + state.currentTarget.iceConnectionState, state);\n var cnState = state.currentTarget.iceConnectionState;\n if (['closed', 'disconnected', 'failed'].indexOf(cnState) > -1) {\n _this._iceStateDisconnected(peerConnection);\n }\n };\n peerConnection.onicecandidate = function (event) {\n if (event.candidate) {\n trace.info(_this._sessionParams.clientType + \" peerConn.onicecandidate\", event.candidate);\n _this._socket.emit(TurnConstants_1.SOCKET_EVENTS.OUTGOING.ICE_CANDIDATE, {\n sessionId: _this._sessionParams.sessionId,\n peerId: peerId,\n candidate: event.candidate,\n clientType: _this._sessionParams.clientType\n });\n }\n else {\n trace.info('ICE Candidate is null in peerConnection', event);\n }\n };\n this._peerConnections.set(peerId, peerConnection);\n trace.info(peerConnectionType + \" peerConnection created\");\n return peerConnection;\n };\n TurnWebRtcSessionV3.prototype._destroyPeerConnection = function (peerConnection) {\n var _this = this;\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 peerConnection.remoteMediaTracks.forEach(function (remoteMediaTrack) {\n _this._sessionStreamsManager.removeMediaTrack(remoteMediaTrack.mediaTrack)\n .catch(function () {\n trace.warn('Error while removing remote media track', remoteMediaTrack);\n });\n });\n this._peerConnections.delete(peerConnection.peerId);\n peerConnection.close();\n };\n TurnWebRtcSessionV3.prototype._withPeerConnection = function (peerId, callback) {\n if (this._peerConnections.get(peerId)) {\n return callback(this._peerConnections.get(peerId));\n }\n return undefined;\n };\n //#endregion\n //#region ICE Candidates\n TurnWebRtcSessionV3.prototype._iceCandidateReceivedHandler = function (iceCandidateData) {\n var candidate = iceCandidateData.candidate, peerId = iceCandidateData.peerId;\n trace.info('_iceCandidateReceivedHandler', candidate);\n if (!candidate) {\n trace.info('Unexpected case, iceCandidate message arrived without candidate');\n return;\n }\n var peerConnection = this._peerConnections.get(peerId);\n if (!peerConnection || !peerConnection.remoteDescription) {\n trace.info('Queueing iceCandidate', candidate);\n this._queueIceCandidate(candidate, peerId);\n return;\n }\n trace.info('Going to add iceCandidate', candidate);\n this._addIceCandidateToPeer(candidate, peerConnection).catch(function () { return undefined; });\n };\n TurnWebRtcSessionV3.prototype._addIceCandidateToPeer = function (iceCandidate, peerConnection) {\n return peerConnection.addIceCandidate(iceCandidate)\n .then(function () {\n trace.info('ICE Candidate add to peer connection');\n })\n .catch(function (e) {\n trace.warn('Error adding ICE Candidate to peer connection', e);\n throw e;\n });\n };\n TurnWebRtcSessionV3.prototype._processQueuedIceCandidates = function (peerId) {\n var _this = this;\n this._withPeerConnection(peerId, function (peerConnection) {\n var pendingIces = _this._pendingPeersIce[peerId];\n if (pendingIces) {\n pendingIces.forEach(function (pendingIce) {\n trace.info('Adding pending ICE to peer connections');\n _this._addIceCandidateToPeer(pendingIce, peerConnection).catch(function () { return undefined; });\n });\n }\n else {\n trace.info('No pending ICE found for peer', peerId);\n }\n });\n };\n TurnWebRtcSessionV3.prototype._queueIceCandidate = function (iceCandidate, peerId) {\n if (!this._pendingPeersIce[peerId]) {\n this._pendingPeersIce[peerId] = [];\n }\n this._pendingPeersIce[peerId].push(iceCandidate);\n };\n TurnWebRtcSessionV3.prototype._iceStateDisconnected = function (peerConnection) {\n this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.PeerConnectionInterrupted).catch(function () { return undefined; });\n };\n return TurnWebRtcSessionV3;\n}());\nexports.TurnWebRtcSessionV3 = TurnWebRtcSessionV3;\n\n//# sourceMappingURL=SessionTurn.v3.js.map\n"]}
1
+ {"version":3,"sources":["MediaSession/SessionTurn.v3.js"],"names":["__extends","extendStatics","d","b","Object","setPrototypeOf","__proto__","Array","p","hasOwnProperty","__","constructor","prototype","create","__importStar","mod","__esModule","result","k","call","__importDefault","defineProperty","exports","value","io","require","once_1","MediaConstants_1","TurnConstants_1","MediaTracer_1","MediaSessionBase_1","trace","getMediaTracer","TurnWebRtcSessionV3","_super","sessionParams","sessionHandlers","streamFactory","_this","_sessionHandlers","_socket","_pendingPeersIce","_peerConnections","Map","iceServers","credentials","ice","map","item","urls","url","username","login","credential","password","_configuration","iceTransportPolicy","_joinResponseHandler","bind","_iceCandidateReceivedHandler","_sendOfferHandler","_sdpOfferHandler","_userPeerReconnectHandler","_peerDisconnectedHandler","_onSocketDisconnectedHandler","get","_sessionParams","sessionId","enumerable","configurable","connect","connectOnly","info","_connectSocket","then","emit","SOCKET_EVENTS","OUTGOING","JOIN_ROOM","clientType","catch","error","disconnect","_disconnectInternal","MediaSessionDisconnectReason","ForcedByConsumer","Promise","resolve","reject","socket","SOCKET_RECONNECTION_DELAY","SOCKET_RECONNECTION_DELAY_MAX","SOCKET_RECONNECTION_ATTEMPTS","SOCKET_PATH","done","default","err","once","on","INCOMING","ERROR","SEND_OFFER","JOIN_RESPONSE","PEER_DISCONNECTED","SDP_OFFER","PUBLISHER_RECONNECT","ICE_CANDIDATE","reason","SignalingChannelDisconnect","undefined","sendOfferEventData","uid","peerId","peerConnection","_createPeerConnection","SessionClientType","GUEST","SessionClientRole","AGENT","offerParams","offerToReceiveAudio","offerToReceiveVideo","ontrack","trackEvent","track","kind","registerMediaTrackFromPeer","_sessionStreamsManager","getMediaStreamForRole","mediaStream","getTracks","forEach","addTrack","createOffer","offerDesc","sdpOffer","sdp","setLocalDescription","e","warn","joinResponseData","sdpAnswer","_withPeerConnection","answer","RTCSessionDescription","type","setRemoteDescription","_processQueuedIceCandidates","peerDisconnectedEvent","PeerDisconnected","sdpOfferEvent","INITIATOR","USER","remoteTrack","mediaTrack","trackType","KnownMediaStream","USER_VIDEO_STREAM","USER_AUDIO_STREAM","remoteMediaTracks","push","addRemoteMediaTrack","remoteDesc","createAnswer","SDP_ANSWER","UserPeerReconnected","onMediaStreamDestroyed","clientRole","PublishedStreamDestroyed","onMediaStreamRenewed","getRemoteTrackStats","peerConnectionOfTrack","filter","id","length","getStats","Error","_destroyPeerConnection","off","setTimeout","onDisconnectedHandler","peerConnectionType","peerConnectionRole","RTCPeerConnection","peerType","peerRole","onconnectionstatechange","oniceconnectionstatechange","state","currentTarget","iceConnectionState","cnState","indexOf","_iceStateDisconnected","onicecandidate","event","candidate","set","onicegatheringstatechange","remoteMediaTrack","removeMediaTrack","delete","close","callback","iceCandidateData","remoteDescription","_queueIceCandidate","_addIceCandidateToPeer","iceCandidate","addIceCandidate","pendingIces","pendingIce","PeerConnectionInterrupted","MediaSessionBase"],"mappings":"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","file":"SessionTurn.v3.js","sourcesContent":["\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\n result[\"default\"] = mod;\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar io = __importStar(require(\"socket.io-client\"));\nvar once_1 = __importDefault(require(\"lodash/once\"));\nvar MediaConstants_1 = require(\"../MediaConstants\");\nvar TurnConstants_1 = require(\"./TurnConstants\");\nvar MediaTracer_1 = require(\"../MediaUtils/MediaTracer\");\nvar MediaSessionBase_1 = require(\"./MediaSessionBase\");\nvar trace = MediaTracer_1.getMediaTracer('TurnSessionV3');\n//Currently this version supports subscribing only. Publishing will be implemented as needed.\nvar TurnWebRtcSessionV3 = /** @class */ (function (_super) {\n __extends(TurnWebRtcSessionV3, _super);\n function TurnWebRtcSessionV3(sessionParams, sessionHandlers, streamFactory) {\n var _this = _super.call(this, sessionParams, streamFactory) || this;\n _this._sessionHandlers = sessionHandlers;\n _this._socket = null;\n _this._pendingPeersIce = {};\n _this._peerConnections = new Map();\n var iceServers = sessionParams.credentials.ice.map(function (item) { return ({\n urls: item.url,\n username: item.login,\n credential: item.password\n }); });\n _this._configuration = {\n iceServers: iceServers,\n iceTransportPolicy: 'relay'\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 return _this;\n }\n Object.defineProperty(TurnWebRtcSessionV3.prototype, \"id\", {\n get: function () {\n return this._sessionParams.sessionId;\n },\n enumerable: true,\n configurable: true\n });\n //#region Socket Connectivity\n TurnWebRtcSessionV3.prototype.connect = function (connectOnly) {\n var _this = this;\n if (connectOnly === void 0) { connectOnly = false; }\n trace.info('Connect to session');\n return this._connectSocket(this._sessionParams.credentials.url, connectOnly)\n .then(function () {\n trace.info('Joining SessionId: ' + _this._sessionParams.sessionId);\n _this._socket.emit(TurnConstants_1.SOCKET_EVENTS.OUTGOING.JOIN_ROOM, {\n clientType: _this._sessionParams.clientType,\n sessionId: _this._sessionParams.sessionId\n });\n })\n .catch(function (error) {\n throw error;\n });\n };\n TurnWebRtcSessionV3.prototype.disconnect = function () {\n return this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.ForcedByConsumer);\n };\n TurnWebRtcSessionV3.prototype._connectSocket = function (url, connectOnly) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n var socket = _this._socket = io.connect(url, {\n 'forceNew': true,\n 'reconnectionDelay': TurnConstants_1.SOCKET_RECONNECTION_DELAY,\n 'reconnectionDelayMax': TurnConstants_1.SOCKET_RECONNECTION_DELAY_MAX,\n 'reconnectionAttempts': TurnConstants_1.SOCKET_RECONNECTION_ATTEMPTS,\n 'path': TurnConstants_1.SOCKET_PATH\n });\n var done = once_1.default(function (err) {\n err ? reject(err) : resolve();\n });\n socket.once('connect', function () { return done(); });\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.ERROR, done);\n socket.on('connect_error', done);\n socket.on('connect_timeout', done);\n socket.on('disconnect', _this._onSocketDisconnectedHandler);\n if (!connectOnly) {\n trace.info('Subscribing socket events');\n //PUBLISHING NOT SUPPORTED YET\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.SEND_OFFER, _this._sendOfferHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.JOIN_RESPONSE, _this._joinResponseHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.PEER_DISCONNECTED, _this._peerDisconnectedHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.SDP_OFFER, _this._sdpOfferHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.PUBLISHER_RECONNECT, _this._userPeerReconnectHandler);\n socket.on(TurnConstants_1.SOCKET_EVENTS.INCOMING.ICE_CANDIDATE, _this._iceCandidateReceivedHandler);\n }\n });\n };\n TurnWebRtcSessionV3.prototype._onSocketDisconnectedHandler = function (reason) {\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(MediaConstants_1.MediaSessionDisconnectReason.SignalingChannelDisconnect).catch(function () { return undefined; });\n }\n }\n };\n //#endregion\n //#region WebRTC Initiator - session Initiator (User on mobile device)\n // Received by Initiator, causing him to emit SDP_OFFER\n TurnWebRtcSessionV3.prototype._sendOfferHandler = function (sendOfferEventData) {\n var _this = this;\n var uid = sendOfferEventData.uid, peerId = sendOfferEventData.peerId;\n trace.info('_sendOfferHandler');\n //Currently we not support of passing role through signaling, so we assume every connection is \"AGENT\" like\n var peerConnection = this._createPeerConnection(peerId, MediaConstants_1.SessionClientType.GUEST, MediaConstants_1.SessionClientRole.AGENT);\n var offerParams = { offerToReceiveAudio: true, offerToReceiveVideo: true };\n peerConnection.ontrack = function (trackEvent) {\n var track = trackEvent.track;\n trace.info(\"MediaStreamTrack arrived from peerConnection: \" + track.kind, track);\n _this.registerMediaTrackFromPeer(peerConnection, track);\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(MediaConstants_1.SessionClientRole.AGENT)\n .then(function (mediaStream) {\n trace.info('_sendOfferHandler stream and peer created');\n if (mediaStream) {\n trace.info('Adding local tracks to peer connection');\n mediaStream.getTracks().forEach(function (track) {\n peerConnection.addTrack(track, mediaStream);\n trace.info(\"Local \" + track.kind + \" track added to peer connection\");\n });\n }\n else {\n trace.info('No media stream was found for publishing');\n }\n })\n .then(function () { return peerConnection.createOffer(offerParams); })\n .then(function (offerDesc) {\n trace.info('Initiator has created sdp offer', { offerDesc: offerDesc });\n _this._socket.emit(TurnConstants_1.SOCKET_EVENTS.OUTGOING.SDP_OFFER, {\n uid: uid,\n peerId: peerId,\n sessionId: _this._sessionParams.sessionId,\n sdpOffer: offerDesc.sdp\n });\n return peerConnection.setLocalDescription(offerDesc)\n .then(function () {\n trace.info('Local description was set on peerConnection', peerConnection);\n });\n })\n .catch(function (e) {\n trace.warn('Error', e);\n });\n };\n // Received by the Initiator: Indicates that publish should be started\n TurnWebRtcSessionV3.prototype._joinResponseHandler = function (joinResponseData) {\n var _this = this;\n var sdpAnswer = joinResponseData.sdpAnswer, uid = joinResponseData.uid, peerId = joinResponseData.peerId;\n trace.info('joinResponse Received', { sdpAnswer: sdpAnswer });\n this._withPeerConnection(peerId, function (peerConnection) {\n var answer = new RTCSessionDescription({\n type: 'answer',\n sdp: sdpAnswer\n });\n peerConnection.setRemoteDescription(answer)\n .then(function () {\n trace.info('Remote description was set', answer);\n _this._processQueuedIceCandidates(peerId);\n })\n .catch(function (e) {\n trace.warn('Error', e);\n });\n });\n };\n // Received by Initiator after a guests socket has been disconnected\n TurnWebRtcSessionV3.prototype._peerDisconnectedHandler = function (peerDisconnectedEvent) {\n var _this = this;\n var peerId = peerDisconnectedEvent.peerId;\n trace.info('_peerDisconnectedHandler');\n this._withPeerConnection(peerId, function (peerConnection) {\n _this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.PeerDisconnected).catch(function () { return undefined; });\n });\n };\n //#endregion WebRTC Initiator - session Initiator (User on mobile device)\n //#region WebRTC Guest - session Guest (Agent on dashboard platform)\n // Received by Guest, causing him to emit SDP_ANSWER\n TurnWebRtcSessionV3.prototype._sdpOfferHandler = function (sdpOfferEvent) {\n var _this = this;\n var sdpOffer = sdpOfferEvent.sdpOffer, peerId = sdpOfferEvent.peerId, uid = sdpOfferEvent.uid;\n trace.info('sdpOffer Received', { sdpOffer: sdpOffer });\n var peerConnection = this._createPeerConnection(peerId, MediaConstants_1.SessionClientType.INITIATOR, MediaConstants_1.SessionClientRole.USER);\n peerConnection.ontrack = function (trackEvent) {\n var track = trackEvent.track;\n trace.info(\"MediaStreamTrack arrived from peerConnection: \" + track.kind, track);\n var remoteTrack = {\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 ? MediaConstants_1.KnownMediaStream.USER_VIDEO_STREAM : MediaConstants_1.KnownMediaStream.USER_AUDIO_STREAM\n };\n peerConnection.remoteMediaTracks.push(remoteTrack);\n _this._sessionStreamsManager.addRemoteMediaTrack(remoteTrack)\n .catch(function () {\n trace.warn('Error adding remote track to stream manager', remoteTrack);\n });\n };\n this._sessionStreamsManager.getMediaStreamForRole(MediaConstants_1.SessionClientRole.USER)\n .then(function (mediaStream) {\n if (mediaStream) {\n trace.info('Adding local tracks to peer connection');\n mediaStream.getTracks().forEach(function (track) {\n peerConnection.addTrack(track, mediaStream);\n trace.info(\"Local \" + track.kind + \" track added to peer connection\");\n });\n }\n else {\n trace.info('No media stream was found for publishing');\n }\n })\n .then(function () {\n var remoteDesc = new RTCSessionDescription({ type: 'offer', sdp: sdpOffer });\n return peerConnection.setRemoteDescription(remoteDesc)\n .then(function () {\n trace.info('Remote description was set', remoteDesc);\n return peerConnection.createAnswer()\n .then(function (sdpAnswer) {\n trace.info('_sdpOfferHandler answer created', sdpAnswer);\n _this._socket.emit(TurnConstants_1.SOCKET_EVENTS.OUTGOING.SDP_ANSWER, {\n uid: uid,\n peerId: peerId,\n sessionId: _this._sessionParams.sessionId,\n sdpAnswer: sdpAnswer.sdp\n });\n return peerConnection.setLocalDescription(sdpAnswer)\n .then(function () {\n trace.info('_sdpOfferHandler local desc was set');\n _this._processQueuedIceCandidates(peerId);\n });\n });\n });\n })\n .catch(function (e) {\n trace.error('Error in _sdpOfferHandler', e);\n throw e;\n });\n };\n // Received by Guest after an Initiator reconnects to room\n TurnWebRtcSessionV3.prototype._userPeerReconnectHandler = function () {\n trace.info('_userPeerReconnectHandler');\n this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.UserPeerReconnected)\n .catch(function (error) {\n trace.warn('Error while disconnecting during userPeerReconnectHandler.', error);\n });\n };\n //#endregion WebRTC Guest - session Guest (Agent on dashboard platform)\n //#region Peer Connection\n //#region Streams Handling\n TurnWebRtcSessionV3.prototype.onMediaStreamDestroyed = function (clientRole) {\n var _this = this;\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation\n this._peerConnections.forEach(function (peerConnection) {\n _this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.PublishedStreamDestroyed).catch(function () { return undefined; });\n });\n return Promise.resolve();\n };\n TurnWebRtcSessionV3.prototype.onMediaStreamRenewed = function (clientRole, mediaStream) {\n //TODO - Alex: need to implement adding new tracks to peer connection and forcing negotiation\n return Promise.resolve();\n };\n TurnWebRtcSessionV3.prototype.getRemoteTrackStats = function (mediaTrack) {\n var peerConnectionOfTrack = null;\n this._peerConnections.forEach(function (peerConnection) {\n var remoteTrack = peerConnection.remoteMediaTracks.filter(function (track) { return track.mediaTrack.id === mediaTrack.id; });\n if (remoteTrack.length === 1) {\n peerConnectionOfTrack = peerConnection;\n }\n });\n if (peerConnectionOfTrack !== null) {\n return peerConnectionOfTrack.getStats(mediaTrack);\n }\n return Promise.reject(new Error('Provided track is not remote track'));\n };\n //#endregion\n TurnWebRtcSessionV3.prototype._disconnectInternal = function (reason) {\n var _this = this;\n this._peerConnections.forEach(function (peerConnection) {\n _this._destroyPeerConnection(peerConnection);\n });\n trace.info('Disconnecting from session', reason);\n if (this._socket) {\n this._socket.off();\n this._socket.disconnect();\n }\n this._socket = null;\n setTimeout(function () { return _this._sessionHandlers.onDisconnectedHandler(reason); });\n return Promise.resolve();\n };\n TurnWebRtcSessionV3.prototype._createPeerConnection = function (peerId, peerConnectionType, peerConnectionRole) {\n var _this = this;\n if (this._peerConnections.get(peerId)) {\n throw new Error(this._sessionParams.clientType + \" peer connection for \" + peerId + \" already exists\");\n }\n var peerConnection = new RTCPeerConnection(this._configuration);\n peerConnection.peerId = peerId;\n peerConnection.peerType = peerConnectionType;\n peerConnection.remoteMediaTracks = [];\n peerConnection.peerRole = peerConnectionRole;\n peerConnection.onconnectionstatechange = function () {\n trace.info('onconnectionstatechange', peerConnection);\n };\n peerConnection.oniceconnectionstatechange = function (state) {\n trace.info(\"ICE Connection state for peer \" + peerId + \" was changed to: \" + state.currentTarget.iceConnectionState, state);\n var cnState = state.currentTarget.iceConnectionState;\n if (['closed', 'disconnected', 'failed'].indexOf(cnState) > -1) {\n _this._iceStateDisconnected(peerConnection);\n }\n };\n peerConnection.onicecandidate = function (event) {\n if (event.candidate) {\n trace.info(_this._sessionParams.clientType + \" peerConn.onicecandidate\", event.candidate);\n _this._socket.emit(TurnConstants_1.SOCKET_EVENTS.OUTGOING.ICE_CANDIDATE, {\n sessionId: _this._sessionParams.sessionId,\n peerId: peerId,\n candidate: event.candidate,\n clientType: _this._sessionParams.clientType\n });\n }\n else {\n trace.info('ICE Candidate is null in peerConnection', event);\n }\n };\n this._peerConnections.set(peerId, peerConnection);\n trace.info(peerConnectionType + \" peerConnection created\");\n return peerConnection;\n };\n TurnWebRtcSessionV3.prototype._destroyPeerConnection = function (peerConnection) {\n var _this = this;\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 peerConnection.remoteMediaTracks.forEach(function (remoteMediaTrack) {\n _this._sessionStreamsManager.removeMediaTrack(remoteMediaTrack.mediaTrack)\n .catch(function () {\n trace.warn('Error while removing remote media track', remoteMediaTrack);\n });\n });\n this._peerConnections.delete(peerConnection.peerId);\n peerConnection.close();\n };\n TurnWebRtcSessionV3.prototype._withPeerConnection = function (peerId, callback) {\n if (this._peerConnections.get(peerId)) {\n return callback(this._peerConnections.get(peerId));\n }\n return undefined;\n };\n //#endregion\n //#region ICE Candidates\n TurnWebRtcSessionV3.prototype._iceCandidateReceivedHandler = function (iceCandidateData) {\n var candidate = iceCandidateData.candidate, peerId = iceCandidateData.peerId;\n trace.info('_iceCandidateReceivedHandler', candidate);\n if (!candidate) {\n trace.info('Unexpected case, iceCandidate message arrived without candidate');\n return;\n }\n var peerConnection = this._peerConnections.get(peerId);\n if (!peerConnection || !peerConnection.remoteDescription) {\n trace.info('Queueing iceCandidate', candidate);\n this._queueIceCandidate(candidate, peerId);\n return;\n }\n trace.info('Going to add iceCandidate', candidate);\n this._addIceCandidateToPeer(candidate, peerConnection).catch(function () { return undefined; });\n };\n TurnWebRtcSessionV3.prototype._addIceCandidateToPeer = function (iceCandidate, peerConnection) {\n return peerConnection.addIceCandidate(iceCandidate)\n .then(function () {\n trace.info('ICE Candidate add to peer connection');\n })\n .catch(function (e) {\n trace.warn('Error adding ICE Candidate to peer connection', e);\n throw e;\n });\n };\n TurnWebRtcSessionV3.prototype._processQueuedIceCandidates = function (peerId) {\n var _this = this;\n this._withPeerConnection(peerId, function (peerConnection) {\n var pendingIces = _this._pendingPeersIce[peerId];\n if (pendingIces) {\n pendingIces.forEach(function (pendingIce) {\n trace.info('Adding pending ICE to peer connections');\n _this._addIceCandidateToPeer(pendingIce, peerConnection).catch(function () { return undefined; });\n });\n }\n else {\n trace.info('No pending ICE found for peer', peerId);\n }\n });\n };\n TurnWebRtcSessionV3.prototype._queueIceCandidate = function (iceCandidate, peerId) {\n if (!this._pendingPeersIce[peerId]) {\n this._pendingPeersIce[peerId] = [];\n }\n this._pendingPeersIce[peerId].push(iceCandidate);\n };\n TurnWebRtcSessionV3.prototype._iceStateDisconnected = function (peerConnection) {\n this._disconnectInternal(MediaConstants_1.MediaSessionDisconnectReason.PeerConnectionInterrupted).catch(function () { return undefined; });\n };\n return TurnWebRtcSessionV3;\n}(MediaSessionBase_1.MediaSessionBase));\nexports.TurnWebRtcSessionV3 = TurnWebRtcSessionV3;\n\n//# sourceMappingURL=SessionTurn.v3.js.map\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techsee/techsee-media-service",
3
- "version": "0.6.1-alpha.3",
3
+ "version": "0.6.1-alpha.4",
4
4
  "description": "Techsee Media Service Client",
5
5
  "author": "TechSee - Alex Danilov",
6
6
  "main": "lib/index.js",