homebridge-xbox-tv 4.1.21 → 4.1.23
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/CHANGELOG.md +7 -0
- package/package.json +5 -5
- package/src/localApi/xboxlocalapi.js +32 -7
package/CHANGELOG.md
CHANGED
|
@@ -18,6 +18,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
18
18
|
- For plugin < v4.1.0 use Homebridge UI <= v5.5.0
|
|
19
19
|
- For plugin >= v4.1.0 use Homebridge UI >= v5.13.0
|
|
20
20
|
|
|
21
|
+
## [4.1.22] - (18.07.2026)
|
|
22
|
+
|
|
23
|
+
## Changes
|
|
24
|
+
|
|
25
|
+
- fix: Local API — UDP socket leak causing socket count to grow continuously while the Xbox is in standby; each 6 s reconnect heartbeat that found the console ping-reachable but not yet handshaked opened a brand-new socket on a fresh ephemeral port without closing the previous, still-open one; `connect()` now closes any stale socket before binding a new one, and the `acknowledge` inactivity watchdog now closes its socket instead of only clearing the in-memory reference
|
|
26
|
+
- chore: bump `@homebridge/plugin-ui-utils` to ^2.2.5, `mqtt` to ^5.15.2, `uuid` to ^14.0.1, `axios` to ^1.18.1
|
|
27
|
+
|
|
21
28
|
## [4.1.21] - (04.06.2026)
|
|
22
29
|
|
|
23
30
|
## Changes
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "Xbox TV",
|
|
3
3
|
"name": "homebridge-xbox-tv",
|
|
4
|
-
"version": "4.1.
|
|
4
|
+
"version": "4.1.23",
|
|
5
5
|
"description": "Homebridge plugin to control Xbox game consoles.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"node": "^20 || ^22 || ^24 || ^25 || ^26"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@homebridge/plugin-ui-utils": "^2.2.
|
|
39
|
-
"mqtt": "^5.15.
|
|
38
|
+
"@homebridge/plugin-ui-utils": "^2.2.6",
|
|
39
|
+
"mqtt": "^5.15.2",
|
|
40
40
|
"hex-to-binary": "^1.0.1",
|
|
41
|
-
"uuid": "^14.0.
|
|
41
|
+
"uuid": "^14.0.2",
|
|
42
42
|
"express": "^5.2.1",
|
|
43
|
-
"axios": "^1.
|
|
43
|
+
"axios": "^1.20.0"
|
|
44
44
|
},
|
|
45
45
|
"keywords": [
|
|
46
46
|
"homebridge",
|
|
@@ -123,6 +123,19 @@ class XboxLocalApi extends EventEmitter {
|
|
|
123
123
|
async connect() {
|
|
124
124
|
return new Promise((resolve, reject) => {
|
|
125
125
|
try {
|
|
126
|
+
// A previous attempt may have bound a socket that never completed
|
|
127
|
+
// the handshake (eg. console in standby, no discoveryResponse).
|
|
128
|
+
// Close it before binding a new one, otherwise every retry leaks
|
|
129
|
+
// a UDP socket on a fresh ephemeral port. Listeners are stripped
|
|
130
|
+
// first so the stale socket's 'close' handler can't fire
|
|
131
|
+
// updateState() against the session we're about to create.
|
|
132
|
+
if (this.socket) {
|
|
133
|
+
const staleSocket = this.socket;
|
|
134
|
+
this.socket = null;
|
|
135
|
+
staleSocket.removeAllListeners();
|
|
136
|
+
staleSocket.close();
|
|
137
|
+
}
|
|
138
|
+
|
|
126
139
|
this.socket = dgram.createSocket('udp4')
|
|
127
140
|
.on('error', (error) => {
|
|
128
141
|
if (this.logError) this.emit('error', `Socket error: ${error}`);
|
|
@@ -431,14 +444,26 @@ class XboxLocalApi extends EventEmitter {
|
|
|
431
444
|
|
|
432
445
|
if (elapsed >= 14) {
|
|
433
446
|
clearInterval(this.acknowledgeInterval);
|
|
447
|
+
this.acknowledgeInterval = null;
|
|
448
|
+
|
|
449
|
+
try {
|
|
450
|
+
const sequenceNumber = await this.getSequenceNumber();
|
|
451
|
+
const disconnect = new MessagePacket('disconnect');
|
|
452
|
+
disconnect.set('reason', 2);
|
|
453
|
+
disconnect.set('errorCode', 0);
|
|
454
|
+
const message = disconnect.pack(this.crypto, sequenceNumber, this.targetParticipantId, this.sourceParticipantId);
|
|
455
|
+
await this.sendSocketMessage(message, 'disconnect');
|
|
456
|
+
} catch (error) {
|
|
457
|
+
if (this.logError) this.emit('error', `Send disconnect error: ${error}`);
|
|
458
|
+
}
|
|
434
459
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
460
|
+
// Close socket first so on('close') triggers updateState().
|
|
461
|
+
// Calling updateState() directly would null this.socket before
|
|
462
|
+
// close(), causing the old socket to leak in the OS.
|
|
463
|
+
const socketToClose = this.socket;
|
|
464
|
+
this.socket = null;
|
|
465
|
+
this.connected = false;
|
|
466
|
+
if (socketToClose) socketToClose.close();
|
|
442
467
|
}
|
|
443
468
|
}, 1000);
|
|
444
469
|
}
|