Source: node_modules/kurento-client-elements/lib/WebRtcEndpoint.js

/* 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
 *  Control interface for Kurento WebRTC endpoint.
 *  <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
 *  </p>
 *  <ul>
 *    <li>
 *      As offerer: The negotiation process is initiated by the media server
 *      <ul>
 *        <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 processes the <i>offer</i>, and generates an
 *          <i>answer</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 be 
 *          a
 *          string, containing an SDP <i>answer</i>.
 *        </li>
 *        <li>
 *          The SDP <i>answer</i> must be sent back to the offerer, so it can be
 *          processed.
 *        </li>
 *      </ul>
 *    </li>
 *  </ul>
 *  <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'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.
 *    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>IceComponentStateChange</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's 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 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>
 *    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>
 *  <p>
 *    Flow control and congestion management is one of the most important 
 *    features
 *    of WebRTC. WebRTC connections start with the lowest bandwidth configured 
 *    and
 *    slowly ramps up to the maximum available bandwidth, or to the higher limit
 *    the exploration range in case no bandwidth limitation is detected. Notice 
 *    that
 *    WebRtcEndpoints in Kurento are designed in a way that multiple WebRTC
 *    connections fed by the same stream share quality. 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 bandwidth 
 *    requirements,
 *    but it won't affect the original stream. If an incoming WebRTC stream 
 *    needs to
 *    be transcoded, for whatever reason, all WebRtcEndpoints fed from 
 *    transcoder
 *    output will share a separate quality than the ones connected directly to 
 *    the
 *    original stream.
 *  </p>
 *  <p>
 *    Note that the default <strong>VideoSendBandwidth</strong> range of the
 *    endpoint is a VERY conservative one, 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).
 *  </p>
 *  <p>
 *    <strong>
 *      Check the extended documentation of these parameters in
 *      {@link module:core/abstracts.SdpEndpoint SdpEndpoint}, {@link 
 *      module:core/abstracts.BaseRtpEndpoint BaseRtpEndpoint}, and
 *      {@link module:core/complexTypes.RembParams RembParams}.
 *    </strong>
 *  </p>
 *  <ul>
 *    <li>
 *      Input bandwidth: Values used to inform remote peers about the bitrate 
 *      that
 *      can be sent to this endpoint.
 *      <ul>
 *        <li>
 *          <strong>MinVideoRecvBandwidth</strong>: Minimum input bitrate, 
 *          requested
 *          from WebRTC senders with REMB (Default: 30 Kbps).
 *        </li>
 *        <li>
 *          <strong>MaxAudioRecvBandwidth</strong> and
 *          <strong>MaxVideoRecvBandwidth</strong>: Maximum input bitrate, 
 *          signaled
 *          in SDP Offers to WebRTC and RTP senders (Default: unlimited).
 *        </li>
 *      </ul>
 *    </li>
 *    <li>
 *      Output bandwidth: Values used to control bitrate of the video streams 
 *      sent
 *      to remote peers. It is important to keep in mind that pushed bitrate 
 *      depends
 *      on network and remote peer capabilities. Remote peers can also announce
 *      bandwidth limitation in their SDPs (through the
 *      <code>b={modifier}:{value}</code> attribute). Kurento will always 
 *      enforce
 *      bitrate limitations specified by the remote peer over internal
 *      configurations.
 *      <ul>
 *        <li>
 *          <strong>MinVideoSendBandwidth</strong>: REMB override of minimum 
 *          bitrate
 *          sent to WebRTC receivers (Default: 100 Kbps).
 *        </li>
 *        <li>
 *          <strong>MaxVideoSendBandwidth</strong>: REMB override of maximum 
 *          bitrate
 *          sent to WebRTC receivers (Default: 500 Kbps).
 *        </li>
 *        <li>
 *          <strong>RembParams.rembOnConnect</strong>: Initial local REMB 
 *          bandwidth
 *          estimation that gets propagated when a new endpoint is connected.
 *        </li>
 *      </ul>
 *    </li>
 *  </ul>
 *  <p>
 *    <strong>
 *      All bandwidth control parameters must be changed before the SDP 
 *      negotiation
 *      takes place, and can't be changed afterwards.
 *    </strong>
 *  </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:
 *  </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: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
//

/**
 * External IP address of the media server.
 * <p>
 *   Forces all local IPv4 and 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>externalAddress</code> is a single IPv4 or IPv6 address.</p>
 * <p>Examples:</p>
 * <ul>
 *   <li><code>externalAddress=198.51.100.1</code></li>
 *   <li><code>externalAddress=2001:0db8:85a3:0000:0000:8a2e:0370:7334</code></li>
 * </ul>
 * @deprecated Use <code>externalIPv4</code> and/or <code>externalIPv6</code> 
 * instead.
 *
 * @alias module:elements.WebRtcEndpoint#getExternalAddress
 *
 * @param {module:elements.WebRtcEndpoint~getExternalAddressCallback} [callback]
 *
 * @return {external:Promise}
 */
WebRtcEndpoint.prototype.getExternalAddress = 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, 'getExternalAddress', callback), this)
};
/**
 * @callback module:elements.WebRtcEndpoint~getExternalAddressCallback
 * @param {external:Error} error
 * @param {external:String} result
 */

/**
 * External IP address of the media server.
 * <p>
 *   Forces all local IPv4 and 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>externalAddress</code> is a single IPv4 or IPv6 address.</p>
 * <p>Examples:</p>
 * <ul>
 *   <li><code>externalAddress=198.51.100.1</code></li>
 *   <li><code>externalAddress=2001:0db8:85a3:0000:0000:8a2e:0370:7334</code></li>
 * </ul>
 * @deprecated Use <code>externalIPv4</code> and/or <code>externalIPv6</code> 
 * instead.
 *
 * @alias module:elements.WebRtcEndpoint#setExternalAddress
 *
 * @param {external:String} externalAddress
 * @param {module:elements.WebRtcEndpoint~setExternalAddressCallback} [callback]
 *
 * @return {external:Promise}
 */
WebRtcEndpoint.prototype.setExternalAddress = function(externalAddress, callback){
  var transaction = (arguments[0] instanceof Transaction)
                  ? Array.prototype.shift.apply(arguments)
                  : undefined;

  //  
  // checkType('String', 'externalAddress', externalAddress, {required: true});
  //  

  var params = {
    externalAddress: externalAddress
  };

  callback = (callback || noop).bind(this)

  return disguise(this._invoke(transaction, 'setExternalAddress', params, callback), this)
};
/**
 * @callback module:elements.WebRtcEndpoint~setExternalAddressCallback
 * @param {external:Error} error
 */

/**
 * 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 gathering of ICE candidates.
 * <p>
 *   It must be called after <code>SdpEndpoint::generateOffer</code> or
 *   <code>SdpEndpoint::processOffer</code> for <strong>Trickle ICE</strong>. If
 *   invoked before generating or processing an SDP offer, the candidates 
 *   gathered
 *   will be added to the SDP processed.
 * </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 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;