Skip to content
This repository has been archived by the owner on Jul 21, 2023. It is now read-only.

follow new transport and connection spec #14

Merged
merged 1 commit into from
Jun 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .aegir.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict'

module.exports = {
webpack: {
resolve: {
},
externals: {
'simple-websocket-server': '{}'
}
}
}
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ 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/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
![](https://img.shields.io/badge/coverage-%3F-yellow.svg?style=flat-square)
[![Dependency Status](https://david-dm.org/diasdavid/js-libp2p-websockets.svg?style=flat-square)](https://david-dm.org/diasdavid/js-libp2p-websockets)
[![Dependency Status](https://david-dm.org/libp2p/js-libp2p-websockets.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websockets)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)

![](https://raw.githubusercontent.com/diasdavid/interace-connection/master/img/badge.png)
![](https://raw.githubusercontent.com/diasdavid/interface-transport/master/img/badge.png)

> JavaScript implementation of the WebSockets module that libp2p uses and that implements the interface-transport interface

![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png)
![](https://raw.githubusercontent.com/libp2p/interface-transport/master/img/badge.png)

> JavaScript implementation of the WebSockets module that libp2p uses and that implements the interface-transport interface
17 changes: 9 additions & 8 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@

const gulp = require('gulp')
const multiaddr = require('multiaddr')
const WSlibp2p = require('./src')
const WS = require('./src')

let ws
let listener

gulp.task('test:browser:before', (done) => {
ws = new WSlibp2p()
const mh = multiaddr('/ip4/127.0.0.1/tcp/9090/ws')
ws.createListener(mh, (socket) => {
socket.pipe(socket)
}, done)
const ws = new WS()
const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws')
listener = ws.createListener((conn) => {
conn.pipe(conn)
})
listener.listen(ma, done)
})

gulp.task('test:browser:after', (done) => {
ws.close(done)
listener.close(done)
})

require('aegir/gulp')(gulp)
14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,25 @@
},
"homepage": "https://github.com/diasdavid/js-libp2p-websockets#readme",
"dependencies": {
"detect-node": "^2.0.3",
"interface-connection": "^0.1.3",
"lodash.contains": "^2.4.3",
"mafmt": "^2.1.0",
"multiaddr": "^2.0.2",
"run-parallel": "^1.1.6",
"simple-websocket": "github:diasdavid/simple-websocket#ec31437"
"simple-websocket": "^4.1.0",
"simple-websocket-server": "^0.1.4"
},
"devDependencies": {
"aegir": "^3.2.0",
"multiaddr": "^2.0.2",
"chai": "^3.5.0",
"aegir": "^3.0.1",
"gulp": "^3.9.1",
"interface-connection": "0.0.3",
"interface-transport": "^0.1.1",
"interface-transport": "^0.2.0",
"pre-commit": "^1.1.2"
},
"contributors": [
"David Dias <daviddias.p@gmail.com>",
"Francisco Baio Dias <xicombd@gmail.com>",
"Friedel Ziegelmayer <dignifiedquire@gmail.com>"
]
}
}
140 changes: 101 additions & 39 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@

const debug = require('debug')
const log = debug('libp2p:websockets')
const SWS = require('simple-websocket')
const SW = require('simple-websocket')
const isNode = require('detect-node')
let SWS
if (isNode) {
SWS = require('simple-websocket-server')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this still requires to have a fake simple-websocket-server in the webpack config :/ not sure how to better solve it though

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We get some warning of missing deps, namely:

WARNING in ./~/ws/lib/Validation.js
Module not found: Error: Can't resolve 'utf-8-validate' in '/Users/david/code/js-libp2p-websockets/node_modules/ws/lib'
 @ ./~/ws/lib/Validation.js 10:19-44

WARNING in ./~/ws/lib/BufferUtil.js
Module not found: Error: Can't resolve 'bufferutil' in '/Users/david/code/js-libp2p-websockets/node_modules/ws/lib'
 @ ./~/ws/lib/BufferUtil.js 10:19-40

But since the execution never goes there, no error is caused. Do we need to 'fix' these warnings?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better, try adding 'simple-websocket-server': '{}' to the externals list

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. no more warnings.

} else {
SWS = {}
}
const mafmt = require('mafmt')
const parallel = require('run-parallel')
const contains = require('lodash.contains')
const Connection = require('interface-connection').Connection

const CLOSE_TIMEOUT = 2000
// const IPFS_CODE = 421

exports = module.exports = WebSockets

Expand All @@ -14,66 +24,118 @@ function WebSockets () {
return new WebSockets()
}

const listeners = []

this.dial = function (multiaddr, options) {
if (!options) {
this.dial = function (ma, options, callback) {
if (typeof options === 'function') {
callback = options
options = {}
}

options.ready = options.ready || function noop () {}
const maOpts = multiaddr.toOptions()
const conn = new SWS('ws://' + maOpts.host + ':' + maOpts.port)
conn.on('connect', options.ready)
conn.getObservedAddrs = () => {
return [multiaddr]
if (!callback) {
callback = function noop () {}
}

const maOpts = ma.toOptions()

const socket = new SW('ws://' + maOpts.host + ':' + maOpts.port)

const conn = new Connection(socket)

socket.on('timeout', () => {
conn.emit('timeout')
})

socket.on('error', (err) => {
callback(err)
conn.emit('error', err)
})

socket.on('connect', () => {
callback(null, conn)
conn.emit('connect')
})

conn.getObservedAddrs = (cb) => {
return cb(null, [ma])
}

return conn
}

this.createListener = (multiaddrs, options, handler, callback) => {
this.createListener = (options, handler) => {
if (typeof options === 'function') {
callback = handler
handler = options
options = {}
}

if (!Array.isArray(multiaddrs)) {
multiaddrs = [multiaddrs]
}
const listener = SWS.createServer((socket) => {
const conn = new Connection(socket)

var count = 0
conn.getObservedAddrs = (cb) => {
// TODO research if we can reuse the address in anyway
return cb(null, [])
}
handler(conn)
})

let listeningMultiaddr

multiaddrs.forEach((m) => {
if (contains(m.protoNames(), 'ipfs')) {
m = m.decapsulate('ipfs')
listener._listen = listener.listen
listener.listen = (ma, callback) => {
if (!callback) {
callback = function noop () {}
}

const listener = SWS.createServer((conn) => {
conn.getObservedAddrs = () => {
return [] // TODO think if it makes sense for WebSockets
}
handler(conn)
})
listeningMultiaddr = ma

if (contains(ma.protoNames(), 'ipfs')) {
ma = ma.decapsulate('ipfs')
}

listener.listen(m.toOptions().port, () => {
if (++count === multiaddrs.length) {
callback()
listener._listen(ma.toOptions(), callback)
}

listener._close = listener.close
listener.close = (options, callback) => {
if (typeof options === 'function') {
callback = options
options = { timeout: CLOSE_TIMEOUT }
}
if (!callback) { callback = function noop () {} }
if (!options) { options = { timeout: CLOSE_TIMEOUT } }

let closed = false
listener.once('close', () => {
closed = true
})
listener._close(callback)
setTimeout(() => {
if (closed) {
return
}
log('unable to close graciously, destroying conns')
Object.keys(listener.__connections).forEach((key) => {
log('destroying %s', key)
listener.__connections[key].destroy()
})
}, options.timeout || CLOSE_TIMEOUT)
}

// Keep track of open connections to destroy in case of timeout
listener.__connections = {}
listener.on('connection', (socket) => {
const key = (~~(Math.random() * 1e9)).toString(36) + Date.now()
listener.__connections[key] = socket

socket.on('close', () => {
delete listener.__connections[key]
})
listeners.push(listener)
})
}

this.close = (callback) => {
if (listeners.length === 0) {
log('Called close with no active listeners')
return callback()
listener.getAddrs = (callback) => {
callback(null, [listeningMultiaddr])
}

parallel(listeners.map((listener) => {
return (cb) => listener.close(cb)
}), callback)
return listener
}

this.filter = (multiaddrs) => {
Expand Down
13 changes: 6 additions & 7 deletions test/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@

const expect = require('chai').expect
const multiaddr = require('multiaddr')
const WSlibp2p = require('../src')
const WS = require('../src')

describe('libp2p-websockets', function () {
this.timeout(10000)
var ws
describe('libp2p-websockets', () => {
let ws

it('create', (done) => {
ws = new WSlibp2p()
ws = new WS()
expect(ws).to.exist
done()
})

it('echo', (done) => {
const mh = multiaddr('/ip4/127.0.0.1/tcp/9090/ws')
const conn = ws.dial(mh)
const ma = multiaddr('/ip4/127.0.0.1/tcp/9090/ws')
const conn = ws.dial(ma)
const message = 'Hello World!'
conn.write(message)
conn.on('data', (data) => {
Expand Down
Loading