mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-44: Expose tunnel UUID to JavaScript. Document allowed internal use of the empty opcode.
This commit is contained in:
@@ -70,6 +70,14 @@ Guacamole.Tunnel = function() {
|
|||||||
*/
|
*/
|
||||||
this.receiveTimeout = 15000;
|
this.receiveTimeout = 15000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UUID uniquely identifying this tunnel. If not yet known, this will
|
||||||
|
* be null.
|
||||||
|
*
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.uuid = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired whenever an error is encountered by the tunnel.
|
* Fired whenever an error is encountered by the tunnel.
|
||||||
*
|
*
|
||||||
@@ -99,6 +107,18 @@ Guacamole.Tunnel = function() {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Guacamole protocol instruction opcode reserved for arbitrary internal
|
||||||
|
* use by tunnel implementations. The value of this opcode is guaranteed to be
|
||||||
|
* the empty string (""). Tunnel implementations may use this opcode for any
|
||||||
|
* purpose. It is currently used by the HTTP tunnel to mark the end of the HTTP
|
||||||
|
* response, and by the WebSocket tunnel to transmit the tunnel UUID.
|
||||||
|
*
|
||||||
|
* @constant
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
Guacamole.Tunnel.INTERNAL_DATA_OPCODE = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All possible tunnel states.
|
* All possible tunnel states.
|
||||||
*/
|
*/
|
||||||
@@ -152,8 +172,6 @@ Guacamole.HTTPTunnel = function(tunnelURL, crossDomain) {
|
|||||||
*/
|
*/
|
||||||
var tunnel = this;
|
var tunnel = this;
|
||||||
|
|
||||||
var tunnel_uuid;
|
|
||||||
|
|
||||||
var TUNNEL_CONNECT = tunnelURL + "?connect";
|
var TUNNEL_CONNECT = tunnelURL + "?connect";
|
||||||
var TUNNEL_READ = tunnelURL + "?read:";
|
var TUNNEL_READ = tunnelURL + "?read:";
|
||||||
var TUNNEL_WRITE = tunnelURL + "?write:";
|
var TUNNEL_WRITE = tunnelURL + "?write:";
|
||||||
@@ -286,7 +304,7 @@ Guacamole.HTTPTunnel = function(tunnelURL, crossDomain) {
|
|||||||
sendingMessages = true;
|
sendingMessages = true;
|
||||||
|
|
||||||
var message_xmlhttprequest = new XMLHttpRequest();
|
var message_xmlhttprequest = new XMLHttpRequest();
|
||||||
message_xmlhttprequest.open("POST", TUNNEL_WRITE + tunnel_uuid);
|
message_xmlhttprequest.open("POST", TUNNEL_WRITE + tunnel.uuid);
|
||||||
message_xmlhttprequest.withCredentials = withCredentials;
|
message_xmlhttprequest.withCredentials = withCredentials;
|
||||||
message_xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
|
message_xmlhttprequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||||
|
|
||||||
@@ -517,7 +535,7 @@ Guacamole.HTTPTunnel = function(tunnelURL, crossDomain) {
|
|||||||
|
|
||||||
// Make request, increment request ID
|
// Make request, increment request ID
|
||||||
var xmlhttprequest = new XMLHttpRequest();
|
var xmlhttprequest = new XMLHttpRequest();
|
||||||
xmlhttprequest.open("GET", TUNNEL_READ + tunnel_uuid + ":" + (request_id++));
|
xmlhttprequest.open("GET", TUNNEL_READ + tunnel.uuid + ":" + (request_id++));
|
||||||
xmlhttprequest.withCredentials = withCredentials;
|
xmlhttprequest.withCredentials = withCredentials;
|
||||||
xmlhttprequest.send(null);
|
xmlhttprequest.send(null);
|
||||||
|
|
||||||
@@ -546,7 +564,7 @@ Guacamole.HTTPTunnel = function(tunnelURL, crossDomain) {
|
|||||||
reset_timeout();
|
reset_timeout();
|
||||||
|
|
||||||
// Get UUID from response
|
// Get UUID from response
|
||||||
tunnel_uuid = connect_xmlhttprequest.responseText;
|
tunnel.uuid = connect_xmlhttprequest.responseText;
|
||||||
|
|
||||||
tunnel.state = Guacamole.Tunnel.State.OPEN;
|
tunnel.state = Guacamole.Tunnel.State.OPEN;
|
||||||
if (tunnel.onstatechange)
|
if (tunnel.onstatechange)
|
||||||
@@ -733,13 +751,7 @@ Guacamole.WebSocketTunnel = function(tunnelURL) {
|
|||||||
socket = new WebSocket(tunnelURL + "?" + data, "guacamole");
|
socket = new WebSocket(tunnelURL + "?" + data, "guacamole");
|
||||||
|
|
||||||
socket.onopen = function(event) {
|
socket.onopen = function(event) {
|
||||||
|
|
||||||
reset_timeout();
|
reset_timeout();
|
||||||
|
|
||||||
tunnel.state = Guacamole.Tunnel.State.OPEN;
|
|
||||||
if (tunnel.onstatechange)
|
|
||||||
tunnel.onstatechange(tunnel.state);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.onclose = function(event) {
|
socket.onclose = function(event) {
|
||||||
@@ -794,8 +806,22 @@ Guacamole.WebSocketTunnel = function(tunnelURL) {
|
|||||||
// Get opcode
|
// Get opcode
|
||||||
var opcode = elements.shift();
|
var opcode = elements.shift();
|
||||||
|
|
||||||
|
// Update state and UUID when first instruction received
|
||||||
|
if (tunnel.state !== Guacamole.Tunnel.State.OPEN) {
|
||||||
|
|
||||||
|
// Associate tunnel UUID if received
|
||||||
|
if (opcode === Guacamole.Tunnel.INTERNAL_DATA_OPCODE)
|
||||||
|
tunnel.uuid = elements[0];
|
||||||
|
|
||||||
|
// Tunnel is now open and UUID is available
|
||||||
|
tunnel.state = Guacamole.Tunnel.State.OPEN;
|
||||||
|
if (tunnel.onstatechange)
|
||||||
|
tunnel.onstatechange(tunnel.state);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Call instruction handler.
|
// Call instruction handler.
|
||||||
if (tunnel.oninstruction)
|
if (opcode !== Guacamole.Tunnel.INTERNAL_DATA_OPCODE && tunnel.oninstruction)
|
||||||
tunnel.oninstruction(opcode, elements);
|
tunnel.oninstruction(opcode, elements);
|
||||||
|
|
||||||
// Clear elements
|
// Clear elements
|
||||||
@@ -926,6 +952,7 @@ Guacamole.ChainedTunnel = function(tunnelChain) {
|
|||||||
tunnel.onstatechange = chained_tunnel.onstatechange;
|
tunnel.onstatechange = chained_tunnel.onstatechange;
|
||||||
tunnel.oninstruction = chained_tunnel.oninstruction;
|
tunnel.oninstruction = chained_tunnel.oninstruction;
|
||||||
tunnel.onerror = chained_tunnel.onerror;
|
tunnel.onerror = chained_tunnel.onerror;
|
||||||
|
chained_tunnel.uuid = tunnel.uuid;
|
||||||
committedTunnel = tunnel;
|
committedTunnel = tunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,6 +33,16 @@ import org.apache.guacamole.io.GuacamoleWriter;
|
|||||||
*/
|
*/
|
||||||
public interface GuacamoleTunnel {
|
public interface GuacamoleTunnel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Guacamole protocol instruction opcode reserved for arbitrary
|
||||||
|
* internal use by tunnel implementations. The value of this opcode is
|
||||||
|
* guaranteed to be the empty string (""). Tunnel implementations may use
|
||||||
|
* this opcode for any purpose. It is currently used by the HTTP tunnel to
|
||||||
|
* mark the end of the HTTP response, and by the WebSocket tunnel to
|
||||||
|
* transmit the tunnel UUID.
|
||||||
|
*/
|
||||||
|
static final String INTERNAL_DATA_OPCODE = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Acquires exclusive read access to the Guacamole instruction stream
|
* Acquires exclusive read access to the Guacamole instruction stream
|
||||||
* and returns a GuacamoleReader for reading from that stream.
|
* and returns a GuacamoleReader for reading from that stream.
|
||||||
|
@@ -36,6 +36,7 @@ import org.apache.guacamole.io.GuacamoleWriter;
|
|||||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||||
import org.apache.guacamole.GuacamoleClientException;
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
import org.apache.guacamole.GuacamoleConnectionClosedException;
|
import org.apache.guacamole.GuacamoleConnectionClosedException;
|
||||||
|
import org.apache.guacamole.protocol.GuacamoleInstruction;
|
||||||
import org.apache.guacamole.protocol.GuacamoleStatus;
|
import org.apache.guacamole.protocol.GuacamoleStatus;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -149,6 +150,12 @@ public abstract class GuacamoleWebSocketTunnelEndpoint extends Endpoint {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// Send tunnel UUID
|
||||||
|
remote.sendText(new GuacamoleInstruction(
|
||||||
|
GuacamoleTunnel.INTERNAL_DATA_OPCODE,
|
||||||
|
tunnel.getUUID().toString()
|
||||||
|
).toString());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Attempt to read
|
// Attempt to read
|
||||||
|
@@ -124,10 +124,6 @@ public class TunnelRESTService {
|
|||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
||||||
Map<String, StreamInterceptingTunnel> tunnels = session.getTunnels();
|
Map<String, StreamInterceptingTunnel> tunnels = session.getTunnels();
|
||||||
|
|
||||||
// STUB: For sake of testing, if only one tunnel exists, use that
|
|
||||||
if (tunnels.size() == 1)
|
|
||||||
tunnelUUID = tunnels.keySet().iterator().next();
|
|
||||||
|
|
||||||
// Pull tunnel with given UUID
|
// Pull tunnel with given UUID
|
||||||
final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID);
|
final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID);
|
||||||
if (tunnel == null)
|
if (tunnel == null)
|
||||||
|
@@ -30,6 +30,7 @@ import org.eclipse.jetty.websocket.WebSocket.Connection;
|
|||||||
import org.eclipse.jetty.websocket.WebSocketServlet;
|
import org.eclipse.jetty.websocket.WebSocketServlet;
|
||||||
import org.apache.guacamole.GuacamoleClientException;
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
import org.apache.guacamole.GuacamoleConnectionClosedException;
|
import org.apache.guacamole.GuacamoleConnectionClosedException;
|
||||||
|
import org.apache.guacamole.protocol.GuacamoleInstruction;
|
||||||
import org.apache.guacamole.tunnel.http.HTTPTunnelRequest;
|
import org.apache.guacamole.tunnel.http.HTTPTunnelRequest;
|
||||||
import org.apache.guacamole.tunnel.TunnelRequest;
|
import org.apache.guacamole.tunnel.TunnelRequest;
|
||||||
import org.apache.guacamole.protocol.GuacamoleStatus;
|
import org.apache.guacamole.protocol.GuacamoleStatus;
|
||||||
@@ -136,6 +137,12 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// Send tunnel UUID
|
||||||
|
connection.sendMessage(new GuacamoleInstruction(
|
||||||
|
GuacamoleTunnel.INTERNAL_DATA_OPCODE,
|
||||||
|
tunnel.getUUID().toString()
|
||||||
|
).toString());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Attempt to read
|
// Attempt to read
|
||||||
|
@@ -30,6 +30,7 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
import org.apache.guacamole.io.GuacamoleReader;
|
import org.apache.guacamole.io.GuacamoleReader;
|
||||||
import org.apache.guacamole.io.GuacamoleWriter;
|
import org.apache.guacamole.io.GuacamoleWriter;
|
||||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||||
|
import org.apache.guacamole.protocol.GuacamoleInstruction;
|
||||||
import org.apache.guacamole.protocol.GuacamoleStatus;
|
import org.apache.guacamole.protocol.GuacamoleStatus;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -127,6 +128,12 @@ public abstract class GuacamoleWebSocketTunnelListener implements WebSocketListe
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// Send tunnel UUID
|
||||||
|
remote.sendString(new GuacamoleInstruction(
|
||||||
|
GuacamoleTunnel.INTERNAL_DATA_OPCODE,
|
||||||
|
tunnel.getUUID().toString()
|
||||||
|
).toString());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Attempt to read
|
// Attempt to read
|
||||||
|
@@ -35,6 +35,7 @@ import org.apache.catalina.websocket.WebSocketServlet;
|
|||||||
import org.apache.catalina.websocket.WsOutbound;
|
import org.apache.catalina.websocket.WsOutbound;
|
||||||
import org.apache.guacamole.GuacamoleClientException;
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
import org.apache.guacamole.GuacamoleConnectionClosedException;
|
import org.apache.guacamole.GuacamoleConnectionClosedException;
|
||||||
|
import org.apache.guacamole.protocol.GuacamoleInstruction;
|
||||||
import org.apache.guacamole.tunnel.http.HTTPTunnelRequest;
|
import org.apache.guacamole.tunnel.http.HTTPTunnelRequest;
|
||||||
import org.apache.guacamole.tunnel.TunnelRequest;
|
import org.apache.guacamole.tunnel.TunnelRequest;
|
||||||
import org.apache.guacamole.protocol.GuacamoleStatus;
|
import org.apache.guacamole.protocol.GuacamoleStatus;
|
||||||
@@ -164,6 +165,12 @@ public abstract class GuacamoleWebSocketTunnelServlet extends WebSocketServlet {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// Send tunnel UUID
|
||||||
|
outbound.writeTextMessage(CharBuffer.wrap(new GuacamoleInstruction(
|
||||||
|
GuacamoleTunnel.INTERNAL_DATA_OPCODE,
|
||||||
|
tunnel.getUUID().toString()
|
||||||
|
).toString()));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Attempt to read
|
// Attempt to read
|
||||||
|
Reference in New Issue
Block a user