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

Commit

Permalink
follow new transport and connection spec
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddias committed Jun 22, 2016
1 parent 0ee73f0 commit bbc92b9
Show file tree
Hide file tree
Showing 7 changed files with 389 additions and 124 deletions.
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')
} 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

0 comments on commit bbc92b9

Please sign in to comment.