Refactor InputStream API.

This commit is contained in:
Michael Jumper
2014-02-28 10:03:01 -08:00
parent 4478e91c8a
commit beb9e5c684
3 changed files with 220 additions and 47 deletions

View File

@@ -438,9 +438,10 @@ Guacamole.Client = function(tunnel) {
* close event. * close event.
* *
* @event * @event
* @param {String} mimetype The mimetype of the file received.
* @param {String} filename The name of the file received. * @param {String} filename The name of the file received.
* @param {Guacamole.InputStream} stream A stream that will receive * @return {Guacamole.InputStream} The stream that will receive data from
* data from the server. * the server.
*/ */
this.onfile = null; this.onfile = null;
@@ -450,9 +451,10 @@ Guacamole.Client = function(tunnel) {
* close event. * close event.
* *
* @event * @event
* @param {String} mimetype The mimetype of the data which will be received.
* @param {String} name The name of the pipe. * @param {String} name The name of the pipe.
* @param {Guacamole.InputStream} stream A stream that will receive * @return {Guacamole.InputStream} The stream that will receive data from
* data from the server. * the server.
*/ */
this.onpipe = null; this.onpipe = null;
@@ -637,16 +639,8 @@ Guacamole.Client = function(tunnel) {
var data = parameters[1]; var data = parameters[1];
var stream = streams[stream_index]; var stream = streams[stream_index];
// Convert to ArrayBuffer
var binary = window.atob(data);
var arrayBuffer = new ArrayBuffer(binary.length);
var bufferView = new Uint8Array(arrayBuffer);
for (var i=0; i<binary.length; i++)
bufferView[i] = binary.charCodeAt(i);
// Write data // Write data
stream.receive(arrayBuffer); stream.receive(data);
// Send success response // Send success response
tunnel.sendMessage("ack", stream_index, "OK", 0x0000); tunnel.sendMessage("ack", stream_index, "OK", 0x0000);
@@ -851,15 +845,24 @@ Guacamole.Client = function(tunnel) {
var filename = parameters[2]; var filename = parameters[2];
// Create stream // Create stream
var stream = streams[stream_index] = if (guac_client.onfile) {
new Guacamole.InputStream(mimetype);
// Call handler now that file stream is created // Attempt to create stream
if (guac_client.onfile) var stream = guac_client.onfile(mimetype, filename);
guac_client.onfile(filename, stream); if (stream) {
streams[stream_index] = stream;
tunnel.sendMessage("ack", stream_index, "OK", 0x0000);
}
// Send success response // Notify if creation failed
tunnel.sendMessage("ack", stream_index, "OK", 0x0000); else
tunnel.sendMessage("ack", stream_index, "Unable to receive file", 0x0201);
}
// Otherwise, unsupported
else
tunnel.sendMessage("ack", stream_index, "File transfer unsupported", 0x0100);
}, },
@@ -943,15 +946,24 @@ Guacamole.Client = function(tunnel) {
var name = parameters[2]; var name = parameters[2];
// Create stream // Create stream
var stream = streams[stream_index] = if (guac_client.onpipe) {
new Guacamole.InputStream(mimetype);
// Call handler now that pipe stream is created // Attempt to create stream
if (guac_client.onpipe) var stream = guac_client.onpipe(mimetype, name);
guac_client.onpipe(name, stream); if (stream) {
streams[stream_index] = stream;
tunnel.sendMessage("ack", stream_index, "OK", 0x0000);
}
// Send success response // Notify if creation failed
tunnel.sendMessage("ack", stream_index, "OK", 0x0000); else
tunnel.sendMessage("ack", stream_index, "Unable to create pipe", 0x0201);
}
// Otherwise, unsupported
else
tunnel.sendMessage("ack", stream_index, "Named pipes unsupported", 0x0100);
}, },

View File

@@ -31,6 +31,102 @@ var Guacamole = Guacamole || {};
*/ */
Guacamole.InputStream = function(mimetype) { Guacamole.InputStream = function(mimetype) {
/**
* The mimetype of the data contained within this blob.
*/
this.mimetype = mimetype;
/**
* Receives the given base64-encoded data.
*
* @param {String} data The received base64 data.
*/
this.receive = function(data) {};
/**
* Closes this Guacamole.InputStream such that no further data will be
* written.
*/
this.close = function() {};
};
/**
* An input stream which receives all data packets as individual ArrayBuffer
* objects.
*
* @constructor
* @param {String} mimetype The mimetype of the data this stream will receive.
*/
Guacamole.ArrayBufferInputStream = function(mimetype) {
/**
* Reference to this Guacamole.InputStream.
* @private
*/
var guac_stream = this;
/*
* This is an input stream.
*/
Guacamole.InputStream.apply(this, [mimetype]);
// Receive implementation
this.receive = function(data) {
// Convert to ArrayBuffer
var binary = window.atob(data);
var arrayBuffer = new ArrayBuffer(binary.length);
var bufferView = new Uint8Array(arrayBuffer);
for (var i=0; i<binary.length; i++)
bufferView[i] = binary.charCodeAt(i);
// Call handler, if present
if (guac_stream.onreceive)
guac_stream.onreceive(arrayBuffer);
};
// Close implementation
this.close = function() {
// Call handler, if present
if (guac_stream.onclose)
guac_stream.onclose();
// NOTE: Currently not enforced.
};
/**
* Fired once for every blob of data received.
*
* @event
* @param {ArrayBuffer} buffer The data packet received.
*/
this.onreceive = null;
/**
* Fired once this stream is finished and no further data will be written.
* @event
*/
this.onclose = null;
};
Guacamole.ArrayBufferInputStream.prototype = new Guacamole.InputStream();
/**
* An input stream which continuously builds a single blob by appending each
* individual blob received. Only the size of each blob received is exposed.
*
* @constructor
* @augments Guacamole.InputStream
* @param {String} mimetype The mimetype of the data this stream will receive.
*/
Guacamole.BlobInputStream = function(mimetype) {
/** /**
* Reference to this Guacamole.InputStream. * Reference to this Guacamole.InputStream.
* @private * @private
@@ -43,10 +139,10 @@ Guacamole.InputStream = function(mimetype) {
*/ */
var length = 0; var length = 0;
/** /*
* The mimetype of the data contained within this blob. * This is an input stream.
*/ */
this.mimetype = mimetype; Guacamole.InputStream.apply(this, [mimetype]);
// Get blob builder // Get blob builder
var blob_builder; var blob_builder;
@@ -70,28 +166,27 @@ Guacamole.InputStream = function(mimetype) {
})(); })();
/** // Receive implementation
* Receives the given ArrayBuffer, storing its data within this this.receive = function(data) {
* Guacamole.InputStream.
*
* @param {ArrayBuffer} buffer An ArrayBuffer containing the data to be
* received.
*/
this.receive = function(buffer) {
blob_builder.append(buffer); // Convert to ArrayBuffer
length += buffer.byteLength; var binary = window.atob(data);
var arrayBuffer = new ArrayBuffer(binary.length);
var bufferView = new Uint8Array(arrayBuffer);
for (var i=0; i<binary.length; i++)
bufferView[i] = binary.charCodeAt(i);
blob_builder.append(arrayBuffer);
length += arrayBuffer.byteLength;
// Call handler, if present // Call handler, if present
if (guac_stream.onreceive) if (guac_stream.onprogress)
guac_stream.onreceive(buffer.byteLength); guac_stream.onprogress(arrayBuffer.byteLength);
}; };
/** // Close implementation
* Closes this Guacamole.InputStream such that no further data will be
* written.
*/
this.close = function() { this.close = function() {
// Call handler, if present // Call handler, if present
@@ -124,6 +219,66 @@ Guacamole.InputStream = function(mimetype) {
* @event * @event
* @param {Number} length The number of bytes received. * @param {Number} length The number of bytes received.
*/ */
this.onprogress = null;
/**
* Fired once this stream is finished and no further data will be written.
* @event
*/
this.onclose = null;
};
Guacamole.BlobInputStream.prototype = new Guacamole.InputStream();
/**
* An input stream which receives strictly text data.
*
* @constructor
* @param {String} mimetype The mimetype of the data this stream will receive.
*/
Guacamole.StringInputStream = function(mimetype) {
/**
* Reference to this Guacamole.InputStream.
* @private
*/
var guac_stream = this;
/*
* This is an input stream.
*/
Guacamole.InputStream.apply(this, [mimetype]);
// Receive implementation
this.receive = function(data) {
// Convert to string
var text = window.atob(data);
// Call handler, if present
if (guac_stream.onreceive)
guac_stream.onreceive(text);
};
// Close implementation
this.close = function() {
// Call handler, if present
if (guac_stream.onclose)
guac_stream.onclose();
// NOTE: Currently not enforced.
};
/**
* Fired once for every blob of data received.
*
* @event
* @param {String} text The data packet received.
*/
this.onreceive = null; this.onreceive = null;
/** /**
@@ -133,3 +288,5 @@ Guacamole.InputStream = function(mimetype) {
this.onclose = null; this.onclose = null;
}; };
Guacamole.StringInputStream.prototype = new Guacamole.InputStream();

View File

@@ -815,7 +815,9 @@ GuacUI.Client.attach = function(guac) {
} }
guac.onfile = function(filename, stream) { guac.onfile = function(mimetype, filename) {
var stream = new Guacamole.BlobInputStream(mimetype);
var download = new GuacUI.Download(filename); var download = new GuacUI.Download(filename);
download.updateProgress(getSizeString(0)); download.updateProgress(getSizeString(0));
@@ -843,6 +845,8 @@ GuacUI.Client.attach = function(guac) {
GuacUI.Client.notification_area.removeChild(download.getElement()); GuacUI.Client.notification_area.removeChild(download.getElement());
}; };
return stream;
}; };
/* /*