From 5fefcdc8a20d337cc92528ecbe280493c9dc4025 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 27 Jun 2018 16:43:44 +0200 Subject: [PATCH] openvidu-browser WebRtcPeer compilation uploaded --- .../WebRtcPeer/WebRtcPeer.d.ts | 63 +++++ .../OpenViduInternal/WebRtcPeer/WebRtcPeer.js | 264 ++++++++++++++++++ .../WebRtcPeer/WebRtcPeer.js.map | 1 + 3 files changed, 328 insertions(+) create mode 100644 openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.d.ts create mode 100644 openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.js create mode 100644 openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.js.map diff --git a/openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.d.ts b/openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.d.ts new file mode 100644 index 00000000..f467f537 --- /dev/null +++ b/openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.d.ts @@ -0,0 +1,63 @@ +export interface WebRtcPeerConfiguration { + mediaConstraints: { + audio: boolean; + video: boolean; + }; + simulcast: boolean; + onicecandidate: (event: any) => void; + iceServers: RTCIceServer[] | undefined; + mediaStream?: MediaStream; + mode?: string; + id?: string; +} +export declare class WebRtcPeer { + private configuration; + pc: RTCPeerConnection; + id: string; + remoteCandidatesQueue: RTCIceCandidate[]; + localCandidatesQueue: RTCIceCandidate[]; + iceCandidateList: RTCIceCandidate[]; + private candidategatheringdone; + constructor(configuration: WebRtcPeerConfiguration); + /** + * This function creates the RTCPeerConnection object taking into account the + * properties received in the constructor. It starts the SDP negotiation + * process: generates the SDP offer and invokes the onsdpoffer callback. This + * callback is expected to send the SDP offer, in order to obtain an SDP + * answer from another peer. + */ + start(): Promise; + /** + * This method frees the resources used by WebRtcPeer + */ + dispose(): void; + /** + * 1) Function that creates an offer, sets it as local description and returns the offer param + * to send to OpenVidu Server (will be the remote description of other peer) + */ + generateOffer(): Promise; + /** + * 2) Function to invoke when a SDP offer is received. Sets it as remote description, + * generates and answer and returns it to send it to OpenVidu Server + */ + processOffer(sdpOffer: string): Promise; + /** + * 3) Function invoked when a SDP answer is received. Final step in SDP negotiation, the peer + * just needs to set the answer as its remote description + */ + processAnswer(sdpAnswer: string): Promise; + /** + * Callback function invoked when an ICE candidate is received + */ + addIceCandidate(iceCandidate: RTCIceCandidate): Promise; + private streamStop; +} +export declare class WebRtcPeerRecvonly extends WebRtcPeer { + constructor(configuration: WebRtcPeerConfiguration); +} +export declare class WebRtcPeerSendonly extends WebRtcPeer { + constructor(configuration: WebRtcPeerConfiguration); +} +export declare class WebRtcPeerSendrecv extends WebRtcPeer { + constructor(configuration: WebRtcPeerConfiguration); +} diff --git a/openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.js b/openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.js new file mode 100644 index 00000000..7830464f --- /dev/null +++ b/openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.js @@ -0,0 +1,264 @@ +"use strict"; +/* + * (C) Copyright 2017-2018 OpenVidu (https://openvidu.io/) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var freeice = require("freeice"); +var uuid = require("uuid"); +var platform = require("platform"); +var WebRtcPeer = /** @class */ (function () { + function WebRtcPeer(configuration) { + var _this = this; + this.configuration = configuration; + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.iceCandidateList = []; + this.candidategatheringdone = false; + this.configuration.iceServers = (!!this.configuration.iceServers && this.configuration.iceServers.length > 0) ? this.configuration.iceServers : freeice(); + this.pc = new RTCPeerConnection({ iceServers: this.configuration.iceServers }); + this.id = !!configuration.id ? configuration.id : uuid.v4(); + this.pc.onicecandidate = function (event) { + var candidate = event.candidate; + if (candidate) { + _this.localCandidatesQueue.push({ candidate: candidate.candidate }); + _this.candidategatheringdone = false; + _this.configuration.onicecandidate(event.candidate); + } + else if (!_this.candidategatheringdone) { + _this.candidategatheringdone = true; + } + }; + this.pc.onsignalingstatechange = function () { + if (_this.pc.signalingState === 'stable') { + while (_this.iceCandidateList.length > 0) { + _this.pc.addIceCandidate(_this.iceCandidateList.shift()); + } + } + }; + this.start(); + } + /** + * This function creates the RTCPeerConnection object taking into account the + * properties received in the constructor. It starts the SDP negotiation + * process: generates the SDP offer and invokes the onsdpoffer callback. This + * callback is expected to send the SDP offer, in order to obtain an SDP + * answer from another peer. + */ + WebRtcPeer.prototype.start = function () { + var _this = this; + return new Promise(function (resolve, reject) { + if (_this.pc.signalingState === 'closed') { + reject('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue'); + } + if (!!_this.configuration.mediaStream) { + _this.pc.addStream(_this.configuration.mediaStream); + } + // [Hack] https://code.google.com/p/chromium/issues/detail?id=443558 + if (_this.configuration.mode === 'sendonly' && + (platform.name === 'Chrome' && platform.version.toString().substring(0, 2) === '39')) { + _this.configuration.mode = 'sendrecv'; + } + resolve(); + }); + }; + /** + * This method frees the resources used by WebRtcPeer + */ + WebRtcPeer.prototype.dispose = function () { + var _this = this; + console.debug('Disposing WebRtcPeer'); + try { + if (this.pc) { + if (this.pc.signalingState === 'closed') { + return; + } + this.remoteCandidatesQueue = []; + this.localCandidatesQueue = []; + this.pc.getLocalStreams().forEach(function (str) { + _this.streamStop(str); + }); + // FIXME This is not yet implemented in firefox + // if(videoStream) pc.removeStream(videoStream); + // if(audioStream) pc.removeStream(audioStream); + this.pc.close(); + } + } + catch (err) { + console.warn('Exception disposing webrtc peer ' + err); + } + }; + /** + * 1) Function that creates an offer, sets it as local description and returns the offer param + * to send to OpenVidu Server (will be the remote description of other peer) + */ + WebRtcPeer.prototype.generateOffer = function () { + var _this = this; + return new Promise(function (resolve, reject) { + var offerAudio, offerVideo = true; + // Constraints must have both blocks + if (!!_this.configuration.mediaConstraints) { + offerAudio = (typeof _this.configuration.mediaConstraints.audio === 'boolean') ? + _this.configuration.mediaConstraints.audio : true; + offerVideo = (typeof _this.configuration.mediaConstraints.video === 'boolean') ? + _this.configuration.mediaConstraints.video : true; + } + var constraints = { + offerToReceiveAudio: +(_this.configuration.mode !== 'sendonly' && offerAudio), + offerToReceiveVideo: +(_this.configuration.mode !== 'sendonly' && offerVideo) + }; + console.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints)); + _this.pc.createOffer(constraints).then(function (offer) { + console.debug('Created SDP offer'); + return _this.pc.setLocalDescription(offer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + })["catch"](function (error) { return reject(error); }); + }); + }; + /** + * 2) Function to invoke when a SDP offer is received. Sets it as remote description, + * generates and answer and returns it to send it to OpenVidu Server + */ + WebRtcPeer.prototype.processOffer = function (sdpOffer) { + var _this = this; + return new Promise(function (resolve, reject) { + var offer = { + type: 'offer', + sdp: sdpOffer + }; + console.debug('SDP offer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('PeerConnection is closed'); + } + _this.pc.setRemoteDescription(offer) + .then(function () { + return _this.pc.createAnswer(); + }).then(function (answer) { + console.debug('Created SDP answer'); + return _this.pc.setLocalDescription(answer); + }).then(function () { + var localDescription = _this.pc.localDescription; + if (!!localDescription) { + console.debug('Local description set', localDescription.sdp); + resolve(localDescription.sdp); + } + else { + reject('Local description is not defined'); + } + })["catch"](function (error) { return reject(error); }); + }); + }; + /** + * 3) Function invoked when a SDP answer is received. Final step in SDP negotiation, the peer + * just needs to set the answer as its remote description + */ + WebRtcPeer.prototype.processAnswer = function (sdpAnswer) { + var _this = this; + return new Promise(function (resolve, reject) { + var answer = { + type: 'answer', + sdp: sdpAnswer + }; + console.debug('SDP answer received, setting remote description'); + if (_this.pc.signalingState === 'closed') { + reject('RTCPeerConnection is closed'); + } + _this.pc.setRemoteDescription(answer).then(function () { return resolve(); })["catch"](function (error) { return reject(error); }); + }); + }; + /** + * Callback function invoked when an ICE candidate is received + */ + WebRtcPeer.prototype.addIceCandidate = function (iceCandidate) { + var _this = this; + return new Promise(function (resolve, reject) { + console.debug('Remote ICE candidate received', iceCandidate); + _this.remoteCandidatesQueue.push(iceCandidate); + switch (_this.pc.signalingState) { + case 'closed': + reject(new Error('PeerConnection object is closed')); + break; + case 'stable': + if (!!_this.pc.remoteDescription) { + _this.pc.addIceCandidate(iceCandidate).then(function () { return resolve(); })["catch"](function (error) { return reject(error); }); + } + break; + default: + _this.iceCandidateList.push(iceCandidate); + resolve(); + } + }); + }; + WebRtcPeer.prototype.streamStop = function (stream) { + stream.getTracks().forEach(function (track) { + track.stop(); + stream.removeTrack(track); + }); + }; + return WebRtcPeer; +}()); +exports.WebRtcPeer = WebRtcPeer; +var WebRtcPeerRecvonly = /** @class */ (function (_super) { + __extends(WebRtcPeerRecvonly, _super); + function WebRtcPeerRecvonly(configuration) { + var _this = this; + configuration.mode = 'recvonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerRecvonly; +}(WebRtcPeer)); +exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly; +var WebRtcPeerSendonly = /** @class */ (function (_super) { + __extends(WebRtcPeerSendonly, _super); + function WebRtcPeerSendonly(configuration) { + var _this = this; + configuration.mode = 'sendonly'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendonly; +}(WebRtcPeer)); +exports.WebRtcPeerSendonly = WebRtcPeerSendonly; +var WebRtcPeerSendrecv = /** @class */ (function (_super) { + __extends(WebRtcPeerSendrecv, _super); + function WebRtcPeerSendrecv(configuration) { + var _this = this; + configuration.mode = 'sendrecv'; + _this = _super.call(this, configuration) || this; + return _this; + } + return WebRtcPeerSendrecv; +}(WebRtcPeer)); +exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv; +//# sourceMappingURL=WebRtcPeer.js.map \ No newline at end of file diff --git a/openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.js.map b/openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.js.map new file mode 100644 index 00000000..945f197c --- /dev/null +++ b/openvidu-browser/lib/OpenViduInternal/WebRtcPeer/WebRtcPeer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"WebRtcPeer.js","sourceRoot":"","sources":["../../../src/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts"],"names":[],"mappings":"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"} \ No newline at end of file