/* Autogenerated with Kurento Idl */
/*
* (C) Copyright 2013-2015 Kurento (http://kurento.org/)
*
* 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 inherits = require('inherits');
var kurentoClient = require('kurento-client');
var disguise = kurentoClient.disguise;
var checkType = kurentoClient.checkType;
var ChecktypeError = checkType.ChecktypeError;
var Transaction = kurentoClient.TransactionsManager.Transaction;
var BaseRtpEndpoint = require('kurento-client-core').abstracts.BaseRtpEndpoint;
function noop(error, result) {
if (error) console.trace(error);
return result
};
/**
* Builder for the {@link module:elements.WebRtcEndpoint WebRtcEndpoint}
*
* @classdesc
* <p>
* Control interface for Kurento WebRTC endpoint.
* </p>
* <p>
* This endpoint is one side of a peer-to-peer WebRTC communication,
* being the other peer a WebRTC capable browser -using the
* RTCPeerConnection API-, a native WebRTC app or even another Kurento
* Media Server.
* </p>
* <p>
* In order to establish a WebRTC communication, peers engage in an SDP
* negotiation process, where one of the peers (the offerer) sends an
* offer, while the other peer (the offeree) responds with an answer.
* This endpoint can function in both situations
* <ul>
* <li>
* As offerer: The negotiation process is initiated by the media
* server
* <ul style='list-style-type:circle'>
* <li>KMS generates the SDP offer through the
* <code>generateOffer</code> method. This <i>offer</i> must then
* be sent to the remote peer (the offeree) through the signaling
* channel, for processing.</li>
* <li>The remote peer process the <i>offer</i>, and generates an
* <i>answer</i> to this <i>offer</i>. The <i>answer</i> is sent
* back to the media server.</li>
* <li>Upon receiving the <i>answer</i>, the endpoint must invoke
* the <code>processAnswer</code> method.</li>
* </ul>
* </li>
* <li>
* As offeree: The negotiation process is initiated by the remote
* peer
* <ul>
* <li>The remote peer, acting as offerer, generates an SDP
* <i>offer</i> and sends it to the WebRTC endpoint in
* Kurento.</li>
* <li>The endpoint will process the <i>offer</i> invoking the
* <code>processOffer</code> method. The result of this method will
* <li>The SDP <i>answer</i> must be sent back to the offerer, so
* it can be processed.</li>
* </ul>
* </li>
* </ul>
* </p>
* <p>
* SDPs are sent without ICE candidates, following the Trickle ICE
* optimization. Once the SDP negotiation is completed, both peers
* proceed with the ICE discovery process, intended to set up a
* bidirectional media connection. During this process, each peer
* <ul>
* <li>Discovers ICE candidates for itself, containing pairs of IPs and
* <li>ICE candidates are sent via the signaling channel as they are
* discovered, to the remote peer for probing.</li>
* <li>ICE connectivity checks are run as soon as the new candidate
* description, from the remote peer, is available.</li>
* </ul>
* Once a suitable pair of candidates (one for each peer) is discovered,
* the media session can start. The harvesting process in Kurento, begins
* </p>
* <p>
* It's important to keep in mind that WebRTC connection is an
* asynchronous process, when designing interactions between different
* MediaElements. For example, it would be pointless to start recording
* before media is flowing. In order to be notified of state changes, the
* <ul>
* <li>
* <code>IceComponentStateChange</code>: This event informs only
* about changes in the ICE connection state. Possible values are:
* <ul style='list-style-type:circle'>
* <li><code>DISCONNECTED</code>: No activity scheduled</li>
* <li><code>GATHERING</code>: Gathering local candidates</li>
* <li><code>CONNECTING</code>: Establishing connectivity</li>
* <li><code>CONNECTED</code>: At least one working candidate
* pair</li>
* <li><code>READY</code>: ICE concluded, candidate pair selection
* is now final</li>
* <li><code>FAILED</code>: Connectivity checks have been
* completed, but media connection was not established</li>
* </ul>
* The transitions between states are covered in RFC5245.
* It could be said that it's network-only, as it only takes into
* account the state of the network connection, ignoring other higher
* </li>
* <li>
* <code>IceCandidateFound</code>: Raised when a new candidate is
* discovered. ICE candidates must be sent to the remote peer of the
* connection. Failing to do so for some or all of the candidates
* might render the connection unusable.
* </li>
* <li>
* <code>IceGatheringDone</code>: Raised when the ICE harvesting
* process is completed. This means that all candidates have already
* been discovered.
* </li>
* <li>
* <code>NewCandidatePairSelected</code>: Raised when a new ICE
* candidate pair gets selected. The pair contains both local and
* remote candidates being used for a component. This event can be
* raised during a media session, if a new pair of candidates with
* higher priority in the link are found.
* </li>
* <li>
* <code>DataChannelOpen</code>: Raised when a data channel is open.
* </li>
* <li>
* <code>DataChannelClose</code>: Raised when a data channel is
* closed.
* </li>
* </ul>
* </p>
* <p>
* Registering to any of above events requires the application to provide
* </p>
* <p>
* Flow control and congestion management is one of the most important
* features of WebRTC. WebRTC connections start with the lowest bandwidth
* </p>
* <p>
* The default bandwidth range of the endpoint is 100kbps-500kbps, but it
* <ul>
* <li>
* Input bandwidth control mechanism: Configuration interval used to
* inform remote peer the range of bitrates that can be pushed into
* this WebRtcEndpoint object.
* <ul style='list-style-type:circle'>
* <li>
* setMin/MaxVideoRecvBandwidth: sets Min/Max bitrate limits
* expected for received video stream.
* </li>
* <li>
* setMin/MaxAudioRecvBandwidth: sets Min/Max bitrate limits
* expected for received audio stream.
* </li>
* </ul>
* Max values are announced in the SDP, while min values are set to
* limit the lower value of REMB packages. It follows that min values
* </li>
* <li>
* Output bandwidth control mechanism: Configuration interval used to
* <ul style='list-style-type:circle'>
* <li>
* setMin/MaxVideoSendBandwidth: sets Min/Max bitrate limits for
* </li>
* </ul>
* </li>
* </ul>
* All bandwidth control parameters must be changed before the SDP
* negotiation takes place, and can't be changed afterwards.
* </p>
* <p>
* DataChannels allow other media elements that make use of the DataPad,
* to send arbitrary data. For instance, if there is a filter that
* publishes event information, it'll be sent to the remote peer through
* the channel. There is no API available for programmers to make use of
* this feature in the WebRtcElement. DataChannels can be configured to
* provide the following:
* <ul>
* <li>
* Reliable or partially reliable delivery of sent messages
* </li>
* <li>
* In-order or out-of-order delivery of sent messages
* </li>
* </ul>
* Unreliable, out-of-order delivery is equivalent to raw UDP semantics.
* The message may make it, or it may not, and order is not important.
* However, the channel can be configured to be <i>partially reliable</i>
* </p>
* <p>
* The possibility to create DataChannels in a WebRtcEndpoint must be
* explicitly enabled when creating the endpoint, as this feature is
* disabled by default. If this is the case, they can be created invoking
* <ul>
* <li>
* <code>label</code>: assigns a label to the DataChannel. This can
* help identify each possible channel separately.
* </li>
* <li>
* <code>ordered</code>: specifies if the DataChannel guarantees
* order, which is the default mode. If maxPacketLifetime and
* maxRetransmits have not been set, this enables reliable mode.
* </li>
* <li>
* <code>maxPacketLifeTime</code>: The time window in milliseconds,
* during which transmissions and retransmissions may take place in
* unreliable mode. This forces unreliable mode, even if
* <code>ordered</code> has been activated.
* </li>
* <li>
* <code>maxRetransmits</code>: maximum number of retransmissions
* that are attempted in unreliable mode. This forces unreliable
* mode, even if <code>ordered</code> has been activated.
* </li>
* <li>
* <code>Protocol</code>: Name of the subprotocol used for data
* communication.
* </li>
* </ul>
*
* @extends module:core/abstracts.BaseRtpEndpoint
*
* @constructor module:elements.WebRtcEndpoint
*
* @fires {@link module:elements#event:DataChannelClose DataChannelClose}
* @fires {@link module:elements#event:DataChannelOpen DataChannelOpen}
* @fires {@link module:elements#event:IceCandidateFound IceCandidateFound}
* @fires {@link module:elements#event:IceComponentStateChange IceComponentStateChange}
* @fires {@link module:elements#event:IceGatheringDone IceGatheringDone}
* @fires {@link module:elements#event:NewCandidatePairSelected NewCandidatePairSelected}
* @fires {@link module:elements#event:OnDataChannelClosed OnDataChannelClosed}
* @fires {@link module:elements#event:OnDataChannelOpened OnDataChannelOpened}
* @fires {@link module:elements#event:OnIceCandidate OnIceCandidate}
* @fires {@link module:elements#event:OnIceComponentStateChanged OnIceComponentStateChanged}
* @fires {@link module:elements#event:OnIceGatheringDone OnIceGatheringDone}
*/
function WebRtcEndpoint(){
WebRtcEndpoint.super_.call(this);
};
inherits(WebRtcEndpoint, BaseRtpEndpoint);
//
// Public properties
//
/**
* the ICE candidate pair (local and remote candidates) used by the ice library
* for each stream.
*
* @alias module:elements.WebRtcEndpoint#getICECandidatePairs
*
* @param {module:elements.WebRtcEndpoint~getICECandidatePairsCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getICECandidatePairs = function(callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
var usePromise = false;
if (callback == undefined) {
usePromise = true;
}
if(!arguments.length) callback = undefined;
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'getICECandidatePairs', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getICECandidatePairsCallback
* @param {external:Error} error
* @param {module:elements/complexTypes.IceCandidatePair} result
*/
/**
* the ICE connection state for all the connections.
*
* @alias module:elements.WebRtcEndpoint#getIceConnectionState
*
* @param {module:elements.WebRtcEndpoint~getIceConnectionStateCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getIceConnectionState = function(callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
var usePromise = false;
if (callback == undefined) {
usePromise = true;
}
if(!arguments.length) callback = undefined;
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'getIceConnectionState', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getIceConnectionStateCallback
* @param {external:Error} error
* @param {module:elements/complexTypes.IceConnection} result
*/
/**
* address of the STUN server (Only IP address are supported)
*
* @alias module:elements.WebRtcEndpoint#getStunServerAddress
*
* @param {module:elements.WebRtcEndpoint~getStunServerAddressCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getStunServerAddress = function(callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
var usePromise = false;
if (callback == undefined) {
usePromise = true;
}
if(!arguments.length) callback = undefined;
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'getStunServerAddress', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getStunServerAddressCallback
* @param {external:Error} error
* @param {external:String} result
*/
/**
* address of the STUN server (Only IP address are supported)
*
* @alias module:elements.WebRtcEndpoint#setStunServerAddress
*
* @param {external:String} stunServerAddress
* @param {module:elements.WebRtcEndpoint~setStunServerAddressCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.setStunServerAddress = function(stunServerAddress, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
//
// checkType('String', 'stunServerAddress', stunServerAddress, {required: true});
//
var params = {
stunServerAddress: stunServerAddress
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'setStunServerAddress', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~setStunServerAddressCallback
* @param {external:Error} error
*/
/**
* port of the STUN server
*
* @alias module:elements.WebRtcEndpoint#getStunServerPort
*
* @param {module:elements.WebRtcEndpoint~getStunServerPortCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getStunServerPort = function(callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
var usePromise = false;
if (callback == undefined) {
usePromise = true;
}
if(!arguments.length) callback = undefined;
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'getStunServerPort', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getStunServerPortCallback
* @param {external:Error} error
* @param {external:Integer} result
*/
/**
* port of the STUN server
*
* @alias module:elements.WebRtcEndpoint#setStunServerPort
*
* @param {external:Integer} stunServerPort
* @param {module:elements.WebRtcEndpoint~setStunServerPortCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.setStunServerPort = function(stunServerPort, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
//
// checkType('int', 'stunServerPort', stunServerPort, {required: true});
//
var params = {
stunServerPort: stunServerPort
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'setStunServerPort', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~setStunServerPortCallback
* @param {external:Error} error
*/
/**
* TURN server URL with this format:
* <code>user:password@address:port(?transport=[udp|tcp|tls])</code>.</br><code>address</code>
*
* @alias module:elements.WebRtcEndpoint#getTurnUrl
*
* @param {module:elements.WebRtcEndpoint~getTurnUrlCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getTurnUrl = function(callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
var usePromise = false;
if (callback == undefined) {
usePromise = true;
}
if(!arguments.length) callback = undefined;
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'getTurnUrl', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getTurnUrlCallback
* @param {external:Error} error
* @param {external:String} result
*/
/**
* TURN server URL with this format:
* <code>user:password@address:port(?transport=[udp|tcp|tls])</code>.</br><code>address</code>
*
* @alias module:elements.WebRtcEndpoint#setTurnUrl
*
* @param {external:String} turnUrl
* @param {module:elements.WebRtcEndpoint~setTurnUrlCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.setTurnUrl = function(turnUrl, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
//
// checkType('String', 'turnUrl', turnUrl, {required: true});
//
var params = {
turnUrl: turnUrl
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'setTurnUrl', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~setTurnUrlCallback
* @param {external:Error} error
*/
//
// Public methods
//
/**
* Process an ICE candidate sent by the remote peer of the connection.
*
* @alias module:elements.WebRtcEndpoint.addIceCandidate
*
* @param {module:elements/complexTypes.IceCandidate} candidate
* Remote ICE candidate
*
* @param {module:elements.WebRtcEndpoint~addIceCandidateCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.addIceCandidate = function(candidate, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
//
// checkType('IceCandidate', 'candidate', candidate, {required: true});
//
var params = {
candidate: candidate
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'addIceCandidate', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~addIceCandidateCallback
* @param {external:Error} error
*/
/**
* Closes an open data channel
*
* @alias module:elements.WebRtcEndpoint.closeDataChannel
*
* @param {external:Integer} channelId
* The channel identifier
*
* @param {module:elements.WebRtcEndpoint~closeDataChannelCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.closeDataChannel = function(channelId, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
//
// checkType('int', 'channelId', channelId, {required: true});
//
var params = {
channelId: channelId
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'closeDataChannel', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~closeDataChannelCallback
* @param {external:Error} error
*/
/**
* Create a new data channel, if data channels are supported. If they are not
* supported, this method throws an exception.
* Being supported means that the WebRtcEndpoint has been created with
* Otherwise, the method throws an exception, indicating that the
* operation is not possible.</br>
* Data channels can work in either unreliable mode (analogous to User
* The two modes have a simple distinction:
* <ul>
* <li>Reliable mode guarantees the transmission of messages and
* also the order in which they are delivered. This takes extra
* overhead, thus potentially making this mode slower.</li>
* <li>Unreliable mode does not guarantee every message will get to
* the other side nor what order they get there. This removes the
* overhead, allowing this mode to work much faster.</li>
* </ul>
*
* @alias module:elements.WebRtcEndpoint.createDataChannel
*
* @param {external:String} [label]
* Channel's label
*
* @param {external:Boolean} [ordered]
* If the data channel should guarantee order or not. If true, and
* maxPacketLifeTime and maxRetransmits have not been provided, reliable mode
* is activated.
*
* @param {external:Integer} [maxPacketLifeTime]
* The time window (in milliseconds) during which transmissions and
* retransmissions may take place in unreliable mode.</br>
* <hr/><b>Note</b> This forces unreliable mode, even if
* <code>ordered</code> has been activated
*
* @param {external:Integer} [maxRetransmits]
* maximum number of retransmissions that are attempted in unreliable
* mode.</br>
* <hr/><b>Note</b> This forces unreliable mode, even if
* <code>ordered</code> has been activated
*
* @param {external:String} [protocol]
* Name of the subprotocol used for data communication
*
* @param {module:elements.WebRtcEndpoint~createDataChannelCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.createDataChannel = function(label, ordered, maxPacketLifeTime, maxRetransmits, protocol, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
callback = arguments[arguments.length-1] instanceof Function
? Array.prototype.pop.call(arguments)
: undefined;
switch(arguments.length){
case 0: label = undefined;
case 1: ordered = undefined;
case 2: maxPacketLifeTime = undefined;
case 3: maxRetransmits = undefined;
case 4: protocol = undefined;
break;
case 5:
break;
default:
var error = new RangeError('Number of params ('+arguments.length+') not in range [0-5]');
error.length = arguments.length;
error.min = 0;
error.max = 5;
throw error;
}
//
// checkType('String', 'label', label);
//
// checkType('boolean', 'ordered', ordered);
//
// checkType('int', 'maxPacketLifeTime', maxPacketLifeTime);
//
// checkType('int', 'maxRetransmits', maxRetransmits);
//
// checkType('String', 'protocol', protocol);
//
var params = {
label: label,
ordered: ordered,
maxPacketLifeTime: maxPacketLifeTime,
maxRetransmits: maxRetransmits,
protocol: protocol
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'createDataChannel', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~createDataChannelCallback
* @param {external:Error} error
*/
/**
* Start the gathering of ICE candidates.</br>It must be called after
* SdpEndpoint::generateOffer or SdpEndpoint::processOffer for Trickle ICE. If
* invoked before generating or processing an SDP offer, the candidates gathered
*
* @alias module:elements.WebRtcEndpoint.gatherCandidates
*
* @param {module:elements.WebRtcEndpoint~gatherCandidatesCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.gatherCandidates = function(callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
var usePromise = false;
if (callback == undefined) {
usePromise = true;
}
if(!arguments.length) callback = undefined;
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'gatherCandidates', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~gatherCandidatesCallback
* @param {external:Error} error
*/
/**
* @alias module:elements.WebRtcEndpoint.constructorParams
*
* @property {module:elements/complexTypes.CertificateKeyType} [certificateKeyType]
* Define the type of the certificate used in dtls
*
* @property {module:core.MediaPipeline} mediaPipeline
* the {@link module:core.MediaPipeline MediaPipeline} to which the endpoint
* belongs
*
* @property {external:Boolean} [recvonly]
* Single direction, receive-only endpoint
*
* @property {external:Boolean} [sendonly]
* Single direction, send-only endpoint
*
* @property {external:Boolean} [useDataChannels]
* Activate data channels support
*/
WebRtcEndpoint.constructorParams = {
certificateKeyType: {
type: 'kurento.CertificateKeyType' },
mediaPipeline: {
type: 'kurento.MediaPipeline',
required: true
},
recvonly: {
type: 'boolean' },
sendonly: {
type: 'boolean' },
useDataChannels: {
type: 'boolean' }
};
/**
* @alias module:elements.WebRtcEndpoint.events
*
* @extends module:core/abstracts.BaseRtpEndpoint.events
*/
WebRtcEndpoint.events = BaseRtpEndpoint.events.concat(['DataChannelClose', 'DataChannelOpen', 'IceCandidateFound', 'IceComponentStateChange', 'IceGatheringDone', 'NewCandidatePairSelected', 'OnDataChannelClosed', 'OnDataChannelOpened', 'OnIceCandidate', 'OnIceComponentStateChanged', 'OnIceGatheringDone']);
/**
* Checker for {@link module:elements.WebRtcEndpoint}
*
* @memberof module:elements
*
* @param {external:String} key
* @param {module:elements.WebRtcEndpoint} value
*/
function checkWebRtcEndpoint(key, value)
{
if(!(value instanceof WebRtcEndpoint))
throw ChecktypeError(key, WebRtcEndpoint, value);
};
module.exports = WebRtcEndpoint;
WebRtcEndpoint.check = checkWebRtcEndpoint;