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

Sign up to get free protection for your applications and to get access to all the features.
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
  }