mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-06-21 21:11:34 +00:00
refactor: add core modules to libp2p (#400)
* refactor: add js-libp2p-connection-manager to repo Co-authored-by: David Dias <daviddias.p@gmail.com> Co-authored-by: Jacob Heun <jacobheun@gmail.com> Co-authored-by: Pedro Teixeira <i@pgte.me> Co-authored-by: Vasco Santos <vasco.santos@ua.pt> * test(conn-mgr): only run in node * refactor: add js-libp2p-identify to repo Co-authored-by: David Dias <daviddias.p@gmail.com> Co-authored-by: Friedel Ziegelmayer <dignifiedquire@gmail.com> Co-authored-by: Hugo Dias <hugomrdias@gmail.com> Co-authored-by: Jacob Heun <jacobheun@gmail.com> Co-authored-by: Maciej Krüger <mkg20001@gmail.com> Co-authored-by: Richard Littauer <richard.littauer@gmail.com> Co-authored-by: Vasco Santos <vasco.santos@moxy.studio> Co-authored-by: Yusef Napora <yusef@protocol.ai> Co-authored-by: ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com> * refactor: add libp2p-pnet to repo Co-authored-by: Jacob Heun <jacobheun@gmail.com> Co-authored-by: Vasco Santos <vasco.santos@moxy.studio> * refactor: add libp2p-ping to repo Co-authored-by: David Dias <daviddias.p@gmail.com> Co-authored-by: Francisco Baio Dias <xicombd@gmail.com> Co-authored-by: Friedel Ziegelmayer <dignifiedquire@gmail.com> Co-authored-by: Hugo Dias <mail@hugodias.me> Co-authored-by: Jacob Heun <jacobheun@gmail.com> Co-authored-by: João Antunes <j.goncalo.antunes@gmail.com> Co-authored-by: Richard Littauer <richard.littauer@gmail.com> Co-authored-by: Vasco Santos <vasco.santos@moxy.studio> Co-authored-by: Vasco Santos <vasco.santos@ua.pt> Co-authored-by: ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com> * refactor: add libp2p-circuit to repo Co-authored-by: David Dias <daviddias.p@gmail.com> Co-authored-by: Dmitriy Ryajov <dryajov@gmail.com> Co-authored-by: Friedel Ziegelmayer <dignifiedquire@gmail.com> Co-authored-by: Hugo Dias <mail@hugodias.me> Co-authored-by: Jacob Heun <jacobheun@gmail.com> Co-authored-by: Maciej Krüger <mkg20001@gmail.com> Co-authored-by: Oli Evans <oli@tableflip.io> Co-authored-by: Pedro Teixeira <i@pgte.me> Co-authored-by: Vasco Santos <vasco.santos@ua.pt> Co-authored-by: Victor Bjelkholm <victorbjelkholm@gmail.com> Co-authored-by: Yusef Napora <yusef@napora.org> Co-authored-by: dirkmc <dirk@mccormick.cx> * test(switch): avoid using instanceof * chore(switch): update bignumber dep * refactor(circuit): clean up tests * refactor(switch): consolidate get peer utils * test(identify): do deep checks of addresses * test(identify): bump timeout for identify test * test(switch): tidy up limit dialer test * refactor(switch): remove redundant circuit tests * chore: add coverage script * refactor(circuit): consolidate get peer info * docs: reference original repositories in each sub readme * docs: fix comment * refactor: clean up sub package.json files and readmes
This commit is contained in:
37
src/identify/README.md
Normal file
37
src/identify/README.md
Normal file
@ -0,0 +1,37 @@
|
||||
# js-libp2p-identify
|
||||
|
||||
> libp2p Identify Protocol
|
||||
|
||||
**Note**: git history prior to merging into js-libp2p can be found in the original repository, https://github.com/libp2p/js-libp2p-identify.
|
||||
|
||||
## Description
|
||||
|
||||
Identify is a STUN protocol, used by libp2p-swarm in order to broadcast and learn about the `ip:port` pairs a specific peer is available through and to know when a new stream muxer is established, so a conn can be reused.
|
||||
|
||||
## How does it work
|
||||
|
||||
Best way to understand the current design is through this issue: https://github.com/libp2p/js-libp2p-swarm/issues/78
|
||||
|
||||
### This module uses `pull-streams`
|
||||
|
||||
We expose a streaming interface based on `pull-streams`, rather then on the Node.js core streams implementation (aka Node.js streams). `pull-streams` offers us a better mechanism for error handling and flow control guarantees. If you would like to know more about why we did this, see the discussion at this [issue](https://github.com/ipfs/js-ipfs/issues/362).
|
||||
|
||||
You can learn more about pull-streams at:
|
||||
|
||||
- [The history of Node.js streams, nodebp April 2014](https://www.youtube.com/watch?v=g5ewQEuXjsQ)
|
||||
- [The history of streams, 2016](http://dominictarr.com/post/145135293917/history-of-streams)
|
||||
- [pull-streams, the simple streaming primitive](http://dominictarr.com/post/149248845122/pull-streams-pull-streams-are-a-very-simple)
|
||||
- [pull-streams documentation](https://pull-stream.github.io/)
|
||||
|
||||
#### Converting `pull-streams` to Node.js Streams
|
||||
|
||||
If you are a Node.js streams user, you can convert a pull-stream to a Node.js stream using the module [`pull-stream-to-stream`](https://github.com/pull-stream/pull-stream-to-stream), giving you an instance of a Node.js stream that is linked to the pull-stream. For example:
|
||||
|
||||
```js
|
||||
const pullToStream = require('pull-stream-to-stream')
|
||||
|
||||
const nodeStreamInstance = pullToStream(pullStreamInstance)
|
||||
// nodeStreamInstance is an instance of a Node.js Stream
|
||||
```
|
||||
|
||||
To learn more about this utility, visit https://pull-stream.github.io/#pull-stream-to-stream.
|
87
src/identify/dialer.js
Normal file
87
src/identify/dialer.js
Normal file
@ -0,0 +1,87 @@
|
||||
'use strict'
|
||||
const PeerInfo = require('peer-info')
|
||||
const PeerId = require('peer-id')
|
||||
const multiaddr = require('multiaddr')
|
||||
const pull = require('pull-stream/pull')
|
||||
const take = require('pull-stream/throughs/take')
|
||||
const collect = require('pull-stream/sinks/collect')
|
||||
const lp = require('pull-length-prefixed')
|
||||
|
||||
const msg = require('./message')
|
||||
|
||||
module.exports = (conn, expectedPeerInfo, callback) => {
|
||||
if (typeof expectedPeerInfo === 'function') {
|
||||
callback = expectedPeerInfo
|
||||
expectedPeerInfo = null
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('WARNING: no expected peer info was given, identify will not be able to verify peer integrity')
|
||||
}
|
||||
|
||||
pull(
|
||||
conn,
|
||||
lp.decode(),
|
||||
take(1),
|
||||
collect((err, data) => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
// connection got closed graciously
|
||||
if (data.length === 0) {
|
||||
return callback(new Error('conn was closed, did not receive data'))
|
||||
}
|
||||
|
||||
const input = msg.decode(data[0])
|
||||
|
||||
PeerId.createFromPubKey(input.publicKey, (err, id) => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
const peerInfo = new PeerInfo(id)
|
||||
if (expectedPeerInfo && expectedPeerInfo.id.toB58String() !== id.toB58String()) {
|
||||
return callback(new Error('invalid peer'))
|
||||
}
|
||||
|
||||
try {
|
||||
input.listenAddrs
|
||||
.map(multiaddr)
|
||||
.forEach((ma) => peerInfo.multiaddrs.add(ma))
|
||||
} catch (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
let observedAddr
|
||||
|
||||
try {
|
||||
observedAddr = getObservedAddrs(input)
|
||||
} catch (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
// Copy the protocols
|
||||
peerInfo.protocols = new Set(input.protocols)
|
||||
|
||||
callback(null, peerInfo, observedAddr)
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
function getObservedAddrs (input) {
|
||||
if (!hasObservedAddr(input)) {
|
||||
return []
|
||||
}
|
||||
|
||||
let addrs = input.observedAddr
|
||||
|
||||
if (!Array.isArray(addrs)) {
|
||||
addrs = [addrs]
|
||||
}
|
||||
|
||||
return addrs.map((oa) => multiaddr(oa))
|
||||
}
|
||||
|
||||
function hasObservedAddr (input) {
|
||||
return input.observedAddr && input.observedAddr.length > 0
|
||||
}
|
7
src/identify/index.js
Normal file
7
src/identify/index.js
Normal file
@ -0,0 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
exports = module.exports
|
||||
exports.multicodec = '/ipfs/id/1.0.0'
|
||||
exports.listener = require('./listener')
|
||||
exports.dialer = require('./dialer')
|
||||
exports.message = require('./message')
|
35
src/identify/listener.js
Normal file
35
src/identify/listener.js
Normal file
@ -0,0 +1,35 @@
|
||||
'use strict'
|
||||
|
||||
const pull = require('pull-stream/pull')
|
||||
const values = require('pull-stream/sources/values')
|
||||
const lp = require('pull-length-prefixed')
|
||||
|
||||
const msg = require('./message')
|
||||
|
||||
module.exports = (conn, pInfoSelf) => {
|
||||
// send what I see from the other + my Info
|
||||
conn.getObservedAddrs((err, observedAddrs) => {
|
||||
if (err) { return }
|
||||
observedAddrs = observedAddrs[0]
|
||||
|
||||
let publicKey = Buffer.alloc(0)
|
||||
if (pInfoSelf.id.pubKey) {
|
||||
publicKey = pInfoSelf.id.pubKey.bytes
|
||||
}
|
||||
|
||||
const msgSend = msg.encode({
|
||||
protocolVersion: 'ipfs/0.1.0',
|
||||
agentVersion: 'na',
|
||||
publicKey: publicKey,
|
||||
listenAddrs: pInfoSelf.multiaddrs.toArray().map((ma) => ma.buffer),
|
||||
observedAddr: observedAddrs ? observedAddrs.buffer : Buffer.from(''),
|
||||
protocols: Array.from(pInfoSelf.protocols)
|
||||
})
|
||||
|
||||
pull(
|
||||
values([msgSend]),
|
||||
lp.encode(),
|
||||
conn
|
||||
)
|
||||
})
|
||||
}
|
30
src/identify/message.js
Normal file
30
src/identify/message.js
Normal file
@ -0,0 +1,30 @@
|
||||
'use strict'
|
||||
|
||||
const protons = require('protons')
|
||||
const schema = `
|
||||
message Identify {
|
||||
// protocolVersion determines compatibility between peers
|
||||
optional string protocolVersion = 5; // e.g. ipfs/1.0.0
|
||||
|
||||
// agentVersion is like a UserAgent string in browsers, or client version in bittorrent
|
||||
// includes the client name and client.
|
||||
optional string agentVersion = 6; // e.g. go-ipfs/0.1.0
|
||||
|
||||
// publicKey is this node's public key (which also gives its node.ID)
|
||||
// - may not need to be sent, as secure channel implies it has been sent.
|
||||
// - then again, if we change / disable secure channel, may still want it.
|
||||
optional bytes publicKey = 1;
|
||||
|
||||
// listenAddrs are the multiaddrs the sender node listens for open connections on
|
||||
repeated bytes listenAddrs = 2;
|
||||
|
||||
// oservedAddr is the multiaddr of the remote endpoint that the sender node perceives
|
||||
// this is useful information to convey to the other side, as it helps the remote endpoint
|
||||
// determine whether its connection to the local peer goes through NAT.
|
||||
optional bytes observedAddr = 4;
|
||||
|
||||
repeated string protocols = 3;
|
||||
}
|
||||
`
|
||||
|
||||
module.exports = protons(schema).Identify
|
5
src/identify/package.json
Normal file
5
src/identify/package.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "libp2p-identify",
|
||||
"description": "libp2p Identify Protocol",
|
||||
"main": "./index.js"
|
||||
}
|
Reference in New Issue
Block a user