2011-01-04 15:09:11 +01:00
|
|
|
/* cortex.js
|
2011-01-14 20:49:41 +01:00
|
|
|
* PURPOSE
|
2011-01-04 15:09:11 +01:00
|
|
|
* AUTHOR
|
|
|
|
* LICENSE
|
|
|
|
*
|
|
|
|
* NOTES
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* HTML elements used
|
|
|
|
* cortexLog - textarea
|
|
|
|
* statusLabel - div
|
|
|
|
* numberOfNodes - div
|
|
|
|
* connections -div
|
|
|
|
* dlc - div
|
|
|
|
*/
|
|
|
|
|
|
|
|
/***** Ajax Basics *****/
|
|
|
|
|
|
|
|
var port = location.href.substring( location.href.substring(7).indexOf(':')+8,
|
|
|
|
location.href.substring(7).indexOf('/')+7);
|
|
|
|
|
|
|
|
// Returns an ajax object
|
|
|
|
function ajaxConnect() {
|
|
|
|
var http = null;
|
|
|
|
if(window.XMLHttpRequest)
|
|
|
|
http = new XMLHttpRequest();
|
|
|
|
else if (window.ActiveXObject)
|
|
|
|
http = new ActiveXObject("Microsoft.XMLHTTP");
|
|
|
|
return http;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns a function that can be passed to http.send
|
|
|
|
* that runs code fn on successful response
|
|
|
|
* Kind of a macro function builder
|
|
|
|
* http: ajax object
|
|
|
|
* fn: function taking one argument, the resp from the server,
|
|
|
|
* this function is run on a successful ajax call
|
|
|
|
* err: OPTIONAL argument that contains a funtion
|
|
|
|
* to be run if the connection failed
|
|
|
|
*/
|
|
|
|
function returnfn(http, fn, err) {
|
|
|
|
if (!fn)
|
|
|
|
fn = function(resp) {};
|
|
|
|
if (!err)
|
|
|
|
err = function() {};
|
|
|
|
return function() {
|
|
|
|
if (http.readyState == 4) {
|
|
|
|
if (http.responseText == '')
|
|
|
|
err();
|
|
|
|
else
|
|
|
|
fn(http.responseText);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Does ajax magic. Makes ajax call with data and sets up
|
|
|
|
* retfn to be called on response
|
|
|
|
* forward is the final destination address of the call if
|
|
|
|
* it is not this local
|
|
|
|
*/
|
|
|
|
function ajaxSend(http, data, retfn, forward) {
|
|
|
|
if (!forward)
|
|
|
|
forward = '';
|
|
|
|
http.onreadystatechange = retfn;
|
|
|
|
http.open('POST', "http://localhost:"+port+"/"+ forward, true);
|
|
|
|
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
|
|
http.send(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***** Utility Functions *****/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// make sure a number is two digits long, padding 0 on front
|
|
|
|
function d2(str) {
|
|
|
|
if (str <10)
|
|
|
|
return "0"+str;
|
|
|
|
else
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
// generate the time as a string
|
|
|
|
function getTime() {
|
|
|
|
var date = new Date();
|
|
|
|
return d2(date.getHours()) + ":" + d2(date.getMinutes()) + ":" + d2(date.getSeconds())
|
|
|
|
}
|
|
|
|
|
|
|
|
function extractHost(url) {
|
|
|
|
// http: or file:
|
|
|
|
var host = url.substr(5);
|
|
|
|
while (host.charAt(0) == '/')
|
|
|
|
host = host.substr(1);
|
|
|
|
var end = host.indexOf('/');
|
|
|
|
|
|
|
|
if (end > 0 )
|
|
|
|
host = host.substr(0, end);
|
|
|
|
return host;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-01-20 19:20:38 +01:00
|
|
|
var logging = true
|
2011-01-04 15:09:11 +01:00
|
|
|
|
|
|
|
function log(str) {
|
|
|
|
//if (logCheckElem == null)
|
|
|
|
// logCheckElem = document.getElementById("logCheck");
|
|
|
|
if (logging) { //logCheckElem.checked == true) {
|
|
|
|
str = getTime() + ": " + str+"\n";
|
|
|
|
var log = document.getElementById('cortexLog');
|
|
|
|
if(log)
|
|
|
|
log.value = str + log.value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function error(msg) {
|
|
|
|
log("ERROR: " + msg);
|
|
|
|
alert("ERROR: " + msg);
|
|
|
|
clearInterval(cronID); // Shuts down cron
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***** Basic Server Communication *****/
|
|
|
|
|
|
|
|
var localNodeAddr = '';
|
|
|
|
var originURL = 'Unknown Source';
|
|
|
|
var connected = false;
|
|
|
|
var numberOfNodes = 0;
|
|
|
|
var connections = new Array();
|
|
|
|
|
|
|
|
var dlc = 0;
|
|
|
|
var msgQ = new Array();
|
|
|
|
|
|
|
|
/* basic ping function for local node
|
|
|
|
* if successful,
|
|
|
|
* if we haven't greeted the server, we do,
|
|
|
|
* otherwise nothing (just a heartbeat)
|
|
|
|
* if it fails, lets the user know we have lost
|
|
|
|
* connection to the node server
|
|
|
|
*/
|
|
|
|
function ping() {
|
|
|
|
var http = ajaxConnect();
|
|
|
|
|
|
|
|
var retfn = returnfn(http,
|
|
|
|
function(resp) {
|
2011-01-06 17:46:26 +01:00
|
|
|
//log("pong!");
|
2011-01-04 15:09:11 +01:00
|
|
|
if (!connected) {
|
|
|
|
connected = true;
|
|
|
|
greet();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(resp) {
|
|
|
|
connected = false;
|
|
|
|
var html = "Connection to local Node failed. Try reloading from <a href=\"" + originURL + "\" target=\"window\">" + originURL + "</a>";
|
2011-01-06 17:46:26 +01:00
|
|
|
|
2011-01-04 15:09:11 +01:00
|
|
|
stl = document.getElementById('statusLabel');
|
|
|
|
if (stl)
|
|
|
|
stl.innerHTML = html;
|
|
|
|
}
|
|
|
|
|
|
|
|
);
|
2011-01-06 17:46:26 +01:00
|
|
|
//log("ping!");
|
2011-01-04 15:09:11 +01:00
|
|
|
ajaxSend(http, "cmd=ping\n\n", retfn);
|
|
|
|
}
|
|
|
|
|
|
|
|
function init() {
|
2011-01-06 17:46:26 +01:00
|
|
|
log("init");
|
2011-01-04 15:09:11 +01:00
|
|
|
if (connected == false)
|
|
|
|
return;
|
|
|
|
numberOfNodes = 1;
|
|
|
|
if (originURL.substr(0, 4) == "file") {
|
|
|
|
// we are the first
|
|
|
|
//numberOfNodes = 1; // ourself
|
|
|
|
log("Loaded from file");
|
|
|
|
// now we sit and wait
|
|
|
|
} else { // it was http, so we were loaded from another node
|
|
|
|
log("Loaded from " + originURL);
|
|
|
|
originAddress = extractHost(originURL);
|
|
|
|
join_network(originAddress);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Greets the server
|
|
|
|
* so far just gets the server's IP and origin URL
|
|
|
|
*/
|
|
|
|
function greet() {
|
|
|
|
var http = ajaxConnect();
|
|
|
|
|
|
|
|
var retfn = returnfn(http,
|
|
|
|
function(resp) {
|
2011-01-06 17:46:26 +01:00
|
|
|
log("greet returned");
|
2011-01-04 15:09:11 +01:00
|
|
|
var arr = resp.split(" ");
|
|
|
|
localNodeAddr = arr[0];
|
|
|
|
originURL = arr[1];
|
|
|
|
stl = document.getElementById('statusLabel');
|
|
|
|
if (stl)
|
|
|
|
stl.innerHTML = "I am <b>" + localNodeAddr + "</b>";
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
);
|
2011-01-06 17:46:26 +01:00
|
|
|
log("send greet msg");
|
2011-01-04 15:09:11 +01:00
|
|
|
ajaxSend(http, "cmd=greet\n\n", retfn);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Kill the server
|
|
|
|
function killServer() {
|
|
|
|
announceDead(localNodeAddr);
|
|
|
|
var http = ajaxConnect();
|
|
|
|
|
|
|
|
var retfn = returnfn(http,
|
|
|
|
function(resp) {
|
|
|
|
// got a resp, server not dead
|
|
|
|
killServer();
|
|
|
|
});
|
|
|
|
ajaxSend(http, "cmd=kill\n\n", retfn);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the latest server logs
|
|
|
|
function getLog() {
|
|
|
|
var http = ajaxConnect();
|
|
|
|
|
|
|
|
var retfn = returnfn(http,
|
|
|
|
function(resp) {
|
|
|
|
var log = document.getElementById('cortexLog');
|
|
|
|
if (log)
|
|
|
|
log.value = resp + log.value;
|
|
|
|
// Since getLog returns (a call back is called later)
|
|
|
|
// this is tail recursive friendly
|
|
|
|
getLog();
|
|
|
|
});
|
|
|
|
ajaxSend(http, "cmd=getLog\n\n", retfn);
|
|
|
|
}
|
|
|
|
|
2011-01-20 18:16:33 +01:00
|
|
|
/***** Function Registry *****/
|
|
|
|
|
|
|
|
var fnreg = new Array;
|
|
|
|
|
|
|
|
function registerFn(fnname, fn, preplace) {
|
|
|
|
path = fnname.split(".");
|
|
|
|
root = fnreg;
|
2011-01-20 19:20:38 +01:00
|
|
|
for(i=0; i < path.length-1; i++) {
|
2011-01-20 18:16:33 +01:00
|
|
|
if (root[path[i]] == undefined)
|
|
|
|
root[path[i]] = new Array();
|
|
|
|
root = root[path[i]];
|
|
|
|
}
|
|
|
|
if (preplace)
|
|
|
|
root[path[i]] = fn;
|
|
|
|
else {
|
|
|
|
if (root[path[i]] == undefined)
|
|
|
|
root[path[i]] = [fn, null];
|
|
|
|
else {
|
|
|
|
j=0;
|
|
|
|
while(root[path[i]][j] != null)
|
|
|
|
j++;
|
|
|
|
root[path[i]][j] = fn;
|
|
|
|
root[path[i]][j+1] = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-26 08:49:52 +01:00
|
|
|
/* Finds the chain of functions,
|
|
|
|
* calls the nth
|
|
|
|
* stores its return
|
|
|
|
* calls the nth+1 with the return of the nth as well
|
|
|
|
* returns the results of the mth
|
|
|
|
*/
|
2011-01-20 18:16:33 +01:00
|
|
|
function execFn(name, args) {
|
|
|
|
root = fnreg;
|
|
|
|
names = name.split(".");
|
2011-01-20 19:20:38 +01:00
|
|
|
for (i=0; i< names.length; i++) {
|
2011-01-20 18:16:33 +01:00
|
|
|
root = root[names[i]];
|
|
|
|
if (root == undefined)
|
|
|
|
return false; // ERROR, NO FN
|
|
|
|
}
|
|
|
|
i=0;
|
2011-01-26 08:49:52 +01:00
|
|
|
ret = true;
|
2011-01-20 18:16:33 +01:00
|
|
|
while(root[i]) {
|
2011-01-26 08:49:52 +01:00
|
|
|
ret = root[i](args, ret);
|
2011-01-20 18:16:33 +01:00
|
|
|
i++;
|
|
|
|
}
|
2011-01-26 08:49:52 +01:00
|
|
|
return ret;
|
2011-01-20 18:16:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-04 15:09:11 +01:00
|
|
|
/***** Messeging between nodes *****/
|
|
|
|
|
2011-01-20 18:16:33 +01:00
|
|
|
|
2011-01-04 15:09:11 +01:00
|
|
|
function addMsgHandler(msgName, handlerFN, handlerReplace) {
|
2011-01-20 18:16:33 +01:00
|
|
|
registerFn("msgHandler." + msgName, handlerFN, handlerReplace);
|
2011-01-04 15:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function processMsg(resp) {
|
2011-01-20 19:20:38 +01:00
|
|
|
log("processMsg: " + resp['query']);
|
2011-01-20 18:16:33 +01:00
|
|
|
if (!execFn("msgHandler." + resp["query"], resp))
|
|
|
|
log("Error: Uknnown message '" + resp['query'] + "'");
|
2011-01-04 15:09:11 +01:00
|
|
|
}
|
|
|
|
|
2011-01-06 17:46:26 +01:00
|
|
|
function packObject(m, defaultValue) {
|
|
|
|
|
|
|
|
var str = "";
|
|
|
|
for (var i in m) {
|
|
|
|
if (m[i] == '')
|
|
|
|
{
|
|
|
|
if (defaultValue == null) {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
m[i] = defaultValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == "results") {
|
|
|
|
str += i + "=" + packResults(m[i]) + "\n";
|
|
|
|
} else {
|
|
|
|
str += i + "=" + m[i] + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2011-01-04 15:09:11 +01:00
|
|
|
function sendMsg(m, addr, time, mtype) {
|
|
|
|
if(time == null)
|
|
|
|
time = dlc;
|
|
|
|
if(mtype == null)
|
|
|
|
mtype = "single";
|
|
|
|
|
|
|
|
var str = "cmd=sendMsg\n";
|
|
|
|
str += "origin=" + localNodeAddr + "\n";
|
|
|
|
str += "dlc=" + time + "\n";
|
|
|
|
str += "mtype=" + mtype + "\n";
|
|
|
|
|
|
|
|
str += packObject(m);
|
|
|
|
|
|
|
|
str += "\n";
|
2011-01-06 17:46:26 +01:00
|
|
|
//log ("SEND: " + str);
|
2011-01-04 15:09:11 +01:00
|
|
|
|
|
|
|
var http = ajaxConnect();
|
|
|
|
var retfn = returnfn(http, null,
|
|
|
|
function() {
|
|
|
|
disconnect(addr);
|
|
|
|
announceDead(addr);
|
|
|
|
log("ERROR> message to " + addr + " not delivered: '" + str + "'");
|
|
|
|
});
|
2011-01-06 17:46:26 +01:00
|
|
|
//log("sendMsg: " + str);
|
2011-01-04 15:09:11 +01:00
|
|
|
ajaxSend(http, str, retfn, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
function bcastMsg(m) {
|
|
|
|
if (m.query != "heartBeat")
|
|
|
|
dlc ++;
|
|
|
|
//log("BCAST conLen: " + connections.length);
|
|
|
|
for(var i=0; i < connections.length; i++) {
|
|
|
|
log("bcast "+ i +" " + m.query + " to " + connections[i] + " dlc:" + dlc);
|
|
|
|
sendMsg(m, connections[i], dlc, "bcast");
|
|
|
|
//log("back from sendMsg, i:" + i + " conlen:" + connections.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function addMsg(resp) {
|
|
|
|
|
|
|
|
for(var i=msgQ.length-1; i>=0; i--) {
|
|
|
|
|
|
|
|
if (resp.dlc > msgQ[i].dlc) {
|
|
|
|
msgQ[i+1] = msgQ[i];
|
|
|
|
} else {
|
|
|
|
msgQ[i+1] = resp;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
msgQ[0] = resp;
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseResp(resp) {
|
|
|
|
var lines = resp.split("\n");
|
|
|
|
var arr = [];
|
|
|
|
for(var i=0; i < lines.length; i++) {
|
|
|
|
//var kv = lines[i].split("=");
|
|
|
|
var mid = lines[i].indexOf("=");
|
|
|
|
var kv = new Array();
|
|
|
|
kv[0] = lines[i].substring(0, mid);
|
|
|
|
kv[1] = lines[i].substring(mid+1);
|
|
|
|
if (kv[1] == "true")
|
|
|
|
kv[1] = true;
|
|
|
|
else if(kv[0] == "false")
|
|
|
|
kv[1] = false;
|
|
|
|
else if (kv[0] == "dlc" ||
|
|
|
|
kv[0] == "start" ||
|
|
|
|
kv[0] == "end" ||
|
|
|
|
kv[0] == "min" ||
|
|
|
|
kv[0] == "max")
|
|
|
|
kv[1] = Number(kv[1]);
|
|
|
|
else if (kv[0] == "results")
|
|
|
|
kv[1] = unpackResults(kv[1]);
|
|
|
|
arr[kv[0]] = kv[1];
|
|
|
|
}
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
function queueMsgs(mstr) {
|
|
|
|
log("GOT messages: " + mstr);
|
|
|
|
var resps = mstr.split("\n\n");
|
|
|
|
for(var rcount=0; rcount < resps.length; rcount++) {
|
|
|
|
var resp = resps[rcount];
|
|
|
|
if (resp == "")
|
|
|
|
continue;
|
|
|
|
resp = parseResp(resp);
|
|
|
|
if (resp.query == "DLC") {
|
|
|
|
dlc = resp.dlc;
|
|
|
|
//var m = new Object();
|
|
|
|
//m.query = "DLC";
|
|
|
|
//bcastMsg(m);
|
|
|
|
} else {
|
|
|
|
addMsg(resp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var s = "QUEUE: "
|
|
|
|
for (var i =0; i< msgQ.length; i++) {
|
|
|
|
s += msgQ[i].dlc + " ";
|
|
|
|
}
|
|
|
|
log(s);
|
|
|
|
log("mqlen:" + msgQ.length);
|
|
|
|
while (msgQ.length>0 && ((msgQ[msgQ.length-1].dlc - 1) <= dlc)) {
|
|
|
|
var r = msgQ.pop();
|
|
|
|
log("mdlc: " + r.dlc + " dlc: " + dlc + " mqlen: " + msgQ.length + " type:" + r.mtype + " query: " + r.query);
|
|
|
|
if (r.mtype == "bcast")
|
|
|
|
dlc = r.dlc
|
|
|
|
processMsg(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function getMsgs() {
|
|
|
|
var http = ajaxConnect();
|
|
|
|
var retfn = returnfn(http,
|
|
|
|
function(resp) {
|
2011-01-06 17:46:26 +01:00
|
|
|
//log("getMsgs: " + resp);
|
2011-01-04 15:09:11 +01:00
|
|
|
queueMsgs(resp);
|
|
|
|
// Since getMsgs returns (a call back is called later)
|
|
|
|
// this is tail recursive friendly
|
|
|
|
getMsgs();
|
2011-01-06 17:46:26 +01:00
|
|
|
},
|
|
|
|
function() {
|
|
|
|
log("ERROR: getMsg RETURN FAIL");
|
2011-01-04 15:09:11 +01:00
|
|
|
});
|
2011-01-06 17:46:26 +01:00
|
|
|
log("getMsgs");
|
2011-01-04 15:09:11 +01:00
|
|
|
ajaxSend(http, "cmd=getMsgs\n\n", retfn);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***** P2P Network Communication *****/
|
|
|
|
|
|
|
|
function connectedTo(addr) {
|
|
|
|
if (addr == localNodeAddr)
|
|
|
|
return true;
|
|
|
|
for(i = 0; i < connections.length; i++) {
|
|
|
|
if (connections[i] == addr)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function addConnection(addr) {
|
|
|
|
if(!connectedTo(addr)) {
|
|
|
|
connections[connections.length] = addr;
|
|
|
|
numberOfNodes++;
|
|
|
|
return true;
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function join_network(address, bcast) {
|
|
|
|
if(bcast == null) {
|
|
|
|
bcast = true;
|
|
|
|
}
|
|
|
|
log("join_network -> " + address);
|
|
|
|
var m = new Object();
|
|
|
|
m["query"] = "join_network";
|
|
|
|
m["addr"] = localNodeAddr;
|
|
|
|
//m["nodes"] = genNodeList();
|
|
|
|
sendMsg(m, address);
|
|
|
|
if (bcast == true) {
|
|
|
|
m = new Object();
|
|
|
|
m["query"] = "new_network";
|
|
|
|
m["addr"] = address;
|
|
|
|
bcastMsg(m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function genNodeList() {
|
|
|
|
var str = "";//localNodeAddr+",";
|
|
|
|
for (var i =0; i < connections.length; i++) {
|
|
|
|
str += connections[i] + ",";
|
|
|
|
}
|
|
|
|
if (connections.length > 0)
|
|
|
|
str = str.substring(0,str.length-1);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
function advertiseNewNode(addr) {
|
|
|
|
var m = new Object();
|
|
|
|
m['query'] = "newNode";
|
|
|
|
m['addr'] = addr;
|
|
|
|
bcastMsg(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
function announceDead(addr) {
|
|
|
|
var m = new Object();
|
|
|
|
m['query'] = "deadNode";
|
|
|
|
m['addr'] = addr;
|
|
|
|
bcastMsg(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
function sendDLC(addr) {
|
|
|
|
var m = new Object();
|
|
|
|
m.query = "DLC";
|
|
|
|
sendMsg(m, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
function sendWelcome(addrList, addr) {
|
|
|
|
var m = new Object();
|
|
|
|
m["query"] = "welcome";
|
|
|
|
m["addrList"] = addrList;
|
|
|
|
sendMsg(m, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
function heartBeat() {
|
|
|
|
var m = new Object();
|
|
|
|
m.query = "heartBeat";
|
|
|
|
bcastMsg(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
function reloadHTML() {
|
|
|
|
var http = ajaxConnect();
|
|
|
|
var retfn = returnfn(http);
|
|
|
|
ajaxSend(http, "cmd=reloadHTML\n\n",retfn);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
function poke() {
|
|
|
|
var http = ajaxConnect();
|
|
|
|
document.getElementById("pingNodeResp").innerHTML = "";
|
|
|
|
var dest = document.getElementById("pingNode").value;
|
|
|
|
|
|
|
|
var retfn = returnfn(http,
|
|
|
|
function(resp) {
|
|
|
|
document.getElementById("pingNodeResp").innerHTML += resp + "<br>";
|
|
|
|
var retfn = returnfn(http,
|
|
|
|
function(resp) {
|
|
|
|
document.getElementById("pingNodeResp").innerHTML += resp + "<br>";
|
|
|
|
});
|
|
|
|
ajaxSend(http, "cmd=greet\n\n", retfn, dest);
|
|
|
|
});
|
|
|
|
|
|
|
|
ajaxSend(http, "cmd=ping\n\n", retfn, dest);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/***** Msg Handlers *****/
|
|
|
|
|
|
|
|
function handleNewNode(resp, welcome) {
|
|
|
|
|
|
|
|
if (welcome == null)
|
|
|
|
welcome = false;
|
|
|
|
var addr = resp.addr;
|
|
|
|
//log2("handle new node " + addr + " from " + resp.origin);
|
|
|
|
|
|
|
|
// handles re adding if reloaded html
|
|
|
|
//if (!connectedTo(addr))
|
|
|
|
//{
|
|
|
|
var ret = genNodeList();
|
|
|
|
var n = addConnection(addr);
|
|
|
|
if (welcome == true) {
|
|
|
|
sendDLC(addr);
|
|
|
|
sendWelcome(ret, addr);
|
|
|
|
//sendLocks(addr);
|
|
|
|
//sendTests(addr);
|
|
|
|
}
|
|
|
|
if (n == true) {
|
|
|
|
//sendReqs(addr);
|
|
|
|
advertiseNewNode(addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addMsgHandler( "join_network",
|
|
|
|
function (resp) {
|
|
|
|
handleNewNode(resp, true);
|
|
|
|
});
|
|
|
|
|
|
|
|
addMsgHandler( "newNode",
|
|
|
|
function (resp) {
|
|
|
|
handleNewNode(resp, false);
|
|
|
|
});
|
|
|
|
|
|
|
|
addMsgHandler( "welcome",
|
|
|
|
function (resp) {
|
|
|
|
log("Welcome message received");
|
|
|
|
//var myNodes = genNodeList();
|
|
|
|
addConnection(resp['origin']);
|
|
|
|
if (resp['addrList']){
|
|
|
|
var nodes = resp['addrList'].split(",");
|
|
|
|
for(var i=0; i < nodes.length; i++){
|
|
|
|
addConnection(nodes[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(var i =0; i< connections.length; i++) {
|
|
|
|
var addr = connections[i];
|
|
|
|
if (addr == localNodeAddr)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
advertiseNewNode(addr);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2011-01-06 17:46:26 +01:00
|
|
|
addMsgHandler( "deadNode",
|
2011-01-04 15:09:11 +01:00
|
|
|
function (resp) {
|
|
|
|
var addr = resp['addr'];
|
2011-01-06 17:46:26 +01:00
|
|
|
log("DISCONNECT " + addr);
|
2011-01-04 15:09:11 +01:00
|
|
|
// remove from connumberOfNodesnections list
|
|
|
|
for (var i=0; i < connections.length; i++) {
|
|
|
|
if (connections[i] == addr) {
|
|
|
|
connections.splice(i,1);
|
|
|
|
numberOfNodes--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2011-01-06 17:46:26 +01:00
|
|
|
addMsgHandler( "new_network",
|
2011-01-04 15:09:11 +01:00
|
|
|
function (resp) {
|
|
|
|
join_network(resp["addr"], false);
|
|
|
|
});
|
|
|
|
|
2011-01-06 17:46:26 +01:00
|
|
|
addMsgHandler( "heartBeat",
|
2011-01-04 15:09:11 +01:00
|
|
|
function (resp) {
|
|
|
|
// do nothing
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
/***** CRON System *****/
|
|
|
|
|
2011-01-20 22:52:54 +01:00
|
|
|
// list of intervals
|
2011-01-06 17:46:26 +01:00
|
|
|
var crontabs = new Array();
|
2011-01-04 15:09:11 +01:00
|
|
|
|
|
|
|
/* add a function to be called repeatedly
|
|
|
|
* interval - in 1/10s of a second
|
|
|
|
* fn - function to be called
|
|
|
|
*/
|
|
|
|
function addCronTab(interval, fn) {
|
2011-01-20 22:52:54 +01:00
|
|
|
crontabs[interval] = true;
|
|
|
|
registerFn("cron."+interval, fn);
|
2011-01-04 15:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var cronI = 0;
|
|
|
|
|
|
|
|
function cron() {
|
|
|
|
if (connected == false)
|
|
|
|
return;
|
|
|
|
|
2011-01-06 17:46:26 +01:00
|
|
|
for (time in crontabs) {
|
|
|
|
if (cronI % Number(time) == 0) {
|
2011-01-20 22:52:54 +01:00
|
|
|
execFn("cron."+ time, null);
|
2011-01-04 15:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
2011-01-06 17:46:26 +01:00
|
|
|
|
|
|
|
cronI += 1;
|
2011-01-04 15:09:11 +01:00
|
|
|
// Reset to 0 after a day
|
2011-01-06 17:46:26 +01:00
|
|
|
if (cronI > 864000) {
|
2011-01-04 15:09:11 +01:00
|
|
|
cronI = 0;
|
2011-01-06 17:46:26 +01:00
|
|
|
}
|
|
|
|
}
|
2011-01-04 15:09:11 +01:00
|
|
|
|
|
|
|
addCronTab(10, ping);
|
2011-01-06 17:46:26 +01:00
|
|
|
addCronTab(300, heartBeat);
|
2011-01-04 15:09:11 +01:00
|
|
|
|
|
|
|
|
|
|
|
/***** UI *****/
|
|
|
|
function setStatus() {
|
|
|
|
var nn = document.getElementById('numberOfNodes');
|
|
|
|
if (nn)
|
|
|
|
nn.innerHTML = "Number of nodes: " + numberOfNodes;
|
|
|
|
var c = document.getElementById('connections');
|
|
|
|
if (c)
|
|
|
|
c.innerHTML = "Connected to: " + genNodeList();
|
|
|
|
var dlcE = document.getElementById('dlc');
|
2011-01-06 17:46:26 +01:00
|
|
|
if (dlcE)
|
2011-01-04 15:09:11 +01:00
|
|
|
dlcE.innerHTML = "DLC: " + dlc;
|
|
|
|
}
|
|
|
|
|
|
|
|
addCronTab(10, setStatus);
|
|
|
|
|
|
|
|
/**** INIT *****/
|
|
|
|
|
2011-01-06 17:46:26 +01:00
|
|
|
function cortex_start(debug) {
|
|
|
|
if(debug)
|
|
|
|
logging = true;
|
2011-01-04 15:09:11 +01:00
|
|
|
ping();
|
|
|
|
var cronID = setInterval("cron()", 100);
|
|
|
|
getMsgs();
|
|
|
|
getLog();
|
|
|
|
}
|
2011-01-06 17:46:26 +01:00
|
|
|
|
|
|
|
|
|
|
|
/********** AND THAT's THE BASIS OF THE CORTEX P2P NETWORK **********/
|
|
|
|
/* We now have dumb do nothing nodes that can connect to each other
|
|
|
|
* and maintain state */
|
|
|
|
/********** NOW TO ADD SOME USEFUL THINGS ON TOP OF IT **********/
|