├── lib ├── server │ ├── public │ │ ├── jquery.js │ │ └── index.html │ ├── start.js │ ├── listen.js │ └── downlink.js ├── browser │ ├── index.js │ └── shimMesh.js ├── client │ ├── connect.js │ └── uplink.js └── Mesh.js ├── .gitignore ├── .travis.yml ├── examples ├── 0_basic │ ├── README.md │ ├── server.js │ └── client.js ├── 1_resource-events │ ├── README.md │ ├── creature.js │ ├── client.js │ └── server.js ├── 3_mesh │ ├── README.md │ └── node.js ├── 4_browser │ └── server.js └── 2_authorization │ ├── client.js │ └── server.js ├── package.json ├── index.js ├── test ├── client-server-test.js ├── server-client-test.js ├── siblings-test.js └── basic-tests.js └── README.md /lib/server/public/jquery.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.11 4 | notifications: 5 | email: 6 | - travis@marak.com 7 | irc: "irc.freenode.org#big" -------------------------------------------------------------------------------- /examples/0_basic/README.md: -------------------------------------------------------------------------------- 1 | # Basic 2 | 3 | This will setup a client node and server node. 4 | 5 | Event are broadcasted directly on the `mesh.emitter` Event Emitter. -------------------------------------------------------------------------------- /examples/1_resource-events/README.md: -------------------------------------------------------------------------------- 1 | # Resource Events 2 | 3 | This will setup a client node and server node where the server has a public resource enabled to remote. 4 | 5 | -------------------------------------------------------------------------------- /examples/3_mesh/README.md: -------------------------------------------------------------------------------- 1 | # Mesh 2 | 3 | This example uses the auto-detecting ability of `mesh.start` to automatically either connect to an existing mesh, or to start up a new mesh server. -------------------------------------------------------------------------------- /examples/1_resource-events/creature.js: -------------------------------------------------------------------------------- 1 | var resource = require('resource'); 2 | 3 | var creature = resource.define('creature'); 4 | // TODO: make remote a getter / setter that updates event table 5 | creature.remote = true; 6 | 7 | // TODO: add granular controls for remote methods 8 | // so that entire resource isn't exposed 9 | creature.method('talk', function(options, callback){ 10 | console.log('talking', options) 11 | callback(null, options.text); 12 | }); 13 | 14 | module['exports'].creature = creature; -------------------------------------------------------------------------------- /examples/3_mesh/node.js: -------------------------------------------------------------------------------- 1 | var resource = require('resource'), 2 | http = require('resource-http'), 3 | mesh = require('../../index'); 4 | 5 | require('colors'); 6 | 7 | mesh.start({ port: 7777 }, function (err){ 8 | 9 | if (err) { 10 | throw err; 11 | } 12 | 13 | mesh.emitter.on('customEvent', function(data){ 14 | console.log(process.pid + ' - mesh '.yellow + this.event + " - " + data.pid); 15 | }); 16 | 17 | setInterval(function(){ 18 | mesh.emitter.emit('customEvent', { "pid": process.pid }); 19 | }, 1000); 20 | 21 | }); -------------------------------------------------------------------------------- /lib/browser/index.js: -------------------------------------------------------------------------------- 1 | var resource = require('resource'), 2 | mesh = resource.define('mesh'); 3 | 4 | var Mesh = require('./shimMesh'); 5 | 6 | mesh.method('connect', connect); 7 | mesh.method('start', start); 8 | 9 | function connect (opts, cb) { 10 | var _mesh = new Mesh(); 11 | mesh.emitter = _mesh.emitter; 12 | 13 | return _mesh.connect(opts, cb); 14 | }; 15 | 16 | function start (opts, cb) { 17 | var _mesh = new Mesh(); 18 | mesh.emitter = _mesh.emitter; 19 | return _mesh.start(opts, cb); 20 | }; 21 | 22 | 23 | module['exports'] = mesh; -------------------------------------------------------------------------------- /examples/1_resource-events/client.js: -------------------------------------------------------------------------------- 1 | var mesh = require('../../').mesh; 2 | var resource = require('resource'); 3 | // var creature = require('./creature').creature; 4 | 5 | require('colors') 6 | 7 | mesh.connect({ port: 7777, name: "test-client" }, function(err){ 8 | 9 | if (err) { 10 | console.log('error connecting to mesh server. most likely the server is not running.', err); 11 | process.exit(); 12 | } 13 | 14 | setInterval(function(){ 15 | console.log('emitting creature::talk') 16 | mesh.emitter.emit('creature::talk', { text: "Hi!" }); 17 | }, 2000); 18 | 19 | }); -------------------------------------------------------------------------------- /lib/client/connect.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('resource::mesh'); 2 | 3 | module['exports'] = function connect (options, callback) { 4 | 5 | debug('Attempting to connect to existing mesh'); 6 | 7 | var mesh = this, 8 | client = require('engine.io-client'); 9 | 10 | mesh.client = new client.Socket({ host: options.host, port: options.port }); 11 | mesh.client.on('error', function (err) { 12 | return callback(err); 13 | }); 14 | 15 | mesh.client.on('open', function(socket){ 16 | debug('Client connected to mesh'); 17 | mesh.mode = "client"; 18 | mesh.uplink(options, callback); 19 | }); 20 | 21 | return mesh; 22 | }; -------------------------------------------------------------------------------- /lib/server/start.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('resource::mesh'); 2 | 3 | module['exports'] = function start (options, callback) { 4 | 5 | var mesh = this; 6 | 7 | if (!callback && typeof options === 'function') { 8 | callback = options; 9 | options = {}; 10 | } 11 | 12 | mesh.listen(options, function (err) { 13 | if (err && err.code === 'EADDRINUSE') { 14 | debug('Service already listening on ' + options.port); 15 | return mesh.connect(options, callback); 16 | } 17 | if (callback) { 18 | callback(null, mesh.server); 19 | } 20 | }); 21 | 22 | return mesh; 23 | 24 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "resource-mesh", 3 | "version": "0.5.1", 4 | "description": "provides a distributed p2p event emitter mesh", 5 | "keywords": [ 6 | "mesh", 7 | "p2p", 8 | "eventemitter" 9 | ], 10 | "main": "./index.js", 11 | "scripts": { 12 | "test": "tap test" 13 | }, 14 | "dependencies": { 15 | "debug": "*", 16 | "engine.io": "1.4.1", 17 | "engine.io-client": "1.4.1", 18 | "eventemitter2": "*", 19 | "resource": "https://github.com/bigcompany/resource/tarball/master", 20 | "resource-http": "0.5.x" 21 | }, 22 | "devDependencies": { 23 | "tap": "*", 24 | "colors": "*" 25 | } 26 | } -------------------------------------------------------------------------------- /examples/1_resource-events/server.js: -------------------------------------------------------------------------------- 1 | var resource = require('resource'), 2 | http = require('resource-http'), 3 | mesh = require('../../').mesh; 4 | 5 | require('colors'); 6 | 7 | 8 | var creature = require('./creature').creature; 9 | 10 | // sets creature resource to be available for remote method calls from the mesh 11 | // creature.remote = true; 12 | 13 | 14 | mesh.listen({ port: 7777 }, function (err){ 15 | 16 | if (err) { 17 | console.log('error starting to mesh server.', err); 18 | process.exit(); 19 | } 20 | 21 | // since creature resource has been set to remote, 22 | /// all creature events are available to the mesh 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /examples/4_browser/server.js: -------------------------------------------------------------------------------- 1 | var resource = require('resource'), 2 | mesh = require('../../'); 3 | 4 | // 5 | // Remark: See: ./lib/server/public folder for index.html file and mesh.js browser bundle 6 | // 7 | 8 | // 9 | // The mesh has started, visit the WebSocket Gateway at: http://localhost:8888 10 | // 11 | mesh.listen({ port: 8888 }, function (err){ 12 | 13 | if (err) { 14 | console.log('error starting to mesh server.', err); 15 | process.exit(); 16 | } 17 | 18 | mesh.emitter.on('hello', function (data){ 19 | console.log('Hello ', data); 20 | }); 21 | 22 | setInterval(function(){ 23 | mesh.emitter.emit('hello', 'i am server ' + process.pid); 24 | }, 5000); 25 | 26 | }); -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var resource = require('resource'), 2 | mesh = resource.define('mesh'); 3 | 4 | var Mesh = require('./lib/Mesh'); 5 | 6 | mesh.method('listen', listen); 7 | mesh.method('connect', connect); 8 | mesh.method('start', start); 9 | 10 | function listen (opts, cb) { 11 | var _mesh = new Mesh(); 12 | mesh.emitter = _mesh.emitter; 13 | return _mesh.listen(opts, cb); 14 | }; 15 | 16 | function connect (opts, cb) { 17 | var _mesh = new Mesh(); 18 | mesh.emitter = _mesh.emitter; 19 | return _mesh.connect(opts, cb); 20 | }; 21 | 22 | function start (opts, cb) { 23 | var _mesh = new Mesh(); 24 | mesh.emitter = _mesh.emitter; 25 | return _mesh.start(opts, cb); 26 | }; 27 | 28 | 29 | module['exports'] = mesh; -------------------------------------------------------------------------------- /examples/0_basic/server.js: -------------------------------------------------------------------------------- 1 | var resource = require('resource'), 2 | http = require('resource-http'), 3 | mesh = require('../../'); 4 | 5 | require('colors'); 6 | 7 | mesh.listen({ port: 7777 }, function (err){ 8 | 9 | if (err) { 10 | console.log('error starting to mesh server.', err); 11 | process.exit(); 12 | } 13 | 14 | setInterval(function(){ 15 | mesh.emitter.emit('server-foo', 'i am server ' + process.pid); 16 | }, 5000); 17 | 18 | mesh.emitter.on('client-foo', function(data){ 19 | console.log('got client foo event'); 20 | mesh.emitter.emit('server-echo-client-foo', 'hello'); 21 | }) 22 | 23 | 24 | mesh.emitter.on('hello', function(data){ 25 | console.log('hello', data) 26 | }) 27 | 28 | 29 | 30 | }); 31 | -------------------------------------------------------------------------------- /examples/2_authorization/client.js: -------------------------------------------------------------------------------- 1 | var mesh = require('../../').mesh; 2 | var resource = require('resource'); 3 | var http = require('resource-http'); 4 | 5 | require('colors'); 6 | 7 | mesh.connect({ 8 | port: 7777, 9 | name: "test-client", 10 | user: "marak", 11 | password: "password" 12 | }, function(err){ 13 | 14 | if (err) { 15 | console.log('error connecting to mesh server. most likely the server is not running.', err); 16 | process.exit(); 17 | } 18 | 19 | setInterval(function(){ 20 | mesh.emitter.emit('client-foo', { bar: "foo" }); 21 | }, 2000); 22 | 23 | mesh.emitter.on("server-foo", function(data){ 24 | console.log('got server-foo event'.green, data); 25 | }); 26 | 27 | mesh.emitter.on("server-echo-client-foo", function(data){ 28 | console.log('got server-echo-client-foo event'.green, data); 29 | }); 30 | 31 | }); -------------------------------------------------------------------------------- /test/client-server-test.js: -------------------------------------------------------------------------------- 1 | var tap = require('tap'), 2 | test = tap.test, 3 | resource = require('resource'), 4 | http = require('resource-http'), 5 | Mesh = require('../lib/Mesh'), 6 | server, 7 | client; 8 | 9 | test("create server", function (t) { 10 | 11 | server = new Mesh(); 12 | 13 | server.listen({ port: 8888 }, function (err){ 14 | t.equal(null, err); 15 | t.end(); 16 | }); 17 | 18 | }); 19 | 20 | test("create client", function (t) { 21 | 22 | t.plan(3); 23 | client = new Mesh(); 24 | 25 | server.emitter.on('hello', function(){ 26 | console.log('!!hello called') 27 | t.ok(true); 28 | }); 29 | 30 | client.connect({ port: 8888 }, function(err){ 31 | t.equal(null, err); 32 | t.ok(true); 33 | client.emitter.emit('hello'); 34 | }); 35 | 36 | }); 37 | 38 | test("end tests", function (t) { 39 | process.exit(0); 40 | }); -------------------------------------------------------------------------------- /examples/0_basic/client.js: -------------------------------------------------------------------------------- 1 | var mesh = require('../../'); 2 | var resource = require('resource'); 3 | var creature = resource.define('creature'); 4 | 5 | require('colors') 6 | /* 7 | creature.method('talk', function(options, cb){ 8 | console.log('creature talked', options.text.green) 9 | cb(null, options.text); 10 | }); 11 | */ 12 | 13 | mesh.connect({ port: 7777, name: "test-client" }, function(err){ 14 | 15 | if (err) { 16 | console.log('error connecting to mesh server. most likely the server is not running.', err); 17 | process.exit(); 18 | } 19 | 20 | setInterval(function(){ 21 | mesh.emitter.emit('client-foo'); 22 | }, 2000); 23 | 24 | mesh.emitter.on("server-foo", function(data){ 25 | console.log('got server-foo event'.green, data); 26 | }) 27 | 28 | mesh.emitter.on("server-echo-client-foo", function(data){ 29 | console.log('got server-echo-client-foo event'.green, data); 30 | }) 31 | 32 | }); 33 | -------------------------------------------------------------------------------- /test/server-client-test.js: -------------------------------------------------------------------------------- 1 | var tap = require('tap'), 2 | test = tap.test, 3 | resource = require('resource'), 4 | http = require('resource-http'), 5 | Mesh = require('../lib/Mesh'), 6 | server, 7 | client; 8 | 9 | test("create server", function (t) { 10 | 11 | server = new Mesh(); 12 | 13 | server.listen({ port: 8888 }, function(err){ 14 | t.equal(null, err); 15 | t.end(); 16 | }); 17 | 18 | }); 19 | 20 | test("create client", function (t) { 21 | 22 | t.plan(3); 23 | client = new Mesh(); 24 | 25 | client.emitter.on('hello', function(){ 26 | console.log('!!hello called') 27 | t.ok(true); 28 | }); 29 | 30 | client.connect({ port: 8888 }, function(err) { 31 | t.equal(null, err); 32 | t.ok(true); 33 | 34 | setTimeout(function(){ 35 | server.emitter.emit('hello'); 36 | }, 500); 37 | }); 38 | 39 | }); 40 | 41 | test("end tests", function (t) { 42 | process.exit(0); 43 | }); -------------------------------------------------------------------------------- /examples/2_authorization/server.js: -------------------------------------------------------------------------------- 1 | var resource = require('resource'), 2 | http = require('resource-http'), 3 | mesh = require('../../').mesh; 4 | 5 | require('colors'); 6 | 7 | // 8 | // Generic authorize method 9 | // This can replaced with any custom auth function 10 | // 11 | function authorize (user, password, callback) { 12 | var result = false; 13 | if (user === "marak" && password === "password") { 14 | result = true; 15 | } 16 | callback(null, result); 17 | } 18 | 19 | mesh.listen({ 20 | port: 7777, 21 | auth: authorize 22 | }, function (err){ 23 | 24 | if (err) { 25 | throw err; 26 | } 27 | 28 | mesh.emitter.on('client-foo', function (data){ 29 | mesh.emitter.emit('server-echo-client-foo', data); 30 | }); 31 | 32 | setInterval(function(){ 33 | console.log('emitting server-foo message to mesh.emitter'.blue) 34 | mesh.emitter.emit('server-foo', { bar: "foo" }); 35 | }, 2000); 36 | 37 | }); 38 | 39 | -------------------------------------------------------------------------------- /test/siblings-test.js: -------------------------------------------------------------------------------- 1 | var tap = require('tap'), 2 | test = tap.test, 3 | resource = require('resource'), 4 | http = require('resource-http'), 5 | Mesh = require('../lib/Mesh'), 6 | server, 7 | client1, 8 | client2; 9 | 10 | test("create server", function (t) { 11 | 12 | server = new Mesh(); 13 | 14 | server.listen({ port: 8888 }, function(err){ 15 | t.equal(null, err); 16 | t.end(); 17 | }); 18 | 19 | }); 20 | 21 | test("create client 1", function (t) { 22 | 23 | client1 = new Mesh(); 24 | 25 | client1.connect({ port: 8888 }, function(err){ 26 | t.equal(null, err); 27 | t.end(); 28 | }); 29 | 30 | }); 31 | 32 | test("create client 2", function (t) { 33 | 34 | client2 = new Mesh(); 35 | 36 | client2.connect({ port: 8888 }, function(err){ 37 | t.equal(null, err); 38 | t.end(); 39 | }); 40 | 41 | }); 42 | 43 | test("add an event to client 1 emit that event from client 2", function (t) { 44 | 45 | client1.emitter.on('hello', function(){ 46 | console.log('client- hello called') 47 | t.ok(true) 48 | t.end(); 49 | }); 50 | 51 | setTimeout(function(){ 52 | client2.emitter.emit('hello', 'there'); 53 | }, 100) 54 | 55 | }); 56 | 57 | 58 | test("end tests", function (t) { 59 | process.exit(0); 60 | }); 61 | 62 | -------------------------------------------------------------------------------- /lib/server/listen.js: -------------------------------------------------------------------------------- 1 | var debug = require('debug')('resource::mesh') 2 | 3 | module['exports'] = function listen (options, callback) { 4 | 5 | debug('Attempting to create new server node'); 6 | 7 | var mesh = this, 8 | http = require('resource-http'), 9 | engine = require('engine.io'); 10 | 11 | if (typeof http.app === 'object') { 12 | attach(http.app); 13 | } 14 | else { 15 | options.root = options.root || __dirname + "/public"; 16 | // 17 | // Remark: resource-http autoport must be set to false or resource-mesh autonode funtionality will not work 18 | // 19 | options.autoport = false; 20 | http.listen(options, function (err, app) { 21 | if (err) { 22 | return callback(err); 23 | } 24 | debug('Node is going into server mode.'); 25 | debug('Created websocket gateway at ' + options.host + ":" + options.port); 26 | mesh.mode = "server"; 27 | attach(app); 28 | }); 29 | } 30 | 31 | function attach(app) { 32 | // 33 | // Remark: mesh.server is the same as http.server 34 | // 35 | mesh.server = engine.attach(app.server); 36 | 37 | mesh.server.on('connection', function(socket){ 38 | options.socket = socket; 39 | mesh.downlink(options, function(err, result){ 40 | if (err) { 41 | throw err; 42 | } 43 | }); 44 | }); 45 | 46 | callback(null, mesh.server); 47 | } 48 | return mesh; 49 | }; -------------------------------------------------------------------------------- /lib/server/public/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 10 | 11 | 12 |You have reached the generic webpage for the mesh's WebSocket Gateway. You can connect to this url using a WebSocket client.
15 | 16 |For additional documentation visit: http://github.com/bigcompany/mesh 17 | 18 |
20 |
21 |
22 |
23 |
42 |
43 |