Improved session recording support.
This commit is contained in:
parent
3b1ece80bd
commit
fd09bebebc
|
@ -1982,7 +1982,7 @@ function OnWebSocket(msg, s, head) {
|
|||
s.on('data', function (msg) {
|
||||
if (this.parent.tunneling == false) {
|
||||
msg = msg.toString();
|
||||
if (msg == 'c') {
|
||||
if ((msg == 'c') || (msg == 'cr')) {
|
||||
this.parent.tunneling = true; this.pipe(this.parent.tcp); this.parent.tcp.pipe(this); debug(1, 'Tunnel active');
|
||||
} else if ((msg.length > 6) && (msg.substring(0, 6) == 'error:')) {
|
||||
console.log(msg.substring(6));
|
||||
|
|
|
@ -1042,7 +1042,7 @@ function createMeshCore(agent)
|
|||
|
||||
if (this.httprequest.state == 0) {
|
||||
// Check if this is a relay connection
|
||||
if (data == 'c') { this.httprequest.state = 1; /*sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid);*/ }
|
||||
if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; /*sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid);*/ }
|
||||
} else {
|
||||
// Handle tunnel data
|
||||
if (this.httprequest.protocol == 0) { // 1 = Terminal, 2 = Desktop, 5 = Files, 6 = PowerShell
|
||||
|
|
|
@ -188,7 +188,7 @@ require('MeshAgent').AddCommandHandler(function (data)
|
|||
|
||||
if (this.httprequest.state == 0) {
|
||||
// Check if this is a relay connection
|
||||
if (data == 'c') { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
|
||||
if ((data == 'c') || (data == 'cr')) { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
|
||||
} else {
|
||||
// Handle tunnel data
|
||||
if (this.httprequest.protocol == 0)
|
||||
|
|
16
meshrelay.js
16
meshrelay.js
|
@ -188,8 +188,8 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
|||
var firstBlock = JSON.stringify({ magic: 'MeshCentralRelaySession', ver: 1, userid: sessionUser._id, username: sessionUser.name, sessionid: obj.id, ipaddr1: cleanRemoteAddr(ws._socket.remoteAddress), ipaddr2: cleanRemoteAddr(obj.peer.ws._socket.remoteAddress), time: new Date().toLocaleString(), protocol: req.query.p, nodeid: req.query.nodeid });
|
||||
recordingEntry(fd, 1, ((req.query.browser) ? 2 : 0), firstBlock, function () {
|
||||
relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false };
|
||||
ws.send('c'); // Send connect to both peers
|
||||
relayinfo.peer1.ws.send('c');
|
||||
ws.send('cr'); // Send connect to both peers, 'cr' indicates the session is being recorded.
|
||||
relayinfo.peer1.ws.send('cr');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -285,7 +285,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
|||
var peer = (relayinfo.peer1 == obj) ? relayinfo.peer2 : relayinfo.peer1;
|
||||
|
||||
// Close the recording file
|
||||
if (ws.logfile != null) { parent.parent.fs.close(ws.logfile.fd); ws.logfile = null; peer.ws.logfile = null; }
|
||||
if (ws.logfile != null) { recordingEntry(ws.logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd, tag) { parent.parent.fs.close(fd); tag.ws.logfile = null; tag.pws.logfile = null; }, { ws: ws, pws: peer.ws }); }
|
||||
|
||||
// Disconnect the peer
|
||||
try { if (peer.relaySessionCounted) { parent.relaySessionCount--; delete peer.relaySessionCounted; } } catch (ex) { console.log(ex); }
|
||||
|
@ -327,7 +327,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
|||
}
|
||||
|
||||
// Record a new entry in a recording log
|
||||
function recordingEntry(fd, type, flags, data, func) {
|
||||
function recordingEntry(fd, type, flags, data, func, tag) {
|
||||
try {
|
||||
if (typeof data == 'string') {
|
||||
// String write
|
||||
|
@ -337,7 +337,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
|||
header.writeInt32BE(blockData.length, 4); // Size
|
||||
header.writeIntBE(new Date(), 10, 6); // Time
|
||||
var block = Buffer.concat([header, blockData]);
|
||||
parent.parent.fs.write(fd, block, 0, block.length, func);
|
||||
parent.parent.fs.write(fd, block, 0, block.length, function () { func(fd, tag); });
|
||||
} else {
|
||||
// Binary write
|
||||
var header = Buffer.alloc(16); // Header: Type (2) + Flags (2) + Size(4) + Time(8)
|
||||
|
@ -346,9 +346,9 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
|||
header.writeInt32BE(data.length, 4); // Size
|
||||
header.writeIntBE(new Date(), 10, 6); // Time
|
||||
var block = Buffer.concat([header, data]);
|
||||
parent.parent.fs.write(fd, block, 0, block.length, func);
|
||||
parent.parent.fs.write(fd, block, 0, block.length, function () { func(fd, tag); });
|
||||
}
|
||||
} catch (ex) { console.log(ex); func(); }
|
||||
} catch (ex) { console.log(ex); func(fd, tag); }
|
||||
}
|
||||
|
||||
// Mark this relay session as authenticated if this is the user end.
|
||||
|
@ -418,7 +418,7 @@ The recording files are binary and contain a set of:
|
|||
|
||||
The header is always 16 bytes long and is encoded like this:
|
||||
|
||||
TYPE 2 bytes, 1 = Header, 2 = Network Data
|
||||
TYPE 2 bytes, 1 = Header, 2 = Network Data, 3 = EndBlock
|
||||
FLAGS 2 bytes, 0x0001 = Binary, 0x0002 = User
|
||||
SIZE 4 bytes, Size of the data following this header.
|
||||
TIME 8 bytes, Time this record was written, number of milliseconds since 1 January, 1970 UTC.
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -84,6 +84,7 @@
|
|||
var recFilePtr = 0;
|
||||
var recFileStartTime = 0;
|
||||
var recFileLastTime = 0;
|
||||
var recFileEndTime = 0;
|
||||
var recFileMetadata = null;
|
||||
var recFileProtocol = 0;
|
||||
var agentDesktop = null;
|
||||
|
@ -106,18 +107,24 @@
|
|||
}
|
||||
|
||||
function readNextBlock(func) {
|
||||
if ((recFilePtr + 16) > recFile.size) { func(-1); } else {
|
||||
if ((recFilePtr + 16) > recFile.size) { QS('progressbar').width = '100%'; func(-1); } else {
|
||||
var fr = new FileReader();
|
||||
fr.onload = function () {
|
||||
var type = ReadShort(this.result, 0);
|
||||
var flags = ReadShort(this.result, 2);
|
||||
var size = ReadInt(this.result, 4);
|
||||
var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
|
||||
if ((recFilePtr + 16 + size) > recFile.size) { func(-1); } else {
|
||||
if ((recFilePtr + 16 + size) > recFile.size) { QS('progressbar').width = '100%'; func(-1); } else {
|
||||
var fr2 = new FileReader();
|
||||
fr2.onload = function () {
|
||||
recFilePtr += (16 + size);
|
||||
QS('progressbar').width = Math.floor(100 * (recFilePtr / recFile.size)) + '%';
|
||||
if (recFileEndTime == 0) {
|
||||
// File pointer progress bar
|
||||
QS('progressbar').width = Math.floor(100 * (recFilePtr / recFile.size)) + '%';
|
||||
} else {
|
||||
// Time progress bar
|
||||
QS('progressbar').width = Math.floor(((recFileLastTime - recFileStartTime) / (recFileEndTime - recFileStartTime)) * 100) + '%';
|
||||
}
|
||||
func(type, flags, time, this.result);
|
||||
};
|
||||
fr2.readAsBinaryString(recFile.slice(recFilePtr + 16, recFilePtr + 16 + size));
|
||||
|
@ -127,6 +134,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
function readLastBlock(func) {
|
||||
if (recFile.size < 32) { func(-1); } else {
|
||||
var fr = new FileReader();
|
||||
fr.onload = function () {
|
||||
var type = ReadShort(this.result, 0);
|
||||
var flags = ReadShort(this.result, 2);
|
||||
var size = ReadInt(this.result, 4);
|
||||
var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12);
|
||||
if ((type == 3) && (size == 16) && (this.result.substring(16, 32) == 'MeshCentralMCREC')) { func(type, flags, time); } else { func(-1); }
|
||||
};
|
||||
fr.readAsBinaryString(recFile.slice(recFile.size - 32, recFile.size));
|
||||
}
|
||||
}
|
||||
|
||||
function addInfo(name, value) { if (value == null) return ''; return addInfoNoEsc(name, EscapeHtml(value)); }
|
||||
|
||||
function addInfoNoEsc(name, value) {
|
||||
|
@ -141,6 +162,7 @@
|
|||
if ((recFileMetadata == null) || (recFileMetadata.magic != 'MeshCentralRelaySession') || (recFileMetadata.ver != 1)) { cleanup(); return; }
|
||||
var x = '';
|
||||
x += addInfo('Time', recFileMetadata.time);
|
||||
if (recFileEndTime != 0) { var secs = Math.floor((recFileEndTime - time) / 1000); x += addInfo('Duration', secs + ' second' + ((secs > 1) ? 's' : '')); }
|
||||
x += addInfo('Username', recFileMetadata.username);
|
||||
x += addInfo('UserID', recFileMetadata.userid);
|
||||
x += addInfo('SessionID', recFileMetadata.sessionid);
|
||||
|
@ -178,6 +200,7 @@
|
|||
amtDesktop = CreateAmtRemoteDesktop('Desk');
|
||||
amtDesktop.onScreenSizeChange = deskAdjust;
|
||||
amtDesktop.State = 3;
|
||||
amtDesktop.Start();
|
||||
deskAdjust();
|
||||
}
|
||||
QV('metadatadiv', true);
|
||||
|
@ -213,15 +236,20 @@
|
|||
}
|
||||
|
||||
if ((type == 2) && flagBinary && !flagUser) {
|
||||
// Device --> User data
|
||||
if (recFileProtocol == 2) {
|
||||
// MeshCentral Remote Desktop
|
||||
agentDesktop.ProcessData(data);
|
||||
} else if (recFileProtocol == 101) {
|
||||
// Intel AMT KVM
|
||||
//if ((readState == 0) && (rstr2hex(data) == '140000000400000000')) { readState = 1; }
|
||||
if ((readState == 0) && (rstr2hex(data) == '4100000000000000')) { readState = 1; }
|
||||
if ((readState == 0) && (rstr2hex(data) == '4100000000000000')) { readState = 1; } // We are not authenticated, KVM data starts here.
|
||||
else if (readState == 1) { amtDesktop.ProcessData(data); }
|
||||
//console.log(rstr2hex(data));
|
||||
}
|
||||
} else if ((type == 2) && flagBinary && flagUser) {
|
||||
// User --> Device data
|
||||
if (recFileProtocol == 101) {
|
||||
// Intel AMT KVM
|
||||
if (rstr2hex(data) == '0000000008080001000700070003050200000000') { amtDesktop.bpp = 1; } // Switch to 1 byte per pixel.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,6 +266,7 @@
|
|||
readState = 0;
|
||||
waitTimerArgs = null;
|
||||
currentDeltaTimeTotalSec = 0;
|
||||
recFileEndTime = 0;
|
||||
if (waitTimer != null) { clearTimeout(waitTimer); waitTimer = null; }
|
||||
QH('deskstatus', '');
|
||||
QE('PlayButton', false);
|
||||
|
@ -267,6 +296,7 @@
|
|||
recFile = files[0];
|
||||
recFilePtr = 0;
|
||||
readNextBlock(processFirstBlock);
|
||||
readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
|
||||
}
|
||||
|
||||
var dragtimer = null;
|
||||
|
@ -309,6 +339,7 @@
|
|||
recFile = files[0];
|
||||
recFilePtr = 0;
|
||||
readNextBlock(processFirstBlock);
|
||||
readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } });
|
||||
Q('OpenFileButton').blur();
|
||||
}
|
||||
|
||||
|
@ -358,13 +389,18 @@
|
|||
QE('RestartButton', false);
|
||||
QS('progressbar').width = '0px';
|
||||
QH('timespan', '00:00:00');
|
||||
if (agentDesktop) { agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height); }
|
||||
if (amtDesktop) { amtDesktop.canvas.clearRect(0, 0, amtDesktop.CanvasId.width, amtDesktop.CanvasId.height); amtDesktop = CreateAmtRemoteDesktop('Desk'); amtDesktop.onScreenSizeChange = deskAdjust; amtDesktop.State = 3; }
|
||||
if (agentDesktop) {
|
||||
agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height);
|
||||
} else if (amtDesktop) {
|
||||
amtDesktop.canvas.clearRect(0, 0, amtDesktop.CanvasId.width, amtDesktop.CanvasId.height);
|
||||
amtDesktop = CreateAmtRemoteDesktop('Desk');
|
||||
amtDesktop.onScreenSizeChange = deskAdjust;
|
||||
amtDesktop.State = 3;
|
||||
amtDesktop.Start();
|
||||
}
|
||||
}
|
||||
|
||||
function clearConsoleMsg() {
|
||||
console.log('clearConsoleMsg');
|
||||
}
|
||||
function clearConsoleMsg() { QH('p11DeskConsoleMsg', ''); }
|
||||
|
||||
// Toggle the web page to full screen
|
||||
function toggleAspectRatio(toggle) {
|
||||
|
@ -404,9 +440,9 @@
|
|||
} else {
|
||||
var wNew = ((deskW * parentH) / deskH) + 'px';
|
||||
//if (webPageFullScreen || fullscreen) {
|
||||
//QS('Desk').height = null;
|
||||
//QS('Desk').height = null;
|
||||
//} else {
|
||||
QS('Desk').height = '100%';
|
||||
QS('Desk').height = '100%';
|
||||
//}
|
||||
QS('Desk').width = wNew;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
|
|||
obj.webchannel = null;
|
||||
obj.webrtc = null;
|
||||
obj.debugmode = 0;
|
||||
obj.serverIsRecording = false;
|
||||
if (domainUrl == null) { domainUrl = '/'; }
|
||||
|
||||
// Console Message
|
||||
|
@ -95,7 +96,8 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort, au
|
|||
obj.xxOnMessage = function (e) {
|
||||
//console.log('Recv', e.data, e.data.byteLength, obj.State);
|
||||
if (obj.State < 3) {
|
||||
if (e.data == 'c') {
|
||||
if ((e.data == 'c') || (e.data == 'cr')) {
|
||||
if (e.data == 'cr') { obj.serverIsRecording = true; }
|
||||
try { obj.socket.send(obj.protocol); } catch (ex) { }
|
||||
obj.xxStateChange(3);
|
||||
|
||||
|
|
|
@ -245,6 +245,11 @@ var CreateAmtRedirect = function (module, authCookie) {
|
|||
if (obj.amtaccumulator.length > 8) { obj.m.ProcessData(obj.amtaccumulator.substring(8)); }
|
||||
cmdsize = obj.amtaccumulator.length;
|
||||
break;
|
||||
case 0xF0:
|
||||
// console.log('Session is being recorded');
|
||||
obj.serverIsRecording = true;
|
||||
cmdsize = 1;
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown Intel AMT command: " + obj.amtaccumulator.charCodeAt(0) + " acclen=" + obj.amtaccumulator.length);
|
||||
obj.Stop(4);
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -443,6 +443,7 @@
|
|||
<div class='deskareaicon' title="Toggle View Mode" onclick="toggleAspectRatio(1)">⇲</div>
|
||||
<div class='deskareaicon' title="Rotate Left" onclick="drotate(-1)">↺</div>
|
||||
<div class='deskareaicon' title="Rotate Right" onclick="drotate(1)">↻</div>
|
||||
<div id="deskRecordIcon" class='deskareaicon' title="Server is recording this session" style="display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px"></div>
|
||||
<input id="deskFocusBtn" type="button" title="Toggle focus mode, when active only the region around the mouse is updated" onkeypress="return false" onkeydown="return false" value="Focus All" onclick="deskToggleFocus()" style="margin-right:3px;display:none">
|
||||
<input id="deskSaveBtn" type="button" title="Save a screenshot of the remote desktop" onkeypress="return false" onkeydown="return false" value="Save..." onclick=deskSaveImage() class="mR">
|
||||
<input id="deskActionsBtn" type=button title="Perform power actions on the device" onkeypress="return false" onkeydown="return false" value=Actions onclick=deviceActionFunction() class="mR" />
|
||||
|
@ -541,6 +542,7 @@
|
|||
<tr>
|
||||
<td class="areaHead">
|
||||
<div class="toright2">
|
||||
<div id="termRecordIcon" class='deskareaicon' title="Server is recording this session" style="display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px"></div>
|
||||
<input id="termActionsBtn" type=button title="Perform power actions on the device" onkeypress="return false" onkeydown="return false" value=Actions onclick=deviceActionFunction() />
|
||||
</div>
|
||||
<div>
|
||||
|
@ -600,6 +602,7 @@
|
|||
<td class="areaHead">
|
||||
<div class="toright2">
|
||||
<input id="filesActionsBtn" type=button title="Perform power actions on the device" value=Actions onclick=deviceActionFunction() />
|
||||
<div id="filesRecordIcon" class='deskareaicon' title="Server is recording this session" style="display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px"></div>
|
||||
</div>
|
||||
<div>
|
||||
<input id=p13AutoConnect value="AutoConnect" onclick=autoConnectFiles(event) type="button" style="display:none">
|
||||
|
@ -4816,6 +4819,7 @@
|
|||
desktopNode = desktop = null;
|
||||
QV('DeskFocus', false);
|
||||
QV('termdisplays', false);
|
||||
QV('deskRecordIcon', false);
|
||||
deskFocusBtn.value = 'All Focus';
|
||||
if (fullscreen == true) { deskToggleFull(); }
|
||||
webRtcDesktopReset();
|
||||
|
@ -4823,6 +4827,9 @@
|
|||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
if (desktop.serverIsRecording == true) { QV('deskRecordIcon', true); }
|
||||
break;
|
||||
default:
|
||||
//console.log('Unknown onDesktopStateChange state', state);
|
||||
break;
|
||||
|
@ -5380,12 +5387,14 @@
|
|||
// Disconnected, clear the terminal
|
||||
QE('termSizeList', true);
|
||||
QH('termtitle', '');
|
||||
QV('termRecordIcon', false);
|
||||
xterminal.m.TermResetScreen();
|
||||
xterminal.m.TermDraw();
|
||||
if (terminal != null) { terminal.Stop(); terminal = null; }
|
||||
break;
|
||||
case 3:
|
||||
QE('termSizeList', false);
|
||||
if (xterminal.serverIsRecording == true) { QV('termRecordIcon', true); }
|
||||
break;
|
||||
default:
|
||||
QE('termSizeList', false);
|
||||
|
@ -5531,12 +5540,14 @@
|
|||
p13filetreelocation = [];
|
||||
QH('p13currentpath', '');
|
||||
QE('p13FolderUp', false);
|
||||
QV('filesRecordIcon', false);
|
||||
p13setActions();
|
||||
if (files != null) { files.Stop(); files = null; }
|
||||
break;
|
||||
case 3:
|
||||
p13targetpath = '';
|
||||
files.sendText({ action: 'ls', reqid: 1, path: '' });
|
||||
if (files.serverIsRecording == true) { QV('filesRecordIcon', true); }
|
||||
break;
|
||||
default:
|
||||
//console.log('Unknown onFilesStateChange state', state);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -579,7 +579,7 @@
|
|||
socket.onerror = function (e) { /*console.error(e);*/ }
|
||||
socket.onclose = function () { disconnect(); }
|
||||
socket.onmessage = function (msg) {
|
||||
if ((state < 2) && (typeof msg.data == 'string') && (msg.data == 'c')) {
|
||||
if ((state < 2) && (typeof msg.data == 'string') && ((msg.data == 'c') || (msg.data == 'cr'))) {
|
||||
hangUpButtonClick(0, true);
|
||||
hangUpButtonClick(1, true);
|
||||
hangUpButtonClick(2, true);
|
||||
|
|
37
webserver.js
37
webserver.js
|
@ -1978,6 +1978,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
var firstBlock = JSON.stringify({ magic: 'MeshCentralRelaySession', ver: 1, userid: user._id, username: user.name, ipaddr: cleanRemoteAddr(ws._socket.remoteAddress), nodeid: node._id, intelamt: true, protocol: (req.query.p == 2) ? 101 : 100, time: new Date().toLocaleString() })
|
||||
recordingEntry(fd, 1, 0, firstBlock, function () { });
|
||||
ws.logfile = { fd: fd, lock: false };
|
||||
if (req.query.p == 2) { ws.send(Buffer.from(String.fromCharCode(0xF0), 'binary')); } // Intel AMT Redirection: Indicate the session is being recorded
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2073,7 +2074,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (ws.forwardclient && ws.forwardclient.close) { ws.forwardclient.close(); } // TODO: If TLS is used, we need to close the socket that is wrapped by TLS
|
||||
|
||||
// Close the recording file
|
||||
if (ws.logfile != null) { obj.fs.close(ws.logfile.fd); ws.logfile = null; }
|
||||
if (ws.logfile != null) {
|
||||
recordingEntry(ws.logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd, ws) {
|
||||
obj.fs.close(fd);
|
||||
ws.logfile = null;
|
||||
}, ws);
|
||||
}
|
||||
});
|
||||
|
||||
// If the web socket is closed, close the associated TCP connection.
|
||||
|
@ -2082,7 +2088,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (ws.forwardclient && ws.forwardclient.close) { ws.forwardclient.close(); } // TODO: If TLS is used, we need to close the socket that is wrapped by TLS
|
||||
|
||||
// Close the recording file
|
||||
if (ws.logfile != null) { obj.fs.close(ws.logfile.fd); ws.logfile = null; }
|
||||
if (ws.logfile != null) {
|
||||
recordingEntry(ws.logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd, ws) {
|
||||
obj.fs.close(fd);
|
||||
ws.logfile = null;
|
||||
}, ws);
|
||||
}
|
||||
});
|
||||
|
||||
ws.forwardclient.onStateChange = function (ciraconn, state) {
|
||||
|
@ -2156,7 +2167,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (ws.forwardclient) { try { ws.forwardclient.destroy(); } catch (e) { } }
|
||||
|
||||
// Close the recording file
|
||||
if (ws.logfile != null) { obj.fs.close(ws.logfile.fd); ws.logfile = null; }
|
||||
if (ws.logfile != null) {
|
||||
recordingEntry(ws.logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd) {
|
||||
obj.fs.close(fd);
|
||||
ws.logfile = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// If the web socket is closed, close the associated TCP connection.
|
||||
|
@ -2165,7 +2181,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (ws.forwardclient) { try { ws.forwardclient.destroy(); } catch (e) { } }
|
||||
|
||||
// Close the recording file
|
||||
if (ws.logfile != null) { obj.fs.close(ws.logfile.fd); ws.logfile = null; }
|
||||
if (ws.logfile != null) {
|
||||
recordingEntry(ws.logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd) {
|
||||
obj.fs.close(fd);
|
||||
ws.logfile = null;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Compute target port
|
||||
|
@ -3467,7 +3488,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
function cleanRemoteAddr(addr) { if (addr.startsWith('::ffff:')) { return addr.substring(7); } else { return addr; } }
|
||||
|
||||
// Record a new entry in a recording log
|
||||
function recordingEntry(fd, type, flags, data, func) {
|
||||
function recordingEntry(fd, type, flags, data, func, tag) {
|
||||
try {
|
||||
if (typeof data == 'string') {
|
||||
// String write
|
||||
|
@ -3477,7 +3498,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
header.writeInt32BE(blockData.length, 4); // Size
|
||||
header.writeIntBE(new Date(), 10, 6); // Time
|
||||
var block = Buffer.concat([header, blockData]);
|
||||
obj.fs.write(fd, block, 0, block.length, func);
|
||||
obj.fs.write(fd, block, 0, block.length, function () { func(fd, tag); });
|
||||
} else {
|
||||
// Binary write
|
||||
var header = Buffer.alloc(16); // Header: Type (2) + Flags (2) + Size(4) + Time(8)
|
||||
|
@ -3486,9 +3507,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
header.writeInt32BE(data.length, 4); // Size
|
||||
header.writeIntBE(new Date(), 10, 6); // Time
|
||||
var block = Buffer.concat([header, data]);
|
||||
obj.fs.write(fd, block, 0, block.length, func);
|
||||
obj.fs.write(fd, block, 0, block.length, function () { func(fd, tag); });
|
||||
}
|
||||
} catch (ex) { console.log(ex); func(); }
|
||||
} catch (ex) { console.log(ex); func(fd, tag); }
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
|
Loading…
Reference in New Issue