resolve merge-conflict with accounting branch

This commit is contained in:
ansuz 2017-03-14 15:52:04 +01:00
commit 306f6ce806
10 changed files with 328 additions and 11 deletions

View file

@ -209,6 +209,21 @@ const handleMessage = function (ctx, user, msg) {
let parsedMsg = {state: 1, channel: parsed[1]};
sendMsg(ctx, user, [0, HISTORY_KEEPER_ID, 'MSG', user.id, JSON.stringify(parsedMsg)]);
});
} else if (ctx.rpc) {
/* RPC Calls... */
var rpc_call = parsed.slice(1);
// slice off the sequence number and pass in the rest of the message
ctx.rpc(rpc_call, function (err, output) {
if (err) {
console.error('[' + err + ']', output); // TODO make this disableable
sendMsg(ctx, user, [seq, 'ACK']);
sendMsg(ctx, user, [0, HISTORY_KEEPER_ID, 'MSG', user.id, JSON.stringify([parsed[0], 'ERROR', err])]);
return
}
sendMsg(ctx, user, [seq, 'ACK']);
sendMsg(ctx, user, [0, HISTORY_KEEPER_ID, 'MSG', user.id, JSON.stringify([parsed[0]].concat(output))]);
});
}
return;
}
@ -251,7 +266,7 @@ const handleMessage = function (ctx, user, msg) {
}
};
let run = module.exports.run = function (storage, socketServer, config) {
let run = module.exports.run = function (storage, socketServer, config, rpc) {
/* Channel removal timeout defaults to 60000ms (one minute) */
config.channelRemovalTimeout =
typeof(config.channelRemovalTimeout) === 'number'?
@ -263,7 +278,8 @@ let run = module.exports.run = function (storage, socketServer, config) {
channels: {},
timeouts: {},
store: storage,
config: config
config: config,
rpc: rpc,
};
setInterval(function () {
Object.keys(ctx.users).forEach(function (userId) {

View file

@ -130,6 +130,13 @@ module.exports = {
*/
openFileLimit: 2048,
/* Cryptpad's socket server can be extended to respond to RPC calls
* you can configure it to respond to custom RPC calls if you like.
* provide the path to your RPC module here, or `false` if you would
* like to disable the RPC interface completely
*/
rpc: './rpc.js',
/* it is recommended that you serve cryptpad over https
* the filepaths below are used to configure your certificates
*/

37
rpc.js Normal file
View file

@ -0,0 +1,37 @@
/* Use Nacl for checking signatures of messages
*/
var Nacl = require("tweetnacl");
var RPC = module.exports;
var pin = function (ctx, cb) { };
var unpin = function (ctx, cb) { };
var getHash = function (ctx, cb) { };
var getTotalSize = function (ctx, cb) { };
var getFileSize = function (ctx, cb) { };
RPC.create = function (config, cb) {
// load pin-store...
console.log('loading rpc module...');
rpc = function (msg, respond) {
switch (msg[0]) {
case 'ECHO':
respond(void 0, msg);
break;
case 'PIN':
case 'UNPIN':
case 'GET_HASH':
case 'GET_TOTAL_SIZE':
case 'GET_FILE_SIZE':
default:
respond('UNSUPPORTED_RPC_CALL', msg);
break;
}
};
cb(void 0, rpc);
};

View file

@ -117,13 +117,32 @@ httpServer.listen(config.httpPort,config.httpAddress,function(){
var wsConfig = { server: httpServer };
if(!config.useExternalWebsocket) {
if (websocketPort !== config.httpPort) {
console.log("setting up a new websocket server");
wsConfig = { port: websocketPort};
var createSocketServer = function (err, rpc) {
if(!config.useExternalWebsocket) {
if (websocketPort !== config.httpPort) {
console.log("setting up a new websocket server");
wsConfig = { port: websocketPort};
}
var wsSrv = new WebSocketServer(wsConfig);
Storage.create(config, function (store) {
NetfluxSrv.run(store, wsSrv, config, rpc);
});
}
var wsSrv = new WebSocketServer(wsConfig);
Storage.create(config, function (store) {
NetfluxSrv.run(store, wsSrv, config);
});
}
};
var loadRPC = function (cb) {
config.rpc = typeof(config.rpc) === 'undefined'? './rpc.js' : config.rpc;
if (typeof(config.rpc) === 'string') {
// load pin store...
var Rpc = require(config.rpc);
Rpc.create(config, function (e, rpc) {
if (e) { throw e; }
cb(void 0, rpc);
});
} else {
cb();
}
};
loadRPC(createSocketServer);

19
www/common/encode.js Normal file
View file

@ -0,0 +1,19 @@
define([], function () {
var exports = {};
var hexToUint8Array = exports.hexToUint8Array = function (s) {
// if not hex or odd number of characters
if (!/[a-fA-F0-9]+/.test(s) || s.length % 2) { throw new Error("string is not hex"); }
return s.split(/([0-9a-fA-F]{2})/)
.filter(function (x) { return x; })
.map(function (x) { return Number('0x' + x); });
};
var uint8ArrayToHex = exports.uint8ArrayToHex = function (a) {
return a.reduce(function(memo, i) {
return memo + ((i < 16) ? '0' : '') + i.toString(16);
}, '');
};
return exports;
});

57
www/common/pinpad.js Normal file
View file

@ -0,0 +1,57 @@
define([
'/common/cryptpad-common.js',
'/common/rpc.js',
'/bower_components/tweetnacl/nacl-fast.min.js'
], function (Cryptpad, Rpc) {
var Nacl = window.nacl;
var deduplicate = function (array) {
var a = array.slice();
for(var i=0; i<a.length; i++) {
for(var j=i+1; j<a.length; j++) {
if(a[i] === a[j]) { a.splice(j--, 1); }
}
}
return a;
};
var create = function (network, ed) {
var exp = {};
var rpc = Rpc.create(network, ed);
var checkHash = exp.checkHash = function (fileList) {
//var fileList = fo.getFilesDataFiles();
var channelIdList = [];
fileList.forEach(function (href) {
var parsedHref = Cryptpad.parsePadUrl(href);
if (!parsedHref || !parsedHref.hash) { return; }
var parsedHash = Cryptpad.parseHash(parsedHref.hash);
if (!parsedHash || !parsedHash.channel) { return; }
channelIdList.push(Cryptpad.base64ToHex(parsedHash.channel));
});
var uniqueList = deduplicate(channelIdList).sort();
/*
1. every time you want to pin or unpid a pad you send a message to the server
2. the server sends back a hash of the sorted list of your pinned pads
3. you hash your sorted list of pinned pads that you should have according to your drive
4. compare them, if same
AWESOME
if they are not
UNPIN all, send all
*/
var hash = Nacl.util.encodeBase64(Nacl.hash(Nacl.util.decodeUTF8( JSON.stringify(uniqueList) )));
console.log(hash);
return hash;
};
return exp;
};
return { create: create };
});

106
www/common/rpc.js Normal file
View file

@ -0,0 +1,106 @@
define([
'/common/encode.js',
'/bower_components/tweetnacl/nacl-fast.min.js',
], function (Encode) {
var MAX_LAG_BEFORE_TIMEOUT = 30000;
var uid = function () {
return Number(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER))
.toString(32).replace(/\./g, '');
};
/*
types of messages:
pin -> hash
unpin -> hash
getHash -> hash
getTotalSize -> bytes
getFileSize -> bytes
*/
/* RPC communicates only with the history keeper
messages have the format:
[TYPE, txid, msg]
*/
var sendMsg = function (ctx, type, msg, cb) {
var network = ctx.network;
var hkn = network.historyKeeper;
var txid = uid();
ctx.pending[txid] = cb;
return network.sendto(hkn, JSON.stringify([txid, type, msg]));
};
var parse = function (msg) {
try {
return JSON.parse(msg);
} catch (e) {
return null;
}
};
/* Returning messages have the format:
[txid, {}]
*/
var onMsg = function (ctx, msg) {
var parsed = parse(msg);
if (!parsed) {
// TODO handle error
console.log(msg);
return;
}
var txid = parsed[0];
var pending = ctx.pending[txid];
var response = parsed.slice(1);
if (typeof(pending) === 'function') {
if (response[0] === 'ERROR') {
return void pending(response[1]);
}
pending(void 0, response);
} else {
console.log("No callback provided");
}
};
var cookie = function (ctx, cb) {
// TODO txid
};
var signMsg = function (msg, secKey) {
// TODO
};
var create = function (network, edPrivateKey) {
if (!/[0-9a-f]{64}/.test(edPrivateKey)) {
//throw new Error("private signing key is not valid");
}
var ctx = {
//privateKey: Encode.hexToUint8Array(edPrivateKey),
seq: new Date().getTime(),
network: network,
timeouts: {}, // timeouts
pending: {}, // callbacks
};
var pin = function (channel, cb) { };
var send = function (type, msg, cb) {
return sendMsg(ctx, type, msg, cb);
};
network.on('message', function (msg, sender) {
onMsg(ctx, msg);
});
return {
cookie: function (cb) { cookie(ctx, cb); },
send: send,
};
};
return { create: create };
});

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html class="cp slide">
<head>
<title>CryptPad</title>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<script data-bootload="main.js" data-main="/common/boot.js" src="/bower_components/requirejs/require.js"></script>
</head>
<body>
<div id="iframe-container">
<iframe id="pad-iframe"></iframe><script src="/common/noscriptfix.js"></script>
</div>
</body>
</html>

View file

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body>
<h1>PEWPEW

35
www/examples/rpc/main.js Normal file
View file

@ -0,0 +1,35 @@
require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } });
define([
'/common/cryptpad-common.js',
'/common/rpc.js',
'/bower_components/jquery/dist/jquery.min.js',
], function (Cryptpad, RPC) {
var $ = window.jQuery;
var APP = window.APP = {
Cryptpad: Cryptpad,
};
$(function () {
Cryptpad.ready(function (err, env) {
var network = Cryptpad.getNetwork();
var rpc = RPC.create(network); // TODO signing key
var payload = {
a: Math.floor(Math.random() * 1000),
b: 7,
};
// console.log(payload);
rpc.send('ECHO', payload, function (e, msg) {
if (e) { return void console.error(e); }
console.log(msg);
});
// test a non-existent RPC call
rpc.send('PEWPEW', ['pew'], function (e, msg) {
if (e) { return void console.error(e); }
console.log(msg);
});
});
});
});