Compare commits

...

27 Commits

Author SHA1 Message Date
Pavel Murygin
157aba2835 bump dependencies 2021-04-09 17:49:30 +03:00
Vasco Santos
f1a5d21600 chore: release version v0.15.4 2021-03-31 16:15:28 +02:00
Vasco Santos
c5ddb0b58e chore: update contributors 2021-03-31 16:15:28 +02:00
Vasco Santos
ff4b764eaf
chore: update deps (#123) 2021-03-31 16:04:13 +02:00
Vasco Santos
d07d1b779e chore: release version v0.15.3 2021-02-22 11:56:15 +01:00
Vasco Santos
993416145d chore: update contributors 2021-02-22 11:56:14 +01:00
Alex Potsides
dff8549c7c
chore: update deps (#122) 2021-02-22 11:51:43 +01:00
Vasco Santos
511d4b4c99 chore: release version v0.15.2 2021-02-09 10:34:39 +01:00
Vasco Santos
d6cdb17dc9 chore: update contributors 2021-02-09 10:34:39 +01:00
Vasco Santos
577d3505f5
fix: add error event handler (#118) 2021-02-09 10:24:28 +01:00
Vasco Santos
757a48f660 chore: release version v0.15.1 2021-02-05 17:06:15 +01:00
Vasco Santos
a9f8cfa4ef chore: update contributors 2021-02-05 17:06:15 +01:00
Irakli Gozalishvili
96244f0489
fix: incompatibility with @evanw/esbuild#740 (#120) 2021-02-05 16:59:45 +01:00
Vasco Santos
62b5dd2fe7 chore: release version v0.15.0 2020-11-24 10:15:43 +01:00
Vasco Santos
a2b095246b chore: update contributors 2020-11-24 10:15:42 +01:00
Vasco Santos
711c721b03
feat: custom address filter (#116)
* feat: custom address filter

BREAKING CHANGE: Only DNS+WSS addresses are now returned on filter by default in the browser. This can be overritten by the filter option and filters are provided in the module.
2020-11-24 10:14:01 +01:00
Jacob Heun
662d04128c
chore: release version v0.14.0 2020-08-11 16:18:38 +02:00
Jacob Heun
4ee32a5b70
chore: update contributors 2020-08-11 16:18:37 +02:00
Alex Potsides
a277bf6bfb
fix: replace node buffers with uint8arrays (#115)
* fix: replace node buffers with uint8arrays

BREAKING CHANGES:

- All deps used by this module now use Uint8Arrays in place of Buffers

* chore: remove gh dep
2020-08-11 15:54:49 +02:00
Jacob Heun
a37c2bd7f7
chore: release version v0.13.6 2020-03-23 19:06:48 +01:00
Jacob Heun
1ad6c7f47b
chore: update contributors 2020-03-23 19:06:47 +01:00
dependabot-preview[bot]
a17c5432e7
chore(deps-dev): bump aegir from 20.6.1 to 21.4.4 (#111)
* chore(deps-dev): bump aegir from 20.6.1 to 21.4.4

Bumps [aegir](https://github.com/ipfs/aegir) from 20.6.1 to 21.4.4.
- [Release notes](https://github.com/ipfs/aegir/releases)
- [Changelog](https://github.com/ipfs/aegir/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ipfs/aegir/compare/v20.6.1...v21.4.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

* test(fix): fix aegir file for latest aegir

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
2020-03-23 19:04:38 +01:00
Hugo Dias
8065e07bad
fix: add buffer (#112) 2020-03-23 17:58:28 +01:00
Jacob Heun
a33db558a6
chore: release version v0.13.5 2020-02-26 17:18:14 +01:00
Jacob Heun
6f2b61f240
chore: update contributors 2020-02-26 17:18:13 +01:00
Vasco Santos
8bfb19a78f fix: catch thrown maConn errors in listener 2020-02-26 16:29:20 +01:00
Vasco Santos
d630b3288d chore: use libp2p badge 2020-02-26 16:29:07 +01:00
12 changed files with 511 additions and 207 deletions

View File

@ -10,23 +10,21 @@ const mockUpgrader = {
} }
let listener let listener
function boot (done) { async function before () {
const ws = new WS({ upgrader: mockUpgrader }) const ws = new WS({ upgrader: mockUpgrader })
const ma = multiaddr('/ip4/127.0.0.1/tcp/9095/ws') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9095/ws')
listener = ws.createListener(conn => pipe(conn, conn)) listener = ws.createListener(conn => pipe(conn, conn))
listener.listen(ma).then(() => done()).catch(done) await listener.listen(ma)
listener.on('error', console.error) listener.on('error', console.error)
} }
function shutdown (done) { function after () {
listener.close().then(done).catch(done) return listener.close()
} }
module.exports = { module.exports = {
hooks: { test: {
browser: { before,
pre: boot, after
post: shutdown
}
} }
} }

View File

@ -1,3 +1,88 @@
## [0.15.4](https://github.com/libp2p/js-libp2p-websockets/compare/v0.15.3...v0.15.4) (2021-03-31)
## [0.15.3](https://github.com/libp2p/js-libp2p-websockets/compare/v0.15.2...v0.15.3) (2021-02-22)
## [0.15.2](https://github.com/libp2p/js-libp2p-websockets/compare/v0.15.1...v0.15.2) (2021-02-09)
### Bug Fixes
* add error event handler ([#118](https://github.com/libp2p/js-libp2p-websockets/issues/118)) ([577d350](https://github.com/libp2p/js-libp2p-websockets/commit/577d3505f559b153ec9e0bbca7d31d2f164712bc))
## [0.15.1](https://github.com/libp2p/js-libp2p-websockets/compare/v0.15.0...v0.15.1) (2021-02-05)
### Bug Fixes
* incompatibility with @evanw/esbuild[#740](https://github.com/libp2p/js-libp2p-websockets/issues/740) ([#120](https://github.com/libp2p/js-libp2p-websockets/issues/120)) ([96244f0](https://github.com/libp2p/js-libp2p-websockets/commit/96244f048929c5225905327ae27a88961fe535f8))
# [0.15.0](https://github.com/libp2p/js-libp2p-websockets/compare/v0.13.1...v0.15.0) (2020-11-24)
### Bug Fixes
* add buffer ([#112](https://github.com/libp2p/js-libp2p-websockets/issues/112)) ([8065e07](https://github.com/libp2p/js-libp2p-websockets/commit/8065e07bad57b5732cdcec5ce3829ac2361604cf))
* catch thrown maConn errors in listener ([8bfb19a](https://github.com/libp2p/js-libp2p-websockets/commit/8bfb19a78f296c10d8e1a3c0ac608daa9ffcfefc))
* remove use of assert module ([#101](https://github.com/libp2p/js-libp2p-websockets/issues/101)) ([89d3723](https://github.com/libp2p/js-libp2p-websockets/commit/89d37232b8f603804b6ce5cd8230cc75d2dd8e28))
* replace node buffers with uint8arrays ([#115](https://github.com/libp2p/js-libp2p-websockets/issues/115)) ([a277bf6](https://github.com/libp2p/js-libp2p-websockets/commit/a277bf6bfbc7ad796e51f7646d7449c203384c06))
### Features
* custom address filter ([#116](https://github.com/libp2p/js-libp2p-websockets/issues/116)) ([711c721](https://github.com/libp2p/js-libp2p-websockets/commit/711c721b033d28b3c57c37bf9ca98d0f5d2a58b6))
### BREAKING CHANGES
* Only DNS+WSS addresses are now returned on filter by default in the browser. This can be overritten by the filter option and filters are provided in the module.
<a name="0.14.0"></a>
# [0.14.0](https://github.com/libp2p/js-libp2p-websockets/compare/v0.13.6...v0.14.0) (2020-08-11)
### Bug Fixes
* replace node buffers with uint8arrays ([#115](https://github.com/libp2p/js-libp2p-websockets/issues/115)) ([a277bf6](https://github.com/libp2p/js-libp2p-websockets/commit/a277bf6))
### BREAKING CHANGES
* - All deps used by this module now use Uint8Arrays in place of Buffers
* chore: remove gh dep
<a name="0.13.6"></a>
## [0.13.6](https://github.com/libp2p/js-libp2p-websockets/compare/v0.13.5...v0.13.6) (2020-03-23)
### Bug Fixes
* add buffer ([#112](https://github.com/libp2p/js-libp2p-websockets/issues/112)) ([8065e07](https://github.com/libp2p/js-libp2p-websockets/commit/8065e07))
<a name="0.13.5"></a>
## [0.13.5](https://github.com/libp2p/js-libp2p-websockets/compare/v0.13.4...v0.13.5) (2020-02-26)
### Bug Fixes
* catch thrown maConn errors in listener ([8bfb19a](https://github.com/libp2p/js-libp2p-websockets/commit/8bfb19a))
<a name="0.13.4"></a> <a name="0.13.4"></a>
## [0.13.4](https://github.com/libp2p/js-libp2p-websockets/compare/v0.13.3...v0.13.4) (2020-02-14) ## [0.13.4](https://github.com/libp2p/js-libp2p-websockets/compare/v0.13.3...v0.13.4) (2020-02-14)

View File

@ -1,7 +1,7 @@
# js-libp2p-websockets # js-libp2p-websockets
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) [![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
[![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io) [![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io)
[![Coverage Status](https://coveralls.io/repos/github/libp2p/js-libp2p-websockets/badge.svg?branch=master)](https://coveralls.io/github/libp2p/js-libp2p-websockets?branch=master) [![Coverage Status](https://coveralls.io/repos/github/libp2p/js-libp2p-websockets/badge.svg?branch=master)](https://coveralls.io/github/libp2p/js-libp2p-websockets?branch=master)
@ -35,40 +35,63 @@
> npm i libp2p-websockets > npm i libp2p-websockets
``` ```
### Example ### Constructor properties
```js ```js
const WS = require('libp2p-websockets') const WS = require('libp2p-websockets')
const multiaddr = require('multiaddr')
const pipe = require('it-pipe')
const { collect } = require('streaming-iterables')
const addr = multiaddr('/ip4/0.0.0.0/tcp/9090/ws') const properties = {
upgrader,
filter
}
const ws = new WS({ upgrader }) const ws = new WS(properties)
const listener = ws.createListener((socket) => {
console.log('new connection opened')
pipe(
['hello'],
socket
)
})
await listener.listen(addr)
console.log('listening')
const socket = await ws.dial(addr)
const values = await pipe(
socket,
collect
)
console.log(`Value: ${values.toString()}`)
// Close connection after reading
await listener.close()
``` ```
| Name | Type | Description | Default |
|------|------|-------------|---------|
| upgrader | [`Upgrader`](https://github.com/libp2p/interface-transport#upgrader) | connection upgrader object with `upgradeOutbound` and `upgradeInbound` | **REQUIRED** |
| filter | `(multiaddrs: Array<Multiaddr>) => Array<Multiaddr>` | override transport addresses filter | **Browser:** DNS+WSS multiaddrs / **Node.js:** DNS+{WS, WSS} multiaddrs |
You can create your own address filters for this transports, or rely in the filters [provided](./src/filters.js).
The available filters are:
- `filters.all`
- Returns all TCP and DNS based addresses, both with `ws` or `wss`.
- `filters.dnsWss`
- Returns all DNS based addresses with `wss`.
- `filters.dnsWsOrWss`
- Returns all DNS based addresses, both with `ws` or `wss`.
## Libp2p Usage Example
```js
const Libp2p = require('libp2p')
const Websockets = require('libp2p-websockets')
const filters = require('libp2p-websockets/src/filters')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
const transportKey = Websockets.prototype[Symbol.toStringTag]
const node = await Libp2p.create({
modules: {
transport: [Websockets],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
},
config: {
transport: {
[transportKey]: { // Transport properties -- Libp2p upgrader is automatically added
filter: filters.dnsWsOrWss
}
}
}
})
```
For more information see [libp2p/js-libp2p/doc/CONFIGURATION.md#customizing-transports](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#customizing-transports).
## API ## API
### Transport ### Transport

View File

@ -1,6 +1,6 @@
{ {
"name": "libp2p-websockets", "name": "libp2p-websockets",
"version": "0.13.4", "version": "0.15.4",
"description": "JavaScript implementation of the WebSockets module that libp2p uses and that implements the interface-transport spec", "description": "JavaScript implementation of the WebSockets module that libp2p uses and that implements the interface-transport spec",
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>", "leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
"main": "src/index.js", "main": "src/index.js",
@ -16,7 +16,7 @@
"coverage": "nyc --reporter=lcov --reporter=text npm run test:node" "coverage": "nyc --reporter=lcov --reporter=text npm run test:node"
}, },
"browser": { "browser": {
"src/listener": "./src/listener.browser.js" "./src/listener.js": "./src/listener.browser.js"
}, },
"files": [ "files": [
"src", "src",
@ -40,48 +40,48 @@
"dependencies": { "dependencies": {
"abortable-iterator": "^3.0.0", "abortable-iterator": "^3.0.0",
"class-is": "^1.1.0", "class-is": "^1.1.0",
"debug": "^4.1.1", "debug": "^4.2.0",
"err-code": "^2.0.0", "err-code": "^3.0.1",
"it-ws": "^3.0.0", "ipfs-utils": "^6.0.1",
"libp2p-utils": "~0.1.0", "it-ws": "^4.0.0",
"mafmt": "^7.0.0", "libp2p-utils": "^0.2.1",
"multiaddr": "^7.1.0", "mafmt": "^8.0.1",
"multiaddr-to-uri": "^5.0.0", "multiaddr": "^9.0.1",
"p-timeout": "^3.2.0" "multiaddr-to-uri": "fluencelabs/js-multiaddr-to-uri",
"p-defer": "^3.0.0",
"p-timeout": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"abort-controller": "^3.0.0", "abort-controller": "^3.0.0",
"aegir": "^20.3.1", "aegir": "^32.2.0",
"bl": "^4.0.0", "bl": "^4.0.0",
"chai": "^4.2.0", "is-loopback-addr": "^1.0.1",
"dirty-chai": "^2.0.1",
"libp2p-interfaces": "^0.2.0",
"it-goodbye": "^2.0.1", "it-goodbye": "^2.0.1",
"it-pipe": "^1.0.1", "it-pipe": "^1.0.1",
"streaming-iterables": "^4.1.0" "libp2p-interfaces": "^0.8.3",
"streaming-iterables": "^5.0.2",
"uint8arrays": "^2.1.2",
"util": "^0.12.3"
}, },
"contributors": [ "contributors": [
"Alan Shaw <alan.shaw@protocol.ai>",
"Alex Potsides <alex@achingbrain.net>",
"Chris Campbell <christopher.d.campbell@gmail.com>",
"David Dias <daviddias.p@gmail.com>", "David Dias <daviddias.p@gmail.com>",
"Diogo Silva <fsdiogo@gmail.com>",
"Dmitriy Ryajov <dryajov@gmail.com>",
"Francisco Baio Dias <xicombd@gmail.com>",
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
"Greenkeeper <support@greenkeeper.io>",
"Hugo Dias <hugomrdias@gmail.com>",
"Jack Kleeman <jackkleeman@gmail.com>",
"Jacob Heun <jacobheun@gmail.com>", "Jacob Heun <jacobheun@gmail.com>",
"Jacob Heun <jake@andyet.net>", "Vasco Santos <vasco.santos@moxy.studio>",
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
"Francisco Baio Dias <xicombd@gmail.com>",
"Dmitriy Ryajov <dryajov@gmail.com>",
"Alex Potsides <alex@achingbrain.net>",
"Hugo Dias <hugomrdias@gmail.com>",
"Maciej Krüger <mkg20001@gmail.com>", "Maciej Krüger <mkg20001@gmail.com>",
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
"Chris Campbell <christopher.d.campbell@gmail.com>",
"Diogo Silva <fsdiogo@gmail.com>",
"Irakli Gozalishvili <contact@gozala.io>",
"Jack Kleeman <jackkleeman@gmail.com>",
"Marcin Rataj <lidel@lidel.org>", "Marcin Rataj <lidel@lidel.org>",
"Michael FIG <michael+github@fig.org>", "Michael FIG <michael+github@fig.org>",
"Richard Littauer <richard.littauer@gmail.com>", "Richard Littauer <richard.littauer@gmail.com>",
"Vasco Santos <vasco.santos@moxy.studio>", "nikor <nikorpoulsen@gmail.com>",
"Vasco Santos <vasco.santos@ua.pt>", "Alan Shaw <alan.shaw@protocol.ai>"
"Victor Bjelkholm <victorbjelkholm@gmail.com>",
"dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>",
"nikor <nikorpoulsen@gmail.com>"
] ]
} }

View File

@ -4,5 +4,9 @@
exports.CODE_P2P = 421 exports.CODE_P2P = 421
exports.CODE_CIRCUIT = 290 exports.CODE_CIRCUIT = 290
exports.CODE_TCP = 6
exports.CODE_WS = 477
exports.CODE_WSS = 478
// Time to wait for a connection to close gracefully before destroying it manually // Time to wait for a connection to close gracefully before destroying it manually
exports.CLOSE_TIMEOUT = 2000 exports.CLOSE_TIMEOUT = 2000

49
src/filters.js Normal file
View File

@ -0,0 +1,49 @@
'use strict'
const mafmt = require('mafmt')
const {
CODE_CIRCUIT,
CODE_P2P,
CODE_TCP,
CODE_WS,
CODE_WSS
} = require('./constants')
module.exports = {
all: (multiaddrs) => multiaddrs.filter((ma) => {
if (ma.protoCodes().includes(CODE_CIRCUIT)) {
return false
}
const testMa = ma.decapsulateCode(CODE_P2P)
return mafmt.WebSockets.matches(testMa) ||
mafmt.WebSocketsSecure.matches(testMa)
}),
dnsWss: (multiaddrs) => multiaddrs.filter((ma) => {
if (ma.protoCodes().includes(CODE_CIRCUIT)) {
return false
}
const testMa = ma.decapsulateCode(CODE_P2P)
return mafmt.WebSocketsSecure.matches(testMa) &&
mafmt.DNS.matches(testMa.decapsulateCode(CODE_TCP).decapsulateCode(CODE_WSS))
}),
dnsWsOrWss: (multiaddrs) => multiaddrs.filter((ma) => {
if (ma.protoCodes().includes(CODE_CIRCUIT)) {
return false
}
const testMa = ma.decapsulateCode(CODE_P2P)
// WS
if (mafmt.WebSockets.matches(testMa)) {
return mafmt.DNS.matches(testMa.decapsulateCode(CODE_TCP).decapsulateCode(CODE_WS))
}
// WSS
return mafmt.WebSocketsSecure.matches(testMa) &&
mafmt.DNS.matches(testMa.decapsulateCode(CODE_TCP).decapsulateCode(CODE_WSS))
})
}

View File

@ -1,38 +1,43 @@
'use strict' 'use strict'
const connect = require('it-ws/client') const connect = require('it-ws/client')
const mafmt = require('mafmt')
const withIs = require('class-is') const withIs = require('class-is')
const toUri = require('multiaddr-to-uri') const toUri = require('multiaddr-to-uri')
const { AbortError } = require('abortable-iterator') const { AbortError } = require('abortable-iterator')
const pDefer = require('p-defer')
const log = require('debug')('libp2p:websockets') const debug = require('debug')
const log = debug('libp2p:websockets')
log.error = debug('libp2p:websockets:error')
const env = require('ipfs-utils/src/env')
const createListener = require('./listener') const createListener = require('./listener')
const toConnection = require('./socket-to-conn') const toConnection = require('./socket-to-conn')
const { CODE_CIRCUIT, CODE_P2P } = require('./constants') const filters = require('./filters')
/** /**
* @class WebSockets * @class WebSockets
*/ */
class WebSockets { class WebSockets {
/** /**
* @constructor * @class
* @param {object} options * @param {object} options
* @param {Upgrader} options.upgrader * @param {Upgrader} options.upgrader
* @param {(multiaddrs: Array<Multiaddr>) => Array<Multiaddr>} options.filter - override transport addresses filter
*/ */
constructor ({ upgrader }) { constructor ({ upgrader, filter }) {
if (!upgrader) { if (!upgrader) {
throw new Error('An upgrader must be provided. See https://github.com/libp2p/interface-transport#upgrader.') throw new Error('An upgrader must be provided. See https://github.com/libp2p/interface-transport#upgrader.')
} }
this._upgrader = upgrader this._upgrader = upgrader
this._filter = filter
} }
/** /**
* @async * @async
* @param {Multiaddr} ma * @param {Multiaddr} ma
* @param {object} [options] * @param {object} [options]
* @param {AbortSignal} [options.signal] Used to abort dial requests * @param {AbortSignal} [options.signal] - Used to abort dial requests
* @returns {Connection} An upgraded Connection * @returns {Connection} An upgraded Connection
*/ */
async dial (ma, options = {}) { async dial (ma, options = {}) {
@ -51,7 +56,7 @@ class WebSockets {
* @private * @private
* @param {Multiaddr} ma * @param {Multiaddr} ma
* @param {object} [options] * @param {object} [options]
* @param {AbortSignal} [options.signal] Used to abort dial requests * @param {AbortSignal} [options.signal] - Used to abort dial requests
* @returns {Promise<WebSocket>} Resolves a extended duplex iterable on top of a WebSocket * @returns {Promise<WebSocket>} Resolves a extended duplex iterable on top of a WebSocket
*/ */
async _connect (ma, options = {}) { async _connect (ma, options = {}) {
@ -61,10 +66,24 @@ class WebSockets {
const cOpts = ma.toOptions() const cOpts = ma.toOptions()
log('dialing %s:%s', cOpts.host, cOpts.port) log('dialing %s:%s', cOpts.host, cOpts.port)
const errorPromise = pDefer()
const errfn = (err) => {
const msg = `connection error: ${err.message}`
log.error(msg)
errorPromise.reject(err)
}
const rawSocket = connect(toUri(ma), Object.assign({ binary: true }, options)) const rawSocket = connect(toUri(ma), Object.assign({ binary: true }, options))
if (rawSocket.socket.on) {
rawSocket.socket.on('error', errfn)
} else {
rawSocket.socket.onerror = errfn
}
if (!options.signal) { if (!options.signal) {
await rawSocket.connected() await Promise.race([rawSocket.connected(), errorPromise.promise])
log('connected %s', ma) log('connected %s', ma)
return rawSocket return rawSocket
@ -75,7 +94,10 @@ class WebSockets {
const abort = new Promise((resolve, reject) => { const abort = new Promise((resolve, reject) => {
onAbort = () => { onAbort = () => {
reject(new AbortError()) reject(new AbortError())
rawSocket.close() // FIXME: https://github.com/libp2p/js-libp2p-websockets/issues/121
setTimeout(() => {
rawSocket.close()
})
} }
// Already aborted? // Already aborted?
@ -84,7 +106,7 @@ class WebSockets {
}) })
try { try {
await Promise.race([abort, rawSocket.connected()]) await Promise.race([abort, errorPromise.promise, rawSocket.connected()])
} finally { } finally {
options.signal.removeEventListener('abort', onAbort) options.signal.removeEventListener('abort', onAbort)
} }
@ -97,8 +119,9 @@ class WebSockets {
* Creates a Websockets listener. The provided `handler` function will be called * Creates a Websockets listener. The provided `handler` function will be called
* anytime a new incoming Connection has been successfully upgraded via * anytime a new incoming Connection has been successfully upgraded via
* `upgrader.upgradeInbound`. * `upgrader.upgradeInbound`.
*
* @param {object} [options] * @param {object} [options]
* @param {http.Server} [options.server] A pre-created Node.js HTTP/S server. * @param {http.Server} [options.server] - A pre-created Node.js HTTP/S server.
* @param {function (Connection)} handler * @param {function (Connection)} handler
* @returns {Listener} A Websockets listener * @returns {Listener} A Websockets listener
*/ */
@ -112,21 +135,26 @@ class WebSockets {
} }
/** /**
* Takes a list of `Multiaddr`s and returns only valid Websockets addresses * Takes a list of `Multiaddr`s and returns only valid Websockets addresses.
* By default, in a browser environment only DNS+WSS multiaddr is accepted,
* while in a Node.js environment DNS+{WS, WSS} multiaddrs are accepted.
*
* @param {Multiaddr[]} multiaddrs * @param {Multiaddr[]} multiaddrs
* @returns {Multiaddr[]} Valid Websockets multiaddrs * @returns {Multiaddr[]} Valid Websockets multiaddrs
*/ */
filter (multiaddrs) { filter (multiaddrs) {
multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs] multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
return multiaddrs.filter((ma) => { if (this._filter) {
if (ma.protoCodes().includes(CODE_CIRCUIT)) { return this._filter(multiaddrs)
return false }
}
return mafmt.WebSockets.matches(ma.decapsulateCode(CODE_P2P)) || // Browser
mafmt.WebSocketsSecure.matches(ma.decapsulateCode(CODE_P2P)) if (env.isBrowser || env.isWebWorker) {
}) return filters.dnsWss(multiaddrs)
}
return filters.all(multiaddrs)
} }
} }

View File

@ -14,16 +14,15 @@ module.exports = ({ handler, upgrader }, options = {}) => {
const listener = new EventEmitter() const listener = new EventEmitter()
const server = createServer(options, async (stream) => { const server = createServer(options, async (stream) => {
const maConn = toConnection(stream) let maConn, conn
log('new inbound connection %s', maConn.remoteAddr)
let conn
try { try {
maConn = toConnection(stream)
log('new inbound connection %s', maConn.remoteAddr)
conn = await upgrader.upgradeInbound(maConn) conn = await upgrader.upgradeInbound(maConn)
} catch (err) { } catch (err) {
log.error('inbound connection failed to upgrade', err) log.error('inbound connection failed to upgrade', err)
return maConn.close() return maConn && maConn.close()
} }
log('inbound connection %s upgraded', maConn.remoteAddr) log('inbound connection %s upgraded', maConn.remoteAddr)
@ -79,7 +78,7 @@ module.exports = ({ handler, upgrader }, options = {}) => {
Object.keys(netInterfaces).forEach((niKey) => { Object.keys(netInterfaces).forEach((niKey) => {
netInterfaces[niKey].forEach((ni) => { netInterfaces[niKey].forEach((ni) => {
if (ni.family === 'IPv4') { if (ni.family === 'IPv4') {
multiaddrs.push(multiaddr(m.toString().replace('0.0.0.0', ni.address))) multiaddrs.push(new multiaddr.Multiaddr(m.toString().replace('0.0.0.0', ni.address)))
} }
}) })
}) })

View File

@ -23,7 +23,7 @@ module.exports = (stream, options = {}) => {
await stream.sink((async function * () { await stream.sink((async function * () {
for await (const chunk of source) { for await (const chunk of source) {
// Convert BufferList to Buffer // Convert BufferList to Buffer
yield Buffer.isBuffer(chunk) ? chunk : chunk.slice() yield chunk instanceof Uint8Array ? chunk : chunk.slice()
} }
})()) })())
} catch (err) { } catch (err) {
@ -38,7 +38,8 @@ module.exports = (stream, options = {}) => {
conn: stream, conn: stream,
localAddr: options.localAddr || (stream.localAddress && stream.localPort localAddr: options.localAddr || (stream.localAddress && stream.localPort
? toMultiaddr(stream.localAddress, stream.localPort) : undefined), ? toMultiaddr(stream.localAddress, stream.localPort)
: undefined),
// If the remote address was passed, use it - it may have the peer ID encapsulated // If the remote address was passed, use it - it may have the peer ID encapsulated
remoteAddr: options.remoteAddr || toMultiaddr(stream.remoteAddress, stream.remotePort), remoteAddr: options.remoteAddr || toMultiaddr(stream.remoteAddress, stream.remotePort),

View File

@ -1,15 +1,13 @@
/* eslint-env mocha */ /* eslint-env mocha */
'use strict' 'use strict'
const chai = require('chai') const { expect } = require('aegir/utils/chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const pipe = require('it-pipe') const pipe = require('it-pipe')
const goodbye = require('it-goodbye') const goodbye = require('it-goodbye')
const { collect, take } = require('streaming-iterables') const { collect, take } = require('streaming-iterables')
const uint8ArrayFromString = require('uint8arrays/from-string')
const WS = require('../src') const WS = require('../src')
@ -19,7 +17,7 @@ const mockUpgrader = {
} }
describe('libp2p-websockets', () => { describe('libp2p-websockets', () => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/9095/ws') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9095/ws')
let ws let ws
let conn let conn
@ -29,16 +27,26 @@ describe('libp2p-websockets', () => {
}) })
it('echo', async () => { it('echo', async () => {
const message = Buffer.from('Hello World!') const message = uint8ArrayFromString('Hello World!')
const s = goodbye({ source: [message], sink: collect }) const s = goodbye({ source: [message], sink: collect })
const results = await pipe(s, conn, s) const results = await pipe(s, conn, s)
expect(results).to.eql([message]) expect(results).to.eql([message])
}) })
it('should filter out no DNS websocket addresses', function () {
const ma1 = multiaddr('/ip4/127.0.0.1/tcp/80/ws')
const ma2 = multiaddr('/ip4/127.0.0.1/tcp/443/wss')
const ma3 = multiaddr('/ip6/::1/tcp/80/ws')
const ma4 = multiaddr('/ip6/::1/tcp/443/wss')
const valid = ws.filter([ma1, ma2, ma3, ma4])
expect(valid.length).to.equal(0)
})
describe('stress', () => { describe('stress', () => {
it('one big write', async () => { it('one big write', async () => {
const rawMessage = Buffer.allocUnsafe(1000000).fill('a') const rawMessage = new Uint8Array(1000000).fill('a')
const s = goodbye({ source: [rawMessage], sink: collect }) const s = goodbye({ source: [rawMessage], sink: collect })
@ -52,7 +60,7 @@ describe('libp2p-websockets', () => {
source: pipe( source: pipe(
{ {
[Symbol.iterator] () { return this }, [Symbol.iterator] () { return this },
next: () => ({ done: false, value: Buffer.from(Math.random().toString()) }) next: () => ({ done: false, value: uint8ArrayFromString(Math.random().toString()) })
}, },
take(20000) take(20000)
), ),

View File

@ -5,16 +5,17 @@ const tests = require('libp2p-interfaces/src/transport/tests')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const http = require('http') const http = require('http')
const WS = require('../src') const WS = require('../src')
const filters = require('../src/filters')
describe('interface-transport compliance', () => { describe('interface-transport compliance', () => {
tests({ tests({
async setup ({ upgrader }) { // eslint-disable-line require-await async setup ({ upgrader }) { // eslint-disable-line require-await
const ws = new WS({ upgrader }) const ws = new WS({ upgrader, filter: filters.all })
const addrs = [ const addrs = [
multiaddr('/ip4/127.0.0.1/tcp/9091/ws'), new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9091/ws'),
multiaddr('/ip4/127.0.0.1/tcp/9092/ws'), new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9092/ws'),
multiaddr('/dns4/ipfs.io/tcp/9092/ws'), new multiaddr.Multiaddr('/dns4/ipfs.io/tcp/9092/ws'),
multiaddr('/dns4/ipfs.io/tcp/9092/wss') new multiaddr.Multiaddr('/dns4/ipfs.io/tcp/9092/wss')
] ]
let delayMs = 0 let delayMs = 0

View File

@ -5,17 +5,18 @@
const https = require('https') const https = require('https')
const fs = require('fs') const fs = require('fs')
const chai = require('chai') const AbortController = require('abort-controller').default
const dirtyChai = require('dirty-chai') const { expect } = require('aegir/utils/chai')
const expect = chai.expect
chai.use(dirtyChai)
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const goodbye = require('it-goodbye') const goodbye = require('it-goodbye')
const isLoopbackAddr = require('is-loopback-addr')
const { collect } = require('streaming-iterables') const { collect } = require('streaming-iterables')
const pipe = require('it-pipe') const pipe = require('it-pipe')
const BufferList = require('bl/BufferList') const BufferList = require('bl/BufferList')
const uint8ArrayFromString = require('uint8arrays/from-string')
const WS = require('../src') const WS = require('../src')
const filters = require('../src/filters')
require('./compliance.node') require('./compliance.node')
@ -34,7 +35,7 @@ describe('instantiate the transport', () => {
describe('listen', () => { describe('listen', () => {
describe('ip4', () => { describe('ip4', () => {
let ws let ws
const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9090/ws')
beforeEach(() => { beforeEach(() => {
ws = new WS({ upgrader: mockUpgrader }) ws = new WS({ upgrader: mockUpgrader })
@ -69,7 +70,7 @@ describe('listen', () => {
}) })
it('listen on addr with /ipfs/QmHASH', async () => { it('listen on addr with /ipfs/QmHASH', async () => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const listener = ws.createListener((conn) => { }) const listener = ws.createListener((conn) => { })
await listener.listen(ma) await listener.listen(ma)
@ -77,7 +78,7 @@ describe('listen', () => {
}) })
it('listen on port 0', async () => { it('listen on port 0', async () => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/0/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/0/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const listener = ws.createListener((conn) => { }) const listener = ws.createListener((conn) => { })
await listener.listen(ma) await listener.listen(ma)
@ -87,7 +88,7 @@ describe('listen', () => {
}) })
it('listen on any Interface', async () => { it('listen on any Interface', async () => {
const ma = multiaddr('/ip4/0.0.0.0/tcp/0/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma = new multiaddr.Multiaddr('/ip4/0.0.0.0/tcp/0/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const listener = ws.createListener((conn) => { }) const listener = ws.createListener((conn) => { })
await listener.listen(ma) await listener.listen(ma)
@ -106,7 +107,7 @@ describe('listen', () => {
}) })
it('getAddrs on port 0 listen', async () => { it('getAddrs on port 0 listen', async () => {
const addr = multiaddr('/ip4/127.0.0.1/tcp/0/ws') const addr = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/0/ws')
const listener = ws.createListener((conn) => { }) const listener = ws.createListener((conn) => { })
await listener.listen(addr) await listener.listen(addr)
const addrs = await listener.getAddrs() const addrs = await listener.getAddrs()
@ -116,7 +117,7 @@ describe('listen', () => {
}) })
it('getAddrs from listening on 0.0.0.0', async () => { it('getAddrs from listening on 0.0.0.0', async () => {
const addr = multiaddr('/ip4/0.0.0.0/tcp/9003/ws') const addr = new multiaddr.Multiaddr('/ip4/0.0.0.0/tcp/9003/ws')
const listener = ws.createListener((conn) => { }) const listener = ws.createListener((conn) => { })
await listener.listen(addr) await listener.listen(addr)
const addrs = await listener.getAddrs() const addrs = await listener.getAddrs()
@ -125,7 +126,7 @@ describe('listen', () => {
}) })
it('getAddrs from listening on 0.0.0.0 and port 0', async () => { it('getAddrs from listening on 0.0.0.0 and port 0', async () => {
const addr = multiaddr('/ip4/0.0.0.0/tcp/0/ws') const addr = new multiaddr.Multiaddr('/ip4/0.0.0.0/tcp/0/ws')
const listener = ws.createListener((conn) => { }) const listener = ws.createListener((conn) => { })
await listener.listen(addr) await listener.listen(addr)
const addrs = await listener.getAddrs() const addrs = await listener.getAddrs()
@ -135,7 +136,7 @@ describe('listen', () => {
}) })
it('getAddrs preserves p2p Id', async () => { it('getAddrs preserves p2p Id', async () => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/p2p/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9090/ws/p2p/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const listener = ws.createListener((conn) => { }) const listener = ws.createListener((conn) => { })
await listener.listen(ma) await listener.listen(ma)
@ -148,7 +149,7 @@ describe('listen', () => {
describe('ip6', () => { describe('ip6', () => {
let ws let ws
const ma = multiaddr('/ip6/::1/tcp/9091/ws') const ma = new multiaddr.Multiaddr('/ip6/::1/tcp/9091/ws')
beforeEach(() => { beforeEach(() => {
ws = new WS({ upgrader: mockUpgrader }) ws = new WS({ upgrader: mockUpgrader })
@ -183,7 +184,7 @@ describe('listen', () => {
}) })
it('listen on addr with /ipfs/QmHASH', async () => { it('listen on addr with /ipfs/QmHASH', async () => {
const ma = multiaddr('/ip6/::1/tcp/9091/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma = new multiaddr.Multiaddr('/ip6/::1/tcp/9091/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const listener = ws.createListener((conn) => { }) const listener = ws.createListener((conn) => { })
await listener.listen(ma) await listener.listen(ma)
await listener.close() await listener.close()
@ -195,7 +196,7 @@ describe('dial', () => {
describe('ip4', () => { describe('ip4', () => {
let ws let ws
let listener let listener
const ma = multiaddr('/ip4/127.0.0.1/tcp/9091/ws') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9091/ws')
beforeEach(() => { beforeEach(() => {
ws = new WS({ upgrader: mockUpgrader }) ws = new WS({ upgrader: mockUpgrader })
@ -211,21 +212,31 @@ describe('dial', () => {
const result = await pipe(s, conn, s) const result = await pipe(s, conn, s)
expect(result).to.be.eql([Buffer.from('hey')]) expect(result).to.be.eql([uint8ArrayFromString('hey')])
}) })
it('dial with p2p Id', async () => { it('dial with p2p Id', async () => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/9091/ws/p2p/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9091/ws/p2p/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const conn = await ws.dial(ma) const conn = await ws.dial(ma)
const s = goodbye({ source: ['hey'], sink: collect }) const s = goodbye({ source: ['hey'], sink: collect })
const result = await pipe(s, conn, s) const result = await pipe(s, conn, s)
expect(result).to.be.eql([Buffer.from('hey')]) expect(result).to.be.eql([uint8ArrayFromString('hey')])
})
it('dial should throw on immediate abort', async () => {
const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/0/ws')
const controller = new AbortController()
const conn = ws.dial(ma, { signal: controller.signal })
controller.abort()
await expect(conn).to.eventually.be.rejected()
}) })
it('should resolve port 0', async () => { it('should resolve port 0', async () => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/0/ws') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/0/ws')
const ws = new WS({ upgrader: mockUpgrader }) const ws = new WS({ upgrader: mockUpgrader })
// Create a Promise that resolves when a connection is handled // Create a Promise that resolves when a connection is handled
@ -252,10 +263,40 @@ describe('dial', () => {
}) })
}) })
describe('ip4 no loopback', () => {
let ws
let listener
const ma = new multiaddr.Multiaddr('/ip4/0.0.0.0/tcp/0/ws')
beforeEach(() => {
ws = new WS({ upgrader: mockUpgrader })
listener = ws.createListener(conn => pipe(conn, conn))
return listener.listen(ma)
})
afterEach(() => listener.close())
it('dial', async () => {
const addrs = listener.getAddrs().filter((ma) => {
const { address } = ma.nodeAddress()
return !isLoopbackAddr(address)
})
// Dial first no loopback address
const conn = await ws.dial(addrs[0])
const s = goodbye({ source: ['hey'], sink: collect })
const result = await pipe(s, conn, s)
expect(result).to.be.eql([uint8ArrayFromString('hey')])
})
})
describe('ip4 with wss', () => { describe('ip4 with wss', () => {
let ws let ws
let listener let listener
const ma = multiaddr('/ip4/127.0.0.1/tcp/9091/wss') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9091/wss')
const server = https.createServer({ const server = https.createServer({
cert: fs.readFileSync('./test/fixtures/certificate.pem'), cert: fs.readFileSync('./test/fixtures/certificate.pem'),
@ -276,14 +317,14 @@ describe('dial', () => {
const result = await pipe(s, conn, s) const result = await pipe(s, conn, s)
expect(result).to.be.eql([Buffer.from('hey')]) expect(result).to.be.eql([uint8ArrayFromString('hey')])
}) })
}) })
describe('ip6', () => { describe('ip6', () => {
let ws let ws
let listener let listener
const ma = multiaddr('/ip6/::1/tcp/9091') const ma = new multiaddr.Multiaddr('/ip6/::1/tcp/9091')
beforeEach(() => { beforeEach(() => {
ws = new WS({ upgrader: mockUpgrader }) ws = new WS({ upgrader: mockUpgrader })
@ -299,7 +340,7 @@ describe('dial', () => {
const result = await pipe(s, conn, s) const result = await pipe(s, conn, s)
expect(result).to.be.eql([Buffer.from('hey')]) expect(result).to.be.eql([uint8ArrayFromString('hey')])
}) })
it('dial and use BufferList', async () => { it('dial and use BufferList', async () => {
@ -308,11 +349,11 @@ describe('dial', () => {
const result = await pipe(s, conn, s) const result = await pipe(s, conn, s)
expect(result).to.be.eql([Buffer.from('hey')]) expect(result).to.be.eql([uint8ArrayFromString('hey')])
}) })
it('dial with p2p Id', async () => { it('dial with p2p Id', async () => {
const ma = multiaddr('/ip6/::1/tcp/9091/ws/p2p/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma = new multiaddr.Multiaddr('/ip6/::1/tcp/9091/ws/p2p/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const conn = await ws.dial(ma) const conn = await ws.dial(ma)
const s = goodbye({ const s = goodbye({
@ -321,7 +362,7 @@ describe('dial', () => {
}) })
const result = await pipe(s, conn, s) const result = await pipe(s, conn, s)
expect(result).to.be.eql([Buffer.from('hey')]) expect(result).to.be.eql([uint8ArrayFromString('hey')])
}) })
}) })
}) })
@ -329,65 +370,25 @@ describe('dial', () => {
describe('filter addrs', () => { describe('filter addrs', () => {
let ws let ws
before(() => { describe('default filter addrs with only dns', () => {
ws = new WS({ upgrader: mockUpgrader }) before(() => {
}) ws = new WS({ upgrader: mockUpgrader })
})
describe('filter valid addrs for this transport', function () { it('should filter out invalid WS addresses', function () {
it('should fail invalid WS addresses', function () { const ma1 = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9090')
const ma1 = multiaddr('/ip4/127.0.0.1/tcp/9090') const ma2 = new multiaddr.Multiaddr('/ip4/127.0.0.1/udp/9090')
const ma2 = multiaddr('/ip4/127.0.0.1/udp/9090') const ma3 = new multiaddr.Multiaddr('/ip6/::1/tcp/80')
const ma3 = multiaddr('/ip6/::1/tcp/80') const ma4 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/80')
const ma4 = multiaddr('/dnsaddr/ipfs.io/tcp/80')
const valid = ws.filter([ma1, ma2, ma3, ma4]) const valid = ws.filter([ma1, ma2, ma3, ma4])
expect(valid.length).to.equal(0) expect(valid.length).to.equal(0)
}) })
it('should filter correct ipv4 addresses', function () {
const ma1 = multiaddr('/ip4/127.0.0.1/tcp/80/ws')
const ma2 = multiaddr('/ip4/127.0.0.1/tcp/443/wss')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct ipv4 addresses with ipfs id', function () {
const ma1 = multiaddr('/ip4/127.0.0.1/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const ma2 = multiaddr('/ip4/127.0.0.1/tcp/80/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct ipv6 address', function () {
const ma1 = multiaddr('/ip6/::1/tcp/80/ws')
const ma2 = multiaddr('/ip6/::1/tcp/443/wss')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct ipv6 addresses with ipfs id', function () {
const ma1 = multiaddr('/ip6/::1/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const ma2 = multiaddr('/ip6/::1/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct dns address', function () { it('should filter correct dns address', function () {
const ma1 = multiaddr('/dnsaddr/ipfs.io/ws') const ma1 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/ws')
const ma2 = multiaddr('/dnsaddr/ipfs.io/tcp/80/ws') const ma2 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/80/ws')
const ma3 = multiaddr('/dnsaddr/ipfs.io/tcp/80/wss') const ma3 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/80/wss')
const valid = ws.filter([ma1, ma2, ma3]) const valid = ws.filter([ma1, ma2, ma3])
expect(valid.length).to.equal(3) expect(valid.length).to.equal(3)
@ -397,8 +398,8 @@ describe('filter addrs', () => {
}) })
it('should filter correct dns address with ipfs id', function () { it('should filter correct dns address with ipfs id', function () {
const ma1 = multiaddr('/dnsaddr/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma1 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const ma2 = multiaddr('/dnsaddr/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma2 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter([ma1, ma2]) const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2) expect(valid.length).to.equal(2)
@ -407,8 +408,8 @@ describe('filter addrs', () => {
}) })
it('should filter correct dns4 address', function () { it('should filter correct dns4 address', function () {
const ma1 = multiaddr('/dns4/ipfs.io/tcp/80/ws') const ma1 = new multiaddr.Multiaddr('/dns4/ipfs.io/tcp/80/ws')
const ma2 = multiaddr('/dns4/ipfs.io/tcp/443/wss') const ma2 = new multiaddr.Multiaddr('/dns4/ipfs.io/tcp/443/wss')
const valid = ws.filter([ma1, ma2]) const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2) expect(valid.length).to.equal(2)
@ -417,8 +418,8 @@ describe('filter addrs', () => {
}) })
it('should filter correct dns6 address', function () { it('should filter correct dns6 address', function () {
const ma1 = multiaddr('/dns6/ipfs.io/tcp/80/ws') const ma1 = new multiaddr.Multiaddr('/dns6/ipfs.io/tcp/80/ws')
const ma2 = multiaddr('/dns6/ipfs.io/tcp/443/wss') const ma2 = new multiaddr.Multiaddr('/dns6/ipfs.io/tcp/443/wss')
const valid = ws.filter([ma1, ma2]) const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2) expect(valid.length).to.equal(2)
@ -427,8 +428,116 @@ describe('filter addrs', () => {
}) })
it('should filter correct dns6 address with ipfs id', function () { it('should filter correct dns6 address with ipfs id', function () {
const ma1 = multiaddr('/dns6/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma1 = new multiaddr.Multiaddr('/dns6/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const ma2 = multiaddr('/dns6/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma2 = new multiaddr.Multiaddr('/dns6/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
})
describe('custom filter addrs', () => {
before(() => {
ws = new WS({ upgrader: mockUpgrader, filter: filters.all })
})
it('should fail invalid WS addresses', function () {
const ma1 = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9090')
const ma2 = new multiaddr.Multiaddr('/ip4/127.0.0.1/udp/9090')
const ma3 = new multiaddr.Multiaddr('/ip6/::1/tcp/80')
const ma4 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/80')
const valid = ws.filter([ma1, ma2, ma3, ma4])
expect(valid.length).to.equal(0)
})
it('should filter correct ipv4 addresses', function () {
const ma1 = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/80/ws')
const ma2 = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/443/wss')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct ipv4 addresses with ipfs id', function () {
const ma1 = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const ma2 = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/80/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct ipv6 address', function () {
const ma1 = new multiaddr.Multiaddr('/ip6/::1/tcp/80/ws')
const ma2 = new multiaddr.Multiaddr('/ip6/::1/tcp/443/wss')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct ipv6 addresses with ipfs id', function () {
const ma1 = new multiaddr.Multiaddr('/ip6/::1/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const ma2 = new multiaddr.Multiaddr('/ip6/::1/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct dns address', function () {
const ma1 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/ws')
const ma2 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/80/ws')
const ma3 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/80/wss')
const valid = ws.filter([ma1, ma2, ma3])
expect(valid.length).to.equal(3)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
expect(valid[2]).to.deep.equal(ma3)
})
it('should filter correct dns address with ipfs id', function () {
const ma1 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const ma2 = new multiaddr.Multiaddr('/dnsaddr/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct dns4 address', function () {
const ma1 = new multiaddr.Multiaddr('/dns4/ipfs.io/tcp/80/ws')
const ma2 = new multiaddr.Multiaddr('/dns4/ipfs.io/tcp/443/wss')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct dns6 address', function () {
const ma1 = new multiaddr.Multiaddr('/dns6/ipfs.io/tcp/80/ws')
const ma2 = new multiaddr.Multiaddr('/dns6/ipfs.io/tcp/443/wss')
const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2)
expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma2)
})
it('should filter correct dns6 address with ipfs id', function () {
const ma1 = new multiaddr.Multiaddr('/dns6/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const ma2 = new multiaddr.Multiaddr('/dns6/ipfs.io/tcp/443/wss/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter([ma1, ma2]) const valid = ws.filter([ma1, ma2])
expect(valid.length).to.equal(2) expect(valid.length).to.equal(2)
@ -437,11 +546,11 @@ describe('filter addrs', () => {
}) })
it('should filter mixed addresses', function () { it('should filter mixed addresses', function () {
const ma1 = multiaddr('/dns6/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma1 = new multiaddr.Multiaddr('/dns6/ipfs.io/tcp/80/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const ma2 = multiaddr('/ip4/127.0.0.1/tcp/9090') const ma2 = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9090')
const ma3 = multiaddr('/ip4/127.0.0.1/udp/9090') const ma3 = new multiaddr.Multiaddr('/ip4/127.0.0.1/udp/9090')
const ma4 = multiaddr('/dns6/ipfs.io/ws') const ma4 = new multiaddr.Multiaddr('/dns6/ipfs.io/ws')
const mh5 = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw' + const mh5 = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw' +
'/p2p-circuit/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') '/p2p-circuit/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter([ma1, ma2, ma3, ma4, mh5]) const valid = ws.filter([ma1, ma2, ma3, ma4, mh5])
@ -449,14 +558,13 @@ describe('filter addrs', () => {
expect(valid[0]).to.deep.equal(ma1) expect(valid[0]).to.deep.equal(ma1)
expect(valid[1]).to.deep.equal(ma4) expect(valid[1]).to.deep.equal(ma4)
}) })
})
it('filter a single addr for this transport', (done) => { it('filter a single addr for this transport', () => {
const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw') const ma = new multiaddr.Multiaddr('/ip4/127.0.0.1/tcp/9090/ws/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw')
const valid = ws.filter(ma) const valid = ws.filter(ma)
expect(valid.length).to.equal(1) expect(valid.length).to.equal(1)
expect(valid[0]).to.deep.equal(ma) expect(valid[0]).to.deep.equal(ma)
done() })
}) })
}) })