From bf9c4ea444fb8c6deca51121bb3a48a26762dfb5 Mon Sep 17 00:00:00 2001 From: hristoterezov Date: Mon, 28 Mar 2016 16:19:32 -0500 Subject: [PATCH] Implements server side connection establishment --- Makefile | 5 +- app.js | 50 ++++++------ connection.js | 38 ++++++++- .../connection_optimization.html | 0 .../do_external_connect.js | 79 +++++++++++++++++++ index.html | 14 ++-- modules/config/URLProcessor.js | 16 +--- utils.js | 52 ++++++++++++ 8 files changed, 202 insertions(+), 52 deletions(-) create mode 100644 connection_optimization/connection_optimization.html create mode 100644 connection_optimization/do_external_connect.js create mode 100644 utils.js diff --git a/Makefile b/Makefile index 12624e6e09..afd0266328 100644 --- a/Makefile +++ b/Makefile @@ -31,8 +31,9 @@ deploy-appbundle: deploy-lib-jitsi-meet: cp $(LIBJITSIMEET_DIR)/lib-jitsi-meet.min.js \ - $(LIBJITSIMEET_DIR)/lib-jitsi-meet.min.map $(DEPLOY_DIR) - + $(LIBJITSIMEET_DIR)/lib-jitsi-meet.min.map \ + $(LIBJITSIMEET_DIR)/connection_optimization/external_connect.js \ + $(DEPLOY_DIR) deploy-css: (cd css; cat $(CSS_FILES)) | $(CLEANCSS) > css/all.css diff --git a/app.js b/app.js index c64cfeff99..cee8118e88 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,4 @@ -/* global $, JitsiMeetJS, config */ +/* global $, JitsiMeetJS, config, getRoomName */ /* application specific logic */ import "babel-polyfill"; @@ -23,40 +23,34 @@ import API from './modules/API/API'; import UIEvents from './service/UI/UIEvents'; - +/** + * Builds and returns the room name. + */ function buildRoomName () { - let path = window.location.pathname; - let roomName; - - // determinde the room node from the url - // TODO: just the roomnode or the whole bare jid? - if (config.getroomnode && typeof config.getroomnode === 'function') { - // custom function might be responsible for doing the pushstate - roomName = config.getroomnode(path); - } else { - /* fall back to default strategy - * this is making assumptions about how the URL->room mapping happens. - * It currently assumes deployment at root, with a rewrite like the - * following one (for nginx): - location ~ ^/([a-zA-Z0-9]+)$ { - rewrite ^/(.*)$ / break; - } - */ - if (path.length > 1) { - roomName = path.substr(1).toLowerCase(); - } else { - let word = RoomnameGenerator.generateRoomWithoutSeparator(); - roomName = word.toLowerCase(); - window.history.pushState( - 'VideoChat', `Room: ${word}`, window.location.pathname + word - ); - } + let roomName = getRoomName(); + + if(!roomName) { + let word = RoomnameGenerator.generateRoomWithoutSeparator(); + roomName = word.toLowerCase(); + window.history.pushState( + 'VideoChat', `Room: ${word}`, window.location.pathname + word + ); } return roomName; } const APP = { + // Used by do_external_connect.js if we receive the attach data after + // connect was already executed. status property can be "initialized", + // "ready" or "connecting". We are interested in "ready" status only which + // means that connect was executed but we have to wait for the attach data. + // In status "ready" handler property will be set to a function that will + // finish the connect process when the attach data or error is received. + connect: { + status: "initialized", + handler: null + }, UI, settings, conference, diff --git a/connection.js b/connection.js index b6348a7741..6e7dec393a 100644 --- a/connection.js +++ b/connection.js @@ -5,6 +5,39 @@ import LoginDialog from './modules/UI/authentication/LoginDialog'; const ConnectionEvents = JitsiMeetJS.events.connection; const ConnectionErrors = JitsiMeetJS.errors.connection; +/** + * Checks if we have data to use attach instead of connect. If we have the data + * executes attach otherwise check if we have to wait for the data. If we have + * to wait for the attach data we are setting handler to APP.connect.handler + * which is going to be called when the attach data is received otherwise + * executes connect. + * + * @param {string} [id] user id + * @param {string} [password] password + * @param {string} [roomName] the name of the conference. + */ +function checkForAttachParametersAndConnect(id, password, connection) { + console.log("call checkForAttachParametersAndConnect"); + if(window.XMPPAttachInfo){ + APP.connect.status = "connecting"; + if(window.XMPPAttachInfo.status === "error") { + connection.connect({id, password}); + return; + } + + var attachOptions = window.XMPPAttachInfo.data; + if(attachOptions) { + connection.attach(attachOptions); + } else { + connection.connect({id, password}); + } + } else { + APP.connect.status = "ready"; + APP.connect.handler = checkForAttachParametersAndConnect.bind(null, + id, password, connection); + } +} + /** * Try to open connection using provided credentials. * @param {string} [id] @@ -18,7 +51,8 @@ function connect(id, password, roomName) { let connectionConfig = config; connectionConfig.bosh += '?room=' + roomName; - let connection = new JitsiMeetJS.JitsiConnection(null, null, config); + let connection + = new JitsiMeetJS.JitsiConnection(null, config.token, config); return new Promise(function (resolve, reject) { connection.addEventListener( @@ -50,7 +84,7 @@ function connect(id, password, roomName) { reject(err); } - connection.connect({id, password}); + checkForAttachParametersAndConnect(id, password, connection); }); } diff --git a/connection_optimization/connection_optimization.html b/connection_optimization/connection_optimization.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/connection_optimization/do_external_connect.js b/connection_optimization/do_external_connect.js new file mode 100644 index 0000000000..99c277f4fa --- /dev/null +++ b/connection_optimization/do_external_connect.js @@ -0,0 +1,79 @@ +/* global config, getRoomName, getConfigParamsFromUrl */ +/* global createConnectionExternally */ +/** + * Implements extrnal connect using createConnectionExtenally function defined + * in external_connect.js for Jitsi Meet. Parses the room name and token from + * the url and executes createConnectionExtenally. + * + * NOTE: If you are using lib-jitsi-meet without Jitsi Meet you should use this + * file as reference only because the implementation is Jitsi Meet specific. + * + * NOTE: For optimal results this file should be included right after + * exrnal_connect.js. + */ + + + + /** + * Gets the token from the URL. + */ +function buildToken(){ + var params = getConfigParamsFromUrl(); + return params["config.token"] || config.token; +} + +/** + * Executes createConnectionExternally function. + */ +(function () { + // FIXME: Add implementation for changing that config from the url for + // consistency + var url = config.externalConnectUrl; + + /** + * Check if connect from connection.js was executed and executes the handler + * that is going to finish the connect work. + */ + function checkForConnectHandlerAndConnect() { + + if(window.APP && window.APP.connect.status === "ready") { + window.APP.connect.handler(); + } + } + + function error_callback(error){ + console.warn(error); + // Sets that global variable to be used later by connect method in + // connection.js + window.XMPPAttachInfo = { + status: "error" + }; + checkForConnectHandlerAndConnect(); + } + + if(!url || !window.createConnectionExternally) { + error_callback(); + return; + } + var room_name = getRoomName(); + if(!room_name) { + error_callback(); + return; + } + + url += "?room=" + room_name; + + var token = buildToken(); + if(token) + url += "&token=" + token; + + createConnectionExternally(url, function(connectionInfo) { + // Sets that global variable to be used later by connect method in + // connection.js + window.XMPPAttachInfo = { + status: "success", + data: connectionInfo + }; + checkForConnectHandlerAndConnect(); + }, error_callback); +})(); diff --git a/index.html b/index.html index b77017611b..e52d422c14 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,13 @@ + + + + + + + @@ -9,12 +16,7 @@ - - - - - - + diff --git a/modules/config/URLProcessor.js b/modules/config/URLProcessor.js index ceb40b8a0d..8f1021dfef 100644 --- a/modules/config/URLProcessor.js +++ b/modules/config/URLProcessor.js @@ -1,18 +1,6 @@ -/* global $, $iq, config, interfaceConfig */ +/* global $, $iq, config, interfaceConfig, getConfigParamsFromUrl */ var configUtils = require('./Util'); var params = {}; -function getConfigParamsFromUrl() { - if (!location.hash) - return {}; - var hash = location.hash.substr(1); - var result = {}; - hash.split("&").forEach(function (part) { - var item = part.split("="); - result[item[0]] = JSON.parse( - decodeURIComponent(item[1]).replace(/\\&/, "&")); - }); - return result; -} params = getConfigParamsFromUrl(); @@ -62,4 +50,4 @@ var URLProcessor = { } }; -module.exports = URLProcessor; \ No newline at end of file +module.exports = URLProcessor; diff --git a/utils.js b/utils.js new file mode 100644 index 0000000000..ebc11984da --- /dev/null +++ b/utils.js @@ -0,0 +1,52 @@ +/* global config */ + +/** + * Defines some utility methods that are used before the other JS files are + * loaded. + */ + + +/** + * Builds and returns the room name. + */ +function getRoomName () { + var path = window.location.pathname; + var roomName; + + // determinde the room node from the url + // TODO: just the roomnode or the whole bare jid? + if (config.getroomnode && typeof config.getroomnode === 'function') { + // custom function might be responsible for doing the pushstate + roomName = config.getroomnode(path); + } else { + /* fall back to default strategy + * this is making assumptions about how the URL->room mapping happens. + * It currently assumes deployment at root, with a rewrite like the + * following one (for nginx): + location ~ ^/([a-zA-Z0-9]+)$ { + rewrite ^/(.*)$ / break; + } + */ + if (path.length > 1) { + roomName = path.substr(1).toLowerCase(); + } + } + + return roomName; +} + +/** + * Parses the hash parameters from the URL and returns them as a JS object. + */ +function getConfigParamsFromUrl() { + if (!location.hash) + return {}; + var hash = location.hash.substr(1); + var result = {}; + hash.split("&").forEach(function (part) { + var item = part.split("="); + result[item[0]] = JSON.parse( + decodeURIComponent(item[1]).replace(/\\&/, "&")); + }); + return result; +}