diff --git a/client.js b/client.js index d3a98cc..2e4d35c 100644 --- a/client.js +++ b/client.js @@ -5,6 +5,7 @@ var Onion = require('multiserver/plugins/onion') var Shs = require('multiserver/plugins/shs') var NoAuth = require('multiserver/plugins/noauth') var UnixSock = require('multiserver/plugins/unix-socket') +const decodeAddress = require('multiserver-address').decode var explain = require('explain-error') var muxrpc = require('muxrpc') var pull = require('pull-stream') @@ -23,32 +24,10 @@ module.exports = function (opts, cb) { var config = opts.config var manifest = opts.manifest - var shs = Shs({ - keys: toSodiumKeys(keys), - appKey: opts.config.caps.shs, - - // no client auth. we can't receive connections anyway. - auth: function (cb) { cb(null, false) }, - timeout: config.timers && config.timers.handshake || 3000 - }) - // todo: refactor multiserver so that muxrpc is a transform. // then we can upgrade muxrpc's codec! - var noauth = NoAuth({ - keys: toSodiumKeys(keys) - }) - - // I think it would be better to make these registerable plugins, - // that got connected up when you called. so they are not hard coded here. - - var ms = MultiServer([ - [Net({}), shs], - [Onion({}), shs], - [WS({}), shs], - [UnixSock({}), noauth], - [Net({}), noauth] - ]) + const ms = makeMultiServer(opts, remote) ms.client(remote, function (err, stream) { if (err) { @@ -98,3 +77,57 @@ module.exports = function (opts, cb) { pull(stream, sbot.stream, stream) }) } + +function makeMultiServer(opts, remote) { + // find out what transports and protocols + // we actually need to connect to 'remote' + const addresses = decodeAddress(remote) + const requiredPlugins = {} + addresses.forEach(address=>{ + address.forEach(({name})=> requiredPlugins[name] = true) + }) + + // make shs instance, if needed + const shs = requiredPlugins.shs && Shs({ + keys: toSodiumKeys(opts.keys), + appKey: opts.config.caps.shs, + + // no client auth. we can't receive connections anyway. + auth: function (cb) { cb(null, false) }, + timeout: opts.config.timers && config.timers.handshake || 3000 + }) + + // make noauth instance, if needed + const noauth = requiredPlugins.noauth && NoAuth({ + keys: toSodiumKeys(opts.keys) + }) + + const stack = [] + if (requiredPlugins.net && shs) { + stack.push( + [Net({}), shs] + ) + } + if (requiredPlugins.onion && shs) { + stack.push( + [Onion({}), shs] + ) + } + if (requiredPlugins.ws && shs) { + stack.push( + [WS({}), shs] + ) + } + if (requiredPlugins.unix && noauth) { + stack.push( + [UnixSock({}), noauth] + ) + } + if (requiredPlugins.net && noauth) { + stack.push( + [Net({}), noauth] + ) + } + + return MultiServer(stack) +} diff --git a/package.json b/package.json index 99398d0..aa8f1f7 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "explain-error": "^1.0.1", "multicb": "^1.2.1", "multiserver": "^3.1.2", + "multiserver-address": "^1.0.1", "muxrpc": "^6.5.0", "pull-hash": "^1.0.0", "pull-stream": "^3.6.0", @@ -23,6 +24,9 @@ "devDependencies": { "ssb-master": "^1.0.2", "ssb-server": "^14.1.2", + "ssb-onion": "^1.0.0", + "ssb-unix-socket": "^1.0.0", + "ssb-ws": "^6.2.3", "tape": "^4.2.0" }, "author": "Paul Frazee ", diff --git a/test/transports.js b/test/transports.js new file mode 100644 index 0000000..80675b7 --- /dev/null +++ b/test/transports.js @@ -0,0 +1,83 @@ +const tape = require('tape') +const ssbKeys = require('ssb-keys') +const pull = require('pull-stream') +const ssbServer = require('ssb-server') + .use(require('ssb-server/plugins/no-auth')) + .use(require('ssb-master')) + .use(require('ssb-ws')) + .use(require('ssb-unix-socket')) + .use(require('ssb-onion')) + +const ssbClient = require('../') + +const shsCap = 'XMHDXXFGBJvloCk8fOinzPkKMRqyA2/eH+3VyUr6lig=' + +const keys = ssbKeys.generate() + +// ssb-server does not support more than one unix socket server +// (if there's more than one, they end up having the same file system path, because ssb.config.path is used for this) +// That's why we create a new server for each transport +// +// More problems: +// - a 2nd unix socket cannot be created by the same process? Even when created by a different multi-server instnace after the +// You can uncomment one or the other unix incomings below, but not both! +// first instance was closed? +// - I can't get the onion stuff to work here. I don't see why. + +const incomings = { + //"unix-shs": {transport: 'unix', opts: {transform: "shs", scope: "device"}}, + "net-shs": {transport: 'net', opts: {transform: "shs", scope: "device", port: 45451}}, + "ws-shs": {transport: 'ws', opts: {transform: "shs", scope: "device", port: 45452}}, + //"onion-shs": {transport: 'onion', opts: {transform: "shs", scope: "private"}}, + "unix-noauth": {transport: 'unix', opts: {transform: "noauth", scope: "device"}} +} + +for (let [testname, incoming] of Object.entries(incomings)) { + tape(testname, t =>{ + let {transport, opts} = incoming + makeServer(transport, testname, opts, (err, server) =>{ + const address = server.getAddress("device") + console.log('a server is listening on: %s', address) + t.pass() + server.close(()=>t.end()) + }) + }) +} + +/* +tape.skip('net', function (t) { + ssbClient(keys, { remote: address, manifest: server.manifest(), caps: { shs: shsCap } }, function (err, client) { + if (err) throw err + + client.whoami(function (err, info) { + if (err) throw err + + console.log('whoami', info) + t.equal(info.id, keys.id) + t.end() + client.close(true) + }) + }) + }) +}) +*/ + +function makeServer(transport, testname, opts, cb) { + const server = ssbServer({ + timeout: 2001, + temp: 'connect-' + testname, + master: keys.id, + keys: keys, + caps: { shs: shsCap }, + connections: { + incoming: { + [transport]: [opts] + } + } + }) + + server.on('multiserver:listening', () => { + cb (null, server) + }) +} +