@matter/general 0.16.8-alpha.0-20260125-38e62bc3e → 0.16.8-alpha.0-20260127-65e1b40e2
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/dist/cjs/net/ServerAddress.d.ts.map +1 -1
- package/dist/cjs/net/ServerAddress.js +2 -1
- package/dist/cjs/net/ServerAddress.js.map +1 -1
- package/dist/cjs/net/dns-sd/DnssdName.d.ts +56 -0
- package/dist/cjs/net/dns-sd/DnssdName.d.ts.map +1 -0
- package/dist/cjs/net/dns-sd/DnssdName.js +193 -0
- package/dist/cjs/net/dns-sd/DnssdName.js.map +6 -0
- package/dist/cjs/net/dns-sd/DnssdNames.d.ts +77 -0
- package/dist/cjs/net/dns-sd/DnssdNames.d.ts.map +1 -0
- package/dist/cjs/net/dns-sd/DnssdNames.js +238 -0
- package/dist/cjs/net/dns-sd/DnssdNames.js.map +6 -0
- package/dist/cjs/net/dns-sd/DnssdSolicitor.d.ts +80 -0
- package/dist/cjs/net/dns-sd/DnssdSolicitor.d.ts.map +1 -0
- package/dist/cjs/net/dns-sd/DnssdSolicitor.js +212 -0
- package/dist/cjs/net/dns-sd/DnssdSolicitor.js.map +6 -0
- package/dist/cjs/net/dns-sd/IpService.d.ts +73 -0
- package/dist/cjs/net/dns-sd/IpService.d.ts.map +1 -0
- package/dist/cjs/net/dns-sd/IpService.js +329 -0
- package/dist/cjs/net/dns-sd/IpService.js.map +6 -0
- package/dist/cjs/net/dns-sd/IpServiceResolution.d.ts +16 -0
- package/dist/cjs/net/dns-sd/IpServiceResolution.d.ts.map +1 -0
- package/dist/cjs/net/dns-sd/IpServiceResolution.js +162 -0
- package/dist/cjs/net/dns-sd/IpServiceResolution.js.map +6 -0
- package/dist/cjs/net/dns-sd/IpServiceStatus.d.ts +58 -0
- package/dist/cjs/net/dns-sd/IpServiceStatus.d.ts.map +1 -0
- package/dist/cjs/net/dns-sd/IpServiceStatus.js +191 -0
- package/dist/cjs/net/dns-sd/IpServiceStatus.js.map +6 -0
- package/dist/cjs/net/dns-sd/index.d.ts +6 -0
- package/dist/cjs/net/dns-sd/index.d.ts.map +1 -1
- package/dist/cjs/net/dns-sd/index.js +6 -0
- package/dist/cjs/net/dns-sd/index.js.map +1 -1
- package/dist/cjs/net/udp/UdpInterface.js +1 -1
- package/dist/cjs/net/udp/UdpInterface.js.map +1 -1
- package/dist/esm/net/ServerAddress.d.ts.map +1 -1
- package/dist/esm/net/ServerAddress.js +2 -1
- package/dist/esm/net/ServerAddress.js.map +1 -1
- package/dist/esm/net/dns-sd/DnssdName.d.ts +56 -0
- package/dist/esm/net/dns-sd/DnssdName.d.ts.map +1 -0
- package/dist/esm/net/dns-sd/DnssdName.js +173 -0
- package/dist/esm/net/dns-sd/DnssdName.js.map +6 -0
- package/dist/esm/net/dns-sd/DnssdNames.d.ts +77 -0
- package/dist/esm/net/dns-sd/DnssdNames.d.ts.map +1 -0
- package/dist/esm/net/dns-sd/DnssdNames.js +218 -0
- package/dist/esm/net/dns-sd/DnssdNames.js.map +6 -0
- package/dist/esm/net/dns-sd/DnssdSolicitor.d.ts +80 -0
- package/dist/esm/net/dns-sd/DnssdSolicitor.d.ts.map +1 -0
- package/dist/esm/net/dns-sd/DnssdSolicitor.js +192 -0
- package/dist/esm/net/dns-sd/DnssdSolicitor.js.map +6 -0
- package/dist/esm/net/dns-sd/IpService.d.ts +73 -0
- package/dist/esm/net/dns-sd/IpService.d.ts.map +1 -0
- package/dist/esm/net/dns-sd/IpService.js +309 -0
- package/dist/esm/net/dns-sd/IpService.js.map +6 -0
- package/dist/esm/net/dns-sd/IpServiceResolution.d.ts +16 -0
- package/dist/esm/net/dns-sd/IpServiceResolution.d.ts.map +1 -0
- package/dist/esm/net/dns-sd/IpServiceResolution.js +142 -0
- package/dist/esm/net/dns-sd/IpServiceResolution.js.map +6 -0
- package/dist/esm/net/dns-sd/IpServiceStatus.d.ts +58 -0
- package/dist/esm/net/dns-sd/IpServiceStatus.d.ts.map +1 -0
- package/dist/esm/net/dns-sd/IpServiceStatus.js +171 -0
- package/dist/esm/net/dns-sd/IpServiceStatus.js.map +6 -0
- package/dist/esm/net/dns-sd/index.d.ts +6 -0
- package/dist/esm/net/dns-sd/index.d.ts.map +1 -1
- package/dist/esm/net/dns-sd/index.js +6 -0
- package/dist/esm/net/dns-sd/index.js.map +1 -1
- package/dist/esm/net/udp/UdpInterface.js +1 -1
- package/dist/esm/net/udp/UdpInterface.js.map +1 -1
- package/package.json +2 -2
- package/src/net/ServerAddress.ts +2 -1
- package/src/net/dns-sd/DnssdName.ts +252 -0
- package/src/net/dns-sd/DnssdNames.ts +208 -0
- package/src/net/dns-sd/DnssdSolicitor.ts +231 -0
- package/src/net/dns-sd/IpService.ts +346 -0
- package/src/net/dns-sd/IpServiceResolution.ts +134 -0
- package/src/net/dns-sd/IpServiceStatus.ts +212 -0
- package/src/net/dns-sd/index.ts +6 -0
- package/src/net/udp/UdpInterface.ts +1 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2026 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Diagnostic } from "#log/Diagnostic.js";
|
|
7
|
+
import { Logger } from "#log/Logger.js";
|
|
8
|
+
import { AbortedError } from "#MatterError.js";
|
|
9
|
+
import { ServerAddress } from "#net/ServerAddress.js";
|
|
10
|
+
import { Time } from "#time/Time.js";
|
|
11
|
+
import { Abort } from "#util/Abort.js";
|
|
12
|
+
import { asError } from "#util/Error.js";
|
|
13
|
+
import { BasicSet } from "#util/Set.js";
|
|
14
|
+
import { IpServiceResolution } from "./IpServiceResolution.js";
|
|
15
|
+
const logger = Logger.get("IpServiceStatus");
|
|
16
|
+
class IpServiceStatus {
|
|
17
|
+
#service;
|
|
18
|
+
#isReachable = false;
|
|
19
|
+
#connecting = new BasicSet();
|
|
20
|
+
#resolveAbort;
|
|
21
|
+
#resolving;
|
|
22
|
+
#connectionInitiatedAt;
|
|
23
|
+
#lastReceiptAt;
|
|
24
|
+
constructor(service) {
|
|
25
|
+
this.#service = service;
|
|
26
|
+
}
|
|
27
|
+
async close() {
|
|
28
|
+
this.#stopResolving();
|
|
29
|
+
if (this.#resolving) {
|
|
30
|
+
await this.#resolving;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Is the service actively connecting?
|
|
35
|
+
*
|
|
36
|
+
* This is true so long as a promise passed to {@link connecting} is unresolved.
|
|
37
|
+
*/
|
|
38
|
+
get isConnecting() {
|
|
39
|
+
return this.#connecting.size > 0;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Is the service currently reachable?
|
|
43
|
+
*
|
|
44
|
+
* This value is writable. If you set {@link isReachable} to false and {@link isConnecting} is true, the service
|
|
45
|
+
* enters discovery mode and begins active solicitation so long as neither condition changes.
|
|
46
|
+
*
|
|
47
|
+
* The service sets {@link isReachable} to true automatically if:
|
|
48
|
+
*
|
|
49
|
+
* - It discovers a new (previously unknown) address, or
|
|
50
|
+
*
|
|
51
|
+
* - The input promise to {@link connecting} resolves to true
|
|
52
|
+
*
|
|
53
|
+
* The service sets {@link isReachable} to false automatically if the input promise to {@link connecting} resolves
|
|
54
|
+
* to false.
|
|
55
|
+
*/
|
|
56
|
+
get isReachable() {
|
|
57
|
+
return this.#isReachable;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Are we actively performing MDNS discovery for the service?
|
|
61
|
+
*/
|
|
62
|
+
get isResolving() {
|
|
63
|
+
return this.#resolving !== void 0;
|
|
64
|
+
}
|
|
65
|
+
set isReachable(isReachable) {
|
|
66
|
+
if (this.#isReachable === isReachable) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.#isReachable = isReachable;
|
|
70
|
+
if (isReachable) {
|
|
71
|
+
this.#maybeStopResolving();
|
|
72
|
+
} else {
|
|
73
|
+
this.#maybeStartResolving();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
get lastReceiptAt() {
|
|
77
|
+
return this.#lastReceiptAt;
|
|
78
|
+
}
|
|
79
|
+
set lastReceiptAt(time) {
|
|
80
|
+
this.#lastReceiptAt = time;
|
|
81
|
+
}
|
|
82
|
+
get connectionInitiatedAt() {
|
|
83
|
+
return this.#connectionInitiatedAt;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Register a new connection attempt.
|
|
87
|
+
*
|
|
88
|
+
* If {@link result} resolves as true the service is marked as reachable. If {@link result} resolves as false
|
|
89
|
+
* reachability is not modified.
|
|
90
|
+
*
|
|
91
|
+
* If {@link result} throws an error other than {@link AbortedError}, the service is marked as unreachable and if
|
|
92
|
+
* the error logged.
|
|
93
|
+
*
|
|
94
|
+
* {@link isConnecting} will be true until {@link result} resolves.
|
|
95
|
+
*/
|
|
96
|
+
connecting(result) {
|
|
97
|
+
logger.debug(this.#service.via, "Connecting");
|
|
98
|
+
result.then(
|
|
99
|
+
(returned) => {
|
|
100
|
+
this.#connecting.delete(result);
|
|
101
|
+
if (!this.#connecting.size) {
|
|
102
|
+
this.#connectionInitiatedAt = void 0;
|
|
103
|
+
}
|
|
104
|
+
if (returned) {
|
|
105
|
+
this.isReachable = true;
|
|
106
|
+
logger.info(this.#service.via, "Connected");
|
|
107
|
+
} else {
|
|
108
|
+
logger.debug(this.#service.via, "Connect attempt aborted");
|
|
109
|
+
}
|
|
110
|
+
this.#maybeStopResolving();
|
|
111
|
+
},
|
|
112
|
+
(error) => {
|
|
113
|
+
this.#connecting.delete(result);
|
|
114
|
+
if (!(error instanceof AbortedError)) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
logger.error(this.#service.via, "Connection error:", asError(error));
|
|
118
|
+
this.#isReachable = false;
|
|
119
|
+
this.#maybeStartResolving();
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
this.#connectionInitiatedAt = Time.nowMs;
|
|
123
|
+
this.#connecting.add(result);
|
|
124
|
+
this.#maybeStartResolving();
|
|
125
|
+
}
|
|
126
|
+
#maybeStartResolving() {
|
|
127
|
+
if (this.#isReachable || !this.isConnecting || this.#resolveAbort) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const numAddresses = this.#service.addresses.size;
|
|
131
|
+
let why;
|
|
132
|
+
switch (numAddresses) {
|
|
133
|
+
case 0:
|
|
134
|
+
why = "need address";
|
|
135
|
+
break;
|
|
136
|
+
case 1:
|
|
137
|
+
why = "address is unreachable";
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
why = `${numAddresses} known addresses are unreachable`;
|
|
141
|
+
}
|
|
142
|
+
logger.info(this.#service.via, "Resolving", Diagnostic.weak(`(${why})`));
|
|
143
|
+
this.#resolveAbort = new Abort();
|
|
144
|
+
this.#resolving = IpServiceResolution(this.#service, this.#resolveAbort).finally(() => {
|
|
145
|
+
if (this.#resolveAbort?.aborted === false) {
|
|
146
|
+
const addresses = [...this.#service.addresses].map(ServerAddress.urlFor);
|
|
147
|
+
logger.debug(this.#service.via, `Resolved as ${addresses.join(", ")}`);
|
|
148
|
+
}
|
|
149
|
+
this.#resolveAbort?.close();
|
|
150
|
+
this.#resolveAbort = void 0;
|
|
151
|
+
this.#resolving = void 0;
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
#maybeStopResolving() {
|
|
155
|
+
if (!this.#isReachable || this.isConnecting || !this.#resolveAbort) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
this.#stopResolving();
|
|
159
|
+
}
|
|
160
|
+
#stopResolving() {
|
|
161
|
+
if (!this.#resolveAbort) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
this.#resolveAbort();
|
|
165
|
+
logger.debug(this.#service.via, "Stopped resolving");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
export {
|
|
169
|
+
IpServiceStatus
|
|
170
|
+
};
|
|
171
|
+
//# sourceMappingURL=IpServiceStatus.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/net/dns-sd/IpServiceStatus.ts"],
|
|
4
|
+
"mappings": "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",
|
|
5
|
+
"names": []
|
|
6
|
+
}
|
|
@@ -3,5 +3,11 @@
|
|
|
3
3
|
* Copyright 2022-2026 Matter.js Authors
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
export * from "./DnssdName.js";
|
|
7
|
+
export * from "./DnssdNames.js";
|
|
8
|
+
export * from "./DnssdSolicitor.js";
|
|
9
|
+
export * from "./IpService.js";
|
|
10
|
+
export * from "./IpServiceResolution.js";
|
|
11
|
+
export * from "./IpServiceStatus.js";
|
|
6
12
|
export * from "./MdnsSocket.js";
|
|
7
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/net/dns-sd/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/net/dns-sd/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC"}
|
|
@@ -3,5 +3,11 @@
|
|
|
3
3
|
* Copyright 2022-2026 Matter.js Authors
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
export * from "./DnssdName.js";
|
|
7
|
+
export * from "./DnssdNames.js";
|
|
8
|
+
export * from "./DnssdSolicitor.js";
|
|
9
|
+
export * from "./IpService.js";
|
|
10
|
+
export * from "./IpServiceResolution.js";
|
|
11
|
+
export * from "./IpServiceStatus.js";
|
|
6
12
|
export * from "./MdnsSocket.js";
|
|
7
13
|
//# sourceMappingURL=index.js.map
|
|
@@ -65,7 +65,7 @@ class UdpConnection {
|
|
|
65
65
|
return this.#server.send(this.#peerAddress, this.#peerPort, data);
|
|
66
66
|
}
|
|
67
67
|
get name() {
|
|
68
|
-
return `${this.type}
|
|
68
|
+
return `${this.type}://${this.#peerAddress.includes(":") ? `[${this.#peerAddress}]` : this.#peerAddress}:${this.#peerPort}`;
|
|
69
69
|
}
|
|
70
70
|
get networkAddress() {
|
|
71
71
|
return { type: "udp", ip: this.#peerAddress, port: this.#peerPort };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/net/udp/UdpInterface.ts"],
|
|
4
|
-
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,SAAkB,mBAAqC;AAEvD,SAAkB,oBAAoB;AAK/B,MAAM,aAAgD;AAAA,EAChD;AAAA,EAET,aAAa,OAAO,SAAkB,MAAuB,MAAe,MAAe,cAAuB;AAC9G,WAAO,IAAI;AAAA,MACP,MAAM,QAAQ,iBAAiB,EAAE,eAAe,MAAM,MAAM,cAAc,kBAAkB,KAAK,CAAC;AAAA,IACtG;AAAA,EACJ;AAAA,EAEA,YAAY,QAAoB;AAC5B,SAAK,UAAU;AAAA,EACnB;AAAA,EAEA,IAAc,SAAS;AACnB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,SAAS,MAAmB,SAAiB;AACzC,WAAO,KAAK,QAAQ,SAAS,MAAM,OAAO;AAAA,EAC9C;AAAA,EAEA,MAAM,YAAY,SAAwB;AACtC,QAAI,QAAQ,SAAS,OAAO;AACxB,YAAM,IAAI,aAAa,4BAA4B,QAAQ,IAAI,EAAE;AAAA,IACrE;AACA,UAAM,EAAE,IAAI,KAAK,IAAI;AACrB,WAAO,QAAQ,QAAQ,IAAI,cAAc,KAAK,SAAS,IAAI,IAAI,CAAC;AAAA,EACpE;AAAA,EAEA,OAAO,UAAoG;AACvG,WAAO,KAAK,QAAQ;AAAA,MAAO,CAAC,eAAe,UAAU,UAAU,SAC3D,SAAS,IAAI,cAAc,KAAK,SAAS,UAAU,QAAQ,GAAG,IAAI;AAAA,IACtE;AAAA,EACJ;AAAA,EAEA,IAAI,OAAO;AACP,WAAO,KAAK,QAAQ;AAAA,EACxB;AAAA,EAEA,QAAQ;AACJ,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC9B;AAAA,EAEA,cAAc,SAAiB;AAC3B,WAAO,KAAK,QAAQ,cAAc,OAAO;AAAA,EAC7C;AAAA,EAEA,eAAe,SAAiB;AAC5B,WAAO,KAAK,QAAQ,eAAe,OAAO;AAAA,EAC9C;AACJ;AAEO,MAAM,cAAiD;AAAA,EACjD,aAAa;AAAA,EACb,wBAAwB;AAAA,EACxB,OAAO,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAoB,aAAqB,UAAkB;AACnE,SAAK,UAAU;AACf,SAAK,eAAe;AACpB,SAAK,YAAY;AAAA,EACrB;AAAA,EAEA,IAAI,iBAAiB;AACjB,WAAO,KAAK,QAAQ;AAAA,EACxB;AAAA,EAEA,KAAK,MAAa;AACd,WAAO,KAAK,QAAQ,KAAK,KAAK,cAAc,KAAK,WAAW,IAAI;AAAA,EACpE;AAAA,EAEA,IAAI,OAAO;AACP,WAAO,GAAG,KAAK,IAAI,
|
|
4
|
+
"mappings": "AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,SAAkB,mBAAqC;AAEvD,SAAkB,oBAAoB;AAK/B,MAAM,aAAgD;AAAA,EAChD;AAAA,EAET,aAAa,OAAO,SAAkB,MAAuB,MAAe,MAAe,cAAuB;AAC9G,WAAO,IAAI;AAAA,MACP,MAAM,QAAQ,iBAAiB,EAAE,eAAe,MAAM,MAAM,cAAc,kBAAkB,KAAK,CAAC;AAAA,IACtG;AAAA,EACJ;AAAA,EAEA,YAAY,QAAoB;AAC5B,SAAK,UAAU;AAAA,EACnB;AAAA,EAEA,IAAc,SAAS;AACnB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,SAAS,MAAmB,SAAiB;AACzC,WAAO,KAAK,QAAQ,SAAS,MAAM,OAAO;AAAA,EAC9C;AAAA,EAEA,MAAM,YAAY,SAAwB;AACtC,QAAI,QAAQ,SAAS,OAAO;AACxB,YAAM,IAAI,aAAa,4BAA4B,QAAQ,IAAI,EAAE;AAAA,IACrE;AACA,UAAM,EAAE,IAAI,KAAK,IAAI;AACrB,WAAO,QAAQ,QAAQ,IAAI,cAAc,KAAK,SAAS,IAAI,IAAI,CAAC;AAAA,EACpE;AAAA,EAEA,OAAO,UAAoG;AACvG,WAAO,KAAK,QAAQ;AAAA,MAAO,CAAC,eAAe,UAAU,UAAU,SAC3D,SAAS,IAAI,cAAc,KAAK,SAAS,UAAU,QAAQ,GAAG,IAAI;AAAA,IACtE;AAAA,EACJ;AAAA,EAEA,IAAI,OAAO;AACP,WAAO,KAAK,QAAQ;AAAA,EACxB;AAAA,EAEA,QAAQ;AACJ,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC9B;AAAA,EAEA,cAAc,SAAiB;AAC3B,WAAO,KAAK,QAAQ,cAAc,OAAO;AAAA,EAC7C;AAAA,EAEA,eAAe,SAAiB;AAC5B,WAAO,KAAK,QAAQ,eAAe,OAAO;AAAA,EAC9C;AACJ;AAEO,MAAM,cAAiD;AAAA,EACjD,aAAa;AAAA,EACb,wBAAwB;AAAA,EACxB,OAAO,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAoB,aAAqB,UAAkB;AACnE,SAAK,UAAU;AACf,SAAK,eAAe;AACpB,SAAK,YAAY;AAAA,EACrB;AAAA,EAEA,IAAI,iBAAiB;AACjB,WAAO,KAAK,QAAQ;AAAA,EACxB;AAAA,EAEA,KAAK,MAAa;AACd,WAAO,KAAK,QAAQ,KAAK,KAAK,cAAc,KAAK,WAAW,IAAI;AAAA,EACpE;AAAA,EAEA,IAAI,OAAO;AACP,WAAO,GAAG,KAAK,IAAI,MAAM,KAAK,aAAa,SAAS,GAAG,IAAI,IAAI,KAAK,YAAY,MAAM,KAAK,YAAY,IAAI,KAAK,SAAS;AAAA,EAC7H;AAAA,EAEA,IAAI,iBAAmC;AACnC,WAAO,EAAE,MAAM,OAAO,IAAI,KAAK,cAAc,MAAM,KAAK,UAAU;AAAA,EACtE;AAAA,EAEA,MAAM,QAAQ;AAAA,EAEd;AACJ;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matter/general",
|
|
3
|
-
"version": "0.16.8-alpha.0-
|
|
3
|
+
"version": "0.16.8-alpha.0-20260127-65e1b40e2",
|
|
4
4
|
"description": "Non-Matter support for Matter.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"iot",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@noble/curves": "^2.0.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@matter/testing": "0.16.8-alpha.0-
|
|
39
|
+
"@matter/testing": "0.16.8-alpha.0-20260127-65e1b40e2"
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
42
|
"dist/**/*",
|
package/src/net/ServerAddress.ts
CHANGED
|
@@ -78,7 +78,8 @@ export namespace ServerAddress {
|
|
|
78
78
|
switch (address.type) {
|
|
79
79
|
case "udp":
|
|
80
80
|
case "tcp":
|
|
81
|
-
|
|
81
|
+
const ip = address.ip;
|
|
82
|
+
return `${address.type}://${ip.includes(":") ? `[${ip}]` : ip}:${address.port}`;
|
|
82
83
|
|
|
83
84
|
case "ble":
|
|
84
85
|
return `ble://${address.peripheralAddress}`;
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022-2026 Matter.js Authors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { DnsRecord, DnsRecordType, SrvRecordValue } from "#codec/DnsCodec.js";
|
|
8
|
+
import { Logger } from "#log/Logger.js";
|
|
9
|
+
import { Time } from "#time/Time.js";
|
|
10
|
+
import type { Timestamp } from "#time/Timestamp.js";
|
|
11
|
+
import { AsyncObserver, BasicObservable } from "#util/Observable.js";
|
|
12
|
+
import { MaybePromise } from "#util/Promises.js";
|
|
13
|
+
import type { DnssdNames } from "./DnssdNames.js";
|
|
14
|
+
|
|
15
|
+
const logger = Logger.get("DnssdName");
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Manages records associated with a single DNS-SD qname.
|
|
19
|
+
*
|
|
20
|
+
* Every DNS-SD qname of interest has a 1:1 relationship with a single instance of this class in the context of a
|
|
21
|
+
* {@link DnssdNames}. We therefore can use the qname or {@link DnssdName} interchangeably.
|
|
22
|
+
*
|
|
23
|
+
* An {@link DnssdName} is created when a new name is discovered or requested by another component. The name
|
|
24
|
+
* automatically deletes when there are no longer observers or unexpired records.
|
|
25
|
+
*/
|
|
26
|
+
export class DnssdName extends BasicObservable<[changes: DnssdName.Changes], MaybePromise> {
|
|
27
|
+
#context: DnssdName.Context;
|
|
28
|
+
#records = new Map<string, DnssdName.Record>();
|
|
29
|
+
#recordCount = 0;
|
|
30
|
+
#changes?: Map<string, { kind: "update" | "delete"; record: DnssdName.Record }>;
|
|
31
|
+
#notified?: Promise<void>;
|
|
32
|
+
#maybeDeleting?: Promise<void>;
|
|
33
|
+
#parameters?: Map<string, string>;
|
|
34
|
+
|
|
35
|
+
constructor(
|
|
36
|
+
readonly qname: string,
|
|
37
|
+
context: DnssdName.Context,
|
|
38
|
+
) {
|
|
39
|
+
super(e => logger.error(`Unhandled error in observer for DNS name "${qname}":`, e));
|
|
40
|
+
this.#context = context;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
override off(observer: AsyncObserver<[]>) {
|
|
44
|
+
super.off(observer);
|
|
45
|
+
this.#deleteIfUnused();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async close() {
|
|
49
|
+
if (this.#notified) {
|
|
50
|
+
await this.#notified;
|
|
51
|
+
}
|
|
52
|
+
if (this.#maybeDeleting) {
|
|
53
|
+
await this.#maybeDeleting;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get records() {
|
|
58
|
+
return this.#records.values();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get parameters() {
|
|
62
|
+
if (this.#parameters === undefined) {
|
|
63
|
+
this.#parameters = new Map();
|
|
64
|
+
}
|
|
65
|
+
return this.#parameters;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get isDiscovered() {
|
|
69
|
+
return !!this.#recordCount;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
installRecord(record: DnsRecord<any>) {
|
|
73
|
+
// For TXT records, extract the standard DNS-SD k/v's
|
|
74
|
+
if (record.recordType === DnsRecordType.TXT) {
|
|
75
|
+
const entries = record.value;
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
const pos = entry.indexOf("=");
|
|
78
|
+
if (pos === -1) {
|
|
79
|
+
this.parameters.set(entry, "");
|
|
80
|
+
} else {
|
|
81
|
+
this.parameters.set(entry.slice(0, pos), entry.slice(pos + 1));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const key = keyOf(record);
|
|
87
|
+
if (key === undefined) {
|
|
88
|
+
this.#deleteIfUnused();
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const oldRecord = this.#records.get(key);
|
|
93
|
+
if (oldRecord) {
|
|
94
|
+
this.#context.unregisterForExpiration(oldRecord);
|
|
95
|
+
} else {
|
|
96
|
+
this.#recordCount++;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const recordWithExpire = { ...record, expiresAt: Time.nowMs + record.ttl } as DnssdName.Record;
|
|
100
|
+
|
|
101
|
+
this.#records.set(key, recordWithExpire);
|
|
102
|
+
|
|
103
|
+
this.#context.registerForExpiration(recordWithExpire);
|
|
104
|
+
|
|
105
|
+
this.#notify("update", key, recordWithExpire);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
deleteRecord(record: DnsRecord, ifOlderThan?: Timestamp) {
|
|
109
|
+
const key = keyOf(record);
|
|
110
|
+
if (key === undefined) {
|
|
111
|
+
this.#deleteIfUnused();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const recordWithExpire = this.#records?.get(key);
|
|
116
|
+
if (!recordWithExpire) {
|
|
117
|
+
this.#deleteIfUnused();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (ifOlderThan !== undefined && recordWithExpire.expiresAt - recordWithExpire.ttl >= ifOlderThan) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
this.#records.delete(key);
|
|
126
|
+
this.#recordCount--;
|
|
127
|
+
|
|
128
|
+
this.#context.unregisterForExpiration(recordWithExpire);
|
|
129
|
+
|
|
130
|
+
if (this.#deleteIfUnused()) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
this.#notify("delete", key, recordWithExpire);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Delete if unused.
|
|
139
|
+
*
|
|
140
|
+
* This is async so we assess whether deletion is appropriate after a batch of updates.
|
|
141
|
+
*/
|
|
142
|
+
#deleteIfUnused() {
|
|
143
|
+
if (this.isObserved || this.isDiscovered) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (this.#maybeDeleting) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const maybeDelete = async () => {
|
|
152
|
+
this.#maybeDeleting = undefined;
|
|
153
|
+
|
|
154
|
+
if (this.isObserved || this.isDiscovered) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this.#context.delete(this);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
this.#maybeDeleting = maybeDelete();
|
|
162
|
+
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Notification of observers.
|
|
168
|
+
*
|
|
169
|
+
* This is async so we coalesce changes into a single notification.
|
|
170
|
+
*/
|
|
171
|
+
#notify(kind: "update" | "delete", key: string, record: DnssdName.Record) {
|
|
172
|
+
if (this.#changes === undefined) {
|
|
173
|
+
this.#changes = new Map();
|
|
174
|
+
}
|
|
175
|
+
this.#changes.set(key, { kind, record });
|
|
176
|
+
|
|
177
|
+
if (this.#notified) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const notify = async () => {
|
|
182
|
+
while (this.#changes?.size) {
|
|
183
|
+
const changes: DnssdName.Changes = { name: this };
|
|
184
|
+
for (const { kind, record } of this.#changes.values()) {
|
|
185
|
+
const key: "updated" | "deleted" = `${kind}d`;
|
|
186
|
+
const list = changes[key];
|
|
187
|
+
if (list === undefined) {
|
|
188
|
+
changes[key] = [record];
|
|
189
|
+
} else {
|
|
190
|
+
list.push(record);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
this.#changes.clear();
|
|
194
|
+
await this.emit(changes);
|
|
195
|
+
}
|
|
196
|
+
this.#notified = undefined;
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
this.#notified = notify();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function keyOf(record: DnsRecord): string | undefined {
|
|
204
|
+
switch (record.recordType) {
|
|
205
|
+
case DnsRecordType.A:
|
|
206
|
+
case DnsRecordType.AAAA:
|
|
207
|
+
case DnsRecordType.PTR:
|
|
208
|
+
if (typeof record.value === "string") {
|
|
209
|
+
return `${record.recordType} ${record.value}`;
|
|
210
|
+
}
|
|
211
|
+
break;
|
|
212
|
+
|
|
213
|
+
case DnsRecordType.SRV:
|
|
214
|
+
if (typeof record.value === "object") {
|
|
215
|
+
const srv = record.value as SrvRecordValue;
|
|
216
|
+
return `${record.recordType} ${srv.target}:${srv.port}`;
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export namespace DnssdName {
|
|
223
|
+
export interface Context {
|
|
224
|
+
delete(name: DnssdName): void;
|
|
225
|
+
registerForExpiration(record: Record): void;
|
|
226
|
+
unregisterForExpiration(record: Record): void;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export interface Expiration {
|
|
230
|
+
expiresAt: Timestamp;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface PointerRecord extends DnsRecord<string>, Expiration {
|
|
234
|
+
recordType: DnsRecordType.PTR;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface HostRecord extends DnsRecord<string>, Expiration {
|
|
238
|
+
recordType: DnsRecordType.A | DnsRecordType.AAAA;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export interface ServiceRecord extends DnsRecord<SrvRecordValue>, Expiration {
|
|
242
|
+
recordType: DnsRecordType.SRV;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export type Record = PointerRecord | ServiceRecord | HostRecord;
|
|
246
|
+
|
|
247
|
+
export interface Changes {
|
|
248
|
+
name: DnssdName;
|
|
249
|
+
updated?: Record[];
|
|
250
|
+
deleted?: Record[];
|
|
251
|
+
}
|
|
252
|
+
}
|