diff --git a/lib/bye.js b/lib/bye.js index 1aa2c65e..dc3ea64a 100644 --- a/lib/bye.js +++ b/lib/bye.js @@ -1,12 +1,9 @@ -if(typeof window !== "undefined"){ - var Gun = window.Gun; -} else { - var Gun = require('../gun'); -} +var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); Gun.on('opt', function(ctx){ this.to.next(ctx); if(ctx.once){ return } + console.log("WARNING: `lib/bye` is out of date!"); ctx.on('in', function(msg){ if(!msg.peer || !msg.BYE){ return this.to.next(msg) } var peer = msg.peer(); diff --git a/lib/erase.js b/lib/erase.js index c6509325..73bd271c 100644 --- a/lib/erase.js +++ b/lib/erase.js @@ -1,4 +1,4 @@ -var Gun = Gun || require('../gun'); +var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); Gun.on('opt', function(ctx){ this.to.next(ctx); diff --git a/lib/evict.js b/lib/evict.js index 77fa268c..24a294f1 100644 --- a/lib/evict.js +++ b/lib/evict.js @@ -1,6 +1,5 @@ ;(function(){ - var Gun = (typeof window !== 'undefined')? window.Gun : require('../gun'); - + var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); var ev = {}, empty = {}, u; Gun.on('opt', function(root){ this.to.next(root); diff --git a/lib/forget.js b/lib/forget.js index effd74db..75283ae9 100644 --- a/lib/forget.js +++ b/lib/forget.js @@ -1,6 +1,5 @@ ;(function(){ - - var Gun = (this||{}).Gun || require('../gun'); + var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); Gun.on('opt', function(ctx){ once(ctx); diff --git a/lib/gunwrapper.js b/lib/gunwrapper.js deleted file mode 100644 index 1c256edf..00000000 --- a/lib/gunwrapper.js +++ /dev/null @@ -1,15 +0,0 @@ - -// This does all old-fashion require stuff before '@std/mjs' steps in... -const Gun = require('../gun') -require('../nts') -require('./s3') -try { - require('./ws') -} catch(e) { - require('./wsp/server') -} -require('./verify') -require('./file') -require('./bye') - -module.exports = Gun diff --git a/lib/load.js b/lib/load.js index b84b2d0c..d888fe34 100644 --- a/lib/load.js +++ b/lib/load.js @@ -1,8 +1,4 @@ -if(typeof window !== "undefined"){ - var Gun = window.Gun; -} else { - var Gun = require('../gun'); -} +var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); Gun.chain.open || require('./open'); Gun.chain.load = function(cb, opt, at){ diff --git a/lib/open.js b/lib/open.js index 2b4e5642..499139fa 100644 --- a/lib/open.js +++ b/lib/open.js @@ -1,8 +1,4 @@ -if(typeof window !== "undefined"){ - var Gun = window.Gun; -} else { - var Gun = require('../gun'); -} +var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); Gun.chain.open = function(cb, opt, at){ opt = opt || {}; diff --git a/lib/path.js b/lib/path.js index 780d0f46..71fd3337 100644 --- a/lib/path.js +++ b/lib/path.js @@ -1,8 +1,4 @@ -if(typeof window !== "undefined"){ - var Gun = window.Gun; -} else { - var Gun = require('../gun'); -} +var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); Gun.chain.path = function(field, opt){ var back = this, gun = back, tmp; diff --git a/lib/server.js b/lib/server.js index 9ecc84e3..a209f099 100644 --- a/lib/server.js +++ b/lib/server.js @@ -11,11 +11,8 @@ require('../nts'); require('./store'); require('./rs3'); - //try{require('./ws');}catch(e){require('./wsp/server');} require('./wire'); - require('./verify'); require('./file'); - require('./bye'); require('./evict'); if('debug' === process.env.GUN_ENV){ require('./debug') } module.exports = Gun; diff --git a/lib/set.js b/lib/set.js deleted file mode 100644 index 47b0653c..00000000 --- a/lib/set.js +++ /dev/null @@ -1,35 +0,0 @@ -var Gun = Gun || require('../gun'); - -/* -Gun.chain.set = function(obj, cb, opt){ - var set = this; - opt = opt || {}; - cb = cb || function(){}; - set = set.put({}); // insert assumes a graph node. So either create it or merge with the existing one. - var error, item = set.chain().put(obj, function(err){ // create the new item in its own context. - error = err; // if this happens, it should get called before the .val - }).val(function(val){ - if(error){ return cb.call(set, error) } // which in case it is, allows us to fail fast. - var add = {}, soul = Gun.is.soul.on(val); - if(!soul){ return cb.call(set, {err: Gun.log("No soul!")}) } - add[soul] = val; // other wise, let's then - set.put(add, cb); // merge with the graph node. - }); - return item; -};*/ - -Gun.chain.set = function(val, cb, opt){ - var gun = this, ctx = {}, drift = Gun.time.now(); - cb = cb || function(){}; - opt = opt || {}; - - if(!gun._.back){ gun = gun.put({}) } - gun = gun.not(function(next, key){ - return key? this.put({}).key(key) : this.put({}); - }); - if(!val && !Gun.is.value(val)){ return gun } - - var obj = {}; - obj['I' + drift + 'R' + Gun.text.random(5)] = val; - return gun.put(obj, cb); -} \ No newline at end of file diff --git a/lib/store.js b/lib/store.js index 82b7cd44..8485b0be 100644 --- a/lib/store.js +++ b/lib/store.js @@ -1,8 +1,4 @@ -if(typeof window !== "undefined"){ - var Gun = window.Gun; -} else { - var Gun = require('../gun'); -} +var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); Gun.on('opt', function(ctx){ this.to.next(ctx); diff --git a/lib/then.js b/lib/then.js index 94e7c80e..b0034094 100644 --- a/lib/then.js +++ b/lib/then.js @@ -1,9 +1,9 @@ -var Gun = Gun || require('../gun'); +var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); Gun.chain.promise = function(cb) { var gun = this, cb = cb || function(ctx) { return ctx }; return (new Promise(function(res, rej) { - gun.val(function(data, key){ + gun.once(function(data, key){ res({put: data, get: key, gun: this}); }); })).then(cb); diff --git a/lib/time.js b/lib/time.js index 9025ab1f..b4d8d951 100644 --- a/lib/time.js +++ b/lib/time.js @@ -1,10 +1,5 @@ -if(typeof window !== "undefined"){ - var Gun = window.Gun; -} else { - var Gun = require('../gun'); -} - ;(function(){ + var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); var ify = Gun.node.ify, u; Gun.chain.time = function(data, a, b){ if(data instanceof Function){ @@ -140,4 +135,4 @@ if(typeof window !== "undefined"){ at = at.slice(-7); return new Date(Date.UTC(at[0], parseFloat(at[1])-1, at[2], at[3], at[4], at[5], at[6])); } -}()); +}()); \ No newline at end of file diff --git a/lib/unset.js b/lib/unset.js index 65ae287c..98dae1a9 100644 --- a/lib/unset.js +++ b/lib/unset.js @@ -1,8 +1,4 @@ -if(typeof window !== "undefined"){ - var Gun = window.Gun; -} else { - var Gun = require('gun/gun'); -} +var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); const rel_ = Gun.val.link._; // '#' const node_ = Gun.node._; // '_' diff --git a/lib/wsp/Peer.js b/lib/wsp/Peer.js deleted file mode 100644 index 2b9dffed..00000000 --- a/lib/wsp/Peer.js +++ /dev/null @@ -1,190 +0,0 @@ -/* eslint-disable no-underscore-dangle */ -'use strict'; - -var WebSocket = require('ws'); -var Emitter = require('events'); -var util = require('util'); - -/** - * Calculates backoff instances. - * @param {Object} [options] - Override the default settings. - * @param {Object} options.time=50 - Initial backoff time. - * @param {Object} options.factor=2 - How much to multiply the time by. - * @param {Object} options.max=1min - Maximum backoff time. - * @class - */ -function Backoff (options) { - this.options = options || {}; - - // Sets the initial backoff settings. - this.reset(); -} - -/** - * Increments the time by the factor. - * @return {Number} - The next backoff time. - */ -Backoff.prototype.next = function () { - var next = this.time * this.factor; - - if (next > this.max) { - this.time = this.max; - return this.max; - } - - this.time = next; - - return this.time; -}; - -/** - * Resets the backoff state to it's original condition. - * @return {Backoff} - The context. - */ -Backoff.prototype.reset = function () { - var options = this.options; - - this.time = options.time || 50; - this.factor = options.factor || 2; - this.max = options.max || 1 * 60 * 1000; - - return this; -}; - -/** - * Schedules the next connection, according to the backoff. - * @param {Peer} peer - A peer instance. - * @return {Timeout} - The timeout value from `setTimeout`. - */ -function scheduleReconnect (peer) { - var backoff = peer.backoff; - var time = backoff.time; - backoff.next(); - - var reconnect = peer.connect.bind(peer); - - return setTimeout(reconnect, time); -} - -/** - * Handles reconnections and defers messages until the socket is ready. - * @param {String} url - The address to connect to. - * @param {Object} [options] - Override how the socket is managed. - * @param {Object} options.backoff - Backoff options (see the constructor). - * @class - */ -function Peer (url, options) { - if (!(this instanceof Peer)) { - return new Peer(url, options); - } - - // Extend EventEmitter. - Emitter.call(this); - this.setMaxListeners(Infinity); - - this.options = options || {}; - - // Messages sent before the socket is ready. - this.deferredMsgs = []; - - this.url = Peer.formatURL(url); - this.backoff = new Backoff(this.options.backoff); - - // Set up the websocket. - this.connect(); - - var peer = this; - var reconnect = scheduleReconnect.bind(null, peer); - - // Handle reconnection. - this.on('close', reconnect); - this.on('error', function (error) { - if (error.code === 'ECONNREFUSED') { - reconnect(); - } - }); - - // Send deferred messages. - this.on('open', function () { - peer.drainQueue(); - peer.backoff.reset(); - }); - -} - -/** - * Turns http URLs into WebSocket URLs. - * @param {String} url - The url to format. - * @return {String} - A correctly formatted WebSocket URL. - */ -Peer.formatURL = function (url) { - - // Works for `https` and `wss` URLs, too. - return url.replace(/^http/, 'ws'); -}; - -util.inherits(Peer, Emitter); -var API = Peer.prototype; - -/** - * Attempts a websocket connection. - * @return {WebSocket} - The new websocket instance. - */ -API.connect = function () { - var url = this.url; - - // Open a new websocket. - var socket = new WebSocket(url, this.options.wsc.protocols, this.options.wsc); - - // Re-use the previous listeners. - socket._events = this._events; - - this.socket = socket; - - return socket; -}; - -/** - * Sends all the messages in the deferred queue. - * @return {Peer} - The context. - */ -API.drainQueue = function () { - var peer = this; - - this.deferredMsgs.forEach(function (msg) { - peer.send(msg); - }); - - // Reset the queue. - this.deferredMsgs = []; - - return this; -}; - -/** - * Send data through the socket, or add it to a queue - * of deferred messages if it's not ready yet. - * @param {Mixed} msg - String, or anything that JSON can handle. - * @return {Peer} - The context. - */ -API.send = function (msg) { - var socket = this.socket; - var state = socket.readyState; - var ready = socket.OPEN; - - // Make sure it's a string. - if (typeof msg !== 'string') { - msg = JSON.stringify(msg); - } - - // Make sure the socket is ready. - if (state === ready) { - socket.send(msg); - } else { - this.deferredMsgs.push(msg); - } - - return this; -}; - -module.exports = Peer; diff --git a/lib/wsp/Pool.js b/lib/wsp/Pool.js deleted file mode 100644 index 542c0482..00000000 --- a/lib/wsp/Pool.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; - -/** - * Simpler interface over a collection of sockets. Works with - * WebSocket clients, or sockets from a WebSocket server. - * @class - */ -function Pool () { - if (!(this instanceof Pool)) { - return new Pool(); - } - - // Maps IDs to sockets. - this.sockets = {}; -} - -var API = Pool.prototype; - -/** - * Returns the socket by the given ID. - * @param {String} id - The unique socket ID. - * @return {WebSocket|Null} - The WebSocket, if found. - */ -API.get = function (id) { - return this.sockets[id] || null; -}; - -/** - * Adds a socket to the pool. - * @param {String} id - The socket ID. - * @param {WebSocket} socket - A websocket instance. - * @return {Pool} - The context. - */ -API.add = function (id, socket) { - this.sockets[id] = socket; - - return this; -}; - -/** - * Removes a socket from the pool. - * @param {String} id - The ID of the socket to remove. - * @return {Boolean} - Whether the pool contained the socket. - */ -API.remove = function (id) { - var sockets = this.sockets; - var hasSocket = sockets.hasOwnProperty(id); - - if (hasSocket) { - delete sockets[id]; - } - - return hasSocket; -}; - -/** - * Creates a filtered pool of sockets. Works the same as Array#filter. - * @param {Function} fn - Called for each socket in the pool. - * @param {Mixed} [_this] - The `this` context to use when invoking - * the callback. - * @return {Pool} - A new, filtered socket pool. - */ -API.filter = function (fn, _this) { - var filtered = Pool(); - var pool = this; - - _this = _this || pool; - - Object.keys(this.sockets).forEach(function (id) { - var socket = pool.sockets[id]; - - var shouldAdd = fn.call(_this, socket, id, pool); - - // Add it to the new pool. - if (shouldAdd) { - filtered.add(id, socket); - } - }); - - return filtered; -}; - -/** - * Send a message through each socket in the pool. - * @param {String} msg - The message to send. - * @return {Number} - How many sockets the message was sent to. - */ -API.send = function (msg) { - var pool = this; - - var ids = Object.keys(this.sockets); - - ids.forEach(function (id) { - var socket = pool.sockets[id]; - socket.send(msg); - }); - - return ids.length; -}; - -module.exports = Pool; diff --git a/lib/wsp/client.js b/lib/wsp/client.js deleted file mode 100644 index 3cdb3850..00000000 --- a/lib/wsp/client.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - eslint-disable - no-warning-comments, - no-underscore-dangle, -*/ -'use strict'; - -var Gun = require('../../gun'); -var Socket = require('./Peer'); -var Pool = require('./Pool'); - -// Maps URLs to sockets. -// Shared between all gun instances. -var sockets = Pool(); -var sid = Gun.text.random(); - -/** - * Take a map of URLs pointing to options and ensure the - * urls are using the WS protocol. - * @param {Object} peers - Any object with URLs as keys. - * @return {Object} - Object with normalized URL keys. - */ -function normalizeURLs (peers) { - var formatted = {}; - - Object.keys(peers).forEach(function (url) { - var options = peers[url]; - var id = Socket.formatURL(url); - formatted[id] = options; - }); - - return formatted; -} - -/** - * Turns a map of URLs into a socket pool. - * @param {Object} peers - Any object with URLs as keys. - * @return {Pool} - A pool of sockets corresponding to the URLs. - */ -function getSocketSubset (peers) { - var urls = normalizeURLs(peers); - - return sockets.filter(function (socket) { - return urls.hasOwnProperty(socket.url); - }); -} - -Gun.on('out', function (ctx) { - this.to.next(ctx); - var gun = ctx.gun; - var opt = ctx.opt || {}; - var peers = opt.peers || gun.back('opt.peers'); - var headers = opt.headers || gun.back('opt.headers') || {}; - - if (!peers) { - return; - } - - var subset = getSocketSubset(peers); - - headers['gun-sid'] = sid; - subset.send({ - headers: headers, - body: ctx, - }); -}); - -// Open any new sockets listed, -// adding them to the global pool. -Gun.on('opt', function (context) { - var gun = context.gun; - var root = gun.back(Infinity); - - var peers = gun.back('opt.peers') || {}; - - Gun.obj.map(peers, function (options, url) { - if (sockets[url]) { - return; - } - if (!options.wsc){ options.wsc = gun.back('opt.wsc') || { protocols:null }; } - - var socket = Socket(url, options); - sockets.add(url, socket); - - socket.on('message', function (msg) { - var request; - - try { - request = JSON.parse(msg); - } catch (error) { - return; - } - - // Validate the request. - if (!request || !request.body) { - return; - } - - root.on('in', request.body); - }); - }); - this.to.next(context); -}); diff --git a/lib/wsp/duplicate.js b/lib/wsp/duplicate.js deleted file mode 100644 index 9080fee7..00000000 --- a/lib/wsp/duplicate.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict'; - -var Gun = require('../../gun'); - -var cache = {}; -var timeout = null; - -/** - * Remove all entries in the cache older than 5 minutes. - * Reschedules itself to run again when the oldest item - * might be too old. - * @return {undefined} - */ -function gc () { - var now = Date.now(); - var oldest = now; - var maxAge = 5 * 60 * 1000; - - Gun.obj.map(cache, function (time, id) { - oldest = Math.min(now, time); - - if ((now - time) < maxAge) { - return; - } - - delete cache[id]; - }); - - var done = Gun.obj.empty(cache); - - // Disengage GC. - if (done) { - timeout = null; - return; - } - - // Just how old? - var elapsed = now - oldest; - - // How long before it's too old? - var nextGC = maxAge - elapsed; - - // Schedule the next GC event. - timeout = setTimeout(gc, nextGC); -} - -/** - * Checks a memory-efficient cache to see if a string has been seen before. - * @param {String} id - A string to keep track of. - * @return {Boolean} - Whether it's been seen recently. - */ -function duplicate (id) { - - // Have we seen this ID recently? - var existing = cache.hasOwnProperty(id); - - // Add it to the cache. - duplicate.track(id); - - return existing; -} - -/** - * Starts tracking an ID as a possible future duplicate. - * @param {String} id - The ID to track. - * @return {String} - The same ID. - */ -duplicate.track = function (id) { - cache[id] = Date.now(); - - // Engage GC. - if (!timeout) { - gc(); - } - - return id; -}; - -/** - * Generate a new ID and start tracking it. - * @param {Number} [chars] - The number of characters to use. - * @return {String} - The newly created ID. - */ -duplicate.track.newID = function (chars) { - var id = Gun.text.random(chars); - - return duplicate.track(id); -}; - -module.exports = duplicate; diff --git a/lib/wsp/server-push.js b/lib/wsp/server-push.js deleted file mode 100644 index 772cd452..00000000 --- a/lib/wsp/server-push.js +++ /dev/null @@ -1,98 +0,0 @@ -'use strict'; -var Gun = require('../../gun.js'); - -/** - * Whether the gun instance is attached to a socket server. - * @param {Gun} gun - The gun instance in question. - * @param {WebSocket.Server} server - A socket server gun might be attached to. - * @return {Boolean} - Whether it's attached. - */ -function isUsingServer (gun, server) { - var servers = gun.back(-1)._.servers; - - return servers ? servers.indexOf(server) !== -1 : false; -} - -/** - * Calls a function when (or if) a socket is ready for messages. - * @param {WebSocket} socket - A websocket connection. - * @param {Function} cb - Called if or when the socket is ready. - * @return {Boolean} - Whether the socket is able to take messages. - */ -function ready (socket, cb) { - var state = socket.readyState; - - // The socket is ready. - if (state === socket.OPEN) { - cb(); - return true; - } - - // Still opening. - if (state === socket.OPENING) { - socket.once('open', cb); - } - - // Nope, closing or closed. - return false; -} - -/** - * Send a message to a group of clients. - * @param {Obejct} msg - An http envelope-like message. - * @param {Object} clients - IDs mapped to socket instances. - * @return {undefined} - */ -function send (msg, clients) { - Gun.obj.map(clients, function (client) { - ready(client, function () { - var serialized = JSON.stringify(msg); - client.send(serialized); - }); - }); -} - -/** * Attaches server push middleware to gun. - * @param {Gun} gun - The gun instance to attach to. - * @param {WebSocket.Server} server - A websocket server instance. - * @return {server} - The socket server. - */ -function attach (gun, server) { - var root = gun.back(-1); - root._.servers = root._.servers || []; - root._.servers.push(server); - var pool = {}; - var sid = Gun.text.random(); - server.on('connection', function (socket) { - socket.id = socket.id || Gun.text.random(10); - pool[socket.id] = socket; - /* - socket.on('message', function (message) { - var data = Gun.obj.ify(message); - - if (!data || !data.body) { - return; - } - root.on('in', data.body); - }); - */ - socket.once('close', function () { - delete pool[socket.id]; - }); - }); - - Gun.on('out', function (context) { - this.to.next(context); - if (!isUsingServer(context.gun, server) || Gun.obj.empty(pool)) { - return; - } - - var msg = { - headers: { 'gun-sid': sid }, - body: context, - }; - send(msg, pool); - }); -} - -module.exports = attach; diff --git a/lib/wsp/server.js b/lib/wsp/server.js deleted file mode 100644 index c7fb528c..00000000 --- a/lib/wsp/server.js +++ /dev/null @@ -1,257 +0,0 @@ -/* eslint-disable require-jsdoc, no-underscore-dangle */ -'use strict'; -var Gun = require('../../gun'); -var http = require('../http'); -var url = require('url'); -var WS = require('ws'); -var WSS = WS.Server; -var attach = require('./server-push'); - -// Handles server to server sync. -require('./client.js'); - -Gun.on('opt', function (at) { - this.to.next(at); - var gun = at.gun, opt = at.opt; - gun.__ = at.root; - gun.__.opt.ws = opt.ws = gun.__.opt.ws || opt.ws || {}; - gun.__.opt.ws.path = gun.__.opt.ws.path || '/gun'; - - if(gun.__.opt.web){ - setTimeout(function(){ - if(gun.__.opt.web.use){ - gun.__.opt.web.use(Gun.serve); - } - start(gun.__.opt.web); - },1); - } - function start (server, port, app) { - if (app && app.use) { - app.use(gun.wsp.server); - } - server = gun.__.opt.ws.server = gun.__.opt.ws.server || gun.__.opt.web || opt.ws.server || server; - - if (!gun.wsp.ws) { - //console.log("????????", gun.__.opt.ws); - gun.wsp.ws = new WSS(gun.__.opt.ws); - attach(gun, gun.wsp.ws); - } - - require('./ws')(gun.wsp.ws, function (req, res) { - var ws = this; - req.headers['gun-sid'] = ws.sid = ws.sid ? ws.sid : req.headers['gun-sid']; - ws.sub = ws.sub || gun.wsp.on('network', function (msg) { - var ev = this; ev.to.next(msg); - if (!ws || !ws.send || !ws._socket || !ws._socket.writable) { return ev.off(); } - if (!msg || (msg.headers && msg.headers['gun-sid'] === ws.sid)) { return; } - if (msg && msg.headers) { delete msg.headers['ws-rid']; } - // TODO: BUG? ^ What if other peers want to ack? Do they use the ws-rid or a gun declared id? - try { ws.send(Gun.text.ify(msg)); - } catch (e) {} // juuuust in case. - }); - gun.wsp.wire(req, res); - }, {headers: {'ws-rid': 1, 'gun-sid': 1}}); - gun.__.opt.ws.port = gun.__.opt.ws.port || opt.ws.port || port || 80; - } - var wsp = gun.wsp = gun.wsp || function (server) { - console.log("WARNING: gun.wsp(server) should be switched to Gun({web: server}) by v0.7!") - if (!server) { return gun; } - if (Gun.fns.is(server.address)) { - if (server.address()) { - start(server, server.address().port); - return gun; - } - } - if (Gun.fns.is(server.get) && server.get('port')) { - start(server, server.get('port')); - return gun; - } - var listen = server.listen; - server.listen = function (port) { - var serve = listen.apply(server, arguments); - start(serve, port, server); - return serve; - }; - return gun; - }; - gun.wsp.on = gun.wsp.on || Gun.on; - gun.wsp.regex = gun.wsp.regex || opt.route || opt.path || /^\/gun/i; - gun.wsp.poll = gun.wsp.poll || opt.poll || 1; - gun.wsp.pull = gun.wsp.pull || opt.pull || gun.wsp.poll * 1000; - gun.wsp.server = gun.wsp.server || function (req, res, next) { // http - next = next || function () {}; - if (!req || !res) { return next(), false; } - if (!req.url) { return next(), false; } - if (!req.method) { return next(), false; } - var msg = {}; - msg.url = url.parse(req.url, true); - if (!gun.wsp.regex.test(msg.url.pathname)) { return next(), false; } // TODO: BUG! If the option isn't a regex then this will fail! - if (msg.url.pathname.replace(gun.wsp.regex, '').slice(0, 3).toLowerCase() === '.js') { - res.writeHead(200, {'Content-Type': 'text/javascript'}); - res.end(gun.wsp.js = gun.wsp.js || require('fs').readFileSync(__dirname + '/../../gun.js')); // gun server is caching the gun library for the client - return true; - } - - if (!req.upgrade) { - next(); - return false; - } - - return http(req, res, function (req, res) { - if (!req) { return next(); } - var stream, cb = res = require('../jsonp')(req, res); - if (req.headers && (stream = req.headers['gun-sid'])) { - stream = (gun.wsp.peers = gun.wsp.peers || {})[stream] = gun.wsp.peers[stream] || {sid: stream}; - stream.drain = stream.drain || function (res) { - if (!res || !stream || !stream.queue || !stream.queue.length) { return; } - res({headers: {'gun-sid': stream.sid}, body: stream.queue }); - stream.off = setTimeout(function () { stream = null; }, gun.wsp.pull); - stream.reply = stream.queue = null; - return true; - }; - stream.sub = stream.sub || gun.wsp.on('network', function (req) { - var ev = this; ev.to.next(req); - if (!stream) { return ev.off(); } // self cleans up after itself! - if (!req || (req.headers && req.headers['gun-sid'] === stream.sid)) { return; } - (stream.queue = stream.queue || []).push(req); - stream.drain(stream.reply); - }); - cb = function (r) { (r.headers || {}).poll = gun.wsp.poll; res(r); }; - clearTimeout(stream.off); - if (req.headers.pull) { - if (stream.drain(cb)) { return; } - return stream.reply = cb; - } - } - gun.wsp.wire(req, cb); - }), true; - }; - if ((gun.__.opt.maxSockets = opt.maxSockets || gun.__.opt.maxSockets) !== false) { - require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = gun.__.opt.maxSockets || Infinity; - } - gun.wsp.msg = gun.wsp.msg || function (id) { - if (!id) { - return gun.wsp.msg.debounce[id = Gun.text.random(9)] = Gun.time.is(), id; - } - clearTimeout(gun.wsp.msg.clear); - gun.wsp.msg.clear = setTimeout(function () { - var now = Gun.time.is(); - Gun.obj.map(gun.wsp.msg.debounce, function (t, id) { - if ((now - t) < (1000 * 60 * 5)) { return; } - Gun.obj.del(gun.wsp.msg.debounce, id); - }); - }, 500); - if (id = gun.wsp.msg.debounce[id]) { - return gun.wsp.msg.debounce[id] = Gun.time.is(), id; - } - gun.wsp.msg.debounce[id] = Gun.time.is(); - return; - }; - gun.wsp.msg.debounce = gun.wsp.msg.debounce || {}; - gun.wsp.wire = gun.wsp.wire || (function () { - // all streams, technically PATCH but implemented as - // PUT or POST, are forwarded to other trusted peers - // except for the ones that are listed in the message - // as having already been sent to. - // all states, implemented with GET, are replied to the - // source that asked for it. - function tran (req, res) { - if (!req || !res || !req.body || !req.headers) { - return; - } - if (req.url) { - req.url = url.format(req.url); - } - // var msg = req.body; - gun.on('in', req.body); - // // AUTH for non-replies. - // if(gun.wsp.msg(msg['#'])){ return } - // gun.wsp.on('network', Gun.obj.copy(req)); - // if(msg['@']){ return } // no need to process. - // if(msg['$'] && msg['$']['#']){ return tran.get(req, res) } - // //if(Gun.is.lex(msg['$'])){ return tran.get(req, res) } - // else { return tran.put(req, res) } - // cb({body: {hello: 'world'}}); - // // TODO: BUG! server put should push. - } - tran.get = function (req, cb) { - var body = req.body; - var lex = body.$; - var reply = { - headers: { 'Content-Type': tran.json }, - }; - - var graph = gun.back(Infinity)._.graph; - var node = graph[lex['#']]; - var result = Gun.graph.ify(node); - - if (node) { - cb({ - headers: reply.headers, - body: { - '#': gun.wsp.msg(), - '@': body['#'], - '$': result, - }, - }); - - return; - } - - gun.on('out', { - gun: gun, - get: lex, - req: 1, - '#': body['#'] || Gun.on.ask(function (at, ev) { - ev.off(); - var graph = at.put; - return cb({ - headers: reply.headers, - body: { - '#': gun.wsp.msg(), - '@': body['#'], - '$': graph, - '!': at.err, - }, - }); - }), - }); - }; - - tran.put = function (req, cb) { - // NOTE: It is highly recommended you do your own PUT/POSTs - // through your own API that then saves to gun manually. - // This will give you much more fine-grain control over - // security, transactions, and what not. - var body = req.body; - var graph = body.$; - var reply = { - headers: { 'Content-Type': tran.json }, - }; - - gun.on('out', { - gun: gun, - put: graph, - '#': Gun.on.ask(function (ack, ev) { - ev.off(); - return cb({ - headers: reply.headers, - body: { - '#': gun.wsp.msg(), - '@': body['#'], - '$': ack, - '!': ack.err, - }, - }); - }), - }); - }; - - tran.json = 'application/json'; - return tran; - }()); - - if (opt.server) { - wsp(opt.server); - } -}); diff --git a/lib/wsp/ws.js b/lib/wsp/ws.js deleted file mode 100644 index 57916afd..00000000 --- a/lib/wsp/ws.js +++ /dev/null @@ -1,40 +0,0 @@ -var Gun = require('../../gun') -, url = require('url'); -module.exports = function(wss, server, opt){ - wss.on('connection', function(ws){ - var req = {}; - ws.upgradeReq = ws.upgradeReq || {}; - req.url = url.parse(ws.upgradeReq.url||''); - req.method = (ws.upgradeReq.method||'').toLowerCase(); - req.headers = ws.upgradeReq.headers || {}; - //Gun.log("wsReq", req); - ws.on('message', function(msg){ - msg = Gun.obj.ify(msg); - msg.url = msg.url || {}; - msg.url.pathname = (req.url.pathname||'') + (msg.url.pathname||''); - Gun.obj.map(req.url, function(val, i){ - msg.url[i] = msg.url[i] || val; // reattach url - }); - msg.method = msg.method || msg.body? 'put' : 'get'; - msg.headers = msg.headers || {}; - Gun.obj.map(opt.headers || req.headers, function(val, i){ - msg.headers[i] = msg.headers[i]; // reattach headers - }); - server.call(ws, msg, function(reply){ - if(!ws || !ws.send || !ws._socket || !ws._socket.writable){ return } - reply = reply || {}; - if(msg && msg.headers && msg.headers['ws-rid']){ - (reply.headers = reply.headers || {})['ws-rid'] = msg.headers['ws-rid']; - } - try{ws.send(Gun.text.ify(reply)); - }catch(e){} // juuuust in case. - }); - }); - ws.off = function(m){ - //Gun.log("ws.off", m); - ws.send = null; - } - ws.on('close', ws.off); - ws.on('error', ws.off); - }); -} \ No newline at end of file