File: source/room-init.js

  1. /**
  2. * The list of <a href="#method_init"><code>init()</code> method</a> ready states.
  3. * @attribute READY_STATE_CHANGE
  4. * @param {Number} INIT <small>Value <code>0</code></small>
  5. * The value of the state when <code>init()</code> has just started.
  6. * @param {Number} LOADING <small>Value <code>1</code></small>
  7. * The value of the state when <code>init()</code> is authenticating App Key provided
  8. * (and with credentials if provided as well) with the Auth server.
  9. * @param {Number} COMPLETED <small>Value <code>2</code></small>
  10. * The value of the state when <code>init()</code> has successfully authenticated with the Auth server.
  11. * Room session token is generated for joining the <code>defaultRoom</code> provided in <code>init()</code>.
  12. * <small>Room session token has to be generated each time User switches to a different Room
  13. * in <a href="#method_joinRoom"><code>joinRoom()</code> method</a>.</small>
  14. * @param {Number} ERROR <small>Value <code>-1</code></small>
  15. * The value of the state when <code>init()</code> has failed authenticating with the Auth server.
  16. * [Rel: Skylink.READY_STATE_CHANGE_ERROR]
  17. * @type JSON
  18. * @readOnly
  19. * @for Skylink
  20. * @since 0.1.0
  21. */
  22. Skylink.prototype.READY_STATE_CHANGE = {
  23. INIT: 0,
  24. LOADING: 1,
  25. COMPLETED: 2,
  26. ERROR: -1
  27. };
  28.  
  29. /**
  30. * The list of <a href="#method_init"><code>init()</code> method</a> ready state failure codes.
  31. * @attribute READY_STATE_CHANGE_ERROR
  32. * @param {Number} API_INVALID <small>Value <code>4001</code></small>
  33. * The value of the failure code when provided App Key in <code>init()</code> does not exists.
  34. * <small>To resolve this, check that the provided App Key exists in
  35. * <a href="https://console.temasys.io">the Temasys Console</a>.</small>
  36. * @param {Number} API_DOMAIN_NOT_MATCH <small>Value <code>4002</code></small>
  37. * The value of the failure code when <code>"domainName"</code> property in the App Key does not
  38. * match the accessing server IP address.
  39. * <small>To resolve this, contact our <a href="http://support.temasys.com.sg">support portal</a>.</small>
  40. * @param {Number} API_CORS_DOMAIN_NOT_MATCH <small>Value <code>4003</code></small>
  41. * The value of the failure code when <code>"corsurl"</code> property in the App Key does not match accessing CORS.
  42. * <small>To resolve this, configure the App Key CORS in
  43. * <a href="https://console.temasys.io">the Temasys Console</a>.</small>
  44. * @param {Number} API_CREDENTIALS_INVALID <small>Value <code>4004</code></small>
  45. * The value of the failure code when there is no [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)
  46. * present in the HTTP headers during the request to the Auth server present nor
  47. * <code>options.credentials.credentials</code> configuration provided in the <code>init()</code>.
  48. * <small>To resolve this, ensure that CORS are present in the HTTP headers during the request to the Auth server.</small>
  49. * @param {Number} API_CREDENTIALS_NOT_MATCH <small>Value <code>4005</code></small>
  50. * The value of the failure code when the <code>options.credentials.credentials</code> configuration provided in the
  51. * <code>init()</code> does not match up with the <code>options.credentials.startDateTime</code>,
  52. * <code>options.credentials.duration</code> or that the <code>"secret"</code> used to generate
  53. * <code>options.credentials.credentials</code> does not match the App Key's <code>"secret</code> property provided.
  54. * <small>To resolve this, check that the <code>options.credentials.credentials</code> is generated correctly and
  55. * that the <code>"secret"</code> used to generate it is from the App Key provided in the <code>init()</code>.</small>
  56. * @param {Number} API_INVALID_PARENT_KEY <small>Value <code>4006</code></small>
  57. * The value of the failure code when the App Key provided does not belong to any existing App.
  58. * <small>To resolve this, check that the provided App Key exists in
  59. * <a href="https://console.temasys.io">the Developer Console</a>.</small>
  60. * @param {Number} API_NO_MEETING_RECORD_FOUND <small>Value <code>4010</code></small>
  61. * The value of the failure code when provided <code>options.credentials</code>
  62. * does not match any scheduled meetings available for the "Persistent Room" enabled App Key provided.
  63. * <small>See the <a href="http://support.temasys.com.sg/support/solutions/articles/
  64. * 12000002811-using-the-persistent-room-feature-to-configure-meetings">Persistent Room article</a> to learn more.</small>
  65. * @param {Number} API_OVER_SEAT_LIMIT <small>Value <code>4020</code></small>
  66. * The value of the failure code when App Key has reached its current concurrent users limit.
  67. * <small>To resolve this, use another App Key. To create App Keys dynamically, see the
  68. * <a href="https://temasys.atlassian.net/wiki/display/TPD/SkylinkAPI+-+Application+Resources">Application REST API
  69. * docs</a> for more information.</small>
  70. * @param {Number} API_RETRIEVAL_FAILED <small>Value <code>4021</code></small>
  71. * The value of the failure code when App Key retrieval of authentication token fails.
  72. * <small>If this happens frequently, contact our <a href="http://support.temasys.com.sg">support portal</a>.</small>
  73. * @param {Number} API_WRONG_ACCESS_DOMAIN <small>Value <code>5005</code></small>
  74. * The value of the failure code when App Key makes request to the incorrect Auth server.
  75. * <small>To resolve this, ensure that the <code>roomServer</code> is not configured. If this persists even without
  76. * <code>roomServer</code> configuration, contact our <a href="http://support.temasys.com.sg">support portal</a>.</small>
  77. * @param {Number} XML_HTTP_REQUEST_ERROR <small>Value <code>-1</code></small>
  78. * The value of the failure code when requesting to Auth server has timed out.
  79. * @param {Number} NO_SOCKET_IO <small>Value <code>1</code></small>
  80. * The value of the failure code when dependency <a href="http://socket.io/download/">Socket.IO client</a> is not loaded.
  81. * <small>To resolve this, ensure that the Socket.IO client dependency is loaded before the Skylink SDK.
  82. * You may use the provided Socket.IO client <a href="http://socket.io/download/">CDN here</a>.</small>
  83. * @param {Number} NO_XMLHTTPREQUEST_SUPPORT <small>Value <code>2</code></small>
  84. * The value of the failure code when <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">
  85. * XMLHttpRequest API</a> required to make request to Auth server is not supported.
  86. * <small>To resolve this, display in the Web UI to ask clients to switch to the list of supported browser
  87. * as <a href="https://github.com/Temasys/SkylinkJS/tree/0.6.14#supported-browsers">listed in here</a>.</small>
  88. * @param {Number} NO_WEBRTC_SUPPORT <small>Value <code>3</code></small>
  89. * The value of the failure code when <a href="https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/">
  90. * RTCPeerConnection API</a> required for Peer connections is not supported.
  91. * <small>To resolve this, display in the Web UI to ask clients to switch to the list of supported browser
  92. * as <a href="https://github.com/Temasys/SkylinkJS/tree/0.6.14#supported-browsers">listed in here</a>.
  93. * For <a href="http://confluence.temasys.com.sg/display/TWPP">plugin supported browsers</a>, if the clients
  94. * does not have the plugin installed, there will be an installation toolbar that will prompt for installation
  95. * to support the RTCPeerConnection API.</small>
  96. * @param {Number} NO_PATH <small>Value <code>4</code></small>
  97. * The value of the failure code when provided <code>init()</code> configuration has errors.
  98. * @param {Number} ADAPTER_NO_LOADED <small>Value <code>7</code></small>
  99. * The value of the failure code when dependency <a href="https://github.com/Temasys/AdapterJS/">AdapterJS</a>
  100. * is not loaded.
  101. * <small>To resolve this, ensure that the AdapterJS dependency is loaded before the Skylink dependency.
  102. * You may use the provided AdapterJS <a href="https://github.com/Temasys/AdapterJS/">CDN here</a>.</small>
  103. * @type JSON
  104. * @readOnly
  105. * @for Skylink
  106. * @since 0.4.0
  107. */
  108. Skylink.prototype.READY_STATE_CHANGE_ERROR = {
  109. API_INVALID: 4001,
  110. API_DOMAIN_NOT_MATCH: 4002,
  111. API_CORS_DOMAIN_NOT_MATCH: 4003,
  112. API_CREDENTIALS_INVALID: 4004,
  113. API_CREDENTIALS_NOT_MATCH: 4005,
  114. API_INVALID_PARENT_KEY: 4006,
  115. API_NO_MEETING_RECORD_FOUND: 4010,
  116. API_OVER_SEAT_LIMIT: 4020,
  117. API_RETRIEVAL_FAILED: 4021,
  118. API_WRONG_ACCESS_DOMAIN: 5005,
  119. XML_HTTP_REQUEST_ERROR: -1,
  120. NO_SOCKET_IO: 1,
  121. NO_XMLHTTPREQUEST_SUPPORT: 2,
  122. NO_WEBRTC_SUPPORT: 3,
  123. NO_PATH: 4,
  124. ADAPTER_NO_LOADED: 7
  125. };
  126.  
  127. /**
  128. * <blockquote class="info"><b>Deprecation Warning!</b>
  129. * This constant has been deprecated.<br>Automatic nearest regional server has been implemented
  130. * on the platform.
  131. * </blockquote>
  132. * The list of available Auth servers in these regions configured in the
  133. * <a href="#method_init"><code>init()</code> method</a>.
  134. * @attribute REGIONAL_SERVER
  135. * @param {String} APAC1 <small>Value <code>"sg"</code></small>
  136. * The value of the option to use the Auth server in Asia Pacific (APAC).
  137. * @param {String} US1 <small>Value <code>"us2"</code></small>
  138. * The value of the option to use the Auth server in United States (US).
  139. * @deprecated
  140. * @type JSON
  141. * @readOnly
  142. * @for Skylink
  143. * @since 0.5.0
  144. */
  145. Skylink.prototype.REGIONAL_SERVER = {
  146. APAC1: 'sg',
  147. US1: 'us2'
  148. };
  149.  
  150. /**
  151. * Stores the flag if HTTPS connections should be enforced when connecting to
  152. * the API or Signaling server if App is accessing from HTTP domain.
  153. * HTTPS connections are enforced if App is accessing from HTTPS domains.
  154. * @attribute _forceSSL
  155. * @type Boolean
  156. * @default false
  157. * @private
  158. * @for Skylink
  159. * @since 0.5.4
  160. */
  161. Skylink.prototype._forceSSL = false;
  162.  
  163. /**
  164. * Stores the flag if TURNS connections should be enforced when connecting to
  165. * the TURN server if App is accessing from HTTP domain.
  166. * TURNS connections are enforced if App is accessing from HTTPS domains.
  167. * @attribute _forceTURNSSL
  168. * @type Boolean
  169. * @default false
  170. * @private
  171. * @for Skylink
  172. * @since 0.6.1
  173. */
  174. Skylink.prototype._forceTURNSSL = false;
  175.  
  176. /**
  177. * Stores the flag if TURN connections should be enforced when connecting to Peers.
  178. * This filters all non "relay" ICE candidates to enforce connections via the TURN server.
  179. * @attribute _forceTURN
  180. * @type Boolean
  181. * @default false
  182. * @private
  183. * @for Skylink
  184. * @since 0.6.1
  185. */
  186. Skylink.prototype._forceTURN = false;
  187.  
  188. /**
  189. * Stores the construct API REST path to obtain Room credentials.
  190. * @attribute _path
  191. * @type String
  192. * @private
  193. * @for Skylink
  194. * @since 0.1.0
  195. */
  196. Skylink.prototype._path = null;
  197.  
  198. /**
  199. * Stores the server region for the Signaling server to use.
  200. * This is already deprecated an no longer useful. To discuss and remove.
  201. * @attribute _serverRegion
  202. * @type String
  203. * @private
  204. * @for Skylink
  205. * @since 0.5.0
  206. */
  207. Skylink.prototype._serverRegion = null;
  208.  
  209. /**
  210. * Stores the API server url.
  211. * @attribute _roomServer
  212. * @type String
  213. * @private
  214. * @for Skylink
  215. * @since 0.5.2
  216. */
  217. Skylink.prototype._roomServer = '//api.temasys.com.sg';
  218.  
  219. /**
  220. * Stores the App Key configured in <code>init()</code>.
  221. * @attribute _appKey
  222. * @type String
  223. * @private
  224. * @for Skylink
  225. * @since 0.3.0
  226. */
  227. Skylink.prototype._appKey = null;
  228.  
  229. /**
  230. * Stores the default Room name to connect to when <code>joinRoom()</code> does not provide a Room name.
  231. * @attribute _defaultRoom
  232. * @type String
  233. * @private
  234. * @for Skylink
  235. * @since 0.3.0
  236. */
  237. Skylink.prototype._defaultRoom = null;
  238.  
  239. /**
  240. * Stores the <code>init()</code> credentials starting DateTime stamp in ISO 8601.
  241. * @attribute _roomStart
  242. * @type String
  243. * @private
  244. * @for Skylink
  245. * @since 0.3.0
  246. */
  247. Skylink.prototype._roomStart = null;
  248.  
  249. /**
  250. * Stores the <code>init()</code> credentials duration counted in hours.
  251. * @attribute _roomDuration
  252. * @type Number
  253. * @private
  254. * @for Skylink
  255. * @since 0.3.0
  256. */
  257. Skylink.prototype._roomDuration = null;
  258.  
  259. /**
  260. * Stores the <code>init()</code> generated credentials string.
  261. * @attribute _roomCredentials
  262. * @type String
  263. * @private
  264. * @for Skylink
  265. * @since 0.3.0
  266. */
  267. Skylink.prototype._roomCredentials = null;
  268.  
  269. /**
  270. * Stores the current <code>init()</code> readyState.
  271. * @attribute _readyState
  272. * @type Number
  273. * @private
  274. * @for Skylink
  275. * @since 0.1.0
  276. */
  277. Skylink.prototype._readyState = 0;
  278.  
  279. /**
  280. * Stores the "cid" used for <code>joinRoom()</code>.
  281. * @attribute _key
  282. * @type String
  283. * @private
  284. * @for Skylink
  285. * @since 0.1.0
  286. */
  287. Skylink.prototype._key = null;
  288.  
  289. /**
  290. * Stores the "apiOwner" used for <code>joinRoom()</code>.
  291. * @attribute _appKeyOwner
  292. * @type String
  293. * @private
  294. * @for Skylink
  295. * @since 0.5.2
  296. */
  297. Skylink.prototype._appKeyOwner = null;
  298.  
  299. /**
  300. * Stores the Room credentials information for <code>joinRoom()</code>.
  301. * @attribute _room
  302. * @param {String} id The "rid" for <code>joinRoom()</code>.
  303. * @param {String} token The "roomCred" for <code>joinRoom()</code>.
  304. * @param {String} startDateTime The "start" for <code>joinRoom()</code>.
  305. * @param {String} duration The "len" for <code>joinRoom()</code>.
  306. * @param {String} connection The RTCPeerConnection constraints and configuration. This is not used in the SDK
  307. * except for the "mediaConstraints" property that sets the default <code>getUserMedia()</code> settings.
  308. * @type JSON
  309. * @private
  310. * @for Skylink
  311. * @since 0.5.2
  312. */
  313. Skylink.prototype._room = null;
  314.  
  315. /**
  316. * Function that authenticates and initialises App Key used for Room connections.
  317. * @method init
  318. * @param {JSON|String} options The configuration options.
  319. * - When provided as a string, it's configured as <code>options.appKey</code>.
  320. * @param {String} options.appKey The App Key.
  321. * <small>By default, <code>init()</code> uses [HTTP CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)
  322. * authentication. For credentials based authentication, see the <code>options.credentials</code> configuration
  323. * below. You can know more about the <a href="http://support.temasys.com.sg/support/solutions/articles/
  324. * 12000002712-authenticating-your-application-key-to-start-a-connection">in the authentication methods article here</a>
  325. * for more details on the various authentication methods.</small>
  326. * <small>If you are using the Persistent Room feature for scheduled meetings, you will require to
  327. * use the credential based authentication. See the <a href="http://support.temasys.com.sg/support
  328. * /solutions/articles/12000002811-using-the-persistent-room-feature-to-configure-meetings">Persistent Room article here
  329. * </a> for more information.</small>
  330. * @param {String} [options.defaultRoom] The default Room to connect to when no <code>room</code> parameter
  331. * is provided in <a href="#method_joinRoom"><code>joinRoom()</code> method</a>.
  332. * - When not provided, its value is <code>options.appKey</code>.
  333. * <small>Note that switching Rooms is not available when using <code>options.credentials</code> based authentication.
  334. * The Room that User will be connected to is the <code>defaultRoom</code> provided.</small>
  335. * @param {String} [options.roomServer] The Auth server.
  336. * <small>Note that this is a debugging feature and is only used when instructed for debugging purposes.</small>
  337. * @param {String} [options.region] <blockquote class="info"><b>Deprecation Warning!</b>
  338. * This option has been deprecated.<br>Automatic nearest regional server has been implemented
  339. * on the platform.</blockquote>
  340. * The Auth server in the various regions to connect to for better connectivity.
  341. * [Rel: Skylink.REGIONAL_SERVER]
  342. * @param {Boolean} [options.enableIceTrickle=true] The flag if Peer connections should
  343. * trickle ICE for faster connectivity.
  344. * @param {Boolean} [options.enableDataChannel=true] The flag if Datachannel connections should be enabled.
  345. * <small>This is required to be enabled for <a href="#method_sendBlobData"><code>sendBlobData()</code> method</a>,
  346. * <a href="#method_sendURLData"><code>sendURLData()</code> method</a> and
  347. * <a href="#method_sendP2PMessage"><code>sendP2PMessage()</code> method</a>.</small>
  348. * @param {Boolean} [options.enableTURNServer=true] The flag if TURN ICE servers should
  349. * be used when constructing Peer connections to allow TURN connections when required and enabled for the App Key.
  350. * @param {Boolean} [options.enableSTUNServer=true] The flag if STUN ICE servers should
  351. * be used when constructing Peer connections to allow TURN connections when required.
  352. * @param {Boolean} [options.forceTURN=false] The flag if Peer connections should enforce
  353. * connections over the TURN server.
  354. * <small>This sets <code>options.enableTURNServer</code> value to <code>true</code> and
  355. * <code>options.enableSTUNServer</code> value to <code>false</code>.</small>
  356. * <small>During Peer connections, it filters out non <code>"relay"</code> ICE candidates to
  357. * ensure that TURN connections is enforced.</small>
  358. * @param {Boolean} [options.usePublicSTUN=true] The flag if publicly available STUN ICE servers should
  359. * be used if <code>options.enableSTUNServer</code> is enabled.
  360. * @param {Boolean} [options.TURNServerTransport] <blockquote class="info">
  361. * Note that configuring the protocol may not necessarily result in the desired network transports protocol
  362. * used in the actual TURN network traffic as it depends which protocol the browser selects and connects with.
  363. * This simply configures the TURN ICE server urls <code?transport=(protocol)</code> query option when constructing
  364. * the Peer connection. When all protocols are selected, the ICE servers urls are duplicated with all protocols.
  365. * </blockquote> The option to configure the <code>?transport=</code>
  366. * query parameter in TURN ICE servers when constructing a Peer connections.
  367. * - When not provided, its value is <code>ANY</code>.
  368. * [Rel: Skylink.TURN_TRANSPORT]
  369. * @param {JSON} [options.credentials] The credentials used for authenticating App Key with
  370. * credentials to retrieve the Room session token used for connection in <a href="#method_joinRoom">
  371. * <code>joinRoom()</code> method</a>.
  372. * <small>Note that switching of Rooms is not allowed when using credentials based authentication, unless
  373. * <code>init()</code> is invoked again with a different set of credentials followed by invoking
  374. * the <a href="#method_joinRoom"><code>joinRoom()</code> method</a>.</small>
  375. * @param {String} options.credentials.startDateTime The credentials User session in Room starting DateTime
  376. * in <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601 format</a>.
  377. * @param {Number} options.credentials.duration The credentials User session in Room duration in hours.
  378. * @param {String} options.credentials.credentials The generated credentials used to authenticate
  379. * the provided App Key with its <code>"secret"</code> property.
  380. * <blockquote class="details"><h5>To generate the credentials:</h5><ol>
  381. * <li>Concatenate a string that consists of the Room name you provide in the <code>options.defaultRoom</code>,
  382. * the <code>options.credentials.duration</code> and the <code>options.credentials.startDateTime</code>.
  383. * <small>Example: <code>var concatStr = defaultRoom + "_" + duration + "_" + startDateTime;</code></small></li>
  384. * <li>Hash the concatenated string with the App Key <code>"secret"</code> property using
  385. * <a href="https://en.wikipedia.org/wiki/SHA-1">SHA-1</a>.
  386. * <small>Example: <code>var hash = CryptoJS.HmacSHA1(concatStr, appKeySecret);</code></small>
  387. * <small>See the <a href="https://code.google.com/p/crypto-js/#HMAC"><code>CryptoJS.HmacSHA1</code> library</a>.</small></li>
  388. * <li>Encode the hashed string using <a href="https://en.wikipedia.org/wiki/Base64">base64</a>
  389. * <small>Example: <code>var b64Str = hash.toString(CryptoJS.enc.Base64);</code></small>
  390. * <small>See the <a href="https://code.google.com/p/crypto-js/#The_Cipher_Output">CryptoJS.enc.Base64</a> library</a>.</small></li>
  391. * <li>Encode the base64 encoded string to replace special characters using UTF-8 encoding.
  392. * <small>Example: <code>var credentials = encodeURIComponent(base64String);</code></small>
  393. * <small>See <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
  394. * Global_Objects/encodeURIComponent">encodeURIComponent() API</a>.</small></li></ol></blockquote>
  395. * @param {Boolean} [options.audioFallback=false] The flag if <a href="#method_getUserMedia">
  396. * <code>getUserMedia()</code> method</a> should fallback to retrieve only audio Stream when
  397. * retrieving audio and video Stream fails.
  398. * @param {Boolean} [options.forceSSL=false] The flag if HTTPS connections should be enforced
  399. * during request to Auth server and socket connections to Signaling server
  400. * when accessing <code>window.location.protocol</code> value is <code>"http:"</code>.
  401. * <small>By default, <code>"https:"</code> protocol connections uses HTTPS connections.</small>
  402. * @param {String} [options.audioCodec] <blockquote class="info">
  403. * Note that if the audio codec is not supported, the SDK will not configure the local <code>"offer"</code> or
  404. * <code>"answer"</code> session description to prefer the codec.</blockquote>
  405. * The option to configure the preferred audio codec
  406. * to use to encode sending audio data when available for Peer connection.
  407. * - When not provided, its value is <code>AUTO</code>.
  408. * [Rel: Skylink.AUDIO_CODEC]
  409. * @param {String} [options.videoCodec] <blockquote class="info">
  410. * Note that if the video codec is not supported, the SDK will not configure the local <code>"offer"</code> or
  411. * <code>"answer"</code> session description to prefer the codec.</blockquote>
  412. * The option to configure the preferred video codec
  413. * to use to encode sending video data when available for Peer connection.
  414. * - When not provided, its value is <code>AUTO</code>.
  415. * [Rel: Skylink.VIDEO_CODEC]
  416. * @param {Number} [options.socketTimeout=20000] The timeout for each attempts for socket connection
  417. * with the Signaling server to indicate that connection has timed out and has failed to establish.
  418. * <small>Note that the mininum timeout value is <code>5000</code>. If less, this value will be <code>5000</code>.</small>
  419. * @param {Boolean} [options.forceTURNSSL=false] <blockquote class="info">
  420. * Note that currently Firefox does not support the TURNS protocol, and that if TURNS is required,
  421. * TURN ICE servers using port <code>443</code> will be used instead.</blockquote>
  422. * The flag if TURNS protocol should be used when <code>options.enableTURNServer</code> is enabled.
  423. * <small>By default, <code>"https:"</code> protocol connections uses TURNS protocol.</small>
  424. * @param {Function} [callback] The callback function fired when request has completed.
  425. * <small>Function parameters signature is <code>function (error, success)</code></small>
  426. * <small>Function request completion is determined by the <a href="#event_readyStateChange">
  427. * <code>readyStateChange</code> event</a> <code>state</code> parameter payload value
  428. * as <code>COMPLETED</code> for request success.</small>
  429. * [Rel: Skylink.READY_STATE_CHANGE]
  430. * @param {JSON|String} callback.error The error result in request.
  431. * - When defined as string, it's the error when required App Key is not provided.
  432. * <small>Defined as <code>null</code> when there are no errors in request</small>
  433. * @param {Number} callback.error.errorCode The <a href="#event_readyStateChange"><code>readyStateChange</code>
  434. * event</a> <code>error.errorCode</code> parameter payload value.
  435. * [Rel: Skylink.READY_STATE_CHANGE_ERROR]
  436. * @param {Object} callback.error.error The <a href="#event_readyStateChange"><code>readyStateChange</code>
  437. * event</a> <code>error.content</code> parameter payload value.
  438. * @param {Number} callback.error.status The <a href="#event_readyStateChange"><code>readyStateChange</code>
  439. * event</a> <code>error.status</code> parameter payload value.
  440. * @param {JSON} callback.success The success result in request.
  441. * <small>Defined as <code>null</code> when there are errors in request</small>
  442. * @param {String} callback.success.serverUrl The constructed REST URL requested to Auth server.
  443. * @param {String} callback.success.readyState The current ready state.
  444. * [Rel: Skylink.READY_STATE_CHANGE]
  445. * @param {String} callback.success.selectedRoom The Room based on the current Room session token retrieved for.
  446. * @param {String} callback.success.appKey The configured value of the <code>options.appKey</code>.
  447. * @param {String} callback.success.defaultRoom The configured value of the <code>options.defaultRoom</code>.
  448. * @param {String} callback.success.roomServer The configured value of the <code>options.roomServer</code>.
  449. * @param {Boolean} callback.success.enableIceTrickle The configured value of the <code>options.enableIceTrickle</code>.
  450. * @param {Boolean} callback.success.enableDataChannel The configured value of the <code>options.enableDataChannel</code>.
  451. * @param {Boolean} callback.success.enableTURNServer The configured value of the <code>options.enableTURNServer</code>.
  452. * @param {Boolean} callback.success.enableSTUNServer The configured value of the <code>options.enableSTUNServer</code>.
  453. * @param {Boolean} callback.success.TURNTransport The configured value of the <code>options.TURNServerTransport</code>.
  454. * @param {String} callback.success.serverRegion The configured value of the <code>options.region</code>.
  455. * @param {Boolean} callback.success.audioFallback The configured value of the <code>options.audioFallback</code>.
  456. * @param {Boolean} callback.success.forceSSL The configured value of the <code>options.forceSSL</code>.
  457. * @param {String} callback.success.audioCodec The configured value of the <code>options.audioCodec</code>.
  458. * @param {String} callback.success.videoCodec The configured value of the <code>options.videoCodec</code>.
  459. * @param {Number} callback.success.socketTimeout The configured value of the <code>options.socketTimeout</code>.
  460. * @param {Boolean} callback.success.forceTURNSSL The configured value of the <code>options.forceTURNSSL</code>.
  461. * @param {Boolean} callback.success.forceTURN The configured value of the <code>options.forceTURN</code>.
  462. * @param {Boolean} callback.success.usePublicSTUN The configured value of the <code>options.usePublicSTUN</code>.
  463. * @example
  464. * // Example 1: Using CORS authentication and connection to default Room
  465. * skylinkDemo(appKey, function (error, success) {
  466. * if (error) return;
  467. * skylinkDemo.joinRoom(); // Goes to default Room
  468. * });
  469. *
  470. * // Example 2: Using CORS authentication and connection to a different Room
  471. * skylinkDemo(appKey, function (error, success) {
  472. * skylinkDemo.joinRoom("testxx"); // Goes to "testxx" Room
  473. * });
  474. *
  475. * // Example 3: Using credentials authentication and connection to only default Room
  476. * var defaultRoom = "test",
  477. * startDateTime = (new Date()).toISOString(),
  478. * duration = 1, // Allows only User session to stay for 1 hour
  479. * appKeySecret = "xxxxxxx",
  480. * hash = CryptoJS.HmacSHA1(defaultRoom + "_" + duration + "_" + startDateTime, appKeySecret);
  481. * credentials = encodeURIComponent(hash.toString(CryptoJS.enc.Base64));
  482. *
  483. * skylinkDemo({
  484. * defaultRoom: defaultRoom,
  485. * appKey: appKey,
  486. * credentials: {
  487. * duration: duration,
  488. * startDateTime: startDateTime,
  489. * credentials: credentials
  490. * }
  491. * }, function (error, success) {
  492. * if (error) return;
  493. * skylinkDemo.joinRoom(); // Goes to default Room (switching to different Room is not allowed for credentials authentication)
  494. * });
  495. * @trigger <ol class="desc-seq">
  496. * <li>If parameter <code>options</code> is not provided: <ol><li><b>ABORT</b> and return error.</li></ol></li>
  497. * <li>Checks if dependecies and browser APIs are available. <ol><li>If AdapterJS is not loaded: <ol>
  498. * <li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a> triggers
  499. * parameter payload <code>state</code> as <code>ERROR</code> and <code>error.errorCode</code> as
  500. * <code>ADAPTER_NO_LOADED</code>.</li><li><b>ABORT</b> and return error.</li></ol></li>
  501. * <li>If socket.io-client is not loaded: <ol><li><a href="#event_readyStateChange">
  502. * <code>readyStateChange</code> event</a> triggers parameter payload <code>state</code>
  503. * as <code>ERROR</code> and <code>error.errorCode</code> as <code>NO_SOCKET_IO</code>.</li>
  504. * <li><b>ABORT</b> and return error. </li></ol></li>
  505. * <li>If XMLHttpRequest API is not available: <ol><li><a href="#event_readyStateChange">
  506. * <code>readyStateChange</code> event</a> triggers parameter payload <code>state</code>
  507. * as <code>ERROR</code> and <code>error.errorCode</code> as <code>NO_XMLHTTPREQUEST_SUPPORT</code>.</li>
  508. * <li><b>ABORT</b> and return error.</li></ol></li><li>If WebRTC is not supported by device: <ol>
  509. * <li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a> triggers parameter
  510. * payload <code>state</code> as <code>ERROR</code> and <code>error.errorCode</code> as
  511. * <code>NO_WEBRTC_SUPPORT</code>.</li><li><b>ABORT</b> and return error.</li></ol></li></ol></li>
  512. * <li>Retrieves Room session token from Auth server. <ol>
  513. * <li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a> triggers
  514. * parameter payload <code>state</code> as <code>LOADING</code>.</li>
  515. * <li>If retrieval was successful: <ol><li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a>
  516. * triggers parameter payload <code>state</code> as <code>COMPLETED</code>.</li></ol></li><li>Else: <ol>
  517. * <li><a href="#event_readyStateChange"><code>readyStateChange</code> event</a> triggers parameter
  518. * payload <code>state</code> as <code>ERROR</code>.</li><li><b>ABORT</b> and return error.</li></ol></li></ol></li></ol>
  519. * @for Skylink
  520. * @since 0.5.5
  521. */
  522. Skylink.prototype.init = function(options, callback) {
  523. var self = this;
  524.  
  525. if (typeof options === 'function'){
  526. callback = options;
  527. options = undefined;
  528. }
  529.  
  530. if (!options) {
  531. var error = 'No API key provided';
  532. log.error(error);
  533. if (typeof callback === 'function'){
  534. callback(error,null);
  535. }
  536. return;
  537. }
  538.  
  539. var appKey, room, defaultRoom, region;
  540. var startDateTime, duration, credentials;
  541. var roomServer = self._roomServer;
  542. // NOTE: Should we get all the default values from the variables
  543. // rather than setting it?
  544. var enableIceTrickle = true;
  545. var enableDataChannel = true;
  546. var enableSTUNServer = true;
  547. var enableTURNServer = true;
  548. var TURNTransport = self.TURN_TRANSPORT.ANY;
  549. var audioFallback = false;
  550. var forceSSL = false;
  551. var socketTimeout = 0;
  552. var forceTURNSSL = false;
  553. var audioCodec = self.AUDIO_CODEC.AUTO;
  554. var videoCodec = self.VIDEO_CODEC.AUTO;
  555. var forceTURN = false;
  556. var usePublicSTUN = true;
  557.  
  558. log.log('Provided init options:', options);
  559.  
  560. if (typeof options === 'string') {
  561. // set all the default api key, default room and room
  562. appKey = options;
  563. defaultRoom = appKey;
  564. room = appKey;
  565. } else {
  566. // set the api key
  567. appKey = options.appKey || options.apiKey;
  568. // set the room server
  569. roomServer = (typeof options.roomServer === 'string') ?
  570. options.roomServer : roomServer;
  571. // check room server if it ends with /. Remove the extra /
  572. roomServer = (roomServer.lastIndexOf('/') ===
  573. (roomServer.length - 1)) ? roomServer.substring(0,
  574. roomServer.length - 1) : roomServer;
  575. // set the region
  576. region = (typeof options.region === 'string') ?
  577. options.region : region;
  578. // set the default room
  579. defaultRoom = (typeof options.defaultRoom === 'string') ?
  580. options.defaultRoom : appKey;
  581. // set the selected room
  582. room = defaultRoom;
  583. // set ice trickle option
  584. enableIceTrickle = (typeof options.enableIceTrickle === 'boolean') ?
  585. options.enableIceTrickle : enableIceTrickle;
  586. // set data channel option
  587. enableDataChannel = (typeof options.enableDataChannel === 'boolean') ?
  588. options.enableDataChannel : enableDataChannel;
  589. // set stun server option
  590. enableSTUNServer = (typeof options.enableSTUNServer === 'boolean') ?
  591. options.enableSTUNServer : enableSTUNServer;
  592. // set turn server option
  593. enableTURNServer = (typeof options.enableTURNServer === 'boolean') ?
  594. options.enableTURNServer : enableTURNServer;
  595. // set the force ssl always option
  596. forceSSL = (typeof options.forceSSL === 'boolean') ?
  597. options.forceSSL : forceSSL;
  598. // set the socket timeout option
  599. socketTimeout = (typeof options.socketTimeout === 'number') ?
  600. options.socketTimeout : socketTimeout;
  601. // set the socket timeout option to be above 5000
  602. socketTimeout = (socketTimeout < 5000) ? 5000 : socketTimeout;
  603. // set the force turn ssl always option
  604. forceTURNSSL = (typeof options.forceTURNSSL === 'boolean') ?
  605. options.forceTURNSSL : forceTURNSSL;
  606. // set the preferred audio codec
  607. audioCodec = typeof options.audioCodec === 'string' ?
  608. options.audioCodec : audioCodec;
  609. // set the preferred video codec
  610. videoCodec = typeof options.videoCodec === 'string' ?
  611. options.videoCodec : videoCodec;
  612. // set the force turn server option
  613. forceTURN = (typeof options.forceTURN === 'boolean') ?
  614. options.forceTURN : forceTURN;
  615. // set the use public stun option
  616. usePublicSTUN = (typeof options.usePublicSTUN === 'boolean') ?
  617. options.usePublicSTUN : usePublicSTUN;
  618.  
  619. // set turn transport option
  620. if (typeof options.TURNServerTransport === 'string') {
  621. // loop out for every transport option
  622. for (var type in self.TURN_TRANSPORT) {
  623. if (self.TURN_TRANSPORT.hasOwnProperty(type)) {
  624. // do a check if the transport option is valid
  625. if (self.TURN_TRANSPORT[type] === options.TURNServerTransport) {
  626. TURNTransport = options.TURNServerTransport;
  627. break;
  628. }
  629. }
  630. }
  631. }
  632. // set audio fallback option
  633. audioFallback = options.audioFallback || audioFallback;
  634. // Custom default meeting timing and duration
  635. // Fallback to default if no duration or startDateTime provided
  636. if (options.credentials &&
  637. typeof options.credentials.credentials === 'string' &&
  638. typeof options.credentials.duration === 'number' &&
  639. typeof options.credentials.startDateTime === 'string') {
  640. // set start data time
  641. startDateTime = options.credentials.startDateTime;
  642. // set the duration
  643. duration = options.credentials.duration;
  644. // set the credentials
  645. credentials = options.credentials.credentials;
  646. }
  647.  
  648. // if force turn option is set to on
  649. if (forceTURN === true) {
  650. enableTURNServer = true;
  651. enableSTUNServer = false;
  652. }
  653. }
  654. // api key path options
  655. self._appKey = appKey;
  656. self._roomServer = roomServer;
  657. self._defaultRoom = defaultRoom;
  658. self._selectedRoom = room;
  659. self._serverRegion = region || null;
  660. self._path = roomServer + '/api/' + appKey + '/' + room;
  661. // set credentials if there is
  662. if (credentials && startDateTime && duration) {
  663. self._roomStart = startDateTime;
  664. self._roomDuration = duration;
  665. self._roomCredentials = credentials;
  666. self._path += (credentials) ? ('/' + startDateTime + '/' +
  667. duration + '?&cred=' + credentials) : '';
  668. }
  669.  
  670. self._path += ((credentials) ? '&' : '?') + 'rand=' + (new Date()).toISOString();
  671.  
  672. // check if there is a other query parameters or not
  673. if (region) {
  674. self._path += '&rg=' + region;
  675. }
  676. // skylink functionality options
  677. self._enableIceTrickle = enableIceTrickle;
  678. self._enableDataChannel = enableDataChannel;
  679. self._enableSTUN = enableSTUNServer;
  680. self._enableTURN = enableTURNServer;
  681. self._TURNTransport = TURNTransport;
  682. self._audioFallback = audioFallback;
  683. self._forceSSL = forceSSL;
  684. self._socketTimeout = socketTimeout;
  685. self._forceTURNSSL = forceTURNSSL;
  686. self._selectedAudioCodec = audioCodec;
  687. self._selectedVideoCodec = videoCodec;
  688. self._forceTURN = forceTURN;
  689. self._usePublicSTUN = usePublicSTUN;
  690.  
  691. log.log('Init configuration:', {
  692. serverUrl: self._path,
  693. readyState: self._readyState,
  694. appKey: self._appKey,
  695. roomServer: self._roomServer,
  696. defaultRoom: self._defaultRoom,
  697. selectedRoom: self._selectedRoom,
  698. serverRegion: self._serverRegion,
  699. enableDataChannel: self._enableDataChannel,
  700. enableIceTrickle: self._enableIceTrickle,
  701. enableTURNServer: self._enableTURN,
  702. enableSTUNServer: self._enableSTUN,
  703. TURNTransport: self._TURNTransport,
  704. audioFallback: self._audioFallback,
  705. forceSSL: self._forceSSL,
  706. socketTimeout: self._socketTimeout,
  707. forceTURNSSL: self._forceTURNSSL,
  708. audioCodec: self._selectedAudioCodec,
  709. videoCodec: self._selectedVideoCodec,
  710. forceTURN: self._forceTURN,
  711. usePublicSTUN: self._usePublicSTUN
  712. });
  713. // trigger the readystate
  714. self._readyState = 0;
  715. self._trigger('readyStateChange', self.READY_STATE_CHANGE.INIT, null, self._selectedRoom);
  716.  
  717. if (typeof callback === 'function'){
  718. var hasTriggered = false;
  719.  
  720. var readyStateChangeFn = function (readyState, error) {
  721. if (!hasTriggered) {
  722. if (readyState === self.READY_STATE_CHANGE.COMPLETED) {
  723. log.log([null, 'Socket', null, 'Firing callback. ' +
  724. 'Ready state change has met provided state ->'], readyState);
  725. hasTriggered = true;
  726. self.off('readyStateChange', readyStateChangeFn);
  727. callback(null,{
  728. serverUrl: self._path,
  729. readyState: self._readyState,
  730. appKey: self._appKey,
  731. roomServer: self._roomServer,
  732. defaultRoom: self._defaultRoom,
  733. selectedRoom: self._selectedRoom,
  734. serverRegion: self._serverRegion,
  735. enableDataChannel: self._enableDataChannel,
  736. enableIceTrickle: self._enableIceTrickle,
  737. enableTURNServer: self._enableTURN,
  738. enableSTUNServer: self._enableSTUN,
  739. TURNTransport: self._TURNTransport,
  740. audioFallback: self._audioFallback,
  741. forceSSL: self._forceSSL,
  742. socketTimeout: self._socketTimeout,
  743. forceTURNSSL: self._forceTURNSSL,
  744. audioCodec: self._selectedAudioCodec,
  745. videoCodec: self._selectedVideoCodec,
  746. forceTURN: self._forceTURN,
  747. usePublicSTUN: self._usePublicSTUN
  748. });
  749. } else if (readyState === self.READY_STATE_CHANGE.ERROR) {
  750. log.log([null, 'Socket', null, 'Firing callback. ' +
  751. 'Ready state change has met provided state ->'], readyState);
  752. log.debug([null, 'Socket', null, 'Ready state met failure'], error);
  753. hasTriggered = true;
  754. self.off('readyStateChange', readyStateChangeFn);
  755. callback({
  756. error: new Error(error),
  757. errorCode: error.errorCode,
  758. status: error.status
  759. },null);
  760. }
  761. }
  762. };
  763.  
  764. self.on('readyStateChange', readyStateChangeFn);
  765. }
  766.  
  767. self._loadInfo();
  768. };
  769.  
  770. /**
  771. * Starts retrieving Room credentials information from API server.
  772. * @method _requestServerInfo
  773. * @private
  774. * @for Skylink
  775. * @since 0.5.2
  776. */
  777. Skylink.prototype._requestServerInfo = function(method, url, callback, params) {
  778. var self = this;
  779. // XDomainRequest is supported in IE8 - 9
  780. var useXDomainRequest = typeof window.XDomainRequest === 'function' ||
  781. typeof window.XDomainRequest === 'object';
  782.  
  783. self._socketUseXDR = useXDomainRequest;
  784. var xhr;
  785.  
  786. // set force SSL option
  787. url = (self._forceSSL) ? 'https:' + url : url;
  788.  
  789. if (useXDomainRequest) {
  790. log.debug([null, 'XMLHttpRequest', method, 'Using XDomainRequest. ' +
  791. 'XMLHttpRequest is now XDomainRequest'], {
  792. agent: window.webrtcDetectedBrowser,
  793. version: window.webrtcDetectedVersion
  794. });
  795. xhr = new XDomainRequest();
  796. xhr.setContentType = function (contentType) {
  797. xhr.contentType = contentType;
  798. };
  799. } else {
  800. log.debug([null, 'XMLHttpRequest', method, 'Using XMLHttpRequest'], {
  801. agent: window.webrtcDetectedBrowser,
  802. version: window.webrtcDetectedVersion
  803. });
  804. xhr = new window.XMLHttpRequest();
  805. xhr.setContentType = function (contentType) {
  806. xhr.setRequestHeader('Content-type', contentType);
  807. };
  808. }
  809.  
  810. xhr.onload = function () {
  811. var response = xhr.responseText || xhr.response;
  812. var status = xhr.status || 200;
  813. log.debug([null, 'XMLHttpRequest', method, 'Received sessions parameters'],
  814. JSON.parse(response || '{}'));
  815. callback(status, JSON.parse(response || '{}'));
  816. };
  817.  
  818. xhr.onerror = function (error) {
  819. log.error([null, 'XMLHttpRequest', method, 'Failed retrieving information:'],
  820. { status: xhr.status });
  821. self._readyState = -1;
  822. self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
  823. status: xhr.status || null,
  824. content: 'Network error occurred. (Status: ' + xhr.status + ')',
  825. errorCode: self.READY_STATE_CHANGE_ERROR.XML_HTTP_REQUEST_ERROR
  826. }, self._selectedRoom);
  827. };
  828.  
  829. xhr.onprogress = function () {
  830. log.debug([null, 'XMLHttpRequest', method,
  831. 'Retrieving information and config from webserver. Url:'], url);
  832. log.debug([null, 'XMLHttpRequest', method, 'Provided parameters:'], params);
  833. };
  834.  
  835. xhr.open(method, url, true);
  836. if (params) {
  837. xhr.setContentType('application/json;charset=UTF-8');
  838. xhr.send(JSON.stringify(params));
  839. } else {
  840. xhr.send();
  841. }
  842. };
  843.  
  844. /**
  845. * Parses the Room credentials information retrieved from API server.
  846. * @method _parseInfo
  847. * @private
  848. * @for Skylink
  849. * @since 0.5.2
  850. */
  851. Skylink.prototype._parseInfo = function(info) {
  852. log.log('Parsing parameter from server', info);
  853. if (!info.pc_constraints && !info.offer_constraints) {
  854. this._trigger('readyStateChange', this.READY_STATE_CHANGE.ERROR, {
  855. status: 200,
  856. content: info.info,
  857. errorCode: info.error
  858. }, self._selectedRoom);
  859. return;
  860. }
  861.  
  862. log.debug('Peer connection constraints:', info.pc_constraints);
  863. log.debug('Offer constraints:', info.offer_constraints);
  864.  
  865. this._key = info.cid;
  866. this._appKeyOwner = info.apiOwner;
  867.  
  868. this._signalingServer = info.ipSigserver;
  869. this._signalingServerPort = null;
  870.  
  871. this._isPrivileged = info.isPrivileged;
  872. this._autoIntroduce = info.autoIntroduce;
  873.  
  874. this._user = {
  875. uid: info.username,
  876. token: info.userCred,
  877. timeStamp: info.timeStamp,
  878. streams: [],
  879. info: {}
  880. };
  881. this._room = {
  882. id: info.room_key,
  883. token: info.roomCred,
  884. startDateTime: info.start,
  885. duration: info.len,
  886. connection: {
  887. peerConstraints: JSON.parse(info.pc_constraints),
  888. peerConfig: null,
  889. offerConstraints: JSON.parse(info.offer_constraints),
  890. sdpConstraints: {
  891. mandatory: {
  892. OfferToReceiveAudio: true,
  893. OfferToReceiveVideo: true
  894. }
  895. },
  896. mediaConstraints: JSON.parse(info.media_constraints)
  897. }
  898. };
  899. //this._parseDefaultMediaStreamSettings(this._room.connection.mediaConstraints);
  900.  
  901. // set the socket ports
  902. this._socketPorts = {
  903. 'http:': info.httpPortList,
  904. 'https:': info.httpsPortList
  905. };
  906.  
  907. // use default bandwidth and media resolution provided by server
  908. //this._streamSettings.bandwidth = info.bandwidth;
  909. //this._streamSettings.video = info.video;
  910. this._readyState = 2;
  911. this._trigger('readyStateChange', this.READY_STATE_CHANGE.COMPLETED, null, this._selectedRoom);
  912. log.info('Parsed parameters from webserver. ' +
  913. 'Ready for web-realtime communication');
  914.  
  915. };
  916.  
  917. /**
  918. * Loads and checks the dependencies if they are loaded correctly.
  919. * @method _loadInfo
  920. * @private
  921. * @for Skylink
  922. * @since 0.5.2
  923. */
  924. Skylink.prototype._loadInfo = function() {
  925. var self = this;
  926.  
  927. // check if adapterjs has been loaded already first or not
  928. var adapter = (function () {
  929. try {
  930. return window.AdapterJS || AdapterJS;
  931. } catch (error) {
  932. return false;
  933. }
  934. })();
  935.  
  936. if (!(!!adapter ? typeof adapter.webRTCReady === 'function' : false)) {
  937. var noAdapterErrorMsg = 'AdapterJS dependency is not loaded or incorrect AdapterJS dependency is used';
  938. self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
  939. status: null,
  940. content: noAdapterErrorMsg,
  941. errorCode: self.READY_STATE_CHANGE_ERROR.ADAPTER_NO_LOADED
  942. }, self._selectedRoom);
  943. return;
  944. }
  945. if (!window.io) {
  946. log.error('Socket.io not loaded. Please load socket.io');
  947. self._readyState = -1;
  948. self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
  949. status: null,
  950. content: 'Socket.io not found',
  951. errorCode: self.READY_STATE_CHANGE_ERROR.NO_SOCKET_IO
  952. }, self._selectedRoom);
  953. return;
  954. }
  955. if (!window.XMLHttpRequest) {
  956. log.error('XMLHttpRequest not supported. Please upgrade your browser');
  957. self._readyState = -1;
  958. self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
  959. status: null,
  960. content: 'XMLHttpRequest not available',
  961. errorCode: self.READY_STATE_CHANGE_ERROR.NO_XMLHTTPREQUEST_SUPPORT
  962. }, self._selectedRoom);
  963. return;
  964. }
  965. if (!self._path) {
  966. log.error('Skylink is not initialised. Please call init() first');
  967. self._readyState = -1;
  968. self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
  969. status: null,
  970. content: 'No API Path is found',
  971. errorCode: self.READY_STATE_CHANGE_ERROR.NO_PATH
  972. }, self._selectedRoom);
  973. return;
  974. }
  975. adapter.webRTCReady(function () {
  976. if (!window.RTCPeerConnection) {
  977. log.error('WebRTC not supported. Please upgrade your browser');
  978. self._readyState = -1;
  979. self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
  980. status: null,
  981. content: 'WebRTC not available',
  982. errorCode: self.READY_STATE_CHANGE_ERROR.NO_WEBRTC_SUPPORT
  983. }, self._selectedRoom);
  984. return;
  985. }
  986. self._readyState = 1;
  987. self._trigger('readyStateChange', self.READY_STATE_CHANGE.LOADING, null, self._selectedRoom);
  988. self._requestServerInfo('GET', self._path, function(status, response) {
  989. if (status !== 200) {
  990. // 403 - Room is locked
  991. // 401 - API Not authorized
  992. // 402 - run out of credits
  993. var errorMessage = 'XMLHttpRequest status not OK\nStatus was: ' + status;
  994. self._readyState = 0;
  995. self._trigger('readyStateChange', self.READY_STATE_CHANGE.ERROR, {
  996. status: status,
  997. content: (response) ? (response.info || errorMessage) : errorMessage,
  998. errorCode: response.error ||
  999. self.READY_STATE_CHANGE_ERROR.INVALID_XMLHTTPREQUEST_STATUS
  1000. }, self._selectedRoom);
  1001. return;
  1002. }
  1003. self._parseInfo(response);
  1004. });
  1005. });
  1006. };
  1007.  
  1008. /**
  1009. * Starts initialising for Room credentials for room name provided in <code>joinRoom()</code> method.
  1010. * @method _initSelectedRoom
  1011. * @private
  1012. * @for Skylink
  1013. * @since 0.5.5
  1014. */
  1015. Skylink.prototype._initSelectedRoom = function(room, callback) {
  1016. var self = this;
  1017. if (typeof room === 'function' || typeof room === 'undefined') {
  1018. log.error('Invalid room provided. Room:', room);
  1019. return;
  1020. }
  1021. var defaultRoom = self._defaultRoom;
  1022. var initOptions = {
  1023. roomServer: self._roomServer,
  1024. defaultRoom: room || defaultRoom,
  1025. appKey: self._appKey,
  1026. region: self._serverRegion,
  1027. enableDataChannel: self._enableDataChannel,
  1028. enableIceTrickle: self._enableIceTrickle
  1029. };
  1030. if (self._roomCredentials) {
  1031. initOptions.credentials = {
  1032. credentials: self._roomCredentials,
  1033. duration: self._roomDuration,
  1034. startDateTime: self._roomStart
  1035. };
  1036. }
  1037. self.init(initOptions, function (error, success) {
  1038. self._defaultRoom = defaultRoom;
  1039. if (error) {
  1040. callback(error);
  1041. } else {
  1042. callback(null);
  1043. }
  1044. });
  1045. };
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.