hap-nodejs 1.1.1-beta.1 → 1.1.1-beta.3
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/@types/bonjour-hap.d.ts +50 -53
- package/README.md +16 -19
- package/dist/accessories/AirConditioner_accessory.js +28 -30
- package/dist/accessories/AirConditioner_accessory.js.map +1 -1
- package/dist/accessories/AppleTVRemote_accessory.js +69 -81
- package/dist/accessories/AppleTVRemote_accessory.js.map +1 -1
- package/dist/accessories/Camera_accessory.js +141 -136
- package/dist/accessories/Camera_accessory.js.map +1 -1
- package/dist/accessories/Fan_accessory.js +18 -22
- package/dist/accessories/Fan_accessory.js.map +1 -1
- package/dist/accessories/GarageDoorOpener_accessory.js +33 -35
- package/dist/accessories/GarageDoorOpener_accessory.js.map +1 -1
- package/dist/accessories/Light-AdaptiveLighting_accessory.js +42 -44
- package/dist/accessories/Light-AdaptiveLighting_accessory.js.map +1 -1
- package/dist/accessories/Light_accessory.js +32 -34
- package/dist/accessories/Light_accessory.js.map +1 -1
- package/dist/accessories/Lock_accessory.js +25 -26
- package/dist/accessories/Lock_accessory.js.map +1 -1
- package/dist/accessories/MotionSensor_accessory.js +13 -16
- package/dist/accessories/MotionSensor_accessory.js.map +1 -1
- package/dist/accessories/Outlet_accessory.js +20 -22
- package/dist/accessories/Outlet_accessory.js.map +1 -1
- package/dist/accessories/SmartSpeaker_accessory.js +18 -20
- package/dist/accessories/SmartSpeaker_accessory.js.map +1 -1
- package/dist/accessories/Sprinkler_accessory.js +34 -37
- package/dist/accessories/Sprinkler_accessory.js.map +1 -1
- package/dist/accessories/TV_accessory.js +43 -45
- package/dist/accessories/TV_accessory.js.map +1 -1
- package/dist/accessories/TemperatureSensor_accessory.js +12 -15
- package/dist/accessories/TemperatureSensor_accessory.js.map +1 -1
- package/dist/accessories/Wi-FiRouter_accessory.d.ts +1 -1
- package/dist/accessories/Wi-FiRouter_accessory.d.ts.map +1 -1
- package/dist/accessories/Wi-FiRouter_accessory.js +9 -12
- package/dist/accessories/Wi-FiRouter_accessory.js.map +1 -1
- package/dist/accessories/Wi-FiSatellite_accessory.d.ts +1 -1
- package/dist/accessories/Wi-FiSatellite_accessory.d.ts.map +1 -1
- package/dist/accessories/Wi-FiSatellite_accessory.js +11 -14
- package/dist/accessories/Wi-FiSatellite_accessory.js.map +1 -1
- package/dist/accessories/gstreamer-audioProducer.d.ts +3 -3
- package/dist/accessories/gstreamer-audioProducer.d.ts.map +1 -1
- package/dist/accessories/gstreamer-audioProducer.js +37 -38
- package/dist/accessories/gstreamer-audioProducer.js.map +1 -1
- package/dist/accessories/types.d.ts +63 -63
- package/dist/accessories/types.d.ts.map +1 -1
- package/dist/accessories/types.js +83 -87
- package/dist/accessories/types.js.map +1 -1
- package/dist/index.d.ts +26 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -34
- package/dist/index.js.map +1 -1
- package/dist/internal-types.d.ts +1 -1
- package/dist/internal-types.d.ts.map +1 -1
- package/dist/internal-types.js +19 -21
- package/dist/internal-types.js.map +1 -1
- package/dist/lib/Accessory.d.ts +39 -38
- package/dist/lib/Accessory.d.ts.map +1 -1
- package/dist/lib/Accessory.js +314 -292
- package/dist/lib/Accessory.js.map +1 -1
- package/dist/lib/Advertiser.d.ts +7 -7
- package/dist/lib/Advertiser.d.ts.map +1 -1
- package/dist/lib/Advertiser.js +128 -136
- package/dist/lib/Advertiser.js.map +1 -1
- package/dist/lib/Bridge.d.ts +1 -1
- package/dist/lib/Bridge.d.ts.map +1 -1
- package/dist/lib/Bridge.js +2 -6
- package/dist/lib/Bridge.js.map +1 -1
- package/dist/lib/Characteristic.d.ts +40 -41
- package/dist/lib/Characteristic.d.ts.map +1 -1
- package/dist/lib/Characteristic.js +204 -208
- package/dist/lib/Characteristic.js.map +1 -1
- package/dist/lib/HAPServer.d.ts +31 -30
- package/dist/lib/HAPServer.d.ts.map +1 -1
- package/dist/lib/HAPServer.js +220 -229
- package/dist/lib/HAPServer.js.map +1 -1
- package/dist/lib/Service.d.ts +22 -22
- package/dist/lib/Service.d.ts.map +1 -1
- package/dist/lib/Service.js +63 -67
- package/dist/lib/Service.js.map +1 -1
- package/dist/lib/camera/RTPProxy.d.ts +2 -1
- package/dist/lib/camera/RTPProxy.d.ts.map +1 -1
- package/dist/lib/camera/RTPProxy.js +28 -44
- package/dist/lib/camera/RTPProxy.js.map +1 -1
- package/dist/lib/camera/RTPStreamManagement.d.ts +34 -33
- package/dist/lib/camera/RTPStreamManagement.d.ts.map +1 -1
- package/dist/lib/camera/RTPStreamManagement.js +179 -151
- package/dist/lib/camera/RTPStreamManagement.js.map +1 -1
- package/dist/lib/camera/RecordingManagement.d.ts +19 -17
- package/dist/lib/camera/RecordingManagement.d.ts.map +1 -1
- package/dist/lib/camera/RecordingManagement.js +160 -151
- package/dist/lib/camera/RecordingManagement.js.map +1 -1
- package/dist/lib/camera/index.d.ts +3 -3
- package/dist/lib/camera/index.d.ts.map +1 -1
- package/dist/lib/camera/index.js +3 -6
- package/dist/lib/camera/index.js.map +1 -1
- package/dist/lib/controller/AdaptiveLightingController.d.ts +33 -33
- package/dist/lib/controller/AdaptiveLightingController.d.ts.map +1 -1
- package/dist/lib/controller/AdaptiveLightingController.js +152 -144
- package/dist/lib/controller/AdaptiveLightingController.js.map +1 -1
- package/dist/lib/controller/CameraController.d.ts +22 -20
- package/dist/lib/controller/CameraController.d.ts.map +1 -1
- package/dist/lib/controller/CameraController.js +74 -78
- package/dist/lib/controller/CameraController.js.map +1 -1
- package/dist/lib/controller/Controller.d.ts +4 -4
- package/dist/lib/controller/Controller.d.ts.map +1 -1
- package/dist/lib/controller/Controller.js +5 -8
- package/dist/lib/controller/Controller.js.map +1 -1
- package/dist/lib/controller/DoorbellController.d.ts +5 -4
- package/dist/lib/controller/DoorbellController.d.ts.map +1 -1
- package/dist/lib/controller/DoorbellController.js +9 -13
- package/dist/lib/controller/DoorbellController.js.map +1 -1
- package/dist/lib/controller/RemoteController.d.ts +39 -37
- package/dist/lib/controller/RemoteController.d.ts.map +1 -1
- package/dist/lib/controller/RemoteController.js +208 -197
- package/dist/lib/controller/RemoteController.js.map +1 -1
- package/dist/lib/controller/index.d.ts +5 -5
- package/dist/lib/controller/index.d.ts.map +1 -1
- package/dist/lib/controller/index.js +5 -8
- package/dist/lib/controller/index.js.map +1 -1
- package/dist/lib/datastream/DataStreamManagement.d.ts +2 -2
- package/dist/lib/datastream/DataStreamManagement.d.ts.map +1 -1
- package/dist/lib/datastream/DataStreamManagement.js +39 -39
- package/dist/lib/datastream/DataStreamManagement.js.map +1 -1
- package/dist/lib/datastream/DataStreamParser.d.ts +1 -0
- package/dist/lib/datastream/DataStreamParser.d.ts.map +1 -1
- package/dist/lib/datastream/DataStreamParser.js +57 -77
- package/dist/lib/datastream/DataStreamParser.js.map +1 -1
- package/dist/lib/datastream/DataStreamServer.d.ts +23 -22
- package/dist/lib/datastream/DataStreamServer.d.ts.map +1 -1
- package/dist/lib/datastream/DataStreamServer.js +154 -164
- package/dist/lib/datastream/DataStreamServer.js.map +1 -1
- package/dist/lib/datastream/index.d.ts +3 -3
- package/dist/lib/datastream/index.d.ts.map +1 -1
- package/dist/lib/datastream/index.js +3 -6
- package/dist/lib/datastream/index.js.map +1 -1
- package/dist/lib/dbus/align.d.ts +2 -0
- package/dist/lib/dbus/align.d.ts.map +1 -0
- package/dist/lib/dbus/align.js +12 -0
- package/dist/lib/dbus/align.js.map +1 -0
- package/dist/lib/dbus/bus.d.ts +38 -0
- package/dist/lib/dbus/bus.d.ts.map +1 -0
- package/dist/lib/dbus/bus.js +222 -0
- package/dist/lib/dbus/bus.js.map +1 -0
- package/dist/lib/dbus/constants.d.ts +43 -0
- package/dist/lib/dbus/constants.d.ts.map +1 -0
- package/dist/lib/dbus/constants.js +53 -0
- package/dist/lib/dbus/constants.js.map +1 -0
- package/dist/lib/dbus/dbus-buffer.d.ts +30 -0
- package/dist/lib/dbus/dbus-buffer.d.ts.map +1 -0
- package/dist/lib/dbus/dbus-buffer.js +175 -0
- package/dist/lib/dbus/dbus-buffer.js.map +1 -0
- package/dist/lib/dbus/handshake.d.ts +2 -0
- package/dist/lib/dbus/handshake.d.ts.map +1 -0
- package/dist/lib/dbus/handshake.js +130 -0
- package/dist/lib/dbus/handshake.js.map +1 -0
- package/dist/lib/dbus/index.d.ts +3 -0
- package/dist/lib/dbus/index.d.ts.map +1 -0
- package/dist/lib/dbus/index.js +123 -0
- package/dist/lib/dbus/index.js.map +1 -0
- package/dist/lib/dbus/introspect.d.ts +30 -0
- package/dist/lib/dbus/introspect.d.ts.map +1 -0
- package/dist/lib/dbus/introspect.js +208 -0
- package/dist/lib/dbus/introspect.js.map +1 -0
- package/dist/lib/dbus/marshall.d.ts +2 -0
- package/dist/lib/dbus/marshall.d.ts.map +1 -0
- package/dist/lib/dbus/marshall.js +97 -0
- package/dist/lib/dbus/marshall.js.map +1 -0
- package/dist/lib/dbus/marshallers.d.ts +10 -0
- package/dist/lib/dbus/marshallers.d.ts.map +1 -0
- package/dist/lib/dbus/marshallers.js +329 -0
- package/dist/lib/dbus/marshallers.js.map +1 -0
- package/dist/lib/dbus/message.d.ts +4 -0
- package/dist/lib/dbus/message.d.ts.map +1 -0
- package/dist/lib/dbus/message.js +116 -0
- package/dist/lib/dbus/message.js.map +1 -0
- package/dist/lib/dbus/put.d.ts +21 -0
- package/dist/lib/dbus/put.d.ts.map +1 -0
- package/dist/lib/dbus/put.js +120 -0
- package/dist/lib/dbus/put.js.map +1 -0
- package/dist/lib/dbus/readline.d.ts +2 -0
- package/dist/lib/dbus/readline.d.ts.map +1 -0
- package/dist/lib/dbus/readline.js +27 -0
- package/dist/lib/dbus/readline.js.map +1 -0
- package/dist/lib/dbus/signature.d.ts +2 -0
- package/dist/lib/dbus/signature.d.ts.map +1 -0
- package/dist/lib/dbus/signature.js +58 -0
- package/dist/lib/dbus/signature.js.map +1 -0
- package/dist/lib/dbus/stdifaces.d.ts +3 -0
- package/dist/lib/dbus/stdifaces.d.ts.map +1 -0
- package/dist/lib/dbus/stdifaces.js +206 -0
- package/dist/lib/dbus/stdifaces.js.map +1 -0
- package/dist/lib/definitions/CharacteristicDefinitions.d.ts +1 -1
- package/dist/lib/definitions/CharacteristicDefinitions.d.ts.map +1 -1
- package/dist/lib/definitions/CharacteristicDefinitions.js +958 -1204
- package/dist/lib/definitions/CharacteristicDefinitions.js.map +1 -1
- package/dist/lib/definitions/ServiceDefinitions.d.ts +1 -1
- package/dist/lib/definitions/ServiceDefinitions.d.ts.map +1 -1
- package/dist/lib/definitions/ServiceDefinitions.js +620 -695
- package/dist/lib/definitions/ServiceDefinitions.js.map +1 -1
- package/dist/lib/definitions/generate-definitions.d.ts +3 -3
- package/dist/lib/definitions/generate-definitions.d.ts.map +1 -1
- package/dist/lib/definitions/generate-definitions.js +246 -253
- package/dist/lib/definitions/generate-definitions.js.map +1 -1
- package/dist/lib/definitions/generator-configuration.d.ts +1 -1
- package/dist/lib/definitions/generator-configuration.d.ts.map +1 -1
- package/dist/lib/definitions/generator-configuration.js +160 -165
- package/dist/lib/definitions/generator-configuration.js.map +1 -1
- package/dist/lib/definitions/index.d.ts +2 -2
- package/dist/lib/definitions/index.d.ts.map +1 -1
- package/dist/lib/definitions/index.js +2 -5
- package/dist/lib/definitions/index.js.map +1 -1
- package/dist/lib/model/AccessoryInfo.d.ts +4 -3
- package/dist/lib/model/AccessoryInfo.d.ts.map +1 -1
- package/dist/lib/model/AccessoryInfo.js +50 -53
- package/dist/lib/model/AccessoryInfo.js.map +1 -1
- package/dist/lib/model/ControllerStorage.d.ts +3 -3
- package/dist/lib/model/ControllerStorage.d.ts.map +1 -1
- package/dist/lib/model/ControllerStorage.js +17 -22
- package/dist/lib/model/ControllerStorage.js.map +1 -1
- package/dist/lib/model/HAPStorage.d.ts +2 -2
- package/dist/lib/model/HAPStorage.d.ts.map +1 -1
- package/dist/lib/model/HAPStorage.js +4 -11
- package/dist/lib/model/HAPStorage.js.map +1 -1
- package/dist/lib/model/IdentifierCache.d.ts +1 -1
- package/dist/lib/model/IdentifierCache.d.ts.map +1 -1
- package/dist/lib/model/IdentifierCache.js +19 -27
- package/dist/lib/model/IdentifierCache.js.map +1 -1
- package/dist/lib/tv/AccessControlManagement.d.ts +9 -9
- package/dist/lib/tv/AccessControlManagement.d.ts.map +1 -1
- package/dist/lib/tv/AccessControlManagement.js +27 -29
- package/dist/lib/tv/AccessControlManagement.js.map +1 -1
- package/dist/lib/util/checkName.d.ts +2 -2
- package/dist/lib/util/checkName.d.ts.map +1 -1
- package/dist/lib/util/checkName.js +6 -9
- package/dist/lib/util/checkName.js.map +1 -1
- package/dist/lib/util/clone.d.ts.map +1 -1
- package/dist/lib/util/clone.js +1 -5
- package/dist/lib/util/clone.js.map +1 -1
- package/dist/lib/util/color-utils.d.ts +1 -1
- package/dist/lib/util/color-utils.d.ts.map +1 -1
- package/dist/lib/util/color-utils.js +4 -9
- package/dist/lib/util/color-utils.js.map +1 -1
- package/dist/lib/util/eventedhttp.d.ts +23 -22
- package/dist/lib/util/eventedhttp.d.ts.map +1 -1
- package/dist/lib/util/eventedhttp.js +109 -116
- package/dist/lib/util/eventedhttp.js.map +1 -1
- package/dist/lib/util/hapCrypto.d.ts +3 -2
- package/dist/lib/util/hapCrypto.d.ts.map +1 -1
- package/dist/lib/util/hapCrypto.js +31 -40
- package/dist/lib/util/hapCrypto.js.map +1 -1
- package/dist/lib/util/hapStatusError.d.ts +1 -1
- package/dist/lib/util/hapStatusError.d.ts.map +1 -1
- package/dist/lib/util/hapStatusError.js +4 -8
- package/dist/lib/util/hapStatusError.js.map +1 -1
- package/dist/lib/util/net-utils.d.ts +1 -1
- package/dist/lib/util/net-utils.js +17 -23
- package/dist/lib/util/net-utils.js.map +1 -1
- package/dist/lib/util/once.d.ts.map +1 -1
- package/dist/lib/util/once.js +2 -6
- package/dist/lib/util/once.js.map +1 -1
- package/dist/lib/util/promise-utils.d.ts +1 -1
- package/dist/lib/util/promise-utils.d.ts.map +1 -1
- package/dist/lib/util/promise-utils.js +3 -9
- package/dist/lib/util/promise-utils.js.map +1 -1
- package/dist/lib/util/request-util.d.ts +3 -2
- package/dist/lib/util/request-util.d.ts.map +1 -1
- package/dist/lib/util/request-util.js +11 -19
- package/dist/lib/util/request-util.js.map +1 -1
- package/dist/lib/util/time.d.ts +1 -0
- package/dist/lib/util/time.d.ts.map +1 -1
- package/dist/lib/util/time.js +6 -11
- package/dist/lib/util/time.js.map +1 -1
- package/dist/lib/util/tlv.d.ts +1 -0
- package/dist/lib/util/tlv.d.ts.map +1 -1
- package/dist/lib/util/tlv.js +28 -43
- package/dist/lib/util/tlv.js.map +1 -1
- package/dist/lib/util/uuid.d.ts +1 -0
- package/dist/lib/util/uuid.d.ts.map +1 -1
- package/dist/lib/util/uuid.js +26 -38
- package/dist/lib/util/uuid.js.map +1 -1
- package/dist/types.d.ts +24 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -5
- package/dist/types.js.map +1 -1
- package/package.json +51 -46
- package/@types/simple-plist.d.ts +0 -4
- package/dist/lib/gen/HomeKit.d.ts +0 -7
- package/dist/lib/gen/HomeKit.d.ts.map +0 -1
- package/dist/lib/gen/HomeKit.js +0 -8
- package/dist/lib/gen/HomeKit.js.map +0 -1
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const debug = (0, debug_1.default)("HAP-NodeJS:EventedHTTPServer");
|
|
16
|
-
const debugCon = (0, debug_1.default)("HAP-NodeJS:EventedHTTPServer:Connection");
|
|
17
|
-
const debugEvents = (0, debug_1.default)("HAP-NodeJS:EventEmitter");
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
3
|
+
import { EventEmitter } from 'node:events';
|
|
4
|
+
import { createServer as createHttpServer } from 'node:http';
|
|
5
|
+
import { createConnection, createServer, isIPv4 } from 'node:net';
|
|
6
|
+
import { networkInterfaces } from 'node:os';
|
|
7
|
+
import { getNetAddress } from '@homebridge/ciao/dist/util/domain-formatter.js';
|
|
8
|
+
import createDebug from 'debug';
|
|
9
|
+
import { layerDecrypt, layerEncrypt } from './hapCrypto.js';
|
|
10
|
+
import { getOSLoopbackAddressIfAvailable } from './net-utils.js';
|
|
11
|
+
import { generate } from './uuid.js';
|
|
12
|
+
const debug = createDebug('HAP-NodeJS:EventedHTTPServer');
|
|
13
|
+
const debugCon = createDebug('HAP-NodeJS:EventedHTTPServer:Connection');
|
|
14
|
+
const debugEvents = createDebug('HAP-NodeJS:EventEmitter');
|
|
18
15
|
/**
|
|
19
16
|
* Simple struct to hold vars needed to support HAP encryption.
|
|
20
17
|
*
|
|
21
18
|
* @group Cryptography
|
|
22
19
|
*/
|
|
23
|
-
class HAPEncryption {
|
|
20
|
+
export class HAPEncryption {
|
|
24
21
|
clientPublicKey;
|
|
25
22
|
secretKey;
|
|
26
23
|
publicKey;
|
|
@@ -41,17 +38,17 @@ class HAPEncryption {
|
|
|
41
38
|
this.controllerToAccessoryKey = Buffer.alloc(0);
|
|
42
39
|
}
|
|
43
40
|
}
|
|
44
|
-
exports.HAPEncryption = HAPEncryption;
|
|
45
41
|
/**
|
|
46
42
|
* @group HAP Accessory Server
|
|
47
43
|
*/
|
|
48
|
-
|
|
44
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
45
|
+
export var EventedHTTPServerEvent;
|
|
49
46
|
(function (EventedHTTPServerEvent) {
|
|
50
47
|
EventedHTTPServerEvent["LISTENING"] = "listening";
|
|
51
48
|
EventedHTTPServerEvent["CONNECTION_OPENED"] = "connection-opened";
|
|
52
49
|
EventedHTTPServerEvent["REQUEST"] = "request";
|
|
53
50
|
EventedHTTPServerEvent["CONNECTION_CLOSED"] = "connection-closed";
|
|
54
|
-
})(EventedHTTPServerEvent || (
|
|
51
|
+
})(EventedHTTPServerEvent || (EventedHTTPServerEvent = {}));
|
|
55
52
|
/**
|
|
56
53
|
* EventedHTTPServer provides an HTTP-like server that supports HAP "extensions" for security and events.
|
|
57
54
|
*
|
|
@@ -71,8 +68,8 @@ var EventedHTTPServerEvent;
|
|
|
71
68
|
*
|
|
72
69
|
* @group HAP Accessory Server
|
|
73
70
|
*/
|
|
74
|
-
// eslint-disable-next-line
|
|
75
|
-
class EventedHTTPServer extends
|
|
71
|
+
// eslint-disable-next-line ts/no-unsafe-declaration-merging
|
|
72
|
+
export class EventedHTTPServer extends EventEmitter {
|
|
76
73
|
static CONNECTION_TIMEOUT_LIMIT = 16; // if we have more (or equal) # connections we start the timeout
|
|
77
74
|
static MAX_CONNECTION_IDLE_TIME = 60 * 60 * 1000; // 1h
|
|
78
75
|
tcpServer;
|
|
@@ -89,20 +86,20 @@ class EventedHTTPServer extends events_1.EventEmitter {
|
|
|
89
86
|
connectionLoggingInterval;
|
|
90
87
|
constructor() {
|
|
91
88
|
super();
|
|
92
|
-
this.tcpServer =
|
|
89
|
+
this.tcpServer = createServer();
|
|
93
90
|
}
|
|
94
91
|
scheduleNextConnectionIdleTimeout() {
|
|
95
92
|
this.connectionIdleTimeout = undefined;
|
|
96
93
|
if (!this.tcpServer.listening) {
|
|
97
94
|
return;
|
|
98
95
|
}
|
|
99
|
-
debug(
|
|
96
|
+
debug('Running idle timeout timer...');
|
|
100
97
|
const currentTime = new Date().getTime();
|
|
101
98
|
let nextTimeout = -1;
|
|
102
99
|
for (const connection of this.connections) {
|
|
103
100
|
const timeDelta = currentTime - connection.lastSocketOperation;
|
|
104
101
|
if (timeDelta >= EventedHTTPServer.MAX_CONNECTION_IDLE_TIME) {
|
|
105
|
-
debug(
|
|
102
|
+
debug(`[%s] Closing connection as it was inactive for ${timeDelta}ms`);
|
|
106
103
|
connection.close();
|
|
107
104
|
}
|
|
108
105
|
else {
|
|
@@ -119,17 +116,17 @@ class EventedHTTPServer extends events_1.EventEmitter {
|
|
|
119
116
|
listen(targetPort, hostname) {
|
|
120
117
|
this.tcpServer.listen(targetPort, hostname, () => {
|
|
121
118
|
const address = this.tcpServer.address(); // address() is only a string when listening to unix domain sockets
|
|
122
|
-
debug(
|
|
119
|
+
debug('Server listening on %s:%s', address.family === 'IPv6' ? `[${address.address}]` : address.address, address.port);
|
|
123
120
|
this.connectionLoggingInterval = setInterval(() => {
|
|
124
121
|
const connectionInformation = [...this.connections]
|
|
125
122
|
.map(connection => `${connection.remoteAddress}:${connection.remotePort}`)
|
|
126
|
-
.join(
|
|
127
|
-
debug(
|
|
123
|
+
.join(', ');
|
|
124
|
+
debug('Currently %d hap connections open: %s', this.connections.size, connectionInformation);
|
|
128
125
|
}, 60_000);
|
|
129
126
|
this.connectionLoggingInterval.unref();
|
|
130
127
|
this.emit("listening" /* EventedHTTPServerEvent.LISTENING */, address.port, address.address);
|
|
131
128
|
});
|
|
132
|
-
this.tcpServer.on(
|
|
129
|
+
this.tcpServer.on('connection', this.onConnection.bind(this));
|
|
133
130
|
}
|
|
134
131
|
stop() {
|
|
135
132
|
if (this.connectionLoggingInterval != null) {
|
|
@@ -158,27 +155,28 @@ class EventedHTTPServer extends events_1.EventEmitter {
|
|
|
158
155
|
* @param value - The newly set value of the characteristic.
|
|
159
156
|
* @param originator - If specified, the connection will not get an event message.
|
|
160
157
|
* @param immediateDelivery - The HAP spec requires some characteristics to be delivery immediately.
|
|
161
|
-
*
|
|
158
|
+
* Namely, for the {@link Characteristic.ButtonEvent} and the {@link Characteristic.ProgrammableSwitchEvent} characteristics.
|
|
162
159
|
*/
|
|
163
160
|
broadcastEvent(aid, iid, value, originator, immediateDelivery) {
|
|
164
161
|
for (const connection of this.connections) {
|
|
165
162
|
if (connection === originator) {
|
|
166
|
-
debug(
|
|
163
|
+
debug('[%s] Muting event \'%s\' notification for this connection since it originated here.', connection.remoteAddress, `${aid}.${iid}`);
|
|
167
164
|
continue;
|
|
168
165
|
}
|
|
169
166
|
connection.sendEvent(aid, iid, value, immediateDelivery);
|
|
170
167
|
}
|
|
171
168
|
}
|
|
172
169
|
onConnection(socket) {
|
|
173
|
-
|
|
170
|
+
/* eslint-disable ts/no-use-before-define */
|
|
174
171
|
const connection = new HAPConnection(this, socket);
|
|
175
172
|
connection.on("request" /* HAPConnectionEvent.REQUEST */, (request, response) => {
|
|
176
173
|
this.emit("request" /* EventedHTTPServerEvent.REQUEST */, connection, request, response);
|
|
177
174
|
});
|
|
178
175
|
connection.on("authenticated" /* HAPConnectionEvent.AUTHENTICATED */, this.handleConnectionAuthenticated.bind(this, connection));
|
|
179
176
|
connection.on("closed" /* HAPConnectionEvent.CLOSED */, this.handleConnectionClose.bind(this, connection));
|
|
177
|
+
/* eslint-enable ts/no-use-before-define */
|
|
180
178
|
this.connections.add(connection);
|
|
181
|
-
debug(
|
|
179
|
+
debug('[%s] New connection from client on interface %s (%s)', connection.remoteAddress, connection.networkInterface, connection.localAddress);
|
|
182
180
|
this.emit("connection-opened" /* EventedHTTPServerEvent.CONNECTION_OPENED */, connection);
|
|
183
181
|
if (this.connections.size >= EventedHTTPServer.CONNECTION_TIMEOUT_LIMIT && !this.connectionIdleTimeout) {
|
|
184
182
|
this.scheduleNextConnectionIdleTimeout();
|
|
@@ -228,12 +226,12 @@ class EventedHTTPServer extends events_1.EventEmitter {
|
|
|
228
226
|
}
|
|
229
227
|
}
|
|
230
228
|
}
|
|
231
|
-
exports.EventedHTTPServer = EventedHTTPServer;
|
|
232
229
|
/**
|
|
233
230
|
* @private
|
|
234
231
|
* @group HAP Accessory Server
|
|
235
232
|
*/
|
|
236
|
-
|
|
233
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
234
|
+
export var HAPConnectionState;
|
|
237
235
|
(function (HAPConnectionState) {
|
|
238
236
|
HAPConnectionState[HAPConnectionState["CONNECTING"] = 0] = "CONNECTING";
|
|
239
237
|
HAPConnectionState[HAPConnectionState["FULLY_SET_UP"] = 1] = "FULLY_SET_UP";
|
|
@@ -243,24 +241,25 @@ var HAPConnectionState;
|
|
|
243
241
|
HAPConnectionState[HAPConnectionState["TO_BE_TEARED_DOWN"] = 3] = "TO_BE_TEARED_DOWN";
|
|
244
242
|
HAPConnectionState[HAPConnectionState["CLOSING"] = 4] = "CLOSING";
|
|
245
243
|
HAPConnectionState[HAPConnectionState["CLOSED"] = 5] = "CLOSED";
|
|
246
|
-
})(HAPConnectionState || (
|
|
244
|
+
})(HAPConnectionState || (HAPConnectionState = {}));
|
|
247
245
|
/**
|
|
248
246
|
* @group HAP Accessory Server
|
|
249
247
|
*/
|
|
250
|
-
|
|
248
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
249
|
+
export var HAPConnectionEvent;
|
|
251
250
|
(function (HAPConnectionEvent) {
|
|
252
251
|
HAPConnectionEvent["REQUEST"] = "request";
|
|
253
252
|
HAPConnectionEvent["AUTHENTICATED"] = "authenticated";
|
|
254
253
|
HAPConnectionEvent["CLOSED"] = "closed";
|
|
255
|
-
})(HAPConnectionEvent || (
|
|
254
|
+
})(HAPConnectionEvent || (HAPConnectionEvent = {}));
|
|
256
255
|
/**
|
|
257
256
|
* Manages a single iOS-initiated HTTP connection during its lifetime.
|
|
258
257
|
* @group HAP Accessory Server
|
|
259
258
|
*/
|
|
260
|
-
// eslint-disable-next-line
|
|
261
|
-
class HAPConnection extends
|
|
259
|
+
// eslint-disable-next-line ts/no-unsafe-declaration-merging
|
|
260
|
+
export class HAPConnection extends EventEmitter {
|
|
262
261
|
/**
|
|
263
|
-
* @private
|
|
262
|
+
* @private
|
|
264
263
|
*/
|
|
265
264
|
server;
|
|
266
265
|
sessionID; // uuid unique to every HAP connection
|
|
@@ -294,58 +293,53 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
294
293
|
constructor(server, clientSocket) {
|
|
295
294
|
super();
|
|
296
295
|
this.server = server;
|
|
297
|
-
this.sessionID =
|
|
296
|
+
this.sessionID = generate(`${clientSocket.remoteAddress}:${clientSocket.remotePort}`);
|
|
298
297
|
this.localAddress = clientSocket.localAddress;
|
|
299
298
|
this.remoteAddress = clientSocket.remoteAddress; // cache because it becomes undefined in 'onClientSocketClose'
|
|
300
299
|
this.remotePort = clientSocket.remotePort;
|
|
301
300
|
this.networkInterface = HAPConnection.getLocalNetworkInterface(clientSocket);
|
|
302
301
|
// clientSocket is the socket connected to the actual iOS device
|
|
303
302
|
this.tcpSocket = clientSocket;
|
|
304
|
-
this.tcpSocket.on(
|
|
305
|
-
this.tcpSocket.on(
|
|
303
|
+
this.tcpSocket.on('data', this.onTCPSocketData.bind(this));
|
|
304
|
+
this.tcpSocket.on('close', this.onTCPSocketClose.bind(this));
|
|
306
305
|
// we MUST register for this event, otherwise the error will bubble up to the top and crash the node process entirely.
|
|
307
|
-
this.tcpSocket.on(
|
|
306
|
+
this.tcpSocket.on('error', this.onTCPSocketError.bind(this));
|
|
308
307
|
this.tcpSocket.setNoDelay(true); // disable Nagle algorithm
|
|
309
308
|
// "HAP accessory servers must not use keepalive messages, which periodically wake up iOS devices".
|
|
310
309
|
// Thus, we don't configure any tcp keepalive
|
|
311
310
|
// create our internal HTTP server for this connection that we will proxy data to and from
|
|
312
|
-
this.internalHttpServer =
|
|
311
|
+
this.internalHttpServer = createHttpServer();
|
|
313
312
|
this.internalHttpServer.timeout = 0; // clients expect to hold connections open as long as they want
|
|
314
313
|
this.internalHttpServer.keepAliveTimeout = 0; // workaround for https://github.com/nodejs/node/issues/13391
|
|
315
|
-
this.internalHttpServer.on(
|
|
316
|
-
this.internalHttpServer.on(
|
|
317
|
-
this.internalHttpServer.on(
|
|
314
|
+
this.internalHttpServer.on('listening', this.onHttpServerListening.bind(this));
|
|
315
|
+
this.internalHttpServer.on('request', this.handleHttpServerRequest.bind(this));
|
|
316
|
+
this.internalHttpServer.on('error', this.onHttpServerError.bind(this));
|
|
318
317
|
// close event is added later on the "connect" event as possible listen retries would throw unnecessary close events
|
|
319
|
-
this.internalHttpServer.listen(0, this.internalHttpServerAddress =
|
|
318
|
+
this.internalHttpServer.listen(0, this.internalHttpServerAddress = getOSLoopbackAddressIfAvailable());
|
|
320
319
|
}
|
|
321
320
|
debugListenerRegistration(event, registration = true, beforeCount = -1) {
|
|
322
|
-
const stackTrace = new Error().stack.split(
|
|
321
|
+
const stackTrace = new Error().stack.split('\n')[3]; // eslint-disable-line unicorn/error-message
|
|
323
322
|
const eventCount = this.listeners(event).length;
|
|
324
|
-
const tabs1 = event === "authenticated" /* HAPConnectionEvent.AUTHENTICATED */ ?
|
|
325
|
-
const tabs2 = !registration ?
|
|
326
|
-
|
|
327
|
-
debugEvents(`[${this.remoteAddress}] ${registration ? "Registered" : "Unregistered"} event '${String(event).toUpperCase()}' ${tabs1}(total: ${eventCount}${!registration ? " Before: " + beforeCount : ""}) ${tabs2}${stackTrace}`);
|
|
323
|
+
const tabs1 = event === "authenticated" /* HAPConnectionEvent.AUTHENTICATED */ ? '\t' : '\t\t';
|
|
324
|
+
const tabs2 = !registration ? '\t' : '\t\t';
|
|
325
|
+
debugEvents(`[${this.remoteAddress}] ${registration ? 'Registered' : 'Unregistered'} event '${String(event).toUpperCase()}' ${tabs1}(total: ${eventCount}${!registration ? ` Before: ${beforeCount}` : ''}) ${tabs2}${stackTrace}`);
|
|
328
326
|
}
|
|
329
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
330
327
|
on(event, listener) {
|
|
331
328
|
const result = super.on(event, listener);
|
|
332
329
|
this.debugListenerRegistration(event);
|
|
333
330
|
return result;
|
|
334
331
|
}
|
|
335
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
336
332
|
addListener(event, listener) {
|
|
337
333
|
const result = super.addListener(event, listener);
|
|
338
334
|
this.debugListenerRegistration(event);
|
|
339
335
|
return result;
|
|
340
336
|
}
|
|
341
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
342
337
|
removeListener(event, listener) {
|
|
343
338
|
const beforeCount = this.listeners(event).length;
|
|
344
339
|
const result = super.removeListener(event, listener);
|
|
345
340
|
this.debugListenerRegistration(event, false, beforeCount);
|
|
346
341
|
return result;
|
|
347
342
|
}
|
|
348
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
349
343
|
off(event, listener) {
|
|
350
344
|
const result = super.off(event, listener);
|
|
351
345
|
const beforeCount = this.listeners(event).length;
|
|
@@ -386,17 +380,17 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
386
380
|
}
|
|
387
381
|
}
|
|
388
382
|
sendEvent(aid, iid, value, immediateDelivery) {
|
|
389
|
-
(
|
|
390
|
-
(
|
|
391
|
-
const eventName = aid
|
|
383
|
+
assert(aid != null, 'HAPConnection.sendEvent: aid must be defined!');
|
|
384
|
+
assert(iid != null, 'HAPConnection.sendEvent: iid must be defined!');
|
|
385
|
+
const eventName = `${aid}.${iid}`;
|
|
392
386
|
if (!this.registeredEvents.has(eventName)) {
|
|
393
387
|
// non verified connections can't register events, so this case is covered!
|
|
394
388
|
return;
|
|
395
389
|
}
|
|
396
390
|
const event = {
|
|
397
|
-
aid
|
|
398
|
-
iid
|
|
399
|
-
value
|
|
391
|
+
aid,
|
|
392
|
+
iid,
|
|
393
|
+
value,
|
|
400
394
|
};
|
|
401
395
|
if (immediateDelivery) {
|
|
402
396
|
// some characteristics are required to deliver notifications immediately
|
|
@@ -450,7 +444,7 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
450
444
|
characteristics: [],
|
|
451
445
|
};
|
|
452
446
|
for (const queuedEvent of this.queuedEvents) {
|
|
453
|
-
if (!this.registeredEvents.has(queuedEvent.aid
|
|
447
|
+
if (!this.registeredEvents.has(`${queuedEvent.aid}.${queuedEvent.iid}`)) {
|
|
454
448
|
continue; // client unregistered that event in the meantime
|
|
455
449
|
}
|
|
456
450
|
eventData.characteristics.push(queuedEvent);
|
|
@@ -467,27 +461,27 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
467
461
|
* @param notification - The event which should be sent out
|
|
468
462
|
*/
|
|
469
463
|
writeEventNotification(notification) {
|
|
470
|
-
debugCon(
|
|
471
|
-
(
|
|
464
|
+
debugCon('[%s] Sending HAP event notifications %o', this.remoteAddress, notification.characteristics);
|
|
465
|
+
assert(!this.handlingRequest, 'Can\'t write event notifications while handling a request!');
|
|
472
466
|
// Apple backend processes events in reverse order, so we need to reverse the array
|
|
473
467
|
// so that events are processed in chronological order.
|
|
474
468
|
notification.characteristics.reverse();
|
|
475
|
-
const dataBuffer = Buffer.from(JSON.stringify(notification),
|
|
476
|
-
const header = Buffer.from(
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
469
|
+
const dataBuffer = Buffer.from(JSON.stringify(notification), 'utf8');
|
|
470
|
+
const header = Buffer.from(`EVENT/1.0 200 OK\r\n`
|
|
471
|
+
+ `Content-Type: application/hap+json\r\n`
|
|
472
|
+
+ `Content-Length: ${dataBuffer.length}\r\n`
|
|
473
|
+
+ `\r\n`, 'utf8');
|
|
480
474
|
const buffer = Buffer.concat([header, dataBuffer]);
|
|
481
475
|
this.tcpSocket.write(this.encrypt(buffer), this.handleTCPSocketWriteFulfilled.bind(this));
|
|
482
476
|
}
|
|
483
477
|
enableEventNotifications(aid, iid) {
|
|
484
|
-
this.registeredEvents.add(aid
|
|
478
|
+
this.registeredEvents.add(`${aid}.${iid}`);
|
|
485
479
|
}
|
|
486
480
|
disableEventNotifications(aid, iid) {
|
|
487
|
-
this.registeredEvents.delete(aid
|
|
481
|
+
this.registeredEvents.delete(`${aid}.${iid}`);
|
|
488
482
|
}
|
|
489
483
|
hasEventNotifications(aid, iid) {
|
|
490
|
-
return this.registeredEvents.has(aid
|
|
484
|
+
return this.registeredEvents.has(`${aid}.${iid}`);
|
|
491
485
|
}
|
|
492
486
|
getRegisteredEvents() {
|
|
493
487
|
return this.registeredEvents;
|
|
@@ -501,37 +495,37 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
501
495
|
// Since all communication calls are asynchronous, we could easily receive this 'encrypt' event for those bytes.
|
|
502
496
|
// So we want to make sure that we aren't encrypting data until we have *received* some encrypted data from the client first.
|
|
503
497
|
if (this.encryption && this.encryption.accessoryToControllerKey.length > 0 && this.encryption.controllerToAccessoryCount > 0) {
|
|
504
|
-
return
|
|
498
|
+
return layerEncrypt(data, this.encryption);
|
|
505
499
|
}
|
|
506
500
|
return data; // otherwise, we don't encrypt and return plaintext
|
|
507
501
|
}
|
|
508
502
|
decrypt(data) {
|
|
509
503
|
if (this.encryption && this.encryption.controllerToAccessoryKey.length > 0) {
|
|
510
504
|
// below call may throw an error if decryption failed
|
|
511
|
-
return
|
|
505
|
+
return layerDecrypt(data, this.encryption);
|
|
512
506
|
}
|
|
513
507
|
return data; // otherwise, we don't decrypt and return plaintext
|
|
514
508
|
}
|
|
515
509
|
onHttpServerListening() {
|
|
516
510
|
const addressInfo = this.internalHttpServer.address(); // address() is only a string when listening to unix domain sockets
|
|
517
|
-
const addressString = addressInfo.family ===
|
|
511
|
+
const addressString = addressInfo.family === 'IPv6' ? `[${addressInfo.address}]` : addressInfo.address;
|
|
518
512
|
this.internalHttpServerPort = addressInfo.port;
|
|
519
|
-
debugCon(
|
|
520
|
-
this.internalHttpServer.on(
|
|
513
|
+
debugCon('[%s] Internal HTTP server listening on %s:%s', this.remoteAddress, addressString, addressInfo.port);
|
|
514
|
+
this.internalHttpServer.on('close', this.onHttpServerClose.bind(this));
|
|
521
515
|
// now we can establish a connection to this running HTTP server for proxying data
|
|
522
|
-
this.httpSocket =
|
|
516
|
+
this.httpSocket = createConnection(this.internalHttpServerPort, this.internalHttpServerAddress); // previously we used addressInfo.address
|
|
523
517
|
this.httpSocket.setNoDelay(true); // disable Nagle algorithm
|
|
524
|
-
this.httpSocket.on(
|
|
518
|
+
this.httpSocket.on('data', this.handleHttpServerResponse.bind(this));
|
|
525
519
|
// we MUST register for this event, otherwise the error will bubble up to the top and crash the node process entirely.
|
|
526
|
-
this.httpSocket.on(
|
|
527
|
-
this.httpSocket.on(
|
|
528
|
-
this.httpSocket.on(
|
|
520
|
+
this.httpSocket.on('error', this.onHttpSocketError.bind(this));
|
|
521
|
+
this.httpSocket.on('close', this.onHttpSocketClose.bind(this));
|
|
522
|
+
this.httpSocket.on('connect', () => {
|
|
529
523
|
// we are now fully set up:
|
|
530
524
|
// - clientSocket is connected to the iOS device
|
|
531
525
|
// - serverSocket is connected to the httpServer
|
|
532
526
|
// - ready to proxy data!
|
|
533
527
|
this.state = 1 /* HAPConnectionState.FULLY_SET_UP */;
|
|
534
|
-
debugCon(
|
|
528
|
+
debugCon('[%s] Internal HTTP socket connected. HAPConnection now fully set up!', this.remoteAddress);
|
|
535
529
|
// start by flushing any pending buffered data received from the client while we were setting up
|
|
536
530
|
if (this.pendingClientSocketData && this.pendingClientSocketData.length > 0) {
|
|
537
531
|
this.httpSocket.write(this.pendingClientSocketData);
|
|
@@ -554,7 +548,7 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
554
548
|
data = this.decrypt(data);
|
|
555
549
|
}
|
|
556
550
|
catch (error) { // decryption and/or verification failed, disconnect the client
|
|
557
|
-
debugCon(
|
|
551
|
+
debugCon('[%s] Error occurred trying to decrypt incoming packet: %s', this.remoteAddress, error.message);
|
|
558
552
|
this.close();
|
|
559
553
|
return;
|
|
560
554
|
}
|
|
@@ -575,7 +569,7 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
575
569
|
// don't accept data of a connection which is about to be closed or already closed
|
|
576
570
|
return;
|
|
577
571
|
}
|
|
578
|
-
debugCon(
|
|
572
|
+
debugCon('[%s] HTTP request: %s', this.remoteAddress, request.url);
|
|
579
573
|
request.socket.setNoDelay(true);
|
|
580
574
|
this.emit("request" /* HAPConnectionEvent.REQUEST */, request, response);
|
|
581
575
|
}
|
|
@@ -587,7 +581,7 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
587
581
|
handleHttpServerResponse(data) {
|
|
588
582
|
data = this.encrypt(data);
|
|
589
583
|
this.tcpSocket.write(data, this.handleTCPSocketWriteFulfilled.bind(this));
|
|
590
|
-
debugCon(
|
|
584
|
+
debugCon('[%s] HTTP Response is finished', this.remoteAddress);
|
|
591
585
|
this.handlingRequest = false;
|
|
592
586
|
if (this.state === 3 /* HAPConnectionState.TO_BE_TEARED_DOWN */) {
|
|
593
587
|
setTimeout(() => this.close(), 10);
|
|
@@ -604,12 +598,12 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
604
598
|
this.lastSocketOperation = new Date().getTime();
|
|
605
599
|
}
|
|
606
600
|
onTCPSocketError(err) {
|
|
607
|
-
debugCon(
|
|
601
|
+
debugCon('[%s] Client connection error: %s', this.remoteAddress, err.message);
|
|
608
602
|
// onTCPSocketClose will be called next
|
|
609
603
|
}
|
|
610
604
|
onTCPSocketClose() {
|
|
611
605
|
this.state = 5 /* HAPConnectionState.CLOSED */;
|
|
612
|
-
debugCon(
|
|
606
|
+
debugCon('[%s] Client connection closed', this.remoteAddress);
|
|
613
607
|
if (this.httpSocket) {
|
|
614
608
|
this.httpSocket.destroy();
|
|
615
609
|
}
|
|
@@ -618,43 +612,43 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
618
612
|
this.removeAllListeners(); // cleanup listeners, we are officially dead now
|
|
619
613
|
}
|
|
620
614
|
onHttpServerError(err) {
|
|
621
|
-
debugCon(
|
|
622
|
-
if (err.code ===
|
|
615
|
+
debugCon('[%s] HTTP server error: %s', this.remoteAddress, err.message);
|
|
616
|
+
if (err.code === 'EADDRINUSE') {
|
|
623
617
|
this.internalHttpServerPort = undefined;
|
|
624
618
|
this.internalHttpServer.close();
|
|
625
|
-
this.internalHttpServer.listen(0, this.internalHttpServerAddress =
|
|
619
|
+
this.internalHttpServer.listen(0, this.internalHttpServerAddress = getOSLoopbackAddressIfAvailable());
|
|
626
620
|
}
|
|
627
621
|
}
|
|
628
622
|
onHttpServerClose() {
|
|
629
|
-
debugCon(
|
|
623
|
+
debugCon('[%s] HTTP server was closed', this.remoteAddress);
|
|
630
624
|
// make sure the iOS side is closed as well
|
|
631
625
|
this.close();
|
|
632
626
|
}
|
|
633
627
|
onHttpSocketError(err) {
|
|
634
|
-
debugCon(
|
|
628
|
+
debugCon('[%s] HTTP connection error: ', this.remoteAddress, err.message);
|
|
635
629
|
// onHttpSocketClose will be called next
|
|
636
630
|
}
|
|
637
631
|
onHttpSocketClose() {
|
|
638
|
-
debugCon(
|
|
632
|
+
debugCon('[%s] HTTP connection was closed', this.remoteAddress);
|
|
639
633
|
// we only support a single long-lived connection to our internal HTTP server. Since it's closed,
|
|
640
634
|
// we'll need to shut it down entirely.
|
|
641
635
|
this.internalHttpServer.close();
|
|
642
636
|
}
|
|
643
637
|
getLocalAddress(ipVersion) {
|
|
644
|
-
const interfaceDetails =
|
|
638
|
+
const interfaceDetails = networkInterfaces()[this.networkInterface];
|
|
645
639
|
if (!interfaceDetails) {
|
|
646
|
-
throw new Error(
|
|
640
|
+
throw new Error(`Could not find ${ipVersion} address for interface ${this.networkInterface}`);
|
|
647
641
|
}
|
|
648
642
|
// Find our first local IPv4 address.
|
|
649
|
-
if (ipVersion ===
|
|
650
|
-
const ipv4Info = interfaceDetails.find(info => info.family ===
|
|
643
|
+
if (ipVersion === 'ipv4') {
|
|
644
|
+
const ipv4Info = interfaceDetails.find(info => info.family === 'IPv4');
|
|
651
645
|
if (ipv4Info) {
|
|
652
646
|
return ipv4Info.address;
|
|
653
647
|
}
|
|
654
|
-
throw new Error(
|
|
648
|
+
throw new Error(`Could not find ${ipVersion} address for interface ${this.networkInterface}.`);
|
|
655
649
|
}
|
|
656
650
|
let localUniqueAddress;
|
|
657
|
-
for (const v6entry of interfaceDetails.filter(entry => entry.family ===
|
|
651
|
+
for (const v6entry of interfaceDetails.filter(entry => entry.family === 'IPv6')) {
|
|
658
652
|
if (!v6entry.scopeid) {
|
|
659
653
|
return v6entry.address;
|
|
660
654
|
}
|
|
@@ -663,26 +657,26 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
663
657
|
if (localUniqueAddress) {
|
|
664
658
|
return localUniqueAddress;
|
|
665
659
|
}
|
|
666
|
-
throw new Error(
|
|
660
|
+
throw new Error(`Could not find ${ipVersion} address for interface ${this.networkInterface}`);
|
|
667
661
|
}
|
|
668
662
|
static getLocalNetworkInterface(socket) {
|
|
669
663
|
let localAddress = socket.localAddress;
|
|
670
664
|
// Grab the list of network interfaces.
|
|
671
|
-
const interfaces =
|
|
665
|
+
const interfaces = networkInterfaces();
|
|
672
666
|
// Default to the first non-loopback interface we see.
|
|
673
|
-
const defaultInterface = () => Object.entries(interfaces).find(([, addresses]) => addresses?.some(address => !address.internal))?.[0] ??
|
|
667
|
+
const defaultInterface = () => Object.entries(interfaces).find(([, addresses]) => addresses?.some(address => !address.internal))?.[0] ?? 'unknown';
|
|
674
668
|
// No local address return our default.
|
|
675
669
|
if (!localAddress) {
|
|
676
670
|
return defaultInterface();
|
|
677
671
|
}
|
|
678
672
|
// Handle IPv4-mapped IPv6 addresses.
|
|
679
|
-
localAddress = localAddress.replace(/^::ffff:/i,
|
|
673
|
+
localAddress = localAddress.replace(/^::ffff:/i, '');
|
|
680
674
|
// Handle edge cases where we have an IPv4-mapped IPv6 address without the requisite prefix.
|
|
681
675
|
if (/^::(?:\d{1,3}\.){3}\d{1,3}$/.test(localAddress)) {
|
|
682
|
-
localAddress = localAddress.replace(/^::/,
|
|
676
|
+
localAddress = localAddress.replace(/^::/, '');
|
|
683
677
|
}
|
|
684
678
|
// Handle link-local IPv6 addresses.
|
|
685
|
-
localAddress = localAddress.split(
|
|
679
|
+
localAddress = localAddress.split('%')[0];
|
|
686
680
|
// Let's find an exact match using the IP.
|
|
687
681
|
for (const [name, addresses] of Object.entries(interfaces)) {
|
|
688
682
|
if (addresses?.some(({ address }) => address === localAddress)) {
|
|
@@ -690,17 +684,16 @@ class HAPConnection extends events_1.EventEmitter {
|
|
|
690
684
|
}
|
|
691
685
|
}
|
|
692
686
|
// We couldn't find an interface to match the address from above, so we attempt to match subnets (see https://github.com/homebridge/HAP-NodeJS/issues/847).
|
|
693
|
-
const family =
|
|
687
|
+
const family = isIPv4(localAddress) ? 'IPv4' : 'IPv6';
|
|
694
688
|
// Let's find a match based on the subnet.
|
|
695
689
|
for (const [name, addresses] of Object.entries(interfaces)) {
|
|
696
|
-
if (addresses?.some(entry => entry.family === family &&
|
|
690
|
+
if (addresses?.some(entry => entry.family === family && getNetAddress(localAddress, entry.netmask) === getNetAddress(entry.address, entry.netmask))) {
|
|
697
691
|
return name;
|
|
698
692
|
}
|
|
699
693
|
}
|
|
700
|
-
|
|
701
|
-
|
|
694
|
+
// eslint-disable-next-line no-console
|
|
695
|
+
console.log(`WARNING: unable to determine which interface to use for socket coming from ${socket.remoteAddress}:${socket.remotePort} to ${socket.localAddress}.`);
|
|
702
696
|
return defaultInterface();
|
|
703
697
|
}
|
|
704
698
|
}
|
|
705
|
-
exports.HAPConnection = HAPConnection;
|
|
706
699
|
//# sourceMappingURL=eventedhttp.js.map
|