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

Commit 3659848

Browse files
committed
feat: support for custom matching functions
1 parent b5fc01f commit 3659848

File tree

9 files changed

+162
-54
lines changed

9 files changed

+162
-54
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ ms.addHandler(<protocol>, <handlerFunc>, [<matchingFunc>])
122122

123123
- `protocol` is a string identifying the protocol.
124124
- `handlerFunc` is a function of type `function (protocol, conn)` that will be called if there is a handshake performed on `protocol`.
125-
- `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.
125+
- `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)`
126126

127127
### Selecting a protocol
128128

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"author": "David Dias <daviddias@ipfs.io>",
4141
"license": "MIT",
4242
"dependencies": {
43+
"async": "^2.1.2",
4344
"debug": "^2.2.0",
4445
"interface-connection": "^0.3.0",
4546
"lodash.isfunction": "^3.0.8",
@@ -64,4 +65,4 @@
6465
"Richard Littauer <richard.littauer@gmail.com>",
6566
"npm-to-cdn-bot (by Forbes Lindesay) <npmcdn-to-unpkg-bot@users.noreply.github.com>"
6667
]
67-
}
68+
}

src/listener/index.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ const pull = require('pull-stream')
44
const isFunction = require('lodash.isfunction')
55
const assert = require('assert')
66
const select = require('../select')
7-
const selectHandler = require('./selectHandler')
8-
const lsHandler = require('./lsHandler')
7+
const selectHandler = require('./select-handler')
8+
const lsHandler = require('./ls-handler')
9+
const matchExact = require('./match-exact')
910

1011
const util = require('./../util')
1112
const Connection = require('interface-connection').Connection
@@ -15,7 +16,11 @@ const PROTOCOL_ID = require('./../constants').PROTOCOL_ID
1516
module.exports = class Listener {
1617
constructor () {
1718
this.handlers = {
18-
ls: (protocol, conn) => lsHandler(this, conn)
19+
ls: {
20+
handlerFunc: (protocol, conn) => lsHandler(this, conn),
21+
matchFunc: matchExact
22+
23+
}
1924
}
2025
this.log = util.log.listener()
2126
}
@@ -50,14 +55,21 @@ module.exports = class Listener {
5055
}
5156

5257
// be ready for a given `protocol`
53-
addHandler (protocol, handler) {
58+
addHandler (protocol, handlerFunc, matchFunc) {
5459
this.log('adding handler: ' + protocol)
55-
assert(isFunction(handler), 'handler must be a function')
60+
assert(isFunction(handlerFunc), 'handler must be a function')
5661

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

61-
this.handlers[protocol] = handler
66+
if (!matchFunc) {
67+
matchFunc = matchExact
68+
}
69+
70+
this.handlers[protocol] = {
71+
handlerFunc: handlerFunc,
72+
matchFunc: matchFunc
73+
}
6274
}
6375
}
File renamed without changes.

src/listener/match-exact.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict'
2+
3+
function matchExact (myProtocol, senderProtocol, callback) {
4+
if (myProtocol === senderProtocol) {
5+
callback(null, true)
6+
} else {
7+
callback(null, false)
8+
}
9+
}
10+
11+
module.exports = matchExact

src/listener/match-semver.js

Whitespace-only changes.

src/listener/select-handler.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
'use strict'
2+
3+
const handshake = require('pull-handshake')
4+
const lp = require('pull-length-prefixed')
5+
const Connection = require('interface-connection').Connection
6+
const writeEncoded = require('../util.js').writeEncoded
7+
const some = require('async/some')
8+
9+
function selectHandler (rawConn, handlersMap, log) {
10+
const cb = (err) => {
11+
// incoming errors are irrelevant for the app
12+
log.error(err)
13+
}
14+
15+
const stream = handshake({ timeout: 60 * 1000 }, cb)
16+
const shake = stream.handshake
17+
18+
next()
19+
return stream
20+
21+
function next () {
22+
lp.decodeFromReader(shake, (err, data) => {
23+
if (err) {
24+
return cb(err)
25+
}
26+
log('received:', data.toString())
27+
const protocol = data.toString().slice(0, -1)
28+
29+
matcher(protocol, handlersMap, (err, result) => {
30+
if (err) {
31+
return cb(err)
32+
}
33+
const key = result
34+
35+
if (key) {
36+
log('send ack back of: ' + protocol)
37+
writeEncoded(shake, data, cb)
38+
39+
const conn = new Connection(shake.rest(), rawConn)
40+
handlersMap[key].handlerFunc(protocol, conn)
41+
} else {
42+
log('not supported protocol: ' + protocol)
43+
writeEncoded(shake, new Buffer('na\n'))
44+
next()
45+
}
46+
})
47+
})
48+
}
49+
}
50+
51+
module.exports = selectHandler
52+
53+
function matcher (protocol, handlers, callback) {
54+
const supportedProtocols = Object.keys(handlers)
55+
let supportedProtocol = false
56+
57+
some(supportedProtocols,
58+
(sp, cb) => {
59+
handlers[sp].matchFunc(sp, protocol, (err, result) => {
60+
if (err) {
61+
return cb(err)
62+
}
63+
if (result) {
64+
supportedProtocol = sp
65+
}
66+
cb()
67+
})
68+
},
69+
(err) => {
70+
if (err) {
71+
return callback(err)
72+
}
73+
callback(null, supportedProtocol)
74+
}
75+
)
76+
}

src/listener/selectHandler.js

Lines changed: 0 additions & 45 deletions
This file was deleted.

test/index.spec.js

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ describe('multistream handshake', () => {
9797
const protocol = '/monkey/1.0.0'
9898
msl.addHandler(protocol, (p, conn) => {
9999
expect(protocol).to.equal(p)
100-
console.log(protocol)
101100
pull(conn, conn)
102101
})
103102
next()
@@ -340,3 +339,57 @@ describe('multistream handshake', () => {
340339
], done)
341340
})
342341
})
342+
343+
describe('custom matching function', () => {
344+
it('match-true always', (done) => {
345+
const p = pullPair()
346+
const dialerConn = p[0]
347+
const listenerConn = p[1]
348+
349+
let msl
350+
let msd
351+
series([
352+
(next) => {
353+
parallel([
354+
(cb) => {
355+
msl = new multistream.Listener()
356+
expect(msl).to.exist
357+
msl.handle(listenerConn, cb)
358+
},
359+
(cb) => {
360+
msd = new multistream.Dialer()
361+
expect(msd).to.exist
362+
msd.handle(dialerConn, cb)
363+
}
364+
], next)
365+
},
366+
(next) => {
367+
msl.addHandler('/does-not-matter/1.0.0', (p, conn) => {
368+
pull(conn, conn)
369+
}, (myProtocol, requestedProtocol, callback) => {
370+
callback(null, true)
371+
})
372+
next()
373+
},
374+
(next) => {
375+
msd.select('/it-is-gonna-match-anyway/1.0.0', (err, conn) => {
376+
expect(err).to.not.exist
377+
378+
pull(
379+
pull.values(['banana']),
380+
conn,
381+
pull.collect((err, data) => {
382+
expect(err).to.not.exist
383+
expect(data).to.be.eql(['banana'])
384+
next()
385+
})
386+
)
387+
})
388+
}
389+
], done)
390+
})
391+
392+
describe('semver-match', () => {
393+
394+
})
395+
})

0 commit comments

Comments
 (0)