@libp2p/circuit-relay-v2 1.0.24-62e32252a → 1.0.24-757fb2674

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 (42) hide show
  1. package/dist/index.min.js +3 -3
  2. package/dist/src/constants.d.ts +12 -13
  3. package/dist/src/constants.d.ts.map +1 -1
  4. package/dist/src/constants.js +12 -13
  5. package/dist/src/constants.js.map +1 -1
  6. package/dist/src/pb/index.d.ts +7 -7
  7. package/dist/src/pb/index.d.ts.map +1 -1
  8. package/dist/src/pb/index.js +52 -94
  9. package/dist/src/pb/index.js.map +1 -1
  10. package/dist/src/server/advert-service.d.ts +44 -0
  11. package/dist/src/server/advert-service.d.ts.map +1 -0
  12. package/dist/src/server/advert-service.js +72 -0
  13. package/dist/src/server/advert-service.js.map +1 -0
  14. package/dist/src/server/index.d.ts +7 -1
  15. package/dist/src/server/index.d.ts.map +1 -1
  16. package/dist/src/server/index.js +19 -10
  17. package/dist/src/server/index.js.map +1 -1
  18. package/dist/src/transport/discovery.d.ts +10 -15
  19. package/dist/src/transport/discovery.d.ts.map +1 -1
  20. package/dist/src/transport/discovery.js +51 -103
  21. package/dist/src/transport/discovery.js.map +1 -1
  22. package/dist/src/transport/index.d.ts +18 -27
  23. package/dist/src/transport/index.d.ts.map +1 -1
  24. package/dist/src/transport/index.js +3 -0
  25. package/dist/src/transport/index.js.map +1 -1
  26. package/dist/src/transport/reservation-store.d.ts +3 -7
  27. package/dist/src/transport/reservation-store.d.ts.map +1 -1
  28. package/dist/src/transport/reservation-store.js +13 -37
  29. package/dist/src/transport/reservation-store.js.map +1 -1
  30. package/dist/src/transport/transport.d.ts +1 -0
  31. package/dist/src/transport/transport.d.ts.map +1 -1
  32. package/dist/src/transport/transport.js +19 -20
  33. package/dist/src/transport/transport.js.map +1 -1
  34. package/package.json +12 -11
  35. package/src/constants.ts +15 -16
  36. package/src/pb/index.ts +53 -96
  37. package/src/server/advert-service.ts +107 -0
  38. package/src/server/index.ts +29 -11
  39. package/src/transport/discovery.ts +56 -121
  40. package/src/transport/index.ts +18 -28
  41. package/src/transport/reservation-store.ts +13 -45
  42. package/src/transport/transport.ts +21 -21
@@ -1,28 +1,24 @@
1
- import { TypedEventEmitter, setMaxListeners } from '@libp2p/interface'
2
- import { PeerQueue } from '@libp2p/utils/peer-queue'
3
- import { anySignal } from 'any-signal'
4
- import { raceSignal } from 'race-signal'
1
+ import { TypedEventEmitter } from '@libp2p/interface'
5
2
  import {
3
+ RELAY_RENDEZVOUS_NS,
6
4
  RELAY_V2_HOP_CODEC
7
5
  } from '../constants.js'
8
- import type { ComponentLogger, Logger, PeerId, PeerStore, Startable, TopologyFilter } from '@libp2p/interface'
9
- import type { ConnectionManager, RandomWalk, Registrar, TransportManager } from '@libp2p/interface-internal'
6
+ import { namespaceToCid } from '../utils.js'
7
+ import type { ComponentLogger, Logger, ContentRouting, PeerId, PeerStore, Startable } from '@libp2p/interface'
8
+ import type { ConnectionManager, Registrar, TransportManager } from '@libp2p/interface-internal'
10
9
 
11
10
  export interface RelayDiscoveryEvents {
12
11
  'relay:discover': CustomEvent<PeerId>
13
12
  }
14
13
 
15
14
  export interface RelayDiscoveryComponents {
15
+ peerId: PeerId
16
16
  peerStore: PeerStore
17
17
  connectionManager: ConnectionManager
18
18
  transportManager: TransportManager
19
+ contentRouting: ContentRouting
19
20
  registrar: Registrar
20
21
  logger: ComponentLogger
21
- randomWalk: RandomWalk
22
- }
23
-
24
- export interface RelayDiscoveryInit {
25
- filter?: TopologyFilter
26
22
  }
27
23
 
28
24
  /**
@@ -30,30 +26,23 @@ export interface RelayDiscoveryInit {
30
26
  * peers that support the circuit v2 HOP protocol.
31
27
  */
32
28
  export class RelayDiscovery extends TypedEventEmitter<RelayDiscoveryEvents> implements Startable {
29
+ private readonly peerId: PeerId
33
30
  private readonly peerStore: PeerStore
31
+ private readonly contentRouting: ContentRouting
34
32
  private readonly registrar: Registrar
35
- private readonly connectionManager: ConnectionManager
36
- private readonly randomWalk: RandomWalk
37
33
  private started: boolean
38
- private running: boolean
39
34
  private topologyId?: string
40
35
  private readonly log: Logger
41
- private discoveryController: AbortController
42
- private readonly filter?: TopologyFilter
43
36
 
44
- constructor (components: RelayDiscoveryComponents, init: RelayDiscoveryInit = {}) {
37
+ constructor (components: RelayDiscoveryComponents) {
45
38
  super()
46
39
 
47
40
  this.log = components.logger.forComponent('libp2p:circuit-relay:discover-relays')
48
41
  this.started = false
49
- this.running = false
42
+ this.peerId = components.peerId
50
43
  this.peerStore = components.peerStore
44
+ this.contentRouting = components.contentRouting
51
45
  this.registrar = components.registrar
52
- this.connectionManager = components.connectionManager
53
- this.randomWalk = components.randomWalk
54
- this.filter = init.filter
55
- this.discoveryController = new AbortController()
56
- setMaxListeners(Infinity, this.discoveryController.signal)
57
46
  }
58
47
 
59
48
  isStarted (): boolean {
@@ -64,9 +53,8 @@ export class RelayDiscovery extends TypedEventEmitter<RelayDiscoveryEvents> impl
64
53
  // register a topology listener for when new peers are encountered
65
54
  // that support the hop protocol
66
55
  this.topologyId = await this.registrar.register(RELAY_V2_HOP_CODEC, {
67
- filter: this.filter,
56
+ notifyOnTransient: true,
68
57
  onConnect: (peerId) => {
69
- this.log('discovered relay %p', peerId)
70
58
  this.safeDispatchEvent('relay:discover', { detail: peerId })
71
59
  }
72
60
  })
@@ -74,12 +62,18 @@ export class RelayDiscovery extends TypedEventEmitter<RelayDiscoveryEvents> impl
74
62
  this.started = true
75
63
  }
76
64
 
65
+ afterStart (): void {
66
+ void this.discover()
67
+ .catch(err => {
68
+ this.log.error('error discovering relays', err)
69
+ })
70
+ }
71
+
77
72
  stop (): void {
78
73
  if (this.topologyId != null) {
79
74
  this.registrar.unregister(this.topologyId)
80
75
  }
81
76
 
82
- this.discoveryController?.abort()
83
77
  this.started = false
84
78
  }
85
79
 
@@ -87,113 +81,54 @@ export class RelayDiscovery extends TypedEventEmitter<RelayDiscoveryEvents> impl
87
81
  * Try to listen on available hop relay connections.
88
82
  * The following order will happen while we do not have enough relays:
89
83
  *
90
- * 1. Check the metadata store for known relays, try to listen on the ones we are already connected to
84
+ * 1. Check the metadata store for known relays, try to listen on the ones we are already connected
91
85
  * 2. Dial and try to listen on the peers we know that support hop but are not connected
92
86
  * 3. Search the network
93
87
  */
94
- startDiscovery (): void {
95
- if (this.running) {
96
- return
97
- }
98
-
99
- this.log('start discovery')
100
- this.running = true
101
- this.discoveryController = new AbortController()
102
- setMaxListeners(Infinity, this.discoveryController.signal)
103
-
104
- Promise.resolve()
105
- .then(async () => {
106
- this.log('searching peer store for relays')
107
-
108
- const peers = (await this.peerStore.all({
109
- filters: [
110
- // filter by a list of peers supporting RELAY_V2_HOP and ones we are not listening on
111
- (peer) => {
112
- return peer.protocols.includes(RELAY_V2_HOP_CODEC)
113
- }
114
- ],
115
- orders: [
116
- () => Math.random() < 0.5 ? 1 : -1
117
- ]
118
- }))
119
-
120
- for (const peer of peers) {
121
- this.log.trace('found relay peer %p in peer store', peer.id)
122
- this.safeDispatchEvent('relay:discover', { detail: peer.id })
88
+ async discover (): Promise<void> {
89
+ this.log('searching peer store for relays')
90
+ const peers = (await this.peerStore.all({
91
+ filters: [
92
+ // filter by a list of peers supporting RELAY_V2_HOP and ones we are not listening on
93
+ (peer) => {
94
+ return peer.protocols.includes(RELAY_V2_HOP_CODEC)
123
95
  }
96
+ ],
97
+ orders: [
98
+ () => Math.random() < 0.5 ? 1 : -1
99
+ ]
100
+ }))
101
+
102
+ for (const peer of peers) {
103
+ this.log('found relay peer %p in content peer store', peer.id)
104
+ this.safeDispatchEvent('relay:discover', { detail: peer.id })
105
+ }
124
106
 
125
- this.log('found %d relay peers in peer store', peers.length)
126
-
127
- // perform random walk and dial peers - after identify has run, the network
128
- // topology will be notified of new relays
129
- const queue = new PeerQueue({
130
- concurrency: 5
131
- })
132
-
133
- this.log('start random walk')
134
- for await (const peer of this.randomWalk.walk({ signal: this.discoveryController.signal })) {
135
- this.log.trace('found random peer %p', peer.id)
136
-
137
- if (queue.has(peer.id)) {
138
- this.log.trace('random peer %p was already in queue', peer.id)
139
-
140
- // skip peers already in the queue
141
- continue
142
- }
143
-
144
- if (this.connectionManager.getConnections(peer.id)?.length > 0) {
145
- this.log.trace('random peer %p was already connected', peer.id)
146
-
147
- // skip peers we are already connected to
148
- continue
149
- }
150
-
151
- if (!(await this.connectionManager.isDialable(peer.multiaddrs))) {
152
- this.log.trace('random peer %p was not dialable', peer.id, peer.multiaddrs.map(ma => ma.toString()))
153
-
154
- // skip peers we can't dial
155
- continue
156
- }
157
-
158
- this.log.trace('wait for space in queue for %p', peer.id)
107
+ this.log('found %d relay peers in peer store', peers.length)
159
108
 
160
- // pause the random walk until there is space in the queue
161
- await raceSignal(queue.onSizeLessThan(10), this.discoveryController.signal)
109
+ try {
110
+ this.log('searching content routing for relays')
111
+ const cid = await namespaceToCid(RELAY_RENDEZVOUS_NS)
162
112
 
163
- this.log('adding random peer %p to dial queue (length: %d)', peer.id, queue.size)
113
+ let found = 0
164
114
 
165
- // dial the peer - this will cause identify to run and our topology to
166
- // be notified and we'll attempt to create reservations
167
- queue.add(async () => {
168
- const signal = anySignal([this.discoveryController.signal, AbortSignal.timeout(5000)])
169
- setMaxListeners(Infinity, signal)
115
+ for await (const provider of this.contentRouting.findProviders(cid)) {
116
+ if (provider.multiaddrs.length > 0 && !provider.id.equals(this.peerId)) {
117
+ const peerId = provider.id
170
118
 
171
- try {
172
- await this.connectionManager.openConnection(peer.id, { signal })
173
- } finally {
174
- signal.clear()
175
- }
176
- }, {
177
- peerId: peer.id,
178
- signal: this.discoveryController.signal
119
+ found++
120
+ await this.peerStore.merge(peerId, {
121
+ multiaddrs: provider.multiaddrs
179
122
  })
180
- .catch(err => {
181
- this.log.error('error opening connection to random peer %p', peer.id, err)
182
- })
183
- }
184
123
 
185
- await queue.onIdle()
186
- })
187
- .catch(err => {
188
- if (!this.discoveryController.signal.aborted) {
189
- this.log.error('failed when finding relays on the network', err)
124
+ this.log('found relay peer %p in content routing', peerId)
125
+ this.safeDispatchEvent('relay:discover', { detail: peerId })
190
126
  }
191
- })
192
- }
127
+ }
193
128
 
194
- stopDiscovery (): void {
195
- this.log('stop discovery')
196
- this.running = false
197
- this.discoveryController?.abort()
129
+ this.log('found %d relay peers in content routing', found)
130
+ } catch (err: any) {
131
+ this.log.error('failed when finding relays on the network', err)
132
+ }
198
133
  }
199
134
  }
@@ -1,16 +1,20 @@
1
+ import { type Transport, type Upgrader, type Libp2pEvents, type ComponentLogger, type ConnectionGater, type ContentRouting, type TypedEventTarget, type PeerId, type PeerStore } from '@libp2p/interface'
2
+ import { type RelayDiscoveryComponents } from './discovery.js'
3
+ import { type RelayStoreInit } from './reservation-store.js'
1
4
  import { CircuitRelayTransport } from './transport.js'
2
- import type { RelayDiscoveryComponents } from './discovery.js'
3
- import type { RelayStoreInit } from './reservation-store.js'
4
- import type { Transport, Upgrader, Libp2pEvents, ConnectionGater, TypedEventTarget, PeerId, TopologyFilter } from '@libp2p/interface'
5
- import type { AddressManager, Registrar } from '@libp2p/interface-internal'
5
+ import type { AddressManager, ConnectionManager, Registrar } from '@libp2p/interface-internal'
6
6
 
7
7
  export interface CircuitRelayTransportComponents extends RelayDiscoveryComponents {
8
8
  peerId: PeerId
9
+ peerStore: PeerStore
9
10
  registrar: Registrar
11
+ connectionManager: ConnectionManager
10
12
  upgrader: Upgrader
11
13
  addressManager: AddressManager
14
+ contentRouting: ContentRouting
12
15
  connectionGater: ConnectionGater
13
16
  events: TypedEventTarget<Libp2pEvents>
17
+ logger: ComponentLogger
14
18
  }
15
19
 
16
20
  /**
@@ -18,48 +22,34 @@ export interface CircuitRelayTransportComponents extends RelayDiscoveryComponent
18
22
  */
19
23
  export interface CircuitRelayTransportInit extends RelayStoreInit {
20
24
  /**
21
- * The number of peers running diable relays to search for and connect to
22
- *
23
- * @default 0
25
+ * The number of peers running diable relays to search for and
26
+ * connect to. (default: 0)
24
27
  */
25
28
  discoverRelays?: number
26
29
 
27
- /**
28
- * An optional filter used to prevent duplicate attempts to reserve relay
29
- * slots on the same peer
30
- */
31
- discoveryFilter?: TopologyFilter
32
-
33
30
  /**
34
31
  * The maximum number of simultaneous STOP inbound streams that can be open at
35
- * once - each inbound relayed connection uses a STOP stream
36
- *
37
- * @default 300
32
+ * once - each inbound relayed connection uses a STOP stream (default: 300)
38
33
  */
39
34
  maxInboundStopStreams?: number
40
35
 
41
36
  /**
42
- * The maximum number of simultaneous STOP outbound streams that can be open
43
- * at once. If this transport is used along with the relay server these
44
- * settings should be set to the same value
45
- *
46
- * @default 300
37
+ * The maximum number of simultaneous STOP outbound streams that can be open at
38
+ * once. If this transport is used along with the relay server these settings
39
+ * should be set to the same value (default: 300)
47
40
  */
48
41
  maxOutboundStopStreams?: number
49
42
 
50
43
  /**
51
- * Incoming STOP requests (e.g. when a remote peer wants to dial us via a
52
- * relay) must finish the initial protocol negotiation within this timeout in
53
- * ms
54
- *
55
- * @default 30000
44
+ * Incoming STOP requests (e.g. when a remote peer wants to dial us via a relay)
45
+ * must finish the initial protocol negotiation within this timeout in ms
46
+ * (default: 30000)
56
47
  */
57
48
  stopTimeout?: number
58
49
 
59
50
  /**
60
51
  * When creating a reservation it must complete within this number of ms
61
- *
62
- * @default 10000
52
+ * (default: 10000)
63
53
  */
64
54
  reservationCompletionTimeout?: number
65
55
  }
@@ -1,17 +1,15 @@
1
- import { TypedEventEmitter, setMaxListeners } from '@libp2p/interface'
1
+ import { TypedEventEmitter } from '@libp2p/interface'
2
2
  import { PeerMap } from '@libp2p/peer-collections'
3
- import { createBloomFilter } from '@libp2p/utils/filters'
4
3
  import { PeerQueue } from '@libp2p/utils/peer-queue'
5
4
  import { multiaddr } from '@multiformats/multiaddr'
6
5
  import { pbStream } from 'it-protobuf-stream'
7
6
  import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
8
- import { DEFAULT_MAX_RESERVATION_QUEUE_LENGTH, DEFAULT_RESERVATION_COMPLETION_TIMEOUT, DEFAULT_RESERVATION_CONCURRENCY, RELAY_TAG, RELAY_V2_HOP_CODEC } from '../constants.js'
7
+ import { DEFAULT_RESERVATION_CONCURRENCY, RELAY_TAG, RELAY_V2_HOP_CODEC } from '../constants.js'
9
8
  import { HopMessage, Status } from '../pb/index.js'
10
9
  import { getExpirationMilliseconds } from '../utils.js'
11
10
  import type { Reservation } from '../pb/index.js'
12
11
  import type { TypedEventTarget, Libp2pEvents, AbortOptions, ComponentLogger, Logger, Connection, PeerId, PeerStore, Startable, Metrics } from '@libp2p/interface'
13
12
  import type { ConnectionManager, TransportManager } from '@libp2p/interface-internal'
14
- import type { Filter } from '@libp2p/utils/filters'
15
13
 
16
14
  // allow refreshing a relay reservation if it will expire in the next 10 minutes
17
15
  const REFRESH_WINDOW = (60 * 1000) * 10
@@ -71,7 +69,6 @@ interface RelayEntry {
71
69
  export interface ReservationStoreEvents {
72
70
  'relay:not-enough-relays': CustomEvent
73
71
  'relay:removed': CustomEvent<PeerId>
74
- 'relay:created-reservation': CustomEvent<PeerId>
75
72
  }
76
73
 
77
74
  export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents> implements Startable {
@@ -87,7 +84,6 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
87
84
  private readonly reservationCompletionTimeout: number
88
85
  private started: boolean
89
86
  private readonly log: Logger
90
- private readonly relayFilter: Filter
91
87
 
92
88
  constructor (components: RelayStoreComponents, init?: RelayStoreInit) {
93
89
  super()
@@ -100,10 +96,9 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
100
96
  this.events = components.events
101
97
  this.reservations = new PeerMap()
102
98
  this.maxDiscoveredRelays = init?.discoverRelays ?? 0
103
- this.maxReservationQueueLength = init?.maxReservationQueueLength ?? DEFAULT_MAX_RESERVATION_QUEUE_LENGTH
104
- this.reservationCompletionTimeout = init?.reservationCompletionTimeout ?? DEFAULT_RESERVATION_COMPLETION_TIMEOUT
99
+ this.maxReservationQueueLength = init?.maxReservationQueueLength ?? 100
100
+ this.reservationCompletionTimeout = init?.reservationCompletionTimeout ?? 10000
105
101
  this.started = false
106
- this.relayFilter = createBloomFilter(100)
107
102
 
108
103
  // ensure we don't listen on multiple relays simultaneously
109
104
  this.reserveQueue = new PeerQueue({
@@ -128,13 +123,6 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
128
123
  this.started = true
129
124
  }
130
125
 
131
- afterStart (): void {
132
- if (this.reservations.size < this.maxDiscoveredRelays) {
133
- this.log('not enough relays %d/%d', this.reservations.size, this.maxDiscoveredRelays)
134
- this.safeDispatchEvent('relay:not-enough-relays', {})
135
- }
136
- }
137
-
138
126
  stop (): void {
139
127
  this.reserveQueue.clear()
140
128
  this.reservations.forEach(({ timeout }) => {
@@ -146,9 +134,9 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
146
134
 
147
135
  /**
148
136
  * If the number of current relays is beneath the configured `maxReservations`
149
- * value, and the passed peer id is not our own, and we have a non-relayed
150
- * connection to the remote, and the remote peer speaks the hop protocol, try
151
- * to reserve a slot on the remote peer
137
+ * value, and the passed peer id is not our own, and we have a non-relayed connection
138
+ * to the remote, and the remote peer speaks the hop protocol, try to reserve a slot
139
+ * on the remote peer
152
140
  */
153
141
  async addRelay (peerId: PeerId, type: RelayType): Promise<void> {
154
142
  if (this.peerId.equals(peerId)) {
@@ -157,25 +145,18 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
157
145
  }
158
146
 
159
147
  if (this.reserveQueue.size > this.maxReservationQueueLength) {
160
- this.log('not adding potential relay peer %p as the queue is full', peerId)
148
+ this.log('not adding relay as the queue is full')
161
149
  return
162
150
  }
163
151
 
164
152
  if (this.reserveQueue.has(peerId)) {
165
- this.log('potential relay peer %p is already in the reservation queue', peerId)
166
- return
167
- }
168
-
169
- if (this.relayFilter.has(peerId.toBytes())) {
170
- this.log('potential relay peer %p has failed previously, not trying again', peerId, new Error('where').stack)
153
+ this.log('relay peer is already in the reservation queue')
171
154
  return
172
155
  }
173
156
 
174
- this.log('try to reserve relay slot with %p', peerId)
157
+ this.log('add relay %p', peerId)
175
158
 
176
159
  await this.reserveQueue.add(async () => {
177
- const start = Date.now()
178
-
179
160
  try {
180
161
  // allow refresh of an existing reservation if it is about to expire
181
162
  const existingReservation = this.reservations.get(peerId)
@@ -202,7 +183,6 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
202
183
  }
203
184
 
204
185
  const signal = AbortSignal.timeout(this.reservationCompletionTimeout)
205
- setMaxListeners(Infinity, signal)
206
186
 
207
187
  const connection = await this.connectionManager.openConnection(peerId, {
208
188
  signal
@@ -250,12 +230,8 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
250
230
 
251
231
  // listen on multiaddr that only the circuit transport is listening for
252
232
  await this.transportManager.listen([multiaddr(`/p2p/${peerId.toString()}/p2p-circuit`)])
253
-
254
- this.safeDispatchEvent('relay:created-reservation', {
255
- detail: peerId
256
- })
257
233
  } catch (err) {
258
- this.log.error('could not reserve slot on %p after %dms', peerId, Date.now() - start, err)
234
+ this.log.error('could not reserve slot on %p', peerId, err)
259
235
 
260
236
  // cancel the renewal timeout if it's been set
261
237
  const reservation = this.reservations.get(peerId)
@@ -266,9 +242,6 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
266
242
 
267
243
  // if listening failed, remove the reservation
268
244
  this.reservations.delete(peerId)
269
-
270
- // don't try this peer again
271
- this.relayFilter.add(peerId.toBytes())
272
245
  }
273
246
  }, {
274
247
  peerId
@@ -283,10 +256,6 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
283
256
  return this.reservations.get(peerId)?.reservation
284
257
  }
285
258
 
286
- reservationCount (): number {
287
- return this.reservations.size
288
- }
289
-
290
259
  async #createReservation (connection: Connection, options: AbortOptions): Promise<Reservation> {
291
260
  options.signal?.throwIfAborted()
292
261
 
@@ -301,12 +270,11 @@ export class ReservationStore extends TypedEventEmitter<ReservationStoreEvents>
301
270
  try {
302
271
  response = await hopstr.read(options)
303
272
  } catch (err: any) {
273
+ this.log.error('error parsing reserve message response from %p because', connection.remotePeer, err)
304
274
  stream.abort(err)
305
275
  throw err
306
276
  } finally {
307
- if (stream.status !== 'closed') {
308
- await stream.close(options)
309
- }
277
+ await stream.close()
310
278
  }
311
279
 
312
280
  if (response.status === Status.OK && (response.reservation != null)) {
@@ -1,12 +1,11 @@
1
- import { CodeError, start, stop } from '@libp2p/interface'
1
+ import { CodeError } from '@libp2p/interface'
2
2
  import { transportSymbol, type Transport, type CreateListenerOptions, type Listener, type Upgrader, type AbortOptions, type ComponentLogger, type Logger, type Connection, type Stream, type ConnectionGater, type PeerId, type PeerStore } from '@libp2p/interface'
3
- import { peerFilter } from '@libp2p/peer-collections'
4
3
  import { peerIdFromBytes, peerIdFromString } from '@libp2p/peer-id'
5
4
  import { streamToMaConnection } from '@libp2p/utils/stream-to-ma-conn'
6
5
  import * as mafmt from '@multiformats/mafmt'
7
6
  import { multiaddr } from '@multiformats/multiaddr'
8
7
  import { pbStream } from 'it-protobuf-stream'
9
- import { CIRCUIT_PROTO_CODE, DEFAULT_DISCOVERY_FILTER_ERROR_RATE, DEFAULT_DISCOVERY_FILTER_SIZE, ERR_HOP_REQUEST_FAILED, ERR_RELAYED_DIAL, MAX_CONNECTIONS, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC } from '../constants.js'
8
+ import { CIRCUIT_PROTO_CODE, ERR_HOP_REQUEST_FAILED, ERR_RELAYED_DIAL, MAX_CONNECTIONS, RELAY_V2_HOP_CODEC, RELAY_V2_STOP_CODEC } from '../constants.js'
10
9
  import { StopMessage, HopMessage, Status } from '../pb/index.js'
11
10
  import { RelayDiscovery } from './discovery.js'
12
11
  import { createListener } from './listener.js'
@@ -78,12 +77,8 @@ export class CircuitRelayTransport implements Transport {
78
77
  this.maxOutboundStopStreams = init.maxOutboundStopStreams ?? defaults.maxOutboundStopStreams
79
78
  this.stopTimeout = init.stopTimeout ?? defaults.stopTimeout
80
79
 
81
- const discoverRelays = init.discoverRelays ?? 0
82
-
83
- if (discoverRelays > 0) {
84
- this.discovery = new RelayDiscovery(components, {
85
- filter: init.discoveryFilter ?? peerFilter(DEFAULT_DISCOVERY_FILTER_SIZE, DEFAULT_DISCOVERY_FILTER_ERROR_RATE)
86
- })
80
+ if (init.discoverRelays != null && init.discoverRelays > 0) {
81
+ this.discovery = new RelayDiscovery(components)
87
82
  this.discovery.addEventListener('relay:discover', (evt) => {
88
83
  this.reservationStore.addRelay(evt.detail, 'discovered')
89
84
  .catch(err => {
@@ -94,12 +89,10 @@ export class CircuitRelayTransport implements Transport {
94
89
 
95
90
  this.reservationStore = new ReservationStore(components, init)
96
91
  this.reservationStore.addEventListener('relay:not-enough-relays', () => {
97
- this.discovery?.startDiscovery()
98
- })
99
- this.reservationStore.addEventListener('relay:created-reservation', () => {
100
- if (this.reservationStore.reservationCount() >= discoverRelays) {
101
- this.discovery?.stopDiscovery()
102
- }
92
+ this.discovery?.discover()
93
+ .catch(err => {
94
+ this.log.error('could not discover relays', err)
95
+ })
103
96
  })
104
97
 
105
98
  this.started = false
@@ -110,6 +103,8 @@ export class CircuitRelayTransport implements Transport {
110
103
  }
111
104
 
112
105
  async start (): Promise<void> {
106
+ this.reservationStore.start()
107
+
113
108
  await this.registrar.handle(RELAY_V2_STOP_CODEC, (data) => {
114
109
  void this.onStop(data).catch(err => {
115
110
  this.log.error('error while handling STOP protocol', err)
@@ -121,13 +116,18 @@ export class CircuitRelayTransport implements Transport {
121
116
  runOnTransientConnection: true
122
117
  })
123
118
 
124
- await start(this.discovery, this.reservationStore)
119
+ await this.discovery?.start()
125
120
 
126
121
  this.started = true
127
122
  }
128
123
 
124
+ afterStart (): void {
125
+ this.discovery?.afterStart()
126
+ }
127
+
129
128
  async stop (): Promise<void> {
130
- await stop(this.discovery, this.reservationStore)
129
+ this.discovery?.stop()
130
+ this.reservationStore.stop()
131
131
  await this.registrar.unhandle(RELAY_V2_STOP_CODEC)
132
132
 
133
133
  this.started = false
@@ -231,9 +231,9 @@ export class CircuitRelayTransport implements Transport {
231
231
  logger: this.logger
232
232
  })
233
233
 
234
- this.log('new outbound relayed connection %a', maConn.remoteAddr)
234
+ this.log('new outbound transient connection %a', maConn.remoteAddr)
235
235
  return await this.upgrader.upgradeOutbound(maConn, {
236
- transient: status.limit != null
236
+ transient: true
237
237
  })
238
238
  } catch (err: any) {
239
239
  this.log.error(`Circuit relay dial to destination ${destinationPeer.toString()} via relay ${connection.remotePeer.toString()} failed`, err)
@@ -346,9 +346,9 @@ export class CircuitRelayTransport implements Transport {
346
346
  logger: this.logger
347
347
  })
348
348
 
349
- this.log('new inbound relayed connection %a', maConn.remoteAddr)
349
+ this.log('new inbound transient connection %a', maConn.remoteAddr)
350
350
  await this.upgrader.upgradeInbound(maConn, {
351
- transient: request.limit != null
351
+ transient: true
352
352
  })
353
353
  this.log('%s connection %a upgraded', 'inbound', maConn.remoteAddr)
354
354
  }