@libp2p/mdns 1.0.1 → 1.0.2

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,81 @@
1
+ import type { PeerData } from '@libp2p/interfaces/peer-data'
2
+ import type { PeerId } from '@libp2p/interfaces/peer-id'
3
+ import { logger } from '@libp2p/logger'
4
+ import { peerIdFromString } from '@libp2p/peer-id'
5
+ import { Multiaddr } from '@multiformats/multiaddr'
6
+ import type { Answer } from 'dns-packet'
7
+ import { SERVICE_TAG_LOCAL } from './constants.js'
8
+
9
+ const log = logger('libp2p:mdns:compat:utils')
10
+
11
+ export function findPeerDataInAnswers (answers: Answer[], ourPeerId: PeerId): PeerData | undefined {
12
+ const ptrRecord = answers.find(a => a.type === 'PTR' && a.name === SERVICE_TAG_LOCAL)
13
+
14
+ // Only deal with responses for our service tag
15
+ if (ptrRecord == null) {
16
+ return
17
+ }
18
+
19
+ log.trace('got response', SERVICE_TAG_LOCAL)
20
+
21
+ const txtRecord = answers.find(a => a.type === 'TXT')
22
+ if (txtRecord == null || txtRecord.type !== 'TXT') {
23
+ log('missing TXT record in response')
24
+ return
25
+ }
26
+
27
+ let peerIdStr: string
28
+ try {
29
+ peerIdStr = txtRecord.data[0].toString()
30
+ } catch (err) {
31
+ log('failed to extract peer ID from TXT record data', txtRecord, err)
32
+ return
33
+ }
34
+
35
+ let peerId: PeerId
36
+ try {
37
+ peerId = peerIdFromString(peerIdStr)
38
+ } catch (err) {
39
+ log('failed to create peer ID from TXT record data', peerIdStr, err)
40
+ return
41
+ }
42
+
43
+ if (ourPeerId.equals(peerId)) {
44
+ log('ignoring reply to myself')
45
+ return
46
+ }
47
+
48
+ const multiaddrs: Multiaddr[] = []
49
+ const hosts: { A: Record<string, string>, AAAA: Record<string, string> } = {
50
+ A: {},
51
+ AAAA: {}
52
+ }
53
+
54
+ answers.forEach(answer => {
55
+ if (answer.type === 'A') {
56
+ hosts.A[answer.name] = answer.data
57
+ }
58
+
59
+ if (answer.type === 'AAAA') {
60
+ hosts.AAAA[answer.name] = answer.data
61
+ }
62
+ })
63
+
64
+ answers.forEach(answer => {
65
+ if (answer.type === 'SRV') {
66
+ if (hosts.A[answer.data.target] != null) {
67
+ multiaddrs.push(new Multiaddr(`/ip4/${hosts.A[answer.data.target]}/tcp/${answer.data.port}/p2p/${peerId.toString()}`))
68
+ } else if (hosts.AAAA[answer.data.target] != null) {
69
+ multiaddrs.push(new Multiaddr(`/ip6/${hosts.AAAA[answer.data.target]}/tcp/${answer.data.port}/p2p/${peerId.toString()}`))
70
+ } else {
71
+ multiaddrs.push(new Multiaddr(`/dnsaddr/${answer.data.target}/tcp/${answer.data.port}/p2p/${peerId.toString()}`))
72
+ }
73
+ }
74
+ })
75
+
76
+ return {
77
+ id: peerId,
78
+ multiaddrs,
79
+ protocols: []
80
+ }
81
+ }
package/src/index.ts CHANGED
@@ -3,26 +3,23 @@ import { CustomEvent, EventEmitter } from '@libp2p/interfaces'
3
3
  import { logger } from '@libp2p/logger'
4
4
  import * as query from './query.js'
5
5
  import { GoMulticastDNS } from './compat/index.js'
6
- import type { PeerId } from '@libp2p/interfaces/peer-id'
7
6
  import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interfaces/peer-discovery'
8
- import type { Multiaddr } from '@multiformats/multiaddr'
9
7
  import type { PeerData } from '@libp2p/interfaces/peer-data'
8
+ import { Components, Initializable } from '@libp2p/interfaces/components'
10
9
 
11
10
  const log = logger('libp2p:mdns')
12
11
 
13
12
  export interface MulticastDNSOptions {
14
- peerId: PeerId
15
13
  broadcast?: boolean
16
14
  interval?: number
17
15
  serviceTag?: string
18
16
  port?: number
19
- multiaddrs?: Multiaddr[]
20
17
  compat?: boolean
21
18
  compatQueryPeriod?: number
22
19
  compatQueryInterval?: number
23
20
  }
24
21
 
25
- export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery {
22
+ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements PeerDiscovery, Initializable {
26
23
  static tag = 'mdns'
27
24
 
28
25
  public mdns?: multicastDNS.MulticastDNS
@@ -31,24 +28,17 @@ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements P
31
28
  private readonly interval: number
32
29
  private readonly serviceTag: string
33
30
  private readonly port: number
34
- private readonly peerId: PeerId
35
- private readonly peerMultiaddrs: Multiaddr[] // TODO: update this when multiaddrs change?
36
- private _queryInterval: NodeJS.Timer | null
31
+ private _queryInterval: ReturnType<typeof setInterval> | null
37
32
  private readonly _goMdns?: GoMulticastDNS
33
+ private components: Components = new Components()
38
34
 
39
- constructor (options: MulticastDNSOptions) {
35
+ constructor (options: MulticastDNSOptions = {}) {
40
36
  super()
41
37
 
42
- if (options.peerId == null) {
43
- throw new Error('needs own PeerId to work')
44
- }
45
-
46
38
  this.broadcast = options.broadcast !== false
47
39
  this.interval = options.interval ?? (1e3 * 10)
48
40
  this.serviceTag = options.serviceTag ?? 'ipfs.local'
49
41
  this.port = options.port ?? 5353
50
- this.peerId = options.peerId
51
- this.peerMultiaddrs = options.multiaddrs ?? []
52
42
  this._queryInterval = null
53
43
  this._onPeer = this._onPeer.bind(this)
54
44
  this._onMdnsQuery = this._onMdnsQuery.bind(this)
@@ -56,8 +46,6 @@ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements P
56
46
 
57
47
  if (options.compat !== false) {
58
48
  this._goMdns = new GoMulticastDNS({
59
- multiaddrs: this.peerMultiaddrs,
60
- peerId: options.peerId,
61
49
  queryPeriod: options.compatQueryPeriod,
62
50
  queryInterval: options.compatQueryInterval
63
51
  })
@@ -65,6 +53,12 @@ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements P
65
53
  }
66
54
  }
67
55
 
56
+ init (components: Components): void {
57
+ this.components = components
58
+
59
+ this._goMdns?.init(components)
60
+ }
61
+
68
62
  isStarted () {
69
63
  return Boolean(this.mdns)
70
64
  }
@@ -95,20 +89,25 @@ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements P
95
89
  return
96
90
  }
97
91
 
98
- query.gotQuery(event, this.mdns, this.peerId, this.peerMultiaddrs, this.serviceTag, this.broadcast)
92
+ log.trace('received incoming mDNS query')
93
+ query.gotQuery(event, this.mdns, this.components.getPeerId(), this.components.getAddressManager().getAddresses(), this.serviceTag, this.broadcast)
99
94
  }
100
95
 
101
96
  _onMdnsResponse (event: multicastDNS.ResponsePacket) {
97
+ log.trace('received mDNS query response')
98
+
102
99
  try {
103
- const foundPeer = query.gotResponse(event, this.peerId, this.serviceTag)
100
+ const foundPeer = query.gotResponse(event, this.components.getPeerId(), this.serviceTag)
104
101
 
105
102
  if (foundPeer != null) {
106
- this.dispatchEvent(new CustomEvent('peer', {
103
+ log('discovered peer in mDNS qeury response %p', foundPeer.id)
104
+
105
+ this.dispatchEvent(new CustomEvent<PeerData>('peer', {
107
106
  detail: foundPeer
108
107
  }))
109
108
  }
110
109
  } catch (err) {
111
- log('Error processing peer response', err)
110
+ log.error('Error processing peer response', err)
112
111
  }
113
112
  }
114
113
 
@@ -117,7 +116,7 @@ export class MulticastDNS extends EventEmitter<PeerDiscoveryEvents> implements P
117
116
  return
118
117
  }
119
118
 
120
- this.dispatchEvent(new CustomEvent('peer', {
119
+ this.dispatchEvent(new CustomEvent<PeerData>('peer', {
121
120
  detail: evt.detail
122
121
  }))
123
122
  }
package/src/query.ts CHANGED
@@ -1,18 +1,18 @@
1
1
  import os from 'os'
2
2
  import { logger } from '@libp2p/logger'
3
- import { Multiaddr, MultiaddrObject } from '@multiformats/multiaddr'
4
- import { base58btc } from 'multiformats/bases/base58'
3
+ import { Multiaddr, MultiaddrObject, protocols } from '@multiformats/multiaddr'
5
4
  import { peerIdFromString } from '@libp2p/peer-id'
6
5
  import type { PeerId } from '@libp2p/interfaces/peer-id'
7
6
  import type { PeerData } from '@libp2p/interfaces/peer-data'
8
7
  import type { MulticastDNS, ResponsePacket, QueryPacket } from 'multicast-dns'
9
8
  import type { SrvAnswer, StringAnswer, TxtAnswer, Answer } from 'dns-packet'
10
9
 
11
- const log = logger('libp2p:mdns')
10
+ const log = logger('libp2p:mdns:query')
12
11
 
13
12
  export function queryLAN (mdns: MulticastDNS, serviceTag: string, interval: number) {
14
13
  const query = () => {
15
14
  log('query', serviceTag)
15
+
16
16
  mdns.query({
17
17
  questions: [{
18
18
  name: serviceTag,
@@ -82,14 +82,16 @@ export function gotResponse (rsp: ResponsePacket, localPeerId: PeerId, serviceTa
82
82
  }
83
83
  })
84
84
 
85
- if (localPeerId.toString(base58btc) === b58Id) {
85
+ if (localPeerId.toString() === b58Id) {
86
86
  return // replied to myself, ignore
87
87
  }
88
88
 
89
- log('peer found -', b58Id)
89
+ const id = peerIdFromString(b58Id)
90
+
91
+ log('peer found %p', id)
90
92
 
91
93
  return {
92
- id: peerIdFromString(b58Id),
94
+ id,
93
95
  multiaddrs,
94
96
  protocols: []
95
97
  }
@@ -97,11 +99,12 @@ export function gotResponse (rsp: ResponsePacket, localPeerId: PeerId, serviceTa
97
99
 
98
100
  export function gotQuery (qry: QueryPacket, mdns: MulticastDNS, peerId: PeerId, multiaddrs: Multiaddr[], serviceTag: string, broadcast: boolean) {
99
101
  if (!broadcast) {
102
+ log('not responding to mDNS query as broadcast mode is false')
100
103
  return
101
104
  }
102
105
 
103
106
  const addresses: MultiaddrObject[] = multiaddrs.reduce<MultiaddrObject[]>((acc, addr) => {
104
- if (addr.isThinWaistAddress()) {
107
+ if (addr.decapsulateCode(protocols('p2p').code).isThinWaistAddress()) {
105
108
  acc.push(addr.toOptions())
106
109
  }
107
110
  return acc
@@ -109,6 +112,7 @@ export function gotQuery (qry: QueryPacket, mdns: MulticastDNS, peerId: PeerId,
109
112
 
110
113
  // Only announce TCP for now
111
114
  if (addresses.length === 0) {
115
+ log('no thin waist addresses present, cannot respond to query')
112
116
  return
113
117
  }
114
118
 
@@ -120,14 +124,14 @@ export function gotQuery (qry: QueryPacket, mdns: MulticastDNS, peerId: PeerId,
120
124
  type: 'PTR',
121
125
  class: 'IN',
122
126
  ttl: 120,
123
- data: peerId.toString(base58btc) + '.' + serviceTag
127
+ data: peerId.toString() + '.' + serviceTag
124
128
  })
125
129
 
126
130
  // Only announce TCP multiaddrs for now
127
131
  const port = addresses[0].port
128
132
 
129
133
  answers.push({
130
- name: peerId.toString(base58btc) + '.' + serviceTag,
134
+ name: peerId.toString() + '.' + serviceTag,
131
135
  type: 'SRV',
132
136
  class: 'IN',
133
137
  ttl: 120,
@@ -140,11 +144,11 @@ export function gotQuery (qry: QueryPacket, mdns: MulticastDNS, peerId: PeerId,
140
144
  })
141
145
 
142
146
  answers.push({
143
- name: peerId.toString(base58btc) + '.' + serviceTag,
147
+ name: peerId.toString() + '.' + serviceTag,
144
148
  type: 'TXT',
145
149
  class: 'IN',
146
150
  ttl: 120,
147
- data: peerId.toString(base58btc)
151
+ data: peerId.toString()
148
152
  })
149
153
 
150
154
  addresses.forEach((addr) => {