@matter-server/ws-controller 0.6.3-alpha.0-20260429-7b8104b → 0.6.4

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.
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025-2026 Open Home Foundation
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { BorderRouterEntry } from "@matter-server/ws-client";
7
+ import { Bytes, type DnsRecord, DnsRecordType, Environment } from "@matter/main";
8
+ interface DnssdRecordLike {
9
+ recordType: DnsRecordType;
10
+ name: string;
11
+ value: unknown;
12
+ }
13
+ interface DnssdParametersLike extends ReadonlyMap<string, string> {
14
+ raw(key: string): Bytes | undefined;
15
+ }
16
+ interface DnssdNameLike {
17
+ readonly qname: string;
18
+ readonly parameters: DnssdParametersLike;
19
+ readonly records: Iterable<DnssdRecordLike>;
20
+ readonly isDiscovered: boolean;
21
+ on(observer: NameObserver): void;
22
+ off(observer: NameObserver): void;
23
+ }
24
+ interface DnssdNamesFiltersLike {
25
+ add(filter: (record: DnsRecord) => boolean): unknown;
26
+ delete(filter: (record: DnsRecord) => boolean): unknown;
27
+ }
28
+ interface DiscoveredObservableLike {
29
+ on(observer: DiscoveredObserver): void;
30
+ off(observer: DiscoveredObserver): void;
31
+ }
32
+ interface SolicitorLike {
33
+ solicit(solicitation: {
34
+ name: DnssdNameLike;
35
+ recordTypes: DnsRecordType[];
36
+ }): void;
37
+ }
38
+ interface DnssdNamesLike {
39
+ readonly filters: DnssdNamesFiltersLike;
40
+ readonly discovered: DiscoveredObservableLike;
41
+ readonly solicitor: SolicitorLike;
42
+ get(qname: string): DnssdNameLike;
43
+ maybeGet(qname: string): DnssdNameLike | undefined;
44
+ }
45
+ type DiscoveredObserver = (name: DnssdNameLike) => void;
46
+ type NameObserver = (changes: {
47
+ name: DnssdNameLike;
48
+ updated?: unknown[];
49
+ deleted?: unknown[];
50
+ }) => void;
51
+ /**
52
+ * Passive Thread Border Router discovery via mDNS.
53
+ *
54
+ * Subscribes to `_meshcop._udp.local` and `_trel._udp.local`, builds a per-extended-address
55
+ * registry, and exposes the current entries through {@link list}. Owned by {@link MatterController}.
56
+ */
57
+ export declare class BorderRouterDiscovery {
58
+ #private;
59
+ constructor(env: Environment, names?: DnssdNamesLike);
60
+ start(): Promise<void>;
61
+ stop(): Promise<void>;
62
+ list(): BorderRouterEntry[];
63
+ get(extAddressHex: string): BorderRouterEntry | undefined;
64
+ }
65
+ export {};
66
+ //# sourceMappingURL=BorderRouterDiscovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BorderRouterDiscovery.d.ts","sourceRoot":"","sources":["../../../src/controller/BorderRouterDiscovery.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,KAAK,SAAS,EAAE,aAAa,EAAE,WAAW,EAA+B,MAAM,cAAc,CAAC;AAuB9G,UAAU,eAAe;IACrB,UAAU,EAAE,aAAa,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,mBAAoB,SAAQ,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC;IAC7D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;CACvC;AAED,UAAU,aAAa;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,EAAE,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IACjC,GAAG,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;CACrC;AAED,UAAU,qBAAqB;IAC3B,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,GAAG,OAAO,CAAC;IACrD,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,GAAG,OAAO,CAAC;CAC3D;AAED,UAAU,wBAAwB;IAC9B,EAAE,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACvC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAC3C;AAED,UAAU,aAAa;IACnB,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,WAAW,EAAE,aAAa,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;CACtF;AAED,UAAU,cAAc;IACpB,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;CACtD;AAED,KAAK,kBAAkB,GAAG,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;AACxD,KAAK,YAAY,GAAG,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,KAAK,IAAI,CAAC;AAmBzG;;;;;GAKG;AACH,qBAAa,qBAAqB;;IAe9B,YAAY,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,cAAc,EAGnD;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAsC3B;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA8B1B;IAED,IAAI,IAAI,iBAAiB,EAAE,CAG1B;IAED,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAIxD;CAkYJ"}
@@ -0,0 +1,446 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025-2026 Open Home Foundation
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Bytes, DnsRecordType, Logger } from "@matter/main";
7
+ import { MdnsService } from "@matter/main/protocol";
8
+ const logger = Logger.get("BorderRouterDiscovery");
9
+ const REGISTRY_MAX_ENTRIES = 256;
10
+ const INSTANCE_OBSERVER_CAP = 512;
11
+ const STALE_RETENTION_MS = 24 * 60 * 60 * 1e3;
12
+ const MESHCOP_TYPE_QNAME = "_meshcop._udp.local";
13
+ const TREL_TYPE_QNAME = "_trel._udp.local";
14
+ const MESHCOP_SUFFIX = "._meshcop._udp.local";
15
+ const TREL_SUFFIX = "._trel._udp.local";
16
+ class BorderRouterDiscovery {
17
+ #env;
18
+ #registry = /* @__PURE__ */ new Map();
19
+ #instanceObservers = /* @__PURE__ */ new Map();
20
+ #targetObservers = /* @__PURE__ */ new Map();
21
+ #names;
22
+ #injectedNames;
23
+ #suffixFilter;
24
+ #discoveredObserver;
25
+ #started = false;
26
+ /** Incremented on every start/stop. Lets a pending `await mdns.construction.ready`
27
+ * detect that `stop()` ran while it was suspended and abort partial setup. */
28
+ #startGeneration = 0;
29
+ #evictionWarnedThisCycle = false;
30
+ constructor(env, names) {
31
+ this.#env = env;
32
+ this.#injectedNames = names;
33
+ }
34
+ async start() {
35
+ if (this.#started) return;
36
+ const gen = ++this.#startGeneration;
37
+ this.#evictionWarnedThisCycle = false;
38
+ let names;
39
+ if (this.#injectedNames !== void 0) {
40
+ names = this.#injectedNames;
41
+ } else {
42
+ try {
43
+ const mdns = this.#env.get(MdnsService);
44
+ await mdns.construction.ready;
45
+ if (gen !== this.#startGeneration) return;
46
+ names = mdns.names;
47
+ } catch (e) {
48
+ if (gen !== this.#startGeneration) return;
49
+ logger.warn("MDNS service unavailable; border router discovery inactive:", e);
50
+ return;
51
+ }
52
+ }
53
+ this.#started = true;
54
+ this.#names = names;
55
+ const suffixFilter = ({ name }) => {
56
+ const lower = name.toLowerCase();
57
+ return lower.endsWith(MESHCOP_SUFFIX) || lower.endsWith(TREL_SUFFIX);
58
+ };
59
+ this.#suffixFilter = suffixFilter;
60
+ names.filters.add(suffixFilter);
61
+ const meshcopType = names.get(MESHCOP_TYPE_QNAME);
62
+ const trelType = names.get(TREL_TYPE_QNAME);
63
+ names.solicitor.solicit({ name: meshcopType, recordTypes: [DnsRecordType.PTR] });
64
+ names.solicitor.solicit({ name: trelType, recordTypes: [DnsRecordType.PTR] });
65
+ const observer = (name) => this.#onDiscovered(name);
66
+ this.#discoveredObserver = observer;
67
+ names.discovered.on(observer);
68
+ }
69
+ async stop() {
70
+ this.#startGeneration++;
71
+ if (!this.#started) return;
72
+ this.#started = false;
73
+ const names = this.#names;
74
+ if (names !== void 0) {
75
+ if (this.#discoveredObserver !== void 0) {
76
+ names.discovered.off(this.#discoveredObserver);
77
+ }
78
+ if (this.#suffixFilter !== void 0) {
79
+ names.filters.delete(this.#suffixFilter);
80
+ }
81
+ }
82
+ this.#discoveredObserver = void 0;
83
+ this.#suffixFilter = void 0;
84
+ for (const tracking of this.#instanceObservers.values()) {
85
+ tracking.name.off(tracking.observer);
86
+ }
87
+ this.#instanceObservers.clear();
88
+ for (const tracking of this.#targetObservers.values()) {
89
+ tracking.target.off(tracking.observer);
90
+ }
91
+ this.#targetObservers.clear();
92
+ this.#registry.clear();
93
+ this.#names = void 0;
94
+ }
95
+ list() {
96
+ this.#pruneExpired();
97
+ return Array.from(this.#registry.values(), (entry) => this.#snapshotEntry(entry));
98
+ }
99
+ get(extAddressHex) {
100
+ this.#pruneExpired();
101
+ const entry = this.#registry.get(extAddressHex.toUpperCase());
102
+ return entry === void 0 ? void 0 : this.#snapshotEntry(entry);
103
+ }
104
+ #pruneExpired() {
105
+ const cutoff = Date.now() - STALE_RETENTION_MS;
106
+ for (const [xaKey, entry] of this.#registry) {
107
+ if (entry.sources.length === 0 && entry.lastSeen < cutoff) {
108
+ this.#registry.delete(xaKey);
109
+ }
110
+ }
111
+ }
112
+ /** Shallow copy so callers cannot mutate registry state through the returned reference. */
113
+ #snapshotEntry(entry) {
114
+ return {
115
+ ...entry,
116
+ sources: [...entry.sources],
117
+ addresses: [...entry.addresses]
118
+ };
119
+ }
120
+ #onDiscovered(name) {
121
+ if (!this.#started) return;
122
+ this.#pruneExpired();
123
+ const lower = name.qname.toLowerCase();
124
+ if (lower === MESHCOP_TYPE_QNAME || lower === TREL_TYPE_QNAME) {
125
+ return;
126
+ }
127
+ let source;
128
+ if (lower.endsWith(MESHCOP_SUFFIX)) {
129
+ source = "meshcop";
130
+ } else if (lower.endsWith(TREL_SUFFIX)) {
131
+ source = "trel";
132
+ } else {
133
+ return;
134
+ }
135
+ const key = lower;
136
+ if (this.#instanceObservers.has(key)) {
137
+ return;
138
+ }
139
+ if (this.#instanceObservers.size >= INSTANCE_OBSERVER_CAP) {
140
+ while (this.#instanceObservers.size >= INSTANCE_OBSERVER_CAP) {
141
+ if (!this.#evictOldestPendingInstance() && !this.#evictOldest()) break;
142
+ }
143
+ }
144
+ const observer = () => this.#onInstanceChanged(name, source);
145
+ this.#instanceObservers.set(key, { name, source, observer, firstSeen: Date.now() });
146
+ name.on(observer);
147
+ this.#parseAndUpsert(name, source);
148
+ }
149
+ /**
150
+ * Evict the oldest xa-less instance observer when the observer cap is hit. Instances
151
+ * that never publish a valid `xa` (malformed broadcasters or hostile noise) would
152
+ * otherwise pin observers in `#instanceObservers` indefinitely — eviction targets only
153
+ * those because observers tied to real registry entries are managed by `#evictOldest`.
154
+ */
155
+ #evictOldestPendingInstance() {
156
+ let oldestKey;
157
+ let oldestSeen = Number.POSITIVE_INFINITY;
158
+ for (const [k, t] of this.#instanceObservers) {
159
+ if (t.xaKey !== void 0) continue;
160
+ if (t.firstSeen < oldestSeen) {
161
+ oldestSeen = t.firstSeen;
162
+ oldestKey = k;
163
+ }
164
+ }
165
+ if (oldestKey === void 0) return false;
166
+ const tracking = this.#instanceObservers.get(oldestKey);
167
+ if (tracking === void 0) return false;
168
+ tracking.name.off(tracking.observer);
169
+ if (tracking.targetKey !== void 0) {
170
+ this.#releaseTarget(tracking.targetKey);
171
+ }
172
+ this.#instanceObservers.delete(oldestKey);
173
+ return true;
174
+ }
175
+ #onInstanceChanged(name, source) {
176
+ if (!this.#started) return;
177
+ if (name.isDiscovered) {
178
+ try {
179
+ this.#parseAndUpsert(name, source);
180
+ } catch (e) {
181
+ logger.debug("Error processing border router instance change:", e);
182
+ }
183
+ return;
184
+ }
185
+ const key = name.qname.toLowerCase();
186
+ const tracking = this.#instanceObservers.get(key);
187
+ if (tracking === void 0) {
188
+ return;
189
+ }
190
+ tracking.name.off(tracking.observer);
191
+ this.#instanceObservers.delete(key);
192
+ if (tracking.targetKey !== void 0) {
193
+ this.#releaseTarget(tracking.targetKey);
194
+ }
195
+ const xaKey = tracking.xaKey;
196
+ if (xaKey === void 0) {
197
+ return;
198
+ }
199
+ const entry = this.#registry.get(xaKey);
200
+ if (entry === void 0) {
201
+ return;
202
+ }
203
+ const idx = entry.sources.indexOf(source);
204
+ if (idx !== -1) {
205
+ entry.sources.splice(idx, 1);
206
+ }
207
+ }
208
+ #onTargetChanged(target) {
209
+ if (!this.#started) return;
210
+ try {
211
+ const targetQname = target.qname.toLowerCase();
212
+ for (const entry of this.#registry.values()) {
213
+ if (entry.hostname?.toLowerCase() === targetQname) {
214
+ entry.addresses = this.#sortAddresses(this.#collectAddresses(target));
215
+ }
216
+ }
217
+ } catch (e) {
218
+ logger.debug("Error processing border router target change:", e);
219
+ }
220
+ }
221
+ #parseAndUpsert(name, source) {
222
+ const names = this.#names;
223
+ if (names === void 0) return;
224
+ try {
225
+ const params = name.parameters;
226
+ const xaKey = rawHex(params.raw("xa"), 8);
227
+ if (xaKey === void 0) {
228
+ return;
229
+ }
230
+ const records = Array.from(name.records);
231
+ const srvRecord = records.find((r) => r.recordType === DnsRecordType.SRV);
232
+ let srvTarget;
233
+ let srvPort;
234
+ if (srvRecord !== void 0 && isSrvValue(srvRecord.value)) {
235
+ srvTarget = srvRecord.value.target;
236
+ srvPort = srvRecord.value.port;
237
+ }
238
+ let addresses = [];
239
+ const tracking = this.#instanceObservers.get(name.qname.toLowerCase());
240
+ if (srvTarget !== void 0) {
241
+ const target = names.get(srvTarget);
242
+ addresses = this.#sortAddresses(this.#collectAddresses(target));
243
+ this.#attachTargetObserver(name, srvTarget, target);
244
+ } else if (tracking?.targetKey !== void 0) {
245
+ this.#releaseTarget(tracking.targetKey);
246
+ tracking.targetKey = void 0;
247
+ }
248
+ const xp = rawHex(params.raw("xp"), 8);
249
+ const existing = this.#registry.get(xaKey);
250
+ const meshcopWins = source === "meshcop";
251
+ const entry = existing ?? {
252
+ extAddressHex: xaKey,
253
+ addresses: [],
254
+ sources: [],
255
+ lastSeen: Date.now()
256
+ };
257
+ const meshcopAlreadyContributed = entry.sources.includes("meshcop");
258
+ const canOverwrite = meshcopWins || !meshcopAlreadyContributed;
259
+ if (xp !== void 0 && canOverwrite) {
260
+ entry.extendedPanIdHex = xp;
261
+ }
262
+ const previousHostname = entry.hostname;
263
+ if (srvTarget !== void 0 && canOverwrite) {
264
+ entry.hostname = srvTarget;
265
+ }
266
+ if (source === "meshcop" && srvTarget !== void 0 && previousHostname !== void 0 && previousHostname.toLowerCase() !== srvTarget.toLowerCase()) {
267
+ this.#repointTrelTargetForXa(xaKey, previousHostname, srvTarget, names);
268
+ }
269
+ if (addresses.length > 0 && canOverwrite) {
270
+ entry.addresses = addresses;
271
+ }
272
+ if (source === "meshcop") {
273
+ if (srvPort !== void 0) entry.meshcopPort = srvPort;
274
+ const nn = params.get("nn");
275
+ if (nn !== void 0) entry.networkName = nn;
276
+ const vn = params.get("vn");
277
+ if (vn !== void 0) entry.vendorName = vn;
278
+ const mn = params.get("mn");
279
+ if (mn !== void 0) entry.modelName = mn;
280
+ const tv = params.get("tv");
281
+ if (tv !== void 0) entry.threadVersion = tv;
282
+ const dd = rawHex(params.raw("dd"));
283
+ if (dd !== void 0) entry.borderAgentIdHex = dd;
284
+ const sb = rawHex(params.raw("sb"), 4);
285
+ if (sb !== void 0) entry.stateBitmapHex = sb;
286
+ const at = rawHex(params.raw("at"), 8);
287
+ if (at !== void 0) entry.activeTimestampHex = at;
288
+ const pt = rawHex(params.raw("pt"), 4);
289
+ if (pt !== void 0) entry.partitionIdHex = pt;
290
+ const dn = params.get("dn");
291
+ if (dn !== void 0) entry.domainName = dn;
292
+ } else if (source === "trel") {
293
+ if (srvPort !== void 0) entry.trelPort = srvPort;
294
+ }
295
+ if (!entry.sources.includes(source)) {
296
+ if (source === "meshcop") {
297
+ entry.sources.unshift(source);
298
+ } else {
299
+ entry.sources.push(source);
300
+ }
301
+ }
302
+ entry.lastSeen = Date.now();
303
+ if (existing === void 0) {
304
+ if (this.#registry.size >= REGISTRY_MAX_ENTRIES) {
305
+ this.#evictOldest();
306
+ }
307
+ this.#registry.set(xaKey, entry);
308
+ }
309
+ if (tracking !== void 0) {
310
+ tracking.xaKey = xaKey;
311
+ }
312
+ } catch (e) {
313
+ logger.debug("Error parsing border router record:", e);
314
+ }
315
+ }
316
+ #collectAddresses(target) {
317
+ const out = new Array();
318
+ for (const record of target.records) {
319
+ if (record.recordType !== DnsRecordType.A && record.recordType !== DnsRecordType.AAAA) continue;
320
+ if (typeof record.value === "string") {
321
+ out.push(record.value);
322
+ }
323
+ }
324
+ return out;
325
+ }
326
+ #sortAddresses(addresses) {
327
+ const seen = /* @__PURE__ */ new Set();
328
+ const unique = new Array();
329
+ for (const addr of addresses) {
330
+ if (!seen.has(addr)) {
331
+ seen.add(addr);
332
+ unique.push(addr);
333
+ }
334
+ }
335
+ const ipv4 = unique.filter((a) => !a.includes(":"));
336
+ const ipv6 = unique.filter((a) => a.includes(":"));
337
+ const categorize = (a) => {
338
+ const lower = a.toLowerCase();
339
+ if (lower.startsWith("fe80:")) return 2;
340
+ if (lower.startsWith("fc") || lower.startsWith("fd")) return 1;
341
+ const firstChar = lower.charAt(0);
342
+ if (firstChar === "2" || firstChar === "3") return 0;
343
+ return 3;
344
+ };
345
+ ipv6.sort((a, b) => {
346
+ const ca = categorize(a);
347
+ const cb = categorize(b);
348
+ if (ca !== cb) return ca - cb;
349
+ return a.localeCompare(b);
350
+ });
351
+ ipv4.sort((a, b) => a.localeCompare(b));
352
+ return [...ipv4, ...ipv6];
353
+ }
354
+ #attachTargetObserver(instance, srvTarget, target) {
355
+ const targetKey = srvTarget.toLowerCase();
356
+ const instanceKey = instance.qname.toLowerCase();
357
+ const instanceTracking = this.#instanceObservers.get(instanceKey);
358
+ const previousTargetKey = instanceTracking?.targetKey;
359
+ if (previousTargetKey === targetKey) {
360
+ return;
361
+ }
362
+ if (previousTargetKey !== void 0) {
363
+ this.#releaseTarget(previousTargetKey);
364
+ }
365
+ const existing = this.#targetObservers.get(targetKey);
366
+ if (existing !== void 0) {
367
+ existing.refcount++;
368
+ } else {
369
+ const observer = () => this.#onTargetChanged(target);
370
+ target.on(observer);
371
+ this.#targetObservers.set(targetKey, { target, observer, refcount: 1 });
372
+ }
373
+ if (instanceTracking !== void 0) {
374
+ instanceTracking.targetKey = targetKey;
375
+ }
376
+ }
377
+ #repointTrelTargetForXa(xaKey, previousHostname, newTarget, names) {
378
+ const previousKey = previousHostname.toLowerCase();
379
+ for (const tracking of this.#instanceObservers.values()) {
380
+ if (tracking.xaKey !== xaKey) continue;
381
+ if (tracking.source !== "trel") continue;
382
+ if (tracking.targetKey !== previousKey) continue;
383
+ this.#attachTargetObserver(tracking.name, newTarget, names.get(newTarget));
384
+ }
385
+ }
386
+ #releaseTarget(targetKey) {
387
+ const tracking = this.#targetObservers.get(targetKey);
388
+ if (tracking === void 0) return;
389
+ tracking.refcount--;
390
+ if (tracking.refcount <= 0) {
391
+ tracking.target.off(tracking.observer);
392
+ this.#targetObservers.delete(targetKey);
393
+ }
394
+ }
395
+ #evictOldest() {
396
+ let oldestStaleKey;
397
+ let oldestStaleSeen = Number.POSITIVE_INFINITY;
398
+ let oldestLiveKey;
399
+ let oldestLiveSeen = Number.POSITIVE_INFINITY;
400
+ for (const [xa, entry] of this.#registry) {
401
+ if (entry.sources.length === 0) {
402
+ if (entry.lastSeen < oldestStaleSeen) {
403
+ oldestStaleSeen = entry.lastSeen;
404
+ oldestStaleKey = xa;
405
+ }
406
+ } else if (entry.lastSeen < oldestLiveSeen) {
407
+ oldestLiveSeen = entry.lastSeen;
408
+ oldestLiveKey = xa;
409
+ }
410
+ }
411
+ const evictKey = oldestStaleKey ?? oldestLiveKey;
412
+ if (evictKey === void 0) return false;
413
+ this.#registry.delete(evictKey);
414
+ let releasedObservers = 0;
415
+ for (const [instanceKey, tracking] of [...this.#instanceObservers]) {
416
+ if (tracking.xaKey !== evictKey) continue;
417
+ tracking.name.off(tracking.observer);
418
+ if (tracking.targetKey !== void 0) {
419
+ this.#releaseTarget(tracking.targetKey);
420
+ }
421
+ this.#instanceObservers.delete(instanceKey);
422
+ releasedObservers++;
423
+ }
424
+ if (!this.#evictionWarnedThisCycle) {
425
+ this.#evictionWarnedThisCycle = true;
426
+ logger.warn(
427
+ `Border router registry exceeded ${REGISTRY_MAX_ENTRIES} entries; evicting oldest (released ${releasedObservers} instance observer${releasedObservers === 1 ? "" : "s"})`
428
+ );
429
+ } else {
430
+ logger.debug(`Evicted border router xa=${evictKey}; released ${releasedObservers} instance observers`);
431
+ }
432
+ return true;
433
+ }
434
+ }
435
+ function isSrvValue(value) {
436
+ return typeof value === "object" && value !== null && "target" in value && typeof value.target === "string" && "port" in value && typeof value.port === "number";
437
+ }
438
+ function rawHex(bytes, expectedByteLength) {
439
+ if (bytes === void 0 || bytes.byteLength === 0) return void 0;
440
+ if (expectedByteLength !== void 0 && bytes.byteLength !== expectedByteLength) return void 0;
441
+ return Bytes.toHex(bytes).toUpperCase();
442
+ }
443
+ export {
444
+ BorderRouterDiscovery
445
+ };
446
+ //# sourceMappingURL=BorderRouterDiscovery.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/controller/BorderRouterDiscovery.ts"],
4
+ "mappings": "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",
5
+ "names": []
6
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ControllerCommandHandler.d.ts","sourceRoot":"","sources":["../../../src/controller/ControllerCommandHandler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ControllerCommandHandler.d.ts","sourceRoot":"","sources":["../../../src/controller/ControllerCommandHandler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEH,eAAe,EAIf,QAAQ,EACR,WAAW,EAKX,MAAM,EACN,UAAU,EASb,MAAM,cAAc,CAAC;AAUtB,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EAO1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAKH,cAAc,EAQjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAA4B,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAW5D,OAAO,EACH,uBAAuB,EACvB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,8BAA8B,EAC9B,+BAA+B,EAC/B,qBAAqB,EACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACH,kBAAkB,EAElB,oBAAoB,EACpB,aAAa,EACb,qBAAqB,EACrB,cAAc,EAGjB,MAAM,mCAAmC,CAAC;AAkD3C,qBAAa,wBAAwB;;IAgBjC,MAAM;QACF,OAAO;QACP,gBAAgB;QAChB,YAAY;QACZ,SAAS;QACT,gBAAgB;QAChB,+EAA+E;QAC/E,uBAAuB;QACvB,oBAAoB;QACpB,kBAAkB;QAClB,iBAAiB;QACjB,mBAAmB;MACrB;IAGF,YAAY,kBAAkB,EAAE,uBAAuB,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAchG;IAiBD;;;OAGG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGjC;IAED,IAAI,OAAO,YAEV;IAED,IAAI,UAAU,YAEb;IAEK,KAAK,kBAgBV;IA4CK,KAAK,kBAUV;IAgHD;;;;;;OAMG;IACG,eAAe,kBAiCpB;IAED,UAAU,aAET;IAED,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE/B;IAED;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,iBAExB;IAEK,aAAa,CAAC,MAAM,EAAE,MAAM,iBAiBjC;IAED;;;;OAIG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,IAAI,GAAG,cAAc,CAgCvE;IAED;;;OAGG;IACG,oBAAoB,CACtB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EAAE,EACxB,cAAc,UAAQ,GACvB,OAAO,CAAC,cAAc,CAAC,CA6CzB;IAmDD;;;OAGG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,iBAEjC;IAEK,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAqBxF;IA6BK,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAwExD;IA8EK,cAAc,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAmB/E;IAED,qBAAqB,uBAEpB;IAEK,yBAAyB,IAAI,OAAO,CAAC;QACvC,QAAQ,EAAE,QAAQ,CAAC;QACnB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,WAAW,EAAE,MAAM,CAAC;KACvB,CAAC,CAOD;IAED,sCAAsC;IAChC,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA6C9E;IAEK,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,UAAO,qBAkC1D;IAmCD;;;;;OAKG;IACG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,OAAO,CAAC,cAAc,CAAC,CAsCpE;IAEK,gBAAgB,CAAC,MAAM,EAAE,MAAM,iBAOpC;IAgBK,uBAAuB,CAAC,IAAI,EAAE,8BAA8B,GAAG,OAAO,CAAC,+BAA+B,CAAC,CAK5G;IAEK,UAAU,CAAC,MAAM,EAAE,MAAM;;;;;SAiC9B;IAED,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,wGAEpD;IAED;;;OAGG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,oBAAoB,EAAE,GAAG,IAAI,CAAC,CAuBvG;IAED;;;OAGG;IACG,cAAc,CAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,cAAc,EAC1B,QAAQ,EAAE,aAAa,EAAE,GAC1B,OAAO,CAAC,oBAAoB,EAAE,GAAG,IAAI,CAAC,CAkBxC;IAED;;;OAGG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA6C3E;IAED;;;;OAIG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA8D/F;CAuBJ"}
@@ -274,12 +274,15 @@ class ControllerCommandHandler {
274
274
  }
275
275
  basicInfoChangedInBatch = false;
276
276
  this.events.nodeStructureChanged.emit(nodeId);
277
+ for (const endpointId of this.#nodes.drainPendingEndpointAdds(nodeId)) {
278
+ this.events.nodeEndpointAdded.emit(nodeId, endpointId);
279
+ }
277
280
  });
278
281
  node.events.decommissioned.on(() => {
279
282
  this.#cleanupNodeAfterRemoval(nodeId);
280
283
  this.events.nodeDecommissioned.emit(nodeId);
281
284
  });
282
- node.events.nodeEndpointAdded.on((endpointId) => this.events.nodeEndpointAdded.emit(nodeId, endpointId));
285
+ node.events.nodeEndpointAdded.on((endpointId) => this.#nodes.queueEndpointAdded(nodeId, endpointId));
283
286
  node.events.nodeEndpointRemoved.on((endpointId) => this.events.nodeEndpointRemoved.emit(nodeId, endpointId));
284
287
  this.#nodes.set(nodeId, node);
285
288
  this.#nodes.seedState(nodeId, node.connectionState);