Skip to content
This repository was archived by the owner on Jul 17, 2023. It is now read-only.

Commit 7a88c98

Browse files
committed
Merge pull request #203 from glyptodon/object-api
GUAC-1172: Add Guacamole.Object and support for related instructions
2 parents 83f6c00 + 4ec407b commit 7a88c98

File tree

3 files changed

+464
-0
lines changed

3 files changed

+464
-0
lines changed

guacamole-common-js/src/main/webapp/modules/Client.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ Guacamole.Client = function(tunnel) {
8686
// No initial streams
8787
var streams = [];
8888

89+
/**
90+
* All current objects. The index of each object is dictated by the
91+
* Guacamole server.
92+
*
93+
* @type Guacamole.Object[]
94+
*/
95+
var objects = [];
96+
8997
// Pool of available stream indices
9098
var stream_indices = new Guacamole.IntegerPool();
9199

@@ -293,6 +301,67 @@ Guacamole.Client = function(tunnel) {
293301

294302
};
295303

304+
/**
305+
* Creates a new output stream associated with the given object and having
306+
* the given mimetype and name. The legality of a mimetype and name is
307+
* dictated by the object itself.
308+
*
309+
* @param {Number} index
310+
* The index of the object for which the output stream is being
311+
* created.
312+
*
313+
* @param {String} mimetype
314+
* The mimetype of the data which will be sent to the output stream.
315+
*
316+
* @param {String} name
317+
* The defined name of an output stream within the given object.
318+
*
319+
* @returns {Guacamole.OutputStream}
320+
* An output stream which will write blobs to the named output stream
321+
* of the given object.
322+
*/
323+
this.createObjectOutputStream = function createObjectOutputStream(index, mimetype, name) {
324+
325+
// Allocate index
326+
var streamIndex = stream_indices.next();
327+
328+
// Create new stream
329+
tunnel.sendMessage("put", index, streamIndex, mimetype, name);
330+
var stream = output_streams[streamIndex] = new Guacamole.OutputStream(guac_client, streamIndex);
331+
332+
// Override sendEnd() of stream to automatically free index
333+
var oldEnd = stream.sendEnd;
334+
stream.sendEnd = function freeStreamIndex() {
335+
oldEnd();
336+
stream_indices.free(streamIndex);
337+
delete output_streams[streamIndex];
338+
};
339+
340+
// Return new, overridden stream
341+
return stream;
342+
343+
};
344+
345+
/**
346+
* Requests read access to the input stream having the given name. If
347+
* successful, a new input stream will be created.
348+
*
349+
* @param {Number} index
350+
* The index of the object from which the input stream is being
351+
* requested.
352+
*
353+
* @param {String} name
354+
* The name of the input stream to request.
355+
*/
356+
this.requestObjectInputStream = function requestObjectInputStream(index, name) {
357+
358+
// Do not send requests if not connected
359+
if (!isConnected())
360+
return;
361+
362+
tunnel.sendMessage("get", index, name);
363+
};
364+
296365
/**
297366
* Acknowledge receipt of a blob on the stream with the given index.
298367
*
@@ -388,6 +457,20 @@ Guacamole.Client = function(tunnel) {
388457
*/
389458
this.onfile = null;
390459

460+
/**
461+
* Fired when a filesystem object is created. The object provided to this
462+
* event handler will contain its own event handlers and functions for
463+
* requesting and handling data.
464+
*
465+
* @event
466+
* @param {Guacamole.Object} object
467+
* The created filesystem object.
468+
*
469+
* @param {String} name
470+
* The name of the filesystem.
471+
*/
472+
this.onfilesystem = null;
473+
391474
/**
392475
* Fired when a pipe stream is created. The stream provided to this event
393476
* handler will contain its own event handlers for received data;
@@ -562,6 +645,28 @@ Guacamole.Client = function(tunnel) {
562645

563646
},
564647

648+
"body" : function handleBody(parameters) {
649+
650+
// Get object
651+
var objectIndex = parseInt(parameters[0]);
652+
var object = objects[objectIndex];
653+
654+
var streamIndex = parseInt(parameters[1]);
655+
var mimetype = parameters[2];
656+
var name = parameters[3];
657+
658+
// Create stream if handler defined
659+
if (object && object.onbody) {
660+
var stream = streams[streamIndex] = new Guacamole.InputStream(guac_client, streamIndex);
661+
object.onbody(stream, mimetype, name);
662+
}
663+
664+
// Otherwise, unsupported
665+
else
666+
guac_client.sendAck(streamIndex, "Receipt of body unsupported", 0x0100);
667+
668+
},
669+
565670
"cfill": function(parameters) {
566671

567672
var channelMask = parseInt(parameters[0]);
@@ -758,6 +863,21 @@ Guacamole.Client = function(tunnel) {
758863

759864
},
760865

866+
"filesystem" : function handleFilesystem(parameters) {
867+
868+
var objectIndex = parseInt(parameters[0]);
869+
var name = parameters[1];
870+
871+
// Create object, if supported
872+
if (guac_client.onfilesystem) {
873+
var object = objects[objectIndex] = new Guacamole.Object(guac_client, objectIndex);
874+
guac_client.onfilesystem(object, name);
875+
}
876+
877+
// If unsupported, simply ignore the availability of the filesystem
878+
879+
},
880+
761881
"identity": function(parameters) {
762882

763883
var layer = getLayer(parseInt(parameters[0]));
@@ -998,6 +1118,18 @@ Guacamole.Client = function(tunnel) {
9981118

9991119
},
10001120

1121+
"undefine" : function handleUndefine(parameters) {
1122+
1123+
// Get object
1124+
var objectIndex = parseInt(parameters[0]);
1125+
var object = objects[objectIndex];
1126+
1127+
// Signal end of object definition
1128+
if (object && object.onundefine)
1129+
object.onundefine();
1130+
1131+
},
1132+
10011133
"video": function(parameters) {
10021134

10031135
var stream_index = parseInt(parameters[0]);
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright (C) 2015 Glyptodon LLC
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
* THE SOFTWARE.
21+
*/
22+
23+
var Guacamole = Guacamole || {};
24+
25+
/**
26+
* A reader which automatically handles the given input stream, assembling all
27+
* received blobs into a JavaScript object by appending them to each other, in
28+
* order, and decoding the result as JSON. Note that this object will overwrite
29+
* any installed event handlers on the given Guacamole.InputStream.
30+
*
31+
* @constructor
32+
* @param {Guacamole.InputStream} stream
33+
* The stream that JSON will be read from.
34+
*/
35+
Guacamole.JSONReader = function guacamoleJSONReader(stream) {
36+
37+
/**
38+
* Reference to this Guacamole.JSONReader.
39+
*
40+
* @private
41+
* @type Guacamole.JSONReader
42+
*/
43+
var guacReader = this;
44+
45+
/**
46+
* Wrapped Guacamole.StringReader.
47+
*
48+
* @private
49+
* @type Guacamole.StringReader
50+
*/
51+
var stringReader = new Guacamole.StringReader(stream);
52+
53+
/**
54+
* All JSON read thus far.
55+
*
56+
* @private
57+
* @type String
58+
*/
59+
var json = '';
60+
61+
/**
62+
* Returns the current length of this Guacamole.JSONReader, in characters.
63+
*
64+
* @return {Number}
65+
* The current length of this Guacamole.JSONReader.
66+
*/
67+
this.getLength = function getLength() {
68+
return json.length;
69+
};
70+
71+
/**
72+
* Returns the contents of this Guacamole.JSONReader as a JavaScript
73+
* object.
74+
*
75+
* @return {Object}
76+
* The contents of this Guacamole.JSONReader, as parsed from the JSON
77+
* contents of the input stream.
78+
*/
79+
this.getJSON = function getJSON() {
80+
return JSON.parse(json);
81+
};
82+
83+
// Append all received text
84+
stringReader.ontext = function ontext(text) {
85+
86+
// Append received text
87+
json += text;
88+
89+
// Call handler, if present
90+
if (guacReader.onprogress)
91+
guacReader.onprogress(text.length);
92+
93+
};
94+
95+
// Simply call onend when end received
96+
stringReader.onend = function onend() {
97+
if (guacReader.onend)
98+
guacReader.onend();
99+
};
100+
101+
/**
102+
* Fired once for every blob of data received.
103+
*
104+
* @event
105+
* @param {Number} length
106+
* The number of characters received.
107+
*/
108+
this.onprogress = null;
109+
110+
/**
111+
* Fired once this stream is finished and no further data will be written.
112+
*
113+
* @event
114+
*/
115+
this.onend = null;
116+
117+
};

0 commit comments

Comments
 (0)