livedesk 0.1.122 → 0.1.124
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/hub/src/remote-hub.js +78 -0
- package/package.json +2 -2
package/hub/src/remote-hub.js
CHANGED
|
@@ -31,6 +31,8 @@ const REMOTE_FRAME_PROTOCOL = 'mindexec.remote.frame.v2';
|
|
|
31
31
|
const REMOTE_FRAME_PROTOCOL_VERSION = 2;
|
|
32
32
|
const REMOTE_FRAME_HANDSHAKE = 'smartview-request-open-frame';
|
|
33
33
|
const DEFAULT_REMOTE_FRAME_MODE = 'mode1-jpeg';
|
|
34
|
+
const TCP_BINARY_FRAME_MAGIC = Buffer.from('LDFB', 'ascii');
|
|
35
|
+
const TCP_BINARY_FRAME_HEADER_BYTES = 12;
|
|
34
36
|
const REMOTE_FRAME_MODE_PROFILES = Object.freeze({
|
|
35
37
|
thumbnail: Object.freeze({
|
|
36
38
|
mode: 'thumbnail',
|
|
@@ -1003,6 +1005,59 @@ function parseRemoteHubWebSocketBinaryFrame(buffer) {
|
|
|
1003
1005
|
return { header, payload };
|
|
1004
1006
|
}
|
|
1005
1007
|
|
|
1008
|
+
function hasTcpBinaryFrameMagicPrefix(buffer) {
|
|
1009
|
+
if (!Buffer.isBuffer(buffer) || buffer.length <= 0 || buffer.length > TCP_BINARY_FRAME_MAGIC.length) {
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
for (let index = 0; index < buffer.length; index += 1) {
|
|
1014
|
+
if (buffer[index] !== TCP_BINARY_FRAME_MAGIC[index]) {
|
|
1015
|
+
return false;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
return true;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
function startsWithTcpBinaryFrameMagic(buffer) {
|
|
1022
|
+
return Buffer.isBuffer(buffer)
|
|
1023
|
+
&& buffer.length >= TCP_BINARY_FRAME_MAGIC.length
|
|
1024
|
+
&& buffer.subarray(0, TCP_BINARY_FRAME_MAGIC.length).equals(TCP_BINARY_FRAME_MAGIC);
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
function parseTcpBinaryFramePacket(buffer) {
|
|
1028
|
+
if (!Buffer.isBuffer(buffer) || buffer.length < TCP_BINARY_FRAME_HEADER_BYTES) {
|
|
1029
|
+
return { incomplete: true };
|
|
1030
|
+
}
|
|
1031
|
+
if (!startsWithTcpBinaryFrameMagic(buffer)) {
|
|
1032
|
+
return null;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
const metaLength = buffer.readUInt32BE(4);
|
|
1036
|
+
const payloadLength = buffer.readUInt32BE(8);
|
|
1037
|
+
const maxPayloadBytes = Math.max(MAX_THUMBNAIL_BINARY_BYTES, MAX_STREAM_BINARY_BYTES, MAX_AUDIO_BINARY_BYTES);
|
|
1038
|
+
if (!Number.isFinite(metaLength)
|
|
1039
|
+
|| !Number.isFinite(payloadLength)
|
|
1040
|
+
|| metaLength <= 0
|
|
1041
|
+
|| metaLength > 64 * 1024
|
|
1042
|
+
|| payloadLength <= 0
|
|
1043
|
+
|| payloadLength > maxPayloadBytes) {
|
|
1044
|
+
return { invalid: true, reason: 'invalid-tcp-binary-frame-size' };
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
const packetLength = TCP_BINARY_FRAME_HEADER_BYTES + metaLength + payloadLength;
|
|
1048
|
+
if (buffer.length < packetLength) {
|
|
1049
|
+
return { incomplete: true };
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
try {
|
|
1053
|
+
const header = JSON.parse(buffer.subarray(TCP_BINARY_FRAME_HEADER_BYTES, TCP_BINARY_FRAME_HEADER_BYTES + metaLength).toString('utf8'));
|
|
1054
|
+
const payload = buffer.subarray(TCP_BINARY_FRAME_HEADER_BYTES + metaLength, packetLength);
|
|
1055
|
+
return { header, payload, packetLength };
|
|
1056
|
+
} catch (err) {
|
|
1057
|
+
return { invalid: true, reason: err?.message || 'invalid-tcp-binary-frame-header' };
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1006
1061
|
class RemoteHubWebSocketAgentSocket {
|
|
1007
1062
|
constructor(socket) {
|
|
1008
1063
|
this.__remoteHubWebSocket = true;
|
|
@@ -3563,6 +3618,29 @@ export function createRemoteHub(options = {}) {
|
|
|
3563
3618
|
continue;
|
|
3564
3619
|
}
|
|
3565
3620
|
|
|
3621
|
+
if (state.authenticated && state.frameOnly && state.buffer.length > 0) {
|
|
3622
|
+
if (state.buffer.length < TCP_BINARY_FRAME_MAGIC.length && hasTcpBinaryFrameMagicPrefix(state.buffer)) {
|
|
3623
|
+
return;
|
|
3624
|
+
}
|
|
3625
|
+
|
|
3626
|
+
if (startsWithTcpBinaryFrameMagic(state.buffer)) {
|
|
3627
|
+
const packet = parseTcpBinaryFramePacket(state.buffer);
|
|
3628
|
+
if (packet?.incomplete) {
|
|
3629
|
+
return;
|
|
3630
|
+
}
|
|
3631
|
+
if (!packet || packet.invalid) {
|
|
3632
|
+
writeJsonLine(socket, { type: 'error', error: 'invalid-tcp-binary-frame' });
|
|
3633
|
+
logWarn('remote', `invalid tcp binary frame from agent: ${packet?.reason || 'bad-magic'}`);
|
|
3634
|
+
socket.destroy();
|
|
3635
|
+
return;
|
|
3636
|
+
}
|
|
3637
|
+
|
|
3638
|
+
state.buffer = state.buffer.subarray(packet.packetLength);
|
|
3639
|
+
enqueueAgentBinaryFrame(socket, state, packet.header, packet.payload);
|
|
3640
|
+
continue;
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
|
|
3566
3644
|
const newlineIndex = state.buffer.indexOf(0x0a);
|
|
3567
3645
|
if (newlineIndex < 0) {
|
|
3568
3646
|
if (state.buffer.length > MAX_LINE_CHARS) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livedesk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.124",
|
|
4
4
|
"description": "LiveDesk Hub and client launcher",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"node": ">=20"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@livedesk/client": "0.1.
|
|
33
|
+
"@livedesk/client": "0.1.86",
|
|
34
34
|
"cors": "^2.8.5",
|
|
35
35
|
"express": "^4.21.2",
|
|
36
36
|
"ws": "^8.18.3"
|