/** * vtkWeb JavaScript Library. * * This module allow the Web client to connect to a remote vtkWeb session. * The session must already exist and waiting for connections. * * This module registers itself as: 'vtkweb-connect' * * @class vtkWeb.connect * * {@img paraview/ParaViewWeb-simple.png * alt Focus on the communication between the client and the vtkWeb process} */ (function (GLOBAL, $) { // Connections field used to store a map of the active sessions var connections = {}, module = {}; /* * Create a transport object appropriate to the protocol specified * in the given url. */ function getTransportObject(url) { var idx = url.indexOf(':'), protocol = url.substring(0, idx); if (protocol === 'ws' || protocol === 'wss') { return { 'type': 'websocket', 'url': url, }; } else if (protocol === 'http' || protocol === 'https') { return { 'type': 'longpoll', 'url': url, request_timeout: 300000 }; } else { throw "Unknown protocol (" + protocol + ") for url (" + url + "). Unable to create transport object."; } } /** * @class vtkWeb.Session * vtkWeb Session object on which RPC method calls can be made. * * session.call("viewport.image.render", request).then( function (reply) { * // Do something with the reply * }); */ /** * @member vtkWeb.Session * @method call * Returns a future of the RPC call. * @param {String} method * Full path method name. * @param {Object|String|Number} args * Arguments of the RPC call. * * @return {vtkWeb.Future} of the RPC call */ /** * @class vtkWeb.Future * Object on which can be attached a callback. */ /** * @member vtkWeb.Future * @method then * @param {Function} callback * Function to be called once the RPC called is done. The argument of the * function is the response of the RPC method. */ /** * Connect to a running vtkWeb session * * @member vtkWeb.connect * * @param {vtkWeb.Connection} connection * A connection object that should have been generated by the Launcher * part if any. * * connection = { * sessionURL: "http://localhost:8080/ws" * } * * get extended to once the readyCallback get called: * * connection = { * sessionURL: "http://localhost:8080/ws", * session: {vtkWeb.Session} * } * * * @param {Function} readyCallback * Callback function called when a connection that has been extended with * a valid {@link vtkWeb.Session}. * * @param {Function} closeCallback * Callback function called when the session end. * * vtkWeb.connect( * connection, * function(connection) { * // Now that we have a valid session let's add a viewport to * // see the 3D view of our vtkWeb pipeline. * var viewport = vtkWeb.createViewport(connection.session); * viewport.bind(".viewport-3d"); * }, * function(code,reason) { * if (code == ab.CONNECTION_UNSUPPORTED) { * alert("Connection not supported"); * } else { * console.log(reason); * } * } * ); */ function connect(connectionInfo, readyCallback, closeCallback) { var uri = connectionInfo.sessionURL, onReady = readyCallback, onClose = closeCallback, uriList = [].concat(uri), transports = []; if(!connectionInfo.hasOwnProperty("secret")) { connectionInfo.secret = "vtkweb-secret"; // Default value } for (var i = 0; i < uriList.length; i+=1) { var url = uriList[i], transport = null; try { transport = getTransportObject(url); transports.push(transport); } catch (transportCreateError) { console.error(transportCreateError); } } connectionInfo.connection = new autobahn.Connection({ transports: transports, realm: "vtkweb", authmethods: ["wampcra"], authid: "vtkweb", onchallenge: function(session, method, extra) { if (method === "wampcra") { var secretKey = autobahn.auth_cra.derive_key(connectionInfo.secret, "salt123"); return autobahn.auth_cra.sign(secretKey, extra.challenge); } else { throw "don't know how to authenticate using '" + method + "'"; } } }); connectionInfo.connection.onopen = function(session, details) { try { connectionInfo.session = session; connections[connectionInfo.sessionURL] = connectionInfo; if (onReady) { onReady(connectionInfo); } } catch(e) { console.log(e); } } connectionInfo.connection.onclose = function() { delete connections[connectionInfo.sessionURL]; if (onClose) { onClose(arguments[0], arguments[1].reason); } return false; } connectionInfo.connection.open(); } /** * Create a session that uses only http to make calls to the * server-side protocols. * * @member {object} vtkWeb.connect * A json object that only needs a 'sessionURL' string in to know where * to send method requests. * * @param connetionInfo * * @param {Function} readyCallback * Callback function called when a connection that has been extended with * a valid session that can be used to make server-side method calls. * */ function httpConnect(connectionInfo, readyCallback) { connectionInfo.session = { 'call': function(methodName, args) { var dfd = $.Deferred(); $.ajax({ type: 'POST', url: connectionInfo.sessionURL + methodName, dataType: 'json', data: JSON.stringify({ 'args': args }), success: function(result) { dfd.resolve(result); }, error: function(error) { dfd.reject(error); } }); return dfd.promise(); } }; readyCallback(connectionInfo); } /** * Return any existing session for a given connection or Wamp URL * * @member vtkWeb.connect * * @param {String} sessionURL * The sessionURL String. * * @return {vtkWeb.Connection} that contains a {@link vtkWeb.Session} */ function getConnection(sessionURL) { return connections[sessionURL]; } /** * Return all the available connections stored in an Object like follow: * * { * "ws://localhost:8080/proxy?sessionId=2345": connection * } * * {@link vtkWeb.Connection} * * @member vtkWeb.connect */ function getConnections() { return connections; } // ---------------------------------------------------------------------- // Init vtkWeb module if needed // ---------------------------------------------------------------------- if (GLOBAL.hasOwnProperty("vtkWeb")) { module = GLOBAL.vtkWeb || {}; } else { GLOBAL.vtkWeb = module; } // ---------------------------------------------------------------------- // Export methods to the vtkWeb module // ---------------------------------------------------------------------- module.connect = function (connection, ready, close) { connect(connection, ready, close); }; module.getConnection = function (connection) { return getConnection(connection); }; module.getConnections = function () { return getConnections(); }; module.httpConnect = function(connection, readyCallback) { return httpConnect(connection, readyCallback); }; // ---------------------------------------------------------------------- // Local module registration // ---------------------------------------------------------------------- try { // Tests for presence of autobahn, then registers this module if (GLOBAL.autobahn !== undefined) { module.registerModule('vtkweb-connect'); } else { console.error('Module failed to register, autobahn is missing'); } } catch(err) { console.error('Caught exception while registering module: ' + err.message); } }(window, jQuery));