├── .github ├── pull_request_template.md └── workflows │ ├── generated-pr.yml │ ├── semantic-pull-request.yml │ └── stale.yml ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── package.json ├── src ├── create-listener.js ├── get-multiaddr.js └── index.js └── test ├── connection.spec.js ├── constructor.spec.js ├── filter.spec.js └── listen-dial.spec.js /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Title 2 | 8 | 9 | ## Description 10 | 11 | 17 | 18 | ## Notes & open questions 19 | 20 | 23 | 24 | ## Change checklist 25 | 26 | - [ ] I have performed a self-review of my own code 27 | - [ ] I have made corresponding changes to the documentation if necessary (this includes comments as well) 28 | - [ ] I have added tests that prove my fix is effective or that my feature works -------------------------------------------------------------------------------- /.github/workflows/generated-pr.yml: -------------------------------------------------------------------------------- 1 | name: Close Generated PRs 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | permissions: 9 | issues: write 10 | pull-requests: write 11 | 12 | jobs: 13 | stale: 14 | uses: ipdxco/unified-github-workflows/.github/workflows/reusable-generated-pr.yml@v1 15 | -------------------------------------------------------------------------------- /.github/workflows/semantic-pull-request.yml: -------------------------------------------------------------------------------- 1 | name: Semantic PR 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | jobs: 11 | main: 12 | uses: ipdxco/unified-github-workflows/.github/workflows/reusable-semantic-pull-request.yml@v1 13 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Close Stale Issues 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | permissions: 9 | issues: write 10 | pull-requests: write 11 | 12 | jobs: 13 | stale: 14 | uses: ipdxco/unified-github-workflows/.github/workflows/reusable-stale-issue.yml@v1 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/node_modules/ 2 | **/*.log 3 | test/repo-tests* 4 | **/bundle.js 5 | 6 | # Logs 7 | logs 8 | *.log 9 | 10 | coverage 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # node-waf configuration 27 | .lock-wscript 28 | 29 | build 30 | 31 | # Dependency directory 32 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 33 | node_modules 34 | 35 | lib 36 | dist 37 | test/test-data/go-ipfs-repo/LOCK 38 | test/test-data/go-ipfs-repo/LOG 39 | test/test-data/go-ipfs-repo/LOG.old 40 | 41 | # while testing npm5 42 | package-lock.json 43 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | test 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: npm 3 | 4 | stages: 5 | - check 6 | - test 7 | - cov 8 | 9 | node_js: 10 | - '10' 11 | 12 | os: 13 | - linux 14 | - osx 15 | - windows 16 | 17 | script: npx nyc -s npm run test:node -- --bail 18 | after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov 19 | 20 | jobs: 21 | include: 22 | - stage: check 23 | script: 24 | - npx aegir commitlint --travis 25 | - npx aegir dep-check 26 | - npm run lint 27 | 28 | notifications: 29 | email: false 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 David Dias 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # js-libp2p-utp 2 | 3 | :warning: Not actively maintained. 4 | 5 | 👉 If you are looking for libp2p transports check [js-libp2p/doc/CONFIGURATION.md#transport](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#transport). 6 | 7 | If you would like to help getting this module updated check [js-libp2p-utp#81](https://github.com/libp2p/js-libp2p-utp/pull/81) 8 | 9 | --- 10 | 11 | [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://protocol.ai) 12 | [![](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) 13 | [![](https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23libp2p) 14 | [![Discourse posts](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg)](https://discuss.libp2p.io) 15 | 16 | [![](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-utp.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-utp) 17 | [![](https://img.shields.io/travis/libp2p/js-libp2p-utp.svg?branch=master)](https://travis-ci.com/libp2p/js-libp2p-utp) 18 | [![Dependency Status](https://david-dm.org/libp2p/js-libp2p-utp.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-utp) 19 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) 20 | 21 | ![](https://raw.githubusercontent.com/libp2p/interface-connection/master/img/badge.png) 22 | ![](https://raw.githubusercontent.com/libp2p/interface-transport/master/img/badge.png) 23 | 24 | > Node.js implementation of the `µTP` module that `libp2p` uses, which implements the [interface-transport](https://github.com/libp2p/interface-transport) interface for dial/listen. Connections follow [interface-connection](https://github.com/libp2p/interface-connection). 25 | 26 | ## Lead Maintainer 27 | 28 | [Vasco Santos](https://github.com/vasco-santos). 29 | 30 | # Acknowledgements 31 | 32 | `js-libp2p-utp` is a wrapper on top on [utp](https://github.com/mafintosh/utp) originally developed by [Mathias Buus](https://github.com/mafintosh) 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libp2p-utp", 3 | "version": "0.2.0", 4 | "description": "Node.js implementation of the µTP module that libp2p uses, which implements the abstract-connection interface", 5 | "leadMaintainer": "Vasco Santos ", 6 | "main": "src/index.js", 7 | "scripts": { 8 | "lint": "aegir lint", 9 | "test": "aegir test -t node", 10 | "test:node": "aegir test -t node", 11 | "release": "aegir release -t node --no-build", 12 | "release-minor": "aegir release --type minor -t node --no-build", 13 | "release-major": "aegir release --type major -t node --no-build", 14 | "coverage": "aegir coverage", 15 | "coverage-publish": "aegir coverage publish --providers coveralls" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/libp2p/js-libp2p-utp.git" 20 | }, 21 | "keywords": [ 22 | "IPFS" 23 | ], 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/libp2p/js-libp2p-utp/issues" 27 | }, 28 | "homepage": "https://github.com/libp2p/js-libp2p-utp", 29 | "devDependencies": { 30 | "aegir": "^18.2.2", 31 | "chai": "^4.2.0", 32 | "dirty-chai": "^2.0.1" 33 | }, 34 | "dependencies": { 35 | "class-is": "^1.1.0", 36 | "debug": "^4.1.1", 37 | "interface-connection": "~0.3.3", 38 | "ip-address": "^5.9.0", 39 | "lodash.includes": "^4.3.0", 40 | "lodash.isfunction": "^3.0.9", 41 | "mafmt": "^6.0.7", 42 | "multiaddr": "^6.0.6", 43 | "once": "^1.4.0", 44 | "pull-stream": "^3.6.11", 45 | "stream-to-pull-stream": "^1.7.3", 46 | "utp-native": "^2.1.3" 47 | }, 48 | "contributors": [ 49 | "David Dias ", 50 | "Pau Ramon Revilla ", 51 | "Richard Littauer ", 52 | "dignifiedquire ", 53 | "greenkeeperio-bot " 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /src/create-listener.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const multiaddr = require('multiaddr') 4 | const Connection = require('interface-connection').Connection 5 | // const os = require('os') 6 | const includes = require('lodash.includes') 7 | const utp = require('utp-native') 8 | const toPull = require('stream-to-pull-stream') 9 | const EventEmitter = require('events').EventEmitter 10 | const debug = require('debug') 11 | const log = debug('libp2p:utp') 12 | 13 | const getMultiaddr = require('./get-multiaddr') 14 | 15 | const IPFS_CODE = 421 16 | const CLOSE_TIMEOUT = 2000 17 | 18 | function noop () {} 19 | 20 | module.exports = (handler) => { 21 | const listener = new EventEmitter() 22 | 23 | const server = utp.createServer((socket) => { 24 | // Avoid uncaught errors cause by unstable connections 25 | socket.on('error', noop) 26 | 27 | const addr = getMultiaddr(socket) 28 | 29 | const s = toPull.duplex(socket) 30 | 31 | s.getObservedAddrs = (cb) => cb(null, [addr]) 32 | 33 | trackSocket(server, socket) 34 | 35 | const conn = new Connection(s) 36 | handler(conn) 37 | listener.emit('connection', conn) 38 | }) 39 | 40 | server.on('listening', () => listener.emit('listening')) 41 | server.on('error', (err) => listener.emit('error', err)) 42 | server.on('close', () => listener.emit('close')) 43 | 44 | // Keep track of open connections to destroy in case of timeout 45 | server.__connections = {} 46 | 47 | listener.close = (options, callback) => { 48 | if (typeof options === 'function') { 49 | callback = options 50 | options = {} 51 | } 52 | callback = callback || noop 53 | options = options || {} 54 | 55 | const timeout = setTimeout(() => { 56 | log('unable to close graciously, destroying conns') 57 | Object.keys(server.__connections).forEach((key) => { 58 | log('destroying %s', key) 59 | server.__connections[key].destroy() 60 | }) 61 | }, options.timeout || CLOSE_TIMEOUT) 62 | 63 | server.close(callback) 64 | 65 | server.once('close', () => { 66 | clearTimeout(timeout) 67 | }) 68 | } 69 | 70 | let ipfsId 71 | let listeningAddr 72 | 73 | listener.listen = (ma, callback) => { 74 | listeningAddr = ma 75 | if (includes(ma.protoNames(), 'ipfs')) { 76 | ipfsId = getIpfsId(ma) 77 | listeningAddr = ma.decapsulate('ipfs') 78 | } 79 | 80 | const lOpts = listeningAddr.toOptions() 81 | log('Listening on %s %s', lOpts.port, lOpts.host) 82 | server.listen(Number(lOpts.port), lOpts.host, callback) 83 | } 84 | 85 | listener.getAddrs = (callback) => { 86 | const multiaddrs = [] 87 | const addr = server.address() 88 | 89 | if (!addr) { 90 | return callback(new Error('Listener is not ready yet')) 91 | } 92 | 93 | let ma 94 | if (addr.family === 'IPv6') { 95 | ma = multiaddr(`/ip6/${addr.address}/udp/${addr.port}/utp`) 96 | } else if (addr.family === 'IPv4') { 97 | console.log(`/ip4/${addr.address}/udp/${addr.port}/utp`) 98 | ma = multiaddr(`/ip4/${addr.address}/udp/${addr.port}/utp`) 99 | } 100 | 101 | if (ipfsId) { 102 | ma = ma.encapsulate('/ipfs/' + ipfsId) 103 | } 104 | 105 | multiaddrs.push(ma) 106 | 107 | callback(null, multiaddrs) 108 | } 109 | 110 | return listener 111 | } 112 | 113 | function getIpfsId (ma) { 114 | return ma.stringTuples().filter((tuple) => { 115 | return tuple[0] === IPFS_CODE 116 | })[0][1] 117 | } 118 | 119 | function trackSocket (server, socket) { 120 | const key = `${socket.remoteAddress}:${socket.remotePort}` 121 | server.__connections[key] = socket 122 | 123 | socket.on('close', () => { 124 | delete server.__connections[key] 125 | }) 126 | } 127 | -------------------------------------------------------------------------------- /src/get-multiaddr.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // const multiaddr = require('multiaddr') 4 | // const Address6 = require('ip-address').Address6 5 | 6 | module.exports = (socket) => { 7 | // utp-native does not pack the remoteAddress 8 | // TODO check if it is possible 9 | return null 10 | /* 11 | let ma 12 | 13 | if (socket.remoteFamily === 'IPv6') { 14 | const addr = new Address6(socket.remoteAddress) 15 | 16 | if (addr.v4) { 17 | const ip4 = addr.to4().correctForm() 18 | ma = multiaddr('/ip4/' + ip4 + 19 | '/tcp/' + socket.remotePort 20 | ) 21 | } else { 22 | ma = multiaddr('/ip6/' + socket.remoteAddress + 23 | '/tcp/' + socket.remotePort 24 | ) 25 | } 26 | } else { 27 | ma = multiaddr('/ip4/' + socket.remoteAddress + 28 | '/tcp/' + socket.remotePort) 29 | } 30 | 31 | return ma 32 | */ 33 | } 34 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const utp = require('utp-native') 4 | const toPull = require('stream-to-pull-stream') 5 | const mafmt = require('mafmt') 6 | const withIs = require('class-is') 7 | const includes = require('lodash.includes') 8 | const isFunction = require('lodash.isfunction') 9 | const Connection = require('interface-connection').Connection 10 | const once = require('once') 11 | const createListener = require('./create-listener.js') 12 | const debug = require('debug') 13 | const log = debug('libp2p:utp') 14 | 15 | function noop () {} 16 | 17 | class UTP { 18 | dial (ma, options, callback) { 19 | if (isFunction(options)) { 20 | callback = options 21 | options = {} 22 | } 23 | 24 | callback = once(callback || noop) 25 | 26 | const cOpts = ma.toOptions() 27 | log('Connecting (UTP) to %s %s', cOpts.port, cOpts.host) 28 | 29 | const rawSocket = utp.connect(cOpts) 30 | 31 | rawSocket.once('timeout', () => { 32 | log('timeout') 33 | rawSocket.emit('error', new Error('Timeout')) 34 | }) 35 | 36 | rawSocket.once('error', callback) 37 | 38 | rawSocket.once('connect', () => { 39 | rawSocket.removeListener('error', callback) 40 | callback() 41 | }) 42 | 43 | const socket = toPull.duplex(rawSocket) 44 | 45 | const conn = new Connection(socket) 46 | 47 | conn.getObservedAddrs = (callback) => { 48 | return callback(null, [ma]) 49 | } 50 | 51 | return conn 52 | } 53 | 54 | createListener (options, handler) { 55 | if (isFunction(options)) { 56 | handler = options 57 | options = {} 58 | } 59 | 60 | handler = handler || noop 61 | 62 | return createListener(handler) 63 | } 64 | 65 | filter (multiaddrs) { 66 | if (!Array.isArray(multiaddrs)) { 67 | multiaddrs = [multiaddrs] 68 | } 69 | 70 | return multiaddrs.filter((ma) => { 71 | if (includes(ma.protoNames(), 'p2p-circuit')) { 72 | return false 73 | } 74 | 75 | if (includes(ma.protoNames(), 'ipfs')) { 76 | ma = ma.decapsulate('ipfs') 77 | } 78 | 79 | return mafmt.UTP.matches(ma) 80 | }) 81 | } 82 | } 83 | 84 | module.exports = withIs(UTP, { className: 'UTP', symbolName: '@libp2p/js-libp2p-utp/utp' }) 85 | -------------------------------------------------------------------------------- /test/connection.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const chai = require('chai') 5 | const dirtyChai = require('dirty-chai') 6 | const expect = chai.expect 7 | chai.use(dirtyChai) 8 | const UTP = require('../src') 9 | 10 | describe('Valid libp2p Connection', () => { 11 | let utp 12 | 13 | beforeEach(() => { 14 | utp = new UTP() 15 | }) 16 | 17 | it.skip('.getObservedAddrs', (done) => { 18 | expect(utp).to.exist() 19 | }) 20 | it.skip('.getPeerInfo', (done) => {}) 21 | it.skip('.setPeerInfo', (done) => {}) 22 | }) 23 | -------------------------------------------------------------------------------- /test/constructor.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const chai = require('chai') 5 | const dirtyChai = require('dirty-chai') 6 | const expect = chai.expect 7 | chai.use(dirtyChai) 8 | const UTP = require('../src') 9 | 10 | describe('Constructor', () => { 11 | it('create an instance', () => { 12 | const utp = new UTP() 13 | expect(utp).to.exist() 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /test/filter.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const chai = require('chai') 5 | const dirtyChai = require('dirty-chai') 6 | const expect = chai.expect 7 | chai.use(dirtyChai) 8 | const UTP = require('../src') 9 | const multiaddr = require('multiaddr') 10 | 11 | describe('filter addrs', () => { 12 | const base = '/ip4/127.0.0.1' 13 | const ipfs = '/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw' 14 | 15 | let utp 16 | 17 | before(() => { 18 | utp = new UTP() 19 | }) 20 | 21 | it('filter valid addrs for this transport', () => { 22 | const ma1 = multiaddr(base + '/tcp/9090') 23 | const ma2 = multiaddr(base + '/udp/9090') 24 | const ma3 = multiaddr(base + '/tcp/9090/http') 25 | const ma4 = multiaddr(base + '/tcp/9090' + ipfs) 26 | const ma5 = multiaddr(base + '/tcp/9090/http' + ipfs) 27 | const ma6 = multiaddr('/ip4/127.0.0.1/tcp/9090/p2p-circuit' + ipfs) 28 | const ma7 = multiaddr(base + '/udp/9090/utp') 29 | const ma8 = multiaddr(base + '/udp/9090/utp' + ipfs) 30 | 31 | const valid = utp.filter([ 32 | ma1, 33 | ma2, 34 | ma3, 35 | ma4, 36 | ma5, 37 | ma6, 38 | ma7, 39 | ma8 40 | ]) 41 | 42 | expect(valid.length).to.equal(2) 43 | expect(valid[0]).to.eql(ma7) 44 | expect(valid[1]).to.eql(ma8) 45 | }) 46 | 47 | it('filter a single addr for this transport', () => { 48 | const ma1 = multiaddr(base + '/udp/9090/utp') 49 | 50 | const valid = utp.filter(ma1) 51 | expect(valid.length).to.equal(1) 52 | expect(valid[0]).to.eql(ma1) 53 | }) 54 | }) 55 | -------------------------------------------------------------------------------- /test/listen-dial.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const chai = require('chai') 5 | const dirtyChai = require('dirty-chai') 6 | const expect = chai.expect 7 | chai.use(dirtyChai) 8 | const nativeUTP = require('utp-native') 9 | const pull = require('pull-stream') 10 | const multiaddr = require('multiaddr') 11 | 12 | const UTP = require('../src') 13 | const isCI = process.env.CI 14 | 15 | describe('Listener (.createListener => listener)', () => { 16 | let utp 17 | 18 | function ma (port) { 19 | const base = '/ip4/127.0.0.1/udp/' 20 | return multiaddr(`${base}${port}/utp`) 21 | } 22 | 23 | beforeEach(() => { 24 | utp = new UTP() 25 | }) 26 | 27 | it('.close with connections, through timeout', function (done) { 28 | this.timeout(20 * 1000) 29 | 30 | const listener = utp.createListener((conn) => pull(conn, conn)) 31 | 32 | const addr = ma(6000) 33 | const connectOptions = addr.toOptions() 34 | 35 | listener.listen(addr, () => { 36 | const socket1 = nativeUTP.connect(Number(connectOptions.port), connectOptions.host) 37 | const socket2 = nativeUTP.connect(Number(connectOptions.port), connectOptions.host) 38 | 39 | socket1.write('Some data that is never handled') 40 | socket1.end() 41 | 42 | socket1.on('error', (err) => expect(err).to.not.exist()) 43 | socket2.on('error', (err) => expect(err).to.not.exist()) 44 | socket1.on('connect', () => listener.close(done)) 45 | }) 46 | }) 47 | 48 | it('.listen on port 0', (done) => { 49 | const listener = utp.createListener((conn) => {}) 50 | 51 | listener.listen(ma(0), () => { 52 | listener.close(done) 53 | }) 54 | }) 55 | 56 | // TODO: Get utp to work with IPv6 Addresses 57 | it.skip('.listen on IPv6 addr', function (done) { 58 | if (isCI) { return this.skip() } 59 | 60 | const ma = multiaddr('/ip6/::/udp/12000/utp') 61 | 62 | const listener = utp.createListener((conn) => {}) 63 | listener.listen(ma, () => { 64 | listener.close(done) 65 | }) 66 | }) 67 | 68 | it('.listen on any Interface', (done) => { 69 | const ma = multiaddr('/ip4/0.0.0.0/udp/12000/utp') 70 | 71 | const listener = utp.createListener((conn) => {}) 72 | 73 | listener.listen(ma, () => { 74 | listener.close(done) 75 | }) 76 | }) 77 | 78 | it('.getAddrs', (done) => { 79 | const listener = utp.createListener((conn) => {}) 80 | const addr = ma(12000) 81 | 82 | listener.listen(addr, () => { 83 | listener.getAddrs((err, multiaddrs) => { 84 | expect(err).to.not.exist() 85 | expect(multiaddrs.length).to.equal(1) 86 | expect(multiaddrs[0]).to.eql(addr) 87 | listener.close(done) 88 | }) 89 | }) 90 | }) 91 | 92 | it('.getAddrs on port 0 listen', (done) => { 93 | const addr = ma(0) 94 | 95 | const listener = utp.createListener((conn) => {}) 96 | listener.listen(addr, () => { 97 | listener.getAddrs((err, multiaddrs) => { 98 | expect(err).to.not.exist() 99 | expect(multiaddrs.length).to.equal(1) 100 | listener.close(done) 101 | }) 102 | }) 103 | }) 104 | 105 | // TODO: Get utp to understand the meaning of 0.0.0.0 106 | it.skip('.getAddrs from listening on 0.0.0.0', (done) => { 107 | const addr = multiaddr('/ip4/0.0.0.0/udp/12000/utp') 108 | 109 | const listener = utp.createListener((conn) => {}) 110 | 111 | listener.listen(addr, () => { 112 | listener.getAddrs((err, multiaddrs) => { 113 | expect(err).to.not.exist() 114 | expect(multiaddrs.length > 0).to.equal(true) 115 | expect(multiaddrs[0].toString().indexOf('0.0.0.0')).to.equal(-1) 116 | listener.close(done) 117 | }) 118 | }) 119 | }) 120 | 121 | // TODO: Get utp to understand the meaning of 0.0.0.0 122 | it.skip('.getAddrs from listening on 0.0.0.0 and port 0', (done) => { 123 | const addr = multiaddr('/ip4/0.0.0.0/udp/0/utp') 124 | const listener = utp.createListener((conn) => {}) 125 | 126 | listener.listen(addr, () => { 127 | listener.getAddrs((err, multiaddrs) => { 128 | expect(err).to.not.exist() 129 | expect(multiaddrs.length > 0).to.equal(true) 130 | expect(multiaddrs[0].toString().indexOf('0.0.0.0')).to.equal(-1) 131 | listener.close(done) 132 | }) 133 | }) 134 | }) 135 | 136 | it('.getAddrs preserves IPFS Id', (done) => { 137 | const ipfsId = '/ipfs/Qmb6owHp6eaWArVbcJJbQSyifyJBttMMjYV76N2hMbf5Vw' 138 | const addr = ma(9090).encapsulate(ipfsId) 139 | 140 | const listener = utp.createListener((conn) => {}) 141 | 142 | listener.listen(addr, () => { 143 | listener.getAddrs((err, multiaddrs) => { 144 | expect(err).to.not.exist() 145 | expect(multiaddrs.length).to.equal(1) 146 | expect(multiaddrs[0]).to.eql(addr) 147 | listener.close(done) 148 | }) 149 | }) 150 | }) 151 | }) 152 | 153 | /* 154 | describe('Dialer (.dial)', () => { 155 | let utp 156 | 157 | beforeEach(() => { 158 | utp = new UTP() 159 | }) 160 | 161 | it.skip('things', () => { 162 | }) 163 | }) 164 | */ 165 | --------------------------------------------------------------------------------