mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 21:27:40 +00:00
GUACAMOLE-201: Occasionally verify client responsiveness when intercepting streams.
This commit is contained in:
@@ -47,6 +47,14 @@ public class OutputStreamInterceptingFilter
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(OutputStreamInterceptingFilter.class);
|
||||
|
||||
/**
|
||||
* Whether this OutputStreamInterceptingFilter should respond to received
|
||||
* blobs with "ack" messages on behalf of the client. If false, blobs will
|
||||
* still be handled by this filter, but empty blobs will be sent to the
|
||||
* client, forcing the client to respond on its own.
|
||||
*/
|
||||
private boolean acknowledgeBlobs = true;
|
||||
|
||||
/**
|
||||
* Creates a new OutputStreamInterceptingFilter which selectively intercepts
|
||||
* "blob" and "end" instructions. The required "ack" responses will
|
||||
@@ -129,10 +137,22 @@ public class OutputStreamInterceptingFilter
|
||||
return null;
|
||||
}
|
||||
|
||||
// Attempt to write data to stream
|
||||
try {
|
||||
|
||||
// Attempt to write data to stream
|
||||
stream.getStream().write(blob);
|
||||
|
||||
// Force client to respond with their own "ack" if we need to
|
||||
// confirm that they are not falling behind with respect to the
|
||||
// graphical session
|
||||
if (!acknowledgeBlobs) {
|
||||
acknowledgeBlobs = true;
|
||||
return new GuacamoleInstruction("blob", index, "");
|
||||
}
|
||||
|
||||
// Otherwise, acknowledge the blob on the client's behalf
|
||||
sendAck(index, "OK", GuacamoleStatus.SUCCESS);
|
||||
|
||||
}
|
||||
catch (IOException e) {
|
||||
sendAck(index, "FAIL", GuacamoleStatus.SERVER_ERROR);
|
||||
@@ -164,6 +184,17 @@ public class OutputStreamInterceptingFilter
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a single "sync" instruction, updating internal tracking of
|
||||
* client render state.
|
||||
*
|
||||
* @param instruction
|
||||
* The "sync" instruction being handled.
|
||||
*/
|
||||
private void handleSync(GuacamoleInstruction instruction) {
|
||||
acknowledgeBlobs = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleInstruction filter(GuacamoleInstruction instruction)
|
||||
throws GuacamoleException {
|
||||
@@ -178,6 +209,13 @@ public class OutputStreamInterceptingFilter
|
||||
return instruction;
|
||||
}
|
||||
|
||||
// Monitor "sync" instructions to ensure the client does not starve
|
||||
// from lack of graphical updates
|
||||
if (instruction.getOpcode().equals("sync")) {
|
||||
handleSync(instruction);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
// Pass instruction through untouched
|
||||
return instruction;
|
||||
|
||||
|
@@ -215,6 +215,11 @@ angular.module('rest').factory('tunnelService', ['$injector',
|
||||
document.body.removeChild(iframe);
|
||||
};
|
||||
|
||||
// Acknowledge (and ignore) any received blobs
|
||||
stream.onblob = function acknowledgeData() {
|
||||
stream.sendAck('OK', Guacamole.Status.Code.SUCCESS);
|
||||
};
|
||||
|
||||
// Automatically remove iframe from DOM a few seconds after the stream
|
||||
// ends, in the browser does NOT fire the "load" event for downloads
|
||||
stream.onend = function downloadComplete() {
|
||||
|
Reference in New Issue
Block a user