- /**
- * The list of <a href="#method_init"><code>init()</code> method</a> ready states.
- * @attribute READY_STATE_CHANGE
- * @param {Number} INIT <small>Value <code>0</code></small>
- * The value of the state when <code>init()</code> has just started.
- * @param {Number} LOADING <small>Value <code>1</code></small>
- * The value of the state when <code>init()</code> is authenticating App Key provided
- * (and with credentials if provided as well) with the Auth server.
- * @param {Number} COMPLETED <small>Value <code>2</code></small>
- * The value of the state when <code>init()</code> has successfully authenticated with the Auth server.
- * Room session token is generated for joining the <code>defaultRoom</code> provided in <code>init()</code>.
- * <small>Room session token has to be generated each time User switches to a different Room
- * in <a href="#method_joinRoom"><code>joinRoom()</code> method</a>.</small>
- * @param {Number} ERROR <small>Value <code>-1</code></small>
- * The value of the state when <code>init()</code> has failed authenticating with the Auth server.
- * [Rel: Skylink.READY_STATE_CHANGE_ERROR]
- * @type JSON
- * @readOnly
- * @for Skylink
- * @since 0.1.0
- */
- Skylink.prototype.READY_STATE_CHANGE = {
- INIT: 0,
- LOADING: 1,
- COMPLETED: 2,
- ERROR: -1
- };
-
- /**
- * The list of <a href="#method_init"><code>init()</code> method</a> ready state failure codes.
- * @attribute READY_STATE_CHANGE_ERROR
- * @param {Number} API_INVALID <small>Value <code>4001</code></small>
- * The value of the failure code when provided App Key in <code>init()</code> does not exists.
- * <small>To resolve this, check that the provided App Key exists in
- * <a href="https://console.temasys.io">the Temasys Console</a>.</small>
- * @param {Number} API_DOMAIN_NOT_MATCH <small>Value <code>4002</code></small>
- * The value of the failure code when <code>"domainName"</code> property in the App Key does not
- * match the accessing server IP address.
- * <small>To resolve this, contact our <a href="http://support.temasys.com.sg">support portal</a>.</small>
- * @param {Number} API_CORS_DOMAIN_NOT_MATCH <small>Value <code>4003</code></small>
- * The value of the failure code when <code>"corsurl"</code> property in the App Key does not match accessing CORS.
- * <small>To resolve this, configure the App Key CORS in
- * <a href="https://console.temasys.io">the Temasys Console</a>.</small>
- * @param {Number} API_CREDENTIALS_INVALID <small>Value <code>4004</code></small>
- * The value of the failure code when there is no [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)
- * present in the HTTP headers during the request to the Auth server present nor
- * <code>options.credentials.credentials</code> configuration provided in the <code>init()</code>.
- * <small>To resolve this, ensure that CORS are present in the HTTP headers during the request to the Auth server.</small>
- * @param {Number} API_CREDENTIALS_NOT_MATCH <small>Value <code>4005</code></small>
- * The value of the failure code when the <code>options.credentials.credentials</code> configuration provided in the
- * <code>init()</code> does not match up with the <code>options.credentials.startDateTime</code>,
- * <code>options.credentials.duration</code> or that the <code>"secret"</code> used to generate
- * <code>options.credentials.credentials</code> does not match the App Key's <code>"secret</code> property provided.
- * <small>To resolve this, check that the <code>options.credentials.credentials</code> is generated correctly and
- * that the <code>"secret"</code> used to generate it is from the App Key provided in the <code>init()</code>.</small>
- * @param {Number} API_INVALID_PARENT_KEY <small>Value <code>4006</code></small>
- * The value of the failure code when the App Key provided does not belong to any existing App.
- * <small>To resolve this, check that the provided App Key exists in
- * <a href="https://console.temasys.io">the Developer Console</a>.</small>
- * @param {Number} API_NO_MEETING_RECORD_FOUND <small>Value <code>4010</code></small>
- * The value of the failure code when provided <code>options.credentials</code>
- * does not match any scheduled meetings available for the "Persistent Room" enabled App Key provided.
- * <small>See the <a href="http://support.temasys.com.sg/support/solutions/articles/
- * 12000002811-using-the-persistent-room-feature-to-configure-meetings">Persistent Room article</a> to learn more.</small>
- * @param {Number} API_OVER_SEAT_LIMIT <small>Value <code>4020</code></small>
- * The value of the failure code when App Key has reached its current concurrent users limit.
- * <small>To resolve this, use another App Key. To create App Keys dynamically, see the
- * <a href="https://temasys.atlassian.net/wiki/display/TPD/SkylinkAPI+-+Application+Resources">Application REST API
- * docs</a> for more information.</small>
- * @param {Number} API_RETRIEVAL_FAILED <small>Value <code>4021</code></small>
- * The value of the failure code when App Key retrieval of authentication token fails.
- * <small>If this happens frequently, contact our <a href="http://support.temasys.com.sg">support portal</a>.</small>
- * @param {Number} API_WRONG_ACCESS_DOMAIN <small>Value <code>5005</code></small>
- * The value of the failure code when App Key makes request to the incorrect Auth server.
- * <small>To resolve this, ensure that the <code>roomServer</code> is not configured. If this persists even without
- * <code>roomServer</code> configuration, contact our <a href="http://support.temasys.com.sg">support portal</a>.</small>
- * @param {Number} XML_HTTP_REQUEST_ERROR <small>Value <code>-1</code></small>
- * The value of the failure code when requesting to Auth server has timed out.
- * @param {Number} NO_SOCKET_IO <small>Value <code>1</code></small>
- * The value of the failure code when dependency <a href="http://socket.io/download/">Socket.IO client</a> is not loaded.
- * <small>To resolve this, ensure that the Socket.IO client dependency is loaded before the Skylink SDK.
- * You may use the provided Socket.IO client <a href="http://socket.io/download/">CDN here</a>.</small>
- * @param {Number} NO_XMLHTTPREQUEST_SUPPORT <small>Value <code>2</code></small>
- * The value of the failure code when <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">
- * XMLHttpRequest API</a> required to make request to Auth server is not supported.
- * <small>To resolve this, display in the Web UI to ask clients to switch to the list of supported browser
- * as <a href="https://github.com/Temasys/SkylinkJS/tree/0.6.14#supported-browsers">listed in here</a>.</small>
- * @param {Number} NO_WEBRTC_SUPPORT <small>Value <code>3</code></small>
- * The value of the failure code when <a href="https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/">
- * RTCPeerConnection API</a> required for Peer connections is not supported.
- * <small>To resolve this, display in the Web UI to ask clients to switch to the list of supported browser
- * as <a href="https://github.com/Temasys/SkylinkJS/tree/0.6.14#supported-browsers">listed in here</a>.
- * For <a href="http://confluence.temasys.com.sg/display/TWPP">plugin supported browsers</a>, if the clients
- * does not have the plugin installed, there will be an installation toolbar that will prompt for installation
- * to support the RTCPeerConnection API.</small>
- * @param {Number} NO_PATH <small>Value <code>4</code></small>
- * The value of the failure code when provided <code>init()</code> configuration has errors.
- * @param {Number} ADAPTER_NO_LOADED <small>Value <code>7</code></small>
- * The value of the failure code when dependency <a href="https://github.com/Temasys/AdapterJS/">AdapterJS</a>
- * is not loaded.
- * <small>To resolve this, ensure that the AdapterJS dependency is loaded before the Skylink dependency.
- * You may use the provided AdapterJS <a href="https://github.com/Temasys/AdapterJS/">CDN here</a>.</small>
- * @type JSON
- * @readOnly
- * @for Skylink
- * @since 0.4.0
- */
- Skylink.prototype.READY_STATE_CHANGE_ERROR = {
- API_INVALID: 4001,
- API_DOMAIN_NOT_MATCH: 4002,
- API_CORS_DOMAIN_NOT_MATCH: 4003,
- API_CREDENTIALS_INVALID: 4004,
- API_CREDENTIALS_NOT_MATCH: 4005,
- API_INVALID_PARENT_KEY: 4006,
- API_NO_MEETING_RECORD_FOUND: 4010,
- API_OVER_SEAT_LIMIT: 4020,
- API_RETRIEVAL_FAILED: 4021,
- API_WRONG_ACCESS_DOMAIN: 5005,
- XML_HTTP_REQUEST_ERROR: -1,
- NO_SOCKET_IO: 1,
- NO_XMLHTTPREQUEST_SUPPORT: 2,
- NO_WEBRTC_SUPPORT: 3,
- NO_PATH: 4,
- ADAPTER_NO_LOADED: 7
- };
-
- /**
- * <blockquote class="info"><b>Deprecation Warning!</b>
- * This constant has been deprecated.<br>Automatic nearest regional server has been implemented
- * on the platform.
- * </blockquote>
- * The list of available Auth servers in these regions configured in the
- * <a href="#method_init"><code>init()</code> method</a>.
- * @attribute REGIONAL_SERVER
- * @param {String} APAC1 <small>Value <code>"sg"</code></small>
- * The value of the option to use the Auth server in Asia Pacific (APAC).
- * @param {String} US1 <small>Value <code>"us2"</code></small>
- * The value of the option to use the Auth server in United States (US).
- * @deprecated
- * @type JSON
- * @readOnly
- * @for Skylink
- * @since 0.5.0
- */
- Skylink.prototype.REGIONAL_SERVER = {
- APAC1: 'sg',
- US1: 'us2'
- };
-
- /**
- * Stores the flag if HTTPS connections should be enforced when connecting to
- * the API or Signaling server if App is accessing from HTTP domain.
- * HTTPS connections are enforced if App is accessing from HTTPS domains.
- * @attribute _forceSSL
- * @type Boolean
- * @default false
- * @private
- * @for Skylink
- * @since 0.5.4
- */
- Skylink.prototype._forceSSL = false;
-
- /**
- * Stores the flag if TURNS connections should be enforced when connecting to
- * the TURN server if App is accessing from HTTP domain.
- * TURNS connections are enforced if App is accessing from HTTPS domains.
- * @attribute _forceTURNSSL
- * @type Boolean
- * @default false
- * @private
- * @for Skylink
- * @since 0.6.1
- */
- Skylink.prototype._forceTURNSSL = false;
-
- /**
- * Stores the flag if TURN connections should be enforced when connecting to Peers.
- * This filters all non "relay" ICE candidates to enforce connections via the TURN server.
- * @attribute _forceTURN
- * @type Boolean
- * @default false
- * @private
- * @for Skylink
- * @since 0.6.1
- */
- Skylink.prototype._forceTURN = false;
-
- /**
- * Stores the construct API REST path to obtain Room credentials.
- * @attribute _path
- * @type String
- * @private
- * @for Skylink
- * @since 0.1.0
- */
- Skylink.prototype._path = null;
-
- /**
- * Stores the server region for the Signaling server to use.
- * This is already deprecated an no longer useful. To discuss and remove.
- * @attribute _serverRegion
- * @type String
- * @private
- * @for Skylink
- * @since 0.5.0
- */
- Skylink.prototype._serverRegion = null;
-
- /**
- * Stores the API server url.
- * @attribute _roomServer
- * @type String
- * @private
- * @for Skylink
- * @since 0.5.2
- */
- Skylink.prototype._roomServer = '//api.temasys.com.sg';
-
- /**
- * Stores the App Key configured in <code>init()</code>.
- * @attribute _appKey
- * @type String
- * @private
- * @for Skylink
- * @since 0.3.0
- */
- Skylink.prototype._appKey = null;
-
- /**
- * Stores the default Room name to connect to when <code>joinRoom()</code> does not provide a Room name.
- * @attribute _defaultRoom
- * @type String
- * @private
- * @for Skylink
- * @since 0.3.0
- */
- Skylink.prototype._defaultRoom = null;
-
- /**
- * Stores the <code>init()</code> credentials starting DateTime stamp in ISO 8601.
- * @attribute _roomStart
- * @type String
- * @private
- * @for Skylink
- * @since 0.3.0
- */
- Skylink.prototype._roomStart = null;
-
- /**
- * Stores the <code>init()</code> credentials duration counted in hours.
- * @attribute _roomDuration
- * @type Number
- * @private
- * @for Skylink
- * @since 0.3.0
- */
- Skylink.prototype._roomDuration = null;
-
- /**
- * Stores the <code>init()</code> generated credentials string.
- * @attribute _roomCredentials
- * @type String
- * @private
- * @for Skylink
- * @since 0.3.0
- */
- Skylink.prototype._roomCredentials = null;
-
- /**
- * Stores the current <code>init()</code> readyState.
- * @attribute _readyState
- * @type Number
- * @private
- * @for Skylink
- * @since 0.1.0
- */
- Skylink.prototype._readyState = 0;
-
- /**
- * Stores the "cid" used for <code>joinRoom()</code>.
- * @attribute _key
- * @type String
- * @private
- * @for Skylink
- * @since 0.1.0
- */
- Skylink.prototype._key = null;
-
- /**
- * Stores the "apiOwner" used for <code>joinRoom()</code>.
- * @attribute _appKeyOwner
- * @type String
- * @private
- * @for Skylink
- * @since 0.5.2
- */
- Skylink.prototype._appKeyOwner = null;
-
- /**
- * Stores the Room credentials information for <code>joinRoom()</code>.
- * @attribute _room
- * @param {String} id The "rid" for <code>joinRoom()</code>.
- * @param {String} token The "roomCred" for <code>joinRoom()</code>.
- * @param {String} startDateTime The "start" for <code>joinRoom()</code>.
- * @param {String} duration The "len" for <code>joinRoom()</code>.
- * @param {String} connection The RTCPeerConnection constraints and configuration. This is not used in the SDK
- * except for the "mediaConstraints" property that sets the default <code>getUserMedia()</code> settings.
- * @type JSON
- * @private
- * @for Skylink
- * @since 0.5.2
- */
- Skylink.prototype._room = null;
-
- /**
- * Function that authenticates and initialises App Key used for Room connections.
- * @method init
- * @param {JSON|String} options The configuration options.
- * - When provided as a string, it's configured as <code>options.appKey</code>.
- * @param {String} options.appKey The App Key.
- * <small>By default, <code>init()</code> uses [HTTP CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)
- * authentication. For credentials based authentication, see the <code>options.credentials</code> configuration
- * below. You can know more about the <a href="http://support.temasys.com.sg/support/solutions/articles/
- * 12000002712-authenticating-your-application-key-to-start-a-connection">in the authentication methods article here</a>
- * for more details on the various authentication methods.</small>
- * <small>If you are using the Persistent Room feature for scheduled meetings, you will require to
- * use the credential based authentication. See the <a href="http://support.temasys.com.sg/support
- * /solutions/articles/12000002811-using-the-persistent-room-feature-to-configure-meetings">Persistent Room article here
- * </a> for more information.</small>
- * @param {String} [options.defaultRoom] The default Room to connect to when no <code>room</code> parameter
- * is provided in <a href="#method_joinRoom"><code>joinRoom()</code> method</a>.
- * - When not provided, its value is <code>options.appKey</code>.
- * <small>Note that switching Rooms is not available when using <code>options.credentials</code> based authentication.
- * The Room that User will be connected to is the <code>defaultRoom</code> provided.</small>
- * @param {String} [options.roomServer] The Auth server.
- * <small>Note that this is a debugging feature and is only used when instructed for debugging purposes.</small>
- * @param {String} [options.region] <blockquote class="info"><b>Deprecation Warning!</b>
- * This option has been deprecated.<br>Automatic nearest regional server has been implemented
- * on the platform.</blockquote>
- * The Auth server in the various regions to connect to for better connectivity.
- * [Rel: Skylink.REGIONAL_SERVER]
- * @param {Boolean} [options.enableIceTrickle=true] The flag if Peer connections should
- * trickle ICE for faster connectivity.
- * @param {Boolean} [options.enableDataChannel=true] The flag if Datachannel connections should be enabled.
- * <small>This is required to be enabled for <a href="#method_sendBlobData"><code>sendBlobData()</code> method</a>,
- * <a href="#method_sendURLData"><code>sendURLData()</code> method</a> and
- * <a href="#method_sendP2PMessage"><code>sendP2PMessage()</code> method</a>.</small>
- * @param {Boolean} [options.enableTURNServer=true] The flag if TURN ICE servers should
- * be used when constructing Peer connections to allow TURN connections when required and enabled for the App Key.
- * @param {Boolean} [options.enableSTUNServer=true] The flag if STUN ICE servers should
- * be used when constructing Peer connections to allow TURN connections when required.
- * @param {Boolean} [options.forceTURN=false] The flag if Peer connections should enforce
- * connections over the TURN server.
- * <small>This sets <code>options.enableTURNServer</code> value to <code>true</code> and
- * <code>options.enableSTUNServer</code> value to <code>false</code>.</small>
- * <small>During Peer connections, it filters out non <code>"relay"</code> ICE candidates to
- * ensure that TURN connections is enforced.</small>
- * @param {Boolean} [options.usePublicSTUN=true] The flag if publicly available STUN ICE servers should
- * be used if <code>options.enableSTUNServer</code> is enabled.
- * @param {Boolean} [options.TURNServerTransport] <blockquote class="info">
- * Note that configuring the protocol may not necessarily result in the desired network transports protocol
- * used in the actual TURN network traffic as it depends which protocol the browser selects and connects with.
- * This simply configures the TURN ICE server urls <code?transport=(protocol)</code> query option when constructing
- * the Peer connection. When all protocols are selected, the ICE servers urls are duplicated with all protocols.
- * </blockquote> The option to configure the <code>?transport=</code>
- * query parameter in TURN ICE servers when constructing a Peer connections.
- * - When not provided, its value is <code>ANY</code>.
- * [Rel: Skylink.TURN_TRANSPORT]
- * @param {JSON} [options.credentials] The credentials used for authenticating App Key with
- * credentials to retrieve the Room session token used for connection in <a href="#method_joinRoom">
- * <code>joinRoom()</code> method</a>.
- * <small>Note that switching of Rooms is not allowed when using credentials based authentication, unless
- * <code>init()</code> is invoked again with a different set of credentials followed by invoking
- * the <a href="#method_joinRoom"><code>joinRoom()</code> method</a>.</small>
- * @param {String} options.credentials.startDateTime The credentials User session in Room starting DateTime
- * in <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601 format</a>.
- * @param {Number} options.credentials.duration The credentials User session in Room duration in hours.
- * @param {String} options.credentials.credentials The generated credentials used to authenticate
- * the provided App Key with its <code>"secret"</code> property.
- * <blockquote class="details"><h5>To generate the credentials:</h5><ol>
- * <li>Concatenate a string that consists of the Room name you provide in the <code>options.defaultRoom</code>,
- * the <code>options.credentials.duration</code> and the <code>options.credentials.startDateTime</code>.
- * <small>Example: <code>var concatStr = defaultRoom + "_" + duration + "_" + startDateTime;</code></small></li>
- * <li>Hash the concatenated string with the App Key <code>"secret"</code> property using
- * <a href="https://en.wikipedia.org/wiki/SHA-1">SHA-1</a>.
- * <small>Example: <code>var hash = CryptoJS.HmacSHA1(concatStr, appKeySecret);</code></small>
- * <small>See the <a href="https://code.google.com/p/crypto-js/#HMAC"><code>CryptoJS.HmacSHA1</code> library</a>.</small></li>
- * <li>Encode the hashed string using <a href="https://en.wikipedia.org/wiki/Base64">base64</a>
- * <small>Example: <code>var b64Str = hash.toString(CryptoJS.enc.Base64);</code></small>
- * <small>See the <a href="https://code.google.com/p/crypto-js/#The_Cipher_Output">CryptoJS.enc.Base64</a> library</a>.</small></li>
- * <li>Encode the base64 encoded string to replace special characters using UTF-8 encoding.
- * <small>Example: <code>var credentials = encodeURIComponent(base64String);</code></small>
- * <small>See <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
- * Global_Objects/encodeURIComponent">encodeURIComponent() API</a>.</small></li></ol></blockquote>
- * @param {Boolean} [options.audioFallback=false] The flag if <a href="#method_getUserMedia">
- * <code>getUserMedia()</code> method</a> should fallback to retrieve only audio Stream when
- * retrieving audio and video Stream fails.
- * @param {Boolean} [options.forceSSL=false] The flag if HTTPS connections should be enforced
- * during request to Auth server and socket connections to Signaling server
- * when accessing <code>window.location.protocol</code> value is <code>"http:"</code>.
- * <small>By default, <code>"https:"</code> protocol connections uses HTTPS connections.</small>
- * @param {String} [options.audioCodec] <blockquote class="info">
- * Note that if the audio codec is not supported, the SDK will not configure the local <code>"offer"</code> or
- * <code>"answer"</code> session description to prefer the codec.</blockquote>
- * The option to configure the preferred audio codec
- * to use to encode sending audio data when available for Peer connection.
- * - When not provided, its value is <code>AUTO</code>.
- * [Rel: Skylink.AUDIO_CODEC]
- * @param {String} [options.videoCodec] <blockquote class="info">
- * Note that if the video codec is not supported, the SDK will not configure the local <code>"offer"</code> or
- * <code>"answer"</code> session description to prefer the codec.</blockquote>
- * The option to configure the preferred video codec
- * to use to encode sending video data when available for Peer connection.
- * - When not provided, its value is <code>AUTO</code>.
- * [Rel: Skylink.VIDEO_CODEC]
- * @param {Number} [options.socketTimeout=20000] The timeout for each attempts for socket connection
- * with the Signaling server to indicate that connection has timed out and has failed to establish.
- * <small>Note that the mininum timeout value is <code>5000</code>. If less, this value will be <code>5000</code>.</small>
- * @param {Boolean} [options.forceTURNSSL=false] <blockquote class="info">
- * Note that currently Firefox does not support the TURNS protocol, and that if TURNS is required,
- * TURN ICE servers using port <code>443</code> will be used instead.</blockquote>
- * The flag if TURNS protocol should be used when <code>options.enableTURNServer</code> is enabled.
- * <small>By default, <code>"https:"</code> protocol connections uses TURNS protocol.</small>
- * @param {Function} [callback] The callback function fired when request has completed.
- * <small>Function parameters signature is <code>function (error, success)</code></small>
- * <small>Function request completion is determined by the <a href="#event_readyStateChange">
- * <code>readyStateChange</code> event</a> <code>state</code> parameter payload value
- * as <code>COMPLETED</code> for request success.</small>
- * [Rel: Skylink.READY_STATE_CHANGE]
- * @param {JSON|String} callback.error The error result in request.
- * - When defined as string, it's the error when required App Key is not provided.
- * <small>Defined as <code>null</code> when there are no errors in request</small>
- * @param {Number} callback.error.errorCode The <a href="#event_readyStateChange"><code>readyStateChange</code>
- * event</a> <code>error.errorCode</code> parameter payload value.
- * [Rel: Skylink.READY_STATE_CHANGE_ERROR]
- * @param {Object} callback.error.error The <a href="#event_readyStateChange"><code>readyStateChange</code>
- * event</a> <code>error.content</code> parameter payload value.
- * @param {Number} callback.error.status The <a href="#event_readyStateChange"><code>readyStateChange</code>
- * event</a> <code>error.status</code> parameter payload value.
- * @param {JSON} callback.success The success result in request.
- * <small>Defined as <code>null</code> when there are errors in request</small>
- * @param {String} callback.success.serverUrl The constructed REST URL requested to Auth server.
- * @param {String} callback.success.readyState The current ready state.
- * [Rel: Skylink.READY_STATE_CHANGE]
- * @param {String} callback.success.selectedRoom The Room based on the current Room session token retrieved for.
- * @param {String} callback.success.appKey The configured value of the <code>options.appKey</code>.
- * @param {String} callback.success.defaultRoom The configured value of the <code>options.defaultRoom</code>.
- * @param {String} callback.success.roomServer The configured value of the <code>options.roomServer</code>.
- * @param {Boolean} callback.success.enableIceTrickle The configured value of the <code>options.enableIceTrickle</code>.
- * @param {Boolean} callback.success.enableDataChannel The configured value of the <code>options.enableDataChannel</code>.
- * @param {Boolean} callback.success.enableTURNServer The configured value of the <code>options.enableTURNServer</code>.
- * @param {Boolean} callback.success.enableSTUNServer The configured value of the <code>options.enableSTUNServer</code>.
- * @param {Boolean} callback.success.TURNTransport The configured value of the <code>options.TURNServerTransport</code>.
- * @param {String} callback.success.serverRegion The configured value of the <code>options.region</code>.
- * @param {Boolean} callback.success.audioFallback The configured value of the <code>options.audioFallback</code>.
- * @param {Boolean} callback.success.forceSSL The configured value of the <code>options.forceSSL</code>.
- * @param {String} callback.success.audioCodec The configured value of the <code>options.audioCodec</code>.
- * @param {String} callback.success.videoCodec The configured value of the <code>options.videoCodec</code>.
- * @param {Number} callback.success.socketTimeout The configured value of the <code>options.socketTimeout</code>.
- * @param {Boolean} callback.success.forceTURNSSL The configured value of the <code>options.forceTURNSSL</code>.
- * @param {Boolean} callback.success.forceTURN The configured value of the <code>options.forceTURN</code>.
- * @param {Boolean} callback.success.usePublicSTUN The configured value of the <code>options.usePublicSTUN</code>.
- * @example
- * // Example 1: Using CORS authentication and connection to default Room
- * skylinkDemo(appKey, function (error, success) {
- * if (error) return;
- * skylinkDemo.joinRoom(); // Goes to default Room
- * });
- *
- * // Example 2: Using CORS authentication and connection to a different Room
- * skylinkDemo(appKey, function (error, success) {
- * skylinkDemo.joinRoom("testxx"); // Goes to "testxx" Room
- * });
- *
- * // Example 3: Using credentials authentication and connection to only default Room
- * var defaultRoom = "test",
- * startDateTime = (new Date()).toISOString(),
- * duration = 1, // Allows only User session to stay for 1 hour
- * appKeySecret = "xxxxxxx",
- * hash = CryptoJS.HmacSHA1(defaultRoom + "_" + duration + "_" + startDateTime, appKeySecret);
- * credentials = encodeURIComponent(hash.toString(CryptoJS.enc.Base64));
- *
- * skylinkDemo({
- * defaultRoom: defaultRoom,
- * appKey: appKey,
- * credentials: {
- * duration: duration,
- * startDateTime: startDateTime,
- * credentials: credentials
- * }
- * }, function (error, success) {
- * if (error) return;
- * skylinkDemo.joinRoom(); // Goes to default Room (switching to different Room is not allowed for credentials authentication)
- * });
- * @trigger <ol class="desc-seq">
- * <li>If parameter <code>options</code> is not provided: <ol><li><b>ABORT</b> and return error.</li></ol></li>
- * <li>Checks if dependecies and browser APIs are available. <ol><li>If AdapterJS is not loaded: <ol>
- * <li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a> triggers
- * parameter payload <code>state</code> as <code>ERROR</code> and <code>error.errorCode</code> as
- * <code>ADAPTER_NO_LOADED</code>.</li><li><b>ABORT</b> and return error.</li></ol></li>
- * <li>If socket.io-client is not loaded: <ol><li><a href="#event_readyStateChange">
- * <code>readyStateChange</code> event</a> triggers parameter payload <code>state</code>
- * as <code>ERROR</code> and <code>error.errorCode</code> as <code>NO_SOCKET_IO</code>.</li>
- * <li><b>ABORT</b> and return error. </li></ol></li>
- * <li>If XMLHttpRequest API is not available: <ol><li><a href="#event_readyStateChange">
- * <code>readyStateChange</code> event</a> triggers parameter payload <code>state</code>
- * as <code>ERROR</code> and <code>error.errorCode</code> as <code>NO_XMLHTTPREQUEST_SUPPORT</code>.</li>
- * <li><b>ABORT</b> and return error.</li></ol></li><li>If WebRTC is not supported by device: <ol>
- * <li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a> triggers parameter
- * payload <code>state</code> as <code>ERROR</code> and <code>error.errorCode</code> as
- * <code>NO_WEBRTC_SUPPORT</code>.</li><li><b>ABORT</b> and return error.</li></ol></li></ol></li>
- * <li>Retrieves Room session token from Auth server. <ol>
- * <li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a> triggers
- * parameter payload <code>state</code> as <code>LOADING</code>.</li>
- * <li>If retrieval was successful: <ol><li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a>
- * triggers parameter payload <code>state</code> as <code>COMPLETED</code>.</li></ol></li><li>Else: <ol>
- * <li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a> triggers parameter
- * payload <code>state</code> as <code>ERROR</code>.</li><li><b>ABORT</b> and return error.</li></ol></li></ol></li></ol>
- * @for Skylink
- * @since 0.5.5
- */
- Skylink.prototype.init = function(options, callback) {
- var self = this;
-
- if (typeof options === 'function'){
- callback = options;
- options = undefined;
- }
-
- if (!options) {
- var error = 'No API key provided';
- log.error(error);
- if (typeof callback === 'function'){
- callback(error,null);
- }
- return;
- }
-
- var appKey, room, defaultRoom, region;
- var startDateTime, duration, credentials;
- var roomServer = self._roomServer;
- // NOTE: Should we get all the default values from the variables
- // rather than setting it?
- var enableIceTrickle = true;
- var enableDataChannel = true;
- var enableSTUNServer = true;
- var enableTURNServer = true;
- var TURNTransport = self.TURN_TRANSPORT.ANY;
- var audioFallback = false;
- var forceSSL = false;
- var socketTimeout = 0;
- var forceTURNSSL = false;
- var audioCodec = self.AUDIO_CODEC.AUTO;
- var videoCodec = self.VIDEO_CODEC.AUTO;
- var forceTURN = false;
- var usePublicSTUN = true;
-
- log.log('Provided init options:', options);
-
- if (typeof options === 'string') {
- // set all the default api key, default room and room
- appKey = options;
- defaultRoom = appKey;
- room = appKey;
- } else {
- // set the api key
- appKey = options.appKey || options.apiKey;
- // set the room server
- roomServer = (typeof options.roomServer === 'string') ?
- options.roomServer : roomServer;
- // check room server if it ends with /. Remove the extra /
- roomServer = (roomServer.lastIndexOf('/') ===
- (roomServer.length - 1)) ? roomServer.substring(0,
- roomServer.length - 1) : roomServer;
- // set the region
- region = (typeof options.region === 'string') ?
- options.region : region;
- // set the default room
- defaultRoom = (typeof options.defaultRoom === 'string') ?
- options.defaultRoom : appKey;
- // set the selected room
- room = defaultRoom;
- // set ice trickle option
- enableIceTrickle = (typeof options.enableIceTrickle === 'boolean') ?
- options.enableIceTrickle : enableIceTrickle;
- // set data channel option
- enableDataChannel = (typeof options.enableDataChannel === 'boolean') ?
- options.enableDataChannel : enableDataChannel;
- // set stun server option
- enableSTUNServer = (typeof options.enableSTUNServer === 'boolean') ?
- options.enableSTUNServer : enableSTUNServer;
- // set turn server option
- enableTURNServer = (typeof options.enableTURNServer === 'boolean') ?
- options.enableTURNServer : enableTURNServer;
- // set the force ssl always option
- forceSSL = (typeof options.forceSSL === 'boolean') ?
- options.forceSSL : forceSSL;
- // set the socket timeout option
- socketTimeout = (typeof options.socketTimeout === 'number') ?
- options.socketTimeout : socketTimeout;
- // set the socket timeout option to be above 5000
- socketTimeout = (socketTimeout < 5000) ? 5000 : socketTimeout;
- // set the force turn ssl always option
- forceTURNSSL = (typeof options.forceTURNSSL === 'boolean') ?
- options.forceTURNSSL : forceTURNSSL;
- // set the preferred audio codec
- audioCodec = typeof options.audioCodec === 'string' ?
- options.audioCodec : audioCodec;
- // set the preferred video codec
- videoCodec = typeof options.videoCodec === 'string' ?
- options.videoCodec : videoCodec;
- // set the force turn server option
- forceTURN = (typeof options.forceTURN === 'boolean') ?
- options.forceTURN : forceTURN;
- // set the use public stun option
- usePublicSTUN = (typeof options.usePublicSTUN === 'boolean') ?
- options.usePublicSTUN : usePublicSTUN;
-
- // set turn transport option
- if (typeof options.TURNServerTransport === 'string') {
- // loop out for every transport option
- for (var type in self.TURN_TRANSPORT) {
- if (self.TURN_TRANSPORT.hasOwnProperty(type)) {
- // do a check if the transport option is valid
- if (self.TURN_TRANSPORT[type] === options.TURNServerTransport) {
- TURNTransport = options.TURNServerTransport;
- break;
- }
- }
- }
- }
- // set audio fallback option
- audioFallback = options.audioFallback || audioFallback;
- // Custom default meeting timing and duration
- // Fallback to default if no duration or startDateTime provided
- if (options.credentials &&
- typeof options.credentials.credentials === 'string' &&
- typeof options.credentials.duration === 'number' &&
- typeof options.credentials.startDateTime === 'string') {
- // set start data time
- startDateTime = options.credentials.startDateTime;
- // set the duration
- duration = options.credentials.duration;
- // set the credentials
- credentials = options.credentials.credentials;
- }
-
- // if force turn option is set to on
- if (forceTURN === true) {
- enableTURNServer = true;
- enableSTUNServer = false;
- }
- }
- // api key path options
- self._appKey = appKey;
- self._roomServer = roomServer;
- self._defaultRoom = defaultRoom;
- self._selectedRoom = room;
- self._serverRegion = region || null;
- self._path = roomServer + '/api/' + appKey + '/' + room;
- // set credentials if there is
- if (credentials && startDateTime && duration) {
- self._roomStart = startDateTime;
- self._roomDuration = duration;
- self._roomCredentials = credentials;
- self._path += (credentials) ? ('/' + startDateTime + '/' +
- duration + '?&cred=' + credentials) : '';
- }
-
- self._path += ((credentials) ? '&' : '?') + 'rand=' + (new Date()).toISOString();
-
- // check if there is a other query parameters or not
- if (region) {
- self._path += '&rg=' + region;
- }
- // skylink functionality options
- self._enableIceTrickle = enableIceTrickle;
- self._enableDataChannel = enableDataChannel;
- self._enableSTUN = enableSTUNServer;
- self._enableTURN = enableTURNServer;
- self._TURNTransport = TURNTransport;
- self._audioFallback = audioFallback;
- self._forceSSL = forceSSL;
- self._socketTimeout = socketTimeout;
- self._forceTURNSSL = forceTURNSSL;
- self._selectedAudioCodec = audioCodec;
- self._selectedVideoCodec = videoCodec;
- self._forceTURN = forceTURN;
- self._usePublicSTUN = usePublicSTUN;
-
- log.log('Init configuration:', {
- serverUrl: self._path,
- readyState: self._readyState,
- appKey: self._appKey,
- roomServer: self._roomServer,
- defaultRoom: self._defaultRoom,
- selectedRoom: self._selectedRoom,
- serverRegion: self._serverRegion,
- enableDataChannel: self._enableDataChannel,
- enableIceTrickle: self._enableIceTrickle,
- enableTURNServer: self._enableTURN,
- enableSTUNServer: self._enableSTUN,
- TURNTransport: self._TURNTransport,
- audioFallback: self._audioFallback,
- forceSSL: self._forceSSL,
- socketTimeout: self._socketTimeout,
- forceTURNSSL: self._forceTURNSSL,
- audioCodec: self._selectedAudioCodec,
- videoCodec: self._selectedVideoCodec,
- forceTURN: self._forceTURN,
- usePublicSTUN: self._usePublicSTUN
- });
- // trigger the readystate
- self._readyState = 0;
- self._trigger('readyStateChange', self.READY_STATE_CHANGE.INIT, null, self._selectedRoom);
-
- if (typeof callback === 'function'){
- var hasTriggered = false;
-
- var readyStateChangeFn = function (readyState, error) {
- if (!hasTriggered) {
- if (readyState === self.READY_STATE_CHANGE.COMPLETED) {
- log.log([null, 'Socket', null, 'Firing callback. ' +
- 'Ready state change has met provided state ->'], readyState);
- hasTriggered = true;
- self.off('readyStateChange', readyStateChangeFn);
- callback(null,{
- serverUrl: self._path,
- readyState: self._readyState,
- appKey: self._appKey,
- roomServer: self._roomServer,
- defaultRoom: self._defaultRoom,
- selectedRoom: self._selectedRoom,
- serverRegion: self._serverRegion,
- enableDataChannel: self._enableDataChannel,
- enableIceTrickle: self._enableIceTrickle,
- enableTURNServer: self._enableTURN,
- enableSTUNServer: self._enableSTUN,
- TURNTransport: self._TURNTransport,
- audioFallback: self._audioFallback,
- forceSSL: self._forceSSL,
- socketTimeout: self._socketTimeout,
- forceTURNSSL: self._forceTURNSSL,
- audioCodec: self._selectedAudioCodec,
- videoCodec: self._selectedVideoCodec,
- forceTURN: self._forceTURN,
- usePublicSTUN: self._usePublicSTUN
- });
- } else if (readyState === self.READY_STATE_CHANGE.ERROR) {
- log.log([null, 'Socket', null, 'Firing callback. ' +
- 'Ready state change has met provided state ->'], readyState);
- log.debug([null, 'Socket', null, 'Ready state met failure'], error);
- hasTriggered = true;
- self.off('readyStateChange', readyStateChangeFn);
- callback({
- error: new Error(error),
- errorCode: error.errorCode,
- status: error.status
- },null);
- }
- }
- };
-
- self.on('readyStateChange', readyStateChangeFn);
- }
-
- self._loadInfo();
- };
-
- /**
- * Starts retrieving Room credentials information from API server.
- * @method _requestServerInfo
- * @private
- * @for Skylink
- * @since 0.5.2
- */
- Skylink.prototype._requestServerInfo = function(method, url, callback, params) {
- var self = this;
- // XDomainRequest is supported in IE8 - 9
- var useXDomainRequest = typeof window.XDomainRequest === 'function' ||
- typeof window.XDomainRequest === 'object';
-
- self._socketUseXDR = useXDomainRequest;
- var xhr;
-
- // set force SSL option
- url = (self._forceSSL) ? 'https:' + url : url;
-
- if (useXDomainRequest) {
- log.debug([null, 'XMLHttpRequest', method, 'Using XDomainRequest. ' +
- 'XMLHttpRequest is now XDomainRequest'], {
- agent: window.webrtcDetectedBrowser,
- version: window.webrtcDetectedVersion
- });
- xhr = new XDomainRequest();
- xhr.setContentType = function (contentType) {
- xhr.contentType = contentType;
- };
- } else {
- log.debug([null, 'XMLHttpRequest', method, 'Using XMLHttpRequest'], {
- agent: window.webrtcDetectedBrowser,
- version: window.webrtcDetectedVersion
- });
- xhr = new window.XMLHttpRequest();
- xhr.setContentType = function (contentType) {
- xhr.setRequestHeader('Content-type', contentType);
- };
- }
-
- xhr.onload = function () {
- var response = xhr.responseText || xhr.response;
- var status = xhr.status || 200;
- log.debug([null, 'XMLHttpRequest', method, 'Received sessions parameters'],
- JSON.parse(response || '{}'));
- callback(status, JSON.parse(response || '{}'));
- };
-
- xhr.onerror = function (error) {
- log.error([null, 'XMLHttpRequest', method, 'Failed retrieving information:'],
- { status: xhr.status });
- self._readyState = -1;
- self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
- status: xhr.status || null,
- content: 'Network error occurred. (Status: ' + xhr.status + ')',
- errorCode: self.READY_STATE_CHANGE_ERROR.XML_HTTP_REQUEST_ERROR
- }, self._selectedRoom);
- };
-
- xhr.onprogress = function () {
- log.debug([null, 'XMLHttpRequest', method,
- 'Retrieving information and config from webserver. Url:'], url);
- log.debug([null, 'XMLHttpRequest', method, 'Provided parameters:'], params);
- };
-
- xhr.open(method, url, true);
- if (params) {
- xhr.setContentType('application/json;charset=UTF-8');
- xhr.send(JSON.stringify(params));
- } else {
- xhr.send();
- }
- };
-
- /**
- * Parses the Room credentials information retrieved from API server.
- * @method _parseInfo
- * @private
- * @for Skylink
- * @since 0.5.2
- */
- Skylink.prototype._parseInfo = function(info) {
- log.log('Parsing parameter from server', info);
- if (!info.pc_constraints && !info.offer_constraints) {
- this._trigger('readyStateChange', this.READY_STATE_CHANGE.ERROR, {
- status: 200,
- content: info.info,
- errorCode: info.error
- }, self._selectedRoom);
- return;
- }
-
- log.debug('Peer connection constraints:', info.pc_constraints);
- log.debug('Offer constraints:', info.offer_constraints);
-
- this._key = info.cid;
- this._appKeyOwner = info.apiOwner;
-
- this._signalingServer = info.ipSigserver;
- this._signalingServerPort = null;
-
- this._isPrivileged = info.isPrivileged;
- this._autoIntroduce = info.autoIntroduce;
-
- this._user = {
- uid: info.username,
- token: info.userCred,
- timeStamp: info.timeStamp,
- streams: [],
- info: {}
- };
- this._room = {
- id: info.room_key,
- token: info.roomCred,
- startDateTime: info.start,
- duration: info.len,
- connection: {
- peerConstraints: JSON.parse(info.pc_constraints),
- peerConfig: null,
- offerConstraints: JSON.parse(info.offer_constraints),
- sdpConstraints: {
- mandatory: {
- OfferToReceiveAudio: true,
- OfferToReceiveVideo: true
- }
- },
- mediaConstraints: JSON.parse(info.media_constraints)
- }
- };
- //this._parseDefaultMediaStreamSettings(this._room.connection.mediaConstraints);
-
- // set the socket ports
- this._socketPorts = {
- 'http:': info.httpPortList,
- 'https:': info.httpsPortList
- };
-
- // use default bandwidth and media resolution provided by server
- //this._streamSettings.bandwidth = info.bandwidth;
- //this._streamSettings.video = info.video;
- this._readyState = 2;
- this._trigger('readyStateChange', this.READY_STATE_CHANGE.COMPLETED, null, this._selectedRoom);
- log.info('Parsed parameters from webserver. ' +
- 'Ready for web-realtime communication');
-
- };
-
- /**
- * Loads and checks the dependencies if they are loaded correctly.
- * @method _loadInfo
- * @private
- * @for Skylink
- * @since 0.5.2
- */
- Skylink.prototype._loadInfo = function() {
- var self = this;
-
- // check if adapterjs has been loaded already first or not
- var adapter = (function () {
- try {
- return window.AdapterJS || AdapterJS;
- } catch (error) {
- return false;
- }
- })();
-
- if (!(!!adapter ? typeof adapter.webRTCReady === 'function' : false)) {
- var noAdapterErrorMsg = 'AdapterJS dependency is not loaded or incorrect AdapterJS dependency is used';
- self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
- status: null,
- content: noAdapterErrorMsg,
- errorCode: self.READY_STATE_CHANGE_ERROR.ADAPTER_NO_LOADED
- }, self._selectedRoom);
- return;
- }
- if (!window.io) {
- log.error('Socket.io not loaded. Please load socket.io');
- self._readyState = -1;
- self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
- status: null,
- content: 'Socket.io not found',
- errorCode: self.READY_STATE_CHANGE_ERROR.NO_SOCKET_IO
- }, self._selectedRoom);
- return;
- }
- if (!window.XMLHttpRequest) {
- log.error('XMLHttpRequest not supported. Please upgrade your browser');
- self._readyState = -1;
- self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
- status: null,
- content: 'XMLHttpRequest not available',
- errorCode: self.READY_STATE_CHANGE_ERROR.NO_XMLHTTPREQUEST_SUPPORT
- }, self._selectedRoom);
- return;
- }
- if (!self._path) {
- log.error('Skylink is not initialised. Please call init() first');
- self._readyState = -1;
- self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
- status: null,
- content: 'No API Path is found',
- errorCode: self.READY_STATE_CHANGE_ERROR.NO_PATH
- }, self._selectedRoom);
- return;
- }
- adapter.webRTCReady(function () {
- if (!window.RTCPeerConnection) {
- log.error('WebRTC not supported. Please upgrade your browser');
- self._readyState = -1;
- self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
- status: null,
- content: 'WebRTC not available',
- errorCode: self.READY_STATE_CHANGE_ERROR.NO_WEBRTC_SUPPORT
- }, self._selectedRoom);
- return;
- }
- self._readyState = 1;
- self._trigger('readyStateChange', self.READY_STATE_CHANGE.LOADING, null, self._selectedRoom);
- self._requestServerInfo('GET', self._path, function(status, response) {
- if (status !== 200) {
- // 403 - Room is locked
- // 401 - API Not authorized
- // 402 - run out of credits
- var errorMessage = 'XMLHttpRequest status not OK\nStatus was: ' + status;
- self._readyState = 0;
- self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
- status: status,
- content: (response) ? (response.info || errorMessage) : errorMessage,
- errorCode: response.error ||
- self.READY_STATE_CHANGE_ERROR.INVALID_XMLHTTPREQUEST_STATUS
- }, self._selectedRoom);
- return;
- }
- self._parseInfo(response);
- });
- });
- };
-
- /**
- * Starts initialising for Room credentials for room name provided in <code>joinRoom()</code> method.
- * @method _initSelectedRoom
- * @private
- * @for Skylink
- * @since 0.5.5
- */
- Skylink.prototype._initSelectedRoom = function(room, callback) {
- var self = this;
- if (typeof room === 'function' || typeof room === 'undefined') {
- log.error('Invalid room provided. Room:', room);
- return;
- }
- var defaultRoom = self._defaultRoom;
- var initOptions = {
- roomServer: self._roomServer,
- defaultRoom: room || defaultRoom,
- appKey: self._appKey,
- region: self._serverRegion,
- enableDataChannel: self._enableDataChannel,
- enableIceTrickle: self._enableIceTrickle
- };
- if (self._roomCredentials) {
- initOptions.credentials = {
- credentials: self._roomCredentials,
- duration: self._roomDuration,
- startDateTime: self._roomStart
- };
- }
- self.init(initOptions, function (error, success) {
- self._defaultRoom = defaultRoom;
- if (error) {
- callback(error);
- } else {
- callback(null);
- }
- });
- };
-
-
-
-
-
-
-