dns-sd-browser 1.0.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.
@@ -0,0 +1,145 @@
1
+ export class ServiceBrowser {
2
+ /**
3
+ * @param {MdnsTransport} transport
4
+ * @param {object} options
5
+ * @param {string} options.queryName - e.g. "_http._tcp.local"
6
+ * @param {string} options.serviceType - e.g. "_http._tcp"
7
+ * @param {string} options.domain - e.g. "local"
8
+ * @param {string} options.protocol - e.g. "tcp"
9
+ * @param {boolean} [options.isTypeEnumeration] - true for browseAll
10
+ * @param {AbortSignal} [options.signal]
11
+ * @param {() => void} [options.onDestroy] - Called when the browser is destroyed
12
+ * @param {number} [options.reconfirmTimeoutMs] - Reconfirmation timeout (ms), default 10000
13
+ * @param {number} [options.poofTimeoutMs=10000] - POOF window (RFC 6762 §10.5)
14
+ * @param {number} [options.poofResponseWaitMs=2000] - Time to wait for response before counting as unanswered
15
+ */
16
+ constructor(transport: MdnsTransport, { queryName, serviceType, domain, protocol, isTypeEnumeration, signal, onDestroy, reconfirmTimeoutMs, poofTimeoutMs, poofResponseWaitMs }: {
17
+ queryName: string;
18
+ serviceType: string;
19
+ domain: string;
20
+ protocol: string;
21
+ isTypeEnumeration?: boolean | undefined;
22
+ signal?: AbortSignal | undefined;
23
+ onDestroy?: (() => void) | undefined;
24
+ reconfirmTimeoutMs?: number | undefined;
25
+ poofTimeoutMs?: number | undefined;
26
+ poofResponseWaitMs?: number | undefined;
27
+ });
28
+ /**
29
+ * Currently discovered services, keyed by FQDN.
30
+ * @type {Map<string, Service>}
31
+ */
32
+ services: Map<string, Service>;
33
+ /**
34
+ * Manually remove a service by FQDN, emitting a `serviceDown` event.
35
+ *
36
+ * Use this when your application detects that a service is unreachable
37
+ * (e.g. via a health check) before its TTL expires. The service is removed
38
+ * from the `services` Map and its known-answer record is cleared, so it
39
+ * will be re-discovered if the advertiser announces it again.
40
+ *
41
+ * @param {string} fqdn - Fully qualified service name (e.g. "My Service._http._tcp.local")
42
+ * @returns {boolean} true if the service was found and removed, false otherwise
43
+ */
44
+ removeService(fqdn: string): boolean;
45
+ /**
46
+ * Request reconfirmation of a service record (RFC 6762 §10.4).
47
+ * Sends verification queries and removes the service if no response
48
+ * is received within the timeout.
49
+ * @param {string} fqdn - The service FQDN to reconfirm
50
+ */
51
+ reconfirm(fqdn: string): void;
52
+ /**
53
+ * Flush all discovered services and restart querying from scratch.
54
+ *
55
+ * Call this after a network interface change (e.g. WiFi reconnect).
56
+ * All current services are emitted as `serviceDown` events, caches are
57
+ * cleared, and querying restarts with the initial rapid schedule.
58
+ */
59
+ resetNetwork(): void;
60
+ /**
61
+ * Stop browsing and end the async iterator.
62
+ * @param {any} [reason] - If provided, the iterator throws this instead of
63
+ * returning done: true (matching Node.js convention for AbortSignal).
64
+ */
65
+ destroy(reason?: any): void;
66
+ /** @returns {Promise<void>} */
67
+ [Symbol.asyncDispose](): Promise<void>;
68
+ /** @returns {AsyncIterableIterator<BrowseEvent>} */
69
+ [Symbol.asyncIterator](): AsyncIterableIterator<BrowseEvent>;
70
+ #private;
71
+ }
72
+ /**
73
+ * AllServiceBrowser — discovers all service instances on the network by
74
+ * first enumerating service types (RFC 6763 §9), then spawning a
75
+ * ServiceBrowser for each discovered type.
76
+ *
77
+ * Presents the same async iterable interface as ServiceBrowser, yielding
78
+ * fully resolved BrowseEvents with real host, port, and addresses.
79
+ */
80
+ export class AllServiceBrowser {
81
+ /**
82
+ * @param {MdnsTransport} transport
83
+ * @param {object} options
84
+ * @param {string} options.domain
85
+ * @param {AbortSignal} [options.signal]
86
+ * @param {() => void} [options.onDestroy]
87
+ */
88
+ constructor(transport: MdnsTransport, { domain, signal, onDestroy }: {
89
+ domain: string;
90
+ signal?: AbortSignal | undefined;
91
+ onDestroy?: (() => void) | undefined;
92
+ });
93
+ /**
94
+ * Merged live map of all discovered service instances across all types.
95
+ * @type {Map<string, Service>}
96
+ */
97
+ services: Map<string, Service>;
98
+ /**
99
+ * Get the first discovered service. Resolves as soon as any service
100
+ * instance emits a serviceUp event.
101
+ * @returns {Promise<Service>}
102
+ */
103
+ first(): Promise<Service>;
104
+ /**
105
+ * Flush all discovered services and restart querying from scratch.
106
+ *
107
+ * Call this after a network interface change (e.g. WiFi reconnect).
108
+ * Delegates to each internal ServiceBrowser and clears the merged
109
+ * services map.
110
+ */
111
+ resetNetwork(): void;
112
+ /**
113
+ * Stop all sub-browsers and end the async iterator.
114
+ * @param {any} [reason] - If provided, the iterator throws this instead of
115
+ * returning done: true (matching Node.js convention for AbortSignal).
116
+ */
117
+ destroy(reason?: any): void;
118
+ /** @returns {Promise<void>} */
119
+ [Symbol.asyncDispose](): Promise<void>;
120
+ /** @returns {AsyncIterableIterator<BrowseEvent>} */
121
+ [Symbol.asyncIterator](): AsyncIterableIterator<BrowseEvent>;
122
+ #private;
123
+ }
124
+ export type Service = import("./service.js").Service;
125
+ export type DnsPacket = import("./dns.js").DnsPacket;
126
+ export type DnsRecord = import("./dns.js").DnsRecord;
127
+ export type MdnsTransport = import("./transport.js").MdnsTransport;
128
+ export type BrowseEvent = {
129
+ type: "serviceUp";
130
+ service: Service;
131
+ } | {
132
+ type: "serviceDown";
133
+ service: Service;
134
+ } | {
135
+ type: "serviceUpdated";
136
+ service: Service;
137
+ };
138
+ /**
139
+ * Resolves a promise externally — used for the async iterator's event queue.
140
+ */
141
+ export type Deferred<T> = {
142
+ promise: Promise<T>;
143
+ resolve: (value: T) => void;
144
+ reject: (reason?: unknown) => void;
145
+ };
@@ -0,0 +1,12 @@
1
+ /** mDNS multicast IPv4 address (RFC 6762 §3) */
2
+ export const MDNS_ADDRESS: "224.0.0.251";
3
+ /** mDNS multicast IPv6 address (RFC 6762 §3) */
4
+ export const MDNS_ADDRESS_V6: "FF02::FB";
5
+ /** mDNS default port (RFC 6762 §3) */
6
+ export const MDNS_PORT: 5353;
7
+ /** mDNS multicast TTL — must be 255 per RFC 6762 §11 */
8
+ export const MDNS_TTL: 255;
9
+ /** Meta-query name for service type enumeration (RFC 6763 §9) */
10
+ export const SERVICE_TYPE_ENUMERATION: "_services._dns-sd._udp.local";
11
+ /** Default domain for mDNS */
12
+ export const DEFAULT_DOMAIN: "local";
package/dist/dns.d.ts ADDED
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @typedef {object} DnsFlags
3
+ * @property {boolean} qr - true for response, false for query
4
+ * @property {number} opcode
5
+ * @property {boolean} aa - Authoritative Answer
6
+ * @property {boolean} tc - Truncated
7
+ * @property {boolean} rd - Recursion Desired
8
+ * @property {boolean} ra - Recursion Available
9
+ * @property {number} rcode - Response code
10
+ */
11
+ /**
12
+ * @typedef {object} DnsQuestion
13
+ * @property {string} name
14
+ * @property {number} type - RecordType value
15
+ * @property {boolean} [qu] - QU (unicast-response) bit (RFC 6762 §5.4)
16
+ */
17
+ /**
18
+ * @typedef {object} SrvData
19
+ * @property {number} priority
20
+ * @property {number} weight
21
+ * @property {number} port
22
+ * @property {string} target
23
+ */
24
+ /**
25
+ * @typedef {object} DnsRecord
26
+ * @property {string} name
27
+ * @property {number} type - RecordType value
28
+ * @property {number} class - Usually 1 (IN)
29
+ * @property {boolean} cacheFlush - mDNS cache-flush bit
30
+ * @property {number} ttl
31
+ * @property {string | SrvData | Uint8Array[]} data - Type-specific data
32
+ */
33
+ /**
34
+ * @typedef {object} DnsPacket
35
+ * @property {number} id
36
+ * @property {DnsFlags} flags
37
+ * @property {DnsQuestion[]} questions
38
+ * @property {DnsRecord[]} answers
39
+ * @property {DnsRecord[]} authorities
40
+ * @property {DnsRecord[]} additionals
41
+ */
42
+ /**
43
+ * Decode a DNS packet from a buffer.
44
+ * @param {Uint8Array} buf
45
+ * @returns {DnsPacket}
46
+ */
47
+ export function decode(buf: Uint8Array): DnsPacket;
48
+ /**
49
+ * @typedef {object} QueryOptions
50
+ * @property {DnsQuestion[]} questions
51
+ * @property {DnsRecord[]} [answers] - Known answers for suppression (RFC 6762 §7.1)
52
+ */
53
+ /**
54
+ * Encode an mDNS query into one or more packets.
55
+ * If the known-answer list is too large for a single packet, splits across
56
+ * multiple packets per RFC 6762 §7.2: the first packet contains the question
57
+ * and sets the TC bit, continuation packets contain only answers (QDCOUNT=0).
58
+ * @param {QueryOptions} options
59
+ * @returns {Buffer[]} - Array of encoded packets (usually 1)
60
+ */
61
+ export function encodeQueryPackets({ questions, answers }: QueryOptions): Buffer[];
62
+ /**
63
+ * Encode a single mDNS query packet.
64
+ * @param {QueryOptions} options
65
+ * @returns {Buffer}
66
+ */
67
+ export function encodeQuery({ questions, answers }: QueryOptions): Buffer;
68
+ export type RecordType = number;
69
+ export namespace RecordType {
70
+ let A: 1;
71
+ let PTR: 12;
72
+ let TXT: 16;
73
+ let AAAA: 28;
74
+ let SRV: 33;
75
+ let ANY: 255;
76
+ }
77
+ export type DnsFlags = {
78
+ /**
79
+ * - true for response, false for query
80
+ */
81
+ qr: boolean;
82
+ opcode: number;
83
+ /**
84
+ * - Authoritative Answer
85
+ */
86
+ aa: boolean;
87
+ /**
88
+ * - Truncated
89
+ */
90
+ tc: boolean;
91
+ /**
92
+ * - Recursion Desired
93
+ */
94
+ rd: boolean;
95
+ /**
96
+ * - Recursion Available
97
+ */
98
+ ra: boolean;
99
+ /**
100
+ * - Response code
101
+ */
102
+ rcode: number;
103
+ };
104
+ export type DnsQuestion = {
105
+ name: string;
106
+ /**
107
+ * - RecordType value
108
+ */
109
+ type: number;
110
+ /**
111
+ * - QU (unicast-response) bit (RFC 6762 §5.4)
112
+ */
113
+ qu?: boolean | undefined;
114
+ };
115
+ export type SrvData = {
116
+ priority: number;
117
+ weight: number;
118
+ port: number;
119
+ target: string;
120
+ };
121
+ export type DnsRecord = {
122
+ name: string;
123
+ /**
124
+ * - RecordType value
125
+ */
126
+ type: number;
127
+ /**
128
+ * - Usually 1 (IN)
129
+ */
130
+ class: number;
131
+ /**
132
+ * - mDNS cache-flush bit
133
+ */
134
+ cacheFlush: boolean;
135
+ ttl: number;
136
+ /**
137
+ * - Type-specific data
138
+ */
139
+ data: string | SrvData | Uint8Array[];
140
+ };
141
+ export type DnsPacket = {
142
+ id: number;
143
+ flags: DnsFlags;
144
+ questions: DnsQuestion[];
145
+ answers: DnsRecord[];
146
+ authorities: DnsRecord[];
147
+ additionals: DnsRecord[];
148
+ };
149
+ export type QueryOptions = {
150
+ questions: DnsQuestion[];
151
+ /**
152
+ * - Known answers for suppression (RFC 6762 §7.1)
153
+ */
154
+ answers?: DnsRecord[] | undefined;
155
+ };
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @typedef {import('./service.js').Service} Service
3
+ * @typedef {import('./browser.js').BrowseEvent} BrowseEvent
4
+ */
5
+ export class DnsSdBrowser {
6
+ /**
7
+ * @param {object} [options]
8
+ * @param {number} [options.port=5353] - mDNS port
9
+ * @param {string} [options.interface] - Network interface IP to bind to
10
+ */
11
+ constructor(options?: {
12
+ port?: number | undefined;
13
+ interface?: string | undefined;
14
+ });
15
+ /**
16
+ * Start browsing for a specific service type.
17
+ *
18
+ * Returns a ServiceBrowser that is an async iterable yielding BrowseEvents
19
+ * as services appear, disappear, or update on the network.
20
+ *
21
+ * @param {string | { name: string, protocol?: string }} serviceType
22
+ * Service type to browse for. Either a string like "_http._tcp" or
23
+ * an object like `{ name: 'http', protocol: 'tcp' }`.
24
+ * @param {object} [options]
25
+ * @param {AbortSignal} [options.signal] - Signal to cancel browsing
26
+ * @param {string} [options.subtype] - Browse a service subtype (RFC 6763 §7.1).
27
+ * e.g. `browse('_http._tcp', { subtype: '_printer' })` queries
28
+ * `_printer._sub._http._tcp.local`.
29
+ * @param {number} [options.reconfirmTimeoutMs] - Reconfirmation timeout (ms) per RFC 6762 §10.4
30
+ * @param {number} [options.poofTimeoutMs] - POOF window (ms) per RFC 6762 §10.5
31
+ * @param {number} [options.poofResponseWaitMs] - POOF response wait (ms) per RFC 6762 §10.5
32
+ * @returns {ServiceBrowser}
33
+ */
34
+ browse(serviceType: string | {
35
+ name: string;
36
+ protocol?: string;
37
+ }, options?: {
38
+ signal?: AbortSignal | undefined;
39
+ subtype?: string | undefined;
40
+ reconfirmTimeoutMs?: number | undefined;
41
+ poofTimeoutMs?: number | undefined;
42
+ poofResponseWaitMs?: number | undefined;
43
+ }): ServiceBrowser;
44
+ /**
45
+ * Browse for all service instances on the network, regardless of type.
46
+ *
47
+ * Discovers service types via `_services._dns-sd._udp.local` (RFC 6763 §9),
48
+ * then automatically browses each discovered type for instances. Returns
49
+ * fully resolved BrowseEvents with real host, port, and addresses — the
50
+ * same as `browse()` but across all types.
51
+ *
52
+ * @param {object} [options]
53
+ * @param {AbortSignal} [options.signal]
54
+ * @returns {AllServiceBrowser}
55
+ */
56
+ browseAll(options?: {
57
+ signal?: AbortSignal | undefined;
58
+ }): AllServiceBrowser;
59
+ /**
60
+ * Browse for service types on the network.
61
+ *
62
+ * Queries `_services._dns-sd._udp.local` (RFC 6763 §9) to discover
63
+ * which service types are being advertised. Returns lightweight
64
+ * Service objects representing types (not instances) — `host`, `port`,
65
+ * and `addresses` will be empty.
66
+ *
67
+ * For discovering fully resolved service instances across all types,
68
+ * use `browseAll()` instead.
69
+ *
70
+ * @param {object} [options]
71
+ * @param {AbortSignal} [options.signal]
72
+ * @returns {ServiceBrowser}
73
+ */
74
+ browseTypes(options?: {
75
+ signal?: AbortSignal | undefined;
76
+ }): ServiceBrowser;
77
+ /**
78
+ * Re-join multicast groups and restart all browsers.
79
+ *
80
+ * Call this after a network interface change (e.g. WiFi reconnect,
81
+ * Ethernet re-plug). The OS drops multicast group membership when an
82
+ * interface goes down; this method re-establishes it and flushes stale
83
+ * service state.
84
+ *
85
+ * All current services are emitted as `serviceDown` events, and
86
+ * querying restarts with the initial rapid schedule so services on
87
+ * the new network are discovered quickly.
88
+ */
89
+ rejoin(): void;
90
+ /**
91
+ * Stop all browsers and close the mDNS transport.
92
+ * @returns {Promise<void>}
93
+ */
94
+ destroy(): Promise<void>;
95
+ /**
96
+ * Returns a promise that resolves when the mDNS transport is ready
97
+ * to send and receive packets. Useful for tests or when you need
98
+ * to ensure the socket is bound before external interaction.
99
+ *
100
+ * Note: the transport is started lazily on the first `browse()` or
101
+ * `browseAll()` call. Calling `ready()` before any browse will throw.
102
+ * @returns {Promise<void>}
103
+ */
104
+ ready(): Promise<void>;
105
+ /** @returns {Promise<void>} */
106
+ [Symbol.asyncDispose](): Promise<void>;
107
+ #private;
108
+ }
109
+ export type Service = import("./service.js").Service;
110
+ export type BrowseEvent = import("./browser.js").BrowseEvent;
111
+ import { ServiceBrowser } from './browser.js';
112
+ import { AllServiceBrowser } from './browser.js';
113
+ export { ServiceBrowser, AllServiceBrowser } from "./browser.js";
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Service data type for discovered DNS-SD services.
3
+ * @module
4
+ */
5
+ /**
6
+ * @typedef {object} Service
7
+ * @property {string} name - Instance name (e.g. "My Printer")
8
+ * @property {string} type - Service type (e.g. "_http._tcp")
9
+ * @property {string} protocol - Transport protocol ("tcp" or "udp")
10
+ * @property {string} domain - Domain (default "local")
11
+ * @property {string} host - Target hostname (e.g. "printer.local")
12
+ * @property {number} port - Port number
13
+ * @property {string[]} addresses - IPv4 and IPv6 addresses
14
+ * @property {Record<string, string | true>} txt - Parsed TXT key-value pairs
15
+ * @property {Record<string, Uint8Array>} txtRaw - Raw TXT record values
16
+ * @property {string} fqdn - Fully qualified service name
17
+ * @property {string[]} subtypes - Service subtypes
18
+ * @property {number} updatedAt - Timestamp of last update (ms)
19
+ */
20
+ /**
21
+ * Parse TXT record data (array of Uint8Array strings) into key-value pairs.
22
+ *
23
+ * Per RFC 6763 §6.3:
24
+ * - Format is "key=value" where value is the part after the first '='
25
+ * - Keys without '=' are boolean flags (value is `true`)
26
+ * - Duplicate keys: only the first occurrence is used
27
+ * - Keys are case-insensitive but we preserve original casing
28
+ *
29
+ * @param {Uint8Array[]} txtData
30
+ * @returns {{ txt: Record<string, string | true>, txtRaw: Record<string, Uint8Array> }}
31
+ */
32
+ export function parseTxtData(txtData: Uint8Array[]): {
33
+ txt: Record<string, string | true>;
34
+ txtRaw: Record<string, Uint8Array>;
35
+ };
36
+ /**
37
+ * Parse a service type string into its components.
38
+ *
39
+ * Accepts either:
40
+ * - Full form: "_http._tcp" or "_http._tcp.local"
41
+ * - Object form: { name: "http", protocol: "tcp" }
42
+ *
43
+ * @param {string | { name: string, protocol?: string }} serviceType
44
+ * @returns {{ type: string, protocol: string, domain: string, queryName: string }}
45
+ */
46
+ export function parseServiceType(serviceType: string | {
47
+ name: string;
48
+ protocol?: string;
49
+ }): {
50
+ type: string;
51
+ protocol: string;
52
+ domain: string;
53
+ queryName: string;
54
+ };
55
+ /**
56
+ * Extract the instance name from a fully qualified service name.
57
+ *
58
+ * Given "My Service._http._tcp.local" and type "_http._tcp",
59
+ * returns "My Service".
60
+ *
61
+ * @param {string} fqdn
62
+ * @param {string} serviceType - e.g. "_http._tcp.local"
63
+ * @returns {string}
64
+ */
65
+ export function extractInstanceName(fqdn: string, serviceType: string): string;
66
+ export type Service = {
67
+ /**
68
+ * - Instance name (e.g. "My Printer")
69
+ */
70
+ name: string;
71
+ /**
72
+ * - Service type (e.g. "_http._tcp")
73
+ */
74
+ type: string;
75
+ /**
76
+ * - Transport protocol ("tcp" or "udp")
77
+ */
78
+ protocol: string;
79
+ /**
80
+ * - Domain (default "local")
81
+ */
82
+ domain: string;
83
+ /**
84
+ * - Target hostname (e.g. "printer.local")
85
+ */
86
+ host: string;
87
+ /**
88
+ * - Port number
89
+ */
90
+ port: number;
91
+ /**
92
+ * - IPv4 and IPv6 addresses
93
+ */
94
+ addresses: string[];
95
+ /**
96
+ * - Parsed TXT key-value pairs
97
+ */
98
+ txt: Record<string, string | true>;
99
+ /**
100
+ * - Raw TXT record values
101
+ */
102
+ txtRaw: Record<string, Uint8Array>;
103
+ /**
104
+ * - Fully qualified service name
105
+ */
106
+ fqdn: string;
107
+ /**
108
+ * - Service subtypes
109
+ */
110
+ subtypes: string[];
111
+ /**
112
+ * - Timestamp of last update (ms)
113
+ */
114
+ updatedAt: number;
115
+ };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @callback PacketHandler
3
+ * @param {dns.DnsPacket} packet
4
+ * @returns {void}
5
+ */
6
+ export class MdnsTransport {
7
+ /**
8
+ * @param {object} [options]
9
+ * @param {number} [options.port] - mDNS port (default 5353)
10
+ * @param {string} [options.interface] - Network interface IP to bind to
11
+ */
12
+ constructor(options?: {
13
+ port?: number | undefined;
14
+ interface?: string | undefined;
15
+ });
16
+ /**
17
+ * Start the transport: bind sockets and join multicast groups.
18
+ * Always binds IPv4. Attempts IPv6 but does not fail if unavailable.
19
+ * @returns {Promise<void>}
20
+ */
21
+ start(): Promise<void>;
22
+ /**
23
+ * Send an mDNS query on IPv4 (and IPv6 if available).
24
+ * @param {dns.QueryOptions} queryOptions
25
+ * @returns {Promise<void>}
26
+ */
27
+ sendQuery(queryOptions: dns.QueryOptions): Promise<void>;
28
+ /**
29
+ * Register a handler for incoming mDNS response packets.
30
+ * @param {PacketHandler} handler
31
+ */
32
+ addHandler(handler: PacketHandler): void;
33
+ /**
34
+ * Remove a previously registered handler.
35
+ * @param {PacketHandler} handler
36
+ */
37
+ removeHandler(handler: PacketHandler): void;
38
+ /**
39
+ * Register a handler for incoming mDNS query packets (QR=0).
40
+ * Used for duplicate question suppression (RFC 6762 §7.3) and
41
+ * Passive Observation of Failures (RFC 6762 §10.5).
42
+ * @param {PacketHandler} handler
43
+ */
44
+ addQueryHandler(handler: PacketHandler): void;
45
+ /**
46
+ * Remove a previously registered query handler.
47
+ * @param {PacketHandler} handler
48
+ */
49
+ removeQueryHandler(handler: PacketHandler): void;
50
+ /**
51
+ * Re-join multicast groups on existing sockets.
52
+ *
53
+ * Call this after a network interface change (e.g. WiFi reconnect,
54
+ * Ethernet re-plug). The OS drops multicast group membership when an
55
+ * interface goes down; this method re-establishes it so the socket
56
+ * can receive multicast responses again.
57
+ */
58
+ rejoinMulticast(): void;
59
+ /**
60
+ * Close all sockets and clean up.
61
+ * @returns {Promise<void>}
62
+ */
63
+ destroy(): Promise<void>;
64
+ #private;
65
+ }
66
+ export type PacketHandler = (packet: dns.DnsPacket) => void;
67
+ import * as dns from './dns.js';