signal-channel
Version:
A signal channel that empowers webrtc
34 lines (33 loc) • 7.93 kB
JSON
{
"author": {
"name": "Dominic Tarr",
"email": "dominic.tarr@gmail.com",
"url": "http://dominictarr.com"
},
"name": "scuttlebutt",
"description": "replicate data via scuttlebutt protocol",
"version": "4.1.1",
"homepage": "https://github.com/dominictarr/scuttlebutt",
"repository": {
"type": "git",
"url": "git://github.com/dominictarr/scuttlebutt.git"
},
"dependencies": {
"iterate": "0.0.2",
"duplex": "~0.1.3",
"stream-serializer": "0.0.3",
"readable-stream": "~0.0.3",
"monotonic-timestamp": "0.0.2"
},
"devDependencies": {
"macgyver": "~1.9.0",
"event-stream": "~3.0"
},
"scripts": {
"test": "set -e; for test in test/*.js; do node $test; done"
},
"readme": "# scuttlebutt\n\n<img src=https://secure.travis-ci.org/dominictarr/scuttlebutt.png?branch=master>\n\nA base class that makes implementing \ndatastructures for real-time replication easy.\n\nThis seems like a silly name, but I assure you, this is real science. \nread this: http://www.cs.cornell.edu/home/rvr/papers/flowgossip.pdf\n\nor if you are lazy: http://en.wikipedia.org/wiki/Scuttlebutt (laziness will get you nowhere, btw)\n\n\n## Usage\n\nUsers may implement a subclass of thier own data model.\ntwo implementations are provided [scuttlebutt/model](#scuttlebuttmodel) and\n[scuttlebutt/events](#scuttlebuttevents)\n\nalso [crdt](https://github.com/dominictarr/crdt) for a subclass with a more\nhigh-level data model.\n\n### Replication\n\nAny Scuttlebutt subclass is replicated with createStream.\n\n``` js\nvar s = new Scuttlebutt()\nvar z = new Scuttlebutt()\nvar zs = z.createStream()\n\nzs.pipe(s.createStream()).pipe(zs)\n```\n\nsubclasses must implement at least `history` and `applyUpdate`\n\n### Persistence\n\npersist by saving to at least one writable stream.\n\n``` js\nvar Model = require('scuttlebutt/model') //or some other subclass...\nvar fs = require('fs')\nvar m = new Model()\n\n//stream FROM disk.\nfs.createReadStream(file).pipe(m.createWriteStream())\n\n//stream TO disk.\nm.on('sync', function () {\n m.createReadStream().pipe(fs.createWriteStream(file))\n})\n```\nuse `on('sync',...` to wait until the persisted state is in the file\nbefore writing to disk.\n(make sure you rotate files, else there is a edge case where if the process\ncrashes before the histroy has been written then some data will be lost\n/*this is where link to module for that will go*/)\n\nuse you may use [kv](https://github.com/dominictarr/kv) to get streams \nto local storage.\n\n## API\n\n### Scuttlebutt#history(sources)\n\n`sources` is a hash of source_ids: timestamps. \nhistory must return an array of all known events from all sources\nThat occur after the given timestamps for each source.\n\nThe array MUST be in order by timestamp.\n\n``` js\n{ A: 0,\n B: 2,\n C: 3 }\n```\n\n### Scuttlebutt#applyUpdate (update)\n\nPossibly apply a given update to the subclasses model.\nreturn true if the update was applied. (see scuttlebutt/model.js\nfor an example of a subclass that does not apply every update)\n\n### Scuttlebutt#createStream (opts)\n\nCreate a duplex stream to replicate with a remote endpoint.\n\nThe stream returned here emits a special `'header'` event with the id of the\nlocal and remote nodes and the vector clock. You can set metadata on the header\nobject using `opts.meta`.\n\n#### Examples\n\n``` js\n\nvar Model = require('scuttlebutt/model')\n\nvar a = new Model()\nvar b = new Model()\n\na.set(key, value)\n\nb.on('update', console.log)\n\nvar s = a.createStream()\ns.pipe(b.createStream()).pipe(s)\n```\n\n### scuttlebutt/events\n\nA Reliable event emmitter. Multiple instances of an emitter\nmay be connected to each other and will remember events,\nso that they may be resent after a disconnection or crash.\n\nWith this approach it is also possible to persist events to disk,\nmaking them durable over crashes.\n\n``` js\nvar Emitter = require('scuttlebutt/events')\nvar emitter = new Emitter()\n```\n\n#### emit (event, data)\n\nemit an event. only one argument is permitted.\n\n#### on (event, listener)\n\nadd an event listener.\n\n### scuttlebutt/model\n\nA replicateable `Model` object.\n\n``` js\nvar Model = require('scuttlebutt/model')\nvar model = new Model()\n```\n\n\n#### get (key)\n\nGet a property\n\n#### set (key, value)\n\nSet a property\n\n#### on('update', function (key, value, source))\n\nEmmitted when a property changes. \nIf `source !== this.id`\nthen it was a remote update.\n\n## Protocol\n\nMessages are sent in this format:\n\n``` js\n[key, value, timestamp, source]\n```\n\n`source` is the id of the node which originated this message.\ntimestamp is the time when the message was created. \nthis message is created using `Scuttlebutt#localUpdate(key, value)`\n\nWhen two `Scuttlebutts` are piped together, they both exchange their current list\nof sources. this is an object of `{source_id: latest_timestamp_for_source_id}`\nafter receiving this message, `Scuttlebutt` sends any messages not yet \nknown by the other end. This is the heart of Scuttlebutt Reconciliation.\n\n## Security\n\nScuttlebutt has an (optional) heavy duty security model using public keys. \nThis enables a high level of security even in peer-to-peer applications.\nYou can be sure that a given message is from the node that sent it, \neven if you did not receive the messasge from them directly.\n\n## Enabling Security\n\n``` js\nvar model = require('scuttlebutt/model')\nvar security = require('scuttlebutt/security')\nvar keys = {}\nvar m = new Model(security(keys, PRIVATE, PUBLIC))\n```\n\n## Security API\n\nWhen security is enabled, each scuttlebutt message is signed with a private key.\nIt is then possible for any Scuttlebutt instance to be confidant about the\nauthenticity of the message by verifying it against the source's public key.\n\nThis is possible even if the verifying node received the message from in intermediate node.\n\nSecurity is activated by passing in a security object to the contructor of a Scuttlebutt\nsubclass. \n\nUse the included implementation:\n\n``` js\nvar security = require('scuttlebutt/security')(keys, PRIVATE, PUBLIC)\nvar Model = require('scuttlebutt/model')\n\nvar m = new Model(security)\n```\n\nSee \n[scuttlebutt/security.js](https://github.com/dominictarr/scuttlebutt/blob/master/security.js)\nfor a simple example implementation.\n\n`sign(update)` should sign the `update` with the instance's private key.\n`verify(update, cb)` should verify the update, using public key associated with the\n`source` field in the update. Verification may be asyncronous. `verify` must callback\n`cb(err, boolean)` where boolean indicates whether or not the signature is valid.\nonly callback in error in the most extreme circumstances. \nIf there was no known key for the required source then that should be treated as a \nverification failure. If it is not possible to reach the key database (or whatever)\nthen the request should be retried until it is available. \n\n> Note: although the API supports asyncronous verification, \n> it's probably a good idea to load keys into memory so that messages can be verified\n> and signed syncronously.\n\n`createId()` returns a new id for the current node. This is used in the example security \nimplementation to return a id that is a hash of the public key. This makes it impossible\nfor rogue nodes to attempt to associate a old node id with a new public key.\n\n## Generating Keys.\n\ngenerate an ssh private key, and a PEM encoded public key.\n```\nssh-keygen -f $KEYNAME -b $LENGTH -N $PASSWORD -q\nssh-keygen -e -f $KEYNAME.pub -m PEM > $KEYNAME.pem\n\n```\n`$LENGTH` must be `>= 786`, shorter is faster but less secure.\npassword may be empty `''`.\n\n`$KEYNAME` is the private key, and `$KEYNAME.pem` is the public key\nto use with Scuttlebutt.\n\n",
"readmeFilename": "README.markdown",
"_id": "scuttlebutt@4.1.1",
"_from": "scuttlebutt"
}