livedesk 0.1.118 → 0.1.119

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.
@@ -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
- handleAgentBinaryFrame(socket, state, packet.header, packet.payload);
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);
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', 512 * 1024);
25
- const frameClientQueuePackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_QUEUE_PACKETS', 3);
26
- const frameClientDrainBudgetPackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_DRAIN_BUDGET_PACKETS', 2);
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.118",
3
+ "version": "0.1.119",
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.82",
33
+ "@livedesk/client": "0.1.83",
34
34
  "cors": "^2.8.5",
35
35
  "express": "^4.21.2",
36
36
  "ws": "^8.18.3"