Skip to content

Commit

Permalink
chore: cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed Jul 15, 2020
1 parent ebb22d1 commit 5931f0e
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 63 deletions.
8 changes: 2 additions & 6 deletions LIBP2P.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Rendezvous Protocol in js-libp2p

The rendezvous protocol can be used in different contexts across libp2p. For using it, the libp2p network needs to have well known libp2p nodes acting as rendezvous servers. These nodes will have an extra role in the network. They will collect and maintain a list of registrations per rendezvous namespace. Other peers in the network will act as rendezvous clients and will register themselves on given namespaces by messaging a rendezvous server node. Taking into account these registrations, a rendezvous client is able to discover other peers in a given namespace by querying a server.
The rendezvous protocol can be used in different contexts across libp2p. For using it, the libp2p network needs to have well known libp2p nodes acting as rendezvous servers. These nodes will have an extra role in the network. They will collect and maintain a list of registrations per rendezvous namespace. Other peers in the network will act as rendezvous clients and will register themselves on given namespaces by messaging a rendezvous server node. Taking into account these registrations, a rendezvous client is able to discover other peers in a given namespace by querying a server. A registration should have a `ttl`, in order to avoid having invalid registrations.

## Usage

`js-libp2p` supports the usage of the rendezvous protocol through its configuration. It allows to enable the rendezvous protocol, as well as its server mode, enable automatic peer discover and to specify the topics to register from startup.
`js-libp2p` supports the usage of the rendezvous protocol through its configuration. It allows the rendezvous protocol to be enabled, as well as its server mode. In addition automatic peer discovery can be enabled and namespaces to register can be specified from startup through the config.

The rendezvous comes with a discovery service that enables libp2p to automatically discover other peers in the provided namespaces and eventually connect to them.

Expand Down Expand Up @@ -40,7 +40,3 @@ If the discovery service is disabled, the rendezvous API should allow users to d
When a libp2p node running the rendezvous protocol is going to stop, it should unregister from all the namespaces previously registered.

In the event of a rendezvous client getting connected to a second rendezvous server, it should propagate its registrations to it. The rendezvous server should clean its registrations for a peer when it is not connected with it anymore.

## Other notes:

After a query is made, who is responsible for determining if we need more records? (cookie reuse)
56 changes: 52 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,67 @@ See https://github.com/libp2p/specs/tree/master/rendezvous for more details

## API

### constructor

Creating an instance of Rendezvous.

`const rendezvous = new Rendezvous({ libp2p })`

#### Parameters

| Name | Type | Description |
|------|------|-------------|
| params | `object` | rendezvous parameters |
| params.libp2p | `Libp2p` | a libp2p node instance |
| params.namespaces | `Array<string>` | namespaces to keep registering and discovering over time (default: `[]`) |
| params.server | `object` | rendezvous server options |
| params.server.enabled | `boolean` | rendezvous server enabled (default: `true`) |
| params.server.gcInterval | `number` | rendezvous garbage collector interval (default: `3e5`) |
| params.discovery | `object` | rendezvous peer discovery options |
| params.discovery.interval | `number` | automatic rendezvous peer discovery interval (default: `5e3`) |

### rendezvous.start

Register the rendezvous protocol topology into libp2p and starts its internal services. The rendezvous server will be started if enabled, as well as the service to keep self registrations available.

`rendezvous.start()`

When registering to new namespaces from the API, the new namespace will be added to the registrations to keep by default.

### rendezvous.stop

Unregister the rendezvous protocol and the streams with other peers will be closed.

`rendezvous.stop()`

### rendezvous.discovery.start

Starts the rendezvous automatic discovery service.

`rendezvous.discovery.start()`

Like other libp2p discovery protocols, it will emit `peer` events when new peers are discovered.

### rendezvous.discovery.stop

Stops the rendezvous automatic discovery service.

`rendezvous.discovery.stop()`

### rendezvous.register

Registers the peer in a given namespace.

`rendezvous.register(namespace, [ttl])`
`rendezvous.register(namespace, [options])`

#### Parameters

| Name | Type | Description |
|------|------|-------------|
| namespace | `string` | namespace to register |
| ttl | `number` | registration ttl in ms (default: `7200e3` and minimum `120`) |
| options | `object` | rendezvous registrations options |
| options.ttl | `number` | registration ttl in ms (default: `7200e3` and minimum `120`) |
| options.keep | `boolean` | register over time to guarantee availability (default: `true`) |

#### Returns

Expand Down Expand Up @@ -75,15 +124,14 @@ await rendezvous.unregister(namespace)

Discovers peers registered under a given namespace.

`rendezvous.discover(namespace, [limit], [cookie])`
`rendezvous.discover(namespace, [limit])`

#### Parameters

| Name | Type | Description |
|------|------|-------------|
| namespace | `string` | namespace to discover |
| limit | `number` | limit of peers to discover |
| cookie | `Buffer` | |

#### Returns

Expand Down
23 changes: 16 additions & 7 deletions src/discovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ log.error = debug('libp2p:redezvous:discovery:error')

const { EventEmitter } = require('events')

const { codes: errCodes } = require('./errors')

const defaultOptions = {
interval: 5000
interval: 5e3
}

/**
Expand Down Expand Up @@ -57,12 +59,19 @@ class Discovery extends EventEmitter {
*/
_discover () {
this._rendezvous._namespaces.forEach(async (ns) => {
for await (const reg of this._rendezvous.discover(ns)) {
// TODO: interface-peer-discovery with signedPeerRecord
this.emit('peer', {
id: reg.id,
multiaddrs: reg.multiaddrs
})
try {
for await (const reg of this._rendezvous.discover(ns)) {
// TODO: interface-peer-discovery with signedPeerRecord
this.emit('peer', {
id: reg.id,
multiaddrs: reg.multiaddrs
})
}
} catch (err) {
// It will fail while there are no connected rendezvous servers
if (err.code !== errCodes.NO_CONNECTED_RENDEZVOUS_SERVERS) {
throw err
}
}
})
}
Expand Down
43 changes: 24 additions & 19 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,24 @@ class Rendezvous {
* @constructor
* @param {object} params
* @param {Libp2p} params.libp2p
* @param {object} params.options
* @param {Array<string>} [params.namespaces = []]
* @param {object} [params.discovery]
* @param {number} [params.discovery.interval = 5000]
* @param {number} [params.discovery.interval = 5e3]
* @param {object} [params.server]
* @param {boolean} [params.server.enabled = true]
* @param {number} [params.server.gcInterval = 3e5]
*/
constructor ({ libp2p, options = {} }) {
constructor ({ libp2p, namespaces = [], discovery = {}, server = {} }) {
this._libp2p = libp2p
this._peerId = libp2p.peerId
this._registrar = libp2p.registrar

this._namespaces = options.namespaces || []
this.discovery = new Discovery(this, options.discovery)
this._namespaces = namespaces
this.discovery = new Discovery(this, discovery)

this._serverOptions = {
...defaultServerOptions,
...options.server || {}
...server
}

/**
Expand All @@ -84,9 +83,9 @@ class Rendezvous {

/**
* Register the rendezvous protocol in the libp2p node.
* @returns {Promise<void>}
* @returns {void}
*/
async start () {
start () {
if (this._registrarId) {
return
}
Expand All @@ -107,18 +106,17 @@ class Rendezvous {
onDisconnect: this._onPeerDisconnected
}
})
this._registrarId = await this._registrar.register(topology)

log('started')
this._registrarId = this._registrar.register(topology)

this._keepRegistrations()
log('started')
}

/**
* Unregister the rendezvous protocol and the streams with other peers will be closed.
* @returns {Promise<void>}
* @returns {void}
*/
async stop () {
stop () {
if (!this._registrarId) {
return
}
Expand All @@ -128,7 +126,7 @@ class Rendezvous {
clearInterval(this._interval)

// unregister protocol and handlers
await this._registrar.unregister(this._registrarId)
this._registrar.unregister(this._registrarId)
if (this._serverOptions.enabled) {
this._server.stop()
}
Expand All @@ -153,7 +151,7 @@ class Rendezvous {
const promises = []

this._namespaces.forEach((ns) => {
promises.push(this.register(ns))
promises.push(this.register(ns, { keep: false }))
})

return Promise.all(promises)
Expand Down Expand Up @@ -195,10 +193,12 @@ class Rendezvous {
/**
* Register the peer in a given namespace
* @param {string} ns
* @param {number} [ttl = 7200e3] registration ttl in ms (minimum 120)
* @returns {Promise<number>}
* @param {object} [options]
* @param {number} [options.ttl = 7200e3] registration ttl in ms (minimum 120)
* @param {number} [options.keep = true] register over time to guarantee availability.
* @returns {Promise<number>} rendezvous register ttl.
*/
async register (ns, ttl = 7200e3) {
async register (ns, { ttl = 7200e3, keep = true } = {}) {
if (!ns) {
throw errCode(new Error('a namespace must be provided'), errCodes.INVALID_NAMESPACE)
}
Expand Down Expand Up @@ -253,7 +253,7 @@ class Rendezvous {
throw new Error('unexpected message received')
}

return recMessage.registerResponse.ttl
return recMessage.registerResponse.ttl // TODO: convert to ms
}

for (const id of this._rendezvousPoints.keys()) {
Expand All @@ -262,6 +262,10 @@ class Rendezvous {

// Return first ttl
const [returnTtl] = await Promise.all(registerTasks)

// Keep registering if enabled
keep && this._namespaces.push(ns)

return returnTtl
}

Expand Down Expand Up @@ -307,6 +311,7 @@ class Rendezvous {
unregisterTasks.push(taskFn(id))
}

this._namespaces.filter((keeptNampesace) => keeptNampesace !== ns)
await Promise.all(unregisterTasks)
}

Expand Down
12 changes: 5 additions & 7 deletions test/client-mode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('client mode', () => {

afterEach(async () => {
peer && await peer.stop()
rendezvous && await rendezvous.stop()
rendezvous && rendezvous.stop()
})

it('registers a rendezvous handler by default', async () => {
Expand All @@ -25,7 +25,7 @@ describe('client mode', () => {

const spyHandle = sinon.spy(peer.registrar, '_handle')

await rendezvous.start()
rendezvous.start()

expect(spyHandle).to.have.property('callCount', 1)
})
Expand All @@ -34,16 +34,14 @@ describe('client mode', () => {
[peer] = await createPeer()
rendezvous = new Rendezvous({
libp2p: peer,
options: {
server: {
enabled: false
}
server: {
enabled: false
}
})

const spyHandle = sinon.spy(peer.registrar, '_handle')

await rendezvous.start()
rendezvous.start()
expect(spyHandle).to.have.property('callCount', 0)
})
})
26 changes: 11 additions & 15 deletions test/discovery.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@ describe('rendezvous discovery', () => {
peers.forEach((peer, index) => {
const rendezvous = new Rendezvous({
libp2p: peer,
options: {
discovery: {
interval: 1000
},
server: {
enabled: index === 0
}
discovery: {
interval: 1000
},
server: {
enabled: index === 0
}
})
rendezvous.start()
Expand Down Expand Up @@ -107,14 +105,12 @@ describe('interface-discovery', () => {
peers.forEach((peer, index) => {
const rendezvous = new Rendezvous({
libp2p: peer,
options: {
discovery: {
interval: 1000
},
namespaces: ['test-namespace'],
server: {
enabled: index === 0
}
discovery: {
interval: 1000
},
namespaces: ['test-namespace'],
server: {
enabled: index === 0
}
})
rendezvous.start()
Expand Down
8 changes: 3 additions & 5 deletions test/rendezvous.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@ describe('rendezvous', () => {
peers.forEach((peer, index) => {
const rendezvous = new Rendezvous({
libp2p: peer,
options: {
server: {
enabled: index !== 0
}
server: {
enabled: index !== 0
}
})
rendezvous.start()
Expand All @@ -95,7 +93,7 @@ describe('rendezvous', () => {
})

it('register throws error if ttl is too small', async () => {
await expect(peers[0].rendezvous.register(namespace, 10))
await expect(peers[0].rendezvous.register(namespace, { ttl: 10 }))
.to.eventually.rejected()
.and.have.property('code', errCodes.INVALID_TTL)
})
Expand Down

0 comments on commit 5931f0e

Please sign in to comment.