hap-nodejs 0.12.3-beta.2 → 0.12.3-beta.21
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/README.md +1 -0
- package/dist/accessories/AirConditioner_accessory.js +24 -24
- package/dist/accessories/AirConditioner_accessory.js.map +1 -1
- package/dist/accessories/AppleTVRemote_accessory.js +23 -23
- package/dist/accessories/AppleTVRemote_accessory.js.map +1 -1
- package/dist/accessories/Camera_accessory.js +292 -373
- package/dist/accessories/Camera_accessory.js.map +1 -1
- package/dist/accessories/Fan_accessory.js +15 -21
- package/dist/accessories/Fan_accessory.js.map +1 -1
- package/dist/accessories/GarageDoorOpener_accessory.js +12 -12
- package/dist/accessories/GarageDoorOpener_accessory.js.map +1 -1
- package/dist/accessories/Light-AdaptiveLighting_accessory.js +31 -21
- package/dist/accessories/Light-AdaptiveLighting_accessory.js.map +1 -1
- package/dist/accessories/Light_accessory.js +45 -48
- package/dist/accessories/Light_accessory.js.map +1 -1
- package/dist/accessories/Lock_accessory.js +11 -11
- package/dist/accessories/Lock_accessory.js.map +1 -1
- package/dist/accessories/MotionSensor_accessory.js +8 -8
- package/dist/accessories/MotionSensor_accessory.js.map +1 -1
- package/dist/accessories/Outlet_accessory.js +10 -10
- package/dist/accessories/Outlet_accessory.js.map +1 -1
- package/dist/accessories/SmartSpeaker_accessory.js +11 -11
- package/dist/accessories/SmartSpeaker_accessory.js.map +1 -1
- package/dist/accessories/Sprinkler_accessory.js +19 -19
- package/dist/accessories/Sprinkler_accessory.js.map +1 -1
- package/dist/accessories/TV_accessory.js +17 -17
- package/dist/accessories/TV_accessory.js.map +1 -1
- package/dist/accessories/TemperatureSensor_accessory.js +6 -6
- package/dist/accessories/TemperatureSensor_accessory.js.map +1 -1
- package/dist/accessories/Wi-FiRouter_accessory.js +3 -3
- package/dist/accessories/Wi-FiRouter_accessory.js.map +1 -1
- package/dist/accessories/Wi-FiSatellite_accessory.js +4 -4
- package/dist/accessories/Wi-FiSatellite_accessory.js.map +1 -1
- package/dist/accessories/gstreamer-audioProducer.js +36 -47
- package/dist/accessories/gstreamer-audioProducer.js.map +1 -1
- package/dist/accessories/types.js +2 -2
- package/dist/accessories/types.js.map +1 -1
- package/dist/index.d.ts +0 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -28
- package/dist/index.js.map +1 -1
- package/dist/lib/Accessory.d.ts +1 -58
- package/dist/lib/Accessory.d.ts.map +1 -1
- package/dist/lib/Accessory.js +747 -1149
- package/dist/lib/Accessory.js.map +1 -1
- package/dist/lib/Advertiser.d.ts +1 -2
- package/dist/lib/Advertiser.d.ts.map +1 -1
- package/dist/lib/Advertiser.js +392 -524
- package/dist/lib/Advertiser.js.map +1 -1
- package/dist/lib/Bridge.js +6 -10
- package/dist/lib/Bridge.js.map +1 -1
- package/dist/lib/Characteristic.d.ts +2 -133
- package/dist/lib/Characteristic.d.ts.map +1 -1
- package/dist/lib/Characteristic.js +1467 -669
- package/dist/lib/Characteristic.js.map +1 -1
- package/dist/lib/HAPServer.d.ts +0 -10
- package/dist/lib/HAPServer.d.ts.map +1 -1
- package/dist/lib/HAPServer.js +216 -280
- package/dist/lib/HAPServer.js.map +1 -1
- package/dist/lib/Service.d.ts +1 -51
- package/dist/lib/Service.d.ts.map +1 -1
- package/dist/lib/Service.js +474 -322
- package/dist/lib/Service.js.map +1 -1
- package/dist/lib/camera/RTPProxy.js +112 -104
- package/dist/lib/camera/RTPProxy.js.map +1 -1
- package/dist/lib/camera/RTPStreamManagement.d.ts +0 -65
- package/dist/lib/camera/RTPStreamManagement.d.ts.map +1 -1
- package/dist/lib/camera/RTPStreamManagement.js +255 -278
- package/dist/lib/camera/RTPStreamManagement.js.map +1 -1
- package/dist/lib/camera/RecordingManagement.js +318 -381
- package/dist/lib/camera/RecordingManagement.js.map +1 -1
- package/dist/lib/camera/index.d.ts +0 -1
- package/dist/lib/camera/index.d.ts.map +1 -1
- package/dist/lib/camera/index.js +1 -2
- package/dist/lib/camera/index.js.map +1 -1
- package/dist/lib/controller/AdaptiveLightingController.d.ts +19 -3
- package/dist/lib/controller/AdaptiveLightingController.d.ts.map +1 -1
- package/dist/lib/controller/AdaptiveLightingController.js +217 -218
- package/dist/lib/controller/AdaptiveLightingController.js.map +1 -1
- package/dist/lib/controller/CameraController.d.ts +0 -4
- package/dist/lib/controller/CameraController.d.ts.map +1 -1
- package/dist/lib/controller/CameraController.js +189 -256
- package/dist/lib/controller/CameraController.js.map +1 -1
- package/dist/lib/controller/DoorbellController.js +38 -39
- package/dist/lib/controller/DoorbellController.js.map +1 -1
- package/dist/lib/controller/RemoteController.d.ts +0 -14
- package/dist/lib/controller/RemoteController.d.ts.map +1 -1
- package/dist/lib/controller/RemoteController.js +340 -415
- package/dist/lib/controller/RemoteController.js.map +1 -1
- package/dist/lib/controller/index.js +1 -1
- package/dist/lib/datastream/DataStreamManagement.js +56 -57
- package/dist/lib/datastream/DataStreamManagement.js.map +1 -1
- package/dist/lib/datastream/DataStreamParser.js +259 -304
- package/dist/lib/datastream/DataStreamParser.js.map +1 -1
- package/dist/lib/datastream/DataStreamServer.d.ts +0 -5
- package/dist/lib/datastream/DataStreamServer.d.ts.map +1 -1
- package/dist/lib/datastream/DataStreamServer.js +252 -269
- package/dist/lib/datastream/DataStreamServer.js.map +1 -1
- package/dist/lib/datastream/index.js +1 -1
- package/dist/lib/definitions/CharacteristicDefinitions.d.ts +1 -106
- package/dist/lib/definitions/CharacteristicDefinitions.d.ts.map +1 -1
- package/dist/lib/definitions/CharacteristicDefinitions.js +2000 -2995
- package/dist/lib/definitions/CharacteristicDefinitions.js.map +1 -1
- package/dist/lib/definitions/ServiceDefinitions.d.ts +0 -32
- package/dist/lib/definitions/ServiceDefinitions.d.ts.map +1 -1
- package/dist/lib/definitions/ServiceDefinitions.js +820 -1147
- package/dist/lib/definitions/ServiceDefinitions.js.map +1 -1
- package/dist/lib/definitions/generate-definitions.js +383 -679
- package/dist/lib/definitions/generate-definitions.js.map +1 -1
- package/dist/lib/definitions/generator-configuration.js +29 -29
- package/dist/lib/definitions/generator-configuration.js.map +1 -1
- package/dist/lib/definitions/index.js +1 -1
- package/dist/lib/model/AccessoryInfo.js +101 -136
- package/dist/lib/model/AccessoryInfo.js.map +1 -1
- package/dist/lib/model/ControllerStorage.js +86 -89
- package/dist/lib/model/ControllerStorage.js.map +1 -1
- package/dist/lib/model/HAPStorage.js +15 -16
- package/dist/lib/model/HAPStorage.js.map +1 -1
- package/dist/lib/model/IdentifierCache.js +49 -49
- package/dist/lib/model/IdentifierCache.js.map +1 -1
- package/dist/lib/tv/AccessControlManagement.js +40 -44
- package/dist/lib/tv/AccessControlManagement.js.map +1 -1
- package/dist/lib/util/checkName.d.ts +2 -1
- package/dist/lib/util/checkName.d.ts.map +1 -1
- package/dist/lib/util/checkName.js +7 -11
- package/dist/lib/util/checkName.js.map +1 -1
- package/dist/lib/util/clone.js +5 -27
- package/dist/lib/util/clone.js.map +1 -1
- package/dist/lib/util/color-utils.js +8 -12
- package/dist/lib/util/color-utils.js.map +1 -1
- package/dist/lib/util/eventedhttp.d.ts.map +1 -1
- package/dist/lib/util/eventedhttp.js +301 -409
- package/dist/lib/util/eventedhttp.js.map +1 -1
- package/dist/lib/util/hapCrypto.js +31 -32
- package/dist/lib/util/hapCrypto.js.map +1 -1
- package/dist/lib/util/hapStatusError.js +9 -12
- package/dist/lib/util/hapStatusError.js.map +1 -1
- package/dist/lib/util/net-utils.js +32 -53
- package/dist/lib/util/net-utils.js.map +1 -1
- package/dist/lib/util/once.js +3 -8
- package/dist/lib/util/once.js.map +1 -1
- package/dist/lib/util/promise-utils.js +8 -13
- package/dist/lib/util/promise-utils.js.map +1 -1
- package/dist/lib/util/request-util.js +2 -3
- package/dist/lib/util/request-util.js.map +1 -1
- package/dist/lib/util/time.js +5 -5
- package/dist/lib/util/time.js.map +1 -1
- package/dist/lib/util/tlv.d.ts +0 -27
- package/dist/lib/util/tlv.d.ts.map +1 -1
- package/dist/lib/util/tlv.js +71 -113
- package/dist/lib/util/tlv.js.map +1 -1
- package/dist/lib/util/uuid.d.ts +0 -9
- package/dist/lib/util/uuid.d.ts.map +1 -1
- package/dist/lib/util/uuid.js +15 -33
- package/dist/lib/util/uuid.js.map +1 -1
- package/dist/types.d.ts +0 -35
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +10 -10
- package/dist/BridgedCore.d.ts +0 -2
- package/dist/BridgedCore.d.ts.map +0 -1
- package/dist/BridgedCore.js +0 -43
- package/dist/BridgedCore.js.map +0 -1
- package/dist/Core.d.ts +0 -2
- package/dist/Core.d.ts.map +0 -1
- package/dist/Core.js +0 -52
- package/dist/Core.js.map +0 -1
- package/dist/lib/AccessoryLoader.d.ts +0 -28
- package/dist/lib/AccessoryLoader.d.ts.map +0 -1
- package/dist/lib/AccessoryLoader.js +0 -166
- package/dist/lib/AccessoryLoader.js.map +0 -1
- package/dist/lib/camera/Camera.d.ts +0 -43
- package/dist/lib/camera/Camera.d.ts.map +0 -1
- package/dist/lib/camera/Camera.js +0 -36
- package/dist/lib/camera/Camera.js.map +0 -1
package/dist/lib/Advertiser.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ResolvedAdvertiser = exports.AvahiAdvertiser = exports.DBusInvokeError = exports.BonjourHAPAdvertiser = exports.CiaoAdvertiser = exports.AdvertiserEvent = exports.PairingFeatureFlag = exports.StatusFlag = void 0;
|
|
4
|
-
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
|
6
6
|
/// <reference path="../../@types/bonjour-hap.d.ts" />
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
const ciao_1 = tslib_1.__importDefault(require("@homebridge/ciao"));
|
|
8
|
+
const dbus_native_1 = tslib_1.__importDefault(require("@homebridge/dbus-native"));
|
|
9
|
+
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
10
|
+
const bonjour_hap_1 = tslib_1.__importDefault(require("bonjour-hap"));
|
|
11
|
+
const crypto_1 = tslib_1.__importDefault(require("crypto"));
|
|
12
|
+
const debug_1 = tslib_1.__importDefault(require("debug"));
|
|
13
|
+
const events_1 = require("events");
|
|
14
|
+
const promise_utils_1 = require("./util/promise-utils");
|
|
15
|
+
const debug = (0, debug_1.default)("HAP-NodeJS:Advertiser");
|
|
16
16
|
/**
|
|
17
17
|
* This enum lists all bitmasks for all known status flags.
|
|
18
18
|
* When the bit for the given bitmask is set, it represents the state described by the name.
|
|
@@ -57,48 +57,49 @@ var AdvertiserEvent;
|
|
|
57
57
|
*
|
|
58
58
|
* @group Advertiser
|
|
59
59
|
*/
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
60
|
+
class CiaoAdvertiser extends events_1.EventEmitter {
|
|
61
|
+
static protocolVersion = "1.1";
|
|
62
|
+
static protocolVersionService = "1.1.0";
|
|
63
|
+
accessoryInfo;
|
|
64
|
+
setupHash;
|
|
65
|
+
responder;
|
|
66
|
+
advertisedService;
|
|
67
|
+
constructor(accessoryInfo, responderOptions, serviceOptions) {
|
|
68
|
+
super();
|
|
69
|
+
this.accessoryInfo = accessoryInfo;
|
|
70
|
+
this.setupHash = CiaoAdvertiser.computeSetupHash(accessoryInfo);
|
|
71
|
+
this.responder = ciao_1.default.getResponder({
|
|
72
|
+
...responderOptions,
|
|
73
|
+
});
|
|
74
|
+
this.advertisedService = this.responder.createService({
|
|
75
|
+
name: this.accessoryInfo.displayName,
|
|
76
|
+
type: "hap" /* ServiceType.HAP */,
|
|
77
|
+
txt: CiaoAdvertiser.createTxt(accessoryInfo, this.setupHash),
|
|
78
|
+
// host will default now to <displayName>.local, spaces replaced with dashes
|
|
79
|
+
...serviceOptions,
|
|
80
|
+
});
|
|
81
|
+
this.advertisedService.on("name-change" /* ServiceEvent.NAME_CHANGED */, this.emit.bind(this, "updated-name" /* AdvertiserEvent.UPDATED_NAME */));
|
|
82
|
+
debug(`Preparing Advertiser for '${this.accessoryInfo.displayName}' using ciao backend!`);
|
|
83
|
+
}
|
|
84
|
+
initPort(port) {
|
|
73
85
|
this.advertisedService.updatePort(port);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
debug(
|
|
86
|
+
}
|
|
87
|
+
startAdvertising() {
|
|
88
|
+
debug(`Starting to advertise '${this.accessoryInfo.displayName}' using ciao backend!`);
|
|
77
89
|
return this.advertisedService.advertise();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
}
|
|
91
|
+
updateAdvertisement(silent) {
|
|
92
|
+
const txt = CiaoAdvertiser.createTxt(this.accessoryInfo, this.setupHash);
|
|
81
93
|
debug("Updating txt record (txt: %o, silent: %d)", txt, silent);
|
|
82
94
|
this.advertisedService.updateTxt(txt, silent);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
case 1:
|
|
92
|
-
// advertisedService.destroy(); is called implicitly via the shutdown call
|
|
93
|
-
_a.sent();
|
|
94
|
-
this.removeAllListeners();
|
|
95
|
-
return [2 /*return*/];
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
};
|
|
100
|
-
CiaoAdvertiser.createTxt = function (accessoryInfo, setupHash) {
|
|
101
|
-
var statusFlags = [];
|
|
95
|
+
}
|
|
96
|
+
async destroy() {
|
|
97
|
+
// advertisedService.destroy(); is called implicitly via the shutdown call
|
|
98
|
+
await this.responder.shutdown();
|
|
99
|
+
this.removeAllListeners();
|
|
100
|
+
}
|
|
101
|
+
static createTxt(accessoryInfo, setupHash) {
|
|
102
|
+
const statusFlags = [];
|
|
102
103
|
if (!accessoryInfo.paired()) {
|
|
103
104
|
statusFlags.push(1 /* StatusFlag.NOT_PAIRED */);
|
|
104
105
|
}
|
|
@@ -109,103 +110,102 @@ var CiaoAdvertiser = /** @class */ (function (_super) {
|
|
|
109
110
|
md: accessoryInfo.model, // model name
|
|
110
111
|
pv: CiaoAdvertiser.protocolVersion, // protocol version
|
|
111
112
|
"s#": 1, // current state number (must be 1)
|
|
112
|
-
sf: CiaoAdvertiser.sf
|
|
113
|
+
sf: CiaoAdvertiser.sf(...statusFlags), // status flags
|
|
113
114
|
ci: accessoryInfo.category,
|
|
114
115
|
sh: setupHash,
|
|
115
116
|
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
}
|
|
118
|
+
static computeSetupHash(accessoryInfo) {
|
|
119
|
+
const hash = crypto_1.default.createHash("sha512");
|
|
119
120
|
hash.update(accessoryInfo.setupID + accessoryInfo.username.toUpperCase());
|
|
120
121
|
return hash.digest().slice(0, 4).toString("base64");
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
flags[_i] = arguments[_i];
|
|
126
|
-
}
|
|
127
|
-
var value = 0;
|
|
128
|
-
flags.forEach(function (flag) { return value |= flag; });
|
|
122
|
+
}
|
|
123
|
+
static ff(...flags) {
|
|
124
|
+
let value = 0;
|
|
125
|
+
flags.forEach(flag => value |= flag);
|
|
129
126
|
return value;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
flags[_i] = arguments[_i];
|
|
135
|
-
}
|
|
136
|
-
var value = 0;
|
|
137
|
-
flags.forEach(function (flag) { return value |= flag; });
|
|
127
|
+
}
|
|
128
|
+
static sf(...flags) {
|
|
129
|
+
let value = 0;
|
|
130
|
+
flags.forEach(flag => value |= flag);
|
|
138
131
|
return value;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
CiaoAdvertiser.protocolVersionService = "1.1.0";
|
|
142
|
-
return CiaoAdvertiser;
|
|
143
|
-
}(events_1.EventEmitter));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
144
134
|
exports.CiaoAdvertiser = CiaoAdvertiser;
|
|
145
135
|
/**
|
|
146
136
|
* Advertiser base on the legacy "bonjour-hap" library.
|
|
147
137
|
*
|
|
148
138
|
* @group Advertiser
|
|
149
139
|
*/
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
140
|
+
class BonjourHAPAdvertiser extends events_1.EventEmitter {
|
|
141
|
+
accessoryInfo;
|
|
142
|
+
setupHash;
|
|
143
|
+
serviceOptions;
|
|
144
|
+
bonjour;
|
|
145
|
+
advertisement;
|
|
146
|
+
port;
|
|
147
|
+
destroyed = false;
|
|
148
|
+
constructor(accessoryInfo, serviceOptions) {
|
|
149
|
+
super();
|
|
150
|
+
this.accessoryInfo = accessoryInfo;
|
|
151
|
+
this.setupHash = CiaoAdvertiser.computeSetupHash(accessoryInfo);
|
|
152
|
+
this.serviceOptions = serviceOptions;
|
|
153
|
+
this.bonjour = (0, bonjour_hap_1.default)();
|
|
154
|
+
debug(`Preparing Advertiser for '${this.accessoryInfo.displayName}' using bonjour-hap backend!`);
|
|
155
|
+
}
|
|
156
|
+
initPort(port) {
|
|
163
157
|
this.port = port;
|
|
164
|
-
}
|
|
165
|
-
|
|
158
|
+
}
|
|
159
|
+
startAdvertising() {
|
|
166
160
|
(0, assert_1.default)(!this.destroyed, "Can't advertise on a destroyed bonjour instance!");
|
|
167
161
|
if (this.port == null) {
|
|
168
162
|
throw new Error("Tried starting bonjour-hap advertisement without initializing port!");
|
|
169
163
|
}
|
|
170
|
-
debug(
|
|
164
|
+
debug(`Starting to advertise '${this.accessoryInfo.displayName}' using bonjour-hap backend!`);
|
|
171
165
|
if (this.advertisement) {
|
|
172
166
|
this.destroy();
|
|
173
167
|
}
|
|
174
|
-
|
|
175
|
-
this.advertisement = this.bonjour.publish(
|
|
168
|
+
const hostname = this.accessoryInfo.username.replace(/:/ig, "_") + ".local";
|
|
169
|
+
this.advertisement = this.bonjour.publish({
|
|
170
|
+
name: this.accessoryInfo.displayName,
|
|
171
|
+
type: "hap",
|
|
172
|
+
port: this.port,
|
|
173
|
+
txt: CiaoAdvertiser.createTxt(this.accessoryInfo, this.setupHash),
|
|
174
|
+
host: hostname,
|
|
175
|
+
addUnsafeServiceEnumerationRecord: true,
|
|
176
|
+
...this.serviceOptions,
|
|
177
|
+
});
|
|
176
178
|
return (0, promise_utils_1.PromiseTimeout)(1);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
179
|
+
}
|
|
180
|
+
updateAdvertisement(silent) {
|
|
181
|
+
const txt = CiaoAdvertiser.createTxt(this.accessoryInfo, this.setupHash);
|
|
180
182
|
debug("Updating txt record (txt: %o, silent: %d)", txt, silent);
|
|
181
183
|
if (this.advertisement) {
|
|
182
184
|
this.advertisement.updateTxt(txt, silent);
|
|
183
185
|
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
var _this = this;
|
|
186
|
+
}
|
|
187
|
+
destroy() {
|
|
187
188
|
if (this.advertisement) {
|
|
188
|
-
this.advertisement.stop(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
189
|
+
this.advertisement.stop(() => {
|
|
190
|
+
this.advertisement.destroy();
|
|
191
|
+
this.advertisement = undefined;
|
|
192
|
+
this.bonjour.destroy();
|
|
192
193
|
});
|
|
193
194
|
}
|
|
194
195
|
else {
|
|
195
196
|
this.bonjour.destroy();
|
|
196
197
|
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
}(events_1.EventEmitter));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
200
|
exports.BonjourHAPAdvertiser = BonjourHAPAdvertiser;
|
|
201
201
|
function messageBusConnectionResult(bus) {
|
|
202
|
-
return new Promise(
|
|
203
|
-
|
|
202
|
+
return new Promise((resolve, reject) => {
|
|
203
|
+
const errorHandler = (error) => {
|
|
204
204
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
205
205
|
bus.connection.removeListener("connect", connectHandler);
|
|
206
206
|
reject(error);
|
|
207
207
|
};
|
|
208
|
-
|
|
208
|
+
const connectHandler = () => {
|
|
209
209
|
bus.connection.removeListener("error", errorHandler);
|
|
210
210
|
resolve();
|
|
211
211
|
};
|
|
@@ -216,30 +216,34 @@ function messageBusConnectionResult(bus) {
|
|
|
216
216
|
/**
|
|
217
217
|
* @group Advertiser
|
|
218
218
|
*/
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
class DBusInvokeError extends Error {
|
|
220
|
+
errorName;
|
|
221
221
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
Object.setPrototypeOf(
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
constructor(errorObject) {
|
|
223
|
+
super();
|
|
224
|
+
Object.setPrototypeOf(this, DBusInvokeError.prototype);
|
|
225
|
+
this.name = "DBusInvokeError";
|
|
226
|
+
this.errorName = errorObject.name;
|
|
227
227
|
if (Array.isArray(errorObject.message) && errorObject.message.length === 1) {
|
|
228
|
-
|
|
228
|
+
this.message = errorObject.message[0];
|
|
229
229
|
}
|
|
230
230
|
else {
|
|
231
|
-
|
|
231
|
+
this.message = errorObject.message.toString();
|
|
232
232
|
}
|
|
233
|
-
return _this;
|
|
234
233
|
}
|
|
235
|
-
|
|
236
|
-
}(Error));
|
|
234
|
+
}
|
|
237
235
|
exports.DBusInvokeError = DBusInvokeError;
|
|
238
236
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
239
237
|
function dbusInvoke(bus, destination, path, dbusInterface, member, others) {
|
|
240
|
-
return new Promise(
|
|
241
|
-
|
|
242
|
-
|
|
238
|
+
return new Promise((resolve, reject) => {
|
|
239
|
+
const command = {
|
|
240
|
+
destination,
|
|
241
|
+
path,
|
|
242
|
+
interface: dbusInterface,
|
|
243
|
+
member,
|
|
244
|
+
...(others || {}),
|
|
245
|
+
};
|
|
246
|
+
bus.invoke(command, (err, result) => {
|
|
243
247
|
if (err) {
|
|
244
248
|
reject(new DBusInvokeError(err));
|
|
245
249
|
}
|
|
@@ -274,232 +278,167 @@ var AvahiServerState;
|
|
|
274
278
|
*
|
|
275
279
|
* @group Advertiser
|
|
276
280
|
*/
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
281
|
+
class AvahiAdvertiser extends events_1.EventEmitter {
|
|
282
|
+
accessoryInfo;
|
|
283
|
+
setupHash;
|
|
284
|
+
port;
|
|
285
|
+
bus;
|
|
286
|
+
avahiServerInterface;
|
|
287
|
+
path;
|
|
288
|
+
stateChangeHandler;
|
|
289
|
+
constructor(accessoryInfo) {
|
|
290
|
+
super();
|
|
291
|
+
this.accessoryInfo = accessoryInfo;
|
|
292
|
+
this.setupHash = CiaoAdvertiser.computeSetupHash(accessoryInfo);
|
|
293
|
+
debug(`Preparing Advertiser for '${this.accessoryInfo.displayName}' using Avahi backend!`);
|
|
294
|
+
this.bus = dbus_native_1.default.systemBus();
|
|
295
|
+
this.stateChangeHandler = this.handleStateChangedEvent.bind(this);
|
|
296
|
+
}
|
|
297
|
+
createTxt() {
|
|
289
298
|
return Object
|
|
290
299
|
.entries(CiaoAdvertiser.createTxt(this.accessoryInfo, this.setupHash))
|
|
291
|
-
.map(
|
|
292
|
-
}
|
|
293
|
-
|
|
300
|
+
.map((el) => Buffer.from(el[0] + "=" + el[1]));
|
|
301
|
+
}
|
|
302
|
+
initPort(port) {
|
|
294
303
|
this.port = port;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
this.accessoryInfo.displayName, // name
|
|
319
|
-
"_hap._tcp", // type
|
|
320
|
-
"", // domain
|
|
321
|
-
"", // host
|
|
322
|
-
this.port, // port
|
|
323
|
-
this.createTxt(), // txt
|
|
324
|
-
],
|
|
325
|
-
signature: "iiussssqaay",
|
|
326
|
-
})];
|
|
327
|
-
case 2:
|
|
328
|
-
_c.sent();
|
|
329
|
-
return [4 /*yield*/, AvahiAdvertiser.avahiInvoke(this.bus, this.path, "EntryGroup", "Commit")];
|
|
330
|
-
case 3:
|
|
331
|
-
_c.sent();
|
|
332
|
-
_c.label = 4;
|
|
333
|
-
case 4:
|
|
334
|
-
_c.trys.push([4, 7, , 8]);
|
|
335
|
-
if (!!this.avahiServerInterface) return [3 /*break*/, 6];
|
|
336
|
-
_b = this;
|
|
337
|
-
return [4 /*yield*/, AvahiAdvertiser.avahiInterface(this.bus, "Server")];
|
|
338
|
-
case 5:
|
|
339
|
-
_b.avahiServerInterface = _c.sent();
|
|
340
|
-
this.avahiServerInterface.on("StateChanged", this.stateChangeHandler);
|
|
341
|
-
_c.label = 6;
|
|
342
|
-
case 6: return [3 /*break*/, 8];
|
|
343
|
-
case 7:
|
|
344
|
-
error_1 = _c.sent();
|
|
345
|
-
// We have some problem on Synology https://github.com/homebridge/HAP-NodeJS/issues/993
|
|
346
|
-
console.warn("Failed to create listener for avahi-daemon server state. The system will not be notified about restarts of avahi-daemon " +
|
|
347
|
-
"and will therefore stay undiscoverable in those instances. Error message: " + error_1);
|
|
348
|
-
if (error_1.stack) {
|
|
349
|
-
debug("Detailed error: " + error_1.stack);
|
|
350
|
-
}
|
|
351
|
-
return [3 /*break*/, 8];
|
|
352
|
-
case 8: return [2 /*return*/];
|
|
353
|
-
}
|
|
354
|
-
});
|
|
304
|
+
}
|
|
305
|
+
async startAdvertising() {
|
|
306
|
+
if (this.port == null) {
|
|
307
|
+
throw new Error("Tried starting Avahi advertisement without initializing port!");
|
|
308
|
+
}
|
|
309
|
+
if (!this.bus) {
|
|
310
|
+
throw new Error("Tried to start Avahi advertisement on a destroyed advertiser!");
|
|
311
|
+
}
|
|
312
|
+
debug(`Starting to advertise '${this.accessoryInfo.displayName}' using Avahi backend!`);
|
|
313
|
+
this.path = await AvahiAdvertiser.avahiInvoke(this.bus, "/", "Server", "EntryGroupNew");
|
|
314
|
+
await AvahiAdvertiser.avahiInvoke(this.bus, this.path, "EntryGroup", "AddService", {
|
|
315
|
+
body: [
|
|
316
|
+
-1, // interface
|
|
317
|
+
-1, // protocol
|
|
318
|
+
0, // flags
|
|
319
|
+
this.accessoryInfo.displayName, // name
|
|
320
|
+
"_hap._tcp", // type
|
|
321
|
+
"", // domain
|
|
322
|
+
"", // host
|
|
323
|
+
this.port, // port
|
|
324
|
+
this.createTxt(), // txt
|
|
325
|
+
],
|
|
326
|
+
signature: "iiussssqaay",
|
|
355
327
|
});
|
|
356
|
-
|
|
328
|
+
await AvahiAdvertiser.avahiInvoke(this.bus, this.path, "EntryGroup", "Commit");
|
|
329
|
+
try {
|
|
330
|
+
if (!this.avahiServerInterface) {
|
|
331
|
+
this.avahiServerInterface = await AvahiAdvertiser.avahiInterface(this.bus, "Server");
|
|
332
|
+
this.avahiServerInterface.on("StateChanged", this.stateChangeHandler);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
// We have some problem on Synology https://github.com/homebridge/HAP-NodeJS/issues/993
|
|
337
|
+
console.warn("Failed to create listener for avahi-daemon server state. The system will not be notified about restarts of avahi-daemon " +
|
|
338
|
+
"and will therefore stay undiscoverable in those instances. Error message: " + error);
|
|
339
|
+
if (error.stack) {
|
|
340
|
+
debug("Detailed error: " + error.stack);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
357
344
|
/**
|
|
358
345
|
* Event handler for the `StateChanged` event of the `org.freedesktop.Avahi.Server` DBus interface.
|
|
359
346
|
*
|
|
360
347
|
* This is called once the state of the running avahi-daemon changes its running state.
|
|
361
348
|
* @param state - The state the server changed into {@see AvahiServerState}.
|
|
362
349
|
*/
|
|
363
|
-
|
|
350
|
+
handleStateChangedEvent(state) {
|
|
364
351
|
if (state === 2 /* AvahiServerState.RUNNING */ && this.path) {
|
|
365
352
|
debug("Found Avahi daemon to have restarted!");
|
|
366
353
|
this.startAdvertising()
|
|
367
|
-
.catch(
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
debug("Updating txt record (txt: %o, silent: %d)", CiaoAdvertiser.createTxt(this.accessoryInfo, this.setupHash), silent);
|
|
384
|
-
_a.label = 1;
|
|
385
|
-
case 1:
|
|
386
|
-
_a.trys.push([1, 3, , 4]);
|
|
387
|
-
return [4 /*yield*/, AvahiAdvertiser.avahiInvoke(this.bus, this.path, "EntryGroup", "UpdateServiceTxt", {
|
|
388
|
-
body: [-1, -1, 0, this.accessoryInfo.displayName, "_hap._tcp", "", this.createTxt()],
|
|
389
|
-
signature: "iiusssaay",
|
|
390
|
-
})];
|
|
391
|
-
case 2:
|
|
392
|
-
_a.sent();
|
|
393
|
-
return [3 /*break*/, 4];
|
|
394
|
-
case 3:
|
|
395
|
-
error_2 = _a.sent();
|
|
396
|
-
console.error("Failed to update avahi advertisement: " + error_2);
|
|
397
|
-
return [3 /*break*/, 4];
|
|
398
|
-
case 4: return [2 /*return*/];
|
|
399
|
-
}
|
|
400
|
-
});
|
|
401
|
-
});
|
|
402
|
-
};
|
|
403
|
-
AvahiAdvertiser.prototype.destroy = function () {
|
|
404
|
-
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
405
|
-
var error_3;
|
|
406
|
-
return tslib_1.__generator(this, function (_a) {
|
|
407
|
-
switch (_a.label) {
|
|
408
|
-
case 0:
|
|
409
|
-
if (!this.bus) {
|
|
410
|
-
throw new Error("Tried to destroy Avahi advertisement on a destroyed advertiser!");
|
|
411
|
-
}
|
|
412
|
-
if (!this.path) return [3 /*break*/, 5];
|
|
413
|
-
_a.label = 1;
|
|
414
|
-
case 1:
|
|
415
|
-
_a.trys.push([1, 3, , 4]);
|
|
416
|
-
return [4 /*yield*/, AvahiAdvertiser.avahiInvoke(this.bus, this.path, "EntryGroup", "Free")];
|
|
417
|
-
case 2:
|
|
418
|
-
_a.sent();
|
|
419
|
-
return [3 /*break*/, 4];
|
|
420
|
-
case 3:
|
|
421
|
-
error_3 = _a.sent();
|
|
422
|
-
// Typically, this fails if e.g. avahi service was stopped in the meantime.
|
|
423
|
-
debug("Destroying Avahi advertisement failed: " + error_3);
|
|
424
|
-
return [3 /*break*/, 4];
|
|
425
|
-
case 4:
|
|
426
|
-
this.path = undefined;
|
|
427
|
-
_a.label = 5;
|
|
428
|
-
case 5:
|
|
429
|
-
if (this.avahiServerInterface) {
|
|
430
|
-
this.avahiServerInterface.removeListener("StateChanged", this.stateChangeHandler);
|
|
431
|
-
this.avahiServerInterface = undefined;
|
|
432
|
-
}
|
|
433
|
-
this.bus.connection.stream.destroy();
|
|
434
|
-
this.bus = undefined;
|
|
435
|
-
return [2 /*return*/];
|
|
436
|
-
}
|
|
437
|
-
});
|
|
438
|
-
});
|
|
439
|
-
};
|
|
440
|
-
AvahiAdvertiser.isAvailable = function () {
|
|
441
|
-
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
442
|
-
var bus, error_4, version, error_5;
|
|
443
|
-
return tslib_1.__generator(this, function (_a) {
|
|
444
|
-
switch (_a.label) {
|
|
445
|
-
case 0:
|
|
446
|
-
bus = dbus_native_1.default.systemBus();
|
|
447
|
-
_a.label = 1;
|
|
448
|
-
case 1:
|
|
449
|
-
_a.trys.push([1, , 9, 10]);
|
|
450
|
-
_a.label = 2;
|
|
451
|
-
case 2:
|
|
452
|
-
_a.trys.push([2, 4, , 5]);
|
|
453
|
-
return [4 /*yield*/, messageBusConnectionResult(bus)];
|
|
454
|
-
case 3:
|
|
455
|
-
_a.sent();
|
|
456
|
-
return [3 /*break*/, 5];
|
|
457
|
-
case 4:
|
|
458
|
-
error_4 = _a.sent();
|
|
459
|
-
debug("Avahi/DBus classified unavailable due to missing dbus interface!");
|
|
460
|
-
return [2 /*return*/, false];
|
|
461
|
-
case 5:
|
|
462
|
-
_a.trys.push([5, 7, , 8]);
|
|
463
|
-
return [4 /*yield*/, this.avahiInvoke(bus, "/", "Server", "GetVersionString")];
|
|
464
|
-
case 6:
|
|
465
|
-
version = _a.sent();
|
|
466
|
-
debug("Detected Avahi over DBus interface running version '%s'.", version);
|
|
467
|
-
return [3 /*break*/, 8];
|
|
468
|
-
case 7:
|
|
469
|
-
error_5 = _a.sent();
|
|
470
|
-
debug("Avahi/DBus classified unavailable due to missing avahi interface!");
|
|
471
|
-
return [2 /*return*/, false];
|
|
472
|
-
case 8: return [2 /*return*/, true];
|
|
473
|
-
case 9:
|
|
474
|
-
bus.connection.stream.destroy();
|
|
475
|
-
return [7 /*endfinally*/];
|
|
476
|
-
case 10: return [2 /*return*/];
|
|
477
|
-
}
|
|
354
|
+
.catch(reason => console.error("Could not (re-)create mDNS advertisement. The HAP-Server won't be discoverable: " + reason));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
async updateAdvertisement(silent) {
|
|
358
|
+
if (!this.bus) {
|
|
359
|
+
throw new Error("Tried to update Avahi advertisement on a destroyed advertiser!");
|
|
360
|
+
}
|
|
361
|
+
if (!this.path) {
|
|
362
|
+
debug("Tried to update advertisement without a valid `path`!");
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
debug("Updating txt record (txt: %o, silent: %d)", CiaoAdvertiser.createTxt(this.accessoryInfo, this.setupHash), silent);
|
|
366
|
+
try {
|
|
367
|
+
await AvahiAdvertiser.avahiInvoke(this.bus, this.path, "EntryGroup", "UpdateServiceTxt", {
|
|
368
|
+
body: [-1, -1, 0, this.accessoryInfo.displayName, "_hap._tcp", "", this.createTxt()],
|
|
369
|
+
signature: "iiusssaay",
|
|
478
370
|
});
|
|
479
|
-
}
|
|
480
|
-
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
console.error("Failed to update avahi advertisement: " + error);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
async destroy() {
|
|
377
|
+
if (!this.bus) {
|
|
378
|
+
throw new Error("Tried to destroy Avahi advertisement on a destroyed advertiser!");
|
|
379
|
+
}
|
|
380
|
+
if (this.path) {
|
|
381
|
+
try {
|
|
382
|
+
await AvahiAdvertiser.avahiInvoke(this.bus, this.path, "EntryGroup", "Free");
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
// Typically, this fails if e.g. avahi service was stopped in the meantime.
|
|
386
|
+
debug("Destroying Avahi advertisement failed: " + error);
|
|
387
|
+
}
|
|
388
|
+
this.path = undefined;
|
|
389
|
+
}
|
|
390
|
+
if (this.avahiServerInterface) {
|
|
391
|
+
this.avahiServerInterface.removeListener("StateChanged", this.stateChangeHandler);
|
|
392
|
+
this.avahiServerInterface = undefined;
|
|
393
|
+
}
|
|
394
|
+
this.bus.connection.stream.destroy();
|
|
395
|
+
this.bus = undefined;
|
|
396
|
+
}
|
|
397
|
+
static async isAvailable() {
|
|
398
|
+
const bus = dbus_native_1.default.systemBus();
|
|
399
|
+
try {
|
|
400
|
+
try {
|
|
401
|
+
await messageBusConnectionResult(bus);
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
debug("Avahi/DBus classified unavailable due to missing dbus interface!");
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
try {
|
|
408
|
+
const version = await this.avahiInvoke(bus, "/", "Server", "GetVersionString");
|
|
409
|
+
debug("Detected Avahi over DBus interface running version '%s'.", version);
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
debug("Avahi/DBus classified unavailable due to missing avahi interface!");
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
return true;
|
|
416
|
+
}
|
|
417
|
+
finally {
|
|
418
|
+
bus.connection.stream.destroy();
|
|
419
|
+
}
|
|
420
|
+
}
|
|
481
421
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
482
|
-
|
|
483
|
-
return dbusInvoke(bus, "org.freedesktop.Avahi", path,
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
return new Promise(
|
|
422
|
+
static avahiInvoke(bus, path, dbusInterface, member, others) {
|
|
423
|
+
return dbusInvoke(bus, "org.freedesktop.Avahi", path, `org.freedesktop.Avahi.${dbusInterface}`, member, others);
|
|
424
|
+
}
|
|
425
|
+
static avahiInterface(bus, dbusInterface) {
|
|
426
|
+
return new Promise((resolve, reject) => {
|
|
487
427
|
bus
|
|
488
428
|
.getService("org.freedesktop.Avahi")
|
|
489
|
-
.getInterface("/", "org.freedesktop.Avahi." + dbusInterface,
|
|
429
|
+
.getInterface("/", "org.freedesktop.Avahi." + dbusInterface, (error, iface) => {
|
|
490
430
|
if (error || !iface) {
|
|
491
|
-
reject(error
|
|
431
|
+
reject(error ?? new Error("Interface not present!"));
|
|
492
432
|
}
|
|
493
433
|
else {
|
|
494
434
|
resolve(iface);
|
|
495
435
|
}
|
|
496
436
|
});
|
|
497
437
|
});
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
}(events_1.EventEmitter));
|
|
438
|
+
}
|
|
439
|
+
}
|
|
501
440
|
exports.AvahiAdvertiser = AvahiAdvertiser;
|
|
502
|
-
|
|
441
|
+
const RESOLVED_PERMISSIONS_ERRORS = [
|
|
503
442
|
"org.freedesktop.DBus.Error.AccessDenied",
|
|
504
443
|
"org.freedesktop.DBus.Error.AuthFailed",
|
|
505
444
|
"org.freedesktop.DBus.Error.InteractiveAuthorizationRequired",
|
|
@@ -510,217 +449,146 @@ var RESOLVED_PERMISSIONS_ERRORS = [
|
|
|
510
449
|
*
|
|
511
450
|
* @group Advertiser
|
|
512
451
|
*/
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
452
|
+
class ResolvedAdvertiser extends events_1.EventEmitter {
|
|
453
|
+
accessoryInfo;
|
|
454
|
+
setupHash;
|
|
455
|
+
port;
|
|
456
|
+
bus;
|
|
457
|
+
path;
|
|
458
|
+
constructor(accessoryInfo) {
|
|
459
|
+
super();
|
|
460
|
+
this.accessoryInfo = accessoryInfo;
|
|
461
|
+
this.setupHash = CiaoAdvertiser.computeSetupHash(accessoryInfo);
|
|
462
|
+
this.bus = dbus_native_1.default.systemBus();
|
|
463
|
+
debug(`Preparing Advertiser for '${this.accessoryInfo.displayName}' using systemd-resolved backend!`);
|
|
464
|
+
}
|
|
465
|
+
createTxt() {
|
|
524
466
|
return Object
|
|
525
467
|
.entries(CiaoAdvertiser.createTxt(this.accessoryInfo, this.setupHash))
|
|
526
|
-
.map(
|
|
527
|
-
}
|
|
528
|
-
|
|
468
|
+
.map((el) => [el[0].toString(), Buffer.from(el[1].toString())]);
|
|
469
|
+
}
|
|
470
|
+
initPort(port) {
|
|
529
471
|
this.port = port;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
this.accessoryInfo.displayName, // name_template
|
|
552
|
-
"_hap._tcp", // type
|
|
553
|
-
this.port, // service_port
|
|
554
|
-
0, // service_priority
|
|
555
|
-
0, // service_weight
|
|
556
|
-
[this.createTxt()], // txt_datas
|
|
557
|
-
],
|
|
558
|
-
signature: "sssqqqaa{say}",
|
|
559
|
-
})];
|
|
560
|
-
case 2:
|
|
561
|
-
_a.path = _b.sent();
|
|
562
|
-
return [3 /*break*/, 4];
|
|
563
|
-
case 3:
|
|
564
|
-
error_6 = _b.sent();
|
|
565
|
-
if (error_6 instanceof DBusInvokeError) {
|
|
566
|
-
if (RESOLVED_PERMISSIONS_ERRORS.includes(error_6.errorName)) {
|
|
567
|
-
error_6.message = "Permissions issue. See https://homebridge.io/w/mDNS-Options for more info. ".concat(error_6.message);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
throw error_6;
|
|
571
|
-
case 4: return [2 /*return*/];
|
|
572
|
-
}
|
|
573
|
-
});
|
|
574
|
-
});
|
|
575
|
-
};
|
|
576
|
-
ResolvedAdvertiser.prototype.updateAdvertisement = function (silent) {
|
|
577
|
-
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
578
|
-
return tslib_1.__generator(this, function (_a) {
|
|
579
|
-
switch (_a.label) {
|
|
580
|
-
case 0:
|
|
581
|
-
if (!this.bus) {
|
|
582
|
-
throw new Error("Tried to update systemd-resolved advertisement on a destroyed advertiser!");
|
|
583
|
-
}
|
|
584
|
-
debug("Updating txt record (txt: %o, silent: %d)", CiaoAdvertiser.createTxt(this.accessoryInfo, this.setupHash), silent);
|
|
585
|
-
// Currently, systemd-resolved has no way to update an existing record.
|
|
586
|
-
return [4 /*yield*/, this.stopAdvertising()];
|
|
587
|
-
case 1:
|
|
588
|
-
// Currently, systemd-resolved has no way to update an existing record.
|
|
589
|
-
_a.sent();
|
|
590
|
-
return [4 /*yield*/, this.startAdvertising()];
|
|
591
|
-
case 2:
|
|
592
|
-
_a.sent();
|
|
593
|
-
return [2 /*return*/];
|
|
594
|
-
}
|
|
472
|
+
}
|
|
473
|
+
async startAdvertising() {
|
|
474
|
+
if (this.port == null) {
|
|
475
|
+
throw new Error("Tried starting systemd-resolved advertisement without initializing port!");
|
|
476
|
+
}
|
|
477
|
+
if (!this.bus) {
|
|
478
|
+
throw new Error("Tried to start systemd-resolved advertisement on a destroyed advertiser!");
|
|
479
|
+
}
|
|
480
|
+
debug(`Starting to advertise '${this.accessoryInfo.displayName}' using systemd-resolved backend!`);
|
|
481
|
+
try {
|
|
482
|
+
this.path = await ResolvedAdvertiser.managerInvoke(this.bus, "RegisterService", {
|
|
483
|
+
body: [
|
|
484
|
+
this.accessoryInfo.displayName, // name
|
|
485
|
+
this.accessoryInfo.displayName, // name_template
|
|
486
|
+
"_hap._tcp", // type
|
|
487
|
+
this.port, // service_port
|
|
488
|
+
0, // service_priority
|
|
489
|
+
0, // service_weight
|
|
490
|
+
[this.createTxt()], // txt_datas
|
|
491
|
+
],
|
|
492
|
+
signature: "sssqqqaa{say}",
|
|
595
493
|
});
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
return tslib_1.__generator(this, function (_a) {
|
|
602
|
-
switch (_a.label) {
|
|
603
|
-
case 0:
|
|
604
|
-
if (!this.bus) {
|
|
605
|
-
throw new Error("Tried to destroy systemd-resolved advertisement on a destroyed advertiser!");
|
|
606
|
-
}
|
|
607
|
-
if (!this.path) return [3 /*break*/, 5];
|
|
608
|
-
_a.label = 1;
|
|
609
|
-
case 1:
|
|
610
|
-
_a.trys.push([1, 3, , 4]);
|
|
611
|
-
return [4 /*yield*/, ResolvedAdvertiser.managerInvoke(this.bus, "UnregisterService", {
|
|
612
|
-
body: [this.path],
|
|
613
|
-
signature: "o",
|
|
614
|
-
})];
|
|
615
|
-
case 2:
|
|
616
|
-
_a.sent();
|
|
617
|
-
return [3 /*break*/, 4];
|
|
618
|
-
case 3:
|
|
619
|
-
error_7 = _a.sent();
|
|
620
|
-
// Typically, this fails if e.g. systemd-resolved service was stopped in the meantime.
|
|
621
|
-
debug("Destroying systemd-resolved advertisement failed: " + error_7);
|
|
622
|
-
return [3 /*break*/, 4];
|
|
623
|
-
case 4:
|
|
624
|
-
this.path = undefined;
|
|
625
|
-
_a.label = 5;
|
|
626
|
-
case 5: return [2 /*return*/];
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
if (error instanceof DBusInvokeError) {
|
|
497
|
+
if (RESOLVED_PERMISSIONS_ERRORS.includes(error.errorName)) {
|
|
498
|
+
error.message = `Permissions issue. See https://homebridge.io/w/mDNS-Options for more info. ${error.message}`;
|
|
627
499
|
}
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
500
|
+
}
|
|
501
|
+
throw error;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
async updateAdvertisement(silent) {
|
|
505
|
+
if (!this.bus) {
|
|
506
|
+
throw new Error("Tried to update systemd-resolved advertisement on a destroyed advertiser!");
|
|
507
|
+
}
|
|
508
|
+
debug("Updating txt record (txt: %o, silent: %d)", CiaoAdvertiser.createTxt(this.accessoryInfo, this.setupHash), silent);
|
|
509
|
+
// Currently, systemd-resolved has no way to update an existing record.
|
|
510
|
+
await this.stopAdvertising();
|
|
511
|
+
await this.startAdvertising();
|
|
512
|
+
}
|
|
513
|
+
async stopAdvertising() {
|
|
514
|
+
if (!this.bus) {
|
|
515
|
+
throw new Error("Tried to destroy systemd-resolved advertisement on a destroyed advertiser!");
|
|
516
|
+
}
|
|
517
|
+
if (this.path) {
|
|
518
|
+
try {
|
|
519
|
+
await ResolvedAdvertiser.managerInvoke(this.bus, "UnregisterService", {
|
|
520
|
+
body: [this.path],
|
|
521
|
+
signature: "o",
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
catch (error) {
|
|
525
|
+
// Typically, this fails if e.g. systemd-resolved service was stopped in the meantime.
|
|
526
|
+
debug("Destroying systemd-resolved advertisement failed: " + error);
|
|
527
|
+
}
|
|
528
|
+
this.path = undefined;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
async destroy() {
|
|
532
|
+
if (!this.bus) {
|
|
533
|
+
throw new Error("Tried to destroy systemd-resolved advertisement on a destroyed advertiser!");
|
|
534
|
+
}
|
|
535
|
+
await this.stopAdvertising();
|
|
536
|
+
this.bus.connection.stream.destroy();
|
|
537
|
+
this.bus = undefined;
|
|
538
|
+
}
|
|
539
|
+
static async isAvailable() {
|
|
540
|
+
const bus = dbus_native_1.default.systemBus();
|
|
541
|
+
try {
|
|
542
|
+
try {
|
|
543
|
+
await messageBusConnectionResult(bus);
|
|
544
|
+
}
|
|
545
|
+
catch (error) {
|
|
546
|
+
debug("systemd-resolved/DBus classified unavailable due to missing dbus interface!");
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
try {
|
|
550
|
+
// Ensure that systemd-resolved is accessible.
|
|
551
|
+
await this.managerInvoke(bus, "ResolveHostname", {
|
|
552
|
+
body: [0, "127.0.0.1", 0, 0],
|
|
553
|
+
signature: "isit",
|
|
554
|
+
});
|
|
555
|
+
debug("Detected systemd-resolved over DBus interface running version.");
|
|
556
|
+
}
|
|
557
|
+
catch (error) {
|
|
558
|
+
debug("systemd-resolved/DBus classified unavailable due to missing systemd-resolved interface!");
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
try {
|
|
562
|
+
const mdnsStatus = await this.resolvedInvoke(bus, "org.freedesktop.DBus.Properties", "Get", {
|
|
563
|
+
body: ["org.freedesktop.resolve1.Manager", "MulticastDNS"],
|
|
564
|
+
signature: "ss",
|
|
565
|
+
});
|
|
566
|
+
if (mdnsStatus[0][0].type !== "s") {
|
|
567
|
+
throw new Error("Invalid type for MulticastDNS");
|
|
645
568
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
ResolvedAdvertiser.isAvailable = function () {
|
|
650
|
-
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
651
|
-
var bus, error_8, error_9, mdnsStatus, error_10;
|
|
652
|
-
return tslib_1.__generator(this, function (_a) {
|
|
653
|
-
switch (_a.label) {
|
|
654
|
-
case 0:
|
|
655
|
-
bus = dbus_native_1.default.systemBus();
|
|
656
|
-
_a.label = 1;
|
|
657
|
-
case 1:
|
|
658
|
-
_a.trys.push([1, , 12, 13]);
|
|
659
|
-
_a.label = 2;
|
|
660
|
-
case 2:
|
|
661
|
-
_a.trys.push([2, 4, , 5]);
|
|
662
|
-
return [4 /*yield*/, messageBusConnectionResult(bus)];
|
|
663
|
-
case 3:
|
|
664
|
-
_a.sent();
|
|
665
|
-
return [3 /*break*/, 5];
|
|
666
|
-
case 4:
|
|
667
|
-
error_8 = _a.sent();
|
|
668
|
-
debug("systemd-resolved/DBus classified unavailable due to missing dbus interface!");
|
|
669
|
-
return [2 /*return*/, false];
|
|
670
|
-
case 5:
|
|
671
|
-
_a.trys.push([5, 7, , 8]);
|
|
672
|
-
// Ensure that systemd-resolved is accessible.
|
|
673
|
-
return [4 /*yield*/, this.managerInvoke(bus, "ResolveHostname", {
|
|
674
|
-
body: [0, "127.0.0.1", 0, 0],
|
|
675
|
-
signature: "isit",
|
|
676
|
-
})];
|
|
677
|
-
case 6:
|
|
678
|
-
// Ensure that systemd-resolved is accessible.
|
|
679
|
-
_a.sent();
|
|
680
|
-
debug("Detected systemd-resolved over DBus interface running version.");
|
|
681
|
-
return [3 /*break*/, 8];
|
|
682
|
-
case 7:
|
|
683
|
-
error_9 = _a.sent();
|
|
684
|
-
debug("systemd-resolved/DBus classified unavailable due to missing systemd-resolved interface!");
|
|
685
|
-
return [2 /*return*/, false];
|
|
686
|
-
case 8:
|
|
687
|
-
_a.trys.push([8, 10, , 11]);
|
|
688
|
-
return [4 /*yield*/, this.resolvedInvoke(bus, "org.freedesktop.DBus.Properties", "Get", {
|
|
689
|
-
body: ["org.freedesktop.resolve1.Manager", "MulticastDNS"],
|
|
690
|
-
signature: "ss",
|
|
691
|
-
})];
|
|
692
|
-
case 9:
|
|
693
|
-
mdnsStatus = _a.sent();
|
|
694
|
-
if (mdnsStatus[0][0].type !== "s") {
|
|
695
|
-
throw new Error("Invalid type for MulticastDNS");
|
|
696
|
-
}
|
|
697
|
-
if (mdnsStatus[1][0] !== "yes") {
|
|
698
|
-
debug("systemd-resolved/DBus classified unavailable because MulticastDNS is not enabled!");
|
|
699
|
-
return [2 /*return*/, false];
|
|
700
|
-
}
|
|
701
|
-
return [3 /*break*/, 11];
|
|
702
|
-
case 10:
|
|
703
|
-
error_10 = _a.sent();
|
|
704
|
-
debug("systemd-resolved/DBus classified unavailable due to failure checking system status: " + error_10);
|
|
705
|
-
return [2 /*return*/, false];
|
|
706
|
-
case 11: return [2 /*return*/, true];
|
|
707
|
-
case 12:
|
|
708
|
-
bus.connection.stream.destroy();
|
|
709
|
-
return [7 /*endfinally*/];
|
|
710
|
-
case 13: return [2 /*return*/];
|
|
569
|
+
if (mdnsStatus[1][0] !== "yes") {
|
|
570
|
+
debug("systemd-resolved/DBus classified unavailable because MulticastDNS is not enabled!");
|
|
571
|
+
return false;
|
|
711
572
|
}
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
|
|
573
|
+
}
|
|
574
|
+
catch (error) {
|
|
575
|
+
debug("systemd-resolved/DBus classified unavailable due to failure checking system status: " + error);
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
finally {
|
|
581
|
+
bus.connection.stream.destroy();
|
|
582
|
+
}
|
|
583
|
+
}
|
|
715
584
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
716
|
-
|
|
585
|
+
static resolvedInvoke(bus, dbusInterface, member, others) {
|
|
717
586
|
return dbusInvoke(bus, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", dbusInterface, member, others);
|
|
718
|
-
}
|
|
587
|
+
}
|
|
719
588
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
720
|
-
|
|
589
|
+
static managerInvoke(bus, member, others) {
|
|
721
590
|
return this.resolvedInvoke(bus, "org.freedesktop.resolve1.Manager", member, others);
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
}(events_1.EventEmitter));
|
|
591
|
+
}
|
|
592
|
+
}
|
|
725
593
|
exports.ResolvedAdvertiser = ResolvedAdvertiser;
|
|
726
594
|
//# sourceMappingURL=Advertiser.js.map
|