` and the use of `MakeWeak` method through `node-weak`. Since node core doesn't have access to WeakMaps yet it's somewhat cumbersome to use them.
90 |
91 | Apart from these minor technical issues, using remote callbacks is not a great design choice for distributed applications. In the real world actors will crash and message confirmations may get lost ( even though the event was received and fired on the receiving node ). It is generally a better design choice to stick with an event emitter pattern with no built in confirmations. This same functionality of a remote callback can be achieved using two separate named events and a unique message identifier.
92 |
93 |
94 |
95 | ## Tests
96 |
97 | ```bash
98 | npm test
99 | ```
100 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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/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/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 | });
--------------------------------------------------------------------------------
/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/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/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 | });
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 | });
--------------------------------------------------------------------------------
/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;
--------------------------------------------------------------------------------
/lib/Mesh.js:
--------------------------------------------------------------------------------
1 | var EventEmitter = require('eventemitter2').EventEmitter2;
2 |
3 | var resource = require('resource');
4 |
5 | // class for constructing new Mesh instances
6 | function Mesh (opts) {
7 |
8 | var self = this;
9 |
10 | opts = opts || {};
11 |
12 | self.port = opts.port || 8888;
13 | self.host = opts.host || "localhost";
14 |
15 | self.mode = "unknown";
16 | self.autoheal = false;
17 |
18 | self.eventTable = {};
19 | //
20 | // Any events emitted on this eventEmitter will be broadcast to the mesh
21 | // by listeners added by the uplink and downlink methods
22 | //
23 | self.emitter = new EventEmitter({
24 | wildcard: true,
25 | delimiter: '::',
26 | maxListeners: 0,
27 | newListener: true
28 | });
29 |
30 | // Whenever a new listener is added to the mesh.emitter
31 | // add that new event to the resource eventTable namedspaced under "mesh::*"
32 | //
33 | // Remark: mesh.emitter events are considered remote by default
34 | // This means that these events will be available to remote sources unless,
35 | // unless remote property is set to `false`
36 | //
37 | // This is special behavior which only applies to the mesh.emitter.
38 | // All other resource event emitters will add events as NOT remote by default
39 | // see: https://github.com/bigcompany/resource
40 | //
41 | //
42 | self.emitter.on('newListener', function(ev){
43 | resource.eventTable["mesh::" + ev] = {
44 | remote: true
45 | };
46 | self.eventTable[ev] = {};
47 | //
48 | // Everytime the client adds a new mesh event listener,
49 | // resend a handshake containing the updated eventTable
50 | //
51 | if (self.mode === "client") {
52 | self.emitter.emit('handshake');
53 | }
54 | });
55 |
56 | };
57 |
58 | Mesh.prototype.connect = require('./client/connect');
59 | Mesh.prototype.listen = require('./server/listen');
60 |
61 | Mesh.prototype.uplink = require('./client/uplink');
62 | Mesh.prototype.downlink = require('./server/downlink');
63 |
64 | Mesh.prototype.start = require('./server/start');
65 |
66 | module['exports'] = Mesh;
--------------------------------------------------------------------------------
/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;
--------------------------------------------------------------------------------
/lib/browser/shimMesh.js:
--------------------------------------------------------------------------------
1 | var EventEmitter = require('eventemitter2').EventEmitter2;
2 |
3 | var resource = require('resource');
4 |
5 | // class for constructing new Mesh instances
6 | function Mesh (opts) {
7 |
8 | var self = this;
9 |
10 | opts = opts || {};
11 |
12 | self.port = opts.port || 8888;
13 | self.host = opts.host || "localhost";
14 |
15 | self.mode = "unknown";
16 | self.autoheal = false;
17 |
18 | self.eventTable = {};
19 | //
20 | // Any events emitted on this eventEmitter will be broadcast to the mesh
21 | // by listeners added by the uplink and downlink methods
22 | //
23 | self.emitter = new EventEmitter({
24 | wildcard: true,
25 | delimiter: '::',
26 | maxListeners: 0,
27 | newListener: true
28 | });
29 |
30 | // Whenever a new listener is added to the mesh.emitter
31 | // add that new event to the resource eventTable namedspaced under "mesh::*"
32 | //
33 | // Remark: mesh.emitter events are considered remote by default
34 | // This means that these events will be available to remote sources unless,
35 | // unless remote property is set to `false`
36 | //
37 | // This is special behavior which only applies to the mesh.emitter.
38 | // All other resource event emitters will add events as NOT remote by default
39 | // see: https://github.com/bigcompany/resource
40 | //
41 | //
42 | self.emitter.on('newListener', function(ev){
43 | resource.eventTable["mesh::" + ev] = {
44 | remote: true
45 | };
46 | self.eventTable[ev] = {};
47 | });
48 |
49 | };
50 |
51 | Mesh.prototype.connect = require('../client/connect');
52 | Mesh.prototype.uplink = require('../client/uplink');
53 | Mesh.prototype.start = require('../client/connect');
54 |
55 | module['exports'] = Mesh;
--------------------------------------------------------------------------------
/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/client/uplink.js:
--------------------------------------------------------------------------------
1 | module['exports'] = function uplink (options, callback) {
2 | var mesh = this;
3 | var resource = require('resource');
4 | var handler = function (data, broadcast) {
5 | data = data || {};
6 |
7 | //
8 | // This event was recieved from a remote source, do not rebroadcast it
9 | //
10 | if (broadcast === false){
11 | return;
12 | }
13 |
14 | mesh.client.send(JSON.stringify({
15 | event: this.event,
16 | payload: data,
17 | eventTable: resource.eventTable,
18 | headers: {
19 | "auth": {
20 | user: options.user,
21 | password: options.password
22 | }
23 | }
24 | }), function(data){
25 | // console.log('client send callback', data)
26 | });
27 | };
28 |
29 | mesh.emitter.onAny(handler);
30 |
31 | // Emit a handshake after connection to communicate the client's eventTable
32 | // Remark: It is possible that the server might try to send an event to a client which
33 | // should be eligible to recieve an event but has not yet broadcasted its eventTable with the handshake.
34 | // This will cause the client to not recieve the event.
35 | //
36 | mesh.emitter.emit('handshake');
37 |
38 | //
39 | // Any mesh client events should be rebroadcasted locally,
40 | // but they should not be re-emitted
41 | //
42 | mesh.client.on('message', function(data){
43 | var msg = JSON.parse(data);
44 |
45 | //
46 | // Emit the event on resource scope
47 | //
48 | resource.emit(msg.event, msg.payload);
49 |
50 | //
51 | // Emit event on mesh.emitter scope with rebroadcast set to false
52 | // This will trigger the event for locale listeners, but not broadcast the event back to the mes
53 | //
54 | mesh.emitter.emit(msg.event, msg.payload, false)
55 | })
56 |
57 | mesh.client.on('error', function(err) {
58 | console.log('error with client', err)
59 | // mesh.emitter.removeListener(handler);
60 | });
61 |
62 | mesh.client.on('close', function() {
63 |
64 | // TODO: add autoheal logic
65 | // server has been lost, attempt to heal the network
66 | // we could add reconnect logic here so client attempts to reconnect a few times before assuming total server failure
67 | if(mesh.autoheal && mesh.rank === 0) {
68 | mesh.listen(options, function(){});
69 | } else {
70 | mesh.connect(options, function(){})
71 | }
72 | // mesh.emitter.removeListener(handler);
73 | });
74 |
75 | //
76 | // Continue with information about the newly connected to node
77 | //
78 | callback(null, {
79 | id: options.host + ":" + options.port,
80 | port: options.port,
81 | host: options.host,
82 | status: "connected",
83 | lastSeen: new Date().toString(),
84 | role: "server",
85 | eventTable: resource.eventTable
86 | });
87 |
88 | };
--------------------------------------------------------------------------------
/lib/server/downlink.js:
--------------------------------------------------------------------------------
1 | var debug = require('debug')('resource::mesh')
2 |
3 | module['exports'] = function downlink (options, callback) {
4 |
5 | debug('new connection recieved', options.socket.id);
6 |
7 | var http = require('resource-http'),
8 | resource = require('resource');
9 |
10 | var mesh = this;
11 | mesh.mode = "server";
12 |
13 | mesh.clients = mesh.clients || {};
14 | mesh.clientCount = Object.keys(mesh.clients);
15 |
16 | var socket = options.socket;
17 | var handler = function (data, broadcast) {
18 | if (typeof broadcast === "undefined") {
19 | broadcast = true;
20 | }
21 | var self = this,
22 | parts = self.event.split('::'),
23 | ev;
24 | if (parts.length === 2) {
25 | ev = self.event
26 | } else {
27 | ev = "mesh::" + self.event;
28 | }
29 |
30 | function broadcastToClients() {
31 | for (var client in mesh.server.clients) {
32 | // Do not rebroadcast the message back to the client which sent it
33 | if (data && mesh.server.clients[client].id === data.id) {
34 | continue;
35 | }
36 | if (broadcast !== false) {
37 | if (mesh.server.clients // any clients are still connected to the server
38 | && mesh.server.clients[client] // and this client is still connected
39 | && mesh.server.clients[client].eventTable // and this client has a registerd eventTable
40 | && typeof mesh.server.clients[client].eventTable[ev] === "object" // and the recieved event is defined in the client's eventTable
41 | && mesh.server.clients[client].eventTable[ev].remote !== false) { // and that event is set to `remote`
42 | if(socket.id === client) {
43 | mesh.server.clients[client].send(JSON.stringify({
44 | event: self.event,
45 | payload: data
46 | }));
47 | } else {
48 | }
49 | } else {
50 | // console.log('refusing to send event ' + ev + ' to client, it is not registered', broadcast)
51 | }
52 | }
53 | }
54 | }
55 | broadcastToClients();
56 | };
57 |
58 | mesh.emitter.onAny(handler);
59 |
60 | socket.on('message', function(data){
61 | var msg = JSON.parse(data);
62 | msg.payload.id = socket.id;
63 | // If incoming message has an eventTable, assumes its an updated event table for that client
64 | // and update the server's definition of that client's eventTable
65 | if (typeof msg.eventTable === "object") {
66 | mesh.server.clients[socket.id].eventTable = msg.eventTable;
67 | }
68 | // TODO: better handling of handshake event. copy cached client headers back into message,
69 | // so that headers like username and password don't have to be sent in every message for authorization
70 | /*
71 | if (msg.event === "handshake") {
72 | mesh.server.clients[socket.id].eventTable = msg.payload.eventTable;
73 | }
74 | */
75 |
76 | // Check if there is an authorize method provided in server options
77 | // If so, don't broadcast any recieved events if authorization fails
78 | if (options.auth) {
79 | options.auth(msg.headers.auth.user, msg.headers.auth.password, function(err, success){
80 | if(success) {
81 | _emit();
82 | } else {
83 | // do nothing, bad auth
84 | }
85 | })
86 | } else {
87 | _emit();
88 | }
89 |
90 | //
91 | // All incoming messages from the mesh should be broadcasted as local event
92 | // unless the event is not registered in the local eventTable and set to `remote`
93 | //
94 | function _emit () {
95 | // Determine if broadcasted message is enabled as remote resource method locally
96 | var ev = msg.event;
97 |
98 | var parts = ev.split('::'),
99 | ev;
100 |
101 | if (parts.length === 2) {
102 | ev = ev;
103 | } else {
104 | ev = "mesh::" + ev;
105 | }
106 |
107 | if (typeof resource.eventTable[ev] === "object"
108 | && resource.eventTable[ev].remote !== false) {
109 | // if so, emit it
110 | var parts = msg.event.split("::");
111 | if (parts.length == 2) {
112 | // if the message looks like `creature::talk`, emit it to the resource library emitter
113 | resource.emit(msg.event, msg.payload);
114 | } else {
115 | // if the message is like `talk` emit it to the mesh resource emitter
116 | mesh.emitter.emit(msg.event, msg.payload);
117 | }
118 | } else {
119 | mesh.emitter.emit(msg.event, msg.payload);
120 | }
121 | }
122 |
123 | });
124 |
125 | socket.on('disconnect', function(data){
126 | // TODO: do something with this event
127 | // mesh.emitter.removeListener(handler);
128 | });
129 |
130 | //
131 | // Continue with information about the client
132 | //
133 | callback(null, {
134 | id: socket.id,
135 | lastSeen: new Date().toString(),
136 | role: "client",
137 | status: "connected",
138 | eventTable: resource.eventTable
139 | });
140 |
141 | };
--------------------------------------------------------------------------------
/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 | Mesh WebSocket Gateway
13 |
14 | 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 |
Live Example code
19 |
20 |
21 |
22 |
23 |
42 |
43 | Send a hello message
44 | Hello:
45 |
46 |
47 | Mesh Activity
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/lib/server/public/jquery.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigcompany/mesh/c31051a799858c4d7a7281ae2a3fd8c6b7d8e20a/lib/server/public/jquery.js
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/test/basic-tests.js:
--------------------------------------------------------------------------------
1 | var spawn = require('child_process').spawn,
2 | tap = require('tap'),
3 | test = tap.test,
4 | resource = require('resource'),
5 | http = require('resource-http'),
6 | Mesh = require('../lib/Mesh'),
7 | server,
8 | client;
9 |
10 | test("create server", function (t) {
11 |
12 | server = new Mesh();
13 |
14 | server.emitter.on('client-foo', function (data){
15 | console.log('server got client-foo', data);
16 | server.emitter.emit('server-echo-client-foo', data);
17 | });
18 |
19 | setInterval(function(){
20 | server.emitter.emit('server-foo', { bar: "foo" });
21 | }, 100);
22 |
23 |
24 | server.listen({ port: 8888 }, function(err){
25 | t.equal(null, err);
26 | t.end();
27 | });
28 |
29 | });
30 |
31 | test("create client", function (t) {
32 |
33 | client = new Mesh();
34 | client.connect({ port: 8888 }, function(err){
35 | t.equal(null, err);
36 | t.end();
37 | });
38 |
39 | setInterval(function(){
40 | client.emitter.emit('client-foo', { bar: "foo" });
41 | }, 100);
42 |
43 | client.emitter.on("server-foo", function(data){
44 | console.log('got server-foo event'.green, data);
45 | })
46 |
47 | client.emitter.on("server-echo-client-foo", function(data){
48 | console.log('got server-echo-client-foo event'.green, data);
49 | })
50 |
51 | });
52 |
53 | test("server can recieve single event from client", function (t) {
54 |
55 | t.plan(1);
56 |
57 | server.emitter.once('client-foo', function (data){
58 | t.ok(true, 'server got client-foo message');
59 | });
60 | /*
61 | client.emitter.once('server-echo-client-foo', function (data) {
62 | t.equal(data.bar, 'foo', 'received server echo');
63 | });
64 |
65 | client.emitter.once('server-foo', function (data) {
66 | t.equal(data.bar, 'foo', 'received server message');
67 | });
68 | */
69 |
70 | });
71 |
72 |
73 |
74 | test("client can recieve an event from server", function (t) {
75 |
76 | t.plan(1);
77 |
78 | client.emitter.once('server-foo', function (data) {
79 | t.equal(data.bar, 'foo', 'received server message');
80 | });
81 |
82 | /*
83 | client.emitter.once('server-echo-client-foo', function (data) {
84 | t.equal(data.bar, 'foo', 'received server echo');
85 | });
86 |
87 | */
88 |
89 | });
90 |
91 |
92 | /*
93 |
94 | test("client send an event and recieve a reply from server", function (t) {
95 |
96 | t.plan(1);
97 |
98 | client.emitter.on('server-echo-client-foo', function (data) {
99 | t.equal(data.bar, 'foo', 'received server echo');
100 | });
101 |
102 | });
103 |
104 | */
105 |
106 | test("end tests", function (t) {
107 | process.exit(0);
108 | });
--------------------------------------------------------------------------------
/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 | });
--------------------------------------------------------------------------------
/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 | });
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------