GUACAMOLE-2043: Fix playback of recordings which have multibyte character instructions. #1066
+51
−8
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
At first I considered to unite and refactor
Guacamole.SessionRecording.loadInstruction
andfunction handleInstruction(opcode, args)
. My idea was to get rid ofGuacamole.SessionRecording.getElementSize
. Unfortunately, most likely it will not allow us to fix the issue isolated because the recording can be received as a blob or via a tunnel.loadInstruction
/getElementSize
are used for both cases and throughGucamole.Parser
. There would be too many changes with a chance of new bugs affecting not just the playback.So to fix the issue isolated, I simply calculate UTF8 string byte size for every instruction content. Performance benchmarks show that a custom implementation of such a function works better than TextEncoder and Blob API. For example, a benchmark. Also, a StackOverflow topic there one of the answers provides benchmarks.
In my tests, a 10Mb recording is preprocessed for about 3 seconds. Byte size calculation of instructions (UTF8 strings) takes about 1-2% of the time. Overall, I did not see significant time difference in preprocessing with or without that byte size calculation. On the other hand, the preprocessing time includes everything including delays to download the content, etc. I could not measure pure parsing time with/without the byte size calculation due to the async function workflow. A single instruction processing takes less than 1 ms. So you cannot measure all instructions separately and then just sum. It will still be 0.
Another option would be to limit byte size calculation for some instructions only. For example,
var getElementSize = function getElementSize(value, unicode) {
var valueLength = value.length;
var protocolSize = (unicode ? getUtf8StringByteSize(value) : valueLength) + 3;
...
and
frameEnd += getElementSize(args[i], opcode === 'name');