mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUAC-558: Ensure state/error handlers are called ONLY on the last tunnel. Rewrite to clean program flow.
This commit is contained in:
@@ -168,15 +168,15 @@ Guacamole.HTTPTunnel = function(tunnelURL) {
|
||||
if (tunnel.state === Guacamole.Tunnel.State.CLOSED)
|
||||
return;
|
||||
|
||||
// If connection closed abnormally, signal error.
|
||||
if (status.code !== Guacamole.Status.Code.SUCCESS && tunnel.onerror)
|
||||
tunnel.onerror(status);
|
||||
|
||||
// Mark as closed
|
||||
tunnel.state = Guacamole.Tunnel.State.CLOSED;
|
||||
if (tunnel.onstatechange)
|
||||
tunnel.onstatechange(tunnel.state);
|
||||
|
||||
// If connection closed abnormally, signal error.
|
||||
if (status.code !== Guacamole.Status.Code.SUCCESS && tunnel.onerror)
|
||||
tunnel.onerror(status);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -602,15 +602,15 @@ Guacamole.WebSocketTunnel = function(tunnelURL) {
|
||||
if (tunnel.state === Guacamole.Tunnel.State.CLOSED)
|
||||
return;
|
||||
|
||||
// If connection closed abnormally, signal error.
|
||||
if (status.code !== Guacamole.Status.Code.SUCCESS && tunnel.onerror)
|
||||
tunnel.onerror(status);
|
||||
|
||||
// Mark as closed
|
||||
tunnel.state = Guacamole.Tunnel.State.CLOSED;
|
||||
if (tunnel.onstatechange)
|
||||
tunnel.onstatechange(tunnel.state);
|
||||
|
||||
// If connection closed abnormally, signal error.
|
||||
if (status.code !== Guacamole.Status.Code.SUCCESS && tunnel.onerror)
|
||||
tunnel.onerror(status);
|
||||
|
||||
socket.close();
|
||||
|
||||
}
|
||||
@@ -759,12 +759,6 @@ Guacamole.ChainedTunnel = function(tunnel_chain) {
|
||||
*/
|
||||
var chained_tunnel = this;
|
||||
|
||||
/**
|
||||
* The currently wrapped tunnel, if any.
|
||||
* @private
|
||||
*/
|
||||
var current_tunnel = null;
|
||||
|
||||
/**
|
||||
* Data passed in via connect(), to be used for
|
||||
* wrapped calls to other tunnels' connect() functions.
|
||||
@@ -791,38 +785,74 @@ Guacamole.ChainedTunnel = function(tunnel_chain) {
|
||||
*/
|
||||
function attach(tunnel) {
|
||||
|
||||
// Clear handlers of current tunnel, if any
|
||||
if (current_tunnel) {
|
||||
current_tunnel.onerror = null;
|
||||
current_tunnel.oninstruction = null;
|
||||
current_tunnel.onstatechange = null;
|
||||
}
|
||||
|
||||
// Set own functions to tunnel's functions
|
||||
chained_tunnel.disconnect = tunnel.disconnect;
|
||||
chained_tunnel.sendMessage = tunnel.sendMessage;
|
||||
|
||||
// Record current tunnel
|
||||
current_tunnel = tunnel;
|
||||
/**
|
||||
* Fails the currently-attached tunnel, attaching a new tunnel if
|
||||
* possible.
|
||||
*
|
||||
* @private
|
||||
* @return {Guacamole.Tunnel} The next tunnel, or null if there are no
|
||||
* more tunnels to try.
|
||||
*/
|
||||
function fail_tunnel() {
|
||||
|
||||
// Get next tunnel
|
||||
var next_tunnel = tunnels.shift();
|
||||
|
||||
// If there IS a next tunnel, try using it.
|
||||
if (next_tunnel) {
|
||||
tunnel.onerror = null;
|
||||
tunnel.oninstruction = null;
|
||||
tunnel.onstatechange = null;
|
||||
attach(next_tunnel);
|
||||
}
|
||||
|
||||
return next_tunnel;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the current tunnel from this point forward. Do not try any more
|
||||
* tunnels, even if the current tunnel fails.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function commit_tunnel() {
|
||||
tunnel.onstatechange = chained_tunnel.onstatechange;
|
||||
tunnel.oninstruction = chained_tunnel.oninstruction;
|
||||
tunnel.onerror = chained_tunnel.onerror;
|
||||
}
|
||||
|
||||
// Wrap own onstatechange within current tunnel
|
||||
current_tunnel.onstatechange = function(state) {
|
||||
tunnel.onstatechange = function(state) {
|
||||
|
||||
// Invoke handler
|
||||
switch (state) {
|
||||
|
||||
// If open, use this tunnel from this point forward.
|
||||
case Guacamole.Tunnel.State.OPEN:
|
||||
commit_tunnel();
|
||||
if (chained_tunnel.onstatechange)
|
||||
chained_tunnel.onstatechange(state);
|
||||
break;
|
||||
|
||||
// If closed, mark failure, attempt next tunnel
|
||||
case Guacamole.Tunnel.State.CLOSED:
|
||||
if (!fail_tunnel() && chained_tunnel.onstatechange)
|
||||
chained_tunnel.onstatechange(state);
|
||||
break;
|
||||
|
||||
// Use handlers permanently from now on
|
||||
if (state === Guacamole.Tunnel.State.OPEN) {
|
||||
current_tunnel.onstatechange = chained_tunnel.onstatechange;
|
||||
current_tunnel.oninstruction = chained_tunnel.oninstruction;
|
||||
current_tunnel.onerror = chained_tunnel.onerror;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Wrap own oninstruction within current tunnel
|
||||
current_tunnel.oninstruction = function(opcode, elements) {
|
||||
tunnel.oninstruction = function(opcode, elements) {
|
||||
|
||||
// Accept current tunnel
|
||||
commit_tunnel();
|
||||
|
||||
// Invoke handler
|
||||
if (chained_tunnel.oninstruction)
|
||||
@@ -831,33 +861,16 @@ Guacamole.ChainedTunnel = function(tunnel_chain) {
|
||||
};
|
||||
|
||||
// Attach next tunnel on error
|
||||
current_tunnel.onerror = function(status) {
|
||||
tunnel.onerror = function(status) {
|
||||
|
||||
// Get next tunnel
|
||||
var next_tunnel = tunnels.shift();
|
||||
|
||||
// If there IS a next tunnel, try using it.
|
||||
if (next_tunnel)
|
||||
attach(next_tunnel);
|
||||
|
||||
// Otherwise, call error handler
|
||||
else if (chained_tunnel.onerror)
|
||||
// Mark failure, attempt next tunnel
|
||||
if (!fail_tunnel() && chained_tunnel.onerror)
|
||||
chained_tunnel.onerror(status);
|
||||
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
// Attempt connection
|
||||
current_tunnel.connect(connect_data);
|
||||
|
||||
}
|
||||
catch (status) {
|
||||
|
||||
// Call error handler of current tunnel on error
|
||||
current_tunnel.onerror(status);
|
||||
|
||||
}
|
||||
tunnel.connect(connect_data);
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user