livedesk 0.1.118 → 0.1.120
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
CHANGED
|
@@ -122,6 +122,8 @@ const DEFAULT_PUBLIC_IP_TIMEOUT_MS = 1800;
|
|
|
122
122
|
const DUPLICATE_DEVICE_ACTIVE_REJECT_MS = 15000;
|
|
123
123
|
const DUPLICATE_DEVICE_LOG_THROTTLE_MS = 60000;
|
|
124
124
|
const DUPLICATE_DEVICE_RETRY_AFTER_MS = 30000;
|
|
125
|
+
const AGENT_BINARY_INGRESS_QUEUE_PACKETS = 18;
|
|
126
|
+
const AGENT_BINARY_INGRESS_DRAIN_BUDGET_PACKETS = 64;
|
|
125
127
|
const SYNTHETIC_FRAME_DATA_URL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAYAAAD0In+KAAAADElEQVR42mP8z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC';
|
|
126
128
|
const SYNTHETIC_FRAME_PAYLOAD = Buffer.from(SYNTHETIC_FRAME_DATA_URL.split(',')[1], 'base64');
|
|
127
129
|
const SYNTHETIC_FRAME_HASH = crypto.createHash('sha256').update(SYNTHETIC_FRAME_PAYLOAD).digest('hex').slice(0, 16);
|
|
@@ -3178,6 +3180,64 @@ export function createRemoteHub(options = {}) {
|
|
|
3178
3180
|
});
|
|
3179
3181
|
}
|
|
3180
3182
|
|
|
3183
|
+
function dropQueuedAgentBinaryFrame(state) {
|
|
3184
|
+
if (!Array.isArray(state.binaryQueue) || state.binaryQueue.length === 0) {
|
|
3185
|
+
return;
|
|
3186
|
+
}
|
|
3187
|
+
const deltaIndex = state.binaryQueue.findIndex(item => {
|
|
3188
|
+
const header = item?.header || {};
|
|
3189
|
+
const frameKind = safeString(header.frameKind || header.kind || header.frameType || '', 40).toLowerCase();
|
|
3190
|
+
const chunkType = safeString(header.chunkType, 20).toLowerCase();
|
|
3191
|
+
return (frameKind === 'stream' || frameKind === 'live' || header.type === 'stream.binary')
|
|
3192
|
+
&& header.isKeyFrame !== true
|
|
3193
|
+
&& chunkType !== 'key';
|
|
3194
|
+
});
|
|
3195
|
+
const index = deltaIndex >= 0 ? deltaIndex : 0;
|
|
3196
|
+
state.binaryQueue.splice(index, 1);
|
|
3197
|
+
state.binaryQueueDrops = Number(state.binaryQueueDrops || 0) + 1;
|
|
3198
|
+
}
|
|
3199
|
+
|
|
3200
|
+
function drainQueuedAgentBinaryFrames(socket, state) {
|
|
3201
|
+
if (state.binaryQueueDraining || state.closed) {
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
state.binaryQueueDraining = true;
|
|
3205
|
+
setImmediate(() => {
|
|
3206
|
+
state.binaryQueueDraining = false;
|
|
3207
|
+
if (state.closed || socket.destroyed) {
|
|
3208
|
+
state.binaryQueue.length = 0;
|
|
3209
|
+
return;
|
|
3210
|
+
}
|
|
3211
|
+
|
|
3212
|
+
let processed = 0;
|
|
3213
|
+
while (state.binaryQueue.length > 0 && processed < AGENT_BINARY_INGRESS_DRAIN_BUDGET_PACKETS) {
|
|
3214
|
+
const item = state.binaryQueue.shift();
|
|
3215
|
+
if (item) {
|
|
3216
|
+
handleAgentBinaryFrame(socket, state, item.header, item.payload);
|
|
3217
|
+
processed += 1;
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
if (state.binaryQueue.length > 0 && !state.closed && !socket.destroyed) {
|
|
3222
|
+
drainQueuedAgentBinaryFrames(socket, state);
|
|
3223
|
+
}
|
|
3224
|
+
});
|
|
3225
|
+
}
|
|
3226
|
+
|
|
3227
|
+
function enqueueAgentBinaryFrame(socket, state, header, payload) {
|
|
3228
|
+
if (state.closed || socket.destroyed) {
|
|
3229
|
+
return;
|
|
3230
|
+
}
|
|
3231
|
+
if (!Array.isArray(state.binaryQueue)) {
|
|
3232
|
+
state.binaryQueue = [];
|
|
3233
|
+
}
|
|
3234
|
+
while (state.binaryQueue.length >= AGENT_BINARY_INGRESS_QUEUE_PACKETS) {
|
|
3235
|
+
dropQueuedAgentBinaryFrame(state);
|
|
3236
|
+
}
|
|
3237
|
+
state.binaryQueue.push({ header, payload });
|
|
3238
|
+
drainQueuedAgentBinaryFrames(socket, state);
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3181
3241
|
function handleAgentMessage(socket, state, message) {
|
|
3182
3242
|
if (!message || typeof message !== 'object') {
|
|
3183
3243
|
return;
|
|
@@ -3318,7 +3378,11 @@ export function createRemoteHub(options = {}) {
|
|
|
3318
3378
|
authenticated: false,
|
|
3319
3379
|
device: null,
|
|
3320
3380
|
inputOnly: false,
|
|
3321
|
-
frameOnly: false
|
|
3381
|
+
frameOnly: false,
|
|
3382
|
+
binaryQueue: [],
|
|
3383
|
+
binaryQueueDraining: false,
|
|
3384
|
+
binaryQueueDrops: 0,
|
|
3385
|
+
closed: false
|
|
3322
3386
|
};
|
|
3323
3387
|
|
|
3324
3388
|
const helloTimer = setTimeout(() => {
|
|
@@ -3359,7 +3423,7 @@ export function createRemoteHub(options = {}) {
|
|
|
3359
3423
|
return;
|
|
3360
3424
|
}
|
|
3361
3425
|
|
|
3362
|
-
|
|
3426
|
+
enqueueAgentBinaryFrame(socket, state, packet.header, packet.payload);
|
|
3363
3427
|
} catch (err) {
|
|
3364
3428
|
writeJsonLine(socket, { type: 'error', error: 'invalid-websocket-binary-frame' });
|
|
3365
3429
|
logWarn('remote', `invalid websocket binary frame: ${err?.message || err}`);
|
|
@@ -3367,6 +3431,8 @@ export function createRemoteHub(options = {}) {
|
|
|
3367
3431
|
};
|
|
3368
3432
|
|
|
3369
3433
|
const detach = reason => {
|
|
3434
|
+
state.closed = true;
|
|
3435
|
+
state.binaryQueue.length = 0;
|
|
3370
3436
|
allSockets.delete(socket);
|
|
3371
3437
|
clearTimeout(helloTimer);
|
|
3372
3438
|
detachInputSocket(socket, reason);
|
|
@@ -3461,8 +3527,13 @@ export function createRemoteHub(options = {}) {
|
|
|
3461
3527
|
authenticated: false,
|
|
3462
3528
|
device: null,
|
|
3463
3529
|
inputOnly: false,
|
|
3530
|
+
frameOnly: false,
|
|
3464
3531
|
buffer: Buffer.alloc(0),
|
|
3465
|
-
pendingBinaryFrame: null
|
|
3532
|
+
pendingBinaryFrame: null,
|
|
3533
|
+
binaryQueue: [],
|
|
3534
|
+
binaryQueueDraining: false,
|
|
3535
|
+
binaryQueueDrops: 0,
|
|
3536
|
+
closed: false
|
|
3466
3537
|
};
|
|
3467
3538
|
|
|
3468
3539
|
const helloTimer = setTimeout(() => {
|
|
@@ -3488,7 +3559,7 @@ export function createRemoteHub(options = {}) {
|
|
|
3488
3559
|
const framePayload = state.buffer.subarray(0, byteLength);
|
|
3489
3560
|
state.buffer = state.buffer.subarray(byteLength);
|
|
3490
3561
|
state.pendingBinaryFrame = null;
|
|
3491
|
-
|
|
3562
|
+
enqueueAgentBinaryFrame(socket, state, header, framePayload);
|
|
3492
3563
|
continue;
|
|
3493
3564
|
}
|
|
3494
3565
|
|
|
@@ -3539,15 +3610,21 @@ export function createRemoteHub(options = {}) {
|
|
|
3539
3610
|
}
|
|
3540
3611
|
|
|
3541
3612
|
socket.on('close', () => {
|
|
3613
|
+
state.closed = true;
|
|
3614
|
+
state.binaryQueue.length = 0;
|
|
3542
3615
|
allSockets.delete(socket);
|
|
3543
3616
|
clearTimeout(helloTimer);
|
|
3544
3617
|
detachInputSocket(socket);
|
|
3618
|
+
detachFrameSocket(socket);
|
|
3545
3619
|
detachSocket(socket);
|
|
3546
3620
|
});
|
|
3547
3621
|
socket.on('error', err => {
|
|
3622
|
+
state.closed = true;
|
|
3623
|
+
state.binaryQueue.length = 0;
|
|
3548
3624
|
allSockets.delete(socket);
|
|
3549
3625
|
clearTimeout(helloTimer);
|
|
3550
3626
|
detachInputSocket(socket, err?.message || 'socket-error');
|
|
3627
|
+
detachFrameSocket(socket, err?.message || 'socket-error');
|
|
3551
3628
|
detachSocket(socket, err?.message || 'socket-error');
|
|
3552
3629
|
});
|
|
3553
3630
|
}
|
package/hub/src/server.js
CHANGED
|
@@ -21,9 +21,9 @@ const webIndexPath = resolve(webDistPath, 'index.html');
|
|
|
21
21
|
const packageInfo = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf8'));
|
|
22
22
|
const httpHost = process.env.LIVEDESK_HUB_HTTP_HOST || '0.0.0.0';
|
|
23
23
|
const httpPort = Number(process.env.LIVEDESK_HUB_HTTP_PORT || process.env.PORT || 5179);
|
|
24
|
-
const frameBackpressureBytes = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_BACKPRESSURE_BYTES',
|
|
25
|
-
const frameClientQueuePackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_QUEUE_PACKETS',
|
|
26
|
-
const frameClientDrainBudgetPackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_DRAIN_BUDGET_PACKETS',
|
|
24
|
+
const frameBackpressureBytes = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_BACKPRESSURE_BYTES', 16 * 1024 * 1024);
|
|
25
|
+
const frameClientQueuePackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_QUEUE_PACKETS', 12);
|
|
26
|
+
const frameClientDrainBudgetPackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_DRAIN_BUDGET_PACKETS', 96);
|
|
27
27
|
const frameClients = new Set();
|
|
28
28
|
const frameClientsByDeviceId = new Map();
|
|
29
29
|
const frameWildcardClients = new Set();
|
|
@@ -484,6 +484,8 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
|
|
|
484
484
|
commandId: frame.commandId || '',
|
|
485
485
|
width: Number(frame.width || 0) || 0,
|
|
486
486
|
height: Number(frame.height || 0) || 0,
|
|
487
|
+
sourceWidth: Number(frame.sourceWidth || 0) || 0,
|
|
488
|
+
sourceHeight: Number(frame.sourceHeight || 0) || 0,
|
|
487
489
|
mimeType: frameEvent.mimeType || frame.mimeType || frame.format || 'image/jpeg',
|
|
488
490
|
mode: frame.mode || '',
|
|
489
491
|
frameMode: frame.frameMode || frame.mode || '',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livedesk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.120",
|
|
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.84",
|
|
34
34
|
"cors": "^2.8.5",
|
|
35
35
|
"express": "^4.21.2",
|
|
36
36
|
"ws": "^8.18.3"
|