libp2p 0.44.0 → 0.45.0-752db6d6

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 (188) hide show
  1. package/dist/index.min.js +30 -30
  2. package/dist/src/address-manager/index.d.ts +8 -4
  3. package/dist/src/address-manager/index.d.ts.map +1 -1
  4. package/dist/src/address-manager/index.js +37 -6
  5. package/dist/src/address-manager/index.js.map +1 -1
  6. package/dist/src/address-manager/utils.d.ts +2 -0
  7. package/dist/src/address-manager/utils.d.ts.map +1 -0
  8. package/dist/src/address-manager/utils.js +12 -0
  9. package/dist/src/address-manager/utils.js.map +1 -0
  10. package/dist/src/autonat/constants.d.ts +16 -2
  11. package/dist/src/autonat/constants.d.ts.map +1 -1
  12. package/dist/src/autonat/constants.js +16 -2
  13. package/dist/src/autonat/constants.js.map +1 -1
  14. package/dist/src/autonat/index.d.ts +12 -33
  15. package/dist/src/autonat/index.d.ts.map +1 -1
  16. package/dist/src/autonat/index.js +36 -30
  17. package/dist/src/autonat/index.js.map +1 -1
  18. package/dist/src/circuit-relay/server/advert-service.d.ts.map +1 -1
  19. package/dist/src/circuit-relay/server/advert-service.js +2 -2
  20. package/dist/src/circuit-relay/server/advert-service.js.map +1 -1
  21. package/dist/src/circuit-relay/server/index.d.ts.map +1 -1
  22. package/dist/src/circuit-relay/server/index.js +10 -3
  23. package/dist/src/circuit-relay/server/index.js.map +1 -1
  24. package/dist/src/circuit-relay/transport/discovery.d.ts.map +1 -1
  25. package/dist/src/circuit-relay/transport/discovery.js +4 -2
  26. package/dist/src/circuit-relay/transport/discovery.js.map +1 -1
  27. package/dist/src/circuit-relay/transport/index.d.ts +3 -0
  28. package/dist/src/circuit-relay/transport/index.d.ts.map +1 -1
  29. package/dist/src/circuit-relay/transport/index.js +6 -4
  30. package/dist/src/circuit-relay/transport/index.js.map +1 -1
  31. package/dist/src/circuit-relay/transport/listener.d.ts.map +1 -1
  32. package/dist/src/circuit-relay/transport/listener.js +30 -26
  33. package/dist/src/circuit-relay/transport/listener.js.map +1 -1
  34. package/dist/src/circuit-relay/transport/reservation-store.d.ts +5 -4
  35. package/dist/src/circuit-relay/transport/reservation-store.d.ts.map +1 -1
  36. package/dist/src/circuit-relay/transport/reservation-store.js +37 -30
  37. package/dist/src/circuit-relay/transport/reservation-store.js.map +1 -1
  38. package/dist/src/components.d.ts +6 -63
  39. package/dist/src/components.d.ts.map +1 -1
  40. package/dist/src/components.js +60 -164
  41. package/dist/src/components.js.map +1 -1
  42. package/dist/src/config/connection-gater.browser.d.ts +8 -0
  43. package/dist/src/config/connection-gater.browser.d.ts.map +1 -0
  44. package/dist/src/config/connection-gater.browser.js +27 -0
  45. package/dist/src/config/connection-gater.browser.js.map +1 -0
  46. package/dist/src/config/connection-gater.d.ts +6 -0
  47. package/dist/src/config/connection-gater.d.ts.map +1 -0
  48. package/dist/src/config/connection-gater.js +18 -0
  49. package/dist/src/config/connection-gater.js.map +1 -0
  50. package/dist/src/config.d.ts +2 -1
  51. package/dist/src/config.d.ts.map +1 -1
  52. package/dist/src/config.js +0 -62
  53. package/dist/src/config.js.map +1 -1
  54. package/dist/src/connection-manager/auto-dial.d.ts +3 -0
  55. package/dist/src/connection-manager/auto-dial.d.ts.map +1 -1
  56. package/dist/src/connection-manager/auto-dial.js +36 -13
  57. package/dist/src/connection-manager/auto-dial.js.map +1 -1
  58. package/dist/src/connection-manager/connection-pruner.d.ts +4 -0
  59. package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
  60. package/dist/src/connection-manager/connection-pruner.js +23 -8
  61. package/dist/src/connection-manager/connection-pruner.js.map +1 -1
  62. package/dist/src/connection-manager/dial-queue.d.ts +2 -1
  63. package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
  64. package/dist/src/connection-manager/dial-queue.js +36 -14
  65. package/dist/src/connection-manager/dial-queue.js.map +1 -1
  66. package/dist/src/connection-manager/index.d.ts +8 -7
  67. package/dist/src/connection-manager/index.d.ts.map +1 -1
  68. package/dist/src/connection-manager/index.js +23 -34
  69. package/dist/src/connection-manager/index.js.map +1 -1
  70. package/dist/src/content-routing/index.d.ts +0 -10
  71. package/dist/src/content-routing/index.d.ts.map +1 -1
  72. package/dist/src/content-routing/index.js +7 -42
  73. package/dist/src/content-routing/index.js.map +1 -1
  74. package/dist/src/content-routing/utils.d.ts.map +1 -1
  75. package/dist/src/content-routing/utils.js +3 -1
  76. package/dist/src/content-routing/utils.js.map +1 -1
  77. package/dist/src/fetch/index.d.ts +13 -35
  78. package/dist/src/fetch/index.d.ts.map +1 -1
  79. package/dist/src/fetch/index.js +7 -9
  80. package/dist/src/fetch/index.js.map +1 -1
  81. package/dist/src/identify/identify.d.ts +53 -0
  82. package/dist/src/identify/identify.d.ts.map +1 -0
  83. package/dist/src/identify/identify.js +407 -0
  84. package/dist/src/identify/identify.js.map +1 -0
  85. package/dist/src/identify/index.d.ts +12 -58
  86. package/dist/src/identify/index.d.ts.map +1 -1
  87. package/dist/src/identify/index.js +5 -388
  88. package/dist/src/identify/index.js.map +1 -1
  89. package/dist/src/index.d.ts +13 -68
  90. package/dist/src/index.d.ts.map +1 -1
  91. package/dist/src/index.js +2 -1
  92. package/dist/src/index.js.map +1 -1
  93. package/dist/src/insecure/index.js.map +1 -1
  94. package/dist/src/libp2p.d.ts +11 -42
  95. package/dist/src/libp2p.d.ts.map +1 -1
  96. package/dist/src/libp2p.js +137 -196
  97. package/dist/src/libp2p.js.map +1 -1
  98. package/dist/src/peer-routing.d.ts +1 -38
  99. package/dist/src/peer-routing.d.ts.map +1 -1
  100. package/dist/src/peer-routing.js +0 -59
  101. package/dist/src/peer-routing.js.map +1 -1
  102. package/dist/src/ping/constants.d.ts +4 -0
  103. package/dist/src/ping/constants.d.ts.map +1 -1
  104. package/dist/src/ping/constants.js +10 -0
  105. package/dist/src/ping/constants.js.map +1 -1
  106. package/dist/src/ping/index.d.ts +10 -27
  107. package/dist/src/ping/index.d.ts.map +1 -1
  108. package/dist/src/ping/index.js +18 -21
  109. package/dist/src/ping/index.js.map +1 -1
  110. package/dist/src/registrar.d.ts +5 -2
  111. package/dist/src/registrar.d.ts.map +1 -1
  112. package/dist/src/registrar.js +27 -25
  113. package/dist/src/registrar.js.map +1 -1
  114. package/dist/src/transport-manager.d.ts +11 -4
  115. package/dist/src/transport-manager.d.ts.map +1 -1
  116. package/dist/src/transport-manager.js +19 -10
  117. package/dist/src/transport-manager.js.map +1 -1
  118. package/dist/src/upgrader.d.ts +15 -10
  119. package/dist/src/upgrader.d.ts.map +1 -1
  120. package/dist/src/upgrader.js +39 -48
  121. package/dist/src/upgrader.js.map +1 -1
  122. package/dist/src/upnp-nat/index.d.ts +42 -0
  123. package/dist/src/upnp-nat/index.d.ts.map +1 -0
  124. package/dist/src/{nat-manager.js → upnp-nat/index.js} +11 -7
  125. package/dist/src/upnp-nat/index.js.map +1 -0
  126. package/dist/src/version.d.ts +1 -1
  127. package/dist/src/version.d.ts.map +1 -1
  128. package/dist/src/version.js +1 -1
  129. package/dist/src/version.js.map +1 -1
  130. package/package.json +61 -45
  131. package/src/address-manager/index.ts +50 -8
  132. package/src/address-manager/utils.ts +14 -0
  133. package/src/autonat/constants.ts +17 -2
  134. package/src/autonat/index.ts +53 -45
  135. package/src/circuit-relay/server/advert-service.ts +2 -2
  136. package/src/circuit-relay/server/index.ts +11 -3
  137. package/src/circuit-relay/transport/discovery.ts +5 -3
  138. package/src/circuit-relay/transport/index.ts +9 -4
  139. package/src/circuit-relay/transport/listener.ts +38 -28
  140. package/src/circuit-relay/transport/reservation-store.ts +34 -20
  141. package/src/components.ts +71 -234
  142. package/src/config/connection-gater.browser.ts +31 -0
  143. package/src/config/connection-gater.ts +19 -0
  144. package/src/config.ts +3 -64
  145. package/src/connection-manager/auto-dial.ts +44 -15
  146. package/src/connection-manager/connection-pruner.ts +28 -8
  147. package/src/connection-manager/dial-queue.ts +41 -21
  148. package/src/connection-manager/index.ts +31 -43
  149. package/src/content-routing/index.ts +7 -55
  150. package/src/content-routing/utils.ts +3 -1
  151. package/src/fetch/index.ts +51 -14
  152. package/src/identify/identify.ts +519 -0
  153. package/src/identify/index.ts +17 -507
  154. package/src/index.ts +14 -77
  155. package/src/insecure/index.ts +4 -4
  156. package/src/libp2p.ts +139 -260
  157. package/src/peer-routing.ts +1 -101
  158. package/src/ping/constants.ts +11 -0
  159. package/src/ping/index.ts +32 -28
  160. package/src/registrar.ts +31 -27
  161. package/src/transport-manager.ts +27 -13
  162. package/src/upgrader.ts +62 -58
  163. package/src/{nat-manager.ts → upnp-nat/index.ts} +16 -17
  164. package/src/version.ts +1 -1
  165. package/dist/src/dht/dht-content-routing.d.ts +0 -17
  166. package/dist/src/dht/dht-content-routing.d.ts.map +0 -1
  167. package/dist/src/dht/dht-content-routing.js +0 -32
  168. package/dist/src/dht/dht-content-routing.js.map +0 -1
  169. package/dist/src/dht/dht-peer-routing.d.ts +0 -15
  170. package/dist/src/dht/dht-peer-routing.d.ts.map +0 -1
  171. package/dist/src/dht/dht-peer-routing.js +0 -26
  172. package/dist/src/dht/dht-peer-routing.js.map +0 -1
  173. package/dist/src/dht/dummy-dht.d.ts +0 -20
  174. package/dist/src/dht/dummy-dht.d.ts.map +0 -1
  175. package/dist/src/dht/dummy-dht.js +0 -46
  176. package/dist/src/dht/dummy-dht.js.map +0 -1
  177. package/dist/src/nat-manager.d.ts +0 -74
  178. package/dist/src/nat-manager.d.ts.map +0 -1
  179. package/dist/src/nat-manager.js.map +0 -1
  180. package/dist/src/peer-record-updater.d.ts +0 -24
  181. package/dist/src/peer-record-updater.d.ts.map +0 -1
  182. package/dist/src/peer-record-updater.js +0 -44
  183. package/dist/src/peer-record-updater.js.map +0 -1
  184. package/dist/typedoc-urls.json +0 -41
  185. package/src/dht/dht-content-routing.ts +0 -44
  186. package/src/dht/dht-peer-routing.ts +0 -36
  187. package/src/dht/dummy-dht.ts +0 -60
  188. package/src/peer-record-updater.ts +0 -65
@@ -23,6 +23,8 @@ import { CIRCUIT_PROTO_CODE, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC } from '../
23
23
  import { RelayStoreInit, ReservationStore } from './reservation-store.js'
24
24
  import { RelayDiscovery, RelayDiscoveryComponents } from './discovery.js'
25
25
  import { CodeError } from '@libp2p/interfaces/errors'
26
+ import type { EventEmitter } from '@libp2p/interfaces/events'
27
+ import type { Libp2pEvents } from '@libp2p/interface-libp2p'
26
28
 
27
29
  const log = logger('libp2p:circuit-relay:transport')
28
30
 
@@ -49,6 +51,7 @@ export interface CircuitRelayTransportComponents extends RelayDiscoveryComponent
49
51
  addressManager: AddressManager
50
52
  contentRouting: ContentRouting
51
53
  connectionGater: ConnectionGater
54
+ events: EventEmitter<Libp2pEvents>
52
55
  }
53
56
 
54
57
  interface ConnectOptions {
@@ -165,7 +168,7 @@ class CircuitRelayTransport implements Transport {
165
168
  const destinationId = destinationAddr.getPeerId()
166
169
 
167
170
  if (relayId == null || destinationId == null) {
168
- const errMsg = 'Circuit relay dial failed as addresses did not have peer id'
171
+ const errMsg = `Circuit relay dial to ${ma.toString()} failed as address did not have peer ids`
169
172
  log.error(errMsg)
170
173
  throw new CodeError(errMsg, codes.ERR_RELAYED_DIAL)
171
174
  }
@@ -178,7 +181,9 @@ class CircuitRelayTransport implements Transport {
178
181
  let relayConnection = relayConnections[0]
179
182
 
180
183
  if (relayConnection == null) {
181
- await this.peerStore.addressBook.add(relayPeer, [relayAddr])
184
+ await this.peerStore.merge(relayPeer, {
185
+ multiaddrs: [relayAddr]
186
+ })
182
187
  relayConnection = await this.connectionManager.openConnection(relayPeer, options)
183
188
  disconnectOnFailure = true
184
189
  }
@@ -196,7 +201,7 @@ class CircuitRelayTransport implements Transport {
196
201
  disconnectOnFailure
197
202
  })
198
203
  } catch (err: any) {
199
- log.error('Circuit relay dial failed', err)
204
+ log.error(`Circuit relay dial to destination ${destinationPeer.toString()} via relay ${relayPeer.toString()} failed`, err)
200
205
  disconnectOnFailure && await relayConnection.close()
201
206
  throw err
202
207
  }
@@ -237,7 +242,7 @@ class CircuitRelayTransport implements Transport {
237
242
  log('new outbound connection %s', maConn.remoteAddr)
238
243
  return await this.upgrader.upgradeOutbound(maConn)
239
244
  } catch (err) {
240
- log.error('Circuit relay dial failed', err)
245
+ log.error(`Circuit relay dial to destination ${destinationPeer.toString()} via relay ${connection.remotePeer.toString()} failed`, err)
241
246
  disconnectOnFailure && await connection.close()
242
247
  throw err
243
248
  }
@@ -1,4 +1,4 @@
1
- import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events'
1
+ import { EventEmitter } from '@libp2p/interfaces/events'
2
2
  import type { ConnectionManager } from '@libp2p/interface-connection-manager'
3
3
  import type { Listener, ListenerEvents } from '@libp2p/interface-transport'
4
4
  import type { Multiaddr } from '@multiformats/multiaddr'
@@ -7,6 +7,9 @@ import type { ReservationStore } from './reservation-store.js'
7
7
  import type { PeerId } from '@libp2p/interface-peer-id'
8
8
  import { PeerMap } from '@libp2p/peer-collections'
9
9
  import { logger } from '@libp2p/logger'
10
+ import { peerIdFromString } from '@libp2p/peer-id'
11
+ import type { Connection } from '@libp2p/interface-connection'
12
+ import { CodeError } from '@libp2p/interfaces/errors'
10
13
 
11
14
  const log = logger('libp2p:circuit-relay:transport:listener')
12
15
 
@@ -18,7 +21,7 @@ export interface CircuitRelayTransportListenerComponents {
18
21
  class CircuitRelayTransportListener extends EventEmitter<ListenerEvents> implements Listener {
19
22
  private readonly connectionManager: ConnectionManager
20
23
  private readonly relayStore: ReservationStore
21
- private readonly listeningAddrs: PeerMap<Multiaddr>
24
+ private readonly listeningAddrs: PeerMap<Multiaddr[]>
22
25
 
23
26
  constructor (components: CircuitRelayTransportListenerComponents) {
24
27
  super()
@@ -31,19 +34,30 @@ class CircuitRelayTransportListener extends EventEmitter<ListenerEvents> impleme
31
34
  this.relayStore.addEventListener('relay:removed', (evt) => {
32
35
  this.#removeRelayPeer(evt.detail)
33
36
  })
34
-
35
- // remove listening addrs when a peer disconnects
36
- this.connectionManager.addEventListener('peer:disconnect', (evt) => {
37
- this.#removeRelayPeer(evt.detail.remotePeer)
38
- })
39
37
  }
40
38
 
41
39
  async listen (addr: Multiaddr): Promise<void> {
42
40
  log('listen on %s', addr)
43
41
 
44
- const addrString = addr.toString().split('/p2p-circuit').find(a => a !== '')
45
- const ma = multiaddr(addrString)
46
- const relayConn = await this.connectionManager.openConnection(ma)
42
+ const relayPeerStr = addr.getPeerId()
43
+ let relayConn: Connection | undefined
44
+
45
+ // check if we already have a connection to the relay
46
+ if (relayPeerStr != null) {
47
+ const relayPeer = peerIdFromString(relayPeerStr)
48
+ const connections = this.connectionManager.getConnectionsMap().get(relayPeer) ?? []
49
+
50
+ if (connections.length > 0) {
51
+ relayConn = connections[0]
52
+ }
53
+ }
54
+
55
+ // open a new connection as we don't already have one
56
+ if (relayConn == null) {
57
+ const addrString = addr.toString().split('/p2p-circuit').find(a => a !== '')
58
+ const ma = multiaddr(addrString)
59
+ relayConn = await this.connectionManager.openConnection(ma)
60
+ }
47
61
 
48
62
  if (!this.relayStore.hasReservation(relayConn.remotePeer)) {
49
63
  // addRelay calls transportManager.listen which calls this listen method
@@ -51,31 +65,27 @@ class CircuitRelayTransportListener extends EventEmitter<ListenerEvents> impleme
51
65
  return
52
66
  }
53
67
 
68
+ const reservation = this.relayStore.getReservation(relayConn.remotePeer)
69
+
70
+ if (reservation == null) {
71
+ throw new CodeError('Did not have reservation after making reservation', 'ERR_NO_RESERVATION')
72
+ }
73
+
54
74
  if (this.listeningAddrs.has(relayConn.remotePeer)) {
55
75
  log('already listening on relay %p', relayConn.remotePeer)
56
76
  return
57
77
  }
58
78
 
59
- this.listeningAddrs.set(relayConn.remotePeer, addr)
60
- this.dispatchEvent(new CustomEvent('listening'))
79
+ // add all addresses from the relay reservation
80
+ this.listeningAddrs.set(relayConn.remotePeer, reservation.addrs.map(buf => {
81
+ return multiaddr(buf).encapsulate('/p2p-circuit')
82
+ }))
83
+
84
+ this.safeDispatchEvent('listening', {})
61
85
  }
62
86
 
63
- /**
64
- * Get fixed up multiaddrs
65
- *
66
- * NOTE: This method will grab the peers multiaddrs and expand them such that:
67
- *
68
- * a) If it's an existing /p2p-circuit address for a specific relay i.e.
69
- * `/ip4/0.0.0.0/tcp/0/ipfs/QmRelay/p2p-circuit` this method will expand the
70
- * address to `/ip4/0.0.0.0/tcp/0/ipfs/QmRelay/p2p-circuit/ipfs/QmPeer` where
71
- * `QmPeer` is this peers id
72
- * b) If it's not a /p2p-circuit address, it will encapsulate the address as a /p2p-circuit
73
- * addr, such when dialing over a relay with this address, it will create the circuit using
74
- * the encapsulated transport address. This is useful when for example, a peer should only
75
- * be dialed over TCP rather than any other transport
76
- */
77
87
  getAddrs (): Multiaddr[] {
78
- return [...this.listeningAddrs.values()]
88
+ return [...this.listeningAddrs.values()].flat()
79
89
  }
80
90
 
81
91
  async close (): Promise<void> {
@@ -89,7 +99,7 @@ class CircuitRelayTransportListener extends EventEmitter<ListenerEvents> impleme
89
99
 
90
100
  if (had) {
91
101
  // Announce listen addresses change
92
- this.dispatchEvent(new CustomEvent('close'))
102
+ this.safeDispatchEvent('close', {})
93
103
  }
94
104
  }
95
105
  }
@@ -11,9 +11,10 @@ import { HopMessage, Status } from '../pb/index.js'
11
11
  import { getExpirationMilliseconds } from '../utils.js'
12
12
  import type { TransportManager } from '@libp2p/interface-transport'
13
13
  import type { Startable } from '@libp2p/interfaces/startable'
14
- import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events'
14
+ import { EventEmitter } from '@libp2p/interfaces/events'
15
15
  import type { PeerStore } from '@libp2p/interface-peer-store'
16
16
  import { multiaddr } from '@multiformats/multiaddr'
17
+ import type { Libp2pEvents } from '@libp2p/interface-libp2p'
17
18
 
18
19
  const log = logger('libp2p:circuit-relay:transport:reservation-store')
19
20
 
@@ -31,6 +32,7 @@ export interface RelayStoreComponents {
31
32
  connectionManager: ConnectionManager
32
33
  transportManager: TransportManager
33
34
  peerStore: PeerStore
35
+ events: EventEmitter<Libp2pEvents>
34
36
  }
35
37
 
36
38
  export interface RelayStoreInit {
@@ -68,6 +70,7 @@ export class ReservationStore extends EventEmitter<ReservationStoreEvents> imple
68
70
  private readonly connectionManager: ConnectionManager
69
71
  private readonly transportManager: TransportManager
70
72
  private readonly peerStore: PeerStore
73
+ private readonly events: EventEmitter<Libp2pEvents>
71
74
  private readonly reserveQueue: PQueue
72
75
  private readonly reservations: PeerMap<RelayEntry>
73
76
  private readonly maxDiscoveredRelays: number
@@ -80,6 +83,7 @@ export class ReservationStore extends EventEmitter<ReservationStoreEvents> imple
80
83
  this.connectionManager = components.connectionManager
81
84
  this.transportManager = components.transportManager
82
85
  this.peerStore = components.peerStore
86
+ this.events = components.events
83
87
  this.reservations = new PeerMap()
84
88
  this.maxDiscoveredRelays = init?.discoverRelays ?? 0
85
89
  this.started = false
@@ -92,8 +96,8 @@ export class ReservationStore extends EventEmitter<ReservationStoreEvents> imple
92
96
  // When a peer disconnects, if we had a reservation on that peer
93
97
  // remove the reservation and multiaddr and maybe trigger search
94
98
  // for new relays
95
- this.connectionManager.addEventListener('peer:disconnect', (evt) => {
96
- this.removeRelay(evt.detail.remotePeer)
99
+ this.events.addEventListener('peer:disconnect', (evt) => {
100
+ this.#removeRelay(evt.detail)
97
101
  })
98
102
  }
99
103
 
@@ -121,15 +125,15 @@ export class ReservationStore extends EventEmitter<ReservationStoreEvents> imple
121
125
  * on the remote peer
122
126
  */
123
127
  async addRelay (peerId: PeerId, type: RelayType): Promise<void> {
124
- log('add relay', this.reserveQueue.size)
128
+ if (this.peerId.equals(peerId)) {
129
+ log('not trying to use self as relay')
130
+ return
131
+ }
132
+
133
+ log('add relay %p', peerId)
125
134
 
126
135
  await this.reserveQueue.add(async () => {
127
136
  try {
128
- if (this.peerId.equals(peerId)) {
129
- log('not trying to use self as relay')
130
- return
131
- }
132
-
133
137
  // allow refresh of an existing reservation if it is about to expire
134
138
  const existingReservation = this.reservations.get(peerId)
135
139
 
@@ -177,6 +181,7 @@ export class ReservationStore extends EventEmitter<ReservationStoreEvents> imple
177
181
  })
178
182
  }, timeoutDuration)
179
183
 
184
+ // we've managed to create a reservation successfully
180
185
  this.reservations.set(peerId, {
181
186
  timeout,
182
187
  reservation,
@@ -184,18 +189,22 @@ export class ReservationStore extends EventEmitter<ReservationStoreEvents> imple
184
189
  })
185
190
 
186
191
  // ensure we don't close the connection to the relay
187
- await this.peerStore.tagPeer(peerId, RELAY_TAG, {
188
- value: 1,
189
- ttl: expiration
192
+ await this.peerStore.merge(peerId, {
193
+ tags: {
194
+ [RELAY_TAG]: {
195
+ value: 1,
196
+ ttl: expiration
197
+ }
198
+ }
190
199
  })
191
200
 
192
- await this.transportManager.listen(
193
- reservation.addrs.map(ma => {
194
- return multiaddr(ma).encapsulate('/p2p-circuit')
195
- })
196
- )
201
+ // listen on multiaddr that only the circuit transport is listening for
202
+ await this.transportManager.listen([multiaddr(`/p2p/${peerId.toString()}/p2p-circuit`)])
197
203
  } catch (err) {
198
204
  log.error('could not reserve slot on %p', peerId, err)
205
+
206
+ // if listening failed, remove the reservation
207
+ this.reservations.delete(peerId)
199
208
  }
200
209
  })
201
210
  }
@@ -204,6 +213,10 @@ export class ReservationStore extends EventEmitter<ReservationStoreEvents> imple
204
213
  return this.reservations.has(peerId)
205
214
  }
206
215
 
216
+ getReservation (peerId: PeerId): Reservation | undefined {
217
+ return this.reservations.get(peerId)?.reservation
218
+ }
219
+
207
220
  async #createReservation (connection: Connection): Promise<Reservation> {
208
221
  log('requesting reservation from %s', connection.remotePeer)
209
222
  const stream = await connection.newStream(RELAY_V2_HOP_CODEC)
@@ -235,14 +248,14 @@ export class ReservationStore extends EventEmitter<ReservationStoreEvents> imple
235
248
  /**
236
249
  * Remove listen relay
237
250
  */
238
- removeRelay (peerId: PeerId): void {
251
+ #removeRelay (peerId: PeerId): void {
239
252
  const existingReservation = this.reservations.get(peerId)
240
253
 
241
254
  if (existingReservation == null) {
242
255
  return
243
256
  }
244
257
 
245
- log('removing relay %p', peerId)
258
+ log('connection to relay %p closed, removing reservation from local store', peerId)
246
259
 
247
260
  clearTimeout(existingReservation.timeout)
248
261
  this.reservations.delete(peerId)
@@ -250,7 +263,8 @@ export class ReservationStore extends EventEmitter<ReservationStoreEvents> imple
250
263
  this.safeDispatchEvent('relay:removed', { detail: peerId })
251
264
 
252
265
  if (this.reservations.size < this.maxDiscoveredRelays) {
253
- this.dispatchEvent(new CustomEvent('relay:not-enough-relays'))
266
+ log('not enough relays %d/%d', this.reservations.size, this.maxDiscoveredRelays)
267
+ this.safeDispatchEvent('relay:not-enough-relays', {})
254
268
  }
255
269
  }
256
270
  }
package/src/components.ts CHANGED
@@ -10,13 +10,14 @@ import type { PeerStore } from '@libp2p/interface-peer-store'
10
10
  import type { Registrar } from '@libp2p/interface-registrar'
11
11
  import type { TransportManager, Upgrader } from '@libp2p/interface-transport'
12
12
  import type { Datastore } from 'interface-datastore'
13
- import type { PubSub } from '@libp2p/interface-pubsub'
14
- import type { DualDHT } from '@libp2p/interface-dht'
15
13
  import type { ConnectionManager } from '@libp2p/interface-connection-manager'
16
14
  import type { ConnectionGater } from '@libp2p/interface-connection-gater'
15
+ import type { Libp2pEvents } from '@libp2p/interface-libp2p'
16
+ import type { EventEmitter } from '@libp2p/interfaces/events'
17
17
 
18
- export interface Components {
18
+ export interface Components extends Record<string, any>, Startable {
19
19
  peerId: PeerId
20
+ events: EventEmitter<Libp2pEvents>
20
21
  addressManager: AddressManager
21
22
  peerStore: PeerStore
22
23
  upgrader: Upgrader
@@ -29,12 +30,11 @@ export interface Components {
29
30
  datastore: Datastore
30
31
  connectionProtector?: ConnectionProtector
31
32
  metrics?: Metrics
32
- dht?: DualDHT
33
- pubsub?: PubSub
34
33
  }
35
34
 
36
35
  export interface ComponentsInit {
37
36
  peerId?: PeerId
37
+ events?: EventEmitter<Libp2pEvents>
38
38
  addressManager?: AddressManager
39
39
  peerStore?: PeerStore
40
40
  upgrader?: Upgrader
@@ -47,271 +47,108 @@ export interface ComponentsInit {
47
47
  peerRouting?: PeerRouting
48
48
  datastore?: Datastore
49
49
  connectionProtector?: ConnectionProtector
50
- dht?: DualDHT
51
- pubsub?: PubSub
52
50
  }
53
51
 
54
- export class DefaultComponents implements Components, Startable {
55
- private _peerId?: PeerId
56
- private _addressManager?: AddressManager
57
- private _peerStore?: PeerStore
58
- private _upgrader?: Upgrader
59
- private _metrics?: Metrics
60
- private _registrar?: Registrar
61
- private _connectionManager?: ConnectionManager
62
- private _transportManager?: TransportManager
63
- private _connectionGater?: ConnectionGater
64
- private _contentRouting?: ContentRouting
65
- private _peerRouting?: PeerRouting
66
- private _datastore?: Datastore
67
- private _connectionProtector?: ConnectionProtector
68
- private _dht?: DualDHT
69
- private _pubsub?: PubSub
52
+ class DefaultComponents implements Startable {
53
+ public components: Record<string, any> = {}
70
54
  private _started = false
71
55
 
72
56
  constructor (init: ComponentsInit = {}) {
73
- this._peerId = init.peerId
74
- this._addressManager = init.addressManager
75
- this._peerStore = init.peerStore
76
- this._upgrader = init.upgrader
77
- this._metrics = init.metrics
78
- this._registrar = init.registrar
79
- this._connectionManager = init.connectionManager
80
- this._transportManager = init.transportManager
81
- this._connectionGater = init.connectionGater
82
- this._contentRouting = init.contentRouting
83
- this._peerRouting = init.peerRouting
84
- this._datastore = init.datastore
85
- this._connectionProtector = init.connectionProtector
86
- this._dht = init.dht
87
- this._pubsub = init.pubsub
57
+ this.components = {}
58
+
59
+ for (const [key, value] of Object.entries(init)) {
60
+ this.components[key] = value
61
+ }
88
62
  }
89
63
 
90
64
  isStarted (): boolean {
91
65
  return this._started
92
66
  }
93
67
 
94
- async beforeStart (): Promise<void> {
68
+ private async _invokeStartableMethod (methodName: 'beforeStart' | 'start' | 'afterStart' | 'beforeStop' | 'stop' | 'afterStop'): Promise<void> {
95
69
  await Promise.all(
96
- Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => {
97
- if (startable.beforeStart != null) {
98
- await startable.beforeStart()
99
- }
100
- })
70
+ Object.values(this.components)
71
+ .filter(obj => isStartable(obj))
72
+ .map(async (startable: Startable) => {
73
+ await startable[methodName]?.()
74
+ })
101
75
  )
102
76
  }
103
77
 
104
- async start (): Promise<void> {
105
- await Promise.all(
106
- Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => {
107
- await startable.start()
108
- })
109
- )
78
+ async beforeStart (): Promise<void> {
79
+ await this._invokeStartableMethod('beforeStart')
80
+ }
110
81
 
82
+ async start (): Promise<void> {
83
+ await this._invokeStartableMethod('start')
111
84
  this._started = true
112
85
  }
113
86
 
114
87
  async afterStart (): Promise<void> {
115
- await Promise.all(
116
- Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => {
117
- if (startable.afterStart != null) {
118
- await startable.afterStart()
119
- }
120
- })
121
- )
88
+ await this._invokeStartableMethod('afterStart')
122
89
  }
123
90
 
124
91
  async beforeStop (): Promise<void> {
125
- await Promise.all(
126
- Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => {
127
- if (startable.beforeStop != null) {
128
- await startable.beforeStop()
129
- }
130
- })
131
- )
92
+ await this._invokeStartableMethod('beforeStop')
132
93
  }
133
94
 
134
95
  async stop (): Promise<void> {
135
- await Promise.all(
136
- Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => {
137
- await startable.stop()
138
- })
139
- )
140
-
96
+ await this._invokeStartableMethod('stop')
141
97
  this._started = false
142
98
  }
143
99
 
144
100
  async afterStop (): Promise<void> {
145
- await Promise.all(
146
- Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => {
147
- if (startable.afterStop != null) {
148
- await startable.afterStop()
149
- }
150
- })
151
- )
152
- }
153
-
154
- get peerId (): PeerId {
155
- if (this._peerId == null) {
156
- throw new CodeError('peerId not set', 'ERR_SERVICE_MISSING')
157
- }
158
-
159
- return this._peerId
160
- }
161
-
162
- set peerId (peerId: PeerId) {
163
- this._peerId = peerId
164
- }
165
-
166
- get addressManager (): AddressManager {
167
- if (this._addressManager == null) {
168
- throw new CodeError('addressManager not set', 'ERR_SERVICE_MISSING')
169
- }
170
-
171
- return this._addressManager
172
- }
173
-
174
- set addressManager (addressManager: AddressManager) {
175
- this._addressManager = addressManager
176
- }
177
-
178
- get peerStore (): PeerStore {
179
- if (this._peerStore == null) {
180
- throw new CodeError('peerStore not set', 'ERR_SERVICE_MISSING')
181
- }
182
-
183
- return this._peerStore
184
- }
185
-
186
- set peerStore (peerStore: PeerStore) {
187
- this._peerStore = peerStore
188
- }
189
-
190
- get upgrader (): Upgrader {
191
- if (this._upgrader == null) {
192
- throw new CodeError('upgrader not set', 'ERR_SERVICE_MISSING')
193
- }
194
-
195
- return this._upgrader
196
- }
197
-
198
- set upgrader (upgrader: Upgrader) {
199
- this._upgrader = upgrader
200
- }
201
-
202
- get registrar (): Registrar {
203
- if (this._registrar == null) {
204
- throw new CodeError('registrar not set', 'ERR_SERVICE_MISSING')
205
- }
206
-
207
- return this._registrar
208
- }
209
-
210
- set registrar (registrar: Registrar) {
211
- this._registrar = registrar
212
- }
213
-
214
- get connectionManager (): ConnectionManager {
215
- if (this._connectionManager == null) {
216
- throw new CodeError('connectionManager not set', 'ERR_SERVICE_MISSING')
217
- }
218
-
219
- return this._connectionManager
220
- }
221
-
222
- set connectionManager (connectionManager: ConnectionManager) {
223
- this._connectionManager = connectionManager
224
- }
225
-
226
- get transportManager (): TransportManager {
227
- if (this._transportManager == null) {
228
- throw new CodeError('transportManager not set', 'ERR_SERVICE_MISSING')
229
- }
230
-
231
- return this._transportManager
232
- }
233
-
234
- set transportManager (transportManager: TransportManager) {
235
- this._transportManager = transportManager
236
- }
237
-
238
- get connectionGater (): ConnectionGater {
239
- if (this._connectionGater == null) {
240
- throw new CodeError('connectionGater not set', 'ERR_SERVICE_MISSING')
241
- }
242
-
243
- return this._connectionGater
244
- }
245
-
246
- set connectionGater (connectionGater: ConnectionGater) {
247
- this._connectionGater = connectionGater
248
- }
249
-
250
- get contentRouting (): ContentRouting {
251
- if (this._contentRouting == null) {
252
- throw new CodeError('contentRouting not set', 'ERR_SERVICE_MISSING')
253
- }
254
-
255
- return this._contentRouting
101
+ await this._invokeStartableMethod('afterStop')
256
102
  }
103
+ }
257
104
 
258
- set contentRouting (contentRouting: ContentRouting) {
259
- this._contentRouting = contentRouting
260
- }
105
+ const OPTIONAL_SERVICES = [
106
+ 'metrics',
107
+ 'connectionProtector'
108
+ ]
109
+
110
+ const NON_SERVICE_PROPERTIES = [
111
+ 'components',
112
+ 'isStarted',
113
+ 'beforeStart',
114
+ 'start',
115
+ 'afterStart',
116
+ 'beforeStop',
117
+ 'stop',
118
+ 'afterStop',
119
+ 'then',
120
+ '_invokeStartableMethod'
121
+ ]
122
+
123
+ export function defaultComponents (init: ComponentsInit = {}): Components {
124
+ const components = new DefaultComponents(init)
125
+
126
+ const proxy = new Proxy(components, {
127
+ get (target, prop, receiver) {
128
+ if (typeof prop === 'string' && !NON_SERVICE_PROPERTIES.includes(prop)) {
129
+ const service = components.components[prop]
130
+
131
+ if (service == null && !OPTIONAL_SERVICES.includes(prop)) {
132
+ throw new CodeError(`${prop} not set`, 'ERR_SERVICE_MISSING')
133
+ }
261
134
 
262
- get peerRouting (): PeerRouting {
263
- if (this._peerRouting == null) {
264
- throw new CodeError('peerRouting not set', 'ERR_SERVICE_MISSING')
265
- }
135
+ return service
136
+ }
266
137
 
267
- return this._peerRouting
268
- }
138
+ return Reflect.get(target, prop, receiver)
139
+ },
269
140
 
270
- set peerRouting (peerRouting: PeerRouting) {
271
- this._peerRouting = peerRouting
272
- }
141
+ set (target, prop, value) {
142
+ if (typeof prop === 'string') {
143
+ components.components[prop] = value
144
+ } else {
145
+ Reflect.set(target, prop, value)
146
+ }
273
147
 
274
- get datastore (): Datastore {
275
- if (this._datastore == null) {
276
- throw new CodeError('datastore not set', 'ERR_SERVICE_MISSING')
148
+ return true
277
149
  }
150
+ })
278
151
 
279
- return this._datastore
280
- }
281
-
282
- set datastore (datastore: Datastore) {
283
- this._datastore = datastore
284
- }
285
-
286
- get connectionProtector (): ConnectionProtector | undefined {
287
- return this._connectionProtector
288
- }
289
-
290
- set connectionProtector (connectionProtector: ConnectionProtector | undefined) {
291
- this._connectionProtector = connectionProtector
292
- }
293
-
294
- get metrics (): Metrics | undefined {
295
- return this._metrics
296
- }
297
-
298
- set metrics (metrics: Metrics | undefined) {
299
- this._metrics = metrics
300
- }
301
-
302
- get dht (): DualDHT | undefined {
303
- return this._dht
304
- }
305
-
306
- set dht (dht: DualDHT | undefined) {
307
- this._dht = dht
308
- }
309
-
310
- get pubsub (): PubSub | undefined {
311
- return this._pubsub
312
- }
313
-
314
- set pubsub (pubsub: PubSub | undefined) {
315
- this._pubsub = pubsub
316
- }
152
+ // @ts-expect-error component keys are proxied
153
+ return proxy
317
154
  }