Skip to content
This repository has been archived by the owner on Oct 19, 2022. It is now read-only.

Commit

Permalink
docs(api): first pass
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire authored Dec 14, 2016
1 parent dd6f956 commit a2f9aea
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ build/Release
node_modules

dist
docs
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ build/Release
node_modules

test
docs
35 changes: 1 addition & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ the global namespace.
### Attach multistream to a connection (socket)

```JavaScript
const Multistream = require('multistream-select')
const multistream = require('multistream-select')

const ms = new multistream.Listener()
// or
Expand All @@ -112,39 +112,6 @@ const ms = new multistream.Dialer()
ms.handle(conn, callback)
```

### Handling a protocol

This function is only available in Listener mode

```JavaScript
ms.addHandler(<protocol>, <handlerFunc>, [<matchingFunc>])
```

- `protocol` is a string identifying the protocol.
- `handlerFunc` is a function of type `function (protocol, conn)` that will be called if there is a handshake performed on `protocol`.
- `matchingFunc` is a function that receives a protocol and a callback and should call `callback(err, result)` where `err` is if there was a error on the matching function, and `result` is a boolean that represents if a match happened. The default `matchingFunc` is exact matching. The exact signature should be: `function (protocol, requestedProtocol, function (err, result)`

### Selecting a protocol

This function is only available in Dialer mode

```JavaScript
ms.select(<protocol>, <callback>)
```

- `protocol` is a string of the protocol that we want to handshake.
- `callback` is a function of type `function (err, conn)` where `err` is an error object that gets passed if something wrong happend (e.g: if the protocol selected is not supported by the other end) and conn is the connection handshaked with the other end.

### Listing the available protocols

This function is only available in Dialer mode

```JavaScript
ms.ls(<callback>)
```

`callback` is a function of type `function (err, protocols)` where `err` is an error object that gets passed if something wrong happend and `protocols` is an array of the supported protocols in the other end.

### 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).
Expand Down
16 changes: 16 additions & 0 deletions example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use strict'

const multistream = require('multistream-select')
const Connection = require('interface-connection').Connection

const listener = new multistream.Listener()
// or
// const dialer = new multistream.Dialer()

// supply a connection
const conn = new Connection()

// apply the multistream to the conn
listener.handle(conn, () => {
console.log('connection established')
})
19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
"lint": "aegir-lint",
"test": "aegir-test",
"build": "aegir-build",
"release": "aegir-release",
"release-minor": "aegir-release --type minor",
"release-major": "aegir-release --type major",
"docs": "aegir-docs",
"release": "aegir-release --docs",
"release-minor": "aegir-release --type minor --docs",
"release-major": "aegir-release --type major --docs",
"test:node": "aegir-test node",
"test:browser": "aegir-test browser",
"coverage": "aegir-coverage",
Expand Down Expand Up @@ -40,21 +41,21 @@
"author": "David Dias <daviddias@ipfs.io>",
"license": "MIT",
"dependencies": {
"async": "^2.1.2",
"debug": "^2.2.0",
"async": "^2.1.4",
"debug": "^2.4.1",
"interface-connection": "^0.3.0",
"lodash.isfunction": "^3.0.8",
"lodash.range": "^3.2.0",
"pull-handshake": "^1.1.4",
"pull-length-prefixed": "^1.2.0",
"pull-stream": "^3.5.0",
"semver": "^5.3.0",
"varint": "^4.0.1"
"varint": "^5.0.0"
},
"devDependencies": {
"aegir": "^9.0.1",
"aegir": "^9.3.0",
"chai": "^3.5.0",
"pre-commit": "^1.1.3",
"pre-commit": "^1.2.2",
"pull-pair": "^1.1.0",
"run-parallel": "^1.1.6",
"run-series": "^1.1.4"
Expand All @@ -66,4 +67,4 @@
"Richard Littauer <richard.littauer@gmail.com>",
"npm-to-cdn-bot (by Forbes Lindesay) <npmcdn-to-unpkg-bot@users.noreply.github.com>"
]
}
}
41 changes: 39 additions & 2 deletions src/dialer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,26 @@ const select = require('../select')

const PROTOCOL_ID = require('./../constants').PROTOCOL_ID

module.exports = class Dialer {
/**
*
*/
class Dialer {
/**
* Create a new Dialer.
*/
constructor () {
this.conn = null
this.log = util.log.dialer()
}

// perform the multistream handshake
/**
* Perform the multistream handshake.
*
* @param {Connection} rawConn - The connection on which
* to perform the handshake.
* @param {function(Error)} callback - Called when the handshake completed.
* @returns {undefined}
*/
handle (rawConn, callback) {
this.log('dialer handle conn')
const s = select(PROTOCOL_ID, (err, conn) => {
Expand All @@ -36,6 +49,18 @@ module.exports = class Dialer {
)
}

/**
* Select a protocol
*
* @param {string} protocol - A string of the protocol that we want to handshake.
* @param {function(Error, Connection)} callback - `err` is
* an error object that gets passed if something wrong happ
* end (e.g: if the protocol selected is not supported by
* the other end) and conn is the connection handshaked
* with the other end.
*
* @returns {undefined}
*/
select (protocol, callback) {
this.log('dialer select ' + protocol)
if (!this.conn) {
Expand All @@ -57,6 +82,16 @@ module.exports = class Dialer {
)
}

/**
* List all available protocols.
*
* @param {function(Error, Array<string>)} callback - If
* something wrong happend `Error` exists, otherwise
* `protocols` is a list of the supported
* protocols on the other end.
*
* @returns {undefined}
*/
ls (callback) {
const lsStream = select('ls', (err, conn) => {
if (err) {
Expand Down Expand Up @@ -103,3 +138,5 @@ function collectLs (conn) {
return counter-- > 0
})
}

module.exports = Dialer
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
exports.Listener = exports.listener = require('./listener')
exports.Dialer = exports.dialer = require('./dialer')
exports.matchSemver = require('./listener/match-semver')
exports.matchExact = require('./listener/match-exact')
42 changes: 39 additions & 3 deletions src/listener/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ const Connection = require('interface-connection').Connection

const PROTOCOL_ID = require('./../constants').PROTOCOL_ID

module.exports = class Listener {
/**
* Listener
*/
class Listener {
/**
* Create a new Listener.
*/
constructor () {
this.handlers = {
ls: {
Expand All @@ -25,7 +31,14 @@ module.exports = class Listener {
this.log = util.log.listener()
}

// perform the multistream handshake
/**
* Perform the multistream handshake.
*
* @param {Connection} rawConn - The connection on which
* to perform the handshake.
* @param {function(Error)} callback - Called when the handshake completed.
* @returns {undefined}
*/
handle (rawConn, callback) {
this.log('listener handle conn')

Expand Down Expand Up @@ -54,7 +67,14 @@ module.exports = class Listener {
)
}

// be ready for a given `protocol`
/**
* Handle a given `protocol`.
*
* @param {string} protocol - A string identifying the protocol.
* @param {function(string, Connection)} handlerFunc - Will be called if there is a handshake performed on `protocol`.
* @param {matchHandler} [matchFunc=matchExact]
* @returns {undefined}
*/
addHandler (protocol, handlerFunc, matchFunc) {
this.log('adding handler: ' + protocol)
assert(isFunction(handlerFunc), 'handler must be a function')
Expand All @@ -72,4 +92,20 @@ module.exports = class Listener {
matchFunc: matchFunc
}
}

/**
* Receives a protocol and a callback and should
* call `callback(err, result)` where `err` is if
* there was a error on the matching function, and
* `result` is a boolean that represents if a
* match happened.
*
* @callback matchHandler
* @param {string} myProtocol
* @param {string} senderProtocol
* @param {function(Error, boolean)} callback
* @returns {undefined}
*/
}

module.exports = Listener
9 changes: 9 additions & 0 deletions src/listener/match-exact.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
'use strict'

/**
* Match protocols exactly.
*
* @param {string} myProtocol
* @param {string} senderProtocol
* @param {function(Error, boolean)} callback
* @returns {undefined}
* @type {matchHandler}
*/
function matchExact (myProtocol, senderProtocol, callback) {
const result = myProtocol === senderProtocol
callback(null, result)
Expand Down
9 changes: 9 additions & 0 deletions src/listener/match-semver.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

const semver = require('semver')

/**
* Match protocols using semver `~` matching.
*
* @param {string} myProtocol
* @param {string} senderProtocol
* @param {function(Error, boolean)} callback
* @returns {undefined}
* @type {matchHandler}
*/
function matchSemver (myProtocol, senderProtocol, callback) {
const mps = myProtocol.split('/')
const sps = senderProtocol.split('/')
Expand Down

0 comments on commit a2f9aea

Please sign in to comment.