├── test ├── node.js ├── browser.js ├── peer.json ├── webrtc-star-only.js └── websockets-only.js ├── examples └── mapper │ ├── .gitignore │ ├── public │ └── index.html │ ├── src │ ├── create-node.js │ └── index.js │ └── package.json ├── circle.yml ├── .npmignore ├── .travis.yml ├── .gitignore ├── LICENSE ├── CHANGELOG.md ├── gulpfile.js ├── src └── index.js ├── package.json └── README.md /test/node.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | -------------------------------------------------------------------------------- /examples/mapper/.gitignore: -------------------------------------------------------------------------------- 1 | bundle.js -------------------------------------------------------------------------------- /test/browser.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const w = require('webrtcsupport') 4 | 5 | require('./websockets-only') 6 | 7 | if (w.support) { 8 | require('./webrtc-star-only') 9 | } 10 | -------------------------------------------------------------------------------- /examples/mapper/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | p2p mapper 6 | 7 | 8 |

p2p mapper

9 |
10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | node: 3 | version: stable 4 | 5 | dependencies: 6 | pre: 7 | - google-chrome --version 8 | - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - 9 | - sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' 10 | - sudo apt-get update 11 | - sudo apt-get --only-upgrade install google-chrome-stable 12 | - google-chrome --version 13 | -------------------------------------------------------------------------------- /examples/mapper/src/create-node.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const PeerInfo = require('peer-info') 4 | const Node = require('../../../src') 5 | 6 | function createNode (callback) { 7 | PeerInfo.create((err, peerInfo) => { 8 | if (err) { 9 | return callback(err) 10 | } 11 | 12 | const peerIdStr = peerInfo.id.toB58String() 13 | const ma = `/libp2p-webrtc-star/dns4/star-signal.cloud.ipfs.team/wss/ipfs/${peerIdStr}` 14 | 15 | peerInfo.multiaddrs.add(ma) 16 | 17 | const node = new Node(peerInfo, undefined, { webRTCStar: true }) 18 | 19 | node.idStr = peerIdStr 20 | callback(null, node) 21 | }) 22 | } 23 | 24 | module.exports = createNode 25 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | 35 | test 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | matrix: 4 | include: 5 | - node_js: 4 6 | env: CXX=g++-4.8 7 | - node_js: 6 8 | env: 9 | - SAUCE=true 10 | - CXX=g++-4.8 11 | - node_js: stable 12 | env: CXX=g++-4.8 13 | 14 | # Make sure we have new NPM. 15 | before_install: 16 | - npm install -g npm 17 | 18 | script: 19 | - npm run lint 20 | - npm test 21 | - npm run coverage 22 | 23 | before_script: 24 | - export DISPLAY=:99.0 25 | - sh -e /etc/init.d/xvfb start 26 | 27 | after_success: 28 | - npm run coverage-publish 29 | 30 | addons: 31 | firefox: 'latest' 32 | apt: 33 | sources: 34 | - ubuntu-toolchain-r-test 35 | packages: 36 | - g++-4.8 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | 35 | dist 36 | examples/mapper/public/bundle.js 37 | -------------------------------------------------------------------------------- /examples/mapper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mapper", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "bundle": "browserify src/index.js --require browserify-zlib-next:zlib > public/bundle.js", 8 | "serve": "static public -p 9090 -H '{\"Cache-Control\": \"no-cache, must-revalidate\"}'", 9 | "mon": "nodemon --exec \"npm run start\" --ignore public/bundle.js", 10 | "start": "npm run bundle && npm run serve" 11 | }, 12 | "license": "MIT", 13 | "devDependencies": { 14 | "browserify": "^14.0.0", 15 | "browserify-optional": "^1.0.0", 16 | "browserify-zlib-next": "^1.0.1", 17 | "concat-stream": "^1.6.0", 18 | "detect-dom-ready": "^1.0.2", 19 | "node-static": "^0.7.9", 20 | "nodemon": "^1.11.0" 21 | }, 22 | "dependencies": {} 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 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 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # [0.25.0](https://github.com/ipfs/js-libp2p-ipfs-browser/compare/v0.24.1...v0.25.0) (2017-06-29) 3 | 4 | 5 | 6 | 7 | ## [0.24.1](https://github.com/ipfs/js-libp2p-ipfs-browser/compare/v0.24.0...v0.24.1) (2017-05-19) 8 | 9 | 10 | 11 | 12 | # [0.24.0](https://github.com/ipfs/js-libp2p-ipfs-browser/compare/v0.23.0...v0.24.0) (2017-04-07) 13 | 14 | 15 | 16 | 17 | # [0.23.0](https://github.com/ipfs/js-libp2p-ipfs-browser/compare/v0.22.0...v0.23.0) (2017-04-03) 18 | 19 | 20 | ### Features 21 | 22 | * update to latest apis ([9a4dea4](https://github.com/ipfs/js-libp2p-ipfs-browser/commit/9a4dea4)) 23 | 24 | 25 | 26 | 27 | # [0.22.0](https://github.com/ipfs/js-libp2p-ipfs-browser/compare/v0.21.0...v0.22.0) (2017-03-29) 28 | 29 | 30 | 31 | 32 | # [0.21.0](https://github.com/ipfs/js-libp2p-ipfs-browser/compare/v0.20.1...v0.21.0) (2017-03-27) 33 | 34 | 35 | ### Features 36 | 37 | * use new API and update docs ([39c2f7b](https://github.com/ipfs/js-libp2p-ipfs-browser/commit/39c2f7b)) 38 | 39 | 40 | 41 | 42 | ## [0.20.1](https://github.com/ipfs/js-libp2p-ipfs-browser/compare/v0.20.0...v0.20.1) (2017-03-21) 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const gulp = require('gulp') 4 | const Node = require('libp2p-ipfs-nodejs') 5 | const PeerInfo = require('peer-info') 6 | const PeerId = require('peer-id') 7 | const pull = require('pull-stream') 8 | 9 | const sigServer = require('libp2p-webrtc-star/src/sig-server') 10 | let server 11 | 12 | let node 13 | const rawPeer = require('./test/peer.json') 14 | 15 | gulp.task('libnode:start', (done) => { 16 | let count = 0 17 | const ready = () => ++count === 2 ? done() : null 18 | 19 | sigServer.start({ port: 15555 }, (err, _server) => { 20 | if (err) { 21 | throw err 22 | } 23 | server = _server 24 | ready() 25 | }) 26 | 27 | PeerId.createFromJSON(rawPeer, (err, peerId) => { 28 | if (err) { 29 | return done(err) 30 | } 31 | const peer = new PeerInfo(peerId) 32 | 33 | peer.multiaddrs.add('/ip4/127.0.0.1/tcp/9200/ws') 34 | 35 | node = new Node(peer) 36 | node.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn)) 37 | node.start(() => ready()) 38 | }) 39 | }) 40 | 41 | gulp.task('libnode:stop', (done) => { 42 | setTimeout(() => node.stop((err) => { 43 | if (err) { 44 | return done(err) 45 | } 46 | server.stop(done) 47 | }), 2000) 48 | }) 49 | 50 | gulp.task('test:browser:before', ['libnode:start']) 51 | gulp.task('test:node:before', ['libnode:start']) 52 | gulp.task('test:browser:after', ['libnode:stop']) 53 | gulp.task('test:node:after', ['libnode:stop']) 54 | 55 | require('aegir/gulp')(gulp) 56 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const WS = require('libp2p-websockets') 4 | const WebRTCStar = require('libp2p-webrtc-star') 5 | const spdy = require('libp2p-spdy') 6 | const multiplex = require('libp2p-multiplex') 7 | const secio = require('libp2p-secio') 8 | const Railing = require('libp2p-railing') 9 | const libp2p = require('libp2p') 10 | 11 | function mapMuxers (list) { 12 | return list.map((pref) => { 13 | if (typeof pref !== 'string') { 14 | return pref 15 | } 16 | switch (pref.trim().toLowerCase()) { 17 | case 'spdy': 18 | return spdy 19 | case 'multiplex': 20 | return multiplex 21 | default: 22 | throw new Error(pref + ' muxer not available') 23 | } 24 | }) 25 | } 26 | 27 | function getMuxers (options) { 28 | if (options) { 29 | return mapMuxers(options) 30 | } else { 31 | return [multiplex, spdy] 32 | } 33 | } 34 | 35 | class Node extends libp2p { 36 | constructor (peerInfo, peerBook, options) { 37 | options = options || {} 38 | const webRTCStar = new WebRTCStar() 39 | 40 | const modules = { 41 | transport: [ 42 | new WS(), 43 | webRTCStar 44 | ], 45 | connection: { 46 | muxer: getMuxers(options.muxer), 47 | crypto: [ 48 | secio 49 | ] 50 | }, 51 | discovery: [] 52 | } 53 | 54 | if (options.webRTCStar) { 55 | modules.discovery.push(webRTCStar.discovery) 56 | } 57 | 58 | if (options.bootstrap) { 59 | const r = new Railing(options.bootstrap) 60 | modules.discovery.push(r) 61 | } 62 | 63 | super(modules, peerInfo, peerBook, options) 64 | } 65 | } 66 | 67 | module.exports = Node 68 | -------------------------------------------------------------------------------- /examples/mapper/src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const domReady = require('detect-dom-ready') 4 | const createNode = require('./create-node') 5 | 6 | domReady(() => { 7 | const myPeerDiv = document.getElementById('my-peer') 8 | const swarmDiv = document.getElementById('swarm') 9 | 10 | createNode((err, node) => { 11 | if (err) { 12 | return console.log('Could not create the Node, check if your browser has WebRTC Support', err) 13 | } 14 | 15 | node.on('peer:discovery', (peerInfo) => { 16 | console.log('Discovered a peer') 17 | const idStr = peerInfo.id.toB58String() 18 | console.log('Discovered: ' + idStr) 19 | 20 | node.dial(peerInfo, (err, conn) => { 21 | if (err) { return console.log('Failed to dial:', idStr) } 22 | }) 23 | }) 24 | 25 | node.on('peer:connect', (peerInfo) => { 26 | const idStr = peerInfo.id.toB58String() 27 | console.log('Got connection to: ' + idStr) 28 | const connDiv = document.createElement('div') 29 | connDiv.innerHTML = 'Connected to: ' + idStr 30 | connDiv.id = idStr 31 | swarmDiv.append(connDiv) 32 | }) 33 | 34 | node.on('peer:disconnect', (peerInfo) => { 35 | const idStr = peerInfo.id.toB58String() 36 | console.log('Lost connection to: ' + idStr) 37 | document.getElementById(idStr).remove() 38 | }) 39 | 40 | node.start((err) => { 41 | if (err) { 42 | return console.log('WebRTC not supported') 43 | } 44 | 45 | const idStr = node.peerInfo.id.toB58String() 46 | 47 | const idDiv = document 48 | .createTextNode('Node is ready. ID: ' + idStr) 49 | 50 | myPeerDiv.append(idDiv) 51 | 52 | console.log('Node is listening o/') 53 | 54 | // NOTE: to stop the node 55 | // node.stop((err) => {}) 56 | }) 57 | }) 58 | }) 59 | -------------------------------------------------------------------------------- /test/peer.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "Qmex1SSsueWFsUfjdkugJ5zhcnjddAt8TxcnDLUXKD9Sx7", 3 | "privKey": "CAASqAkwggSkAgEAAoIBAQCXzV127CvVHOGMzvsn/U+/32JM58KA6k0FSCCeNFzNowiDS/vV5eezGN5AFoxsF6icWLoaczz7l9RdVD+I/t6PEt9X7XUdrDCtSS8WmAcCgvZWSSf7yAd3jT4GSZDUIgIEeRZsERDt/yVqTLwsZ1G9dMIeh8sbf2zwjTXZIWaRM6o4lq3DYFfzLvJUXlJodxPogU7l7nLkITPUv+yQAMcVHizbNwJvwiETKYeUj73/m/wEPAlnFESexDstxNiIwE/FH8Ao50QPZRO6E6Jb0hhYSI/4CLRdrzDFm/Vzplei3Wr2DokSROaNyeG37VAueyA+pDqn84um+L9uXLwbv5FbAgMBAAECggEAdBUzV/GaQ0nmoQrWvOnUxmFIho7kCjkh1NwnNVPNc+Msa1r7pcI9wJNPwap8j1w4L/cZuYhOJgcg+o2mWFiuULKZ4F9Ro/M89gZ038457g2/2pPu43c/Xoi/2YcAHXg0Gr+OCe2zCIyITBWKAFqyAzL6DubAxrJW2Ezj1LrZ+EZgMyzbh/go/eEGSJaaGkINeAkY144DqDWWWvzyhKhryipsGkZGEkVy9xJgMEI3ipVvuPez2XAvoyyeuinBBLe+Z2vY5G50XXzbIMhIQGLncHf9MwTv6wt1ilyOSLOXK0BoQbB76J3R3is5dSULXXP9r8VocjLBEkmBuf4FXAKzoQKBgQDNNS4F1XE1gxD8LPkL+aB/hi6eVHVPhr+w0I/9ATikcLGeUfBM2Gd6cZRPFtNVrv1p6ZF1D1UyGDknGbDBSQd9wLUgb0fDoo3jKYMGWq6G+VvaP5rzWQeBV8YV2EhSmUk1i6kiYe2ZE8WyrPie7iwpQIY60e2A8Ly0GKZiBZUcHQKBgQC9YDAVsGnEHFVFkTDpvw5HwEzCgTb2A3NgkGY3rTYZ7L6AFjqCYmUwFB8Fmbyc4kdFWNh8wfmq5Qrvl49NtaeukiqWKUUlB8uPdztB1P0IahA2ks0owStZlRifmwfgYyMd4xE17lhaOgQQJZZPxmP0F6mdOvb3YJafNURCdMS51wKBgEvvIM+h0tmFXXSjQ6kNvzlRMtD92ccKysYn9xAdMpOO6/r0wSH+dhQWEVZO0PcE4NsfReb2PIVj90ojtIdhebcr5xpQc1LORQjJJKXmSmzBux6AqNrhl+hhzXfp56FA/Zkly/lgGWaqrV5XqUxOP+Mn8EO1yNgMvRc7g94DyNB1AoGBAKLBuXHalXwDsdHBUB2Eo3xNLGt6bEcRfia+0+sEBdxQGQWylQScFkU09dh1YaIf44sZKa5HdBFJGpYCVxo9hmjFnK5Dt/Z0daHOonIY4INLzLVqg8KECoLKXkhGEIXsDjFQhukn+G1LMVTDSSU055DQiWjlVX4UWD9qo0jOXIkvAoGBAMP50p2X6PsWWZUuuR7i1JOJHRyQZPWdHh9p8SSLnCtEpHYZfJr4INXNmhnSiB/3TUnHix2vVKjosjMTCk/CjfzXV2H41WPOLZ2/Pi3SxCicWIRj4kCcWhkEuIF2jGkg1+jmNiCl/zNMaBOAIP3QbDPtqOWbYlPd2YIzdj6WQ6R4", 4 | "pubKey": "CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXzV127CvVHOGMzvsn/U+/32JM58KA6k0FSCCeNFzNowiDS/vV5eezGN5AFoxsF6icWLoaczz7l9RdVD+I/t6PEt9X7XUdrDCtSS8WmAcCgvZWSSf7yAd3jT4GSZDUIgIEeRZsERDt/yVqTLwsZ1G9dMIeh8sbf2zwjTXZIWaRM6o4lq3DYFfzLvJUXlJodxPogU7l7nLkITPUv+yQAMcVHizbNwJvwiETKYeUj73/m/wEPAlnFESexDstxNiIwE/FH8Ao50QPZRO6E6Jb0hhYSI/4CLRdrzDFm/Vzplei3Wr2DokSROaNyeG37VAueyA+pDqn84um+L9uXLwbv5FbAgMBAAE=" 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "libp2p-ipfs-browser", 3 | "version": "301.0.0", 4 | "description": "libp2p build (module) used in js-ipfs when running it on the browser", 5 | "main": "src/index.js", 6 | "pre-commit": [ 7 | "lint", 8 | "test" 9 | ], 10 | "scripts": { 11 | "lint": "aegir-lint", 12 | "test": "gulp test:browser --dom", 13 | "test:node": "gulp test:node", 14 | "test:browser": "gulp test:browser --dom", 15 | "build": "gulp build", 16 | "release": "gulp release --dom", 17 | "release-minor": "gulp release --type minor --dom", 18 | "release-major": "gulp release --type major --dom", 19 | "coverage": "gulp coverage", 20 | "coverage-publish": "aegir-coverage publish" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/ipfs/js-libp2p-ipfs-browser.git" 25 | }, 26 | "author": "Friedel Ziegelmayer ", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/ipfs/js-libp2p-ipfs-browser/issues" 30 | }, 31 | "homepage": "https://github.com/ipfs/js-libp2p-ipfs-browser#readme", 32 | "devDependencies": { 33 | "aegir": "^11.0.2", 34 | "async": "^2.5.0", 35 | "chai": "^4.0.2", 36 | "dirty-chai": "^2.0.0", 37 | "gulp": "^3.9.1", 38 | "libp2p-ipfs-nodejs": "~0.26.0", 39 | "peer-id": "~0.8.7", 40 | "pre-commit": "^1.2.2", 41 | "pull-goodbye": "0.0.2", 42 | "pull-serializer": "^0.3.2", 43 | "pull-stream": "^3.6.0", 44 | "webrtcsupport": "^2.2.0" 45 | }, 46 | "dependencies": { 47 | "libp2p": "~0.9.1", 48 | "libp2p-multiplex": "^0.4.3", 49 | "libp2p-railing": "~0.5.1", 50 | "libp2p-secio": "~0.6.8", 51 | "libp2p-spdy": "~0.10.6", 52 | "libp2p-swarm": "~0.29.1", 53 | "libp2p-webrtc-star": "~0.11.0", 54 | "libp2p-websockets": "~0.10.0", 55 | "mafmt": "^2.1.8", 56 | "multiaddr": "^2.3.0", 57 | "peer-book": "~0.4.0", 58 | "peer-id": "~0.8.7", 59 | "peer-info": "~0.9.2" 60 | }, 61 | "contributors": [ 62 | "David Dias ", 63 | "Friedel Ziegelmayer ", 64 | "Richard Littauer ", 65 | "greenkeeper[bot] ", 66 | "greenkeeperio-bot ", 67 | "kumavis " 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecation Notice 2 | 3 | This module has been deprecated in favour of: 4 | 5 | - Consolidating examples for libp2p on js-libp2p 6 | - Avoid duplication of code 7 | - Reducing overhead in maintainece. Now the bundles live in js-ipfs itself, see - https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime 8 | - Now all of the tests live in https://github.com/libp2p/js-libp2p/tree/master/test 9 | 10 | -------------------------------------------------------------------------------------------------------------------------- 11 | -------------------------------------------------------------------------------------------------------------------------- 12 | 13 | 14 | 15 | ![](https://github.com/libp2p/js-libp2p/raw/1e3e9db84d1e5fdd5682cc5e0fdaabfcd07ad55a/img/js-libp2p-ipfs-browser.png?raw=true) 16 | 17 | [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) 18 | [![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/) 19 | [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs) 20 | [![Coverage Status](https://coveralls.io/repos/github/ipfs/js-libp2p-ipfs-browser/badge.svg?branch=master)](https://coveralls.io/github/ipfs/js-libp2p-ipfs-browser?branch=master) 21 | [![Travis CI](https://travis-ci.org/ipfs/js-libp2p-ipfs-browser.svg?branch=master)](https://travis-ci.org/ipfs/js-libp2p-ipfs-browser) 22 | [![Circle CI](https://circleci.com/gh/ipfs/js-libp2p-ipfs-browser.svg?style=svg)](https://circleci.com/gh/ipfs/js-libp2p-ipfs-browser) 23 | [![Dependency Status](https://david-dm.org/ipfs/js-libp2p-ipfs-browser.svg?style=flat-square)](https://david-dm.org/ipfs/js-libp2p-ipfs-browser) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) 24 | ![](https://img.shields.io/badge/npm-%3E%3D3.0.0-orange.svg?style=flat-square) 25 | ![](https://img.shields.io/badge/Node.js-%3E%3D4.0.0-orange.svg?style=flat-square) 26 | 27 | [![Sauce Test Status](https://saucelabs.com/browser-matrix/libp2p-ipfs-browser.svg)](https://saucelabs.com/u/libp2p-ipfs-browser) 28 | 29 | > libp2p build (module) used in js-ipfs when running it on the browser. If you are looking for the version to be used in Node.js, see [libp2p-ipfs-nodejs](https://github.com/ipfs/js-libp2p-ipfs-nodejs). 30 | 31 | This libp2p build has support for: 32 | 33 | - WebSockets and WebRTC 34 | - SPDY and mplex stream multiplexing 35 | - secio encrypted channels 36 | - Identify STUN protocol 37 | 38 | ## Table of Contents 39 | 40 | - [Table of Contents](#table-of-contents) 41 | - [Install](#install) 42 | - [Usage](#usage) 43 | - [API](#api) 44 | - [Contribute](#contribute) 45 | - [License](#license) 46 | 47 | ## Install 48 | 49 | ```sh 50 | npm install --save libp2p-ipfs-browser 51 | ``` 52 | 53 | ## Usage 54 | 55 | ```js 56 | const Node = require('libp2p-ipfs-browser') 57 | ``` 58 | 59 | ## API 60 | 61 | API docs can be found at https://github.com/libp2p/js-libp2p#usage 62 | 63 | ## Contribute 64 | 65 | Feel free to join in. All welcome. Open an [issue](https://github.com/ipfs/js-libp2p-ipfs-browser/issues)! 66 | 67 | This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). 68 | 69 | [![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/contributing.md) 70 | 71 | ## License 72 | 73 | [MIT](LICENSE) 74 | -------------------------------------------------------------------------------- /test/webrtc-star-only.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const chai = require('chai') 5 | chai.use(require('dirty-chai')) 6 | const expect = chai.expect 7 | const PeerInfo = require('peer-info') 8 | const PeerId = require('peer-id') 9 | const parallel = require('async/parallel') 10 | const pull = require('pull-stream') 11 | 12 | const Node = require('../src') 13 | 14 | describe('libp2p-ipfs-browser (webrtc only)', () => { 15 | let peer1 16 | let peer2 17 | let node1 18 | let node2 19 | 20 | it('create two peerInfo with webrtc-star addrs', (done) => { 21 | parallel([ 22 | (cb) => PeerId.create({ bits: 1024 }, cb), 23 | (cb) => PeerId.create({ bits: 1024 }, cb) 24 | ], (err, ids) => { 25 | expect(err).to.not.exist() 26 | 27 | peer1 = new PeerInfo(ids[0]) 28 | const ma1 = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + ids[0].toB58String() 29 | peer1.multiaddrs.add(ma1) 30 | 31 | peer2 = new PeerInfo(ids[1]) 32 | const ma2 = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + ids[1].toB58String() 33 | peer2.multiaddrs.add(ma2) 34 | 35 | done() 36 | }) 37 | }) 38 | 39 | it('create two libp2p nodes with those peers', (done) => { 40 | node1 = new Node(peer1, null, { webRTCStar: true }) 41 | node2 = new Node(peer2, null, { webRTCStar: true }) 42 | done() 43 | }) 44 | 45 | it('listen on the two libp2p nodes', (done) => { 46 | parallel([ 47 | (cb) => node1.start(cb), 48 | (cb) => node2.start(cb) 49 | ], done) 50 | }) 51 | 52 | it('handle a protocol on the first node', () => { 53 | node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn)) 54 | }) 55 | 56 | it('dial from the second node to the first node', (done) => { 57 | node1.dial(peer2, '/echo/1.0.0', (err, conn) => { 58 | expect(err).to.not.exist() 59 | setTimeout(check, 500) 60 | 61 | function check () { 62 | const text = 'hello' 63 | const peers1 = node1.peerBook.getAll() 64 | expect(Object.keys(peers1)).to.have.length(1) 65 | 66 | const peers2 = node2.peerBook.getAll() 67 | expect(Object.keys(peers2)).to.have.length(1) 68 | 69 | pull( 70 | pull.values([Buffer(text)]), 71 | conn, 72 | pull.collect((err, data) => { 73 | expect(err).to.not.exist() 74 | expect(data[0].toString()).to.equal(text) 75 | done() 76 | }) 77 | ) 78 | } 79 | }) 80 | }) 81 | 82 | it('node1 hangUp node2', (done) => { 83 | node1.hangUp(peer2, (err) => { 84 | expect(err).to.not.exist() 85 | setTimeout(check, 500) 86 | 87 | function check () { 88 | const peers = node1.peerBook.getAll() 89 | expect(Object.keys(peers)).to.have.length(1) 90 | expect(Object.keys(node1.swarm.muxedConns)).to.have.length(0) 91 | done() 92 | } 93 | }) 94 | }) 95 | 96 | it('create a third node and check that discovery works', (done) => { 97 | let counter = 0 98 | 99 | function check () { 100 | if (++counter === 3) { 101 | expect(Object.keys(node1.swarm.muxedConns).length).to.equal(1) 102 | expect(Object.keys(node2.swarm.muxedConns).length).to.equal(1) 103 | done() 104 | } 105 | } 106 | 107 | PeerId.create((err, id3) => { 108 | expect(err).to.not.exist() 109 | 110 | const peer3 = new PeerInfo(id3) 111 | const ma3 = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + id3.toB58String() 112 | peer3.multiaddrs.add(ma3) 113 | 114 | node1.on('peer:discovery', (peerInfo) => node1.dial(peerInfo, check)) 115 | node2.on('peer:discovery', (peerInfo) => node2.dial(peerInfo, check)) 116 | 117 | const node3 = new Node(peer3, null, { webRTCStar: true }) 118 | node3.start(check) 119 | }) 120 | }) 121 | }) 122 | -------------------------------------------------------------------------------- /test/websockets-only.js: -------------------------------------------------------------------------------- 1 | /* eslint max-nested-callbacks: ["error", 8] */ 2 | /* eslint-env mocha */ 3 | 'use strict' 4 | 5 | const chai = require('chai') 6 | chai.use(require('dirty-chai')) 7 | const expect = chai.expect 8 | const PeerInfo = require('peer-info') 9 | const PeerId = require('peer-id') 10 | const pull = require('pull-stream') 11 | const goodbye = require('pull-goodbye') 12 | const serializer = require('pull-serializer') 13 | 14 | const Node = require('../src') 15 | const rawPeer = require('./peer.json') 16 | 17 | describe('libp2p-ipfs-browser (websockets only)', () => { 18 | let peerB 19 | let nodeA 20 | 21 | before((done) => { 22 | const ma = '/ip4/127.0.0.1/tcp/9200/ws/ipfs/' + rawPeer.id 23 | 24 | PeerId.createFromPrivKey(rawPeer.privKey, (err, id) => { 25 | if (err) { 26 | return done(err) 27 | } 28 | 29 | peerB = new PeerInfo(id) 30 | peerB.multiaddrs.add(ma) 31 | done() 32 | }) 33 | }) 34 | 35 | after((done) => nodeA.stop(done)) 36 | 37 | it('create libp2pNode', (done) => { 38 | PeerInfo.create((err, peerInfo) => { 39 | expect(err).to.not.exist() 40 | peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0') 41 | 42 | nodeA = new Node(peerInfo) 43 | done() 44 | }) 45 | }) 46 | 47 | it('create libp2pNode with multiplex only', (done) => { 48 | PeerInfo.create((err, peerInfo) => { 49 | expect(err).to.not.exist() 50 | 51 | const b = new Node(peerInfo, null, { muxer: ['multiplex'] }) 52 | expect(b.modules.connection.muxer).to.eql([require('libp2p-multiplex')]) 53 | done() 54 | }) 55 | }) 56 | 57 | it('start libp2pNode', (done) => { 58 | nodeA.start(done) 59 | }) 60 | 61 | // General connectivity tests 62 | 63 | it('libp2p.dial using Multiaddr nodeA to nodeB', (done) => { 64 | nodeA.dial(peerB.multiaddrs.toArray()[0], (err) => { 65 | expect(err).to.not.exist() 66 | 67 | setTimeout(check, 500) // Some time for Identify to finish 68 | 69 | function check () { 70 | const peers = nodeA.peerBook.getAll() 71 | expect(Object.keys(peers)).to.have.length(1) 72 | done() 73 | } 74 | }) 75 | }) 76 | 77 | it('libp2p.dial using Multiaddr on Protocol nodeA to nodeB', (done) => { 78 | nodeA.dial(peerB.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => { 79 | expect(err).to.not.exist() 80 | 81 | const peers = nodeA.peerBook.getAll() 82 | expect(Object.keys(peers)).to.have.length(1) 83 | 84 | pull( 85 | pull.values([Buffer('hey')]), 86 | conn, 87 | pull.collect((err, data) => { 88 | expect(err).to.not.exist() 89 | expect(data).to.eql([Buffer('hey')]) 90 | done() 91 | }) 92 | ) 93 | }) 94 | }) 95 | 96 | it('libp2p.hangUp using Multiaddr nodeA to nodeB', (done) => { 97 | nodeA.hangUp(peerB.multiaddrs.toArray()[0], (err) => { 98 | expect(err).to.not.exist() 99 | 100 | setTimeout(check, 500) 101 | 102 | function check () { 103 | const peers = nodeA.peerBook.getAll() 104 | expect(Object.keys(peers)).to.have.length(1) 105 | expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0) 106 | done() 107 | } 108 | }) 109 | }) 110 | 111 | it('libp2p.dial using PeerInfo nodeA to nodeB', (done) => { 112 | nodeA.dial(peerB, (err) => { 113 | expect(err).to.not.exist() 114 | 115 | setTimeout(check, 500) // Some time for Identify to finish 116 | 117 | function check () { 118 | const peers = nodeA.peerBook.getAll() 119 | expect(Object.keys(peers)).to.have.length(1) 120 | done() 121 | } 122 | }) 123 | }) 124 | 125 | it('libp2p.dial using PeerInfo on Protocol nodeA to nodeB', (done) => { 126 | nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => { 127 | expect(err).to.not.exist() 128 | const peers = nodeA.peerBook.getAll() 129 | expect(err).to.not.exist() 130 | expect(Object.keys(peers)).to.have.length(1) 131 | 132 | pull( 133 | pull.values([Buffer('hey')]), 134 | conn, 135 | pull.collect((err, data) => { 136 | expect(err).to.not.exist() 137 | expect(data).to.eql([Buffer('hey')]) 138 | done() 139 | }) 140 | ) 141 | }) 142 | }) 143 | 144 | it('libp2p.hangUp using PeerInfo nodeA to nodeB', (done) => { 145 | nodeA.hangUp(peerB, (err) => { 146 | expect(err).to.not.exist() 147 | setTimeout(check, 500) 148 | 149 | function check () { 150 | const peers = nodeA.peerBook.getAll() 151 | expect(err).to.not.exist() 152 | expect(Object.keys(peers)).to.have.length(1) 153 | expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0) 154 | done() 155 | } 156 | }) 157 | }) 158 | 159 | describe('stress', () => { 160 | it('one big write', (done) => { 161 | nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => { 162 | expect(err).to.not.exist() 163 | const rawMessage = new Buffer(100000) 164 | rawMessage.fill('a') 165 | 166 | const s = serializer(goodbye({ 167 | source: pull.values([rawMessage]), 168 | sink: pull.collect((err, results) => { 169 | expect(err).to.not.exist() 170 | expect(results).to.have.length(1) 171 | expect(Buffer(results[0])).to.have.length(rawMessage.length) 172 | done() 173 | }) 174 | })) 175 | pull(s, conn, s) 176 | }) 177 | }) 178 | 179 | it('many writes', (done) => { 180 | nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => { 181 | expect(err).to.not.exist() 182 | 183 | const s = serializer(goodbye({ 184 | source: pull( 185 | pull.infinite(), 186 | pull.take(1000), 187 | pull.map((val) => Buffer(val.toString())) 188 | ), 189 | sink: pull.collect((err, result) => { 190 | expect(err).to.not.exist() 191 | expect(result).to.have.length(1000) 192 | done() 193 | }) 194 | })) 195 | 196 | pull(s, conn, s) 197 | }) 198 | }) 199 | }) 200 | }) 201 | --------------------------------------------------------------------------------