Skip to content

Commit afaee4c

Browse files
authored
fix: accept two incoming PING streams per peer (#1617)
Modify the default configuration for the PING protocol to accept at most two streams per peer, as recommended in the PING protocol spec. Signed-off-by: Miroslav Bajtoš <oss@bajtos.net>
1 parent 4e01f48 commit afaee4c

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/config.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ const DefaultConfig: Partial<Libp2pInit> = {
7979
},
8080
ping: {
8181
protocolPrefix: 'ipfs',
82-
maxInboundStreams: 1,
82+
// See https://github.com/libp2p/specs/blob/d4b5fb0152a6bb86cfd9ea/ping/ping.md?plain=1#L38-L43
83+
// The dialing peer MUST NOT keep more than one outbound stream for the ping protocol per peer.
84+
// The listening peer SHOULD accept at most two streams per peer since cross-stream behavior is
85+
// non-linear and stream writes occur asynchronously. The listening peer may perceive the
86+
// dialing peer closing and opening the wrong streams (for instance, closing stream B and
87+
// opening stream A even though the dialing peer is opening stream B and closing stream A).
88+
maxInboundStreams: 2,
8389
maxOutboundStreams: 1,
8490
timeout: 10000
8591
},

test/ping/ping.node.ts

+30
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,34 @@ describe('ping', () => {
7575

7676
defer.resolve()
7777
})
78+
79+
it('allows two incoming streams from the same peer', async () => {
80+
const remote = nodes[0]
81+
const client = await createNode({
82+
config: createBaseOptions({
83+
ping: {
84+
// Allow two outbound ping streams.
85+
// It is not allowed by the spec, but this test needs to open two concurrent streams.
86+
maxOutboundStreams: 2
87+
}
88+
})
89+
})
90+
await client.components.peerStore.addressBook.set(remote.peerId, remote.getMultiaddrs())
91+
// register our new node for shutdown after the test finishes
92+
// otherwise the Mocha/Node.js process never finishes
93+
nodes.push(client)
94+
95+
// Send two ping requests in parallel, this should open two concurrent streams
96+
const results = await Promise.allSettled([
97+
client.ping(remote.peerId),
98+
client.ping(remote.peerId)
99+
])
100+
101+
// Verify that the remote peer accepted both inbound streams
102+
expect(results.map(describe)).to.deep.equal(['fulfilled', 'fulfilled'])
103+
104+
function describe (result: PromiseSettledResult<number>): string {
105+
return result.status === 'fulfilled' ? result.status : result.reason ?? result.status
106+
}
107+
})
78108
})

0 commit comments

Comments
 (0)