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,28 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const hapCrypto = tslib_1.__importStar(require("../util/hapCrypto"));
|
|
11
|
-
const DataStreamParser_1 = require("./DataStreamParser");
|
|
12
|
-
const debug = (0, debug_1.default)("HAP-NodeJS:DataStream:Server");
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
3
|
+
import { randomBytes } from 'node:crypto';
|
|
4
|
+
import { EventEmitter, EventEmitter as NodeEventEmitter } from 'node:events';
|
|
5
|
+
import { createServer } from 'node:net';
|
|
6
|
+
import createDebug from 'debug';
|
|
7
|
+
import { chacha20_poly1305_decryptAndVerify, chacha20_poly1305_encryptAndSeal, HKDF, writeUInt64LE, } from '../util/hapCrypto.js';
|
|
8
|
+
import { DataStreamParser, DataStreamReader, DataStreamWriter, Int64 } from './DataStreamParser.js';
|
|
9
|
+
const debug = createDebug('HAP-NodeJS:DataStream:Server');
|
|
13
10
|
/**
|
|
14
11
|
* @group HomeKit Data Streams (HDS)
|
|
15
12
|
*/
|
|
16
|
-
|
|
13
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
14
|
+
export var Protocols;
|
|
17
15
|
(function (Protocols) {
|
|
18
16
|
Protocols["CONTROL"] = "control";
|
|
19
17
|
Protocols["TARGET_CONTROL"] = "targetControl";
|
|
20
18
|
Protocols["DATA_SEND"] = "dataSend";
|
|
21
|
-
})(Protocols || (
|
|
19
|
+
})(Protocols || (Protocols = {}));
|
|
22
20
|
/**
|
|
23
21
|
* @group HomeKit Data Streams (HDS)
|
|
24
22
|
*/
|
|
25
|
-
|
|
23
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
24
|
+
export var Topics;
|
|
26
25
|
(function (Topics) {
|
|
27
26
|
// control
|
|
28
27
|
Topics["HELLO"] = "hello";
|
|
@@ -33,13 +32,12 @@ var Topics;
|
|
|
33
32
|
Topics["DATA"] = "data";
|
|
34
33
|
Topics["ACK"] = "ack";
|
|
35
34
|
Topics["CLOSE"] = "close";
|
|
36
|
-
})(Topics || (
|
|
35
|
+
})(Topics || (Topics = {}));
|
|
37
36
|
/**
|
|
38
37
|
* @group HomeKit Data Streams (HDS)
|
|
39
38
|
*/
|
|
40
|
-
var HDSStatus;
|
|
39
|
+
export var HDSStatus;
|
|
41
40
|
(function (HDSStatus) {
|
|
42
|
-
// noinspection JSUnusedGlobalSymbols
|
|
43
41
|
HDSStatus[HDSStatus["SUCCESS"] = 0] = "SUCCESS";
|
|
44
42
|
HDSStatus[HDSStatus["OUT_OF_MEMORY"] = 1] = "OUT_OF_MEMORY";
|
|
45
43
|
HDSStatus[HDSStatus["TIMEOUT"] = 2] = "TIMEOUT";
|
|
@@ -47,13 +45,13 @@ var HDSStatus;
|
|
|
47
45
|
HDSStatus[HDSStatus["PAYLOAD_ERROR"] = 4] = "PAYLOAD_ERROR";
|
|
48
46
|
HDSStatus[HDSStatus["MISSING_PROTOCOL"] = 5] = "MISSING_PROTOCOL";
|
|
49
47
|
HDSStatus[HDSStatus["PROTOCOL_SPECIFIC_ERROR"] = 6] = "PROTOCOL_SPECIFIC_ERROR";
|
|
50
|
-
})(HDSStatus || (
|
|
48
|
+
})(HDSStatus || (HDSStatus = {}));
|
|
51
49
|
/**
|
|
52
50
|
* @group HomeKit Data Streams (HDS)
|
|
53
51
|
*/
|
|
54
|
-
|
|
52
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
53
|
+
export var HDSProtocolSpecificErrorReason;
|
|
55
54
|
(function (HDSProtocolSpecificErrorReason) {
|
|
56
|
-
// noinspection JSUnusedGlobalSymbols
|
|
57
55
|
HDSProtocolSpecificErrorReason[HDSProtocolSpecificErrorReason["NORMAL"] = 0] = "NORMAL";
|
|
58
56
|
HDSProtocolSpecificErrorReason[HDSProtocolSpecificErrorReason["NOT_ALLOWED"] = 1] = "NOT_ALLOWED";
|
|
59
57
|
HDSProtocolSpecificErrorReason[HDSProtocolSpecificErrorReason["BUSY"] = 2] = "BUSY";
|
|
@@ -64,26 +62,26 @@ var HDSProtocolSpecificErrorReason;
|
|
|
64
62
|
HDSProtocolSpecificErrorReason[HDSProtocolSpecificErrorReason["BAD_DATA"] = 7] = "BAD_DATA";
|
|
65
63
|
HDSProtocolSpecificErrorReason[HDSProtocolSpecificErrorReason["PROTOCOL_ERROR"] = 8] = "PROTOCOL_ERROR";
|
|
66
64
|
HDSProtocolSpecificErrorReason[HDSProtocolSpecificErrorReason["INVALID_CONFIGURATION"] = 9] = "INVALID_CONFIGURATION";
|
|
67
|
-
})(HDSProtocolSpecificErrorReason || (
|
|
65
|
+
})(HDSProtocolSpecificErrorReason || (HDSProtocolSpecificErrorReason = {}));
|
|
68
66
|
/**
|
|
69
67
|
* An error indicating a protocol level HDS error.
|
|
70
68
|
* E.g. it may be used to encode a {@link HDSStatus.PROTOCOL_SPECIFIC_ERROR} in the {@link Protocols.DATA_SEND} protocol.
|
|
71
69
|
* @group HomeKit Data Streams (HDS)
|
|
72
70
|
*/
|
|
73
|
-
class HDSProtocolError extends Error {
|
|
71
|
+
export class HDSProtocolError extends Error {
|
|
74
72
|
reason;
|
|
75
73
|
/**
|
|
76
74
|
* Initializes a new `HDSProtocolError`
|
|
77
75
|
* @param reason - The {@link HDSProtocolSpecificErrorReason}.
|
|
78
|
-
*
|
|
76
|
+
* Values MUST NOT be {@link HDSProtocolSpecificErrorReason.NORMAL}.
|
|
79
77
|
*/
|
|
80
78
|
constructor(reason) {
|
|
81
|
-
super(
|
|
82
|
-
(
|
|
79
|
+
super(`HDSProtocolError: ${reason}`);
|
|
80
|
+
assert(reason !== 0 /* HDSProtocolSpecificErrorReason.NORMAL */, 'Cannot initialize a HDSProtocolError with NORMAL!');
|
|
83
81
|
this.reason = reason;
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
|
-
|
|
84
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
87
85
|
var ServerState;
|
|
88
86
|
(function (ServerState) {
|
|
89
87
|
ServerState[ServerState["UNINITIALIZED"] = 0] = "UNINITIALIZED";
|
|
@@ -91,6 +89,7 @@ var ServerState;
|
|
|
91
89
|
ServerState[ServerState["LISTENING"] = 2] = "LISTENING";
|
|
92
90
|
ServerState[ServerState["CLOSING"] = 3] = "CLOSING";
|
|
93
91
|
})(ServerState || (ServerState = {}));
|
|
92
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
94
93
|
var ConnectionState;
|
|
95
94
|
(function (ConnectionState) {
|
|
96
95
|
ConnectionState[ConnectionState["UNIDENTIFIED"] = 0] = "UNIDENTIFIED";
|
|
@@ -102,16 +101,18 @@ var ConnectionState;
|
|
|
102
101
|
/**
|
|
103
102
|
* @group HomeKit Data Streams (HDS)
|
|
104
103
|
*/
|
|
105
|
-
|
|
104
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
105
|
+
export var MessageType;
|
|
106
106
|
(function (MessageType) {
|
|
107
107
|
MessageType[MessageType["EVENT"] = 1] = "EVENT";
|
|
108
108
|
MessageType[MessageType["REQUEST"] = 2] = "REQUEST";
|
|
109
109
|
MessageType[MessageType["RESPONSE"] = 3] = "RESPONSE";
|
|
110
|
-
})(MessageType || (
|
|
110
|
+
})(MessageType || (MessageType = {}));
|
|
111
111
|
/**
|
|
112
112
|
* @group HomeKit Data Streams (HDS)
|
|
113
113
|
*/
|
|
114
|
-
|
|
114
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
115
|
+
export var DataStreamServerEvent;
|
|
115
116
|
(function (DataStreamServerEvent) {
|
|
116
117
|
/**
|
|
117
118
|
* This event is emitted when a new client socket is received. At this point we have no idea to what
|
|
@@ -122,23 +123,23 @@ var DataStreamServerEvent;
|
|
|
122
123
|
* This event is emitted when the socket of a connection gets closed.
|
|
123
124
|
*/
|
|
124
125
|
DataStreamServerEvent["CONNECTION_CLOSED"] = "connection-closed";
|
|
125
|
-
})(DataStreamServerEvent || (
|
|
126
|
+
})(DataStreamServerEvent || (DataStreamServerEvent = {}));
|
|
126
127
|
/**
|
|
127
128
|
* DataStreamServer which listens for incoming tcp connections and handles identification of new connections
|
|
128
129
|
* @group HomeKit Data Streams (HDS)
|
|
129
130
|
*/
|
|
130
|
-
// eslint-disable-next-line
|
|
131
|
-
class DataStreamServer extends
|
|
132
|
-
static version =
|
|
131
|
+
// eslint-disable-next-line ts/no-unsafe-declaration-merging
|
|
132
|
+
export class DataStreamServer extends EventEmitter {
|
|
133
|
+
static version = '1.0';
|
|
133
134
|
state = 0 /* ServerState.UNINITIALIZED */;
|
|
134
|
-
static accessoryToControllerInfo = Buffer.from(
|
|
135
|
-
static controllerToAccessoryInfo = Buffer.from(
|
|
135
|
+
static accessoryToControllerInfo = Buffer.from('HDS-Read-Encryption-Key');
|
|
136
|
+
static controllerToAccessoryInfo = Buffer.from('HDS-Write-Encryption-Key');
|
|
136
137
|
tcpServer;
|
|
137
138
|
tcpPort;
|
|
138
139
|
preparedSessions = [];
|
|
139
140
|
connections = [];
|
|
140
141
|
removeListenersOnceClosed = false;
|
|
141
|
-
internalEventEmitter = new
|
|
142
|
+
internalEventEmitter = new NodeEventEmitter(); // used for message event and message request handlers
|
|
142
143
|
constructor() {
|
|
143
144
|
super();
|
|
144
145
|
}
|
|
@@ -152,7 +153,7 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
152
153
|
* @param handler - function to be called for every occurring event
|
|
153
154
|
*/
|
|
154
155
|
onEventMessage(protocol, event, handler) {
|
|
155
|
-
this.internalEventEmitter.on(protocol
|
|
156
|
+
this.internalEventEmitter.on(`${protocol}-e-${event}`, handler);
|
|
156
157
|
return this;
|
|
157
158
|
}
|
|
158
159
|
/**
|
|
@@ -163,7 +164,7 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
163
164
|
* @param handler - registered event handler
|
|
164
165
|
*/
|
|
165
166
|
removeEventHandler(protocol, event, handler) {
|
|
166
|
-
this.internalEventEmitter.removeListener(protocol
|
|
167
|
+
this.internalEventEmitter.removeListener(`${protocol}-e-${event}`, handler);
|
|
167
168
|
return this;
|
|
168
169
|
}
|
|
169
170
|
/**
|
|
@@ -176,7 +177,7 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
176
177
|
* @param handler - function to be called for every occurring request
|
|
177
178
|
*/
|
|
178
179
|
onRequestMessage(protocol, request, handler) {
|
|
179
|
-
this.internalEventEmitter.on(protocol
|
|
180
|
+
this.internalEventEmitter.on(`${protocol}-r-${request}`, handler);
|
|
180
181
|
return this;
|
|
181
182
|
}
|
|
182
183
|
/**
|
|
@@ -187,20 +188,20 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
187
188
|
* @param handler - registered request handler
|
|
188
189
|
*/
|
|
189
190
|
removeRequestHandler(protocol, request, handler) {
|
|
190
|
-
this.internalEventEmitter.removeListener(protocol
|
|
191
|
+
this.internalEventEmitter.removeListener(`${protocol}-r-${request}`, handler);
|
|
191
192
|
return this;
|
|
192
193
|
}
|
|
193
194
|
prepareSession(connection, controllerKeySalt, callback) {
|
|
194
|
-
debug(
|
|
195
|
-
const accessoryKeySalt =
|
|
195
|
+
debug('Preparing for incoming HDS connection from %s', connection.sessionID);
|
|
196
|
+
const accessoryKeySalt = randomBytes(32);
|
|
196
197
|
const salt = Buffer.concat([controllerKeySalt, accessoryKeySalt]);
|
|
197
|
-
const accessoryToControllerEncryptionKey =
|
|
198
|
-
const controllerToAccessoryEncryptionKey =
|
|
198
|
+
const accessoryToControllerEncryptionKey = HKDF('sha512', salt, connection.encryption.sharedSecret, DataStreamServer.accessoryToControllerInfo, 32);
|
|
199
|
+
const controllerToAccessoryEncryptionKey = HKDF('sha512', salt, connection.encryption.sharedSecret, DataStreamServer.controllerToAccessoryInfo, 32);
|
|
199
200
|
const preparedSession = {
|
|
200
|
-
connection
|
|
201
|
-
accessoryToControllerEncryptionKey
|
|
202
|
-
controllerToAccessoryEncryptionKey
|
|
203
|
-
accessoryKeySalt
|
|
201
|
+
connection,
|
|
202
|
+
accessoryToControllerEncryptionKey,
|
|
203
|
+
controllerToAccessoryEncryptionKey,
|
|
204
|
+
accessoryKeySalt,
|
|
204
205
|
connectTimeout: setTimeout(() => this.timeoutPreparedSession(preparedSession), 10000),
|
|
205
206
|
};
|
|
206
207
|
preparedSession.connectTimeout.unref();
|
|
@@ -215,7 +216,7 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
215
216
|
});
|
|
216
217
|
}
|
|
217
218
|
timeoutPreparedSession(preparedSession) {
|
|
218
|
-
debug(
|
|
219
|
+
debug('Prepared HDS session timed out out since no connection was opened for 10 seconds (%s)', preparedSession.connection.sessionID);
|
|
219
220
|
const index = this.preparedSessions.indexOf(preparedSession);
|
|
220
221
|
if (index >= 0) {
|
|
221
222
|
this.preparedSessions.splice(index, 1);
|
|
@@ -225,51 +226,52 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
225
226
|
checkTCPServerEstablished(preparedSession, callback) {
|
|
226
227
|
switch (this.state) {
|
|
227
228
|
case 0 /* ServerState.UNINITIALIZED */:
|
|
228
|
-
debug(
|
|
229
|
-
this.tcpServer =
|
|
230
|
-
this.tcpServer.once(
|
|
231
|
-
this.tcpServer.on(
|
|
232
|
-
this.tcpServer.on(
|
|
229
|
+
debug('Starting up TCP server.');
|
|
230
|
+
this.tcpServer = createServer();
|
|
231
|
+
this.tcpServer.once('listening', this.listening.bind(this, preparedSession, callback));
|
|
232
|
+
this.tcpServer.on('connection', this.onConnection.bind(this));
|
|
233
|
+
this.tcpServer.on('close', this.closed.bind(this));
|
|
233
234
|
this.tcpServer.listen();
|
|
234
235
|
this.state = 1 /* ServerState.BINDING */;
|
|
235
236
|
break;
|
|
236
237
|
case 1 /* ServerState.BINDING */:
|
|
237
|
-
debug(
|
|
238
|
-
this.tcpServer.once(
|
|
238
|
+
debug('TCP server already running. Waiting for it to bind.');
|
|
239
|
+
this.tcpServer.once('listening', this.listening.bind(this, preparedSession, callback));
|
|
239
240
|
break;
|
|
240
241
|
case 2 /* ServerState.LISTENING */:
|
|
241
|
-
debug(
|
|
242
|
+
debug('Instructing client to connect to already running TCP server');
|
|
242
243
|
preparedSession.port = this.tcpPort;
|
|
243
244
|
callback();
|
|
244
245
|
break;
|
|
245
246
|
case 3 /* ServerState.CLOSING */:
|
|
246
|
-
debug(
|
|
247
|
-
this.tcpServer.once(
|
|
247
|
+
debug('TCP socket is currently closing. Trying again when server is fully closed and opening a new one then.');
|
|
248
|
+
this.tcpServer.once('close', () => setTimeout(() => this.checkTCPServerEstablished(preparedSession, callback), 10));
|
|
248
249
|
break;
|
|
249
250
|
}
|
|
250
251
|
}
|
|
251
252
|
listening(preparedSession, callback) {
|
|
252
253
|
this.state = 2 /* ServerState.LISTENING */;
|
|
253
254
|
const address = this.tcpServer.address();
|
|
254
|
-
if (address && typeof address !==
|
|
255
|
+
if (address && typeof address !== 'string') { // address is only typeof string when listening to a pipe or unix socket
|
|
255
256
|
this.tcpPort = address.port;
|
|
256
257
|
preparedSession.port = address.port;
|
|
257
|
-
debug(
|
|
258
|
+
debug('TCP server is now listening for new data stream connections on port %s', address.port);
|
|
258
259
|
callback();
|
|
259
260
|
}
|
|
260
261
|
}
|
|
261
262
|
onConnection(socket) {
|
|
262
|
-
debug(
|
|
263
|
-
// eslint-disable-
|
|
264
|
-
|
|
263
|
+
debug('[%s] New DataStream connection was established', socket.remoteAddress);
|
|
264
|
+
const connection = new DataStreamConnection(socket); // eslint-disable-line ts/no-use-before-define
|
|
265
|
+
/* eslint-disable ts/no-use-before-define */
|
|
265
266
|
connection.on("identification" /* DataStreamConnectionEvent.IDENTIFICATION */, this.handleSessionIdentification.bind(this, connection));
|
|
266
267
|
connection.on("handle-message-globally" /* DataStreamConnectionEvent.HANDLE_MESSAGE_GLOBALLY */, this.handleMessageGlobally.bind(this, connection));
|
|
267
268
|
connection.on("closed" /* DataStreamConnectionEvent.CLOSED */, this.connectionClosed.bind(this, connection));
|
|
269
|
+
/* eslint-enable ts/no-use-before-define */
|
|
268
270
|
this.connections.push(connection);
|
|
269
271
|
this.emit("connection-opened" /* DataStreamServerEvent.CONNECTION_OPENED */, connection);
|
|
270
272
|
}
|
|
271
273
|
handleSessionIdentification(connection, firstFrame, callback) {
|
|
272
|
-
let identifiedSession
|
|
274
|
+
let identifiedSession;
|
|
273
275
|
for (let i = 0; i < this.preparedSessions.length; i++) {
|
|
274
276
|
const preparedSession = this.preparedSessions[i];
|
|
275
277
|
// if we successfully decrypt the first frame with this key we know to which session this connection belongs
|
|
@@ -280,7 +282,7 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
280
282
|
}
|
|
281
283
|
callback(identifiedSession);
|
|
282
284
|
if (identifiedSession) {
|
|
283
|
-
debug(
|
|
285
|
+
debug('[%s] Connection was successfully identified (linked with sessionId: %s)', connection.remoteAddress, identifiedSession.connection.sessionID);
|
|
284
286
|
const index = this.preparedSessions.indexOf(identifiedSession);
|
|
285
287
|
if (index >= 0) {
|
|
286
288
|
this.preparedSessions.splice(index, 1);
|
|
@@ -292,19 +294,19 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
292
294
|
// on the other hand the keepAlive should handle that also :thinking:
|
|
293
295
|
}
|
|
294
296
|
else { // we looped through all session and didn't find anything
|
|
295
|
-
debug(
|
|
297
|
+
debug('[%s] Could not identify connection. Terminating.', connection.remoteAddress);
|
|
296
298
|
connection.close(); // disconnecting since first message was not a valid hello
|
|
297
299
|
}
|
|
298
300
|
}
|
|
299
301
|
handleMessageGlobally(connection, message) {
|
|
300
|
-
|
|
301
|
-
let separator =
|
|
302
|
+
assert.notStrictEqual(message.type, 3 /* MessageType.RESPONSE */); // responses can't physically get here
|
|
303
|
+
let separator = '';
|
|
302
304
|
const args = [];
|
|
303
305
|
if (message.type === 1 /* MessageType.EVENT */) {
|
|
304
|
-
separator =
|
|
306
|
+
separator = '-e-';
|
|
305
307
|
}
|
|
306
308
|
else if (message.type === 2 /* MessageType.REQUEST */) {
|
|
307
|
-
separator =
|
|
309
|
+
separator = '-r-';
|
|
308
310
|
args.push(message.id);
|
|
309
311
|
}
|
|
310
312
|
args.push(message.message);
|
|
@@ -314,15 +316,15 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
314
316
|
}
|
|
315
317
|
catch (error) {
|
|
316
318
|
hadListeners = true;
|
|
317
|
-
debug(
|
|
319
|
+
debug('[%s] Error occurred while dispatching handler for HDS message: %o', connection.remoteAddress, message);
|
|
318
320
|
debug(error.stack);
|
|
319
321
|
}
|
|
320
322
|
if (!hadListeners) {
|
|
321
|
-
debug(
|
|
323
|
+
debug('[%s] WARNING no handler was found for message: %o', connection.remoteAddress, message);
|
|
322
324
|
}
|
|
323
325
|
}
|
|
324
326
|
connectionClosed(connection) {
|
|
325
|
-
debug(
|
|
327
|
+
debug('[%s] DataStream connection closed', connection.remoteAddress);
|
|
326
328
|
this.connections.splice(this.connections.indexOf(connection), 1);
|
|
327
329
|
this.emit("connection-closed" /* DataStreamServerEvent.CONNECTION_CLOSED */, connection);
|
|
328
330
|
this.checkCloseable();
|
|
@@ -332,7 +334,7 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
332
334
|
}
|
|
333
335
|
checkCloseable() {
|
|
334
336
|
if (this.connections.length === 0 && this.preparedSessions.length === 0 && this.state < 3 /* ServerState.CLOSING */) {
|
|
335
|
-
debug(
|
|
337
|
+
debug('Last connection disconnected. Closing the server now.');
|
|
336
338
|
this.state = 3 /* ServerState.CLOSING */;
|
|
337
339
|
this.tcpServer.close();
|
|
338
340
|
}
|
|
@@ -357,11 +359,11 @@ class DataStreamServer extends events_1.EventEmitter {
|
|
|
357
359
|
this.state = 0 /* ServerState.UNINITIALIZED */;
|
|
358
360
|
}
|
|
359
361
|
}
|
|
360
|
-
exports.DataStreamServer = DataStreamServer;
|
|
361
362
|
/**
|
|
362
363
|
* @group HomeKit Data Streams (HDS)
|
|
363
364
|
*/
|
|
364
|
-
|
|
365
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
366
|
+
export var DataStreamConnectionEvent;
|
|
365
367
|
(function (DataStreamConnectionEvent) {
|
|
366
368
|
/**
|
|
367
369
|
* This event is emitted when the first HDSFrame is received from a new connection.
|
|
@@ -378,35 +380,35 @@ var DataStreamConnectionEvent;
|
|
|
378
380
|
* This event is emitted when the socket of the connection was closed.
|
|
379
381
|
*/
|
|
380
382
|
DataStreamConnectionEvent["CLOSED"] = "closed";
|
|
381
|
-
})(DataStreamConnectionEvent || (
|
|
383
|
+
})(DataStreamConnectionEvent || (DataStreamConnectionEvent = {}));
|
|
382
384
|
/**
|
|
383
385
|
* @group HomeKit Data Streams (HDS)
|
|
384
386
|
*/
|
|
385
|
-
|
|
387
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
388
|
+
export var HDSConnectionErrorType;
|
|
386
389
|
(function (HDSConnectionErrorType) {
|
|
387
390
|
HDSConnectionErrorType[HDSConnectionErrorType["ILLEGAL_STATE"] = 1] = "ILLEGAL_STATE";
|
|
388
391
|
HDSConnectionErrorType[HDSConnectionErrorType["CLOSED_SOCKET"] = 2] = "CLOSED_SOCKET";
|
|
389
392
|
HDSConnectionErrorType[HDSConnectionErrorType["MAX_PAYLOAD_LENGTH"] = 3] = "MAX_PAYLOAD_LENGTH";
|
|
390
|
-
})(HDSConnectionErrorType || (
|
|
393
|
+
})(HDSConnectionErrorType || (HDSConnectionErrorType = {}));
|
|
391
394
|
/**
|
|
392
395
|
* @group HomeKit Data Streams (HDS)
|
|
393
396
|
*/
|
|
394
|
-
class HDSConnectionError extends Error {
|
|
397
|
+
export class HDSConnectionError extends Error {
|
|
395
398
|
type;
|
|
396
399
|
constructor(message, type) {
|
|
397
400
|
super(message);
|
|
398
401
|
this.type = type;
|
|
399
402
|
}
|
|
400
403
|
}
|
|
401
|
-
exports.HDSConnectionError = HDSConnectionError;
|
|
402
404
|
/**
|
|
403
405
|
* DataStream connection which holds any necessary state information, encryption and decryption keys, manages
|
|
404
406
|
* protocol handlers and also handles sending and receiving of data stream frames.
|
|
405
407
|
*
|
|
406
408
|
* @group HomeKit Data Streams (HDS)
|
|
407
409
|
*/
|
|
408
|
-
// eslint-disable-next-line
|
|
409
|
-
class DataStreamConnection extends
|
|
410
|
+
// eslint-disable-next-line ts/no-unsafe-declaration-merging
|
|
411
|
+
export class DataStreamConnection extends EventEmitter {
|
|
410
412
|
static MAX_PAYLOAD_LENGTH = 0b11111111111111111111;
|
|
411
413
|
socket;
|
|
412
414
|
connection; // reference to the hap connection. is present when state > UNIDENTIFIED
|
|
@@ -447,12 +449,12 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
447
449
|
},
|
|
448
450
|
});
|
|
449
451
|
this.helloTimer = setTimeout(() => {
|
|
450
|
-
debug(
|
|
452
|
+
debug('[%s] Hello message did not arrive in time. Killing the connection', this.remoteAddress);
|
|
451
453
|
this.close();
|
|
452
454
|
}, 10000);
|
|
453
|
-
this.socket.on(
|
|
454
|
-
this.socket.on(
|
|
455
|
-
this.socket.on(
|
|
455
|
+
this.socket.on('data', this.onSocketData.bind(this));
|
|
456
|
+
this.socket.on('error', this.onSocketError.bind(this));
|
|
457
|
+
this.socket.on('close', this.onSocketClose.bind(this));
|
|
456
458
|
// this is to mitigate the event emitter "memory leak warning".
|
|
457
459
|
// e.g. with HSV there might be multiple cameras subscribing to the CLOSE event. one subscription for
|
|
458
460
|
// every active recording stream on a camera. The default limit of 10 might be easily reached.
|
|
@@ -460,10 +462,9 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
460
462
|
// a warning is still be printed if running long enough.
|
|
461
463
|
this.setMaxListeners(100);
|
|
462
464
|
}
|
|
463
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
464
465
|
handleHello(id, message) {
|
|
465
466
|
// that hello is indeed the _first_ message received is verified in onSocketData(...)
|
|
466
|
-
debug(
|
|
467
|
+
debug('[%s] Received hello message from client: %o', this.remoteAddress, message);
|
|
467
468
|
clearTimeout(this.helloTimer);
|
|
468
469
|
this.helloTimer = undefined;
|
|
469
470
|
this.state = 2 /* ConnectionState.READY */;
|
|
@@ -502,9 +503,7 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
502
503
|
* @param event - name of the event (also referred to as topic. See {@link Topics} for some known ones)
|
|
503
504
|
* @param message - message dictionary which gets sent along the event
|
|
504
505
|
*/
|
|
505
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
506
506
|
sendEvent(protocol, event, message = {}) {
|
|
507
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
508
507
|
const header = {};
|
|
509
508
|
header.protocol = protocol;
|
|
510
509
|
header.event = event;
|
|
@@ -519,9 +518,8 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
519
518
|
* @param request - name of the request (also referred to as topic. See {@link Topics} for some known ones)
|
|
520
519
|
* @param message - message dictionary which gets sent along the request
|
|
521
520
|
* @param callback - handler which gets supplied with an error object if the response didn't
|
|
522
|
-
*
|
|
521
|
+
* arrive in time or the status and the message dictionary from the response
|
|
523
522
|
*/
|
|
524
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
525
523
|
sendRequest(protocol, request, message = {}, callback) {
|
|
526
524
|
let requestId;
|
|
527
525
|
do { // generate unused requestId
|
|
@@ -536,13 +534,12 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
536
534
|
delete this.responseHandlers[requestId];
|
|
537
535
|
delete this.responseTimers[requestId];
|
|
538
536
|
// handler should be able to clean up their stuff
|
|
539
|
-
handler(new Error(
|
|
537
|
+
handler(new Error('timeout'), undefined, {});
|
|
540
538
|
}, 10000); // 10s timer
|
|
541
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
542
539
|
const header = {};
|
|
543
540
|
header.protocol = protocol;
|
|
544
541
|
header.request = request;
|
|
545
|
-
header.id = new
|
|
542
|
+
header.id = new Int64(requestId);
|
|
546
543
|
this.sendHDSFrame(header, message);
|
|
547
544
|
}
|
|
548
545
|
/**
|
|
@@ -554,15 +551,12 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
554
551
|
* @param status - status indication if the request was successful. A status of zero indicates success.
|
|
555
552
|
* @param message - message dictionary which gets sent along the response
|
|
556
553
|
*/
|
|
557
|
-
sendResponse(protocol, response, id, status = HDSStatus.SUCCESS,
|
|
558
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
559
|
-
message = {}) {
|
|
560
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
554
|
+
sendResponse(protocol, response, id, status = HDSStatus.SUCCESS, message = {}) {
|
|
561
555
|
const header = {};
|
|
562
556
|
header.protocol = protocol;
|
|
563
557
|
header.response = response;
|
|
564
|
-
header.id = new
|
|
565
|
-
header.status = new
|
|
558
|
+
header.id = new Int64(id);
|
|
559
|
+
header.status = new Int64(status);
|
|
566
560
|
this.sendHDSFrame(header, message);
|
|
567
561
|
}
|
|
568
562
|
onSocketData(data) {
|
|
@@ -587,7 +581,7 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
587
581
|
// below listener is removed in .close()
|
|
588
582
|
this.connection.setMaxListeners(this.connection.getMaxListeners() + 1);
|
|
589
583
|
this.connection.on("closed" /* HAPConnectionEvent.CLOSED */, this.hapConnectionClosedListener); // register close listener
|
|
590
|
-
debug(
|
|
584
|
+
debug('[%s] Registering CLOSED handler to HAP connection. Connection currently has %d close handlers!', this.remoteAddress, this.connection.listeners("closed" /* HAPConnectionEvent.CLOSED */).length);
|
|
591
585
|
}
|
|
592
586
|
});
|
|
593
587
|
if (this.state === 0 /* ConnectionState.UNIDENTIFIED */) {
|
|
@@ -597,7 +591,7 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
597
591
|
}
|
|
598
592
|
for (; frameIndex < frames.length; frameIndex++) { // decrypt all remaining frames
|
|
599
593
|
if (!this.decryptHDSFrame(frames[frameIndex])) {
|
|
600
|
-
debug(
|
|
594
|
+
debug('[%s] HDS frame decryption or authentication failed. Connection will be terminated!', this.remoteAddress);
|
|
601
595
|
this.close();
|
|
602
596
|
return;
|
|
603
597
|
}
|
|
@@ -607,12 +601,12 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
607
601
|
const firstMessage = messages[0];
|
|
608
602
|
if (firstMessage.protocol !== "control" /* Protocols.CONTROL */ || firstMessage.type !== 2 /* MessageType.REQUEST */ || firstMessage.topic !== "hello" /* Topics.HELLO */) {
|
|
609
603
|
// first message is not the expected hello request
|
|
610
|
-
debug(
|
|
604
|
+
debug('[%s] First message received was not the expected hello message. Instead got: %o', this.remoteAddress, firstMessage);
|
|
611
605
|
this.close();
|
|
612
606
|
return;
|
|
613
607
|
}
|
|
614
608
|
}
|
|
615
|
-
messages.forEach(message => {
|
|
609
|
+
messages.forEach((message) => {
|
|
616
610
|
if (message.type === 3 /* MessageType.RESPONSE */) {
|
|
617
611
|
// protocol and topic are currently not tested here; just assumed they are correct;
|
|
618
612
|
// probably they are as the requestId is unique per connection no matter what protocol is used
|
|
@@ -624,14 +618,14 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
624
618
|
}
|
|
625
619
|
if (!responseHandler) {
|
|
626
620
|
// we got a response to a request we did not send; we ignore it for now, since nobody will be hurt
|
|
627
|
-
debug(
|
|
621
|
+
debug('WARNING we received a response to a request we have not sent: %o', message);
|
|
628
622
|
return;
|
|
629
623
|
}
|
|
630
624
|
try {
|
|
631
625
|
responseHandler(undefined, message.status, message.message);
|
|
632
626
|
}
|
|
633
627
|
catch (error) {
|
|
634
|
-
debug(
|
|
628
|
+
debug('[%s] Error occurred while dispatching response handler for HDS message: %o', this.remoteAddress, message);
|
|
635
629
|
debug(error.stack);
|
|
636
630
|
}
|
|
637
631
|
delete this.responseHandlers[message.id];
|
|
@@ -644,35 +638,35 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
644
638
|
return;
|
|
645
639
|
}
|
|
646
640
|
if (message.type === 1 /* MessageType.EVENT */) {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
debug("[%s] WARNING no event handler was found for message: %o", this.remoteAddress, message);
|
|
641
|
+
if (!handler.eventHandler || !handler.eventHandler[message.topic]) {
|
|
642
|
+
debug('[%s] WARNING no event handler was found for message: %o', this.remoteAddress, message);
|
|
650
643
|
return;
|
|
651
644
|
}
|
|
645
|
+
const eventHandler = handler.eventHandler[message.topic];
|
|
652
646
|
try {
|
|
653
647
|
eventHandler(message.message);
|
|
654
648
|
}
|
|
655
649
|
catch (error) {
|
|
656
|
-
debug(
|
|
650
|
+
debug('[%s] Error occurred while dispatching event handler for HDS message: %o', this.remoteAddress, message);
|
|
657
651
|
debug(error.stack);
|
|
658
652
|
}
|
|
659
653
|
}
|
|
660
654
|
else if (message.type === 2 /* MessageType.REQUEST */) {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
debug("[%s] WARNING no request handler was found for message: %o", this.remoteAddress, message);
|
|
655
|
+
if (!handler.requestHandler || !handler.requestHandler[message.topic]) {
|
|
656
|
+
debug('[%s] WARNING no request handler was found for message: %o', this.remoteAddress, message);
|
|
664
657
|
return;
|
|
665
658
|
}
|
|
659
|
+
const requestHandler = handler.requestHandler[message.topic];
|
|
666
660
|
try {
|
|
667
661
|
requestHandler(message.id, message.message);
|
|
668
662
|
}
|
|
669
663
|
catch (error) {
|
|
670
|
-
debug(
|
|
664
|
+
debug('[%s] Error occurred while dispatching request handler for HDS message: %o', this.remoteAddress, message);
|
|
671
665
|
debug(error.stack);
|
|
672
666
|
}
|
|
673
667
|
}
|
|
674
668
|
else {
|
|
675
|
-
debug(
|
|
669
|
+
debug('[%s] Encountered unknown message type with id %d', this.remoteAddress, message.type);
|
|
676
670
|
}
|
|
677
671
|
}
|
|
678
672
|
});
|
|
@@ -687,13 +681,13 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
687
681
|
for (let frameBegin = 0; frameBegin < totalBufferLength;) {
|
|
688
682
|
if (frameBegin + 4 > totalBufferLength) {
|
|
689
683
|
// we don't have enough data in the buffer for the next header
|
|
690
|
-
this.frameBuffer = data.
|
|
684
|
+
this.frameBuffer = data.subarray(frameBegin);
|
|
691
685
|
break;
|
|
692
686
|
}
|
|
693
687
|
const payloadType = data.readUInt8(frameBegin); // type defining structure of payload; 8-bit; currently expected to be 1
|
|
694
688
|
const payloadLength = data.readUIntBE(frameBegin + 1, 3); // read 24-bit big-endian uint length field
|
|
695
689
|
if (payloadLength > DataStreamConnection.MAX_PAYLOAD_LENGTH) {
|
|
696
|
-
debug(
|
|
690
|
+
debug('[%s] Connection send payload with size bigger than the maximum allow for data stream', this.remoteAddress);
|
|
697
691
|
this.close();
|
|
698
692
|
return [];
|
|
699
693
|
}
|
|
@@ -701,38 +695,38 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
701
695
|
// check if the data from this frame is already there (payload + 16-byte authTag)
|
|
702
696
|
if (payloadLength + 16 > remainingBufferLength) {
|
|
703
697
|
// Frame is fragmented, so we wait until we receive more
|
|
704
|
-
this.frameBuffer = data.
|
|
698
|
+
this.frameBuffer = data.subarray(frameBegin);
|
|
705
699
|
break;
|
|
706
700
|
}
|
|
707
701
|
const payloadBegin = frameBegin + 4;
|
|
708
702
|
const authTagBegin = payloadBegin + payloadLength;
|
|
709
|
-
const header = data.
|
|
710
|
-
const cipheredPayload = data.
|
|
703
|
+
const header = data.subarray(frameBegin, payloadBegin); // header is also authenticated using authTag
|
|
704
|
+
const cipheredPayload = data.subarray(payloadBegin, authTagBegin);
|
|
711
705
|
const plaintextPayload = Buffer.alloc(payloadLength);
|
|
712
|
-
const authTag = data.
|
|
706
|
+
const authTag = data.subarray(authTagBegin, authTagBegin + 16);
|
|
713
707
|
frameBegin = authTagBegin + 16; // move to next frame
|
|
714
708
|
if (payloadType === 1) {
|
|
715
709
|
const hdsFrame = {
|
|
716
|
-
header
|
|
717
|
-
cipheredPayload
|
|
718
|
-
authTag
|
|
710
|
+
header,
|
|
711
|
+
cipheredPayload,
|
|
712
|
+
authTag,
|
|
719
713
|
};
|
|
720
714
|
frames.push(hdsFrame);
|
|
721
715
|
}
|
|
722
716
|
else {
|
|
723
|
-
debug(
|
|
717
|
+
debug('[%s] Encountered unknown payload type %d for payload: %s', this.remoteAddress, plaintextPayload.toString('hex'));
|
|
724
718
|
}
|
|
725
719
|
}
|
|
726
720
|
return frames;
|
|
727
721
|
}
|
|
728
722
|
/**
|
|
729
|
-
* @private
|
|
723
|
+
* @private
|
|
730
724
|
*/
|
|
731
725
|
decryptHDSFrame(frame, keyOverwrite) {
|
|
732
|
-
|
|
726
|
+
writeUInt64LE(this.controllerToAccessoryNonce, this.controllerToAccessoryNonceBuffer, 0); // update nonce buffer
|
|
733
727
|
const key = keyOverwrite || this.controllerToAccessoryEncryptionKey;
|
|
734
728
|
try {
|
|
735
|
-
frame.plaintextPayload =
|
|
729
|
+
frame.plaintextPayload = chacha20_poly1305_decryptAndVerify(key, this.controllerToAccessoryNonceBuffer, frame.header, frame.cipheredPayload, frame.authTag);
|
|
736
730
|
this.controllerToAccessoryNonce++; // we had a successful encryption, increment the nonce
|
|
737
731
|
return true;
|
|
738
732
|
}
|
|
@@ -743,42 +737,40 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
743
737
|
}
|
|
744
738
|
decodePayloads(frames) {
|
|
745
739
|
const messages = [];
|
|
746
|
-
frames.forEach(frame => {
|
|
740
|
+
frames.forEach((frame) => {
|
|
747
741
|
const payload = frame.plaintextPayload;
|
|
748
742
|
if (!payload) {
|
|
749
|
-
throw new HDSConnectionError(
|
|
743
|
+
throw new HDSConnectionError('Reached illegal state. Encountered HDSFrame with wasn\'t decrypted yet!', 1 /* HDSConnectionErrorType.ILLEGAL_STATE */);
|
|
750
744
|
}
|
|
751
745
|
const headerLength = payload.readUInt8(0);
|
|
752
746
|
const messageLength = payload.length - headerLength - 1;
|
|
753
747
|
const headerBegin = 1;
|
|
754
748
|
const messageBegin = headerBegin + headerLength;
|
|
755
|
-
const headerPayload = new
|
|
756
|
-
const messagePayload = new
|
|
757
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
749
|
+
const headerPayload = new DataStreamReader(payload.subarray(headerBegin, headerBegin + headerLength));
|
|
750
|
+
const messagePayload = new DataStreamReader(payload.subarray(messageBegin, messageBegin + messageLength));
|
|
758
751
|
let headerDictionary;
|
|
759
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
760
752
|
let messageDictionary;
|
|
761
753
|
try {
|
|
762
|
-
headerDictionary =
|
|
754
|
+
headerDictionary = DataStreamParser.decode(headerPayload);
|
|
763
755
|
headerPayload.finished();
|
|
764
756
|
}
|
|
765
757
|
catch (error) {
|
|
766
|
-
debug(
|
|
758
|
+
debug('[%s] Failed to decode header payload: %s', this.remoteAddress, error.message);
|
|
767
759
|
return;
|
|
768
760
|
}
|
|
769
761
|
try {
|
|
770
|
-
messageDictionary =
|
|
762
|
+
messageDictionary = DataStreamParser.decode(messagePayload);
|
|
771
763
|
messagePayload.finished();
|
|
772
764
|
}
|
|
773
765
|
catch (error) {
|
|
774
|
-
debug(
|
|
766
|
+
debug('[%s] Failed to decode message payload: %s (header: %o)', this.remoteAddress, error.message, headerDictionary);
|
|
775
767
|
return;
|
|
776
768
|
}
|
|
777
769
|
let type;
|
|
778
770
|
const protocol = headerDictionary.protocol;
|
|
779
771
|
let topic;
|
|
780
|
-
let id
|
|
781
|
-
let status
|
|
772
|
+
let id;
|
|
773
|
+
let status;
|
|
782
774
|
if (headerDictionary.event !== undefined) {
|
|
783
775
|
type = 1 /* MessageType.EVENT */;
|
|
784
776
|
topic = headerDictionary.event;
|
|
@@ -795,44 +787,43 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
795
787
|
status = headerDictionary.status;
|
|
796
788
|
}
|
|
797
789
|
else {
|
|
798
|
-
debug(
|
|
790
|
+
debug('[%s] Encountered unknown payload header format: %o (message: %o)', this.remoteAddress, headerDictionary, messageDictionary);
|
|
799
791
|
return;
|
|
800
792
|
}
|
|
801
793
|
const message = {
|
|
802
|
-
type
|
|
803
|
-
protocol
|
|
804
|
-
topic
|
|
805
|
-
id
|
|
806
|
-
status
|
|
794
|
+
type,
|
|
795
|
+
protocol,
|
|
796
|
+
topic,
|
|
797
|
+
id,
|
|
798
|
+
status,
|
|
807
799
|
message: messageDictionary,
|
|
808
800
|
};
|
|
809
801
|
messages.push(message);
|
|
810
802
|
});
|
|
811
803
|
return messages;
|
|
812
804
|
}
|
|
813
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
814
805
|
sendHDSFrame(header, message) {
|
|
815
806
|
if (this.state >= 3 /* ConnectionState.CLOSING */) {
|
|
816
|
-
throw new HDSConnectionError(
|
|
807
|
+
throw new HDSConnectionError('Cannot send message on closing/closed socket!', 2 /* HDSConnectionErrorType.CLOSED_SOCKET */);
|
|
817
808
|
}
|
|
818
|
-
const headerWriter = new
|
|
819
|
-
const messageWriter = new
|
|
820
|
-
|
|
821
|
-
|
|
809
|
+
const headerWriter = new DataStreamWriter();
|
|
810
|
+
const messageWriter = new DataStreamWriter();
|
|
811
|
+
DataStreamParser.encode(header, headerWriter);
|
|
812
|
+
DataStreamParser.encode(message, messageWriter);
|
|
822
813
|
const payloadHeaderBuffer = Buffer.alloc(1);
|
|
823
814
|
payloadHeaderBuffer.writeUInt8(headerWriter.length(), 0);
|
|
824
815
|
const payloadBuffer = Buffer.concat([payloadHeaderBuffer, headerWriter.getData(), messageWriter.getData()]);
|
|
825
816
|
if (payloadBuffer.length > DataStreamConnection.MAX_PAYLOAD_LENGTH) {
|
|
826
|
-
throw new HDSConnectionError(
|
|
817
|
+
throw new HDSConnectionError('Tried sending payload with length larger than the maximum allowed for data stream', 3 /* HDSConnectionErrorType.MAX_PAYLOAD_LENGTH */);
|
|
827
818
|
}
|
|
828
819
|
const frameTypeBuffer = Buffer.alloc(1);
|
|
829
820
|
frameTypeBuffer.writeUInt8(1, 0);
|
|
830
821
|
let frameLengthBuffer = Buffer.alloc(4);
|
|
831
822
|
frameLengthBuffer.writeUInt32BE(payloadBuffer.length, 0);
|
|
832
|
-
frameLengthBuffer = frameLengthBuffer.
|
|
823
|
+
frameLengthBuffer = frameLengthBuffer.subarray(1, 4); // a bit hacky but the only real way to write 24-bit int in node
|
|
833
824
|
const frameHeader = Buffer.concat([frameTypeBuffer, frameLengthBuffer]);
|
|
834
|
-
|
|
835
|
-
const encrypted =
|
|
825
|
+
writeUInt64LE(this.accessoryToControllerNonce++, this.accessoryToControllerNonceBuffer);
|
|
826
|
+
const encrypted = chacha20_poly1305_encryptAndSeal(this.accessoryToControllerEncryptionKey, this.accessoryToControllerNonceBuffer, frameHeader, payloadBuffer);
|
|
836
827
|
this.socket.write(Buffer.concat([frameHeader, encrypted.ciphertext, encrypted.authTag]));
|
|
837
828
|
/* Useful for debugging outgoing packages and detecting encoding errors
|
|
838
829
|
console.log("SENT DATA: " + payloadBuffer.toString("hex"));
|
|
@@ -844,7 +835,7 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
844
835
|
};
|
|
845
836
|
const sentMessage = this.decodePayloads([frame])[0];
|
|
846
837
|
console.log("Sent message: " + JSON.stringify(sentMessage, null, 4));
|
|
847
|
-
|
|
838
|
+
// */
|
|
848
839
|
}
|
|
849
840
|
close() {
|
|
850
841
|
if (this.state >= 3 /* ConnectionState.CLOSING */) {
|
|
@@ -858,11 +849,11 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
858
849
|
}
|
|
859
850
|
onHAPSessionClosed() {
|
|
860
851
|
// If the hap connection is closed it is probably also a good idea to close the data stream connection
|
|
861
|
-
debug(
|
|
852
|
+
debug('[%s] HAP connection disconnected. Also closing DataStream connection now.', this.remoteAddress);
|
|
862
853
|
this.close();
|
|
863
854
|
}
|
|
864
855
|
onSocketError(error) {
|
|
865
|
-
debug(
|
|
856
|
+
debug('[%s] Encountered socket error: %s', this.remoteAddress, error.message);
|
|
866
857
|
// onSocketClose will be called next
|
|
867
858
|
}
|
|
868
859
|
onSocketClose() {
|
|
@@ -874,5 +865,4 @@ class DataStreamConnection extends events_1.EventEmitter {
|
|
|
874
865
|
this.removeAllListeners();
|
|
875
866
|
}
|
|
876
867
|
}
|
|
877
|
-
exports.DataStreamConnection = DataStreamConnection;
|
|
878
868
|
//# sourceMappingURL=DataStreamServer.js.map
|