├── .gitignore ├── LICENSE ├── README.md ├── example.js ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Mathias Buus 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hypercore-protocol-proxy 2 | 3 | A module that allows you to proxy a single hypercore replication stream to multiple peers. 4 | 5 | ``` 6 | npm install hypercore-protocol-proxy 7 | ``` 8 | 9 | Useful if you want to implement a hypercore proxy gateway that replicates with many peers behind the scene, for privacy or connectivity reasons. 10 | 11 | ## Usage 12 | 13 | ``` js 14 | const createProxyStream = require('hypercore-protocol-proxy') 15 | const net = require('net') 16 | const pump = require('pump') 17 | 18 | net.createServer(function (socket) { 19 | const { stream, proxy } = createProxyStream(aFeedKey) 20 | 21 | pump(socket, stream, socket) 22 | 23 | // find some peers something 24 | findSomePeers(aFeedKey, function (stream) { 25 | proxy(stream) // proxy to this peer, can be called multiple times 26 | }) 27 | }).listen(3282) 28 | ``` 29 | 30 | ## API 31 | 32 | #### `{ stream, proxy } = createProxyStream(feedKey, [options])` 33 | 34 | Create a proxy stream and forwarded. 35 | All options are forwarded to hypercore's replication method. 36 | 37 | Call `proxy(stream)` with a stream to another peer to start proxying to them. 38 | It is safe to call this as many times as you want. 39 | 40 | ## License 41 | 42 | MIT 43 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | const ram = require('random-access-memory') 2 | const hypercore = require('hypercore') 3 | const pump = require('pump') 4 | const hyperproxy = require('./') 5 | 6 | const feed = hypercore(ram) 7 | 8 | feed.append(['a', 'b', 'c'], function () { 9 | const {stream, proxy} = hyperproxy(feed.key, {live: true}) 10 | 11 | const a = hypercore(ram, feed.key, {sparse: true}) 12 | const b = hypercore(ram, feed.key) 13 | 14 | pump(stream, a.replicate({live: true}), stream) 15 | setTimeout(function () { 16 | proxy(feed.replicate({live: true})) 17 | proxy(b.replicate({live: true})) 18 | }, 10) 19 | 20 | a.get(1, console.log) 21 | }) 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const protocol = require('hypercore-protocol') 2 | const pump = require('pump') 3 | 4 | module.exports = createProxyStream 5 | 6 | function exec (feed, n, m) { 7 | switch (n) { 8 | case 2: return feed.info(m) 9 | case 3: return feed.have(m) 10 | case 4: return feed.unhave(m) 11 | case 5: return feed.want(m) 12 | case 6: return feed.unwant(m) 13 | case 7: return feed.request(m) 14 | case 8: return feed.cancel(m) 15 | case 9: return feed.data(m) 16 | } 17 | } 18 | 19 | function createProxyStream (key, opts) { 20 | if (!opts) opts = {} 21 | 22 | const proxies = [] 23 | const stream = opts.stream || protocol(opts) 24 | const feed = stream.feed(key) 25 | 26 | // missing info since that is stateful and handshake cause we only allow one 27 | 28 | feed.on('have', execProxy(3)) 29 | feed.on('unhave', execProxy(4)) 30 | 31 | // TODO: reenable these, and don't just send a [0, Inf] want message 32 | // feed.on('want', execProxy(5)) 33 | // feed.on('unwant', execProxy(6)) 34 | 35 | feed.on('request', execProxy(7)) 36 | feed.on('cancel', execProxy(8)) 37 | feed.on('data', execProxy(9)) 38 | 39 | return {stream, proxy} 40 | 41 | function execProxy (n) { 42 | return function (m) { 43 | for (const f of proxies) exec(f, n, m) 44 | } 45 | } 46 | 47 | function execMain (n) { 48 | return function (m) { 49 | exec(feed, n, m) 50 | } 51 | } 52 | 53 | function proxy (otherStream, proxyOpts) { 54 | if (!proxyOpts) proxyOpts = {} 55 | const otherProtocol = proxyOpts.stream || protocol(opts) 56 | const otherFeed = otherProtocol.feed(key) 57 | 58 | proxies.push(otherFeed) 59 | 60 | // See above TODO 61 | otherFeed.want({start: 0, length: 0}) 62 | 63 | otherFeed.on('have', execMain(3)) 64 | otherFeed.on('unhave', execMain(4)) 65 | otherFeed.on('want', execMain(5)) 66 | otherFeed.on('unwant', execMain(6)) 67 | otherFeed.on('request', execMain(7)) 68 | otherFeed.on('cancel', execMain(8)) 69 | otherFeed.on('data', execMain(9)) 70 | 71 | pump(otherStream, otherProtocol, otherStream, done) 72 | 73 | function done () { 74 | proxies.splice(proxies.indexOf(otherFeed), 1) 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hypercore-protocol-proxy", 3 | "version": "1.1.0", 4 | "description": "A module that allows you to proxy a single hypercore replication stream to multiple peers", 5 | "main": "index.js", 6 | "dependencies": { 7 | "hypercore-protocol": "^6.6.4", 8 | "pump": "^3.0.0" 9 | }, 10 | "devDependencies": { 11 | "standard": "^11.0.1" 12 | }, 13 | "scripts": { 14 | "test": "standard" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/mafintosh/hypercore-protocol-proxy.git" 19 | }, 20 | "author": "Mathias Buus (@mafintosh)", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/mafintosh/hypercore-protocol-proxy/issues" 24 | }, 25 | "homepage": "https://github.com/mafintosh/hypercore-protocol-proxy" 26 | } 27 | --------------------------------------------------------------------------------