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

Commit

Permalink
feat: convert to typescript
Browse files Browse the repository at this point in the history
Converts this module to typescript

Depends on:

- [ ] libp2p/js-libp2p-interfaces#116

BREAKING CHANGE: this module now uses the updated libp2p-interfaces module
  • Loading branch information
achingbrain committed Dec 10, 2021
1 parent 1faa587 commit 8bc0b09
Show file tree
Hide file tree
Showing 16 changed files with 635 additions and 704 deletions.
File renamed without changes.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@

> JavaScript implementation of the TCP module for libp2p. It exposes the [interface-transport](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/transport) for dial/listen. `libp2p-tcp` is a very thin shim that adds support for dialing to a `multiaddr`. This small shim will enable libp2p to use other transports.
## Lead Maintainer

[Jacob Heun](https://github.com/jacobheun)

## Table of Contents

- [Install](#install)
- [npm](#npm)
- [Usage](#usage)
- [API](#api)
- [Contribute](#contribute)
- [License](#license)
- [js-libp2p-tcp](#js-libp2p-tcp)
- [Table of Contents](#table-of-contents)
- [Install](#install)
- [npm](#npm)
- [Usage](#usage)
- [API](#api)
- [Transport](#transport)
- [Connection](#connection)
- [Contribute](#contribute)
- [License](#license)

## Install

Expand All @@ -52,7 +52,7 @@ const upgrader = {

const tcp = new TCP({ upgrader })

const listener = tcp.createListener((socket) => {
const listener = tcp.createListener({}, (socket) => {
console.log('new connection opened')
pipe(
['hello'],
Expand Down
37 changes: 21 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@
"name": "libp2p-tcp",
"version": "0.17.2",
"description": "Node.js implementation of the TCP module that libp2p uses, which implements the interface-connection and interface-transport interfaces",
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
"main": "src/index.js",
"main": "./dist/src/index.js",
"type": "module",
"exports": {
".": {
"import": "./dist/src/index.js"
}
},
"scripts": {
"lint": "aegir ts -p check && aegir lint",
"build": "aegir build",
"test": "aegir test -t node",
"test:node": "aegir test -t node",
"release": "aegir release -t node",
"release-minor": "aegir release -t node --type minor",
"release-major": "aegir-release -t node --type major",
"build": "tsc",
"pretest": "npm run build",
"test": "aegir test -t node -f ./dist/test/*.js",
"test:node": "aegir test -t node -f ./dist/test/*.js",
"release": "aegir release -t node -f ./dist/test/*.js",
"release-minor": "aegir release -t node -f ./dist/test/*.js --type minor",
"release-major": "aegir-release -t node -f ./dist/test/*.js --type major",
"coverage": "nyc --reporter=text --reporter=lcov npm run test:node"
},
"pre-push": [
"lint"
],
"repository": {
"type": "git",
"url": "https://github.com/libp2p/js-libp2p-tcp.git"
Expand All @@ -41,11 +44,12 @@
"types": "dist/src/index.d.ts",
"devDependencies": {
"@types/debug": "^4.1.5",
"aegir": "^35.0.3",
"@types/mocha": "^9.0.0",
"aegir": "^36.0.0",
"it-pipe": "^1.1.0",
"libp2p-interfaces": "^1.0.0",
"libp2p-interfaces-compliance-tests": "^1.0.0",
"sinon": "^11.1.1",
"libp2p-interfaces": "^2.0.0",
"libp2p-interfaces-compliance-tests": "^2.0.0",
"sinon": "^12.0.0",
"streaming-iterables": "^6.0.0"
},
"dependencies": {
Expand All @@ -56,7 +60,8 @@
"libp2p-utils": "^0.4.0",
"mafmt": "^10.0.0",
"multiaddr": "^10.0.0",
"stream-to-it": "^0.2.2"
"stream-to-it": "^0.2.2",
"why-is-node-running": "^2.2.0"
},
"contributors": [
"David Dias <daviddias.p@gmail.com>",
Expand Down
8 changes: 3 additions & 5 deletions src/constants.js → src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
'use strict'

// p2p multi-address code
exports.CODE_P2P = 421
exports.CODE_CIRCUIT = 290
export const CODE_P2P = 421
export const CODE_CIRCUIT = 290

// Time to wait for a connection to close gracefully before destroying it manually
exports.CLOSE_TIMEOUT = 2000
export const CLOSE_TIMEOUT = 2000
123 changes: 54 additions & 69 deletions src/index.js → src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
'use strict'

const net = require('net')
const mafmt = require('mafmt')
// Missing Type
// @ts-ignore
const withIs = require('class-is')
const errCode = require('err-code')
const log = require('debug')('libp2p:tcp')
const toConnection = require('./socket-to-conn')
const createListener = require('./listener')
const { multiaddrToNetConfig } = require('./utils')
const { AbortError } = require('abortable-iterator')
const { CODE_CIRCUIT, CODE_P2P } = require('./constants')
import net from 'net'
import mafmt from 'mafmt'
import errCode from 'err-code'
import debug from 'debug'
import { toConnection } from './socket-to-conn.js'
import { createListener } from './listener.js'
import { multiaddrToNetConfig } from './utils.js'
import { AbortError } from 'abortable-iterator'
import { CODE_CIRCUIT, CODE_P2P } from './constants.js'
import type { Transport, Upgrader } from 'libp2p-interfaces/transport'
import type { Connection } from 'libp2p-interfaces/connection'
import type { Multiaddr } from 'multiaddr'
import type { Socket } from 'net'

const log = debug('libp2p:tcp')

/**
* @typedef {import('multiaddr').Multiaddr} Multiaddr
Expand All @@ -21,28 +22,28 @@ const { CODE_CIRCUIT, CODE_P2P } = require('./constants')
* @typedef {import('net').Socket} Socket
*/

class TCP {
/**
* @class
* @param {object} options
* @param {Upgrader} options.upgrader
*/
constructor ({ upgrader }) {
if (!upgrader) {
interface TCPOptions {
upgrader: Upgrader
}

interface DialOptions {
signal?: AbortSignal
}

export default class TCP implements Transport<DialOptions, {}> {
private readonly _upgrader: Upgrader

constructor (options: TCPOptions) {
const { upgrader } = options

if (upgrader == null) {
throw new Error('An upgrader must be provided. See https://github.com/libp2p/interface-transport#upgrader.')
}

this._upgrader = upgrader
}

/**
* @async
* @param {Multiaddr} ma
* @param {object} options
* @param {AbortSignal} [options.signal] - Used to abort dial requests
* @returns {Promise<Connection>} An upgraded Connection
*/
async dial (ma, options) {
options = options || {}
async dial (ma: Multiaddr, options: DialOptions = {}) {
const socket = await this._connect(ma, options)
const maConn = toConnection(socket, { remoteAddr: ma, signal: options.signal })
log('new outbound connection %s', maConn.remoteAddr)
Expand All @@ -51,32 +52,27 @@ class TCP {
return conn
}

/**
* @private
* @param {Multiaddr} ma
* @param {object} options
* @param {AbortSignal} [options.signal] - Used to abort dial requests
* @returns {Promise<Socket>} Resolves a TCP Socket
*/
_connect (ma, options = {}) {
if (options.signal && options.signal.aborted) {
async _connect (ma: Multiaddr, options: DialOptions = {}) {
if (options.signal?.aborted === true) {
throw new AbortError()
}

return new Promise((resolve, reject) => {
return await new Promise<Socket>((resolve, reject) => {
const start = Date.now()
const cOpts = multiaddrToNetConfig(ma)

log('dialing %j', cOpts)
const rawSocket = net.connect(cOpts)

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

done(err)
}

const onTimeout = () => {
log('connection timeout %s:%s', cOpts.host, cOpts.port)

const err = errCode(new Error(`connection timeout after ${Date.now() - start}ms`), 'ERR_CONNECT_TIMEOUT')
// Note: this will result in onError() being called
rawSocket.emit('error', err)
Expand All @@ -93,52 +89,45 @@ class TCP {
done(new AbortError())
}

const done = /** @param {Error} [err] */ err => {
const done = (err?: any) => {
rawSocket.removeListener('error', onError)
rawSocket.removeListener('timeout', onTimeout)
rawSocket.removeListener('connect', onConnect)
options.signal && options.signal.removeEventListener('abort', onAbort)

if (err) return reject(err)
if (options.signal != null) {
options.signal.removeEventListener('abort', onAbort)
}

if (err != null) {
return reject(err)
}

resolve(rawSocket)
}

rawSocket.on('error', onError)
rawSocket.on('timeout', onTimeout)
rawSocket.on('connect', onConnect)
options.signal && options.signal.addEventListener('abort', onAbort)

if (options.signal != null) {
options.signal.addEventListener('abort', onAbort)
}
})
}

/**
* Creates a TCP listener. The provided `handler` function will be called
* anytime a new incoming Connection has been successfully upgraded via
* `upgrader.upgradeInbound`.
*
* @param {* | function(Connection):void} options
* @param {function(Connection):void} [handler]
* @returns {Listener} A TCP listener
*/
createListener (options, handler) {
let listenerHandler

if (typeof options === 'function') {
listenerHandler = options
options = {}
} else {
listenerHandler = handler
}
options = options || {}
return createListener({ handler: listenerHandler, upgrader: this._upgrader }, options)
createListener (options: {}, handler?: (connection: Connection) => void) {
return createListener({ handler: handler, upgrader: this._upgrader })
}

/**
* Takes a list of `Multiaddr`s and returns only valid TCP addresses
*
* @param {Multiaddr[]} multiaddrs
* @returns {Multiaddr[]} Valid TCP multiaddrs
*/
filter (multiaddrs) {
filter (multiaddrs: Multiaddr[]) {
multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]

return multiaddrs.filter(ma => {
Expand All @@ -150,7 +139,3 @@ class TCP {
})
}
}

const TCPWithIs = withIs(TCP, { className: 'TCP', symbolName: '@libp2p/js-libp2p-tcp/tcp' })

exports = module.exports = TCPWithIs
Loading

0 comments on commit 8bc0b09

Please sign in to comment.