git ssb

2+

cel / ssb-party



Tree: 8b6827337d6c9a677261c5987cb95bbee685d870

Files: 8b6827337d6c9a677261c5987cb95bbee685d870 / index.js

4152 bytesRaw
1var createConfig = require('ssb-config/inject')
2var ssbKeys = require('ssb-keys')
3var path = require('path')
4var fs = require('fs')
5var MultiServer = require('multiserver')
6var msShs = require('multiserver/plugins/shs')
7var msNet = require('multiserver/plugins/net')
8var muxrpc = require('muxrpc')
9var pull = require('pull-stream')
10var ssbHash = require('pull-hash/ext/ssb')
11var multicb = require('multicb')
12
13function toSodiumKeys(keys) {
14 if(!keys || !keys.public) return null
15 return {
16 publicKey: new Buffer(keys.public.replace('.ed25519', ''), 'base64'),
17 secretKey: new Buffer(keys.private.replace('.ed25519', ''), 'base64'),
18 }
19}
20
21function fixAddBlob(add) {
22 return function (hash, cb) {
23 if (typeof hash === 'function') cb = hash, hash = null
24 var done = multicb({ pluck: 1, spread: true })
25 var sink = pull(
26 ssbHash(done()),
27 add(hash, done())
28 )
29 done(cb)
30 return sink
31 }
32}
33
34function fork(before, after) {
35 return function () {
36 before.apply(this, arguments)
37 after.apply(this, arguments)
38 }
39}
40
41module.exports = function (opts, cb) {
42 if (typeof opts === 'function') cb = opts, opts = null
43 opts = opts || {}
44 var config = createConfig(process.env.ssb_appname || opts.appName, opts)
45 var appKey = config.appKey ||
46 (config.caps && config.caps.shs && new Buffer(config.caps.shs, 'base64'))
47 if (!appKey) return cb(new Error('missing secret-handshake capability key'))
48 var keys = config.keys || (config.keys =
49 ssbKeys.loadOrCreateSync(path.join(config.path, 'secret')))
50 config.manifestFile = path.join(config.path, 'manifest.json')
51
52 var shs = msShs({
53 keys: toSodiumKeys(keys),
54 appKey: appKey,
55 auth: function (cb) { cb(null, false) },
56 timeout: config.timers && config.timers.handshake || 5e3
57 })
58
59 var ms = MultiServer([
60 [msNet({}), shs]
61 ])
62
63 var keyPublic = keys.public.replace('.ed25519', '')
64 var host = config.host || 'localhost'
65 var remote = 'net:' + host + ':' + config.port + '~shs:' + keyPublic
66
67 ;(function tryConnect(remote) {
68 ms.client(remote, function (err, stream) {
69 if (err && err.code === 'ECONNREFUSED') {
70 return spawnSbot(config, function (err, remote) {
71 if (err) return cb(new Error(
72 'unable to connect to or start sbot: ' + err.stack))
73 tryConnect(remote)
74 })
75 }
76 if (err) return cb(new Error('unable to connect to sbot: ' + err.stack))
77
78 var manifest = config.manifest
79 || JSON.parse(fs.readFileSync(config.manifestFile))
80 var sbot = muxrpc(manifest, false)()
81 sbot.id = '@'+stream.remote.toString('base64')+'.ed25519'
82 if (sbot.blobs && sbot.blobs.add) sbot.blobs.add = fixAddBlob(sbot.blobs.add)
83 pull(stream, sbot.createStream(), stream)
84 delete config.keys
85 var keepalive = setInterval(sbot.whoami, 1e3)
86 sbot.close = fork(sbot.close, function () {
87 clearInterval(keepalive)
88 })
89 cb(null, sbot, config)
90 })
91 }(remote))
92}
93
94function spawnSbot(config, cb) {
95 console.error('Starting scuttlebot...')
96 function cbOnce(err, addr) {
97 if (!cb) return
98 cb(err, addr)
99 cb = null
100 }
101 var conf = config.party || {}
102 var out = typeof conf.out === 'string'
103 ? fs.openSync(path.resolve(config.path, conf.out), 'a')
104 : conf.out === false ? 'ignore' : 'inherit'
105 var err = typeof conf.err === 'string'
106 ? fs.openSync(path.resolve(config.path, conf.err), 'a')
107 : conf.err === false ? 'ignore' : conf.err === true ? 'inherit' : out
108 var proc = require('child_process')
109 var scriptPath = path.join(__dirname, 'server.js')
110 var child = proc.spawn(process.execPath, [scriptPath], {
111 detached: true,
112 stdio: ['ignore', out, err, 'ipc'],
113 })
114 child.send(config)
115 child.once('message', function (msg) {
116 var manifestJSON = JSON.stringify(msg.manifest, null, 2)
117 fs.writeFile(config.manifestFile, manifestJSON, function (err) {
118 if (err) console.error('warning: unable to write manifest: ' + err.stack)
119 child.unref()
120 cbOnce(null, msg.address)
121 })
122 })
123 child.once('error', function (err) {
124 cbOnce(new Error('child sbot error: ' + err.stack))
125 })
126}
127

Built with git-ssb-web