Skip to content
This repository was archived by the owner on Jul 21, 2023. It is now read-only.

Commit 20d57b5

Browse files
authored
feat: adds custom multicodec protocol option (#206)
1 parent efd5e0f commit 20d57b5

File tree

6 files changed

+86
-12
lines changed

6 files changed

+86
-12
lines changed

README.md

+22
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,28 @@ See https://libp2p.github.io/js-libp2p-kad-dht for the auto generated docs.
4848

4949
The libp2p-kad-dht module offers 3 APIs: Peer Routing, Content Routing and Peer Discovery.
5050

51+
### Custom secondary DHT in libp2p
52+
53+
```js
54+
/**
55+
* @param {Libp2p} libp2p
56+
*/
57+
function addDHT(libp2p) {
58+
const customDHT = new KadDHT({
59+
libp2p,
60+
dialer: libp2p.dialer,
61+
peerId: libp2p.peerId,
62+
peerStore: libp2p.peerStore,
63+
registrar: libp2p.registrar,
64+
protocolPrefix: '/custom'
65+
})
66+
customDHT.start()
67+
customDHT.on('peer', libp2p._onDiscoveryPeer)
68+
return customDHT
69+
}
70+
```
71+
72+
Note that you may want to supply your own peer discovery function and datastore
5173
### Peer Routing
5274

5375
[![](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/src/peer-routing/img/badge.png)](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/peer-routing)

src/constants.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const hour = exports.hour = 60 * minute
1313

1414
exports.MAX_RECORD_AGE = 36 * hour
1515

16-
exports.PROTOCOL_DHT = '/ipfs/kad/1.0.0'
16+
exports.PROTOCOL_DHT = '/kad/1.0.0'
1717

1818
exports.PROVIDERS_KEY_PREFIX = '/providers/'
1919

src/index.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class KadDHT extends EventEmitter {
4747
* @param {function} props.registrar.handle
4848
* @param {function} props.registrar.register
4949
* @param {function} props.registrar.unregister
50+
* @param {string} [props.protocolPrefix = '/ipfs'] libp2p registrar handle protocol
51+
* @param {boolean} [props.forceProtocolLegacy = false] WARNING: this is not recommended and should only be used for legacy purposes
5052
* @param {number} props.kBucketSize k-bucket size (default 20)
5153
* @param {boolean} props.clientMode If true, the DHT will not respond to queries. This should be true if your node will not be dialable. (default: false)
5254
* @param {number} props.concurrency alpha concurrency of queries (default 3)
@@ -63,6 +65,8 @@ class KadDHT extends EventEmitter {
6365
peerId,
6466
peerStore,
6567
registrar,
68+
protocolPrefix = '/ipfs',
69+
forceProtocolLegacy = false,
6670
datastore = new MemoryDatastore(),
6771
kBucketSize = c.K,
6872
clientMode = false,
@@ -109,6 +113,12 @@ class KadDHT extends EventEmitter {
109113
*/
110114
this.registrar = registrar
111115

116+
/**
117+
* Registrar protocol
118+
* @type {string}
119+
*/
120+
this.protocol = protocolPrefix + (forceProtocolLegacy ? '' : c.PROTOCOL_DHT)
121+
112122
/**
113123
* k-bucket size
114124
*
@@ -553,4 +563,4 @@ class KadDHT extends EventEmitter {
553563
}
554564

555565
module.exports = KadDHT
556-
module.exports.multicodec = c.PROTOCOL_DHT
566+
module.exports.multicodec = '/ipfs' + c.PROTOCOL_DHT

src/network.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ class Network {
5050
// Only respond to queries when not in client mode
5151
if (this.dht._clientMode === false) {
5252
// Incoming streams
53-
this.dht.registrar.handle(c.PROTOCOL_DHT, this._rpc)
53+
this.dht.registrar.handle(this.dht.protocol, this._rpc)
5454
}
5555

5656
// register protocol with topology
5757
const topology = new MulticodecTopology({
58-
multicodecs: [c.PROTOCOL_DHT],
58+
multicodecs: [this.dht.protocol],
5959
handlers: {
6060
onConnect: this._onPeerConnected,
6161
onDisconnect: () => {}
@@ -129,7 +129,7 @@ class Network {
129129
conn = await this.dht.dialer.connectToPeer(to)
130130
}
131131

132-
const { stream } = await conn.newStream(c.PROTOCOL_DHT)
132+
const { stream } = await conn.newStream(this.dht.protocol)
133133

134134
return this._writeReadMessage(stream, msg.serialize())
135135
}
@@ -153,7 +153,7 @@ class Network {
153153
if (!conn) {
154154
conn = await this.dht.dialer.connectToPeer(to)
155155
}
156-
const { stream } = await conn.newStream(c.PROTOCOL_DHT)
156+
const { stream } = await conn.newStream(this.dht.protocol)
157157

158158
return this._writeMessage(stream, msg.serialize())
159159
}

test/kad-dht.spec.js

+41
Original file line numberDiff line numberDiff line change
@@ -957,5 +957,46 @@ describe('KadDHT', () => {
957957
}
958958
throw new Error('get should handle correctly an invalid record error and return not found')
959959
})
960+
961+
it('should not find peers with different protocols', async function () {
962+
this.timeout(40 * 1000)
963+
964+
const protocol1 = '/test1'
965+
const protocol2 = '/test2'
966+
967+
const tdht = new TestDHT()
968+
const dhts = []
969+
dhts.push(...await tdht.spawn(2, { protocolPrefix: protocol1 }))
970+
dhts.push(...await tdht.spawn(2, { protocolPrefix: protocol2 }))
971+
972+
// Connect all
973+
await Promise.all([
974+
tdht.connect(dhts[0], dhts[1]),
975+
tdht.connect(dhts[1], dhts[2]),
976+
tdht.connect(dhts[2], dhts[3])
977+
])
978+
979+
try {
980+
const ids = dhts.map((d) => d.peerId)
981+
await dhts[0].findPeer(ids[3], { timeout: 1000 })
982+
} catch (err) {
983+
expect(err).to.exist()
984+
expect(err.code).to.eql('ERR_NOT_FOUND')
985+
return tdht.teardown()
986+
}
987+
throw new Error('seperate protocols should have their own topologies and communication streams')
988+
})
989+
990+
it('force legacy protocol', async function () {
991+
this.timeout(40 * 1000)
992+
993+
const protocol = '/test/dht/0.0.0'
994+
995+
const tdht = new TestDHT()
996+
const [dht] = await tdht.spawn(1, { protocolPrefix: protocol, forceProtocolLegacy: true })
997+
998+
expect(dht.protocol).to.eql(protocol)
999+
return tdht.teardown()
1000+
})
9601001
})
9611002
})

test/utils/test-dht.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class TestDHT {
3535
randomWalk: {
3636
enabled: false
3737
},
38+
protocolPrefix: '/ipfs',
3839
...options
3940
}
4041

@@ -46,10 +47,10 @@ class TestDHT {
4647
(node) => node.peerId.toB58String() === remotePeerB58
4748
)
4849

49-
const localOnConnect = regRecord[PROTOCOL_DHT].onConnect
50-
const remoteOnConnect = remoteDht.regRecord[PROTOCOL_DHT].onConnect
50+
const localOnConnect = regRecord[options.protocolPrefix + PROTOCOL_DHT].onConnect
51+
const remoteOnConnect = remoteDht.regRecord[options.protocolPrefix + PROTOCOL_DHT].onConnect
5152

52-
const remoteHandler = remoteDht.regRecord[PROTOCOL_DHT].handler
53+
const remoteHandler = remoteDht.regRecord[options.protocolPrefix + PROTOCOL_DHT].handler
5354

5455
// Notice peers of connection
5556
const [c0, c1] = ConnectionPair()
@@ -65,7 +66,7 @@ class TestDHT {
6566
if (!localDHT._clientMode) await remoteOnConnect(peerId, c0)
6667

6768
await remoteHandler({
68-
protocol: PROTOCOL_DHT,
69+
protocol: options.protocolPrefix + PROTOCOL_DHT,
6970
stream: c0.stream,
7071
connection: {
7172
remotePeer: peerId
@@ -116,8 +117,8 @@ class TestDHT {
116117
}
117118

118119
async connect (dhtA, dhtB) {
119-
const onConnectA = dhtA.regRecord[PROTOCOL_DHT].onConnect
120-
const onConnectB = dhtB.regRecord[PROTOCOL_DHT].onConnect
120+
const onConnectA = dhtA.regRecord[dhtA.protocol].onConnect
121+
const onConnectB = dhtB.regRecord[dhtB.protocol].onConnect
121122

122123
const [c0, c1] = ConnectionPair()
123124

0 commit comments

Comments
 (0)