From 22014f82b35d6746df189115d4fb33a10886a90e Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Mon, 13 Dec 2021 15:18:53 -0800 Subject: [PATCH] Improved playback of terminal sessions, #3336 --- views/player.handlebars | 57 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/views/player.handlebars b/views/player.handlebars index bc6c1d1f..fb8e792c 100644 --- a/views/player.handlebars +++ b/views/player.handlebars @@ -8,6 +8,7 @@ + @@ -17,6 +18,8 @@ + + @@ -43,6 +46,8 @@ +
@@ -115,6 +120,7 @@ var browser = null; var domainUrl = '{{{domainurl}}}'; var urlargs; + var term = null; // Streaming values var ws = null; @@ -414,6 +420,7 @@ } QV('DeskParent', true); QV('TermParent', false); + QV('XTermParent', false); QV('ConvertAsWebM', false); if (recFileMetadata.protocol == 1) { // MeshCentral remote terminal @@ -526,11 +533,21 @@ videoWriterCurrentFrame = time; } + // MeshCentral Terminal options + if ((type == 2) && !flagBinary && flagUser && (data.length > 2) && (data[0] == '{')) { + var parsed = null; + try { parsed = JSON.parse(data); } catch (ex) { } + if ((parsed != null) && ((parsed.type == 'options') || (parsed.type == 'termsize')) && (typeof parsed.cols == 'number') && (typeof parsed.rows == 'number')) { + term.resize(parsed.cols, parsed.rows); + //console.log('termsize', parsed.cols, parsed.rows); + } + } + if ((type == 2) && flagBinary && !flagUser) { // Device --> User data if (recFileProtocol == 1) { // MeshCentral Terminal - agentTerminal.ProcessData(data); + writeXTerm(data); } else if (recFileProtocol == 2) { // MeshCentral Remote Desktop var view = new Uint8Array(data.length); @@ -582,6 +599,7 @@ } function cleanup() { + clearXTerm(); recFile = null; recFilePtr = 0; recFileMetadata = null; @@ -610,6 +628,7 @@ } QV('DeskParent', true); QV('TermParent', false); + QV('XTermParent', false); } function ondrop(e) { @@ -740,6 +759,7 @@ function togglePause() { if (xxdialogMode) return; + if (term != null) return; if (recFile != null) { if (playing == true) { pause(); } else { if (recFilePtr != recFile.size) { play(); } } } return false; } @@ -752,11 +772,13 @@ QE('PlayButton', false); QE('PauseButton', true); QE('RestartButton', false); - if ((recFileProtocol == 1) && (agentTerminal == null)) { + if ((recFileProtocol == 1) && (term == null)) { QV('DeskParent', false); - QV('TermParent', true); - agentTerminal = CreateAmtRemoteTerminal('Term', {}); - agentTerminal.State = 3; + QV('TermParent', false); + QV('XTermParent', true); + setupXTerm(); + //agentTerminal = CreateAmtRemoteTerminal('Term', {}); + //agentTerminal.State = 3; } readNextBlock(processBlock); } @@ -792,6 +814,8 @@ QH('timespan', '00:00:00'); QV('DeskParent', true); QV('TermParent', false); + QV('XTermParent', false); + clearXTerm(); if (agentDesktop) { agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height); } else if (amtDesktop) { @@ -1045,6 +1069,29 @@ return chars; } + function setupXTerm() { + // Setup the terminal + if (term != null) { term.dispose(); } + term = new Terminal(); + term.open(Q('XTermParent')); + term.onData(function (data) { if (tunnel != null) { tunnel.sendText(data); } }) + term.resize(80, 25); + //term.setOption('convertEol', true); // Consider \n to be \r\n, this should be taken care of by "termios" + } + + function clearXTerm() { + if (term != null) { term.dispose(); term = null; } + } + + function writeXTerm(data) { + if (term == null) return; + if (typeof data == 'string') { + term.writeUtf8(data); + } else { + term.writeUtf8(new Uint8Array(data)); + } + } + start();