/* Autogenerated with Kurento Idl */
/*
* (C) Copyright 2013-2015 Kurento (https://kurento.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 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 WebRtcEndpoint}
*
* @classdesc
* Endpoint that provides bidirectional WebRTC capabilities for Kurento.
* <p>
* This endpoint is one side of a peer-to-peer WebRTC communication, where
* the
* other peer is either of a WebRTC capable browser (using the
* <em>RTCPeerConnection</em> API), a native WebRTC app, or even another
* Kurento
* Media Server instance.
* </p>
* <p>
* In order to establish WebRTC communications, peers first engage in an SDP
* Offer/Answer negotiation process, where one of the peers (the offerer)
* sends
* an SDP Offer, while the other peer (the answerer) responds with an SDP
* Answer.
* This endpoint can work in both roles.
* </p>
* <ul>
* <li>
* <b>As offerer</b>: The negotiation process is initiated by the media
* server.
* <ul>
* <li>
* Kurento generates the SDP Offer through the
* <code>generateOffer()</code> method. This offer must then be sent to
* remote peer (the answerer) through the signaling channel.
* </li>
* <li>
* The remote peer process the SDP Offer, and generates an SDP Answer.
* This
* answer is then sent back to the media server.
* </li>
* <li>
* Upon receiving the SDP Answer, this endpoint must process it with
* the
* <code>processAnswer()</code> method.
* </li>
* </ul>
* </li>
* <li>
* <b>As answerer</b>: The negotiation process is initiated by the remote
* peer.
* <ul>
* <li>
* The remote peer, acting as offerer, generates an SDP Offer and sends
* to this endpoint.
* </li>
* <li>
* This endpoint processes the SDP Offer with the
* <code>processOffer()</code> method. The result of this method will
* be a
* string, containing an SDP Answer.
* </li>
* <li>
* The SDP Answer must then be sent back to the offerer, so it can be
* processed by it.
* </li>
* </ul>
* </li>
* </ul>
* <h2>ICE candidates and connectivity checks</h2>
* <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...
* </p>
* <ul>
* <li>
* Discovers ICE candidates for itself, containing pairs of IPs and ports.
* </li>
* <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>
* <p>
* Once a suitable pair of candidates (one for each peer) is discovered, the
* media session can start. The harvesting process in Kurento, begins with
* the
* invocation of the <code>gatherCandidates()</code> method. Since the whole
* Trickle ICE purpose is to speed-up connectivity, candidates are generated
* asynchronously. Therefore, in order to capture the candidates, the user
* must
* subscribe to the event <code>IceCandidateFound</code>. It is important
* that
* the event listener is bound before invoking
* <code>gatherCandidates()</code>,
* otherwise a suitable candidate might be lost, and connection might not be
* established.
* </p>
* <p>
* It is 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.
* order to be notified of state changes, the application can subscribe to
* events
* generated by the WebRtcEndpoint. Following is a full list of events
* generated
* by WebRtcEndpoint:
* </p>
* <ul>
* <li>
* <code>IceComponentStateChanged</code>: This event informs only about
* changes
* in the ICE connection state. Possible values are:
* <ul>
* <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 is network-only, as it only takes into account the state of the
* network
* connection, ignoring other higher level stuff, like DTLS handshake, RTCP
* flow, etc. This implies that, while the component state is
* <code>CONNECTED</code>, there might be no media flowing between the
* peers.
* This makes this event useful only to receive low-level information about
* connection between peers. Even more, while other events might leave a
* graceful period of time before firing, this event fires immediately
* after
* the state change is detected.
* </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 gathering 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>DataChannelOpened</code>: Raised when a data channel is
* open.</li>
* <li><code>DataChannelClosed</code>: Raised when a data channel is
* closed.</li>
* </ul>
* <p>
* Registering to any of above events requires the application to provide a
* callback function. Each event provides different information, so it is
* recommended to consult the signature of the event listeners.
* </p>
* <h2>Bitrate management and network congestion control</h2>
* <p>
* Congestion control is one of the most important features of WebRTC. WebRTC
* connections start with the lowest bandwidth configured and slowly ramps up
* the maximum available bandwidth, or to the higher limit of the allowed
* range
* in case no bandwidth limitation is detected.
* </p>
* <p>
* Notice that WebRtcEndpoints in Kurento are designed in a way that
* <strong>
* multiple WebRTC connections fed by the same stream, share the same
* bitrate
* limits.
* </strong>
* When a new connection is added, as it requires to start with low
* bandwidth, it
* will cause the rest of connections to experience a transient period of
* degraded quality, until it stabilizes its bitrate. This doesn't apply when
* transcoding is involved; transcoders will adjust their output bitrate
* based in
* the receiver requirements, but it won't affect the original stream.
* </p>
* <p>
* If an incoming WebRTC stream needs to be transcoded, for whatever reason,
* all
* WebRtcEndpoints fed from the transcoder output will share a separate
* quality
* than the ones connected directly to the original stream.
* </p>
* <p>
* <strong>
* Note that the default <em>MaxVideoSendBandwidth</em> is a VERY
* conservative
* value, and leads to a low maximum video quality. Most applications will
* probably want to increase this to higher values such as 2000 kbps (2
* Mbps).
* </strong>
* Check the documentation of {@link BaseRtpEndpoint} and
* :rom:cls:`RembParams` for detailed information about bitrate management.
* </p>
* <h3>Keyframe requests (PLI/FIR)</h3>
* <p>
* WebRTC allows receivers to emit keyframe requests for the senders, by
* means of
* RTCP Feedback messages called PLI (Picture Loss Indication) and/or FIR
* (Full
* Intra-frame Request). Kurento supports this mechanism: PLI and FIR
* requests
* that are emitted by a receiver will be forwarded to the sender. This way,
* the
* encoder of the video (e.g. a web browser) can decide if a new keyframe
* should
* be generated. Sometimes Kurento itself acts as encoder when transcoding is
* enabled, so in this case it is Kurento itself the one generating
* keyframes.
* </p>
* <p>
* On top of this, a common technique used for streaming is to forcefully
* request
* new keyframes. Either in fixed intervals, or explicitly by the
* application.
* Kurento doesn't support the former, but the latter is possible by calling
* <code>requestKeyframe()</code> from a subscribing element (i.e. an
* endpoint
* that sends data out from the Kurento Pipeline).
* </p>
* <h2>WebRTC Data Channels</h2>
* <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 will be sent to the remote peer through the channel. There
* no API available for programmers to make use of this feature in the
* WebRtcElement. DataChannels can be configured to provide the following:
* </p>
* <ul>
* <li>Reliable or partially reliable delivery of sent messages</li>
* <li>In-order or out-of-order delivery of sent messages</li>
* </ul>
* <p>
* 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> by specifying
* the
* maximum number of retransmissions or setting a time limit for
* retransmissions:
* the WebRTC stack will handle the acknowledgments and timeouts.
* </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 the createDataChannel
* method.
* The arguments for this method, all of them optional, provide the necessary
* configuration:
* </p>
* <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:DataChannelClosed DataChannelClosed}
* @fires {@link module:elements#event:DataChannelOpened DataChannelOpened}
* @fires {@link module:elements#event:DtlsConnectionStateChange DtlsConnectionStateChange}
* @fires {@link module:elements#event:IceCandidateFound IceCandidateFound}
* @fires {@link module:elements#event:IceComponentStateChanged IceComponentStateChanged}
* @fires {@link module:elements#event:IceGatheringDone IceGatheringDone}
* @fires {@link module:elements#event:NewCandidatePairSelected NewCandidatePairSelected}
*/
function WebRtcEndpoint(){
WebRtcEndpoint.super_.call(this);
};
inherits(WebRtcEndpoint, BaseRtpEndpoint);
//
// Public properties
//
/**
* the DTLS connection state for all the connections.
*
* @alias module:elements.WebRtcEndpoint#getDtlsConnectionState
*
* @param {module:elements.WebRtcEndpoint~getDtlsConnectionStateCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getDtlsConnectionState = 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, 'getDtlsConnectionState', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getDtlsConnectionStateCallback
* @param {external:Error} error
* @param {module:elements/complexTypes.DtlsConnection} result
*/
/**
* External IPv4 address of the media server.
* <p>
* Forces all local IPv4 ICE candidates to have the given address. This is
* really
* nothing more than a hack, but it's very effective to force a public IP
* address
* when one is known in advance for the media server. In doing so, KMS will
* not
* need a STUN or TURN server, but remote peers will still be able to contact
* it.
* </p>
* <p>
* You can try using this setting if KMS is deployed on a publicly accessible
* server, without NAT, and with a static public IP address. But if it doesn't
* work for you, just go back to configuring a STUN or TURN server for ICE.
* </p>
* <p>
* Only set this parameter if you know what you're doing, and you understand
* 100%
* WHY you need it. For the majority of cases, you should just prefer to
* configure a STUN or TURN server.
* </p>
* <p><code>externalIPv4</code> is a single IPv4 address.</p>
* <p>Example:</p>
* <ul>
* <li><code>externalIPv4=198.51.100.1</code></li>
* </ul>
*
* @alias module:elements.WebRtcEndpoint#getExternalIPv4
*
* @param {module:elements.WebRtcEndpoint~getExternalIPv4Callback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getExternalIPv4 = 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, 'getExternalIPv4', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getExternalIPv4Callback
* @param {external:Error} error
* @param {external:String} result
*/
/**
* External IPv4 address of the media server.
* <p>
* Forces all local IPv4 ICE candidates to have the given address. This is
* really
* nothing more than a hack, but it's very effective to force a public IP
* address
* when one is known in advance for the media server. In doing so, KMS will
* not
* need a STUN or TURN server, but remote peers will still be able to contact
* it.
* </p>
* <p>
* You can try using this setting if KMS is deployed on a publicly accessible
* server, without NAT, and with a static public IP address. But if it doesn't
* work for you, just go back to configuring a STUN or TURN server for ICE.
* </p>
* <p>
* Only set this parameter if you know what you're doing, and you understand
* 100%
* WHY you need it. For the majority of cases, you should just prefer to
* configure a STUN or TURN server.
* </p>
* <p><code>externalIPv4</code> is a single IPv4 address.</p>
* <p>Example:</p>
* <ul>
* <li><code>externalIPv4=198.51.100.1</code></li>
* </ul>
*
* @alias module:elements.WebRtcEndpoint#setExternalIPv4
*
* @param {external:String} externalIPv4
* @param {module:elements.WebRtcEndpoint~setExternalIPv4Callback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.setExternalIPv4 = function(externalIPv4, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
//
// checkType('String', 'externalIPv4', externalIPv4, {required: true});
//
var params = {
externalIPv4: externalIPv4
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'setExternalIPv4', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~setExternalIPv4Callback
* @param {external:Error} error
*/
/**
* External IPv6 address of the media server.
* <p>
* Forces all local IPv6 ICE candidates to have the given address. This is
* really
* nothing more than a hack, but it's very effective to force a public IP
* address
* when one is known in advance for the media server. In doing so, KMS will
* not
* need a STUN or TURN server, but remote peers will still be able to contact
* it.
* </p>
* <p>
* You can try using this setting if KMS is deployed on a publicly accessible
* server, without NAT, and with a static public IP address. But if it doesn't
* work for you, just go back to configuring a STUN or TURN server for ICE.
* </p>
* <p>
* Only set this parameter if you know what you're doing, and you understand
* 100%
* WHY you need it. For the majority of cases, you should just prefer to
* configure a STUN or TURN server.
* </p>
* <p><code>externalIPv6</code> is a single IPv6 address.</p>
* <p>Example:</p>
* <ul>
* <li><code>externalIPv6=2001:0db8:85a3:0000:0000:8a2e:0370:7334</code></li>
* </ul>
*
* @alias module:elements.WebRtcEndpoint#getExternalIPv6
*
* @param {module:elements.WebRtcEndpoint~getExternalIPv6Callback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getExternalIPv6 = 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, 'getExternalIPv6', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getExternalIPv6Callback
* @param {external:Error} error
* @param {external:String} result
*/
/**
* External IPv6 address of the media server.
* <p>
* Forces all local IPv6 ICE candidates to have the given address. This is
* really
* nothing more than a hack, but it's very effective to force a public IP
* address
* when one is known in advance for the media server. In doing so, KMS will
* not
* need a STUN or TURN server, but remote peers will still be able to contact
* it.
* </p>
* <p>
* You can try using this setting if KMS is deployed on a publicly accessible
* server, without NAT, and with a static public IP address. But if it doesn't
* work for you, just go back to configuring a STUN or TURN server for ICE.
* </p>
* <p>
* Only set this parameter if you know what you're doing, and you understand
* 100%
* WHY you need it. For the majority of cases, you should just prefer to
* configure a STUN or TURN server.
* </p>
* <p><code>externalIPv6</code> is a single IPv6 address.</p>
* <p>Example:</p>
* <ul>
* <li><code>externalIPv6=2001:0db8:85a3:0000:0000:8a2e:0370:7334</code></li>
* </ul>
*
* @alias module:elements.WebRtcEndpoint#setExternalIPv6
*
* @param {external:String} externalIPv6
* @param {module:elements.WebRtcEndpoint~setExternalIPv6Callback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.setExternalIPv6 = function(externalIPv6, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
//
// checkType('String', 'externalIPv6', externalIPv6, {required: true});
//
var params = {
externalIPv6: externalIPv6
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'setExternalIPv6', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~setExternalIPv6Callback
* @param {external:Error} error
*/
/**
* 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
*/
/**
* Enable ICE-TCP candidate gathering.
* <p>
* This setting enables or disables using TCP for ICE candidate gathering in
* the
* underlying libnice library:
* https://libnice.freedesktop.org/libnice/NiceAgent.html#NiceAgent--ice-tcp
* </p>
* <p>
* You might want to disable ICE-TCP to potentially speed up ICE gathering by
* avoiding TCP candidates in scenarios where they are not needed.
* </p>
* <p><code>iceTcp</code> is either 1 (ON) or 0 (OFF). Default: 1 (ON).</p>
*
* @alias module:elements.WebRtcEndpoint#getIceTcp
*
* @param {module:elements.WebRtcEndpoint~getIceTcpCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getIceTcp = 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, 'getIceTcp', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getIceTcpCallback
* @param {external:Error} error
* @param {external:Boolean} result
*/
/**
* Enable ICE-TCP candidate gathering.
* <p>
* This setting enables or disables using TCP for ICE candidate gathering in
* the
* underlying libnice library:
* https://libnice.freedesktop.org/libnice/NiceAgent.html#NiceAgent--ice-tcp
* </p>
* <p>
* You might want to disable ICE-TCP to potentially speed up ICE gathering by
* avoiding TCP candidates in scenarios where they are not needed.
* </p>
* <p><code>iceTcp</code> is either 1 (ON) or 0 (OFF). Default: 1 (ON).</p>
*
* @alias module:elements.WebRtcEndpoint#setIceTcp
*
* @param {external:Boolean} iceTcp
* @param {module:elements.WebRtcEndpoint~setIceTcpCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.setIceTcp = function(iceTcp, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
//
// checkType('boolean', 'iceTcp', iceTcp, {required: true});
//
var params = {
iceTcp: iceTcp
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'setIceTcp', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~setIceTcpCallback
* @param {external:Error} error
*/
/**
* Local network interfaces used for ICE gathering.
* <p>
* If you know which network interfaces should be used to perform ICE (for
* WebRTC
* connectivity), you can define them here. Doing so has several advantages:
* </p>
* <ul>
* <li>
* The WebRTC ICE gathering process will be much quicker. Normally, it needs
* gather local candidates for all of the network interfaces, but this step
* can
* be made faster if you limit it to only the interface that you know will
* work.
* </li>
* <li>
* It will ensure that the media server always decides to use the correct
* network interface. With WebRTC ICE gathering it's possible that, under
* some
* circumstances (in systems with virtual network interfaces such as
* <code>docker0</code>) the ICE process ends up choosing the wrong local
* IP.
* </li>
* </ul>
* <p>
* <code>networkInterfaces</code> is a comma-separated list of network
* interface
* names.
* </p>
* <p>Examples:</p>
* <ul>
* <li><code>networkInterfaces=eth0</code></li>
* <li><code>networkInterfaces=eth0,enp0s25</code></li>
* </ul>
*
* @alias module:elements.WebRtcEndpoint#getNetworkInterfaces
*
* @param {module:elements.WebRtcEndpoint~getNetworkInterfacesCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.getNetworkInterfaces = 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, 'getNetworkInterfaces', callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~getNetworkInterfacesCallback
* @param {external:Error} error
* @param {external:String} result
*/
/**
* Local network interfaces used for ICE gathering.
* <p>
* If you know which network interfaces should be used to perform ICE (for
* WebRTC
* connectivity), you can define them here. Doing so has several advantages:
* </p>
* <ul>
* <li>
* The WebRTC ICE gathering process will be much quicker. Normally, it needs
* gather local candidates for all of the network interfaces, but this step
* can
* be made faster if you limit it to only the interface that you know will
* work.
* </li>
* <li>
* It will ensure that the media server always decides to use the correct
* network interface. With WebRTC ICE gathering it's possible that, under
* some
* circumstances (in systems with virtual network interfaces such as
* <code>docker0</code>) the ICE process ends up choosing the wrong local
* IP.
* </li>
* </ul>
* <p>
* <code>networkInterfaces</code> is a comma-separated list of network
* interface
* names.
* </p>
* <p>Examples:</p>
* <ul>
* <li><code>networkInterfaces=eth0</code></li>
* <li><code>networkInterfaces=eth0,enp0s25</code></li>
* </ul>
*
* @alias module:elements.WebRtcEndpoint#setNetworkInterfaces
*
* @param {external:String} networkInterfaces
* @param {module:elements.WebRtcEndpoint~setNetworkInterfacesCallback} [callback]
*
* @return {external:Promise}
*/
WebRtcEndpoint.prototype.setNetworkInterfaces = function(networkInterfaces, callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
//
// checkType('String', 'networkInterfaces', networkInterfaces, {required: true});
//
var params = {
networkInterfaces: networkInterfaces
};
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'setNetworkInterfaces', params, callback), this)
};
/**
* @callback module:elements.WebRtcEndpoint~setNetworkInterfacesCallback
* @param {external:Error} error
*/
/**
* STUN server IP address.
* <p>The ICE process uses STUN to punch holes through NAT firewalls.</p>
* <p>
* <code>stunServerAddress</code> MUST be an IP address; domain names are NOT
* supported.
* </p>
* <p>
* You need to use a well-working STUN server. Use this to check if it
* works:<br />
* https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/<br
* From that check, you should get at least one Server-Reflexive Candidate
* (type
* <code>srflx</code>).
* </p>
*
* @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
*/
/**
* STUN server IP address.
* <p>The ICE process uses STUN to punch holes through NAT firewalls.</p>
* <p>
* <code>stunServerAddress</code> MUST be an IP address; domain names are NOT
* supported.
* </p>
* <p>
* You need to use a well-working STUN server. Use this to check if it
* works:<br />
* https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/<br
* From that check, you should get at least one Server-Reflexive Candidate
* (type
* <code>srflx</code>).
* </p>
*
* @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.
* <p>
* When STUN is not enough to open connections through some NAT firewalls,
* using
* TURN is the remaining alternative.
* </p>
* <p>
* Note that TURN is a superset of STUN, so you don't need to configure STUN
* if
* you are using TURN.
* </p>
* <p>The provided URL should follow one of these formats:</p>
* <ul>
* <li><code>user:password@ipaddress:port</code></li>
* <li>
* <code>user:password@ipaddress:port?transport=[udp|tcp|tls]</code>
* </li>
* </ul>
* <p>
* <code>ipaddress</code> MUST be an IP address; domain names are NOT
* supported.<br />
* <code>transport</code> is OPTIONAL. Possible values: udp, tcp, tls.
* Default: udp.
* </p>
* <p>
* You need to use a well-working TURN server. Use this to check if it
* works:<br />
* https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/<br
* From that check, you should get at least one Server-Reflexive Candidate
* (type
* <code>srflx</code>) AND one Relay Candidate (type <code>relay</code>).
* </p>
*
* @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.
* <p>
* When STUN is not enough to open connections through some NAT firewalls,
* using
* TURN is the remaining alternative.
* </p>
* <p>
* Note that TURN is a superset of STUN, so you don't need to configure STUN
* if
* you are using TURN.
* </p>
* <p>The provided URL should follow one of these formats:</p>
* <ul>
* <li><code>user:password@ipaddress:port</code></li>
* <li>
* <code>user:password@ipaddress:port?transport=[udp|tcp|tls]</code>
* </li>
* </ul>
* <p>
* <code>ipaddress</code> MUST be an IP address; domain names are NOT
* supported.<br />
* <code>transport</code> is OPTIONAL. Possible values: udp, tcp, tls.
* Default: udp.
* </p>
* <p>
* You need to use a well-working TURN server. Use this to check if it
* works:<br />
* https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/<br
* From that check, you should get at least one Server-Reflexive Candidate
* (type
* <code>srflx</code>) AND one Relay Candidate (type <code>relay</code>).
* </p>
*
* @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.
* <p>
* Being supported means that the WebRtcEndpoint has been created with data
* channel support, the client also supports data channels, and they have been
* negotiated in the SDP exchange. Otherwise, the method throws an exception,
* indicating that the operation is not possible.
* </p>
* <p>
* Data channels can work in either unreliable mode (analogous to User
* Datagram
* Protocol or UDP) or reliable mode (analogous to Transmission Control
* Protocol
* or TCP). The two modes have a simple distinction:
* </p>
* <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>
* <p>If data channels are not supported, this method throws an exception.</p>
*
* @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.
* Note that this forces unreliable mode, even if <code>ordered</code> has been
*
* @param {external:Integer} [maxRetransmits]
* maximum number of retransmissions that are attempted in unreliable mode.
* Note that this forces unreliable mode, even if <code>ordered</code> has been
*
* @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 ICE candidate gathering.
* <p>
* This method triggers the asynchronous discovery of ICE candidates (as per
* the
* Trickle ICE mechanism), and returns immediately. Every newly trickled
* candidate is reported to the application by means of an
* <code>IceCandidateFound</code> event. Finally, when all candidates have
* been
* gathered, the <code>IceGatheringDone</code> event is emitted.
* </p>
* <p>
* Normally, you would call this method as soon as possible after calling
* <code>SdpEndpoint::generateOffer</code> or
* <code>SdpEndpoint::processOffer</code>, to quickly start discovering
* candidates and sending them to the remote peer.
* </p>
* <p>
* You can also call this method <em>before</em> calling
* <code>generateOffer</code> or <code>processOffer</code>. Doing so will
* include
* any already gathered candidates into the resulting SDP. You can leverage
* this
* behavior to implement fully traditional ICE (without Trickle): first call
* <code>gatherCandidates</code>, then only handle the SDP messages after the
* <code>IceGatheringDone</code> event has been received. This way, you're
* making
* sure that all candidates have indeed been gathered, so the resulting SDP
* will
* include all of them.
* </p>
*
* @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 MediaPipeline} to which the endpoint belongs
*
* @property {module:elements/complexTypes.DSCPValue} [qosDscp]
* DSCP value to be used in network traffic sent from this endpoint
* <p>
* If this parameter is present with a value different to
* NO_VALUE, all traffic sent from this WebRTCEndpoint will be
* marked with the correspondent
* DSCP value according to the DiffServ architecture. This may
* provide better handling of network traffic according to its
* characteristics associated to
* its DSCP value. This better handling includes priority in
* forwarding traffic and probability of packet drop in case of
* network congestion.
* <p>
* It must be taken into account that on Internet not all
* intermediate routers are guaranteed to enforce those DSCP
* values, even it is possible that
* certain routers just block traffic marked with specific DSCP
* values, as discussed here
* https://datatracker.ietf.org/doc/html/rfc8835#section-4.2.
* <p>
* So, this feature must be managed with care and is mostly
* intended for private networks, where the network proprietor
* can configure and guarantee
* DSCP management in all routers.
*
* @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
},
qosDscp: {
type: 'kurento.DSCPValue' },
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(['DataChannelClosed', 'DataChannelOpened', 'DtlsConnectionStateChange', 'IceCandidateFound', 'IceComponentStateChanged', 'IceGatheringDone', 'NewCandidatePairSelected']);
/**
* 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;