Skip to content
This repository has been archived by the owner on Aug 23, 2019. It is now read-only.

Commit

Permalink
Merge pull request #20 from diasdavid/update/simplify
Browse files Browse the repository at this point in the history
simplify libp2p-swarm
  • Loading branch information
daviddias committed Mar 10, 2016
2 parents 1fd6a38 + 9901119 commit bb7f739
Show file tree
Hide file tree
Showing 7 changed files with 789 additions and 768 deletions.
147 changes: 103 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,81 +13,140 @@ libp2p-swarm is used by libp2p but it can be also used as a standalone module.

# Usage

### Install and create a Swarm
## Install

libp2p-swarm is available on npm and so, like any other npm module, just:

```bash
$ npm install libp2p-swarm --save
> npm install libp2p-swarm --save
```

## API

#### Create a libp2p Swarm

And use it in your Node.js code as:

```JavaScript
var Swarm = require('libp2p-swarm')
const Swarm = require('libp2p-swarm')

var sw = new Swarm(peerInfoSelf)
const sw = new Swarm(peerInfo)
```

peerInfoSelf is a [PeerInfo](https://github.com/diasdavid/js-peer-info) object that represents the peer creating this swarm instance.
peerInfo is a [PeerInfo](https://github.com/diasdavid/js-peer-info) object that represents the peer creating this swarm instance.

### Support a transport
### Transports

libp2p-swarm expects transports that implement [abstract-transport](https://github.com/diasdavid/abstract-transport). For example [libp2p-tcp](https://github.com/diasdavid/js-libp2p-tcp), a simple shim on top of the `net` module to make it work with swarm expectations.
##### `swarm.transport.add(key, transport, options, callback)`

```JavaScript
sw.addTransport(transport, [options, dialOptions, listenOptions])
```
libp2p-swarm expects transports that implement [interface-transport](https://github.com/diasdavid/abstract-transport). For example [libp2p-tcp](https://github.com/diasdavid/js-libp2p-tcp).

### Add a connection upgrade
- `key` - the transport identifier
- `transport` -
- `options`
- `callback`

A connection upgrade must be able to receive and return something that implements the [abstract-connection](https://github.com/diasdavid/abstract-connection) interface.
##### `swarm.transport.dial(key, multiaddrs, callback)`

```JavaScript
sw.addUpgrade(connUpgrade, [options])
```
Dial to a peer on a specific transport.

Upgrading a connection to use a stream muxer is still considered an upgrade, but a special case since once this connection is applied, the returned obj will implement the [abstract-stream-muxer](https://github.com/diasdavid/abstract-stream-muxer) interface.
- `key`
- `multiaddrs`
- `callback`

```JavaScript
sw.addStreamMuxer(streamMuxer, [options])
```
##### `swarm.transport.listen(key, options, handler, callback)`

### Dial to another peer
Set a transport to start listening mode.

```JavaScript
sw.dial(PeerInfo, options, protocol, callback)
sw.dial(PeerInfo, options, callback)
```
- `key`
- `options`
- `handler`
- `callback`

##### `swarm.transport.close(key, callback)`

Close the listeners of a given transport.

- `key`
- `callback`

### Connection

##### `swarm.connection.addUpgrade()`

A connection upgrade must be able to receive and return something that implements the [interface-connection](https://github.com/diasdavid/interface-connection) specification.

> **WIP**
##### `swarm.connection.addStreamMuxer(muxer)`

Upgrading a connection to use a stream muxer is still considered an upgrade, but a special case since once this connection is applied, the returned obj will implement the [interface-stream-muxer](https://github.com/diasdavid/interface-stream-muxer) spec.

- `muxer`

##### `swarm.connection.reuse()`

Enable the identify protocol

### `swarm.dial(pi, protocol, callback)`

dial uses the best transport (whatever works first, in the future we can have some criteria), and jump starts the connection until the point we have to negotiate the protocol. If a muxer is available, then drop the muxer onto that connection. Good to warm up connections or to check for connectivity. If we have already a muxer for that peerInfo, than do nothing.

### Accept requests on a specific protocol
- `pi` - peer info project
- `protocol`
- `callback`

```JavaScript
sw.handleProtocol(protocol, handlerFunction)
```
### `swarm.handle(protocol, handler)`

### Cleaning up before exiting
handle a new protocol.

Each time you add a transport or dial you create connections. Be sure to close
them up before exiting. To do so you can:
- `protocol`
- `handler` - function called when we receive a dial on `protocol. Signature must be `function (conn) {}`

Close a transport listener:
### `swarm.close(callback)`

```js
sw.closeListener(transportName, callback)
sw.closeAllListeners(callback)
```
close all the listeners and muxers.

Close all open connections
- `callback`

```js
sw.closeConns(callback)
```
# Design

Close everything!
## Multitransport

```js
sw.close(callback)
```
libp2p is designed to support multiple transports at the same time. While peers are identified by their ID (which are generated from their public keys), the addresses of each pair may vary, depending the device where they are being run or the network in which they are accessible through.

In order for a transport to be supported, it has to follow the [interface-transport](https://github.com/diasdavid/interface-transport) spec.

## Connection upgrades

Each connection in libp2p follows the [interface-connection](https://github.com/diasdavid/interface-connection) spec. This design decision enables libp2p to have upgradable transports.

We think of `upgrade` as a very important notion when we are talking about connections, we can see mechanisms like: stream multiplexing, congestion control, encrypted channels, multipath, simulcast, etc, as `upgrades` to a connection. A connection can be a simple and with no guarantees, drop a packet on the network with a destination thing, a transport in the other hand can be a connection and or a set of different upgrades that are mounted on top of each other, giving extra functionality to that connection and therefore `upgrading` it.

Types of upgrades to a connection:

- encrypted channel (with TLS for e.g)
- congestion flow (some transports don't have it by default)
- multipath (open several connections and abstract it as a single connection)
- simulcast (still really thinking this one through, it might be interesting to send a packet through different connections under some hard network circumstances)
- stream-muxer - this a special case, because once we upgrade a connection to a stream-muxer, we can open more streams (multiplex them) on a single stream, also enabling us to reuse the underlying dialed transport

We also want to enable flexibility when it comes to upgrading a connection, for example, we might that all dialed transports pass through the encrypted channel upgrade, but not the congestion flow, specially when a transport might have already some underlying properties (UDP vs TCP vs WebRTC vs every other transport protocol)

## Identify

Identify is a protocol that Swarms mounts on top of itself, to identify the connections between any two peers. E.g:

- a) peer A dials a conn to peer B
- b) that conn gets upgraded to a stream multiplexer that both peers agree
- c) peer B executes de identify protocol
- d) peer B now can open streams to peer A, knowing which is the identity of peer A

In addition to this, we also share the 'observed addresses' by the other peer, which is extremely useful information for different kinds of network topologies.

## Notes

To avoid the confusion between connection, stream, transport, and other names that represent an abstraction of data flow between two points, we use terms as:

- connection - something that implements the transversal expectations of a stream between two peers, including the benefits of using a stream plus having a way to do half duplex, full duplex
- transport - something that as a dial/listen interface and return objs that implement a connection interface
25 changes: 0 additions & 25 deletions examples/peerA.js

This file was deleted.

14 changes: 0 additions & 14 deletions examples/peerB.js

This file was deleted.

16 changes: 7 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,26 @@
"test"
],
"engines": {
"node": "^4.0.0"
"node": "^4.3.0"
},
"devDependencies": {
"bl": "^1.1.2",
"chai": "^3.5.0",
"istanbul": "^0.4.2",
"libp2p-spdy": "^0.1.0",
"libp2p-tcp": "^0.1.1",
"libp2p-spdy": "^0.2.3",
"libp2p-tcp": "^0.3.0",
"mocha": "^2.4.5",
"multiaddr": "^1.1.1",
"peer-id": "^0.6.0",
"peer-info": "^0.6.0",
"pre-commit": "^1.1.2",
"sinon": "^1.15.4",
"standard": "^6.0.7",
"stream-pair": "^1.0.3"
},
"dependencies": {
"async": "^1.3.0",
"ip-address": "^5.0.2",
"ipfs-logger": "^0.1.0",
"multiaddr": "^1.0.0",
"multiplex-stream-muxer": "^0.2.0",
"multistream-select": "^0.6.1",
"peer-id": "^0.3.3",
"peer-info": "^0.3.2",
"protocol-buffers-stream": "^1.2.0"
}
}
Loading

0 comments on commit bb7f739

Please sign in to comment.