livedesk 0.1.470 → 0.1.471
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/client/bin/livedesk-client.js +98 -12
- package/client/package.json +52 -52
- package/hub/src/transport/udp-hub-transport.js +44 -9
- package/package.json +62 -62
|
@@ -2791,6 +2791,8 @@ export async function resolveManagerFromPin(supabase, pin, options = {}) {
|
|
|
2791
2791
|
endpointCandidates,
|
|
2792
2792
|
directReachable: target.directReachable,
|
|
2793
2793
|
connectionTransport: target.connectionTransport,
|
|
2794
|
+
directProbeSkipped: target.directProbeSkipped === true,
|
|
2795
|
+
directProbeSkipReason: String(target.directProbeSkipReason || ''),
|
|
2794
2796
|
discoverySource: 'supabase'
|
|
2795
2797
|
};
|
|
2796
2798
|
}
|
|
@@ -3511,6 +3513,63 @@ function parseManagerEndpoint(value) {
|
|
|
3511
3513
|
return { host, port };
|
|
3512
3514
|
}
|
|
3513
3515
|
|
|
3516
|
+
function ipv4ToUnsignedInteger(address) {
|
|
3517
|
+
const octets = String(address || '').split('.').map(Number);
|
|
3518
|
+
if (octets.length !== 4
|
|
3519
|
+
|| octets.some(octet => !Number.isInteger(octet) || octet < 0 || octet > 255)) {
|
|
3520
|
+
return null;
|
|
3521
|
+
}
|
|
3522
|
+
return (((octets[0] << 24) >>> 0)
|
|
3523
|
+
+ (octets[1] << 16)
|
|
3524
|
+
+ (octets[2] << 8)
|
|
3525
|
+
+ octets[3]) >>> 0;
|
|
3526
|
+
}
|
|
3527
|
+
|
|
3528
|
+
function isAutomaticPrivateIpv4(address) {
|
|
3529
|
+
const value = ipv4ToUnsignedInteger(address);
|
|
3530
|
+
if (value === null) return false;
|
|
3531
|
+
const first = value >>> 24;
|
|
3532
|
+
const second = (value >>> 16) & 0xff;
|
|
3533
|
+
return first === 10
|
|
3534
|
+
|| first === 127
|
|
3535
|
+
|| (first === 100 && second >= 64 && second <= 127)
|
|
3536
|
+
|| (first === 169 && second === 254)
|
|
3537
|
+
|| (first === 172 && second >= 16 && second <= 31)
|
|
3538
|
+
|| (first === 192 && second === 168);
|
|
3539
|
+
}
|
|
3540
|
+
|
|
3541
|
+
export function isEndpointOnLocalNetwork(endpoint, networkInterfaces = os.networkInterfaces()) {
|
|
3542
|
+
const parsedEndpoint = parseManagerEndpoint(endpoint);
|
|
3543
|
+
if (!parsedEndpoint || !net.isIPv4(parsedEndpoint.host)) return false;
|
|
3544
|
+
const target = ipv4ToUnsignedInteger(parsedEndpoint.host);
|
|
3545
|
+
if (target === null) return false;
|
|
3546
|
+
if ((target >>> 24) === 127) return true;
|
|
3547
|
+
for (const entries of Object.values(networkInterfaces || {})) {
|
|
3548
|
+
for (const entry of Array.isArray(entries) ? entries : []) {
|
|
3549
|
+
if (!entry || entry.internal || (entry.family !== 'IPv4' && entry.family !== 4)) continue;
|
|
3550
|
+
const address = ipv4ToUnsignedInteger(entry.address);
|
|
3551
|
+
const netmask = ipv4ToUnsignedInteger(entry.netmask);
|
|
3552
|
+
if (address === null || netmask === null) continue;
|
|
3553
|
+
if (address === target || ((address & netmask) >>> 0) === ((target & netmask) >>> 0)) {
|
|
3554
|
+
return true;
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
return false;
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3561
|
+
export function shouldSkipAutomaticDirectProbe(endpoint, options = {}) {
|
|
3562
|
+
if (options.forcePrivateDirectProbe === true
|
|
3563
|
+
|| /^(1|true|yes|on)$/i.test(String(process.env.LIVEDESK_FORCE_PRIVATE_DIRECT_PROBE || '').trim())) {
|
|
3564
|
+
return false;
|
|
3565
|
+
}
|
|
3566
|
+
const parsedEndpoint = parseManagerEndpoint(endpoint);
|
|
3567
|
+
return !!parsedEndpoint
|
|
3568
|
+
&& net.isIPv4(parsedEndpoint.host)
|
|
3569
|
+
&& isAutomaticPrivateIpv4(parsedEndpoint.host)
|
|
3570
|
+
&& !isEndpointOnLocalNetwork(endpoint, options.networkInterfaces);
|
|
3571
|
+
}
|
|
3572
|
+
|
|
3514
3573
|
function requestHubSlotAssignment({ manager, pairToken, deviceId, slotNumber, timeoutMs = 5000 }) {
|
|
3515
3574
|
const endpoint = parseManagerEndpoint(manager);
|
|
3516
3575
|
const normalizedPairToken = String(pairToken || '').trim();
|
|
@@ -3639,10 +3698,21 @@ export async function chooseManagerConnectionTarget(candidates, options = {}) {
|
|
|
3639
3698
|
.filter(Boolean))];
|
|
3640
3699
|
if (endpoints.length === 0) return null;
|
|
3641
3700
|
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3701
|
+
// A signed 192.168/10/172.16 endpoint from another site cannot normally be
|
|
3702
|
+
// reached from this Client. Skip that full TCP timeout only in automatic
|
|
3703
|
+
// relay-capable discovery. Direct-only mode and an explicit override still
|
|
3704
|
+
// probe it for routed VPN and port-forwarding deployments.
|
|
3705
|
+
const skippedPrivateEndpoints = options.allowRelayFallback === true
|
|
3706
|
+
? endpoints.filter(endpoint => shouldSkipAutomaticDirectProbe(endpoint, options))
|
|
3707
|
+
: [];
|
|
3708
|
+
const skippedPrivateSet = new Set(skippedPrivateEndpoints);
|
|
3709
|
+
const directCandidates = endpoints.filter(endpoint => !skippedPrivateSet.has(endpoint));
|
|
3710
|
+
const manager = directCandidates.length > 0
|
|
3711
|
+
? await chooseReachableEndpoint(directCandidates, {
|
|
3712
|
+
requireReachable: true,
|
|
3713
|
+
probeEndpoint: options.probeEndpoint
|
|
3714
|
+
})
|
|
3715
|
+
: '';
|
|
3646
3716
|
if (manager) {
|
|
3647
3717
|
return {
|
|
3648
3718
|
manager,
|
|
@@ -3655,12 +3725,16 @@ export async function chooseManagerConnectionTarget(candidates, options = {}) {
|
|
|
3655
3725
|
}
|
|
3656
3726
|
return {
|
|
3657
3727
|
// The account/PIN response is the authority for this retry candidate.
|
|
3658
|
-
// RemoteFast
|
|
3659
|
-
// pair-token-authenticated encrypted relay rather than keeping the
|
|
3660
|
-
// launcher in an indefinite TCP reachability loop.
|
|
3728
|
+
// RemoteFast uses relay control to negotiate encrypted UDP P2P video.
|
|
3661
3729
|
manager: endpoints[0],
|
|
3662
3730
|
directReachable: false,
|
|
3663
|
-
connectionTransport: 'relay-fallback'
|
|
3731
|
+
connectionTransport: 'relay-fallback',
|
|
3732
|
+
...(skippedPrivateEndpoints.length > 0
|
|
3733
|
+
? {
|
|
3734
|
+
directProbeSkipped: true,
|
|
3735
|
+
directProbeSkipReason: 'private-endpoint-outside-local-subnet'
|
|
3736
|
+
}
|
|
3737
|
+
: {})
|
|
3664
3738
|
};
|
|
3665
3739
|
}
|
|
3666
3740
|
|
|
@@ -3929,7 +4003,9 @@ export async function resolveManagerFromSupabase(supabase, options = {}) {
|
|
|
3929
4003
|
hubDeviceId: String(data.node_id || '').trim(),
|
|
3930
4004
|
endpointCandidates,
|
|
3931
4005
|
directReachable: target.directReachable,
|
|
3932
|
-
connectionTransport: target.connectionTransport
|
|
4006
|
+
connectionTransport: target.connectionTransport,
|
|
4007
|
+
directProbeSkipped: target.directProbeSkipped === true,
|
|
4008
|
+
directProbeSkipReason: String(target.directProbeSkipReason || '')
|
|
3933
4009
|
};
|
|
3934
4010
|
}
|
|
3935
4011
|
|
|
@@ -4050,6 +4126,7 @@ async function prepareLoginConnection(parsed, existingConnectionPage = null, get
|
|
|
4050
4126
|
let discoverySource = '';
|
|
4051
4127
|
let connectionTransport = '';
|
|
4052
4128
|
let directReachable = false;
|
|
4129
|
+
let directProbeSkipReason = '';
|
|
4053
4130
|
const allowRelayFallback = transportAllowsRelay(parsed.transport);
|
|
4054
4131
|
|
|
4055
4132
|
if (shouldLogin) {
|
|
@@ -4123,12 +4200,15 @@ async function prepareLoginConnection(parsed, existingConnectionPage = null, get
|
|
|
4123
4200
|
discoverySource = choice.discoverySource || 'supabase';
|
|
4124
4201
|
connectionTransport = choice.connectionTransport || 'direct-tcp';
|
|
4125
4202
|
directReachable = choice.directReachable !== false;
|
|
4203
|
+
directProbeSkipReason = String(choice.directProbeSkipReason || '');
|
|
4126
4204
|
connectionPage?.update({
|
|
4127
4205
|
endpointCandidates: choice.endpointCandidates || [],
|
|
4128
4206
|
manager,
|
|
4129
4207
|
assignedHubId: choice.hubDeviceId || '',
|
|
4130
4208
|
message: connectionTransport === 'relay-fallback'
|
|
4131
|
-
?
|
|
4209
|
+
? directProbeSkipReason
|
|
4210
|
+
? `LiveDesk Hub found at ${manager}; the private endpoint is outside this local subnet, so encrypted relay/P2P negotiation starts immediately.`
|
|
4211
|
+
: `LiveDesk Hub found at ${manager}; starting encrypted relay fallback.`
|
|
4132
4212
|
: `Connected to LiveDesk Hub at ${manager}.`
|
|
4133
4213
|
});
|
|
4134
4214
|
console.log(connectionTransport === 'relay-fallback'
|
|
@@ -4210,17 +4290,22 @@ async function prepareLoginConnection(parsed, existingConnectionPage = null, get
|
|
|
4210
4290
|
pair = resolved.pair;
|
|
4211
4291
|
connectionTransport = resolved.connectionTransport || 'direct-tcp';
|
|
4212
4292
|
directReachable = resolved.directReachable !== false;
|
|
4293
|
+
directProbeSkipReason = String(resolved.directProbeSkipReason || '');
|
|
4213
4294
|
connectionPage?.update({
|
|
4214
4295
|
endpointCandidates: resolved.endpointCandidates || [],
|
|
4215
4296
|
manager,
|
|
4216
4297
|
assignedHubId: resolved.hubDeviceId || '',
|
|
4217
4298
|
message: connectionTransport === 'relay-fallback'
|
|
4218
|
-
?
|
|
4299
|
+
? directProbeSkipReason
|
|
4300
|
+
? `LiveDesk Hub found at ${manager}; the private endpoint is outside this local subnet, so encrypted relay/P2P negotiation starts immediately.`
|
|
4301
|
+
: `LiveDesk Hub found at ${manager}; starting encrypted relay fallback.`
|
|
4219
4302
|
: `Connected to LiveDesk Hub at ${manager}.`
|
|
4220
4303
|
});
|
|
4221
4304
|
}
|
|
4222
4305
|
console.log(connectionTransport === 'relay-fallback'
|
|
4223
|
-
?
|
|
4306
|
+
? directProbeSkipReason
|
|
4307
|
+
? `Found LiveDesk Hub record at ${manager}; private endpoint is outside this local subnet, so Direct TCP was skipped and encrypted relay control will negotiate UDP P2P video.`
|
|
4308
|
+
: `Found LiveDesk Hub record at ${manager}; direct TCP did not answer, so RemoteFast will use encrypted relay control and prefer UDP P2P video.`
|
|
4224
4309
|
: `Found LiveDesk Hub at ${manager}.`);
|
|
4225
4310
|
}
|
|
4226
4311
|
// Exact-package updates preserve the already paired Hub endpoint and pass
|
|
@@ -4285,6 +4370,7 @@ async function prepareLoginConnection(parsed, existingConnectionPage = null, get
|
|
|
4285
4370
|
forwarded,
|
|
4286
4371
|
connectionTransport: connectionTransport || 'direct-tcp',
|
|
4287
4372
|
directReachable: connectionTransport === 'relay-fallback' ? false : (directReachable || !shouldLogin),
|
|
4373
|
+
directProbeSkipReason,
|
|
4288
4374
|
discoverySource,
|
|
4289
4375
|
rediscoverOnDisconnect: shouldLogin,
|
|
4290
4376
|
rediscoverOnInvalidPair: shouldLogin
|
package/client/package.json
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@livedesk/client",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "LiveDesk local remote client",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
"client": "bin/livedesk-client.js",
|
|
8
|
-
"livedesk-client": "bin/livedesk-client.js",
|
|
9
|
-
"livedesk-client-node": "bin/livedesk-client-node.js",
|
|
10
|
-
"livedesk-client-fast": "bin/livedesk-client-fast.js"
|
|
11
|
-
},
|
|
12
|
-
"files": [
|
|
13
|
-
"bin/",
|
|
14
|
-
"src/",
|
|
15
|
-
"tests/",
|
|
16
|
-
"README.md",
|
|
17
|
-
"THIRD_PARTY_NOTICES.md"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
20
|
-
"check": "node --check bin/client-version.js && node --check bin/livedesk-client.js && node --check bin/livedesk-client-node.js && node --check bin/livedesk-client-update-bootstrap.cjs && node --check bin/livedesk-client-fast.js",
|
|
21
|
-
"test:version": "node --test tests/client-version.test.mjs",
|
|
22
|
-
"pack:dry": "npm pack --dry-run"
|
|
23
|
-
},
|
|
24
|
-
"keywords": [
|
|
25
|
-
"livedesk",
|
|
26
|
-
"remote",
|
|
27
|
-
"agent",
|
|
28
|
-
"local",
|
|
29
|
-
"desktop"
|
|
30
|
-
],
|
|
31
|
-
"license": "MIT",
|
|
32
|
-
"engines": {
|
|
33
|
-
"node": ">=20"
|
|
34
|
-
},
|
|
35
|
-
"dependencies": {
|
|
36
|
-
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
37
|
-
"ffmpeg-static": "^5.3.0",
|
|
38
|
-
"@livedesk/runtime-core": "0.1.1",
|
|
39
|
-
"@supabase/supabase-js": "^2.110.0",
|
|
40
|
-
"node-screenshots": "^0.2.8",
|
|
41
|
-
"ws": "^8.18.3"
|
|
42
|
-
},
|
|
43
|
-
"optionalDependencies": {
|
|
44
|
-
"@livedesk/fast-linux-x64": "0.1.
|
|
45
|
-
"@livedesk/fast-osx-arm64": "0.1.
|
|
46
|
-
"@livedesk/fast-osx-x64": "0.1.
|
|
47
|
-
"@livedesk/fast-win-x64": "0.1.
|
|
48
|
-
},
|
|
49
|
-
"publishConfig": {
|
|
50
|
-
"access": "public"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@livedesk/client",
|
|
3
|
+
"version": "0.1.220",
|
|
4
|
+
"description": "LiveDesk local remote client",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"client": "bin/livedesk-client.js",
|
|
8
|
+
"livedesk-client": "bin/livedesk-client.js",
|
|
9
|
+
"livedesk-client-node": "bin/livedesk-client-node.js",
|
|
10
|
+
"livedesk-client-fast": "bin/livedesk-client-fast.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin/",
|
|
14
|
+
"src/",
|
|
15
|
+
"tests/",
|
|
16
|
+
"README.md",
|
|
17
|
+
"THIRD_PARTY_NOTICES.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"check": "node --check bin/client-version.js && node --check bin/livedesk-client.js && node --check bin/livedesk-client-node.js && node --check bin/livedesk-client-update-bootstrap.cjs && node --check bin/livedesk-client-fast.js",
|
|
21
|
+
"test:version": "node --test tests/client-version.test.mjs",
|
|
22
|
+
"pack:dry": "npm pack --dry-run"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"livedesk",
|
|
26
|
+
"remote",
|
|
27
|
+
"agent",
|
|
28
|
+
"local",
|
|
29
|
+
"desktop"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=20"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
37
|
+
"ffmpeg-static": "^5.3.0",
|
|
38
|
+
"@livedesk/runtime-core": "0.1.1",
|
|
39
|
+
"@supabase/supabase-js": "^2.110.0",
|
|
40
|
+
"node-screenshots": "^0.2.8",
|
|
41
|
+
"ws": "^8.18.3"
|
|
42
|
+
},
|
|
43
|
+
"optionalDependencies": {
|
|
44
|
+
"@livedesk/fast-linux-x64": "0.1.425",
|
|
45
|
+
"@livedesk/fast-osx-arm64": "0.1.425",
|
|
46
|
+
"@livedesk/fast-osx-x64": "0.1.425",
|
|
47
|
+
"@livedesk/fast-win-x64": "0.1.425"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -96,7 +96,8 @@ export function createHubUdpTransport({ env = process.env, logEvent = () => {},
|
|
|
96
96
|
let rendezvousAddresses = new Set();
|
|
97
97
|
let rendezvousRefreshTimer = null;
|
|
98
98
|
let rendezvousRefreshPromise = null;
|
|
99
|
-
let frameExpiryTimer = null;
|
|
99
|
+
let frameExpiryTimer = null;
|
|
100
|
+
const peerProbeBurstDelaysMs = [0, 120, 360];
|
|
100
101
|
|
|
101
102
|
function emit(type, event = {}) {
|
|
102
103
|
eventHandler(type, event);
|
|
@@ -230,6 +231,33 @@ export function createHubUdpTransport({ env = process.env, logEvent = () => {},
|
|
|
230
231
|
return true;
|
|
231
232
|
}
|
|
232
233
|
|
|
234
|
+
function clearPeerProbeTimers(session) {
|
|
235
|
+
if (!session?.peerProbeTimers) return;
|
|
236
|
+
for (const timer of session.peerProbeTimers) clearTimeout(timer);
|
|
237
|
+
session.peerProbeTimers.clear();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function schedulePeerProbeBurst(session, endpoint) {
|
|
241
|
+
clearPeerProbeTimers(session);
|
|
242
|
+
for (const delayMs of peerProbeBurstDelaysMs) {
|
|
243
|
+
const sendProbe = () => {
|
|
244
|
+
if (sessions.get(session.deviceId) !== session
|
|
245
|
+
|| !sameEndpoint(session.peerEndpoint, endpoint)) return;
|
|
246
|
+
sendPacket(session, 'probe', { punch: true }, Buffer.alloc(0), endpoint);
|
|
247
|
+
};
|
|
248
|
+
if (delayMs === 0) {
|
|
249
|
+
sendProbe();
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
const timer = setTimeout(() => {
|
|
253
|
+
session.peerProbeTimers.delete(timer);
|
|
254
|
+
sendProbe();
|
|
255
|
+
}, delayMs);
|
|
256
|
+
timer.unref?.();
|
|
257
|
+
session.peerProbeTimers.add(timer);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
233
261
|
function onRendezvousPeer(message, rinfo) {
|
|
234
262
|
const session = sessionsBySessionId.get(safeText(message.roomId, 160));
|
|
235
263
|
if (!session || message.protocol !== UDP_P2P_PROTOCOL || !isTrustedRendezvousSource(rinfo)) return;
|
|
@@ -248,9 +276,9 @@ export function createHubUdpTransport({ env = process.env, logEvent = () => {},
|
|
|
248
276
|
};
|
|
249
277
|
session.hubRendezvousObservedAt = Date.now();
|
|
250
278
|
}
|
|
251
|
-
session.peerEndpoint = { address, port };
|
|
279
|
+
session.peerEndpoint = { address, port };
|
|
252
280
|
session.lastPeerAt = Date.now();
|
|
253
|
-
|
|
281
|
+
schedulePeerProbeBurst(session, session.peerEndpoint);
|
|
254
282
|
emit('UdpPeerEndpointObserved', { deviceId: session.deviceId, endpoint: `${address}:${port}` });
|
|
255
283
|
}
|
|
256
284
|
|
|
@@ -298,7 +326,8 @@ export function createHubUdpTransport({ env = process.env, logEvent = () => {},
|
|
|
298
326
|
emit('UdpProbeReceived', { deviceId: session.deviceId });
|
|
299
327
|
return;
|
|
300
328
|
}
|
|
301
|
-
if (packet.type === 'ready') {
|
|
329
|
+
if (packet.type === 'ready') {
|
|
330
|
+
clearPeerProbeTimers(session);
|
|
302
331
|
session.ready = true;
|
|
303
332
|
sendPacket(session, 'pong', { state: 'ready' });
|
|
304
333
|
session.sendControl?.({
|
|
@@ -396,8 +425,9 @@ export function createHubUdpTransport({ env = process.env, logEvent = () => {},
|
|
|
396
425
|
const id = safeText(deviceId, 160);
|
|
397
426
|
if (!id) return null;
|
|
398
427
|
const previous = sessions.get(id);
|
|
399
|
-
previous?.sendControl?.({ type: 'udp.session.close', reason: 'replaced' });
|
|
400
|
-
if (previous) {
|
|
428
|
+
previous?.sendControl?.({ type: 'udp.session.close', reason: 'replaced' });
|
|
429
|
+
if (previous) {
|
|
430
|
+
clearPeerProbeTimers(previous);
|
|
401
431
|
sessions.delete(id);
|
|
402
432
|
sessionsBySessionId.delete(previous.sessionId);
|
|
403
433
|
sessionsByRouteKey.delete(previous.routeKey);
|
|
@@ -432,7 +462,8 @@ export function createHubUdpTransport({ env = process.env, logEvent = () => {},
|
|
|
432
462
|
authenticatedDatagrams: 0,
|
|
433
463
|
rejectedDatagrams: 0
|
|
434
464
|
},
|
|
435
|
-
ready: false,
|
|
465
|
+
ready: false,
|
|
466
|
+
peerProbeTimers: new Set(),
|
|
436
467
|
createdAt: Date.now(),
|
|
437
468
|
lastPacketAt: 0,
|
|
438
469
|
framesReceived: 0
|
|
@@ -466,7 +497,8 @@ export function createHubUdpTransport({ env = process.env, logEvent = () => {},
|
|
|
466
497
|
const id = safeText(deviceId, 160);
|
|
467
498
|
const session = sessions.get(id);
|
|
468
499
|
if (!session || (tcpSessionId && session.tcpSessionId !== tcpSessionId)) return;
|
|
469
|
-
|
|
500
|
+
clearPeerProbeTimers(session);
|
|
501
|
+
sessions.delete(id);
|
|
470
502
|
sessionsBySessionId.delete(session.sessionId);
|
|
471
503
|
sessionsByRouteKey.delete(session.routeKey);
|
|
472
504
|
session.reassembler.clear();
|
|
@@ -562,7 +594,10 @@ export function createHubUdpTransport({ env = process.env, logEvent = () => {},
|
|
|
562
594
|
async function close() {
|
|
563
595
|
stopRendezvousRefreshTimer();
|
|
564
596
|
stopFrameExpiryTimer();
|
|
565
|
-
for (const session of sessions.values())
|
|
597
|
+
for (const session of sessions.values()) {
|
|
598
|
+
clearPeerProbeTimers(session);
|
|
599
|
+
session.reassembler.clear();
|
|
600
|
+
}
|
|
566
601
|
sessions.clear();
|
|
567
602
|
sessionsBySessionId.clear();
|
|
568
603
|
sessionsByRouteKey.clear();
|
package/package.json
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "livedesk",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"livedeskClientVersion": "0.1.
|
|
5
|
-
"buildFlavor": "production",
|
|
6
|
-
"description": "LiveDesk Hub and client launcher",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"main": "electron/main.mjs",
|
|
9
|
-
"bin": {
|
|
10
|
-
"livedesk": "bin/livedesk.js"
|
|
11
|
-
},
|
|
12
|
-
"files": [
|
|
13
|
-
"bin/",
|
|
14
|
-
"bootstrap/",
|
|
15
|
-
"diagnostics/",
|
|
16
|
-
"hub/",
|
|
17
|
-
"runtime-core/",
|
|
18
|
-
"client/",
|
|
19
|
-
"electron/",
|
|
20
|
-
"scripts/",
|
|
21
|
-
"web/",
|
|
22
|
-
"README.md"
|
|
23
|
-
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"check": "node --check bin/livedesk.js && node --check diagnostics/livedesk-mode3-capture-smoke.mjs && node --check diagnostics/livedesk-mac-physical-gate-core.mjs && node --check diagnostics/livedesk-mac-physical-isolation.mjs && node --check diagnostics/livedesk-transport-physical-core.mjs && node --check diagnostics/livedesk-transport-physical.mjs && node --check scripts/sync-web-dist.js",
|
|
26
|
-
"build": "node scripts/sync-web-dist.js",
|
|
27
|
-
"prepack": "node scripts/sync-web-dist.js",
|
|
28
|
-
"pack:dry": "npm pack --dry-run"
|
|
29
|
-
},
|
|
30
|
-
"keywords": [
|
|
31
|
-
"livedesk",
|
|
32
|
-
"remote",
|
|
33
|
-
"screen-wall",
|
|
34
|
-
"hub",
|
|
35
|
-
"local"
|
|
36
|
-
],
|
|
37
|
-
"license": "MIT",
|
|
38
|
-
"engines": {
|
|
39
|
-
"node": ">=20"
|
|
40
|
-
},
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
43
|
-
"ffmpeg-static": "^5.3.0",
|
|
44
|
-
"@openai/codex-sdk": "0.145.0",
|
|
45
|
-
"@supabase/supabase-js": "^2.110.0",
|
|
46
|
-
"cors": "^2.8.5",
|
|
47
|
-
"electron-updater": "^6.8.9",
|
|
48
|
-
"express": "^4.21.2",
|
|
49
|
-
"node-screenshots": "^0.2.8",
|
|
50
|
-
"path-to-regexp": "0.1.13",
|
|
51
|
-
"ws": "^8.18.3"
|
|
52
|
-
},
|
|
53
|
-
"optionalDependencies": {
|
|
54
|
-
"@livedesk/fast-linux-x64": "0.1.
|
|
55
|
-
"@livedesk/fast-osx-arm64": "0.1.
|
|
56
|
-
"@livedesk/fast-osx-x64": "0.1.
|
|
57
|
-
"@livedesk/fast-win-x64": "0.1.
|
|
58
|
-
},
|
|
59
|
-
"publishConfig": {
|
|
60
|
-
"access": "public"
|
|
61
|
-
}
|
|
62
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "livedesk",
|
|
3
|
+
"version": "0.1.471",
|
|
4
|
+
"livedeskClientVersion": "0.1.220",
|
|
5
|
+
"buildFlavor": "production",
|
|
6
|
+
"description": "LiveDesk Hub and client launcher",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "electron/main.mjs",
|
|
9
|
+
"bin": {
|
|
10
|
+
"livedesk": "bin/livedesk.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin/",
|
|
14
|
+
"bootstrap/",
|
|
15
|
+
"diagnostics/",
|
|
16
|
+
"hub/",
|
|
17
|
+
"runtime-core/",
|
|
18
|
+
"client/",
|
|
19
|
+
"electron/",
|
|
20
|
+
"scripts/",
|
|
21
|
+
"web/",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"check": "node --check bin/livedesk.js && node --check diagnostics/livedesk-mode3-capture-smoke.mjs && node --check diagnostics/livedesk-mac-physical-gate-core.mjs && node --check diagnostics/livedesk-mac-physical-isolation.mjs && node --check diagnostics/livedesk-transport-physical-core.mjs && node --check diagnostics/livedesk-transport-physical.mjs && node --check scripts/sync-web-dist.js",
|
|
26
|
+
"build": "node scripts/sync-web-dist.js",
|
|
27
|
+
"prepack": "node scripts/sync-web-dist.js",
|
|
28
|
+
"pack:dry": "npm pack --dry-run"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"livedesk",
|
|
32
|
+
"remote",
|
|
33
|
+
"screen-wall",
|
|
34
|
+
"hub",
|
|
35
|
+
"local"
|
|
36
|
+
],
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
43
|
+
"ffmpeg-static": "^5.3.0",
|
|
44
|
+
"@openai/codex-sdk": "0.145.0",
|
|
45
|
+
"@supabase/supabase-js": "^2.110.0",
|
|
46
|
+
"cors": "^2.8.5",
|
|
47
|
+
"electron-updater": "^6.8.9",
|
|
48
|
+
"express": "^4.21.2",
|
|
49
|
+
"node-screenshots": "^0.2.8",
|
|
50
|
+
"path-to-regexp": "0.1.13",
|
|
51
|
+
"ws": "^8.18.3"
|
|
52
|
+
},
|
|
53
|
+
"optionalDependencies": {
|
|
54
|
+
"@livedesk/fast-linux-x64": "0.1.425",
|
|
55
|
+
"@livedesk/fast-osx-arm64": "0.1.425",
|
|
56
|
+
"@livedesk/fast-osx-x64": "0.1.425",
|
|
57
|
+
"@livedesk/fast-win-x64": "0.1.425"
|
|
58
|
+
},
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
61
|
+
}
|
|
62
|
+
}
|