Skip to content

Commit

Permalink
fix: remove relay:removed event listener after relay is removed (#1998)
Browse files Browse the repository at this point in the history
When a relay is removed, also remove the event listener 

Closes #1944

Closes #2106

---------

Co-authored-by: Alex Potsides <alex@achingbrain.net>
  • Loading branch information
maschad and achingbrain authored Oct 25, 2023
1 parent ce0e38d commit ab2c1f6
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
10 changes: 7 additions & 3 deletions packages/libp2p/src/circuit-relay/transport/listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ class CircuitRelayTransportListener extends EventEmitter<ListenerEvents> impleme
this.listeningAddrs = new PeerMap()

// remove listening addrs when a relay is removed
this.relayStore.addEventListener('relay:removed', (evt) => {
this.#removeRelayPeer(evt.detail)
})
this.relayStore.addEventListener('relay:removed', this._onRemoveRelayPeer)
}

_onRemoveRelayPeer = (evt: CustomEvent<PeerId>): void => {
this.#removeRelayPeer(evt.detail)
}

async listen (addr: Multiaddr): Promise<void> {
Expand Down Expand Up @@ -100,6 +102,8 @@ class CircuitRelayTransportListener extends EventEmitter<ListenerEvents> impleme
this.listeningAddrs.delete(peerId)

if (had) {
log.trace('removing relay event listener for peer %p', peerId)
this.relayStore.removeEventListener('relay:removed', this._onRemoveRelayPeer)
// Announce listen addresses change
this.safeDispatchEvent('close', {})
}
Expand Down
33 changes: 31 additions & 2 deletions packages/libp2p/test/circuit-relay/relay.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { HopMessage, Status } from '../../src/circuit-relay/pb/index.js'
import { identifyService } from '../../src/identify/index.js'
import { createLibp2p, type Libp2pOptions } from '../../src/index.js'
import { plaintext } from '../../src/insecure/index.js'
import { discoveredRelayConfig, doesNotHaveRelay, getRelayAddress, hasRelay, usingAsRelay } from './utils.js'
import { discoveredRelayConfig, doesNotHaveRelay, getRelayAddress, hasRelay, notUsingAsRelay, usingAsRelay, usingAsRelayCount } from './utils.js'
import type { Components } from '../../src/components.js'
import type { Libp2p } from '@libp2p/interface'
import type { Connection } from '@libp2p/interface/connection'
Expand Down Expand Up @@ -354,7 +354,7 @@ describe('circuit-relay', () => {
transports: [
tcp(),
circuitRelayTransport({
discoverRelays: 1
discoverRelays: 3
})
]
}),
Expand Down Expand Up @@ -603,6 +603,35 @@ describe('circuit-relay', () => {
expect(events[1].detail.remotePeer.toString()).to.equal(relay1.peerId.toString())
})

it('should remove the relay event listener when the relay stops', async () => {
// discover relay and make reservation
await local.dial(relay1.getMultiaddrs()[0])
await local.dial(relay2.getMultiaddrs()[0])

await usingAsRelayCount(local, [relay1, relay2], 2)

// expect 2 listeners
// @ts-expect-error these are private fields
const listeners = local.components.transportManager.getListeners()

// @ts-expect-error as a result these will have any types
const circuitListener = listeners.filter(listener => {
// @ts-expect-error as a result these will have any types
const circuitMultiaddrs = listener.getAddrs().filter(ma => Circuit.matches(ma))
return circuitMultiaddrs.length > 0
})

expect(circuitListener[0].relayStore.listenerCount('relay:removed')).to.equal(2)

// remove one listener
await local.hangUp(relay1.peerId)

await notUsingAsRelay(local, relay1)

// expect 1 listener
expect(circuitListener[0].relayStore.listenerCount('relay:removed')).to.equal(1)
})

it('should mark a relayed connection as transient', async () => {
// discover relay and make reservation
const connectionToRelay = await remote.dial(relay1.getMultiaddrs()[0])
Expand Down
17 changes: 17 additions & 0 deletions packages/libp2p/test/circuit-relay/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@ export async function usingAsRelay (node: Libp2p, relay: Libp2p, opts?: PWaitFor
}, opts)
}

export async function usingAsRelayCount (node: Libp2p, relays: Libp2p[], count: number): Promise<void> {
// Wait for peer to be used as a relay
await pWaitFor(async () => {
let relayCount = 0

for (const relay of relays) {
for (const addr of node.getMultiaddrs()) {
const search = `${relay.peerId.toString()}/p2p-circuit`
if (addr.toString().includes(search)) {
relayCount++
}
}
}
return relayCount === count
})
}

export async function notUsingAsRelay (node: Libp2p, relay: Libp2p, opts?: PWaitForOptions<boolean>): Promise<void> {
// Wait for peer to be used as a relay
await pWaitFor(() => {
Expand Down

0 comments on commit ab2c1f6

Please sign in to comment.