diff --git a/.travis.yml b/.travis.yml index f1d0f13..2d26206 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,3 @@ language: node_js node_js: - - 0.4 - 0.6 diff --git a/README.markdown b/README.markdown index 51959fe..174bd97 100644 --- a/README.markdown +++ b/README.markdown @@ -3,293 +3,292 @@ dnode  -DNode is an asynchronous object-oriented RPC system for node.js that lets you +dnode is an asynchronous rpc system for node.js that lets you call remote functions. -[](http://travis-ci.org/substack/dnode) +You can pass callbacks to remote functions, and the remote end can call +the functions you passed in with callbacks of its own and so on. +It's callbacks all the way down! -It works over network sockets and even in the browser with -[socket.io](https://github.com/LearnBoost/Socket.IO). +[](http://travis-ci.org/substack/dnode) -Plus, there are dnode implementations for -[perl](http://github.com/substack/dnode-perl), -[ruby](http://github.com/substack/dnode-ruby), -[php](https://github.com/bergie/dnode-php), -and -[java](https://github.com/aslakhellesoy/dnode-java), -so you can glue -together all your backend processes. +example +======= -dnode between two node.js processes ------------------------------------ +listen and connect +------------------ -Just write a server.js: +server: -```javascript +``` js var dnode = require('dnode'); - var server = dnode({ - zing : function (n, cb) { cb(n * 100) } + transform : function (s, cb) { + cb(s.replace(/[aeiou]{2,}/, 'oo').toUpperCase()) + } }); -server.listen(5050); -```` - -Run it... - - $ node server.js +server.listen(5004); +``` -Then you can whip up a client.js that calls the server's `zing` function! +client: -```javascript +``` js var dnode = require('dnode'); -dnode.connect(5050, function (remote) { - remote.zing(66, function (n) { - console.log('n = ' + n); +var d = dnode.connect(5004); +d.on('remote', function (remote) { + remote.transform('beep', function (s) { + console.log('beep => ' + s); + d.end(); }); }); -```` +``` -*** +output: - $ node client.js - n = 6600 - ^C +``` +$ node server.js & +[1] 27574 +$ node client.js +beep => BOOP +``` -dnode on the browser --------------------- - -We can retrofit the previous example to run in the browser. - -Just write a server.js: +streaming +--------- -````javascript -var express = require('express'); -var app = express.createServer(); -app.use(express.static(__dirname)); +The `.connect()` and `.listen()` calls in the previous example are just +convenience methods for piping to and from readable/writable streams. +Here's the previous example with the streams set up explicitly: -app.listen(8080); -console.log('http://localhost:8080/'); - -// then just pass the server app handle to .listen()! +server: +``` js var dnode = require('dnode'); -var server = dnode({ - zing : function (n, cb) { cb(n * 100) } -}); -server.listen(app); -```` - -and whip up an index.html: - -````html - -
- - - - +var net = require('net'); -n = ? +var server = net.createServer(function (c) { + var d = dnode({ + transform : function (s, cb) { + cb(s.replace(/[aeiou]{2,}/, 'oo').toUpperCase()) + } + }); + c.pipe(d).pipe(c); +}); - - -```` +server.listen(5004); +``` -then just run the server.js: +client: - $ node server.js - http://localhost:8080/ +``` js +var dnode = require('dnode'); +var net = require('net'); -and navigate to http://localhost:8080: +var d = dnode(); +d.on('remote', function (remote) { + remote.transform('beep', function (s) { + console.log('beep => ' + s); + d.end(); + }); +}); - +var c = net.connect(5004); +c.pipe(d).pipe(c); +``` -Awesome it works! +output: -The dnode browser source automatically gets hosted at `/dnode.js` and it also -works with -[browserify](https://github.com/substack/node-browserify) -[out of the box](https://github.com/substack/dnode/tree/master/examples/web-browserify). +``` +$ node server.js & +[1] 27586 +$ node client.js +beep => BOOP +``` -how it works ------------- +dnode in the browser +-------------------- -When you throw an object at dnode, a recursive traversal scrubs out all of the -`function` objects nested in your data structure and a secondary data structure -is sent along with remote requests that creates shim functions that create RPC -calls back to the side where the functions were originally defined. +Since dnode instances are just readable/writable streams, you can use them with +any streaming transport, including in the browser! -When you call a remote function, the same recursive traversal trick happens to -the arguments you pass along, so you can pass callbacks to your remote functions -that actually call you back over the wire when the remote side calls the shim -function on the other end. +This example uses the streaming interface provided by +[shoe](https://github.com/substack/shoe), which is just a thin wrapper on top of +[sockjs](http://sockjs.org/) that provides websockets with fallbacks. -Basically, dnode lets you call remote functions as if they were defined locally -without using `eval()` or `Function.prototype.toString()`. Awesome! +First whip up a server: -The only catch is that because the function calls are traveling down the -high-latency network, the return values of your functions are ignored. Use -[continuation-passing -style](http://en.wikipedia.org/wiki/Continuation-passing_style) instead! +``` js +var http = require('http'); +var shoe = require('shoe'); +var ecstatic = require('ecstatic')(__dirname + '/static'); +var dnode = require('dnode'); -More features: +var server = http.createServer(ecstatic); +server.listen(9999); -* symmetric design: both sides of the connection can host up methods for the - other side to call +var sock = shoe(function (stream) { + var d = dnode({ + transform : function (s, cb) { + var res = s.replace(/[aeiou]{2,}/, 'oo').toUpperCase(); + cb(res); + } + }); + d.pipe(stream).pipe(d); +}); +sock.install(server, '/dnode'); +``` -* use TCP streams, UNIX domain sockets, or websockets courtesy of socket.io! - (see below, just throw a webserver at `listen()`) +Then write some browser code: -methods -======= +``` js +var domready = require('domready'); +var shoe = require('shoe'); +var dnode = require('dnode'); -dnode(wrapper) --------------- +domready(function () { + var result = document.getElementById('result'); + var stream = shoe('/dnode'); + + var d = dnode(); + d.on('remote', function (remote) { + remote.transform('beep', function (s) { + result.textContent = 'beep => ' + s; + }); + }); + d.pipe(stream).pipe(d); +}); +``` -If `wrapper` is an object, serve this object up to the other side every time. +Install the dependencies for this example then compile the browser code with +[browserify](https://github.com/substack/node-browserify): -If `wrapper` is a function, use it to build a new object for each new client. -The result of `new wrapper(remote, conn)` will be used, where `remote` is an -empty object that will be filled with the other side's methods once the initial -protocol phase finishes and where `conn` is the connection object. +``` +$ npm install dnode shoe domready ecstatic +$ npm install -g browserify +$ browserify client.js -o static/bundle.js +``` -Both client and server can call `dnode()` with a wrapper. -`dnode.connect()` and `dnode.listen()` are shortcut that set `wrapper` to `{}`. +Now drop a script tag into static/index.html: -.connect(...) -------------- +``` html + + +``` -Connect to a remote dnode service. Pass in a port, host, UNIX domain socket -path, block, or options object in any order. The block function if present will -be executed with the remote object and the connection object once the remote -object is ready. +and navigate to http://localhost:9999. +You should see `beep => BOOP` on the page! -You can reconnect when the connection is refused or drops by passing in a -`reconnect` option as the number of milliseconds to wait between reconnection -attempts. +Check out the +[complete shoe example](https://github.com/substack/dnode/tree/master/example/shoe). -Returns `this` so you can chain multiple connections. +methods +======= -.listen(...) ------------- +``` js +var dnode = require('dnode') +``` -Listen for incoming dnode clients. Pass in a port, host, UNIX domain socket -path, block, or options object in any order. The block function if present will -be executed with the remote object and the connection object once the remote -object is ready for each client. +var d = dnode(cons, opts={}) +---------------------------- -If you pass a webserver (http.Server, https.Server, connect, express) to -listen(), socket.io will be bound to the webserver and the dnode browser source -will be hosted at `options.mount || "/dnode.js"`. +Create a new readable/writable dnode stream object `d`. +All the usual stream methods are at your disposal: pipe(), write(), end(). -You can pass options through to socket.io with the `io` parameter: +If `cons` is a function, it will be called `new cons(remote, d)` to create a new +instance object. Otherwise its value will be used directly. When `cons` is +called as a function, the `remote` ref will be an empty unpopulated object. -````javascript -dnode(...).listen(webserver, { io : { flashPolicyServer : false } }); -```` +By default, dnode uses weakmaps to garbage collect unused callbacks +automatically. This behavior prevents memory leaks in long-running connections. -Returns `this` so you can chain multiple listeners. +You can turn weakmaps off by setting `opts.weak = false`. -.use(middleware) ----------------- +d.connect(...) +-------------- -You can write your own dnode middleware with `.use()`. The `middleware` function -you pass will be called just like the constructor function that `dnode()` takes. -You can modify `this`, `remote`, and `conn` objects after the instance computed -with the `dnode()` constructor executes but before the methods are sent over the -wire. +This method is a shortcut for setting up a pipe between `d` and a new +`net.connect()` stream. -Returns `this` so you can chain middlewares. +The host, port, and callback arguments supplied will be inferred by their +types. -the connection object -===================== +If you pass a callback in as an argument, it will be added as a listener to the +`'remote'` event. -When you pass a constructor function to `dnode()` you'll get a connection -object as the second argument to your constructor. +Returns the `d` object. -The connection object (`conn`) is an EventEmitter. +dnode.connect(...) +------------------ -* conn.id is a random hex string that uniquely identifies clients +Shortcut to create a connection without a constructor. -* conn.end() closes the connection and won't reconnect +d.listen(...) +------------- -* conn emits 'ready' when the remote object has been fully populated from - the methods exchange +This method is a shortcut for setting up a `net.createServer()` and piping +network streams to and from new dnode streams. -* conn emits 'remote' at the same time as 'ready', except with the remote object - as an argument +The host, port, and callback parameters will be inferred from the types of the +arguments. -* conn emits 'end' when the connection drops +Returns a net server object that will also emit `'local'` and `'remote'` events +from the underlying dnode streams.. -* conn emits 'connect' when the connection is established +dnode.listen(...) +----------------- -* conn re-emits error events from the stream object +Shortcut to create a listener without a constructor. -* conn emits 'refused', 'drop', and 'reconnect' when reconnect is enabled +events +====== -more examples -------------- +d.on('remote', cb) +------------------ -Check out -[the examples directory](https://github.com/substack/dnode/tree/master/examples/) -of this distribution. +This event fires with `cb(remote, d)` when the remote side of the connection +has constructed its instance. -You'll find examples for using dnode with -[connect](https://github.com/SenchaLabs/connect), -[express](http://expressjs.com/), -[https](https://github.com/substack/dnode/tree/master/examples/https), -and authentication. +d.on('local', cb) +----------------- -There's a chat server too! +This event fires right after the constructed instance has been created locally +but before it gets sent to the remote end so you can modify the ref object. -installation -============ +This event fires with `cb(ref, d)` where `ref` is the local instance object. -Using [npm](http://npmjs.org): +d.on('fail', cb) +---------------- - npm install dnode +This event fires when the remote end causes errors in the protocol layer. -Or check out the repository and fetch the deps with npm, then build the bundle: +These are non-fatal and can probably be ignored but you could also terminate the +connection here. - git clone https://github.com/substack/dnode.git - cd dnode - npm install --dev - node bin/bundle.js +d.on('error', cb) +----------------- -The dnode dependencies are listed in the -[package.json](https://github.com/substack/dnode/tree/master/package.json). -If you install with npm they will be fetched automatically. +This event fires when local code causes errors in its callbacks. +Not all errors can be caught here since some might be in async functions. -read more -========= +d.on('end', cb) +--------------- -* [slides from my dnode talk at parisoma](http://substack.net/posts/9aabb1) +This event fires when the input stream finishes. -* [Roll your own PubSub with DNode](http://substack.net/posts/9bac3e/Roll-your-own-PubSub-with-DNode) - (Note: EventEmitters are no longer exported directly, use - [browserify](https://github.com/substack/node-browserify) to get them back) +install +======= -* [DNode: Asynchronous Remote Method Invocation for Node.js and the Browser](http://substack.net/posts/85e1bd/DNode-Asynchronous-Remote-Method-Invocation-for-Node-js-and-the-Browser) +With [npm](http://npmjs.org) do: -* [Simon Willison's Weblog](http://simonwillison.net/2010/Jul/11/dnode/) +``` +npm install dnode +``` protocol ======== -DNode uses a newline-terminated JSON protocol -[documented in the dnode-protocol -readme](https://github.com/substack/dnode-protocol). +dnode uses a newline-terminated JSON protocol +[documented in the dnode-protocol project](https://github.com/substack/dnode-protocol/blob/master/doc/protocol.markdown#the-protocol). dnode in other languages ======================== @@ -300,12 +299,9 @@ between scripts written in different languages. * [dnode-perl](http://github.com/substack/dnode-perl) * [dnode-ruby](http://github.com/substack/dnode-ruby) * [dnode-php](https://github.com/bergie/dnode-php) +* [dnode-php-sync-client](https://github.com/erasys/dnode-php-sync-client) * [dnode-java](https://github.com/aslakhellesoy/dnode-java) -There's a -[dnode-python](https://github.com/jesusabdullah/dnode-python) -in the works too but it's not finished yet. - shameless plug ============== @@ -313,6 +309,3 @@ Want to make sure your crazy javascript-heavy app still works in other browsers? Give [browserling](http://browserling.com) a spin! Browsers in your browser. Powered by dnode. - -[](http://travis-ci.org/substack/dnode) - diff --git a/bin/bundle.js b/bin/bundle.js deleted file mode 100755 index dbd90f5..0000000 --- a/bin/bundle.js +++ /dev/null @@ -1,21 +0,0 @@ -var fs = require('fs'); -var path = require('path'); -var browserify = require('browserify'); - -var src = browserify({ filter : require('uglify-js') }) - .require(__dirname + '/../browser/index.js') - .bundle() -; - -var buf = new Buffer('var DNode = (function () {' - + src + '; return require("/index.js")' -+ '})()'); - -var file = __dirname + '/../browser/bundle.js'; -fs.writeFile(file, buf, function (err) { - if (err) console.error('Error: ' + err) - else { - var bytes = buf.length; - console.log(bytes + ' bytes written'); - } -}); diff --git a/browser.js b/browser.js new file mode 100644 index 0000000..e0e5de7 --- /dev/null +++ b/browser.js @@ -0,0 +1,5 @@ +var dnode = require('./lib/dnode'); + +module.exports = function (cons, opts) { + return new dnode(cons, opts); +}; diff --git a/browser/index.js b/browser/index.js deleted file mode 100644 index 84cac3a..0000000 --- a/browser/index.js +++ /dev/null @@ -1,69 +0,0 @@ -var protocol = require('dnode-protocol'); -var EventEmitter = require('events').EventEmitter; -var io = require('socket.io-client'); -var json = typeof JSON === 'object' ? JSON : require('jsonify'); - -var exports = module.exports = dnode; - -function dnode (wrapper) { - if (!(this instanceof dnode)) return new dnode(wrapper); - this.proto = protocol(wrapper); - this.stack = []; - return this; -} - -dnode.prototype = new EventEmitter; - -dnode.prototype.use = function (middleware) { - this.stack.push(middleware); - return this; -}; - -dnode.prototype.connect = function () { - var self = this; - var params = protocol.parseArgs(arguments); - var client = self.proto.create(); - - var proto = (params.proto || window.location.protocol) - .replace(/:.*/, '') + '://'; - - var sock = client.socketio = io.connect( - proto + (params.host || window.location.host), - params - ); - - client.end = function () { - sock.disconnect(); - }; - - sock.on('connect', function () { - client.start(); - self.emit('connect'); - }); - - sock.on('disconnect', function () { - client.emit('end'); - self.emit('end'); - }); - - sock.on('message', client.parse); - - client.on('request', function (req) { - sock.send(json.stringify(req) + '\n'); - }); - - if (params.block) { - client.on('remote', function () { - params.block.call(client.instance, client.remote, client); - }); - } - - this.stack.forEach(function (middleware) { - middleware.call(client.instance, client.remote, client); - }); -}; - -exports.connect = function () { - var d = exports(); - return d.connect.apply(d, arguments); -}; diff --git a/example/auth/client.js b/example/auth/client.js new file mode 100644 index 0000000..5459a13 --- /dev/null +++ b/example/auth/client.js @@ -0,0 +1,24 @@ +var dnode = require('dnode'); + +if (process.argv.length < 4) { + return console.error('Usage: ./client.js user pass'); +} + +var user = process.argv[2]; +var pass = process.argv[3]; + +var d = dnode.connect(7007); +d.on('remote', function (remote) { + remote.auth(user, pass, function (err, session) { + if (err) { + console.error(err); + return d.end(); + } + + session.quote(function (q) { + console.log('And now for a quote by ' + q.who + ':\n'); + console.log(q.quote + '\n'); + d.end(); + }); + }); +}); diff --git a/examples/auth/quotes.json b/example/auth/quotes.json similarity index 100% rename from examples/auth/quotes.json rename to example/auth/quotes.json diff --git a/example/auth/server.js b/example/auth/server.js new file mode 100644 index 0000000..29b9891 --- /dev/null +++ b/example/auth/server.js @@ -0,0 +1,29 @@ +var dnode = require('dnode'); +var fs = require('fs'); +var net = require('net'); + +var secretQuotes = require('./quotes.json'); +function randomQuote (cb) { + var ix = Math.floor(Math.random() * secretQuotes.length); + cb(secretQuotes[ix]); +} + +var server = net.createServer(function (stream) { + var d = dnode({ auth : auth }); + d.pipe(stream).pipe(d); + + function auth (user, pass, cb) { + if (typeof cb !== 'function') return; + + if (user === 'moo' && pass === 'hax') { + console.log('signed in: ' + user); + d.on('end', function () { + console.log('disconnected: ' + user); + }); + + cb(null, { quote : randomQuote }); + } + else cb('ACCESS DENIED') + } +}); +server.listen(7007); diff --git a/example/shoe/Makefile b/example/shoe/Makefile new file mode 100644 index 0000000..103950e --- /dev/null +++ b/example/shoe/Makefile @@ -0,0 +1,2 @@ +all: + node_modules/.bin/browserify client.js -o static/bundle.js diff --git a/example/shoe/client.js b/example/shoe/client.js new file mode 100644 index 0000000..46d8296 --- /dev/null +++ b/example/shoe/client.js @@ -0,0 +1,16 @@ +var domready = require('domready'); +var shoe = require('shoe'); +var dnode = require('../../'); + +domready(function () { + var result = document.getElementById('result'); + var stream = shoe('/dnode'); + + var d = dnode(); + d.on('remote', function (remote) { + remote.transform('beep', function (s) { + result.textContent = 'beep => ' + s; + }); + }); + d.pipe(stream).pipe(d); +}); diff --git a/example/shoe/package.json b/example/shoe/package.json new file mode 100644 index 0000000..d7c44f2 --- /dev/null +++ b/example/shoe/package.json @@ -0,0 +1,11 @@ +{ + "name" : "dnode-shoe-example", + "version" : "0.0.0", + "dependencies" : { + "shoe" : "~0.0.0", + "ecstatic" : "~0.1.6", + "domready" : "~0.2.11", + "browserify" : "~1.12.3" + }, + "private" : true +} diff --git a/example/shoe/server.js b/example/shoe/server.js new file mode 100644 index 0000000..b415cfa --- /dev/null +++ b/example/shoe/server.js @@ -0,0 +1,18 @@ +var http = require('http'); +var shoe = require('shoe'); +var ecstatic = require('ecstatic')(__dirname + '/static'); +var dnode = require('../../'); + +var server = http.createServer(ecstatic); +server.listen(9999); + +var sock = shoe(function (stream) { + var d = dnode({ + transform : function (s, cb) { + var res = s.replace(/[aeiou]{2,}/, 'oo').toUpperCase(); + cb(res); + } + }); + d.pipe(stream).pipe(d); +}); +sock.install(server, '/dnode'); diff --git a/example/shoe/static/index.html b/example/shoe/static/index.html new file mode 100644 index 0000000..4ad0e26 --- /dev/null +++ b/example/shoe/static/index.html @@ -0,0 +1,2 @@ + + diff --git a/examples/simple/client.js b/example/simple/client.js similarity index 82% rename from examples/simple/client.js rename to example/simple/client.js index 193fe3a..c399fc2 100644 --- a/examples/simple/client.js +++ b/example/simple/client.js @@ -1,4 +1,4 @@ -var dnode = require('dnode'); +var dnode = require('../../'); dnode.connect(7070, function (remote, conn) { remote.zing(33, function (n) { diff --git a/examples/simple/server.js b/example/simple/server.js similarity index 79% rename from examples/simple/server.js rename to example/simple/server.js index 188afbb..60e8115 100644 --- a/examples/simple/server.js +++ b/example/simple/server.js @@ -1,4 +1,4 @@ -var dnode = require('dnode'); +var dnode = require('../../'); var server = dnode(function (remote, conn) { this.zing = function (n, cb) { cb(n * 100) }; diff --git a/example/stream/connect.js b/example/stream/connect.js new file mode 100644 index 0000000..79b6547 --- /dev/null +++ b/example/stream/connect.js @@ -0,0 +1,13 @@ +var dnode = require('../../'); +var net = require('net'); + +var d = dnode(); +d.on('remote', function (remote) { + remote.transform('beep', function (s) { + console.log('beep => ' + s); + d.end(); + }); +}); + +var c = net.connect(5004); +c.pipe(d).pipe(c); diff --git a/example/stream/listen.js b/example/stream/listen.js new file mode 100644 index 0000000..abedc66 --- /dev/null +++ b/example/stream/listen.js @@ -0,0 +1,13 @@ +var dnode = require('../../'); +var net = require('net'); + +var server = net.createServer(function (c) { + var d = dnode({ + transform : function (s, cb) { + cb(s.replace(/[aeiou]{2,}/, 'oo').toUpperCase()) + } + }); + c.pipe(d).pipe(c); +}); + +server.listen(5004); diff --git a/examples/auth/client.js b/examples/auth/client.js deleted file mode 100755 index ff51fdd..0000000 --- a/examples/auth/client.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node -// Connect to the auth server and display a quote from it. - -var DNode = require('dnode'); -var sys = require('sys'); - -if (process.argv.length < 4) { - sys.puts('Usage: ./client.js user pass'); - process.exit(); -} - -var user = process.argv[2]; -var pass = process.argv[3]; - -DNode.connect(7007, function (remote,conn) { - remote.authenticate(user, pass, function (session) { - if (session) { - sys.puts('Authentication success'); - session.quote(function (q) { - sys.puts('\nAnd now for a quote by ' + q.who + ':\n\n'); - sys.puts(q.quote + '\n\n'); - conn.end(); - }); - } - else { - sys.puts('Authentication failure'); - conn.end(); - } - }); -}); diff --git a/examples/auth/server.js b/examples/auth/server.js deleted file mode 100755 index a4ef38b..0000000 --- a/examples/auth/server.js +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env node -// Serve an object with authentication - -var DNode = require('dnode'); -var sys = require('sys'); -var fs = require('fs'); - -var quotes = JSON.parse( - fs.readFileSync(__dirname + '/quotes.json').toString() -); - -// Serve up a Session object only after the client supplies the valid user/pass -DNode(function (client, connection) { - this.authenticate = function (user, pass, cb) { - if (user == 'moo' && pass == 'hax') { - sys.puts('Sign in as ' + sys.inspect(user) + ' succeeded!'); - cb(new Session({ - user : user, - client : client, - connection : connection, - })); - } - else { - sys.puts('Sign in as ' + sys.inspect(user) + ' failed!'); - cb(null); - } - }; -}).listen(7007); - -// Clients who connect get an instance of this session object: -function Session (params) { - var conn = params.connection; - var user = params.user; - var client = params.client; - - conn.addListener('end', function () { - sys.puts('User ' + sys.inspect(user) + ' disconnected'); - }); - - this.quote = function (f) { - var i = Math.floor(Math.random() * quotes.length); - f(quotes[i]); - }; -} diff --git a/examples/bidirectional/client.js b/examples/bidirectional/client.js deleted file mode 100644 index 5efe66e..0000000 --- a/examples/bidirectional/client.js +++ /dev/null @@ -1,21 +0,0 @@ -var dnode = require('dnode'); - -var client = dnode({ - // Compute the client's temperature and stuff that value into the callback - - temperature : function (cb) { - var degC = Math.round(20 + Math.random() * 10 - 5); - console.log(degC + '° C'); - cb(degC); - } -}); - -client.connect(6060, function (remote, conn) { - // Call the server's conversion routine, which polls the client's - // temperature in celsius degrees and converts to fahrenheit - - remote.clientTempF(function (degF) { - console.log(degF + '° F'); - conn.end(); // all done! - }); -}); diff --git a/examples/bidirectional/server.js b/examples/bidirectional/server.js deleted file mode 100644 index 829c49f..0000000 --- a/examples/bidirectional/server.js +++ /dev/null @@ -1,12 +0,0 @@ -var dnode = require('dnode'); - -dnode(function (client) { - // Poll the client's own temperature() in celsius and convert that value to - // fahrenheit in the supplied callback - this.clientTempF = function (cb) { - client.temperature(function (degC) { - var degF = Math.round(degC * 9 / 5 + 32); - cb(degF); - }); - }; -}).listen(6060); diff --git a/examples/chat/INSTALL.txt b/examples/chat/INSTALL.txt deleted file mode 100644 index 159ee7d..0000000 --- a/examples/chat/INSTALL.txt +++ /dev/null @@ -1,4 +0,0 @@ -Do this first: - - mkdir node_modules - npm install jquery-browserify diff --git a/examples/chat/chat.css b/examples/chat/chat.css deleted file mode 100644 index c8e7bda..0000000 --- a/examples/chat/chat.css +++ /dev/null @@ -1,67 +0,0 @@ -div#prompt { - width: 600px; - height: 400px; - margin: auto; - display: table-cell; - vertical-align: middle; - text-align: center; - background-color: rgb(30,30,30); - color: white; -} - -div#chat { - width: 600px; - margin: auto; -} - -div#messages { - display: none; - overflow-x: hidden; - overflow-y: scroll; - padding: 0.5em; - width: 600px; - height: 400px; - border-color: black; - border-style: solid; - border-width: 2px; - background-color: rgb(30,30,30); -} - -form#post input { - width: 600px; - padding: 0.5em; - background-color: black; - color: white; - border-width: 0px; -} - -span.who { - font-weight: bold; - margin-right: 1em; - color: rgb(200,200,200); -} - -span.me { - font-weight: bold; - margin-right: 1em; - color: white; -} - -span.msg { - color: white; -} - -div.join { - color: rgb(200,250,150); - font-weight: bold; -} - -div.part { - color: rgb(250,200,150); - font-weight: bold; -} - -div.users { - color: rgb(150,200,250); - font-weight: bold; -} diff --git a/examples/chat/entry.js b/examples/chat/entry.js deleted file mode 100644 index a9c1e07..0000000 --- a/examples/chat/entry.js +++ /dev/null @@ -1,73 +0,0 @@ -var $ = require('jquery-browserify'); -var dnode = require('dnode'); - -$(document).ready(function () { - // Fetch the user's name before the main chat code fires - $('form#name').submit(function (ev) { - ev.preventDefault(); - var name = $('input[name="name"]').val(); - $('#messages').show(); - $('#prompt').hide(); - chat(name); - }); -}); - -function chat (name) { - // Connect to the chat server now that we've got a name - dnode(function () { - this.name = name; - - this.joined = function (who) { - addLine($('timesTen(10) == ?
-My name is ?.
diff --git a/examples/https/server.js b/examples/https/server.js deleted file mode 100755 index 055cf34..0000000 --- a/examples/https/server.js +++ /dev/null @@ -1,50 +0,0 @@ -var https = require('https'); -var fs = require('fs'); -var dnode = require('dnode'); - -try { - var opts = { - key : fs.readFileSync(__dirname + '/privatekey.pem'), - cert : fs.readFileSync(__dirname + '/certificate.pem'), - }; -} -catch (e) { - console.log('# {privatekey,certificate}.pem missing, do this first:'); - console.log('openssl genrsa -out privatekey.pem 1024'); - console.log('openssl req -new -key privatekey.pem -out certrequest.csr'); - console.log('openssl x509 -req -in certrequest.csr ' - + '-signkey privatekey.pem -out certificate.pem'); - process.exit(); -} - -var index = fs.readFileSync(__dirname + '/index.html'); -var server = https.createServer(opts, function (req, res) { - if (req.url === '/') { - res.writeHead(200, { 'Content-Type' : 'text/html' }); - res.end(index); - } - else if (!res.finished) { - process.nextTick(function () { - if (!res.finished) { - res.writeHead(404, { 'Content-Type' : 'text/html' }); - res.end('Not found!'); - } - }); - } -}); - -dnode(function (client) { - this.timesTen = function (n,f) { f(n * 10) }; - this.whoAmI = function (reply) { - client.name(function (name) { - reply(name - .replace(/Mr\.?/,'Mister') - .replace(/Ms\.?/,'Miss') - .replace(/Mrs\.?/,'Misses') - ); - }) - }; -}).listen(server); -server.listen(8020); - -console.log('https://localhost:8020/'); diff --git a/examples/nested.js b/examples/nested.js deleted file mode 100644 index 22f5b2e..0000000 --- a/examples/nested.js +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env node -var DNode = require('dnode'); -var sys = require('sys'); -var EventEmitter = require('events').EventEmitter; - -// server-side: -var server1 = DNode({ - timesTen : function (n,reply) { reply(n * 10) } -}).listen(6060); - -var server2 = DNode({ - timesTwenty : function (n,reply) { reply(n * 20) } -}).listen(6061); - -var moo = new EventEmitter; - -// client-side: -// Good thing this example is so contrived. Real code doesn't turn out this -// ugly very often on purpose. -server1.on('ready', function () { - server2.on('ready', function () { - DNode.connect(6060, function (remote1) { - DNode.connect(6061, function (remote2) { - moo.addListener('hi', function (x) { - remote1.timesTen(x, function (res) { - sys.puts(res); - remote2.timesTwenty(res, function (res2) { - sys.puts(res2); - }); - }); - }); - remote2.timesTwenty(5, function (n) { - sys.puts(n); // 100 - remote1.timesTen(0.1, function (n) { - sys.puts(n); // 1 - }); - }); - }); - }); - }); -}); - -setTimeout(function() { - moo.emit('hi', 100); -}, 500); - -setTimeout(function () { - // kill the service after a while - server1.end(); - server2.end(); -}, 1000); - -/* - Output: - 100 - 1 - ... after half a second ... - 1000 - 20000 -*/ - diff --git a/examples/perf/client.js b/examples/perf/client.js deleted file mode 100644 index 9898119..0000000 --- a/examples/perf/client.js +++ /dev/null @@ -1,15 +0,0 @@ -var frames = 0, last = 0; -setInterval(function () { - if (last) { - var fps = frames / (Date.now() - last) * 1000; - console.log('fps: ' + fps); - } - - last = Date.now(); - frames = 0; -}, 1000); - -var dnode = require('dnode'); -dnode({ - emit : function (i) { frames ++ } -}).connect(7575); diff --git a/examples/perf/emitter.js b/examples/perf/emitter.js deleted file mode 100644 index 4d716ab..0000000 --- a/examples/perf/emitter.js +++ /dev/null @@ -1,20 +0,0 @@ -var dnode = require('dnode'); -var EventEmitter = require('events').EventEmitter; - -var clients = {}; -setInterval(function () { - Object.keys(clients).forEach(function (id) { - var i = Math.floor(Math.random() * Math.pow(2,32)); - clients[id].emit(i); - }); -}, 1000 / 50); // 50 fps - -dnode(function (client, conn) { - conn.on('ready', function () { - clients[conn.id] = client; - }); - - conn.on('end', function () { - delete clients[conn.id]; - }); -}).listen(7575); diff --git a/examples/saturate/index.html b/examples/saturate/index.html deleted file mode 100644 index dc9be0c..0000000 --- a/examples/saturate/index.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - -