libp2p-tcp
Advanced tools
Comparing version 0.6.2 to 0.7.0
250
lib/index.js
@@ -9,4 +9,6 @@ 'use strict'; | ||
var mafmt = require('mafmt'); | ||
var parallel = require('run-parallel'); | ||
// const parallel = require('run-parallel') | ||
var contains = require('lodash.contains'); | ||
var os = require('os'); | ||
var Connection = require('interface-connection').Connection; | ||
@@ -16,3 +18,3 @@ exports = module.exports = TCP; | ||
var IPFS_CODE = 421; | ||
var CLOSE_TIMEOUT = 300; | ||
var CLOSE_TIMEOUT = 2000; | ||
@@ -24,101 +26,177 @@ function TCP() { | ||
var 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() {}; | ||
var conn = tcp.connect(multiaddr.toOptions(), options.ready); | ||
conn.getObservedAddrs = function () { | ||
return [multiaddr]; | ||
if (!callback) { | ||
callback = function noop() {}; | ||
} | ||
var socket = tcp.connect(ma.toOptions()); | ||
var conn = new Connection(socket); | ||
socket.on('timeout', function () { | ||
conn.emit('timeout'); | ||
}); | ||
socket.on('error', function (err) { | ||
callback(err); | ||
conn.emit('error', err); | ||
}); | ||
socket.on('connect', function () { | ||
callback(null, conn); | ||
conn.emit('connect'); | ||
}); | ||
conn.getObservedAddrs = function (cb) { | ||
return cb(null, [ma]); | ||
}; | ||
return conn; | ||
}; | ||
this.createListener = function (multiaddrs, handler, callback) { | ||
if (!Array.isArray(multiaddrs)) { | ||
multiaddrs = [multiaddrs]; | ||
this.createListener = function (options, handler) { | ||
if (typeof options === 'function') { | ||
handler = options; | ||
options = {}; | ||
} | ||
var freshMultiaddrs = []; | ||
var listener = tcp.createServer(function (socket) { | ||
var conn = new Connection(socket); | ||
parallel(multiaddrs.map(function (m) { | ||
return function (cb) { | ||
var ipfsHashId = void 0; | ||
if (contains(m.protoNames(), 'ipfs')) { | ||
ipfsHashId = m.stringTuples().filter(function (tuple) { | ||
if (tuple[0] === IPFS_CODE) { | ||
return true; | ||
} | ||
})[0][1]; | ||
m = m.decapsulate('ipfs'); | ||
} | ||
conn.getObservedAddrs = function (cb) { | ||
return cb(null, [getMultiaddr(socket)]); | ||
}; | ||
handler(conn); | ||
}); | ||
var listener = tcp.createServer(function (conn) { | ||
conn.getObservedAddrs = function () { | ||
return [getMultiaddr(conn)]; | ||
}; | ||
handler(conn); | ||
}); | ||
var ipfsId = void 0; | ||
var listeningMultiaddr = void 0; | ||
listener.__connections = {}; | ||
listener.on('connection', function (conn) { | ||
var key = conn.remoteAddress + ':' + conn.remotePort; | ||
listener.__connections[key] = conn; | ||
listener._listen = listener.listen; | ||
listener.listen = function (ma, callback) { | ||
listeningMultiaddr = ma; | ||
if (contains(ma.protoNames(), 'ipfs')) { | ||
ipfsId = ma.stringTuples().filter(function (tuple) { | ||
if (tuple[0] === IPFS_CODE) { | ||
return true; | ||
} | ||
})[0][1]; | ||
listeningMultiaddr = ma.decapsulate('ipfs'); | ||
} | ||
conn.on('close', function () { | ||
delete listener.__connections[key]; | ||
}); | ||
listener._listen(listeningMultiaddr.toOptions(), callback); | ||
}; | ||
listener._close = listener.close; | ||
listener.close = function (options, callback) { | ||
if (typeof options === 'function') { | ||
callback = options; | ||
options = {}; | ||
} | ||
if (!callback) { | ||
callback = function noop() {}; | ||
} | ||
if (!options) { | ||
options = {}; | ||
} | ||
var closed = false; | ||
listener._close(callback); | ||
listener.once('close', function () { | ||
closed = true; | ||
}); | ||
setTimeout(function () { | ||
if (closed) { | ||
return; | ||
} | ||
log('unable to close graciously, destroying conns'); | ||
Object.keys(listener.__connections).forEach(function (key) { | ||
log('destroying %s', key); | ||
listener.__connections[key].destroy(); | ||
}); | ||
}, options.timeout || CLOSE_TIMEOUT); | ||
}; | ||
listener.listen(m.toOptions(), function () { | ||
// Node.js likes to convert addr to IPv6 (when 0.0.0.0 for e.g) | ||
var address = listener.address(); | ||
if (m.toString().indexOf('ip4')) { | ||
m = m.decapsulate('tcp'); | ||
m = m.encapsulate('/tcp/' + address.port); | ||
if (ipfsHashId) { | ||
m = m.encapsulate('/ipfs/' + ipfsHashId); | ||
} | ||
freshMultiaddrs.push(m); | ||
} | ||
// Keep track of open connections to destroy in case of timeout | ||
listener.__connections = {}; | ||
listener.on('connection', function (socket) { | ||
var key = socket.remoteAddress + ':' + socket.remotePort; | ||
listener.__connections[key] = socket; | ||
if (address.family === 'IPv6') { | ||
var mh = multiaddr('/ip6/' + address.address + '/tcp/' + address.port); | ||
if (ipfsHashId) { | ||
mh = mh.encapsulate('/ipfs/' + ipfsHashId); | ||
} | ||
socket.on('close', function () { | ||
delete listener.__connections[key]; | ||
}); | ||
}); | ||
freshMultiaddrs.push(mh); | ||
listener.getAddrs = function (callback) { | ||
var multiaddrs = []; | ||
var address = listener.address(); | ||
// Because TCP will only return the IPv6 version | ||
// we need to capture from the passed multiaddr | ||
if (listeningMultiaddr.toString().indexOf('ip4') !== -1) { | ||
(function () { | ||
var m = listeningMultiaddr.decapsulate('tcp'); | ||
m = m.encapsulate('/tcp/' + address.port); | ||
if (ipfsId) { | ||
m = m.encapsulate('/ipfs/' + ipfsId); | ||
} | ||
cb(); | ||
}); | ||
listeners.push(listener); | ||
}; | ||
}), function (err) { | ||
callback(err, freshMultiaddrs); | ||
}); | ||
}; | ||
if (m.toString().indexOf('0.0.0.0') !== -1) { | ||
(function () { | ||
var netInterfaces = os.networkInterfaces(); | ||
Object.keys(netInterfaces).forEach(function (niKey) { | ||
netInterfaces[niKey].forEach(function (ni) { | ||
if (ni.family === 'IPv4') { | ||
multiaddrs.push(multiaddr(m.toString().replace('0.0.0.0', ni.address))); | ||
} | ||
}); | ||
}); | ||
})(); | ||
} else { | ||
multiaddrs.push(m); | ||
} | ||
})(); | ||
} | ||
this.close = function (callback) { | ||
log('closing'); | ||
if (listeners.length === 0) { | ||
log('Called close with no active listeners'); | ||
return callback(); | ||
} | ||
if (address.family === 'IPv6') { | ||
var ma = multiaddr('/ip6/' + address.address + '/tcp/' + address.port); | ||
if (ipfsId) { | ||
ma = ma.encapsulate('/ipfs/' + ipfsId); | ||
} | ||
parallel(listeners.map(function (listener) { | ||
return function (cb) { | ||
setTimeout(function () { | ||
Object.keys(listener.__connections).forEach(function (key) { | ||
log('destroying %s', key); | ||
listener.__connections[key].destroy(); | ||
}); | ||
}, CLOSE_TIMEOUT); | ||
multiaddrs.push(ma); | ||
} | ||
listener.close(cb); | ||
}; | ||
}), callback); | ||
callback(null, multiaddrs); | ||
}; | ||
return listener; | ||
/* | ||
listener.listen(m.toOptions(), () => { | ||
// Node.js likes to convert addr to IPv6 (when 0.0.0.0 for e.g) | ||
const address = listener.address() | ||
if (m.toString().indexOf('ip4')) { | ||
m = m.decapsulate('tcp') | ||
m = m.encapsulate('/tcp/' + address.port) | ||
if (ipfsHashId) { | ||
m = m.encapsulate('/ipfs/' + ipfsHashId) | ||
} | ||
freshMultiaddrs.push(m) | ||
} | ||
if (address.family === 'IPv6') { | ||
let mh = multiaddr('/ip6/' + address.address + '/tcp/' + address.port) | ||
if (ipfsHashId) { | ||
mh = mh.encapsulate('/ipfs/' + ipfsHashId) | ||
} | ||
freshMultiaddrs.push(mh) | ||
} | ||
cb() | ||
}) | ||
listeners.push(listener) | ||
*/ | ||
}; | ||
@@ -139,15 +217,15 @@ | ||
function getMultiaddr(conn) { | ||
function getMultiaddr(socket) { | ||
var mh; | ||
if (conn.remoteFamily === 'IPv6') { | ||
var addr = new Address6(conn.remoteAddress); | ||
if (socket.remoteFamily === 'IPv6') { | ||
var addr = new Address6(socket.remoteAddress); | ||
if (addr.v4) { | ||
var ip4 = addr.to4().correctForm(); | ||
mh = multiaddr('/ip4/' + ip4 + '/tcp/' + conn.remotePort); | ||
mh = multiaddr('/ip4/' + ip4 + '/tcp/' + socket.remotePort); | ||
} else { | ||
mh = multiaddr('/ip6/' + conn.remoteAddress + '/tcp/' + conn.remotePort); | ||
mh = multiaddr('/ip6/' + socket.remoteAddress + '/tcp/' + socket.remotePort); | ||
} | ||
} else { | ||
mh = multiaddr('/ip4/' + conn.remoteAddress + '/tcp/' + conn.remotePort); | ||
mh = multiaddr('/ip4/' + socket.remoteAddress + '/tcp/' + socket.remotePort); | ||
} | ||
@@ -154,0 +232,0 @@ |
{ | ||
"name": "libp2p-tcp", | ||
"version": "0.6.2", | ||
"version": "0.7.0", | ||
"description": "Node.js implementation of the TCP module that libp2p uses, which implements the interface-connection and interface-transport interfaces", | ||
@@ -37,4 +37,3 @@ "main": "lib/index.js", | ||
"chai": "^3.5.0", | ||
"interface-connection": "0.0.3", | ||
"interface-transport": "^0.1.1", | ||
"interface-transport": "^0.2.0", | ||
"pre-commit": "^1.1.2", | ||
@@ -44,2 +43,4 @@ "tape": "^4.5.1" | ||
"dependencies": { | ||
"duplexify": "^3.4.3", | ||
"interface-connection": "0.1.2", | ||
"ip-address": "^5.8.0", | ||
@@ -46,0 +47,0 @@ "lodash.contains": "^2.4.3", |
@@ -6,12 +6,12 @@ js-libp2p-tcp | ||
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) | ||
[![Build Status](https://travis-ci.org/diasdavid/js-libp2p-tcp.svg?style=flat-square)](https://travis-ci.org/diasdavid/js-libp2p-tcp) | ||
[![Build Status](https://travis-ci.org/libp2p/js-libp2p-tcp.svg?style=flat-square)](https://travis-ci.org/libp2p/js-libp2p-tcp) | ||
![](https://img.shields.io/badge/coverage-%3F-yellow.svg?style=flat-square) | ||
[![Dependency Status](https://david-dm.org/diasdavid/js-libp2p-tcp.svg?style=flat-square)](https://david-dm.org/diasdavid/js-libp2p-tcp) | ||
[![Dependency Status](https://david-dm.org/libp2p/js-libp2p-tcp.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-tcp) | ||
[![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/abstract-connection/master/img/badge.png) | ||
![](https://raw.githubusercontent.com/diasdavid/abstract-transport/master/img/badge.png) | ||
![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png) | ||
![](https://raw.githubusercontent.com/libp2p/interface-transport/master/img/badge.png) | ||
> Node.js implementation of the TCP module that libp2p uses, which implements | ||
> the [interface-connection](https://github.com/diasdavid/interface-connection) | ||
> the [interface-connection](https://github.com/libp2p/interface-connection) | ||
> interface for dial/listen. | ||
@@ -28,3 +28,3 @@ | ||
```js | ||
const Tcp = require('libp2p-tcp') | ||
const TCP = require('libp2p-tcp') | ||
const multiaddr = require('multiaddr') | ||
@@ -37,6 +37,8 @@ | ||
tcp.createListener([mh1, mh2], function handler (socket) { | ||
var listener = tcp.createListener(mh1, function handler (socket) { | ||
console.log('connection') | ||
socket.end('bye') | ||
}, function ready () { | ||
}) | ||
var listener.listen(function ready () { | ||
console.log('ready') | ||
@@ -71,30 +73,13 @@ | ||
```js | ||
const Tcp = require('libp2p-tcp') | ||
``` | ||
[![](https://raw.githubusercontent.com/diasdavid/interface-transport/master/img/badge.png)](https://github.com/diasdavid/interface-transport) | ||
### var tcp = new Tcp() | ||
`libp2p-tcp` accepts TCP addresses both IPFS and non IPFS encapsulated addresses, i.e: | ||
Creates a new TCP object. This does nothing on its own, but provides access to | ||
`dial` and `createListener`. | ||
`/ip4/127.0.0.1/tcp/4001` | ||
`/ip4/127.0.0.1/tcp/4001/ipfs/QmHash` | ||
### tcp.createListener(multiaddrs, handler, ready) | ||
Both for dialing and listening. | ||
Creates TCP servers that listen on the addresses described in the array | ||
`multiaddrs`. Each connection will call `handler` with a connection stream. | ||
`ready` is called once all servers are listening. | ||
### tcp.dial(multiaddr, options={}) | ||
Connects to the multiaddress `multiaddr` using TCP, returning the socket stream. | ||
If `options.ready` is set to a function, it is called when a connection is | ||
established. | ||
### tcp.close(callback) | ||
Closes all the listening TCP servers, calling `callback` once all of them have | ||
been shut down. | ||
## License | ||
MIT |
195
src/index.js
@@ -9,4 +9,6 @@ 'use strict' | ||
const mafmt = require('mafmt') | ||
const parallel = require('run-parallel') | ||
// const parallel = require('run-parallel') | ||
const contains = require('lodash.contains') | ||
const os = require('os') | ||
const Connection = require('interface-connection').Connection | ||
@@ -16,3 +18,3 @@ exports = module.exports = TCP | ||
const IPFS_CODE = 421 | ||
const CLOSE_TIMEOUT = 300 | ||
const CLOSE_TIMEOUT = 2000 | ||
@@ -24,27 +26,59 @@ function TCP () { | ||
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 conn = tcp.connect(multiaddr.toOptions(), options.ready) | ||
conn.getObservedAddrs = () => { | ||
return [multiaddr] | ||
if (!callback) { | ||
callback = function noop () {} | ||
} | ||
const socket = tcp.connect(ma.toOptions()) | ||
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, handler, callback) => { | ||
if (!Array.isArray(multiaddrs)) { | ||
multiaddrs = [multiaddrs] | ||
this.createListener = (options, handler) => { | ||
if (typeof options === 'function') { | ||
handler = options | ||
options = {} | ||
} | ||
const freshMultiaddrs = [] | ||
const listener = tcp.createServer((socket) => { | ||
const conn = new Connection(socket) | ||
parallel(multiaddrs.map((m) => (cb) => { | ||
let ipfsHashId | ||
if (contains(m.protoNames(), 'ipfs')) { | ||
ipfsHashId = m.stringTuples().filter((tuple) => { | ||
conn.getObservedAddrs = (cb) => { | ||
return cb(null, [getMultiaddr(socket)]) | ||
} | ||
handler(conn) | ||
}) | ||
let ipfsId | ||
let listeningMultiaddr | ||
listener._listen = listener.listen | ||
listener.listen = (ma, callback) => { | ||
listeningMultiaddr = ma | ||
if (contains(ma.protoNames(), 'ipfs')) { | ||
ipfsId = ma.stringTuples().filter((tuple) => { | ||
if (tuple[0] === IPFS_CODE) { | ||
@@ -54,22 +88,86 @@ return true | ||
})[0][1] | ||
m = m.decapsulate('ipfs') | ||
listeningMultiaddr = ma.decapsulate('ipfs') | ||
} | ||
const listener = tcp.createServer((conn) => { | ||
conn.getObservedAddrs = () => { | ||
return [getMultiaddr(conn)] | ||
listener._listen(listeningMultiaddr.toOptions(), callback) | ||
} | ||
listener._close = listener.close | ||
listener.close = (options, callback) => { | ||
if (typeof options === 'function') { | ||
callback = options | ||
options = {} | ||
} | ||
if (!callback) { callback = function noop () {} } | ||
if (!options) { options = {} } | ||
let closed = false | ||
listener._close(callback) | ||
listener.once('close', () => { | ||
closed = true | ||
}) | ||
setTimeout(() => { | ||
if (closed) { | ||
return | ||
} | ||
handler(conn) | ||
}) | ||
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) | ||
} | ||
listener.__connections = {} | ||
listener.on('connection', (conn) => { | ||
const key = `${conn.remoteAddress}:${conn.remotePort}` | ||
listener.__connections[key] = conn | ||
// Keep track of open connections to destroy in case of timeout | ||
listener.__connections = {} | ||
listener.on('connection', (socket) => { | ||
const key = `${socket.remoteAddress}:${socket.remotePort}` | ||
listener.__connections[key] = socket | ||
conn.on('close', () => { | ||
delete listener.__connections[key] | ||
}) | ||
socket.on('close', () => { | ||
delete listener.__connections[key] | ||
}) | ||
}) | ||
listener.getAddrs = (callback) => { | ||
const multiaddrs = [] | ||
const address = listener.address() | ||
// Because TCP will only return the IPv6 version | ||
// we need to capture from the passed multiaddr | ||
if (listeningMultiaddr.toString().indexOf('ip4') !== -1) { | ||
let m = listeningMultiaddr.decapsulate('tcp') | ||
m = m.encapsulate('/tcp/' + address.port) | ||
if (ipfsId) { | ||
m = m.encapsulate('/ipfs/' + ipfsId) | ||
} | ||
if (m.toString().indexOf('0.0.0.0') !== -1) { | ||
const netInterfaces = os.networkInterfaces() | ||
Object.keys(netInterfaces).forEach((niKey) => { | ||
netInterfaces[niKey].forEach((ni) => { | ||
if (ni.family === 'IPv4') { | ||
multiaddrs.push(multiaddr(m.toString().replace('0.0.0.0', ni.address))) | ||
} | ||
}) | ||
}) | ||
} else { | ||
multiaddrs.push(m) | ||
} | ||
} | ||
if (address.family === 'IPv6') { | ||
let ma = multiaddr('/ip6/' + address.address + '/tcp/' + address.port) | ||
if (ipfsId) { | ||
ma = ma.encapsulate('/ipfs/' + ipfsId) | ||
} | ||
multiaddrs.push(ma) | ||
} | ||
callback(null, multiaddrs) | ||
} | ||
return listener | ||
/* | ||
listener.listen(m.toOptions(), () => { | ||
@@ -99,26 +197,5 @@ // Node.js likes to convert addr to IPv6 (when 0.0.0.0 for e.g) | ||
listeners.push(listener) | ||
}), (err) => { | ||
callback(err, freshMultiaddrs) | ||
}) | ||
*/ | ||
} | ||
this.close = (callback) => { | ||
log('closing') | ||
if (listeners.length === 0) { | ||
log('Called close with no active listeners') | ||
return callback() | ||
} | ||
parallel(listeners.map((listener) => (cb) => { | ||
setTimeout(() => { | ||
Object.keys(listener.__connections).forEach((key) => { | ||
log('destroying %s', key) | ||
listener.__connections[key].destroy() | ||
}) | ||
}, CLOSE_TIMEOUT) | ||
listener.close(cb) | ||
}), callback) | ||
} | ||
this.filter = (multiaddrs) => { | ||
@@ -137,15 +214,15 @@ if (!Array.isArray(multiaddrs)) { | ||
function getMultiaddr (conn) { | ||
function getMultiaddr (socket) { | ||
var mh | ||
if (conn.remoteFamily === 'IPv6') { | ||
var addr = new Address6(conn.remoteAddress) | ||
if (socket.remoteFamily === 'IPv6') { | ||
var addr = new Address6(socket.remoteAddress) | ||
if (addr.v4) { | ||
var ip4 = addr.to4().correctForm() | ||
mh = multiaddr('/ip4/' + ip4 + '/tcp/' + conn.remotePort) | ||
mh = multiaddr('/ip4/' + ip4 + '/tcp/' + socket.remotePort) | ||
} else { | ||
mh = multiaddr('/ip6/' + conn.remoteAddress + '/tcp/' + conn.remotePort) | ||
mh = multiaddr('/ip6/' + socket.remoteAddress + '/tcp/' + socket.remotePort) | ||
} | ||
} else { | ||
mh = multiaddr('/ip4/' + conn.remoteAddress + '/tcp/' + conn.remotePort) | ||
mh = multiaddr('/ip4/' + socket.remoteAddress + '/tcp/' + socket.remotePort) | ||
} | ||
@@ -152,0 +229,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18406
5
385
7
82
3
+ Addedduplexify@^3.4.3
+ Addedinterface-connection@0.1.2
+ Addedcore-util-is@1.0.3(transitive)
+ Addedduplexify@3.7.1(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedinterface-connection@0.1.2(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedreadable-stream@2.3.8(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedstream-shift@1.0.3(transitive)
+ Addedstring_decoder@1.1.1(transitive)
+ Addedtimed-tape@0.1.1(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addedwrappy@1.0.2(transitive)