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

Commit

Permalink
feat: support for custom matching functions
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddias committed Nov 3, 2016
1 parent b5fc01f commit 3659848
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 54 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ 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.
- `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

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"author": "David Dias <daviddias@ipfs.io>",
"license": "MIT",
"dependencies": {
"async": "^2.1.2",
"debug": "^2.2.0",
"interface-connection": "^0.3.0",
"lodash.isfunction": "^3.0.8",
Expand All @@ -64,4 +65,4 @@
"Richard Littauer <richard.littauer@gmail.com>",
"npm-to-cdn-bot (by Forbes Lindesay) <npmcdn-to-unpkg-bot@users.noreply.github.com>"
]
}
}
24 changes: 18 additions & 6 deletions src/listener/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ const pull = require('pull-stream')
const isFunction = require('lodash.isfunction')
const assert = require('assert')
const select = require('../select')
const selectHandler = require('./selectHandler')
const lsHandler = require('./lsHandler')
const selectHandler = require('./select-handler')
const lsHandler = require('./ls-handler')
const matchExact = require('./match-exact')

const util = require('./../util')
const Connection = require('interface-connection').Connection
Expand All @@ -15,7 +16,11 @@ const PROTOCOL_ID = require('./../constants').PROTOCOL_ID
module.exports = class Listener {
constructor () {
this.handlers = {
ls: (protocol, conn) => lsHandler(this, conn)
ls: {
handlerFunc: (protocol, conn) => lsHandler(this, conn),
matchFunc: matchExact

}
}
this.log = util.log.listener()
}
Expand Down Expand Up @@ -50,14 +55,21 @@ module.exports = class Listener {
}

// be ready for a given `protocol`
addHandler (protocol, handler) {
addHandler (protocol, handlerFunc, matchFunc) {
this.log('adding handler: ' + protocol)
assert(isFunction(handler), 'handler must be a function')
assert(isFunction(handlerFunc), 'handler must be a function')

if (this.handlers[protocol]) {
this.log('overwriting handler for ' + protocol)
}

this.handlers[protocol] = handler
if (!matchFunc) {
matchFunc = matchExact
}

this.handlers[protocol] = {
handlerFunc: handlerFunc,
matchFunc: matchFunc
}
}
}
File renamed without changes.
11 changes: 11 additions & 0 deletions src/listener/match-exact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict'

function matchExact (myProtocol, senderProtocol, callback) {
if (myProtocol === senderProtocol) {
callback(null, true)
} else {
callback(null, false)
}
}

module.exports = matchExact
Empty file added src/listener/match-semver.js
Empty file.
76 changes: 76 additions & 0 deletions src/listener/select-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
'use strict'

const handshake = require('pull-handshake')
const lp = require('pull-length-prefixed')
const Connection = require('interface-connection').Connection
const writeEncoded = require('../util.js').writeEncoded
const some = require('async/some')

function selectHandler (rawConn, handlersMap, log) {
const cb = (err) => {
// incoming errors are irrelevant for the app
log.error(err)
}

const stream = handshake({ timeout: 60 * 1000 }, cb)
const shake = stream.handshake

next()
return stream

function next () {
lp.decodeFromReader(shake, (err, data) => {
if (err) {
return cb(err)
}
log('received:', data.toString())
const protocol = data.toString().slice(0, -1)

matcher(protocol, handlersMap, (err, result) => {
if (err) {
return cb(err)
}
const key = result

if (key) {
log('send ack back of: ' + protocol)
writeEncoded(shake, data, cb)

const conn = new Connection(shake.rest(), rawConn)
handlersMap[key].handlerFunc(protocol, conn)
} else {
log('not supported protocol: ' + protocol)
writeEncoded(shake, new Buffer('na\n'))
next()
}
})
})
}
}

module.exports = selectHandler

function matcher (protocol, handlers, callback) {
const supportedProtocols = Object.keys(handlers)
let supportedProtocol = false

some(supportedProtocols,
(sp, cb) => {
handlers[sp].matchFunc(sp, protocol, (err, result) => {
if (err) {
return cb(err)
}
if (result) {
supportedProtocol = sp
}
cb()
})
},
(err) => {
if (err) {
return callback(err)
}
callback(null, supportedProtocol)
}
)
}
45 changes: 0 additions & 45 deletions src/listener/selectHandler.js

This file was deleted.

55 changes: 54 additions & 1 deletion test/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ describe('multistream handshake', () => {
const protocol = '/monkey/1.0.0'
msl.addHandler(protocol, (p, conn) => {
expect(protocol).to.equal(p)
console.log(protocol)
pull(conn, conn)
})
next()
Expand Down Expand Up @@ -340,3 +339,57 @@ describe('multistream handshake', () => {
], done)
})
})

describe('custom matching function', () => {
it('match-true always', (done) => {
const p = pullPair()
const dialerConn = p[0]
const listenerConn = p[1]

let msl
let msd
series([
(next) => {
parallel([
(cb) => {
msl = new multistream.Listener()
expect(msl).to.exist
msl.handle(listenerConn, cb)
},
(cb) => {
msd = new multistream.Dialer()
expect(msd).to.exist
msd.handle(dialerConn, cb)
}
], next)
},
(next) => {
msl.addHandler('/does-not-matter/1.0.0', (p, conn) => {
pull(conn, conn)
}, (myProtocol, requestedProtocol, callback) => {
callback(null, true)
})
next()
},
(next) => {
msd.select('/it-is-gonna-match-anyway/1.0.0', (err, conn) => {
expect(err).to.not.exist

pull(
pull.values(['banana']),
conn,
pull.collect((err, data) => {
expect(err).to.not.exist
expect(data).to.be.eql(['banana'])
next()
})
)
})
}
], done)
})

describe('semver-match', () => {

})
})

0 comments on commit 3659848

Please sign in to comment.