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)
|
if (tunnel.state === Guacamole.Tunnel.State.CLOSED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// If connection closed abnormally, signal error.
|
||||||
|
if (status.code !== Guacamole.Status.Code.SUCCESS && tunnel.onerror)
|
||||||
|
tunnel.onerror(status);
|
||||||
|
|
||||||
// Mark as closed
|
// Mark as closed
|
||||||
tunnel.state = Guacamole.Tunnel.State.CLOSED;
|
tunnel.state = Guacamole.Tunnel.State.CLOSED;
|
||||||
if (tunnel.onstatechange)
|
if (tunnel.onstatechange)
|
||||||
tunnel.onstatechange(tunnel.state);
|
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)
|
if (tunnel.state === Guacamole.Tunnel.State.CLOSED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// If connection closed abnormally, signal error.
|
||||||
|
if (status.code !== Guacamole.Status.Code.SUCCESS && tunnel.onerror)
|
||||||
|
tunnel.onerror(status);
|
||||||
|
|
||||||
// Mark as closed
|
// Mark as closed
|
||||||
tunnel.state = Guacamole.Tunnel.State.CLOSED;
|
tunnel.state = Guacamole.Tunnel.State.CLOSED;
|
||||||
if (tunnel.onstatechange)
|
if (tunnel.onstatechange)
|
||||||
tunnel.onstatechange(tunnel.state);
|
tunnel.onstatechange(tunnel.state);
|
||||||
|
|
||||||
// If connection closed abnormally, signal error.
|
|
||||||
if (status.code !== Guacamole.Status.Code.SUCCESS && tunnel.onerror)
|
|
||||||
tunnel.onerror(status);
|
|
||||||
|
|
||||||
socket.close();
|
socket.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -759,12 +759,6 @@ Guacamole.ChainedTunnel = function(tunnel_chain) {
|
|||||||
*/
|
*/
|
||||||
var chained_tunnel = this;
|
var chained_tunnel = this;
|
||||||
|
|
||||||
/**
|
|
||||||
* The currently wrapped tunnel, if any.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
var current_tunnel = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data passed in via connect(), to be used for
|
* Data passed in via connect(), to be used for
|
||||||
* wrapped calls to other tunnels' connect() functions.
|
* wrapped calls to other tunnels' connect() functions.
|
||||||
@@ -791,39 +785,75 @@ Guacamole.ChainedTunnel = function(tunnel_chain) {
|
|||||||
*/
|
*/
|
||||||
function attach(tunnel) {
|
function attach(tunnel) {
|
||||||
|
|
||||||
// Clear handlers of current tunnel, if any
|
// Set own functions to tunnel's functions
|
||||||
if (current_tunnel) {
|
chained_tunnel.disconnect = tunnel.disconnect;
|
||||||
current_tunnel.onerror = null;
|
chained_tunnel.sendMessage = tunnel.sendMessage;
|
||||||
current_tunnel.oninstruction = null;
|
|
||||||
current_tunnel.onstatechange = null;
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set own functions to tunnel's functions
|
/**
|
||||||
chained_tunnel.disconnect = tunnel.disconnect;
|
* Use the current tunnel from this point forward. Do not try any more
|
||||||
chained_tunnel.sendMessage = tunnel.sendMessage;
|
* tunnels, even if the current tunnel fails.
|
||||||
|
*
|
||||||
// Record current tunnel
|
* @private
|
||||||
current_tunnel = tunnel;
|
*/
|
||||||
|
function commit_tunnel() {
|
||||||
|
tunnel.onstatechange = chained_tunnel.onstatechange;
|
||||||
|
tunnel.oninstruction = chained_tunnel.oninstruction;
|
||||||
|
tunnel.onerror = chained_tunnel.onerror;
|
||||||
|
}
|
||||||
|
|
||||||
// Wrap own onstatechange within current tunnel
|
// Wrap own onstatechange within current tunnel
|
||||||
current_tunnel.onstatechange = function(state) {
|
tunnel.onstatechange = function(state) {
|
||||||
|
|
||||||
// Invoke handler
|
|
||||||
if (chained_tunnel.onstatechange)
|
|
||||||
chained_tunnel.onstatechange(state);
|
|
||||||
|
|
||||||
// Use handlers permanently from now on
|
switch (state) {
|
||||||
if (state === Guacamole.Tunnel.State.OPEN) {
|
|
||||||
current_tunnel.onstatechange = chained_tunnel.onstatechange;
|
// If open, use this tunnel from this point forward.
|
||||||
current_tunnel.oninstruction = chained_tunnel.oninstruction;
|
case Guacamole.Tunnel.State.OPEN:
|
||||||
current_tunnel.onerror = chained_tunnel.onerror;
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wrap own oninstruction within current tunnel
|
// Wrap own oninstruction within current tunnel
|
||||||
current_tunnel.oninstruction = function(opcode, elements) {
|
tunnel.oninstruction = function(opcode, elements) {
|
||||||
|
|
||||||
|
// Accept current tunnel
|
||||||
|
commit_tunnel();
|
||||||
|
|
||||||
// Invoke handler
|
// Invoke handler
|
||||||
if (chained_tunnel.oninstruction)
|
if (chained_tunnel.oninstruction)
|
||||||
chained_tunnel.oninstruction(opcode, elements);
|
chained_tunnel.oninstruction(opcode, elements);
|
||||||
@@ -831,34 +861,17 @@ Guacamole.ChainedTunnel = function(tunnel_chain) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Attach next tunnel on error
|
// Attach next tunnel on error
|
||||||
current_tunnel.onerror = function(status) {
|
tunnel.onerror = function(status) {
|
||||||
|
|
||||||
// Get next tunnel
|
// Mark failure, attempt next tunnel
|
||||||
var next_tunnel = tunnels.shift();
|
if (!fail_tunnel() && chained_tunnel.onerror)
|
||||||
|
|
||||||
// If there IS a next tunnel, try using it.
|
|
||||||
if (next_tunnel)
|
|
||||||
attach(next_tunnel);
|
|
||||||
|
|
||||||
// Otherwise, call error handler
|
|
||||||
else if (chained_tunnel.onerror)
|
|
||||||
chained_tunnel.onerror(status);
|
chained_tunnel.onerror(status);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
// Attempt connection
|
||||||
|
tunnel.connect(connect_data);
|
||||||
// Attempt connection
|
|
||||||
current_tunnel.connect(connect_data);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (status) {
|
|
||||||
|
|
||||||
// Call error handler of current tunnel on error
|
|
||||||
current_tunnel.onerror(status);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connect = function(data) {
|
this.connect = function(data) {
|
||||||
|
Reference in New Issue
Block a user