diff --git a/app/controllers/socket.js b/app/controllers/socket.js index a98f3503..be6e614c 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -9,15 +9,16 @@ module.exports.init = function(io_ext) { ios = io_ext; ios.sockets.on('connection', function(socket) { socket.on('subscribe', function(topic) { - console.log('subscribe ' + topic); socket.join(topic); }); socket.on('message', function(m) { - mdb.addMessage(m, m.from, m.to, function(err) { + mdb.addMessage(m, function(err) { if (err) throw err; // TODO: handle }); }); }); + + mdb.on('message', broadcastMessage); }; module.exports.broadcastTx = function(tx) { @@ -60,14 +61,9 @@ module.exports.broadcastSyncInfo = function(historicSync) { ios.sockets.in('sync').emit('status', historicSync); }; -module.exports.broadcastMessage = function(from, to, ts, message) { +var broadcastMessage = module.exports.broadcastMessage = function(message) { if (ios) { - console.log('sending message '+to); - ios.sockets.in(to).emit('message', { - from: from, - payload: message, - ts: ts - }); + ios.sockets.in(message.to).emit('message', message); } } diff --git a/examples/messages.html b/examples/messages.html index fde7b90f..dfbd83ee 100644 --- a/examples/messages.html +++ b/examples/messages.html @@ -67,41 +67,44 @@ var AuthMessage = bitcore.AuthMessage; var Buffer = bitcore.Buffer; - // show message - var show = function(msg) { - $('#messages').append($('
  • ').text(msg.from+':' + JSON.stringify(msg.payload))); - }; - - // generate new identity var pk = Key.generateSync(); var pubkey = pk.public.toString('hex'); $('#pubkey').text('Your key: '+pubkey); + // show message + var show = function(from, text) { + $('#messages').append($('
  • ').text(from+': ' + text)); + }; + // send chat handler - $('form').submit(function() + $('form').submit(function(e) { + e.preventDefault(); var text = $('#m').val() if (text.length === 0) { - return false; + return; } var otherPubkey = $('#other').val(); - var data = AuthMessage.encode(otherPubkey, pk, new Buffer(text)); - data.to = otherPubkey; + var data = AuthMessage.encode(otherPubkey, pk, text); socket.emit('message', data); - data.from = 'You'; - show(data); + show('You', text); $('#m').val(''); - return false; + return; }); // receive chat handler socket.emit('subscribe', pubkey); socket.on('message', function(msg) { - show(msg); + try { + var data = AuthMessage.decode(pk, msg); + } catch(e) { + alert(e); + } + show(msg.pubkey, data.payload); }); }); diff --git a/lib/MessageDb.js b/lib/MessageDb.js index 164abfcd..36b195cb 100644 --- a/lib/MessageDb.js +++ b/lib/MessageDb.js @@ -8,10 +8,10 @@ var async = require('async'); var logger = require('./logger').logger; var util = require('util'); var EventEmitter = require('events').EventEmitter; -var sockets = require('../app/controllers/socket.js'); var microtime = require('microtime'); var bitcore = require('bitcore'); var AuthMessage = bitcore.AuthMessage; +var preconditions = require('preconditions').singleton(); var MESSAGE_PREFIX = 'msg-'; // msg-- => @@ -37,13 +37,13 @@ util.inherits(MessageDb, EventEmitter); MessageDb.prototype.initEvents = function() { if (db) return; + var self = this; this.db.on('put', function(key, value) { - var spl = key.split('-'); - var from = spl[1]; - var to = spl[2]; - var ts = spl[3]; - var message = value; - sockets.broadcastMessage(from, to, ts, message); + var data = {}; + data.key = key; + data.value = value; + var message = MessageDb.fromStorage(data); + self.emit('message', message); }); this.db.on('ready', function() { //console.log('Database ready!'); @@ -55,49 +55,58 @@ MessageDb.prototype.close = function(cb) { }; -var messageKey = function(from, to, ts) { +var messageKey = function(pubkey, to, ts) { if (!ts) ts = Math.round(microtime.now()); - return MESSAGE_PREFIX + from.toString() + '-' + to.toString() + '-' + ts; + return MESSAGE_PREFIX + pubkey.toString() + '-' + to.toString() + '-' + ts; }; -MessageDb.prototype.addMessage = function(m, from, to, cb) { - +MessageDb.prototype.addMessage = function(m, cb) { + if (!this.authenticate(m)) { cb(new Error('Authentication failed')); return; } - var key = messageKey(from, to); + var key = messageKey(m.pubkey, m.to); var value = m; this.db.put(key, value, cb); }; MessageDb.prototype.authenticate = function(m) { + preconditions.checkArgument(m.pubkey); + preconditions.checkArgument(m.sig); + preconditions.checkArgument(m.encrypted); + var frompubkey = new Buffer(m.pubkey, 'hex'); var sig = new Buffer(m.sig, 'hex'); var encrypted = new Buffer(m.encrypted, 'hex'); return AuthMessage._verify(frompubkey, sig, encrypted); }; -MessageDb.prototype.getMessages = function(from, to, lower_ts, upper_ts, cb) { +MessageDb.fromStorage = function(data) { + var spl = data.key.split('-'); + var pubkey = spl[1]; + var to = spl[2]; + var ts = +spl[3]; + var message = data.value; + message.ts = ts; + message.to = to; + return message; +}; + +MessageDb.prototype.getMessages = function(pubkey, to, lower_ts, upper_ts, cb) { var list = []; var opts = { - end: messageKey(from, to, lower_ts), - start: messageKey(from, to, upper_ts), + end: messageKey(pubkey, to, lower_ts), + start: messageKey(pubkey, to, upper_ts), // limit: limit, TODO reverse: true, }; db.createReadStream(opts) .on('data', function(data) { - var spl = data.key.split('-'); - var from = spl[1]; - var to = spl[2]; - var ts = +spl[3]; - list.push({ - ts: ts, - message: data.value, - }); + var message = MessageDb.fromStorage(data); + list.push(message); }) .on('error', function(err) { return cb(err); diff --git a/package.json b/package.json index 31dd267a..be8c9cd5 100644 --- a/package.json +++ b/package.json @@ -51,24 +51,25 @@ "start": "node node_modules/grunt-cli/bin/grunt" }, "dependencies": { - "bitcore": "git://github.com/bitpay/bitcore.git#4d8af75ae9916984c52ee2eda1870d5980656341", - "base58-native": "0.1.2", "async": "*", + "base58-native": "0.1.2", + "bignum": "*", + "bitcore": "git://github.com/bitpay/bitcore.git#4d8af75ae9916984c52ee2eda1870d5980656341", + "bufferput": "git://github.com/bitpay/node-bufferput.git", + "buffertools": "*", + "commander": "*", + "express": "~3.4.7", + "glob": "*", "leveldown": "*", "levelup": "*", - "glob": "*", - "soop": "=0.1.5", - "commander": "*", - "bignum": "*", - "winston": "*", - "express": "~3.4.7", - "buffertools": "*", - "should": "~2.1.1", - "socket.io": "~1.0.4", "moment": "~2.5.0", + "preconditions": "^1.0.7", + "should": "~2.1.1", "sinon": "~1.7.3", - "xmlhttprequest": "~1.6.0", - "bufferput": "git://github.com/bitpay/node-bufferput.git" + "socket.io": "~1.0.4", + "soop": "=0.1.5", + "winston": "*", + "xmlhttprequest": "~1.6.0" }, "devDependencies": { "chai": "*", diff --git a/test/test.MessageDb.js b/test/test.MessageDb.js index c6aabaa0..151b6614 100644 --- a/test/test.MessageDb.js +++ b/test/test.MessageDb.js @@ -4,12 +4,14 @@ var chai = require('chai'); var should = chai.should; var expect = chai.expect; -var MessageDb = require('../lib/MessageDb'); -var bitcore = require('bitcore'); -var SIN = bitcore.SIN; var levelup = require('levelup'); var memdown = require('memdown'); var microtime = require('microtime'); +var MessageDb = require('../lib/MessageDb'); +var bitcore = require('bitcore'); +var SIN = bitcore.SIN; +var Key = bitcore.Key; +var AuthMessage = bitcore.AuthMessage; describe('MessageDb', function() { var opts = { @@ -28,18 +30,23 @@ describe('MessageDb', function() { var mdb = MessageDb.default(); expect(mdb).to.exist; }); - var from = new SIN(new Buffer('dadbad00', 'hex')); - var to = new SIN(new Buffer('bacacafe', 'hex')); - var message = { + var fpk = Key.generateSync(); + var tpk = Key.generateSync(); + var from = fpk.public.toString('hex'); + var to = tpk.public.toString('hex'); + var messageData = { a: 1, b: 2 }; - var message2 = {}; - var message3 = ['a', 'b']; + var messageData2 = {}; + var messageData3 = ['a', 'b']; + var message = AuthMessage.encode(to, fpk, messageData); + var message2 = AuthMessage.encode(to, fpk, messageData2); + var message3 = AuthMessage.encode(to, fpk, messageData3); it('should be able to add and read a message', function(done) { var mdb = new MessageDb(opts); var lower_ts = microtime.now(); - mdb.addMessage(message, from, to, function(err) { + mdb.addMessage(message, function(err) { expect(err).to.not.exist; var upper_ts = microtime.now(); mdb.getMessages(from, to, lower_ts, upper_ts, function(err, messages) { @@ -47,7 +54,7 @@ describe('MessageDb', function() { messages.length.should.equal(1); messages[0].ts.should.be.below(upper_ts); messages[0].ts.should.be.above(lower_ts); - var m = messages[0].message; + var m = AuthMessage.decode(tpk, messages[0]).payload; m.a.should.equal(1); m.b.should.equal(2); done(); @@ -57,23 +64,25 @@ describe('MessageDb', function() { it('should be able to add many messages and read them', function(done) { var mdb = new MessageDb(opts); var lower_ts = microtime.now(); - mdb.addMessage(message, from, to, function(err) { + mdb.addMessage(message, function(err) { expect(err).to.not.exist; - mdb.addMessage(message2, from, to, function(err) { + mdb.addMessage(message2, function(err) { expect(err).to.not.exist; var upper_ts = microtime.now(); setTimeout(function() { - mdb.addMessage(message3, from, to, function(err) { + mdb.addMessage(message3, function(err) { expect(err).to.not.exist; mdb.getMessages(from, to, lower_ts, upper_ts, function(err, messages) { expect(err).to.not.exist; messages.length.should.equal(2); messages[0].ts.should.be.below(upper_ts); messages[0].ts.should.be.above(lower_ts); - JSON.stringify(messages[0].message).should.equal('{"a":1,"b":2}'); + var m0 = AuthMessage.decode(tpk, messages[0]).payload; + JSON.stringify(m0).should.equal('{"a":1,"b":2}'); messages[1].ts.should.be.below(upper_ts); messages[1].ts.should.be.above(lower_ts); - JSON.stringify(messages[1].message).should.equal('{}'); + var m1 = AuthMessage.decode(tpk, messages[1]).payload; + JSON.stringify(m1).should.equal('{}'); done(); }); });