appium-ios-remotexpc 2.0.2 → 2.1.0

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/src/lib/discovery/discovery-backend-factory.d.ts +3 -8
  3. package/build/src/lib/discovery/discovery-backend-factory.d.ts.map +1 -1
  4. package/build/src/lib/discovery/discovery-backend-factory.js +6 -14
  5. package/build/src/lib/discovery/discovery-backend-factory.js.map +1 -1
  6. package/build/src/lib/discovery/index.d.ts +1 -2
  7. package/build/src/lib/discovery/index.d.ts.map +1 -1
  8. package/build/src/lib/discovery/index.js +1 -2
  9. package/build/src/lib/discovery/index.js.map +1 -1
  10. package/build/src/lib/discovery/mdns-browser.d.ts +15 -0
  11. package/build/src/lib/discovery/mdns-browser.d.ts.map +1 -0
  12. package/build/src/lib/discovery/mdns-browser.js +228 -0
  13. package/build/src/lib/discovery/mdns-browser.js.map +1 -0
  14. package/build/src/lib/discovery/mdns-discovery-backend.d.ts +15 -0
  15. package/build/src/lib/discovery/mdns-discovery-backend.d.ts.map +1 -0
  16. package/build/src/lib/discovery/mdns-discovery-backend.js +102 -0
  17. package/build/src/lib/discovery/mdns-discovery-backend.js.map +1 -0
  18. package/build/src/lib/discovery/mdns-protocol.d.ts +48 -0
  19. package/build/src/lib/discovery/mdns-protocol.d.ts.map +1 -0
  20. package/build/src/lib/discovery/mdns-protocol.js +238 -0
  21. package/build/src/lib/discovery/mdns-protocol.js.map +1 -0
  22. package/build/src/services/ios/afc/index.d.ts.map +1 -1
  23. package/build/src/services/ios/afc/index.js +20 -14
  24. package/build/src/services/ios/afc/index.js.map +1 -1
  25. package/build/src/services/ios/afc/local-filesystem-case.d.ts +23 -0
  26. package/build/src/services/ios/afc/local-filesystem-case.d.ts.map +1 -0
  27. package/build/src/services/ios/afc/local-filesystem-case.js +132 -0
  28. package/build/src/services/ios/afc/local-filesystem-case.js.map +1 -0
  29. package/build/src/services/ios/afc/pull-local-name-allocator.d.ts +21 -0
  30. package/build/src/services/ios/afc/pull-local-name-allocator.d.ts.map +1 -0
  31. package/build/src/services/ios/afc/pull-local-name-allocator.js +82 -0
  32. package/build/src/services/ios/afc/pull-local-name-allocator.js.map +1 -0
  33. package/build/src/services/ios/afc/sanitize-local-filename.d.ts +15 -0
  34. package/build/src/services/ios/afc/sanitize-local-filename.d.ts.map +1 -0
  35. package/build/src/services/ios/afc/sanitize-local-filename.js +130 -0
  36. package/build/src/services/ios/afc/sanitize-local-filename.js.map +1 -0
  37. package/package.json +3 -4
  38. package/src/lib/discovery/discovery-backend-factory.ts +6 -14
  39. package/src/lib/discovery/index.ts +1 -2
  40. package/src/lib/discovery/mdns-browser.ts +292 -0
  41. package/src/lib/discovery/mdns-discovery-backend.ts +143 -0
  42. package/src/lib/discovery/mdns-protocol.ts +319 -0
  43. package/src/services/ios/afc/index.ts +36 -15
  44. package/src/services/ios/afc/local-filesystem-case.ts +173 -0
  45. package/src/services/ios/afc/pull-local-name-allocator.ts +107 -0
  46. package/src/services/ios/afc/sanitize-local-filename.ts +163 -0
  47. package/build/src/lib/discovery/bonjour-discovery-backend.d.ts +0 -21
  48. package/build/src/lib/discovery/bonjour-discovery-backend.d.ts.map +0 -1
  49. package/build/src/lib/discovery/bonjour-discovery-backend.js +0 -221
  50. package/build/src/lib/discovery/bonjour-discovery-backend.js.map +0 -1
  51. package/build/src/lib/discovery/bonjour-output-parsers.d.ts +0 -37
  52. package/build/src/lib/discovery/bonjour-output-parsers.d.ts.map +0 -1
  53. package/build/src/lib/discovery/bonjour-output-parsers.js +0 -77
  54. package/build/src/lib/discovery/bonjour-output-parsers.js.map +0 -1
  55. package/build/src/lib/discovery/dnssd-discovery-backend.d.ts +0 -14
  56. package/build/src/lib/discovery/dnssd-discovery-backend.d.ts.map +0 -1
  57. package/build/src/lib/discovery/dnssd-discovery-backend.js +0 -98
  58. package/build/src/lib/discovery/dnssd-discovery-backend.js.map +0 -1
  59. package/src/lib/discovery/bonjour-discovery-backend.ts +0 -316
  60. package/src/lib/discovery/bonjour-output-parsers.ts +0 -101
  61. package/src/lib/discovery/dnssd-discovery-backend.ts +0 -118
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [2.1.0](https://github.com/appium/appium-ios-remotexpc/compare/v2.0.3...v2.1.0) (2026-05-22)
2
+
3
+ ### Features
4
+
5
+ * Unify dnssd discovery ([#221](https://github.com/appium/appium-ios-remotexpc/issues/221)) ([68470b9](https://github.com/appium/appium-ios-remotexpc/commit/68470b9283b58faf687ddfd4d4c08d523f88781a))
6
+
7
+ ## [2.0.3](https://github.com/appium/appium-ios-remotexpc/compare/v2.0.2...v2.0.3) (2026-05-22)
8
+
9
+ ### Bug Fixes
10
+
11
+ * Respect local file system limitations while pulling remote files ([#220](https://github.com/appium/appium-ios-remotexpc/issues/220)) ([4aa9491](https://github.com/appium/appium-ios-remotexpc/commit/4aa949169c6763d99aee8fa6b7c6cd4b74f39a82))
12
+
1
13
  ## [2.0.2](https://github.com/appium/appium-ios-remotexpc/compare/v2.0.1...v2.0.2) (2026-05-21)
2
14
 
3
15
  ### Bug Fixes
@@ -2,14 +2,9 @@ import type { DiscoveryOptions, IDeviceDiscoveryBackend } from './types.js';
2
2
  /**
3
3
  * Create the default device discovery backend for the current platform.
4
4
  *
5
- * On macOS we prefer the system `dns-sd` CLI (Bonjour) because Apple's
6
- * mDNSResponder advertises non-RFC-6335-compliant service names (e.g.
7
- * `_remotepairing-manual-pairing._tcp`) that pure-JS mDNS libraries reject.
8
- *
9
- * Other platforms fall back to the cross-platform `dnssd` library. Note that
10
- * `dnssd` enforces RFC 6335 (max 15-char service names), so on Linux/Windows
11
- * it will not see Apple-style long service names; in those environments
12
- * callers should advertise/discover via a shorter, compliant service type.
5
+ * Uses a raw mDNS browser on UDP port 5353 so Apple's non-RFC-6335 service
6
+ * names (e.g. `_remotepairing-manual-pairing._tcp`) work on macOS, Linux,
7
+ * and Windows without the macOS `dns-sd` CLI or the `dnssd` npm package.
13
8
  */
14
9
  export declare function createDiscoveryBackend(platform?: NodeJS.Platform, options?: DiscoveryOptions): IDeviceDiscoveryBackend;
15
10
  //# sourceMappingURL=discovery-backend-factory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery-backend-factory.d.ts","sourceRoot":"","sources":["../../../../src/lib/discovery/discovery-backend-factory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE5E;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,OAAO,CAAC,EAAE,gBAAgB,GACzB,uBAAuB,CAKzB"}
1
+ {"version":3,"file":"discovery-backend-factory.d.ts","sourceRoot":"","sources":["../../../../src/lib/discovery/discovery-backend-factory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE5E;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,OAAO,CAAC,EAAE,gBAAgB,GACzB,uBAAuB,CAGzB"}
@@ -1,21 +1,13 @@
1
- import { BonjourDiscoveryBackend } from './bonjour-discovery-backend.js';
2
- import { DnssdDiscoveryBackend } from './dnssd-discovery-backend.js';
1
+ import { MdnsDiscoveryBackend } from './mdns-discovery-backend.js';
3
2
  /**
4
3
  * Create the default device discovery backend for the current platform.
5
4
  *
6
- * On macOS we prefer the system `dns-sd` CLI (Bonjour) because Apple's
7
- * mDNSResponder advertises non-RFC-6335-compliant service names (e.g.
8
- * `_remotepairing-manual-pairing._tcp`) that pure-JS mDNS libraries reject.
9
- *
10
- * Other platforms fall back to the cross-platform `dnssd` library. Note that
11
- * `dnssd` enforces RFC 6335 (max 15-char service names), so on Linux/Windows
12
- * it will not see Apple-style long service names; in those environments
13
- * callers should advertise/discover via a shorter, compliant service type.
5
+ * Uses a raw mDNS browser on UDP port 5353 so Apple's non-RFC-6335 service
6
+ * names (e.g. `_remotepairing-manual-pairing._tcp`) work on macOS, Linux,
7
+ * and Windows without the macOS `dns-sd` CLI or the `dnssd` npm package.
14
8
  */
15
9
  export function createDiscoveryBackend(platform = process.platform, options) {
16
- if (platform === 'darwin') {
17
- return new BonjourDiscoveryBackend(options);
18
- }
19
- return new DnssdDiscoveryBackend(options);
10
+ void platform;
11
+ return new MdnsDiscoveryBackend(options);
20
12
  }
21
13
  //# sourceMappingURL=discovery-backend-factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery-backend-factory.js","sourceRoot":"","sources":["../../../../src/lib/discovery/discovery-backend-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAGrE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAA4B,OAAO,CAAC,QAAQ,EAC5C,OAA0B;IAE1B,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,IAAI,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"discovery-backend-factory.js","sourceRoot":"","sources":["../../../../src/lib/discovery/discovery-backend-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAA4B,OAAO,CAAC,QAAQ,EAC5C,OAA0B;IAE1B,KAAK,QAAQ,CAAC;IACd,OAAO,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC3C,CAAC"}
@@ -1,6 +1,5 @@
1
1
  export { createDiscoveryBackend } from './discovery-backend-factory.js';
2
- export { BonjourDiscoveryBackend } from './bonjour-discovery-backend.js';
3
- export { DnssdDiscoveryBackend } from './dnssd-discovery-backend.js';
2
+ export { MdnsDiscoveryBackend } from './mdns-discovery-backend.js';
4
3
  export { listDevicectlDeviceRecords } from './devicectl-device-records.js';
5
4
  export type { DiscoveredDevice, DiscoveredDeviceMetadata, DiscoveryOptions, IDeviceDiscoveryBackend, } from './types.js';
6
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,YAAY,EACV,gBAAgB,EAChB,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,YAAY,EACV,gBAAgB,EAChB,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,YAAY,CAAC"}
@@ -1,5 +1,4 @@
1
1
  export { createDiscoveryBackend } from './discovery-backend-factory.js';
2
- export { BonjourDiscoveryBackend } from './bonjour-discovery-backend.js';
3
- export { DnssdDiscoveryBackend } from './dnssd-discovery-backend.js';
2
+ export { MdnsDiscoveryBackend } from './mdns-discovery-backend.js';
4
3
  export { listDevicectlDeviceRecords } from './devicectl-device-records.js';
5
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,15 @@
1
+ export interface MdnsServiceInstance {
2
+ instance: string;
3
+ host?: string;
4
+ port?: number;
5
+ addresses: string[];
6
+ properties: Record<string, string>;
7
+ }
8
+ /**
9
+ * Browse a DNS-SD service type on the local link (e.g. `_remotepairing._tcp`).
10
+ *
11
+ * Opens raw UDP sockets on port 5353, sends a PTR query, and parses replies
12
+ * without enforcing RFC 6335 service-name length limits.
13
+ */
14
+ export declare function browseMdnsService(serviceType: string, domain: string, timeoutMs: number): Promise<MdnsServiceInstance[]>;
15
+ //# sourceMappingURL=mdns-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdns-browser.d.ts","sourceRoot":"","sources":["../../../../src/lib/discovery/mdns-browser.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAaD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAsFhC"}
@@ -0,0 +1,228 @@
1
+ import { createSocket } from 'node:dgram';
2
+ import { networkInterfaces } from 'node:os';
3
+ import { setTimeout } from 'node:timers';
4
+ import { getLogger } from '../logger.js';
5
+ import { MDNS_MCAST_V4, MDNS_MCAST_V6, MDNS_PORT, QTYPE_A, QTYPE_AAAA, QTYPE_PTR, QTYPE_SRV, QTYPE_TXT, buildQuery, buildServiceTypeFqdn, parseMdnsMessage, } from './mdns-protocol.js';
6
+ const log = getLogger('MdnsBrowser');
7
+ /**
8
+ * Browse a DNS-SD service type on the local link (e.g. `_remotepairing._tcp`).
9
+ *
10
+ * Opens raw UDP sockets on port 5353, sends a PTR query, and parses replies
11
+ * without enforcing RFC 6335 service-name length limits.
12
+ */
13
+ export async function browseMdnsService(serviceType, domain, timeoutMs) {
14
+ const serviceTypeFqdn = buildServiceTypeFqdn(serviceType, domain);
15
+ const sockets = await openMdnsSockets();
16
+ const ptrTargets = new Set();
17
+ const srvMap = new Map();
18
+ const txtMap = new Map();
19
+ const hostAddresses = new Map();
20
+ const recordAddress = (hostName, ip) => {
21
+ const key = hostName.endsWith('.') ? hostName : `${hostName}.`;
22
+ const existing = hostAddresses.get(key) ?? [];
23
+ if (!existing.includes(ip)) {
24
+ existing.push(ip);
25
+ hostAddresses.set(key, existing);
26
+ }
27
+ };
28
+ try {
29
+ const query = buildQuery(serviceTypeFqdn, QTYPE_PTR, false);
30
+ sendQueryAll(sockets, query);
31
+ await collectResponses(sockets, timeoutMs, (data) => {
32
+ let records;
33
+ try {
34
+ records = parseMdnsMessage(data);
35
+ }
36
+ catch (err) {
37
+ log.info(`Ignoring malformed mDNS packet (${data.length} octets)`, err);
38
+ return;
39
+ }
40
+ for (const rr of records) {
41
+ if (rr.type === QTYPE_PTR &&
42
+ rr.name === serviceTypeFqdn &&
43
+ rr.ptrdname) {
44
+ ptrTargets.add(rr.ptrdname);
45
+ }
46
+ else if (rr.type === QTYPE_SRV && rr.name) {
47
+ addSrvEntry(srvMap, rr.name, {
48
+ target: rr.target,
49
+ port: rr.port,
50
+ });
51
+ }
52
+ else if (rr.type === QTYPE_TXT && rr.name) {
53
+ txtMap.set(rr.name, rr.txt ?? {});
54
+ }
55
+ else if ((rr.type === QTYPE_A || rr.type === QTYPE_AAAA) &&
56
+ rr.address &&
57
+ rr.name) {
58
+ recordAddress(rr.name, rr.address);
59
+ }
60
+ }
61
+ });
62
+ }
63
+ finally {
64
+ for (const handle of sockets) {
65
+ handle.close();
66
+ }
67
+ }
68
+ const results = [];
69
+ for (const instance of [...ptrTargets].sort()) {
70
+ const srvEntries = srvMap.get(instance) ?? [];
71
+ const properties = txtMap.get(instance) ?? {};
72
+ if (srvEntries.length === 0) {
73
+ results.push({
74
+ instance,
75
+ properties,
76
+ addresses: [],
77
+ });
78
+ continue;
79
+ }
80
+ for (const srv of dedupeSrvEntries(srvEntries)) {
81
+ const target = srv.target;
82
+ const host = target && target.endsWith('.') ? target.slice(0, -1) : target;
83
+ const addresses = target ? (hostAddresses.get(target) ?? []) : [];
84
+ results.push({
85
+ instance,
86
+ host,
87
+ port: srv.port,
88
+ addresses,
89
+ properties,
90
+ });
91
+ }
92
+ }
93
+ return results;
94
+ }
95
+ async function openMdnsSockets() {
96
+ const handles = [];
97
+ const errors = [];
98
+ try {
99
+ handles.push(await bindIpv4Socket());
100
+ }
101
+ catch (err) {
102
+ errors.push(err instanceof Error ? err : new Error(String(err)));
103
+ }
104
+ try {
105
+ handles.push(...(await bindIpv6Sockets()));
106
+ }
107
+ catch (err) {
108
+ errors.push(err instanceof Error ? err : new Error(String(err)));
109
+ }
110
+ if (handles.length === 0) {
111
+ const detail = errors.map((e) => e.message).join('; ');
112
+ throw new Error(`Failed to open mDNS sockets on UDP port ${MDNS_PORT}: ${detail}`);
113
+ }
114
+ return handles;
115
+ }
116
+ function bindIpv4Socket() {
117
+ return new Promise((resolve, reject) => {
118
+ const socket = createSocket({ type: 'udp4', reuseAddr: true });
119
+ socket.once('error', reject);
120
+ socket.bind(MDNS_PORT, '0.0.0.0', () => {
121
+ socket.removeListener('error', reject);
122
+ try {
123
+ socket.addMembership(MDNS_MCAST_V4, '0.0.0.0');
124
+ }
125
+ catch (err) {
126
+ log.debug(`IPv4 multicast membership skipped: ${err}`);
127
+ }
128
+ resolve({
129
+ socket,
130
+ family: 'ipv4',
131
+ close: () => socket.close(),
132
+ });
133
+ });
134
+ });
135
+ }
136
+ async function bindIpv6Sockets() {
137
+ const socket = createSocket({ type: 'udp6', reuseAddr: true });
138
+ try {
139
+ await new Promise((resolve, reject) => {
140
+ socket.once('error', reject);
141
+ socket.bind(MDNS_PORT, '::', () => {
142
+ socket.removeListener('error', reject);
143
+ resolve();
144
+ });
145
+ });
146
+ }
147
+ catch {
148
+ socket.close();
149
+ return [];
150
+ }
151
+ for (const entries of Object.values(networkInterfaces())) {
152
+ for (const entry of entries ?? []) {
153
+ if (!isIpv6Interface(entry)) {
154
+ continue;
155
+ }
156
+ try {
157
+ socket.addMembership(MDNS_MCAST_V6, entry.address);
158
+ }
159
+ catch {
160
+ // interface may not support multicast
161
+ }
162
+ }
163
+ }
164
+ try {
165
+ socket.addMembership(MDNS_MCAST_V6);
166
+ }
167
+ catch {
168
+ // optional default membership
169
+ }
170
+ return [
171
+ {
172
+ socket,
173
+ family: 'ipv6',
174
+ close: () => socket.close(),
175
+ },
176
+ ];
177
+ }
178
+ function isIpv6Interface(entry) {
179
+ return entry.family === 'IPv6' || entry.family === 6;
180
+ }
181
+ function srvEntryKey(entry) {
182
+ return `${entry.target ?? ''}:${entry.port ?? 0}`;
183
+ }
184
+ function addSrvEntry(srvMap, instance, entry) {
185
+ const entries = srvMap.get(instance) ?? [];
186
+ const key = srvEntryKey(entry);
187
+ if (entries.some((existing) => srvEntryKey(existing) === key)) {
188
+ return;
189
+ }
190
+ entries.push(entry);
191
+ srvMap.set(instance, entries);
192
+ }
193
+ function dedupeSrvEntries(entries) {
194
+ const seen = new Set();
195
+ const unique = [];
196
+ for (const entry of entries) {
197
+ const key = srvEntryKey(entry);
198
+ if (seen.has(key)) {
199
+ continue;
200
+ }
201
+ seen.add(key);
202
+ unique.push(entry);
203
+ }
204
+ return unique;
205
+ }
206
+ function sendQueryAll(handles, packet) {
207
+ for (const { socket, family } of handles) {
208
+ if (family !== 'ipv4') {
209
+ continue;
210
+ }
211
+ socket.send(packet, MDNS_PORT, MDNS_MCAST_V4);
212
+ }
213
+ }
214
+ function collectResponses(handles, timeoutMs, onMessage) {
215
+ return new Promise((resolve) => {
216
+ const onData = (chunk) => onMessage(chunk);
217
+ for (const { socket } of handles) {
218
+ socket.on('message', onData);
219
+ }
220
+ setTimeout(() => {
221
+ for (const { socket } of handles) {
222
+ socket.off('message', onData);
223
+ }
224
+ resolve();
225
+ }, timeoutMs);
226
+ });
227
+ }
228
+ //# sourceMappingURL=mdns-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdns-browser.js","sourceRoot":"","sources":["../../../../src/lib/discovery/mdns-browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { BaseDiscoveryBackend } from './base-discovery-backend.js';
2
+ import type { DiscoveredDevice, DiscoveryOptions } from './types.js';
3
+ /**
4
+ * Cross-platform discovery via a raw mDNS browser (UDP port 5353).
5
+ *
6
+ * Unlike the `dnssd` npm package or strict pure-JS mDNS clients, this path
7
+ * does not enforce RFC 6335 service-name length limits, so Apple's long
8
+ * DNS-SD types (e.g. `_remotepairing-manual-pairing._tcp`) work on all
9
+ * platforms.
10
+ */
11
+ export declare class MdnsDiscoveryBackend extends BaseDiscoveryBackend {
12
+ constructor(options?: DiscoveryOptions);
13
+ protected runDiscovery(timeoutMs: number): Promise<DiscoveredDevice[]>;
14
+ }
15
+ //# sourceMappingURL=mdns-discovery-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdns-discovery-backend.d.ts","sourceRoot":"","sources":["../../../../src/lib/discovery/mdns-discovery-backend.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AASnE,OAAO,KAAK,EACV,gBAAgB,EAEhB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAIpB;;;;;;;GAOG;AACH,qBAAa,oBAAqB,SAAQ,oBAAoB;gBAChD,OAAO,CAAC,EAAE,gBAAgB;cAIb,YAAY,CACnC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAiC/B"}
@@ -0,0 +1,102 @@
1
+ import { getLogger } from '../logger.js';
2
+ import { BaseDiscoveryBackend } from './base-discovery-backend.js';
3
+ import { DISCOVERY_DEFAULT_TIMEOUT_MS } from './constants.js';
4
+ import { normalizeHostname, resolveIpAddress } from './discovery-utils.js';
5
+ import { browseMdnsService } from './mdns-browser.js';
6
+ import { MDNS_PORT, buildServiceTypeFqdn, decodeDnsSdInstanceName, } from './mdns-protocol.js';
7
+ const log = getLogger('MdnsDiscoveryBackend');
8
+ /**
9
+ * Cross-platform discovery via a raw mDNS browser (UDP port 5353).
10
+ *
11
+ * Unlike the `dnssd` npm package or strict pure-JS mDNS clients, this path
12
+ * does not enforce RFC 6335 service-name length limits, so Apple's long
13
+ * DNS-SD types (e.g. `_remotepairing-manual-pairing._tcp`) work on all
14
+ * platforms.
15
+ */
16
+ export class MdnsDiscoveryBackend extends BaseDiscoveryBackend {
17
+ constructor(options) {
18
+ super(options);
19
+ }
20
+ async runDiscovery(timeoutMs) {
21
+ const browseTimeout = Math.max(timeoutMs, DISCOVERY_DEFAULT_TIMEOUT_MS);
22
+ let instances;
23
+ try {
24
+ instances = await browseMdnsService(this.serviceType, this.domain, browseTimeout);
25
+ }
26
+ catch (err) {
27
+ const message = formatMdnsBrowseError(err);
28
+ log.warn(message);
29
+ throw new Error(message, { cause: err });
30
+ }
31
+ if (instances.length === 0) {
32
+ return [];
33
+ }
34
+ const settled = await Promise.allSettled(instances.map((instance) => instanceToDevice(instance, this.serviceType, this.domain)));
35
+ const devices = settled
36
+ .filter((item) => item.status === 'fulfilled')
37
+ .map((item) => item.value)
38
+ .filter((device) => device !== null);
39
+ return dedupeDiscoveredDevices(devices);
40
+ }
41
+ }
42
+ function dedupeDiscoveredDevices(devices) {
43
+ const seen = new Map();
44
+ for (const device of devices) {
45
+ const key = `${device.id}:${device.hostname ?? ''}:${device.port ?? 0}`;
46
+ if (!seen.has(key)) {
47
+ seen.set(key, device);
48
+ }
49
+ }
50
+ return [...seen.values()];
51
+ }
52
+ async function instanceToDevice(instance, serviceType, domain) {
53
+ try {
54
+ const name = extractInstanceName(instance.instance, serviceType, domain);
55
+ const hostname = normalizeHostname(instance.host);
56
+ if (!hostname || !instance.port) {
57
+ return null;
58
+ }
59
+ const ipv4 = instance.addresses.find((addr) => !addr.includes(':'));
60
+ const ip = await resolveIpAddress(hostname, ipv4 ? [ipv4] : instance.addresses);
61
+ const txt = instance.properties;
62
+ const identifier = txt.identifier ?? name;
63
+ const metadata = {
64
+ identifier,
65
+ model: txt.model ?? '',
66
+ version: txt.ver ?? '',
67
+ };
68
+ return {
69
+ id: identifier,
70
+ name,
71
+ hostname,
72
+ ip,
73
+ port: instance.port,
74
+ metadata,
75
+ };
76
+ }
77
+ catch (err) {
78
+ log.warn(`Failed to process mDNS service ${instance.instance}: ${err}`);
79
+ return null;
80
+ }
81
+ }
82
+ function extractInstanceName(instanceFqdn, serviceType, domain) {
83
+ const suffix = buildServiceTypeFqdn(serviceType, domain);
84
+ const normalized = instanceFqdn.endsWith('.')
85
+ ? instanceFqdn
86
+ : `${instanceFqdn}.`;
87
+ if (normalized.endsWith(suffix)) {
88
+ const raw = normalized.slice(0, -suffix.length).replace(/\.$/, '');
89
+ return decodeDnsSdInstanceName(raw);
90
+ }
91
+ const firstLabel = normalized.slice(0, -1).split('.')[0] ?? normalized;
92
+ return decodeDnsSdInstanceName(firstLabel);
93
+ }
94
+ function formatMdnsBrowseError(err) {
95
+ const detail = err instanceof Error ? err.message : String(err);
96
+ const base = `mDNS browse failed: ${detail}`;
97
+ if (typeof process.getuid === 'function' && process.getuid() !== 0) {
98
+ return `${base}. Binding to UDP port ${MDNS_PORT} may require elevated privileges; try running with sudo.`;
99
+ }
100
+ return base;
101
+ }
102
+ //# sourceMappingURL=mdns-discovery-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdns-discovery-backend.js","sourceRoot":"","sources":["../../../../src/lib/discovery/mdns-discovery-backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Minimal DNS/mDNS packet helpers for raw service browsing.
3
+ *
4
+ * No third-party mDNS library and no RFC 6335 service-name length checks, so
5
+ * Apple's long DNS-SD types work.
6
+ */
7
+ export declare const MDNS_PORT = 5353;
8
+ export declare const MDNS_MCAST_V4 = "224.0.0.251";
9
+ export declare const MDNS_MCAST_V6 = "ff02::fb";
10
+ export declare const QTYPE_A = 1;
11
+ export declare const QTYPE_PTR = 12;
12
+ export declare const QTYPE_TXT = 16;
13
+ export declare const QTYPE_AAAA = 28;
14
+ export declare const QTYPE_SRV = 33;
15
+ export interface ParsedResourceRecord {
16
+ name: string;
17
+ type: number;
18
+ class: number;
19
+ ttl: number;
20
+ ptrdname?: string;
21
+ priority?: number;
22
+ weight?: number;
23
+ port?: number;
24
+ target?: string;
25
+ txt?: Record<string, string>;
26
+ address?: string;
27
+ raw?: Buffer;
28
+ }
29
+ /** Encode a dotted DNS name as a length-prefixed wire-format name. */
30
+ export declare function encodeName(name: string): Buffer;
31
+ /** Decode a wire-format DNS name starting at `offset`. */
32
+ export declare function decodeName(data: Buffer, offset: number): {
33
+ name: string;
34
+ offset: number;
35
+ };
36
+ /** Build a DNS query packet with a single question. */
37
+ export declare function buildQuery(name: string, qtype: number, unicast?: boolean): Buffer;
38
+ /** Parse answer/authority/additional records from an mDNS response packet. */
39
+ export declare function parseMdnsMessage(data: Buffer): ParsedResourceRecord[];
40
+ /**
41
+ * Decode DNS-SD decimal escape sequences in instance names (e.g. `\032` → space).
42
+ *
43
+ * Per RFC 6763, `\DDD` uses three decimal digits for the byte value, not octal.
44
+ */
45
+ export declare function decodeDnsSdInstanceName(name: string): string;
46
+ /** Build a trailing-dot FQDN from a DNS-SD type and domain (e.g. `local`). */
47
+ export declare function buildServiceTypeFqdn(serviceType: string, domain: string): string;
48
+ //# sourceMappingURL=mdns-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdns-protocol.d.ts","sourceRoot":"","sources":["../../../../src/lib/discovery/mdns-protocol.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,SAAS,OAAO,CAAC;AAC9B,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAC3C,eAAO,MAAM,aAAa,aAAa,CAAC;AAExC,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,SAAS,KAAK,CAAC;AA+B5B,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmB/C;AAED,0DAA0D;AAC1D,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAwElC;AAED,uDAAuD;AACvD,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,UAAQ,GACd,MAAM,CAaR;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAuBrE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,MAAM,CAMR"}