Skip to content

Commit 0d326d1

Browse files
authored
fix: emit 'listening' when relays change (#2758)
To signal to the rest of libp2p that our addresses are changing, emit the `listening` event when relays go away or our reservation expires. Also remove the old tags on startup to ensure we don't reconnect to old relays as the spec says the reservation is only valid while we are connected.
1 parent 29b47ad commit 0d326d1

File tree

13 files changed

+298
-143
lines changed

13 files changed

+298
-143
lines changed

packages/integration-tests/test/circuit-relay.node.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -624,15 +624,16 @@ describe('circuit-relay', () => {
624624
return circuitMultiaddrs.length > 0
625625
})
626626

627-
expect(circuitListener[0].relayStore.listenerCount('relay:removed')).to.equal(2)
627+
expect(circuitListener[0].reservationStore.listenerCount('relay:removed')).to.equal(2)
628628

629-
// remove one listener
630-
await local.hangUp(relay1.peerId)
629+
// stop the listener
630+
await circuitListener[0].close()
631631

632+
// not using the relay any more
632633
await notUsingAsRelay(local, relay1)
633634

634635
// expect 1 listener
635-
expect(circuitListener[0].relayStore.listenerCount('relay:removed')).to.equal(1)
636+
expect(circuitListener[0].reservationStore.listenerCount('relay:removed')).to.equal(1)
636637
})
637638

638639
it('should mark an outgoing relayed connection as limited', async () => {

packages/interface/src/index.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,10 @@ export interface Libp2pEvents<T extends ServiceMap = ServiceMap> {
161161
'peer:connect': CustomEvent<PeerId>
162162

163163
/**
164-
* This event will be triggered any time we are disconnected from another peer, regardless of
165-
* the circumstances of that disconnection. If we happen to have multiple connections to a
166-
* peer, this event will **only** be triggered when the last connection is closed.
164+
* This event will be triggered any time we are disconnected from another
165+
* peer, regardless of the circumstances of that disconnection. If we happen
166+
* to have multiple connections to a peer, this event will **only** be
167+
* triggered when the last connection is closed.
167168
*
168169
* @example
169170
*
@@ -177,9 +178,26 @@ export interface Libp2pEvents<T extends ServiceMap = ServiceMap> {
177178
'peer:disconnect': CustomEvent<PeerId>
178179

179180
/**
180-
* This event is dispatched after a remote peer has successfully responded to the identify
181-
* protocol. Note that for this to be emitted, both peers must have an identify service
182-
* configured.
181+
* When a peer tagged with `keep-alive` disconnects, we will make multiple
182+
* attempts to reconnect to it with a backoff factor (see the connection
183+
* manager settings for details). If these all fail, the `keep-alive` tag will
184+
* be removed and this event will be emitted.
185+
*
186+
* @example
187+
*
188+
* ```TypeScript
189+
* libp2p.addEventListener('peer:reconnect-failure', (event) => {
190+
* const peerId = event.detail
191+
* // ...
192+
* })
193+
* ```
194+
*/
195+
'peer:reconnect-failure': CustomEvent<PeerId>
196+
197+
/**
198+
* This event is dispatched after a remote peer has successfully responded to
199+
* the identify protocol. Note that for this to be emitted, both peers must
200+
* have an identify service configured.
183201
*
184202
* @example
185203
*

packages/libp2p/src/connection-manager/reconnect-queue.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export class ReconnectQueue implements Startable {
3333
private readonly retryInterval?: number
3434
private readonly backoffFactor?: number
3535
private readonly connectionManager: ConnectionManager
36+
private readonly events: TypedEventTarget<Libp2pEvents>
3637

3738
constructor (components: ReconnectQueueComponents, init: ReconnectQueueInit = {}) {
3839
this.log = components.logger.forComponent('libp2p:reconnect-queue')
@@ -47,11 +48,12 @@ export class ReconnectQueue implements Startable {
4748
this.retries = init.retries ?? 5
4849
this.backoffFactor = init.backoffFactor
4950
this.retryInterval = init.retryInterval
51+
this.events = components.events
5052

5153
components.events.addEventListener('peer:disconnect', (evt) => {
5254
this.maybeReconnect(evt.detail)
5355
.catch(err => {
54-
this.log.error('failed to maybe reconnect to %p', evt.detail, err)
56+
this.log.error('failed to maybe reconnect to %p - %e', evt.detail, err)
5557
})
5658
})
5759
}
@@ -82,7 +84,7 @@ export class ReconnectQueue implements Startable {
8284
signal: options?.signal
8385
})
8486
} catch (err) {
85-
this.log('reconnecting to %p attempt %d of %d failed', peerId, attempt, this.retries, err)
87+
this.log('reconnecting to %p attempt %d of %d failed - %e', peerId, attempt, this.retries, err)
8688
throw err
8789
}
8890
}, {
@@ -108,6 +110,10 @@ export class ReconnectQueue implements Startable {
108110
await this.peerStore.merge(peerId, {
109111
tags
110112
})
113+
114+
this.events.safeDispatchEvent('peer:reconnect-failure', {
115+
detail: peerId
116+
})
111117
})
112118
.catch(async err => {
113119
this.log.error('failed to remove keep-alive tag from %p - %e', peerId, err)

packages/transport-circuit-relay-v2/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
"it-protobuf-stream": "^1.1.3",
6565
"it-stream-types": "^2.0.1",
6666
"multiformats": "^13.1.0",
67-
"p-defer": "^4.0.1",
6867
"progress-events": "^1.0.0",
6968
"protons-runtime": "^5.4.0",
7069
"race-signal": "^1.0.2",

packages/transport-circuit-relay-v2/src/constants.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ export const DEFAULT_MAX_RESERVATION_TTL = 2 * 60 * minute
2929
export const DEFAULT_RESERVATION_CONCURRENCY = 1
3030

3131
/**
32-
* How long to wait for a reservation attempt to finsih
32+
* How long to wait for a reservation attempt to finish
3333
*/
34-
export const DEFAULT_RESERVATION_COMPLETION_TIMEOUT = 1000
34+
export const DEFAULT_RESERVATION_COMPLETION_TIMEOUT = 2000
3535

3636
/**
3737
* How long to let the reservation attempt queue to grow
@@ -43,6 +43,7 @@ export const RELAY_SOURCE_TAG = 'circuit-relay-source'
4343
export const RELAY_TAG = 'circuit-relay-relay'
4444

4545
export const KEEP_ALIVE_TAG = `${KEEP_ALIVE}-circuit-relay`
46+
export const KEEP_ALIVE_SOURCE_TAG = `${KEEP_ALIVE}-circuit-relay-source`
4647

4748
// circuit v2 connection limits
4849
// https://github.com/libp2p/go-libp2p/blob/master/p2p/protocol/circuitv2/relay/resources.go#L61-L66

packages/transport-circuit-relay-v2/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ export interface CircuitRelayService extends TypedEventEmitter<CircuitRelayServi
6464

6565
export { circuitRelayServer } from './server/index.js'
6666
export type { CircuitRelayServerInit, CircuitRelayServerComponents } from './server/index.js'
67-
export type { ReservationStoreInit } from './server/reservation-store.js'
67+
export type { ReservationStoreInit as ServerReservationStoreInit } from './server/reservation-store.js'
6868
export { circuitRelayTransport } from './transport/index.js'
6969
export type { RelayDiscoveryComponents } from './transport/discovery.js'
70-
export type { RelayStoreInit } from './transport/reservation-store.js'
70+
export type { ReservationStoreInit as TransportReservationStoreInit } from './transport/reservation-store.js'
7171
export type { CircuitRelayTransportInit, CircuitRelayTransportComponents } from './transport/index.js'
7272

7373
export {

0 commit comments

Comments
 (0)