Skip to content
This repository was archived by the owner on Feb 26, 2021. It is now read-only.

feat: Rewrite from SIO+ws-relay to protobuf+p2p-circuit #43

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions CRYPTO_PUZZLE.md

This file was deleted.

62 changes: 62 additions & 0 deletions PROTOCOL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Protocol

### `/ws-star/2.0.0`

## Connecting & Crypto challenge

```protobuf
message IdentifyRequest {
required string nonce = 1;
}

message IdentifyResponse {
required string id = 1;
required string pubKey = 2;
required bytes signature = 3;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not have all the same fields as the identify protocol?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the same identify protocol. Additionally in the libp2p-identify protocol the public keys never get exchanged.

}
```

### Error Handling

If verifing the IdentifyResponse fails the connection gets closed by the server (protocol error)

### Example Connection

C: connects

S: Uses `.getPeerInfo()` to get id. Generates random nonce (64 byte alphanumeric string) and sends IndentifyRequest.

C: Signs nonce and send id, pubkey and signature back to server as IndentifyResponse

S: Verifies IndentifyResponse

S: Server adds peer to peerDB, starts to announce peer
(If peer disconnects server stops to announce it)

## Discovery

The server peer periodically sends a list of all ids (in binary instead of b58)

The client peer responds with discovery ACKs (which are basically pings)

```protobuf
message DiscoveryEvent {
repeated bytes id = 1;
}

message DiscoveryACK {
required bool ok = 1;
}
```

## Dials

Dials work using p2p-circuit (currently with a fixed relay server)

### Example Connection

Ca: Connects via `<server-address>/p2p-circuit/ipfs/<dst-id>`

Ca -> S -> Cb: Uses p2p-circuit to establish a connection with `<dst-id>`

Cb: Finishes up connection
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Id.create((err, id) => {
throw err
}

node.dial(peerInfo, "/test/1.0.0", (err, conn) => {
node.dialProtocol(peerInfo, "/test/1.0.0", (err, conn) => {
if (err) {
throw err
}
Expand Down
25 changes: 12 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,30 +27,29 @@
"license": "MIT",
"dependencies": {
"async": "^2.6.0",
"data-queue": "0.0.3",
"debug": "^3.1.0",
"interface-connection": "^0.3.2",
"libp2p-crypto": "^0.11.0",
"mafmt": "^3.0.2",
"merge-recursive": "0.0.3",
"mafmt": "^4.0.0",
"multiaddr": "^3.0.2",
"once": "^1.4.0",
"peer-id": "^0.10.4",
"peer-info": "^0.11.4",
"pull-stream": "^3.6.1",
"socket.io-client": "^2.0.4",
"socket.io-pull-stream": "^0.1.3",
"uuid": "^3.1.0"
"peer-info": "^0.11.6",
"protons": "^1.0.1",
"pull-length-prefixed": "^1.3.0",
"pull-stream": "^3.6.1"
},
"directories": {
"test": "test"
},
"devDependencies": {
"aegir": "^12.3.0",
"aegir": "^13.0.0",
"chai": "^4.1.2",
"dirty-chai": "^2.0.1",
"libp2p-websocket-star-rendezvous": "github:libp2p/js-libp2p-websocket-star-rendezvous",
"lodash": "^4.17.4"
"libp2p": "^0.16.5",
"libp2p-multiplex": "^0.5.1",
"libp2p-secio": "^0.9.2",
"libp2p-spdy": "^0.11.0",
"libp2p-websockets": "^0.10.4",
"lodash": "^4.17.5"
},
"repository": {
"type": "git",
Expand Down
77 changes: 26 additions & 51 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@

const debug = require('debug')
const log = debug('libp2p:websocket-star')
const multiaddr = require('multiaddr')
const EE = require('events').EventEmitter
const PeerId = require('peer-id')
const PeerInfo = require('peer-info')
const Id = require('peer-id')
const Peer = require('peer-info')
const Connection = require('interface-connection').Connection
const setImmediate = require('async/setImmediate')
const utils = require('./utils')
const Listener = require('./listener')
const cleanUrlSIO = utils.cleanUrlSIO
const mafmt = require('mafmt')
const assert = require('assert')

class WebsocketStar {
module.exports = class WebsocketStar {
/**
* WebsocketStar Transport
* @class
Expand All @@ -23,7 +21,11 @@ class WebsocketStar {
constructor (options) {
options = options || {}

log('creating new WebsocketStar transport')

this.id = options.id
assert(this.id, 'Id MUST be set since v2')
this.b58 = this.id.toB58String()
this.flag = options.allowJoinWithDisabledChallenge // let's just refer to it as "flag"

this.discovery = new EE()
Expand All @@ -38,42 +40,21 @@ class WebsocketStar {
this._peerDiscovered = this._peerDiscovered.bind(this)
}

/**
* Sets the id after transport creation (aka the lazy way)
* @param {PeerId} id
* @returns {undefined}
*/
lazySetId (id) {
if (!id) return
this.id = id
this.canCrypto = true
setSwarm (swarm) {
this.swarm = swarm
}

/**
* Dials a peer
* Dials a peer - should actually never get called because p2p-circuit handles dials
* @param {Multiaddr} ma - Multiaddr to dial to
* @param {Object} options
* @param {function} callback
* @private
* @returns {Connection}
*/
dial (ma, options, callback) {
if (typeof options === 'function') {
callback = options
options = {}
}

let url
try {
url = cleanUrlSIO(ma)
} catch (err) {
return callback(err) // early
}
const listener = this.listeners_list[url]
if (!listener) {
callback(new Error('No listener for this server'))
return new Connection()
}
return listener.dial(ma, options, callback)
callback(new Error('This should never have been called!'))
return new Connection()
}

/**
Expand All @@ -88,14 +69,9 @@ class WebsocketStar {
options = {}
}

const listener = new Listener({
id: this.id,
handler,
listeners: this.listeners_list,
flag: this.flag
})
const listener = new Listener(this, handler)

listener.on('peer', this._peerDiscovered)
listener.on('peers', peers => peers.forEach(peer => this._peerDiscovered(peer, listener)))

return listener
}
Expand All @@ -115,20 +91,19 @@ class WebsocketStar {

/**
* Used to fire peer events on the discovery part
* @param {Multiaddr} maStr
* @param {id} id - Buffer containing id
* @param {Listener} listener - Listener which discovered this peer
* @fires Discovery#peer
* @returns {undefined}
* @private
*/
_peerDiscovered (maStr) {
log('Peer Discovered:', maStr)
const peerIdStr = maStr.split('/ipfs/').pop()
const peerId = PeerId.createFromB58String(peerIdStr)
const peerInfo = new PeerInfo(peerId)

peerInfo.multiaddrs.add(multiaddr(maStr))
this.discovery.emit('peer', peerInfo)
_peerDiscovered (id, listener) {
const peer = new Peer(new Id(id))
if (peer.id.toB58String() === this.id.toB58String()) return
const addr = listener.getFullAddr(peer.id.toB58String())
log('Peer Discovered: %s', addr)

peer.multiaddrs.add(addr)
this.discovery.emit('peer', peer)
}
}

module.exports = WebsocketStar
Loading