Socket
Socket
Sign inDemoInstall

libp2p-tcp

Package Overview
Dependencies
36
Maintainers
4
Versions
57
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.15.4 to 0.16.0

.aegir.js

9

CHANGELOG.md

@@ -0,1 +1,10 @@

# [0.16.0](https://github.com/libp2p/js-libp2p-tcp/compare/v0.15.4...v0.16.0) (2021-06-10)
### Features
* add types ([#145](https://github.com/libp2p/js-libp2p-tcp/issues/145)) ([3249e02](https://github.com/libp2p/js-libp2p-tcp/commit/3249e0292b2ef5d818fe428ce61f689b25060d85))
## [0.15.4](https://github.com/libp2p/js-libp2p-tcp/compare/v0.15.2...v0.15.4) (2021-04-12)

@@ -2,0 +11,0 @@

20

package.json
{
"name": "libp2p-tcp",
"version": "0.15.4",
"version": "0.16.0",
"description": "Node.js implementation of the TCP module that libp2p uses, which implements the interface-connection and interface-transport interfaces",

@@ -9,7 +9,8 @@ "leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",

"lint": "aegir lint",
"build": "aegir build",
"test": "aegir test -t node",
"test:node": "aegir test -t node",
"release": "aegir release -t node --no-build",
"release-minor": "aegir release -t node --type minor --no-build",
"release-major": "aegir-release -t node --type major --no-build",
"release": "aegir release -t node",
"release-minor": "aegir release -t node --type minor",
"release-major": "aegir-release -t node --type major",
"coverage": "nyc --reporter=text --reporter=lcov npm run test:node"

@@ -41,6 +42,8 @@ },

},
"types": "dist/src/index.d.ts",
"devDependencies": {
"aegir": "^33.0.0",
"@types/debug": "^4.1.5",
"aegir": "^33.2.0",
"it-pipe": "^1.1.0",
"libp2p-interfaces": "^0.9.0",
"libp2p-interfaces": "^0.11.0",
"sinon": "^10.0.1",

@@ -69,6 +72,7 @@ "streaming-iterables": "^5.0.2"

"Alan Shaw <alan@tableflip.io>",
"Nazar Hussain <nazarhussain@gmail.com>",
"Pedro Teixeira <i@pgte.me>",
"Prashanth Chandra <coolshanth94@gmail.com>",
"Ryan Mehta <ryan.mehta@gmail.com>",
"João Antunes <j.goncalo.antunes@gmail.com>",
"Linus Unnebäck <linus@folkdatorn.se>",
"Cayman <caymannava@gmail.com>",

@@ -79,5 +83,5 @@ "Diogo Silva <fsdiogo@gmail.com>",

"Evan Schwartz <evan.mark.schwartz@gmail.com>",
"Linus Unnebäck <linus@folkdatorn.se>",
"João Antunes <j.goncalo.antunes@gmail.com>",
"Mikeal Rogers <mikeal.rogers@gmail.com>"
]
}

29

src/index.js

@@ -5,2 +5,4 @@ 'use strict'

const mafmt = require('mafmt')
// Missing Type
// @ts-ignore
const withIs = require('class-is')

@@ -18,2 +20,5 @@ const errCode = require('err-code')

* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('libp2p-interfaces/src/transport/types').Upgrader} Upgrader
* @typedef {import('libp2p-interfaces/src/transport/types').Listener} Listener
* @typedef {import('net').Socket} Socket
*/

@@ -38,4 +43,4 @@

* @param {object} options
* @param {AbortSignal} options.signal - Used to abort dial requests
* @returns {Connection} An upgraded Connection
* @param {AbortSignal} [options.signal] - Used to abort dial requests
* @returns {Promise<Connection>} An upgraded Connection
*/

@@ -56,3 +61,3 @@ async dial (ma, options) {

* @param {object} options
* @param {AbortSignal} options.signal - Used to abort dial requests
* @param {AbortSignal} [options.signal] - Used to abort dial requests
* @returns {Promise<Socket>} Resolves a TCP Socket

@@ -72,3 +77,3 @@ */

const onError = err => {
const onError = /** @param {Error} err */ err => {
err.message = `connection error ${cOpts.host}:${cOpts.port}: ${err.message}`

@@ -79,3 +84,3 @@ done(err)

const onTimeout = () => {
log('connnection timeout %s:%s', cOpts.host, cOpts.port)
log('connection timeout %s:%s', cOpts.host, cOpts.port)
const err = errCode(new Error(`connection timeout after ${Date.now() - start}ms`), 'ERR_CONNECT_TIMEOUT')

@@ -97,3 +102,3 @@ // Note: this will result in onError() being called

const done = err => {
const done = /** @param {Error} [err] */ err => {
rawSocket.removeListener('error', onError)

@@ -120,13 +125,17 @@ rawSocket.removeListener('timeout', onTimeout)

*
* @param {*} [options]
* @param {function(Connection)} handler
* @param {* | function(Connection):void} options
* @param {function(Connection):void} [handler]
* @returns {Listener} A TCP listener
*/
createListener (options, handler) {
let listenerHandler
if (typeof options === 'function') {
handler = options
listenerHandler = options
options = {}
} else {
listenerHandler = handler
}
options = options || {}
return createListener({ handler, upgrader: this._upgrader }, options)
return createListener({ handler: listenerHandler, upgrader: this._upgrader }, options)
}

@@ -133,0 +142,0 @@

@@ -6,5 +6,5 @@ 'use strict'

const debug = require('debug')
const log = debug('libp2p:tcp:listener')
log.error = debug('libp2p:tcp:listener:error')
const log = Object.assign(
debug('libp2p:tcp:listener'),
{ error: debug('libp2p:tcp:listener:error') })
const toConnection = require('./socket-to-conn')

@@ -18,6 +18,15 @@ const { CODE_P2P } = require('./constants')

/**
* @typedef {import('multiaddr').Multiaddr} Multiaddr
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('libp2p-interfaces/src/transport/types').Upgrader} Upgrader
* @typedef {import('libp2p-interfaces/src/transport/types').MultiaddrConnection} MultiaddrConnection
* @typedef {import('libp2p-interfaces/src/transport/types').Listener} Listener
* @typedef {import('net').Server & {__connections: MultiaddrConnection[]}} Server
*/
/**
* Attempts to close the given maConn. If a failure occurs, it will be logged.
*
* @private
* @param {import('libp2p-interfaces/src/transport/types').MultiaddrConnection} maConn
* @param {MultiaddrConnection} maConn
*/

@@ -32,9 +41,76 @@ async function attemptClose (maConn) {

/**
* Create listener
*
* @param {object} context
* @param {function(Connection):void} context.handler
* @param {Upgrader} context.upgrader
* @param {*} options
* @returns {Listener}
*/
module.exports = ({ handler, upgrader }, options) => {
const listener = new EventEmitter()
/** @type {Server} */
// eslint-disable-next-line prefer-const
let server
const server = net.createServer(async socket => {
/** @type {string | null} */
let peerId
/** @type {Multiaddr} */
let listeningAddr
const listener = Object.assign(new EventEmitter(), {
getAddrs: () => {
/** @type {Multiaddr[]} */
let addrs = []
/** @type {import('net').AddressInfo} */
// @ts-ignore
const address = server.address()
if (!address) {
throw new Error('Listener is not ready yet')
}
// Because TCP will only return the IPv6 version
// we need to capture from the passed multiaddr
if (listeningAddr.toString().startsWith('/ip4')) {
addrs = addrs.concat(getMultiaddrs('ip4', address.address, address.port))
} else if (address.family === 'IPv6') {
addrs = addrs.concat(getMultiaddrs('ip6', address.address, address.port))
}
return addrs.map(ma => peerId ? ma.encapsulate(`/p2p/${peerId}`) : ma)
},
listen: async (/** @type {Multiaddr} */ ma) => {
listeningAddr = ma
peerId = ma.getPeerId()
if (peerId) {
listeningAddr = ma.decapsulateCode(CODE_P2P)
}
return new Promise((resolve, reject) => {
const options = multiaddrToNetConfig(listeningAddr)
server.listen(options, (/** @type {any} */ err) => {
if (err) return reject(err)
log('Listening on %s', server.address())
resolve(undefined)
})
})
},
close: async () => {
if (!server.listening) return
return new Promise((resolve, reject) => {
server.__connections.forEach(maConn => attemptClose(maConn))
server.close(err => err ? reject(err) : resolve(undefined))
})
}
})
server = Object.assign(net.createServer(async socket => {
// Avoid uncaught errors caused by unstable connections
socket.on('error', err => log('socket error', err))
/** @type {MultiaddrConnection} */
let maConn

@@ -48,2 +124,3 @@ let conn

log.error('inbound connection failed', err)
// @ts-ignore
return attemptClose(maConn)

@@ -58,3 +135,5 @@ }

listener.emit('connection', conn)
})
}),
// Keep track of open connections to destroy in case of timeout
{ __connections: [] })

@@ -66,56 +145,9 @@ server

// Keep track of open connections to destroy in case of timeout
server.__connections = []
listener.close = () => {
if (!server.listening) return
return new Promise((resolve, reject) => {
server.__connections.forEach(maConn => attemptClose(maConn))
server.close(err => err ? reject(err) : resolve())
})
}
let peerId, listeningAddr
listener.listen = ma => {
listeningAddr = ma
peerId = ma.getPeerId()
if (peerId) {
listeningAddr = ma.decapsulateCode(CODE_P2P)
}
return new Promise((resolve, reject) => {
const options = multiaddrToNetConfig(listeningAddr)
server.listen(options, err => {
if (err) return reject(err)
log('Listening on %s', server.address())
resolve()
})
})
}
listener.getAddrs = () => {
let addrs = []
const address = server.address()
if (!address) {
throw new Error('Listener is not ready yet')
}
// Because TCP will only return the IPv6 version
// we need to capture from the passed multiaddr
if (listeningAddr.toString().startsWith('/ip4')) {
addrs = addrs.concat(getMultiaddrs('ip4', address.address, address.port))
} else if (address.family === 'IPv6') {
addrs = addrs.concat(getMultiaddrs('ip6', address.address, address.port))
}
return addrs.map(ma => peerId ? ma.encapsulate(`/p2p/${peerId}`) : ma)
}
return listener
}
/**
* @param {Server} server
* @param {MultiaddrConnection} maConn
*/
function trackConn (server, maConn) {

@@ -128,3 +160,4 @@ server.__connections.push(maConn)

// @ts-ignore
maConn.conn.once('close', untrackConn)
}

@@ -5,2 +5,4 @@ 'use strict'

const log = require('debug')('libp2p:tcp:socket')
// Missing Type
// @ts-ignore
const toIterable = require('stream-to-it')

@@ -10,5 +12,22 @@ const toMultiaddr = require('libp2p-utils/src/ip-port-to-multiaddr')

// Convert a socket into a MultiaddrConnection
// https://github.com/libp2p/interface-transport#multiaddrconnection
module.exports = (socket, options) => {
/**
* @typedef {import('multiaddr').Multiaddr} Multiaddr
* @typedef {import('libp2p-interfaces/src/transport/types').MultiaddrConnection} MultiaddrConnection
* @typedef {import('net').Socket} Socket
*/
/**
* Convert a socket into a MultiaddrConnection
* https://github.com/libp2p/interface-transport#multiaddrconnection
*
* @private
* @param {Socket} socket
* @param {object} options
* @param {Multiaddr} [options.listeningAddr]
* @param {Multiaddr} [options.remoteAddr]
* @param {Multiaddr} [options.localAddr]
* @param {AbortSignal} [options.signal]
* @returns {MultiaddrConnection}
*/
const toConnection = (socket, options) => {
options = options || {}

@@ -26,5 +45,9 @@

const { sink, source } = toIterable.duplex(socket)
/** @type {MultiaddrConnection} */
const maConn = {
async sink (source) {
if (options.signal) {
// Missing Type for "abortable"
// @ts-ignore
source = abortable(source, options.signal)

@@ -37,2 +60,4 @@ }

// Convert BufferList to Buffer
// Sink in StreamMuxer define argument as Uint8Array so chunk type infers as number which can't be sliced
// @ts-ignore
yield Buffer.isBuffer(chunk) ? chunk : chunk.slice()

@@ -52,2 +77,4 @@ }

// Missing Type for "abortable"
// @ts-ignore
source: options.signal ? abortable(source, options.signal) : source,

@@ -60,7 +87,7 @@

// If the remote address was passed, use it - it may have the peer ID encapsulated
remoteAddr: options.remoteAddr || toMultiaddr(socket.remoteAddress, socket.remotePort),
remoteAddr: options.remoteAddr || toMultiaddr(socket.remoteAddress || '', socket.remotePort || ''),
timeline: { open: Date.now() },
close () {
async close () {
if (socket.destroyed) return

@@ -75,4 +102,8 @@

const { host, port } = maConn.remoteAddr.toOptions()
log('timeout closing socket to %s:%s after %dms, destroying it manually',
host, port, Date.now() - start)
log(
'timeout closing socket to %s:%s after %dms, destroying it manually',
host,
port,
Date.now() - start
)

@@ -92,3 +123,3 @@ if (socket.destroyed) {

})
socket.end(err => {
socket.end(/** @param {Error} [err] */(err) => {
maConn.timeline.close = Date.now()

@@ -113,1 +144,3 @@ if (err) return reject(err)

}
module.exports = toConnection

@@ -8,2 +8,10 @@ 'use strict'

/**
* @typedef {import('multiaddr').MultiaddrObject} MultiaddrObject
*/
/**
* @param {Multiaddr} addr
* @returns {MultiaddrObject}
*/
function multiaddrToNetConfig (addr) {

@@ -13,2 +21,4 @@ const listenPath = addr.getPath()

if (listenPath) {
// TCP should not return unix socket else need to refactor listener which accepts connection options object
// @ts-ignore
return resolve(listenPath)

@@ -20,7 +30,17 @@ }

/**
* @param {'ip4' | 'ip6'} proto
* @param {string} ip
* @param {number} port
* @returns {Multiaddr[]}
*/
function getMultiaddrs (proto, ip, port) {
const toMa = ip => new Multiaddr(`/${proto}/${ip}/tcp/${port}`)
const toMa = /** @param {string} ip */ ip => new Multiaddr(`/${proto}/${ip}/tcp/${port}`)
return (isAnyAddr(ip) ? getNetworkAddrs(ProtoFamily[proto]) : [ip]).map(toMa)
}
/**
* @param {string} ip
* @returns {boolean}
*/
function isAnyAddr (ip) {

@@ -36,10 +56,21 @@ return ['0.0.0.0', '::'].includes(ip)

const networks = os.networkInterfaces()
/**
* @param {string} family
* @returns {string[]}
*/
function getNetworkAddrs (family) {
return Object.values(networks).reduce((addresses, netAddrs) => {
netAddrs.forEach(netAddr => {
// Add the ip of each matching network interface
if (netAddr.family === family) addresses.push(netAddr.address)
})
return addresses
}, [])
const addresses = []
for (const [, netAddrs] of Object.entries(networks)) {
if (netAddrs) {
for (const netAddr of netAddrs) {
if (netAddr.family === family) {
addresses.push(netAddr.address)
}
}
}
}
return addresses
}

@@ -46,0 +77,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc