mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 21:27:40 +00:00
GUAC-1172: Add Guacamole.Object and handlers for object-related instructions.
This commit is contained in:
@@ -86,6 +86,14 @@ Guacamole.Client = function(tunnel) {
|
|||||||
// No initial streams
|
// No initial streams
|
||||||
var streams = [];
|
var streams = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All current objects. The index of each object is dictated by the
|
||||||
|
* Guacamole server.
|
||||||
|
*
|
||||||
|
* @type Guacamole.Object[]
|
||||||
|
*/
|
||||||
|
var objects = [];
|
||||||
|
|
||||||
// Pool of available stream indices
|
// Pool of available stream indices
|
||||||
var stream_indices = new Guacamole.IntegerPool();
|
var stream_indices = new Guacamole.IntegerPool();
|
||||||
|
|
||||||
@@ -293,6 +301,67 @@ Guacamole.Client = function(tunnel) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new output stream associated with the given object and having
|
||||||
|
* the given mimetype and name. The legality of a mimetype and name is
|
||||||
|
* dictated by the object itself.
|
||||||
|
*
|
||||||
|
* @param {Number} index
|
||||||
|
* The index of the object for which the output stream is being
|
||||||
|
* created.
|
||||||
|
*
|
||||||
|
* @param {String} mimetype
|
||||||
|
* The mimetype of the data which will be sent to the output stream.
|
||||||
|
*
|
||||||
|
* @param {String} name
|
||||||
|
* The defined name of an output stream within the given object.
|
||||||
|
*
|
||||||
|
* @returns {Guacamole.OutputStream}
|
||||||
|
* An output stream which will write blobs to the named output stream
|
||||||
|
* of the given object.
|
||||||
|
*/
|
||||||
|
this.createObjectOutputStream = function(index, mimetype, name) {
|
||||||
|
|
||||||
|
// Allocate index
|
||||||
|
var streamIndex = stream_indices.next();
|
||||||
|
|
||||||
|
// Create new stream
|
||||||
|
tunnel.sendMessage("put", index, streamIndex, mimetype, name);
|
||||||
|
var stream = output_streams[streamIndex] = new Guacamole.OutputStream(guac_client, streamIndex);
|
||||||
|
|
||||||
|
// Override sendEnd() of stream to automatically free index
|
||||||
|
var oldEnd = stream.sendEnd;
|
||||||
|
stream.sendEnd = function() {
|
||||||
|
oldEnd();
|
||||||
|
stream_indices.free(streamIndex);
|
||||||
|
delete output_streams[streamIndex];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return new, overridden stream
|
||||||
|
return stream;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests read access to the input stream having the given name. If
|
||||||
|
* successful, a new input stream will be created.
|
||||||
|
*
|
||||||
|
* @param {Number} index
|
||||||
|
* The index of the object from which the input stream is being
|
||||||
|
* requested.
|
||||||
|
*
|
||||||
|
* @param {String} name
|
||||||
|
* The name of the input stream to request.
|
||||||
|
*/
|
||||||
|
this.requestObjectInputStream = function(index, name) {
|
||||||
|
|
||||||
|
// Do not send requests if not connected
|
||||||
|
if (!isConnected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
tunnel.sendMessage("get", index, name);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Acknowledge receipt of a blob on the stream with the given index.
|
* Acknowledge receipt of a blob on the stream with the given index.
|
||||||
*
|
*
|
||||||
@@ -388,6 +457,20 @@ Guacamole.Client = function(tunnel) {
|
|||||||
*/
|
*/
|
||||||
this.onfile = null;
|
this.onfile = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when a filesystem object is created. The object provided to this
|
||||||
|
* event handler will contain its own event handlers and functions for
|
||||||
|
* requesting and handling data.
|
||||||
|
*
|
||||||
|
* @event
|
||||||
|
* @param {Guacamole.Object} object
|
||||||
|
* The created filesystem object.
|
||||||
|
*
|
||||||
|
* @param {String} name
|
||||||
|
* The name of the filesystem.
|
||||||
|
*/
|
||||||
|
this.onfilesystem = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired when a pipe stream is created. The stream provided to this event
|
* Fired when a pipe stream is created. The stream provided to this event
|
||||||
* handler will contain its own event handlers for received data;
|
* handler will contain its own event handlers for received data;
|
||||||
@@ -562,6 +645,28 @@ Guacamole.Client = function(tunnel) {
|
|||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"body": function(parameters) {
|
||||||
|
|
||||||
|
// Get object
|
||||||
|
var objectIndex = parseInt(parameters[0]);
|
||||||
|
var object = objects[objectIndex];
|
||||||
|
|
||||||
|
var streamIndex = parseInt(parameters[1]);
|
||||||
|
var mimetype = parameters[2];
|
||||||
|
var name = parameters[3];
|
||||||
|
|
||||||
|
// Create stream if handler defined
|
||||||
|
if (object && object.onbody) {
|
||||||
|
var stream = streams[streamIndex] = new Guacamole.InputStream(guac_client, streamIndex);
|
||||||
|
object.onbody(stream, mimetype, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, unsupported
|
||||||
|
else
|
||||||
|
guac_client.sendAck(streamIndex, "Receipt of body unsupported", 0x0100);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
"cfill": function(parameters) {
|
"cfill": function(parameters) {
|
||||||
|
|
||||||
var channelMask = parseInt(parameters[0]);
|
var channelMask = parseInt(parameters[0]);
|
||||||
@@ -758,6 +863,21 @@ Guacamole.Client = function(tunnel) {
|
|||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"filesystem": function(parameters) {
|
||||||
|
|
||||||
|
var objectIndex = parseInt(parameters[0]);
|
||||||
|
var name = parameters[1];
|
||||||
|
|
||||||
|
// Create object, if supported
|
||||||
|
if (guac_client.onfilesystem) {
|
||||||
|
var object = objects[objectIndex] = new Guacamole.Object(guac_client, objectIndex);
|
||||||
|
guac_client.onfilesystem(object, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If unsupported, simply ignore the availability of the filesystem
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
"identity": function(parameters) {
|
"identity": function(parameters) {
|
||||||
|
|
||||||
var layer = getLayer(parseInt(parameters[0]));
|
var layer = getLayer(parseInt(parameters[0]));
|
||||||
@@ -998,6 +1118,18 @@ Guacamole.Client = function(tunnel) {
|
|||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"undefine": function(parameters) {
|
||||||
|
|
||||||
|
// Get object
|
||||||
|
var objectIndex = parseInt(parameters[0]);
|
||||||
|
var object = objects[objectIndex];
|
||||||
|
|
||||||
|
// Signal end of object definition
|
||||||
|
if (object && object.onundefine)
|
||||||
|
object.onundefine();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
"video": function(parameters) {
|
"video": function(parameters) {
|
||||||
|
|
||||||
var stream_index = parseInt(parameters[0]);
|
var stream_index = parseInt(parameters[0]);
|
||||||
|
205
guacamole-common-js/src/main/webapp/modules/Object.js
Normal file
205
guacamole-common-js/src/main/webapp/modules/Object.js
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 Glyptodon LLC
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Guacamole = Guacamole || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object used by the Guacamole client to house arbitrarily-many named
|
||||||
|
* input and output streams.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {Guacamole.Client} client
|
||||||
|
* The client owning this object.
|
||||||
|
*
|
||||||
|
* @param {Number} index
|
||||||
|
* The index of this object.
|
||||||
|
*/
|
||||||
|
Guacamole.Object = function(client, index) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to this Guacamole.Object.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type Guacamole.Object
|
||||||
|
*/
|
||||||
|
var guacObject = this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The callbacks associated with all pending input stream requests, if the
|
||||||
|
* default onbody handling is in use.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type Object.<String, Function[]>
|
||||||
|
* Map of stream name to corresponding queue of callbacks. The queue of
|
||||||
|
* callbacks is guaranteed to be in order of request.
|
||||||
|
*/
|
||||||
|
var bodyCallbacks = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes and returns the callback at the head of the callback queue for
|
||||||
|
* the stream having the given name. If no such callbacks exist, null is
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} name
|
||||||
|
* The name of the stream to retrieve a callback for.
|
||||||
|
*
|
||||||
|
* @returns {Function}
|
||||||
|
* The next callback associated with the stream having the given name,
|
||||||
|
* or null if no such callback exists.
|
||||||
|
*/
|
||||||
|
var dequeueBodyCallback = function dequeueBodyCallback(name) {
|
||||||
|
|
||||||
|
// If no callbacks defined, simply return null
|
||||||
|
var callbacks = bodyCallbacks[name];
|
||||||
|
if (!callbacks)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Otherwise, pull off first callback, deleting the queue if empty
|
||||||
|
var callback = callbacks.shift();
|
||||||
|
if (callbacks.length === 0)
|
||||||
|
delete bodyCallbacks[name];
|
||||||
|
|
||||||
|
// Return found callback
|
||||||
|
return callback;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given callback to the tail of the callback queue for the stream
|
||||||
|
* having the given name.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} name
|
||||||
|
* The name of the stream to associate with the given callback.
|
||||||
|
*
|
||||||
|
* @param {Function} callback
|
||||||
|
* The callback to add to the queue of the stream with the given name.
|
||||||
|
*/
|
||||||
|
var enqueueBodyCallback = function enqueueBodyCallback(name, callback) {
|
||||||
|
|
||||||
|
// Get callback queue by name, creating first if necessary
|
||||||
|
var callbacks = bodyCallbacks[name];
|
||||||
|
if (!callbacks) {
|
||||||
|
callbacks = [];
|
||||||
|
bodyCallbacks[name] = callbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add callback to end of queue
|
||||||
|
callbacks.push(callback);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index of this object.
|
||||||
|
*
|
||||||
|
* @type Number
|
||||||
|
*/
|
||||||
|
this.index = index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this object receives the body of a requested input stream.
|
||||||
|
* By default, all objects will invoke the callbacks provided to their
|
||||||
|
* requestInputStream() functions based on the name of the stream
|
||||||
|
* requested. This behavior can be overridden by specifying a different
|
||||||
|
* handler here.
|
||||||
|
*
|
||||||
|
* @event
|
||||||
|
* @param {Guacamole.InputStream} inputStream
|
||||||
|
* The input stream of the received body.
|
||||||
|
*
|
||||||
|
* @param {String} mimetype
|
||||||
|
* The mimetype of the data being received.
|
||||||
|
*
|
||||||
|
* @param {String} name
|
||||||
|
* The name of the stream whose body has been received.
|
||||||
|
*/
|
||||||
|
this.onbody = function defaultBodyHandler(inputStream, mimetype, name) {
|
||||||
|
|
||||||
|
// Call queued callback for the received body, if any
|
||||||
|
var callback = dequeueBodyCallback(name);
|
||||||
|
if (callback)
|
||||||
|
callback(inputStream, mimetype);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this object is being undefined. Once undefined, no further
|
||||||
|
* communication involving this object may occur.
|
||||||
|
*
|
||||||
|
* @event
|
||||||
|
*/
|
||||||
|
this.onundefine = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests read access to the input stream having the given name. If
|
||||||
|
* successful, a new input stream will be created.
|
||||||
|
*
|
||||||
|
* @param {String} name
|
||||||
|
* The name of the input stream to request.
|
||||||
|
*
|
||||||
|
* @param {Function} [bodyCallback]
|
||||||
|
* The callback to invoke when the body of the requested input stream
|
||||||
|
* is received. This callback will be provided a Guacamole.InputStream
|
||||||
|
* and its mimetype as its two only arguments. If the onbody handler of
|
||||||
|
* this object is overridden, this callback will not be invoked.
|
||||||
|
*/
|
||||||
|
this.requestInputStream = function(name, bodyCallback) {
|
||||||
|
|
||||||
|
// Queue body callback if provided
|
||||||
|
if (bodyCallback)
|
||||||
|
queueBodyCallback(name, bodyCallback);
|
||||||
|
|
||||||
|
// Send request for input stream
|
||||||
|
client.requestObjectInputStream(guacObject.index, name);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new output stream associated with this object and having the
|
||||||
|
* given mimetype and name. The legality of a mimetype and name is dictated
|
||||||
|
* by the object itself.
|
||||||
|
*
|
||||||
|
* @param {String} mimetype
|
||||||
|
* The mimetype of the data which will be sent to the output stream.
|
||||||
|
*
|
||||||
|
* @param {String} name
|
||||||
|
* The defined name of an output stream within this object.
|
||||||
|
*
|
||||||
|
* @returns {Guacamole.OutputStream}
|
||||||
|
* An output stream which will write blobs to the named output stream
|
||||||
|
* of this object.
|
||||||
|
*/
|
||||||
|
this.createOutputStream = function(mimetype, name) {
|
||||||
|
return client.createObjectOutputStream(guacObject.index, mimetype, name);
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reserved name denoting the root stream of any object. The contents of
|
||||||
|
* the root stream MUST be a JSON map of stream name to mimetype.
|
||||||
|
*
|
||||||
|
* @constant
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
Guacamole.Object.ROOT_STREAM = '/';
|
Reference in New Issue
Block a user