Skip to content

Commit

Permalink
chore: store self protocols in protobook (#760)
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos authored Oct 27, 2020
1 parent 5246cf8 commit c9e6757
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 96 deletions.
77 changes: 51 additions & 26 deletions doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* [`peerStore.protoBook.add`](#peerstoreprotobookadd)
* [`peerStore.protoBook.delete`](#peerstoreprotobookdelete)
* [`peerStore.protoBook.get`](#peerstoreprotobookget)
* [`peerStore.protoBook.remove`](#peerstoreprotobookremove)
* [`peerStore.protoBook.set`](#peerstoreprotobookset)
* [`peerStore.delete`](#peerstoredelete)
* [`peerStore.get`](#peerstoreget)
Expand Down Expand Up @@ -843,32 +844,6 @@ Consider using `addressBook.add()` if you're not sure this is what you want to d
peerStore.addressBook.add(peerId, multiaddr)
```

### peerStore.protoBook.add

Add known `protocols` of a given peer.

`peerStore.protoBook.add(peerId, protocols)`

#### Parameters

| Name | Type | Description |
|------|------|-------------|
| peerId | [`PeerId`][peer-id] | peerId to set |
| protocols | `Array<string>` | protocols to add |

#### Returns

| Type | Description |
|------|-------------|
| `ProtoBook` | Returns the Proto Book component |

#### Example

```js
peerStore.protoBook.add(peerId, protocols)
```


### peerStore.keyBook.delete

Delete the provided peer from the book.
Expand Down Expand Up @@ -1091,6 +1066,31 @@ Set known metadata of a given `peerId`.
peerStore.metadataBook.set(peerId, 'location', uint8ArrayFromString('Berlin'))
```

### peerStore.protoBook.add

Add known `protocols` of a given peer.

`peerStore.protoBook.add(peerId, protocols)`

#### Parameters

| Name | Type | Description |
|------|------|-------------|
| peerId | [`PeerId`][peer-id] | peerId to set |
| protocols | `Array<string>` | protocols to add |

#### Returns

| Type | Description |
|------|-------------|
| `ProtoBook` | Returns the Proto Book component |

#### Example

```js
peerStore.protoBook.add(peerId, protocols)
```

### peerStore.protoBook.delete

Delete the provided peer from the book.
Expand Down Expand Up @@ -1147,6 +1147,31 @@ peerStore.protoBook.get(peerId)
// [ '/proto/1.0.0', '/proto/1.1.0' ]
```

### peerStore.protoBook.remove

Remove given `protocols` of a given peer.

`peerStore.protoBook.remove(peerId, protocols)`

#### Parameters

| Name | Type | Description |
|------|------|-------------|
| peerId | [`PeerId`][peer-id] | peerId to set |
| protocols | `Array<string>` | protocols to remove |

#### Returns

| Type | Description |
|------|-------------|
| `ProtoBook` | Returns the Proto Book component |

#### Example

```js
peerStore.protoBook.remove(peerId, protocols)
```

### peerStore.protoBook.set

Set known `protocols` of a given peer.
Expand Down
23 changes: 17 additions & 6 deletions src/identify/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,8 @@ class IdentifyService {
* @class
* @param {object} options
* @param {Libp2p} options.libp2p
* @param {Map<string, handler>} options.protocols - A reference to the protocols we support
*/
constructor ({ libp2p, protocols }) {
constructor ({ libp2p }) {
/**
* @property {PeerStore}
*/
Expand All @@ -74,10 +73,9 @@ class IdentifyService {
*/
this._libp2p = libp2p

this._protocols = protocols

this.handleMessage = this.handleMessage.bind(this)

// When a new connection happens, trigger identify
this.connectionManager.on('peer:connect', (connection) => {
const peerId = connection.remotePeer

Expand All @@ -90,6 +88,13 @@ class IdentifyService {
this.pushToPeerStore()
}
})

// When self protocols change, trigger identify-push
this.peerStore.on('change:protocols', ({ peerId }) => {
if (peerId.toString() === this.peerId.toString()) {
this.pushToPeerStore()
}
})
}

/**
Expand All @@ -101,7 +106,7 @@ class IdentifyService {
async push (connections) {
const signedPeerRecord = await this.peerStore.addressBook.getRawEnvelope(this.peerId)
const listenAddrs = this._libp2p.multiaddrs.map((ma) => ma.bytes)
const protocols = Array.from(this._protocols.keys())
const protocols = this.peerStore.protoBook.get(this.peerId) || []

const pushes = connections.map(async connection => {
try {
Expand Down Expand Up @@ -132,6 +137,11 @@ class IdentifyService {
* @returns {void}
*/
pushToPeerStore () {
// Do not try to push if libp2p node is not running
if (!this._libp2p.isStarted()) {
return
}

const connections = []
let connection
for (const peer of this.peerStore.peers.values()) {
Expand Down Expand Up @@ -251,6 +261,7 @@ class IdentifyService {
}

const signedPeerRecord = await this.peerStore.addressBook.getRawEnvelope(this.peerId)
const protocols = this.peerStore.protoBook.get(this.peerId) || []

const message = Message.encode({
protocolVersion: PROTOCOL_VERSION,
Expand All @@ -259,7 +270,7 @@ class IdentifyService {
listenAddrs: this._libp2p.multiaddrs.map((ma) => ma.bytes),
signedPeerRecord,
observedAddr: connection.remoteAddr.bytes,
protocols: Array.from(this._protocols.keys())
protocols
})

try {
Expand Down
17 changes: 5 additions & 12 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,7 @@ class Libp2p extends EventEmitter {
})

// Add the identify service since we can multiplex
this.identifyService = new IdentifyService({
libp2p: this,
protocols: this.upgrader.protocols
})
this.identifyService = new IdentifyService({ libp2p: this })
this.handle(Object.values(IDENTIFY_PROTOCOLS), this.identifyService.handleMessage)
}

Expand Down Expand Up @@ -436,10 +433,8 @@ class Libp2p extends EventEmitter {
this.upgrader.protocols.set(protocol, handler)
})

// Only push if libp2p is running
if (this.isStarted() && this.identifyService) {
this.identifyService.pushToPeerStore()
}
// Add new protocols to self protocols in the Protobook
this.peerStore.protoBook.add(this.peerId, protocols)
}

/**
Expand All @@ -454,10 +449,8 @@ class Libp2p extends EventEmitter {
this.upgrader.protocols.delete(protocol)
})

// Only push if libp2p is running
if (this.isStarted() && this.identifyService) {
this.identifyService.pushToPeerStore()
}
// Remove protocols from self protocols in the Protobook
this.peerStore.protoBook.remove(this.peerId, protocols)
}

async _onStarting () {
Expand Down
41 changes: 39 additions & 2 deletions src/peer-store/proto-book.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,50 @@ class ProtoBook extends Book {
return this
}

protocols = [...newSet]

this._setData(peerId, newSet)
log(`added provided protocols for ${id}`)

return this
}

/**
* Removes known protocols of a provided peer.
* If the protocols did not exist before, nothing will be done.
*
* @param {PeerId} peerId
* @param {Array<string>} protocols
* @returns {ProtoBook}
*/
remove (peerId, protocols) {
if (!PeerId.isPeerId(peerId)) {
log.error('peerId must be an instance of peer-id to store data')
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
}

if (!protocols) {
log.error('protocols must be provided to store data')
throw errcode(new Error('protocols must be provided'), ERR_INVALID_PARAMETERS)
}

const id = peerId.toB58String()
const recSet = this.data.get(id)

if (recSet) {
const newSet = new Set([
...recSet
].filter((p) => !protocols.includes(p)))

// Any protocol removed?
if (recSet.size === newSet.size) {
return this
}

this._setData(peerId, newSet)
log(`removed provided protocols for ${id}`)
}

return this
}
}

module.exports = ProtoBook
Loading

0 comments on commit c9e6757

Please sign in to comment.