diff --git a/gun.js b/gun.js index c84c7f34..f190d9cd 100644 --- a/gun.js +++ b/gun.js @@ -735,10 +735,10 @@ } function put(msg){ if(!msg){ return } - var ctx = msg._||'', root = ctx.root = ((msg.$||'')._||'').root; + var ctx = msg._||'', root = ctx.root = ((ctx.$ = msg.$||'')._||'').root; var put = msg.put, id = msg['#'], err, tmp; var DBG = ctx.DBG = msg.DBG; - if(put['#'] && put['.']){ root.on('put', msg); return } + if(put['#'] && put['.']){ root.on('put', msg); return } // TODO: BUG! This needs to call HAM instead. /*root.on(id, function(m){ console.log('ack:', m); });*/ @@ -777,10 +777,11 @@ setTimeout(function(){ ham(val, key, soul, state, msg); }, to > MD? MD : to); // setTimeout Max Defer 32bit :( - if(!ctx.to){ root.on('in', {'@': msg['#'], err: to}) } ctx.to = 1; + if(!ctx.to){ root.on('in', {'@': msg['#'], err: to}) } ctx.to = 1; // TODO: This causes too many problems unless sending peers auto-retry. return to; } - return; + //return; // it should be this + if(!ctx.miss){ return } // but some chains have a cache miss that need to re-fire. // TODO: Improve in future. } (lot = ctx.lot||'').s++; lot.more++; (ctx.stun || (ctx.stun = {}))[soul+key] = 1; @@ -808,7 +809,7 @@ function fire(ctx){ if(ctx.err){ return } var stop = {}; - var root = ctx.root, next = root.next||'', put = ctx.put, tmp; + var root = ((ctx.$||'')._||'').root, next = (root||'').next||'', put = ctx.put, tmp; var S = +new Date; //Gun.graph.is(put, function(node, soul){ for(var soul in put){ var node = put[soul]; // Gun.obj.native() makes this safe. @@ -931,6 +932,7 @@ node = Gun.graph.node(node); tmp = (at||empty).ack; var faith = function(){}; faith.ram = faith.faith = true; // HNPERF: We're testing performance improvement by skipping going through security again, but this should be audited. + faith.$ = msg.$; DBG && (DBG.ga = +new Date); root.on('in', { '@': msg['#'], @@ -1331,6 +1333,9 @@ at.on('in', {get: at.get, put: Gun.val.link.ify(get['#']), $: at.$, '@': msg['@']}); return; } + if(at.$ === (msg._||'').$){ // replying to self, for perf, skip ham/security tho needs audit. + (msg._).miss = (at.put === u); + } Gun.on.put(msg); } var empty = {}, u; @@ -1631,9 +1636,12 @@ } var G = String.fromCharCode(31); function soul(id, as, msg, eve){ - var as = as.as, path = as.p, ref = as.ref, cat = as.at; as = as.as; - var sat = ref.back(function(at){ return sat = at.soul || at.link || at.dub }); - var pat = [sat || as.soul].concat(ref._.has || ref._.get || path) + var as = as.as, path = as.p, ref = as.ref, cat = as.at, pat = []; as = as.as; + ref.back(function(at){ + if(sat = at.soul || at.link || at.dub){ return sat } + pat.push(at.has || at.get); + }); + pat = [sat || as.soul].concat(pat.reverse()); var at = ((msg || {}).$ || {})._ || {}; id = at.dub = at.dub || id || Gun.node.soul(cat.obj) || Gun.node.soul(msg.put || at.put) || Gun.val.link.is(msg.put || at.put) || pat.join('/') /* || (function(){ return (as.soul+'.')+Gun.text.hash(path.join(G)).toString(32); @@ -2157,10 +2165,10 @@ var SMIA = 0; var message, loop; function each(peer){ mesh.say(message, peer) } - var say = mesh.say = function(msg, peer){ - if(this && this.to){ this.to.next(msg) } // compatible with middleware adapters. + var say = mesh.say = function(msg, peer){ var tmp; + if((tmp = this) && (tmp = tmp.to) && tmp.next){ tmp.next(msg) } // compatible with middleware adapters. if(!msg){ return false } - var id, hash, tmp, raw; + var id, hash, raw; var DBG = msg.DBG, S; if(!peer){ S = +new Date ; DBG && (DBG.y = S) } var meta = msg._||(msg._=function(){}); if(!(id = msg['#'])){ id = msg['#'] = Type.text.random(9) } diff --git a/lib/store.js b/lib/store.js index 672f8010..a4af2ad9 100644 --- a/lib/store.js +++ b/lib/store.js @@ -8,7 +8,7 @@ Gun.on('create', function(root){ var Radisk = (Gun.window && Gun.window.Radisk) || require('./radisk'); var Radix = Radisk.Radix; var ST = 0; - + // TODO: BUG! For RN storage, RN does not like the following require: opt.store = opt.store || (!Gun.window && require('./rfs')(opt)); var dare = Radisk(opt), esc = String.fromCharCode(27); diff --git a/test/common.js b/test/common.js index 1cf70726..bee8a035 100644 --- a/test/common.js +++ b/test/common.js @@ -1394,6 +1394,33 @@ describe('Gun', function(){ }); + describe('predictable souls', function(){ + it('public', function(done){ + gun.get('z').get('y').get('x').put({c: {b: {a: 1}}}, function(){ + if(done.c){ return } done.c = 1; + var g = gun._.graph; + expect(g['z']).to.be.ok(); + expect(g['z/y']).to.be.ok(); + expect(g['z/y/x']).to.be.ok(); + expect(g['z/y/x/c']).to.be.ok(); + expect(g['z/y/x/c/b']).to.be.ok(); + done(); + }); + }); + it('public mix', function(done){ + var ref = gun.get('zasdf').put({a: 9}); + var at = gun.get('zfdsa').get('y').get('x').get('c').put(ref); + at.get('foo').get('bar').put('yay'); + ref.get('foo').get('ah').put(1, function(){ + if(done.c){ return } done.c = 1; + var g = gun._.graph; + expect(Object.keys(g['zasdf']).sort()).to.be.eql(['_', 'a', 'foo'].sort()); + expect(Object.keys(g['zasdf/foo']).sort()).to.be.eql(['_', 'bar', 'ah'].sort()); + done(); + }); + }); + }); + describe('plural chains', function(){ this.timeout(9000); it('uncached synchronous map on', function(done){ diff --git a/test/panic/thread.js b/test/panic/thread.js new file mode 100644 index 00000000..e8e67d54 --- /dev/null +++ b/test/panic/thread.js @@ -0,0 +1,230 @@ +var config = { + IP: require('ip').address(), + port: 8765, + servers: 1, + browsers: 2, + route: { + '/': __dirname + '/index.html', + '/gun.js': __dirname + '/../../gun.js', + '/jquery.js': __dirname + '/../../examples/jquery.js', + '/sea.js': __dirname + '/../../sea.js' + } +} + +var panic = require('panic-server'); +panic.server().on('request', function(req, res){ + config.route[req.url] && require('fs').createReadStream(config.route[req.url]).pipe(res); +}).listen(config.port); + +var clients = panic.clients; +var manager = require('panic-manager')(); + +manager.start({ + clients: Array(config.servers).fill().map(function(u, i){ + return { + type: 'node', + port: config.port + (i + 1) + } + }), + panic: 'http://' + config.IP + ':' + config.port +}); + +var servers = clients.filter('Node.js'); +var server = servers.pluck(1); +var browsers = clients.excluding(servers); +var alice = browsers.pluck(1); +var bob = browsers.excluding(alice).pluck(1); + +describe("Private Message Threading", function(){ + //this.timeout(5 * 60 * 1000); + this.timeout(10 * 60 * 1000); + + it("Servers have joined!", function(){ + return servers.atLeast(config.servers); + }); + + it("GUN started!", function(){ + return server.run(function(test){ + var env = test.props; + test.async(); + try{ require('fs').unlinkSync(env.i+'data') }catch(e){} + try{ require('fs').unlinkSync((env.i+1)+'data') }catch(e){} + try{ require('gun/lib/fsrm')(env.i+'data') }catch(e){} + try{ require('gun/lib/fsrm')((env.i+1)+'data') }catch(e){} + var port = env.config.port + env.i; + var server = require('http').createServer(function(req, res){ + res.end("I am "+ env.i +"!"); + }); + var Gun = require('gun'); + var gun = Gun({file: env.i+'data', web: server}); + server.listen(port, function(){ + test.done(); + }); + }, {i: 1, config: config}); + }); + + it(config.browsers +" browser(s) have joined!", function(){ + console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!"); + return browsers.atLeast(config.browsers); + }); + + it("Browsers load SEA!", function(){ + var tests = [], i = 0; + browsers.each(function(client, id){ + tests.push(client.run(function(test){ + test.async(); + //console.log("load?"); + function load(src, cb){ + var script = document.createElement('script'); + script.onload = cb; script.src = src; + document.head.appendChild(script); + } + load('sea.js', function(){ + test.done(); + }); + }, {i: i += 1, config: config})); + }); + return Promise.all(tests); + }); + + it("Browsers initiate user!", function(){ + var tests = [], i = 0; + browsers.each(function(client, id){ + tests.push(client.run(function(test){ + test.async(); + localStorage.clear(); + var env = test.props; + console.log("I AM!!!!", env.i); + var gun = window.gun = Gun('http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun'); + var alice = window.alice = { + "pub": "iYIONCL4rq6-SqmXHjDBoWBJIuhReIHy7MtzBp0zEiw.OXqW4c-FnmcbG2K9IM4avl8WyULHvZxQIyvgTH25PSo", + "priv": "5xIKfcjHSrPPr9u80YVJjDITMsif-MHYQyKY7xH-474", + "epub": "4Goj7wufxhuyc7IdIMInEOqXgNHaZi8mCWgDGrQIikI.2oTovqZJb8Ez-GB4VEIVU4ixWlshPwt-99hcZk9i63E", + "epriv": "6ut8nfxpGSBbyBoZso7QU7jyhiYGRgZZ4LPAtJvWQsQ" + }; + var bob = window.bob = { + "pub": "xDAF7JiabamDhUiUFuh4dI8cjRM-yIZwYInzoKoOLlQ.qyBHHKvFhNs0BesfWmpkkg-AyBslWgQ5NtIjZjtzpRM", + "priv": "skNy4i4FGFZudqxgkPYMjnggylMu_fZnl-vLref1Hl0", + "epub": "ZiCAyWdAixUxYr0I4KRI2raWDXwj0dQltMvdR0_Eld8.Vjz_pGf2LE6i1Qi-8je9U42mnjoPyB50S2dmXZpnC_E", + "epriv": "JdGqj9E_VzfjgLdi0fpj1VjeP5tKPYfstpd1n9DQklg" + } + var me = window.me = (env.i-1)? bob : alice; // keep it DRY since both need to login. + var them = window.them = (env.i-1)? alice : bob; + window.count = 0; + window.check = {}; + window.thread = function thread(node, my, their){ + node.on(msgs => { + //console.log("THREAD!!!", msgs); + for(var time in msgs){ + // don't load ones already loaded + if(thread[time]){ continue } thread[time] = 1; + //console.log("get...", time, msgs); + node.get(time).on(async function(chat){ + if(!chat.msg){ return } + var msg = await SEA.decrypt(chat.msg, sec); + console.log('chat:::::::::::::::::', msg); + window.check[chat.pub + chat.count] = msg; + $('