mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +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 =
|
private static final Logger logger =
|
||||||
LoggerFactory.getLogger(OutputStreamInterceptingFilter.class);
|
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
|
* Creates a new OutputStreamInterceptingFilter which selectively intercepts
|
||||||
* "blob" and "end" instructions. The required "ack" responses will
|
* "blob" and "end" instructions. The required "ack" responses will
|
||||||
@@ -129,10 +137,22 @@ public class OutputStreamInterceptingFilter
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to write data to stream
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// Attempt to write data to stream
|
||||||
stream.getStream().write(blob);
|
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);
|
sendAck(index, "OK", GuacamoleStatus.SUCCESS);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
sendAck(index, "FAIL", GuacamoleStatus.SERVER_ERROR);
|
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
|
@Override
|
||||||
public GuacamoleInstruction filter(GuacamoleInstruction instruction)
|
public GuacamoleInstruction filter(GuacamoleInstruction instruction)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
@@ -178,6 +209,13 @@ public class OutputStreamInterceptingFilter
|
|||||||
return instruction;
|
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
|
// Pass instruction through untouched
|
||||||
return instruction;
|
return instruction;
|
||||||
|
|
||||||
|
@@ -215,6 +215,11 @@ angular.module('rest').factory('tunnelService', ['$injector',
|
|||||||
document.body.removeChild(iframe);
|
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
|
// Automatically remove iframe from DOM a few seconds after the stream
|
||||||
// ends, in the browser does NOT fire the "load" event for downloads
|
// ends, in the browser does NOT fire the "load" event for downloads
|
||||||
stream.onend = function downloadComplete() {
|
stream.onend = function downloadComplete() {
|
||||||
|
Reference in New Issue
Block a user