@libp2p/mdns 9.0.14 → 10.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.
package/src/index.ts CHANGED
@@ -76,185 +76,23 @@
76
76
  * ```
77
77
  */
78
78
 
79
- import { CustomEvent, TypedEventEmitter } from '@libp2p/interface/events'
80
- import { peerDiscovery } from '@libp2p/interface/peer-discovery'
81
- import { logger } from '@libp2p/logger'
82
- import multicastDNS from 'multicast-dns'
83
- import * as query from './query.js'
84
- import { stringGen } from './utils.js'
85
- import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interface/peer-discovery'
86
- import type { PeerInfo } from '@libp2p/interface/peer-info'
87
- import type { Startable } from '@libp2p/interface/src/startable.js'
88
- import type { AddressManager } from '@libp2p/interface-internal/address-manager'
89
-
90
- const log = logger('libp2p:mdns')
79
+ import { MulticastDNS } from './mdns.js'
80
+ import type { ComponentLogger, PeerDiscovery } from '@libp2p/interface'
81
+ import type { AddressManager } from '@libp2p/interface-internal'
91
82
 
92
83
  export interface MulticastDNSInit {
93
- /**
94
- * (true/false) announce our presence through mDNS, default `true`
95
- */
96
84
  broadcast?: boolean
97
-
98
- /**
99
- * query interval, default 10 \* 1000 (10 seconds)
100
- */
101
85
  interval?: number
102
-
103
- /**
104
- * name of the service announce , default '_p2p._udp.local\`
105
- */
106
86
  serviceTag?: string
107
- /**
108
- * Peer name to announce (should not be peeer id), default random string
109
- */
110
87
  peerName?: string
111
-
112
- /**
113
- * UDP port to broadcast to
114
- */
115
88
  port?: number
116
-
117
- /**
118
- * UDP IP to broadcast to
119
- */
120
89
  ip?: string
121
90
  }
122
91
 
123
92
  export interface MulticastDNSComponents {
124
93
  addressManager: AddressManager
125
- }
126
-
127
- class MulticastDNS extends TypedEventEmitter<PeerDiscoveryEvents> implements PeerDiscovery, Startable {
128
- public mdns?: multicastDNS.MulticastDNS
129
-
130
- private readonly broadcast: boolean
131
- private readonly interval: number
132
- private readonly serviceTag: string
133
- private readonly peerName: string
134
- private readonly port: number
135
- private readonly ip: string
136
- private _queryInterval: ReturnType<typeof setInterval> | null
137
- private readonly components: MulticastDNSComponents
138
-
139
- constructor (components: MulticastDNSComponents, init: MulticastDNSInit = {}) {
140
- super()
141
-
142
- this.broadcast = init.broadcast !== false
143
- this.interval = init.interval ?? (1e3 * 10)
144
- this.serviceTag = init.serviceTag ?? '_p2p._udp.local'
145
- this.ip = init.ip ?? '224.0.0.251'
146
- this.peerName = init.peerName ?? stringGen(63)
147
- // 63 is dns label limit
148
- if (this.peerName.length >= 64) {
149
- throw new Error('Peer name should be less than 64 chars long')
150
- }
151
- this.port = init.port ?? 5353
152
- this.components = components
153
- this._queryInterval = null
154
- this._onMdnsQuery = this._onMdnsQuery.bind(this)
155
- this._onMdnsResponse = this._onMdnsResponse.bind(this)
156
- this._onMdnsWarning = this._onMdnsWarning.bind(this)
157
- this._onMdnsError = this._onMdnsError.bind(this)
158
- }
159
-
160
- readonly [peerDiscovery] = this
161
-
162
- readonly [Symbol.toStringTag] = '@libp2p/mdns'
163
-
164
- isStarted (): boolean {
165
- return Boolean(this.mdns)
166
- }
167
-
168
- /**
169
- * Start sending queries to the LAN.
170
- *
171
- * @returns {void}
172
- */
173
- async start (): Promise<void> {
174
- if (this.mdns != null) {
175
- return
176
- }
177
-
178
- this.mdns = multicastDNS({ port: this.port, ip: this.ip })
179
- this.mdns.on('query', this._onMdnsQuery)
180
- this.mdns.on('response', this._onMdnsResponse)
181
- this.mdns.on('warning', this._onMdnsWarning)
182
- this.mdns.on('error', this._onMdnsError)
183
-
184
- this._queryInterval = query.queryLAN(this.mdns, this.serviceTag, this.interval)
185
- }
186
-
187
- _onMdnsQuery (event: multicastDNS.QueryPacket): void {
188
- if (this.mdns == null) {
189
- return
190
- }
191
-
192
- log.trace('received incoming mDNS query')
193
- query.gotQuery(
194
- event,
195
- this.mdns,
196
- this.peerName,
197
- this.components.addressManager.getAddresses(),
198
- this.serviceTag,
199
- this.broadcast)
200
- }
201
-
202
- _onMdnsResponse (event: multicastDNS.ResponsePacket): void {
203
- log.trace('received mDNS query response')
204
-
205
- try {
206
- const foundPeer = query.gotResponse(event, this.peerName, this.serviceTag)
207
-
208
- if (foundPeer != null) {
209
- log('discovered peer in mDNS query response %p', foundPeer.id)
210
-
211
- this.dispatchEvent(new CustomEvent<PeerInfo>('peer', {
212
- detail: foundPeer
213
- }))
214
- }
215
- } catch (err) {
216
- log.error('Error processing peer response', err)
217
- }
218
- }
219
-
220
- _onMdnsWarning (err: Error): void {
221
- log.error('mdns warning', err)
222
- }
223
-
224
- _onMdnsError (err: Error): void {
225
- log.error('mdns error', err)
226
- }
227
-
228
- /**
229
- * Stop sending queries to the LAN.
230
- *
231
- * @returns {Promise}
232
- */
233
- async stop (): Promise<void> {
234
- if (this.mdns == null) {
235
- return
236
- }
237
-
238
- this.mdns.removeListener('query', this._onMdnsQuery)
239
- this.mdns.removeListener('response', this._onMdnsResponse)
240
- this.mdns.removeListener('warning', this._onMdnsWarning)
241
- this.mdns.removeListener('error', this._onMdnsError)
242
-
243
- if (this._queryInterval != null) {
244
- clearInterval(this._queryInterval)
245
- this._queryInterval = null
246
- }
247
-
248
- await new Promise<void>((resolve) => {
249
- if (this.mdns != null) {
250
- this.mdns.destroy(resolve)
251
- } else {
252
- resolve()
253
- }
254
- })
94
+ logger: ComponentLogger
255
95
 
256
- this.mdns = undefined
257
- }
258
96
  }
259
97
 
260
98
  export function mdns (init: MulticastDNSInit = {}): (components: MulticastDNSComponents) => PeerDiscovery {
package/src/mdns.ts ADDED
@@ -0,0 +1,149 @@
1
+ import { CustomEvent, TypedEventEmitter, peerDiscoverySymbol } from '@libp2p/interface'
2
+ import multicastDNS from 'multicast-dns'
3
+ import * as query from './query.js'
4
+ import { stringGen } from './utils.js'
5
+ import type { MulticastDNSComponents, MulticastDNSInit } from './index.js'
6
+ import type { Logger, PeerDiscovery, PeerDiscoveryEvents, PeerInfo } from '@libp2p/interface'
7
+ import type { Startable } from '@libp2p/interface/src/startable.js'
8
+
9
+ export class MulticastDNS extends TypedEventEmitter<PeerDiscoveryEvents> implements PeerDiscovery, Startable {
10
+ public mdns?: multicastDNS.MulticastDNS
11
+
12
+ private readonly log: Logger
13
+ private readonly broadcast: boolean
14
+ private readonly interval: number
15
+ private readonly serviceTag: string
16
+ private readonly peerName: string
17
+ private readonly port: number
18
+ private readonly ip: string
19
+ private _queryInterval: ReturnType<typeof setInterval> | null
20
+ private readonly components: MulticastDNSComponents
21
+
22
+ constructor (components: MulticastDNSComponents, init: MulticastDNSInit = {}) {
23
+ super()
24
+
25
+ this.log = components.logger.forComponent('libp2p:mdns')
26
+ this.broadcast = init.broadcast !== false
27
+ this.interval = init.interval ?? (1e3 * 10)
28
+ this.serviceTag = init.serviceTag ?? '_p2p._udp.local'
29
+ this.ip = init.ip ?? '224.0.0.251'
30
+ this.peerName = init.peerName ?? stringGen(63)
31
+ // 63 is dns label limit
32
+ if (this.peerName.length >= 64) {
33
+ throw new Error('Peer name should be less than 64 chars long')
34
+ }
35
+ this.port = init.port ?? 5353
36
+ this.components = components
37
+ this._queryInterval = null
38
+ this._onMdnsQuery = this._onMdnsQuery.bind(this)
39
+ this._onMdnsResponse = this._onMdnsResponse.bind(this)
40
+ this._onMdnsWarning = this._onMdnsWarning.bind(this)
41
+ this._onMdnsError = this._onMdnsError.bind(this)
42
+ }
43
+
44
+ readonly [peerDiscoverySymbol] = this
45
+
46
+ readonly [Symbol.toStringTag] = '@libp2p/mdns'
47
+
48
+ isStarted (): boolean {
49
+ return Boolean(this.mdns)
50
+ }
51
+
52
+ /**
53
+ * Start sending queries to the LAN.
54
+ *
55
+ * @returns {void}
56
+ */
57
+ async start (): Promise<void> {
58
+ if (this.mdns != null) {
59
+ return
60
+ }
61
+
62
+ this.mdns = multicastDNS({ port: this.port, ip: this.ip })
63
+ this.mdns.on('query', this._onMdnsQuery)
64
+ this.mdns.on('response', this._onMdnsResponse)
65
+ this.mdns.on('warning', this._onMdnsWarning)
66
+ this.mdns.on('error', this._onMdnsError)
67
+
68
+ this._queryInterval = query.queryLAN(this.mdns, this.serviceTag, this.interval, {
69
+ log: this.log
70
+ })
71
+ }
72
+
73
+ _onMdnsQuery (event: multicastDNS.QueryPacket): void {
74
+ if (this.mdns == null) {
75
+ return
76
+ }
77
+
78
+ this.log.trace('received incoming mDNS query')
79
+ query.gotQuery(
80
+ event,
81
+ this.mdns,
82
+ this.peerName,
83
+ this.components.addressManager.getAddresses(),
84
+ this.serviceTag,
85
+ this.broadcast, {
86
+ log: this.log
87
+ }
88
+ )
89
+ }
90
+
91
+ _onMdnsResponse (event: multicastDNS.ResponsePacket): void {
92
+ this.log.trace('received mDNS query response')
93
+
94
+ try {
95
+ const foundPeer = query.gotResponse(event, this.peerName, this.serviceTag, {
96
+ log: this.log
97
+ })
98
+
99
+ if (foundPeer != null) {
100
+ this.log('discovered peer in mDNS query response %p', foundPeer.id)
101
+
102
+ this.dispatchEvent(new CustomEvent<PeerInfo>('peer', {
103
+ detail: foundPeer
104
+ }))
105
+ }
106
+ } catch (err) {
107
+ this.log.error('Error processing peer response', err)
108
+ }
109
+ }
110
+
111
+ _onMdnsWarning (err: Error): void {
112
+ this.log.error('mdns warning', err)
113
+ }
114
+
115
+ _onMdnsError (err: Error): void {
116
+ this.log.error('mdns error', err)
117
+ }
118
+
119
+ /**
120
+ * Stop sending queries to the LAN.
121
+ *
122
+ * @returns {Promise}
123
+ */
124
+ async stop (): Promise<void> {
125
+ if (this.mdns == null) {
126
+ return
127
+ }
128
+
129
+ this.mdns.removeListener('query', this._onMdnsQuery)
130
+ this.mdns.removeListener('response', this._onMdnsResponse)
131
+ this.mdns.removeListener('warning', this._onMdnsWarning)
132
+ this.mdns.removeListener('error', this._onMdnsError)
133
+
134
+ if (this._queryInterval != null) {
135
+ clearInterval(this._queryInterval)
136
+ this._queryInterval = null
137
+ }
138
+
139
+ await new Promise<void>((resolve) => {
140
+ if (this.mdns != null) {
141
+ this.mdns.destroy(resolve)
142
+ } else {
143
+ resolve()
144
+ }
145
+ })
146
+
147
+ this.mdns = undefined
148
+ }
149
+ }
package/src/query.ts CHANGED
@@ -1,16 +1,13 @@
1
- import { logger } from '@libp2p/logger'
2
1
  import { peerIdFromString } from '@libp2p/peer-id'
3
2
  import { isPrivate } from '@libp2p/utils/multiaddr/is-private'
4
3
  import { multiaddr, type Multiaddr, protocols } from '@multiformats/multiaddr'
5
- import type { PeerInfo } from '@libp2p/interface/peer-info'
4
+ import type { LoggerOptions, PeerInfo } from '@libp2p/interface'
6
5
  import type { Answer, StringAnswer, TxtAnswer } from 'dns-packet'
7
6
  import type { MulticastDNS, QueryPacket, ResponsePacket } from 'multicast-dns'
8
7
 
9
- const log = logger('libp2p:mdns:query')
10
-
11
- export function queryLAN (mdns: MulticastDNS, serviceTag: string, interval: number): ReturnType<typeof setInterval> {
8
+ export function queryLAN (mdns: MulticastDNS, serviceTag: string, interval: number, options?: LoggerOptions): ReturnType<typeof setInterval> {
12
9
  const query = (): void => {
13
- log.trace('query', serviceTag)
10
+ options?.log.trace('query', serviceTag)
14
11
 
15
12
  mdns.query({
16
13
  questions: [{
@@ -25,7 +22,7 @@ export function queryLAN (mdns: MulticastDNS, serviceTag: string, interval: numb
25
22
  return setInterval(query, interval)
26
23
  }
27
24
 
28
- export function gotResponse (rsp: ResponsePacket, localPeerName: string, serviceTag: string): PeerInfo | undefined {
25
+ export function gotResponse (rsp: ResponsePacket, localPeerName: string, serviceTag: string, options?: LoggerOptions): PeerInfo | undefined {
29
26
  if (rsp.answers == null) {
30
27
  return
31
28
  }
@@ -70,21 +67,20 @@ export function gotResponse (rsp: ResponsePacket, localPeerName: string, service
70
67
  if (peerId == null) {
71
68
  throw new Error("Multiaddr doesn't contain PeerId")
72
69
  }
73
- log('peer found %p', peerId)
70
+ options?.log('peer found %p', peerId)
74
71
 
75
72
  return {
76
73
  id: peerIdFromString(peerId),
77
- multiaddrs: multiaddrs.map(addr => addr.decapsulateCode(protocols('p2p').code)),
78
- protocols: []
74
+ multiaddrs: multiaddrs.map(addr => addr.decapsulateCode(protocols('p2p').code))
79
75
  }
80
76
  } catch (e) {
81
- log.error('failed to parse mdns response', e)
77
+ options?.log.error('failed to parse mdns response', e)
82
78
  }
83
79
  }
84
80
 
85
- export function gotQuery (qry: QueryPacket, mdns: MulticastDNS, peerName: string, multiaddrs: Multiaddr[], serviceTag: string, broadcast: boolean): void {
81
+ export function gotQuery (qry: QueryPacket, mdns: MulticastDNS, peerName: string, multiaddrs: Multiaddr[], serviceTag: string, broadcast: boolean, options?: LoggerOptions): void {
86
82
  if (!broadcast) {
87
- log('not responding to mDNS query as broadcast mode is false')
83
+ options?.log('not responding to mDNS query as broadcast mode is false')
88
84
  return
89
85
  }
90
86
 
@@ -113,13 +109,13 @@ export function gotQuery (qry: QueryPacket, mdns: MulticastDNS, peerName: string
113
109
  // TXT record fields have a max data length of 255 bytes
114
110
  // see 6.1 - https://www.ietf.org/rfc/rfc6763.txt
115
111
  if (data.length > 255) {
116
- log('multiaddr %a is too long to use in mDNS query response', addr)
112
+ options?.log('multiaddr %a is too long to use in mDNS query response', addr)
117
113
  return
118
114
  }
119
115
 
120
116
  // spec mandates multiaddr contains peer id
121
117
  if (addr.getPeerId() == null) {
122
- log('multiaddr %a did not have a peer ID so cannot be used in mDNS query response', addr)
118
+ options?.log('multiaddr %a did not have a peer ID so cannot be used in mDNS query response', addr)
123
119
  return
124
120
  }
125
121
 
@@ -132,7 +128,7 @@ export function gotQuery (qry: QueryPacket, mdns: MulticastDNS, peerName: string
132
128
  })
133
129
  })
134
130
 
135
- log.trace('responding to query')
131
+ options?.log.trace('responding to query')
136
132
  mdns.respond(answers)
137
133
  }
138
134
  }