Merge pull request #2 from sairajzero/master
This commit is contained in:
commit
196ae1c30e
6
.gitattributes
vendored
Normal file
6
.gitattributes
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.gitattributes linguist-vendored
|
||||
util/mongoose.c linguist-vendored
|
||||
util/mongoose.h linguist-vendored
|
||||
app/web/init.js linguist-vendored
|
||||
|
||||
.gitattributes export-ignore
|
||||
482
app/web/app.js
482
app/web/app.js
@ -7,6 +7,15 @@ if (!window.indexedDB) {
|
||||
window.alert("Your browser doesn't support a stable version of IndexedDB.")
|
||||
}
|
||||
|
||||
const adminID = "FMabh7gTSyKPAb2Wi9sK5CBhV8nVFk783i";
|
||||
|
||||
if(blockchain == "FLO")
|
||||
var api_url = `https://flosight.duckdns.org/`;
|
||||
else if(blockchain == "FLO_TEST")
|
||||
var api_url = `https://testnet-flosight.duckdns.org/`;
|
||||
|
||||
var supernodeKBucket;
|
||||
var superNodeList;
|
||||
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
||||
|
||||
var encrypt = {
|
||||
@ -14,7 +23,7 @@ var encrypt = {
|
||||
p: BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16),
|
||||
|
||||
exponent1: function () {
|
||||
return encrypt.p.add(BigInteger.ONE).divide(BigInteger("4"))
|
||||
return this.p.add(BigInteger.ONE).divide(BigInteger("4"))
|
||||
},
|
||||
|
||||
calculateY: function (x) {
|
||||
@ -147,7 +156,7 @@ var encrypt = {
|
||||
getPubKeyHex: function(privateKeyHex){
|
||||
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||
if(key.priv == null){
|
||||
alert("Invalid Private key");
|
||||
console.log("Invalid Private key");
|
||||
return;
|
||||
}
|
||||
key.setCompressed(true);
|
||||
@ -159,6 +168,34 @@ var encrypt = {
|
||||
var floID = key.getBitcoinAddress();
|
||||
return floID;
|
||||
},
|
||||
validateAddr: function (value) {
|
||||
try{
|
||||
var addr = new Bitcoin.Address(value);
|
||||
if (addr == value)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}catch(error){
|
||||
return false;
|
||||
}
|
||||
},
|
||||
verifyWIF: function (wif,addr){
|
||||
try {
|
||||
var key = new Bitcoin.ECKey(wif);
|
||||
if(key.priv == null){
|
||||
return false;
|
||||
}
|
||||
key.setCompressed(true);
|
||||
var bitcoinAddress = key.getBitcoinAddress();
|
||||
if (addr == bitcoinAddress)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
sign: function (msg, privateKeyHex) {
|
||||
var key = new Bitcoin.ECKey(privateKeyHex);
|
||||
key.setCompressed(true);
|
||||
@ -255,14 +292,354 @@ function getTime(time){
|
||||
|
||||
function logout(){
|
||||
sessionStorage.clear();
|
||||
location.reload();
|
||||
window.location.href = "index.html";
|
||||
}
|
||||
|
||||
var supernodeKBucket;
|
||||
var superNodeList;
|
||||
/*Refresh profile and superNode data from API */
|
||||
function ajax(method, uri){
|
||||
var request = new XMLHttpRequest();
|
||||
var url = `${api_url}/${uri}`
|
||||
console.log(url)
|
||||
var result;
|
||||
request.open(method,url , false);
|
||||
request.onload = function () {
|
||||
if (request.readyState == 4 && request.status == 200)
|
||||
result = this.response;
|
||||
else {
|
||||
console.log('error');
|
||||
result = false;
|
||||
}
|
||||
};
|
||||
request.send();
|
||||
console.log(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function reloadInitData(){
|
||||
refreshAPIdata.then(result => {
|
||||
console.log(result);
|
||||
sessionStorage.profiles = JSON.stringify(profiles);
|
||||
sessionStorage.superNodeList = JSON.stringify(Array.from(superNodeList));
|
||||
kBucketObj.launchKBucket().then(result => {
|
||||
console.log(result)
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function refreshAPIdata(){
|
||||
return new Promise((resolve,reject) => {
|
||||
var addr = adminID;
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var lastTx = db.transaction('lastTx', "readwrite").objectStore('lastTx');
|
||||
console.log(addr);
|
||||
new Promise((res,rej) => {
|
||||
var lastTxReq = lastTx.get(addr);
|
||||
lastTxReq.onsuccess = (event) => {
|
||||
var lasttx = event.target.result;
|
||||
if(lasttx === undefined){
|
||||
lasttx = 0;
|
||||
}
|
||||
res(lasttx);
|
||||
}
|
||||
}).then(lasttx => {
|
||||
var response = ajax("GET",`api/addrs/${addr}/txs`);
|
||||
var nRequired = JSON.parse(response).totalItems - lasttx;
|
||||
console.log(nRequired);
|
||||
while(true && nRequired){
|
||||
var response = ajax("GET",`api/addrs/${addr}/txs?from=0&to=${nRequired}`);
|
||||
response = JSON.parse(response);
|
||||
if (nRequired + lasttx != response.totalItems ){
|
||||
nRequired = response.totalItems - lasttx;
|
||||
continue;
|
||||
}
|
||||
response.items.reverse().forEach(tx => {
|
||||
try {
|
||||
if (tx.vin[0].addr == addr){
|
||||
var data = JSON.parse(tx.floData).FLO_Tweet_SuperNode;
|
||||
if(data !== undefined){
|
||||
if(data.addNodes)
|
||||
for(var i=0; i<data.addNodes.length; i++)
|
||||
superNodeList.add(data.addNodes[i])
|
||||
if(data.removeNodes)
|
||||
for(var i=0; i<data.removeNodes.length; i++)
|
||||
superNodeList.delete(data.removeNodes[i])
|
||||
storeSuperNodeData(data).then(function (response) {
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}else{
|
||||
var data = JSON.parse(tx.floData).FLO_Tweet;
|
||||
if(data !== undefined){
|
||||
if(encrypt.getFLOIDfromPubkeyHex(data.pubKey)!=tx.vin[0].addr)
|
||||
throw("PublicKey doesnot match with floID")
|
||||
data = {floID : tx.vin[0].addr, onionAddr : data.onionAddr, name : data.name, pubKey:data.pubKey};
|
||||
profiles[data.floID] = {onionAddr : data.onionAddr, name : data.name, pubKey : data.pubKey};
|
||||
storeProfile(data).then(function (response) {
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
//console.log(error)
|
||||
}
|
||||
});
|
||||
var obs = db.transaction('lastTx', "readwrite").objectStore('lastTx');
|
||||
obs.put(response.totalItems,addr);
|
||||
break;
|
||||
}
|
||||
db.close();
|
||||
resolve('retrived data from API');
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/* Common IDB functions */
|
||||
function storeProfile(data){
|
||||
return new Promise((resolve,reject) => {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction('profiles', "readwrite").objectStore('profiles');
|
||||
objectRequest = obs.put(data);
|
||||
objectRequest.onerror = (event) => { reject(Error('Error occured: Unable to store data'))};
|
||||
objectRequest.onsuccess = (event) => { resolve('Data saved OK') };
|
||||
db.close();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function storeSuperNodeData(data){
|
||||
return new Promise((resolve,reject) => {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!"); };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction('superNodes', "readwrite").objectStore('superNodes');
|
||||
if(data.addNodes)
|
||||
for(var i=0; i<data.addNodes.length; i++)
|
||||
obs.add(true,data.addNodes[i])
|
||||
if(data.removeNodes)
|
||||
for(var i=0; i<data.removeNodes.length; i++)
|
||||
obs.delete(data.removeNodes[i])
|
||||
db.close();
|
||||
resolve('Updated superNodes list in IDB');
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function storeTweet(data,tid){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
|
||||
data.tweetID = `${data.time}_${data.floID}`;
|
||||
data.tid = tid;
|
||||
obs.add(data);
|
||||
var obsL = db.transaction("lastTweet", "readwrite").objectStore("lastTweet");
|
||||
obsL.put(tid,data.floID);
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function storeMsg(data){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("messages", "readwrite").objectStore("messages");
|
||||
data.msgID = `${data.time}_${data.floID}`;
|
||||
obs.add(data);
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
/* SuperNode functions */
|
||||
function sendDataToSuperNode(floID,data){
|
||||
kBucketObj.determineClosestSupernode(floID).then(result=>{
|
||||
var superNodeWS = new WebSocket("ws://"+profiles[result[0].floID].onionAddr+"/ws");
|
||||
superNodeWS.onopen = function(ev){
|
||||
console.log(`Connected to ${floID}'s SuperNode!`);
|
||||
superNodeWS.send(data);
|
||||
};
|
||||
superNodeWS.onerror = function(ev) {console.log(`${floid}'s SuperNode is offline!`);};
|
||||
superNodeWS.onclose = function(ev) {console.log(`Disconnected from ${floid}'s SuperNode!`);};
|
||||
}).catch(e => {
|
||||
console.log(e.message);
|
||||
});
|
||||
}
|
||||
|
||||
function superNodeMode(data){
|
||||
if(data.reqNewTweets){
|
||||
kBucketObj.determineClosestSupernode(data.floID).then(result => {
|
||||
if(result[0].floID == selfID)
|
||||
SuperNode_sendTweetsFromIDB(data.floID,data.tid,data.requestor);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}else if(data.newSuperNodeTweet){
|
||||
kBucketObj.determineClosestSupernode(data.floID).then(result => {
|
||||
if(result[0].floID == selfID)
|
||||
SuperNode_storeSuperNodeTweet(data.data,data.tid);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}else if(data.viaSuperNodeMsg){
|
||||
kBucketObj.determineClosestSupernode(data.to).then(result => {
|
||||
if(result[0].floID == selfID)
|
||||
SuperNode_storeViaSuperNodeMsg(data.from,data.to,data.data);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}else if(data.viaMsgreq){
|
||||
kBucketObj.determineClosestSupernode(data.floID).then(result => {
|
||||
if(result[0].floID == selfID)
|
||||
SuperNode_sendviaMsgFromIDB(data.floID);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function SuperNode_sendTweetsFromIDB(floID,tid,requestor){
|
||||
return new Promise((resolve,reject) => {
|
||||
var requestorWS = new WebSocket("ws://"+profiles[requestor].onionAddr+"/ws");
|
||||
requestorWS.onopen = (event) => {
|
||||
console.log(`sending ${floID} tweets to ${requestor} Server!`);
|
||||
var idb = indexedDB.open("FLO_Tweet",2);
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onupgradeneeded = (event) => {
|
||||
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
|
||||
objectStore1.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore1.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore1.createIndex('data', 'data', { unique: false });
|
||||
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
|
||||
objectStore2.createIndex('from', 'from', { unique: false });
|
||||
objectStore2.createIndex('to', 'to', { unique: false });
|
||||
objectStore2.createIndex('data', 'data', { unique: false });
|
||||
}
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("superNodeTweet", "readwrite").objectStore("superNodeTweet");
|
||||
var curReq = obs.openCursor();
|
||||
curReq.onsuccess = (event) => {
|
||||
var cursor = event.target.result;
|
||||
if(cursor) {
|
||||
if(cursor.value.floID == floID && cursor.value.tid > tid){
|
||||
data = JSON.stringify({fromSuperNode:true, floID:cursor.value.floID,tid:cursor.value.tid,data:cursor.value.data})
|
||||
requestorWS.send(data);
|
||||
}
|
||||
cursor.continue();
|
||||
}else{
|
||||
resolve("Displayed Tweets from IDB!");
|
||||
}
|
||||
}
|
||||
curReq.onerror = (event) => { reject("Error in Reading tweets from IDB!") }
|
||||
db.close();
|
||||
};
|
||||
};
|
||||
requestorWS.onerror = (event) => { console.log(`${requestor} Server is offline!`) };
|
||||
requestorWS.onclose = (event) => { console.log(`Disconnected from ${requestor} Server!`) };
|
||||
});
|
||||
}
|
||||
|
||||
function SuperNode_storeSuperNodeTweet(data,tid){
|
||||
var idb = indexedDB.open("FLO_Tweet",2);
|
||||
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
|
||||
idb.onupgradeneeded = (event) => {
|
||||
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
|
||||
objectStore1.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore1.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore1.createIndex('data', 'data', { unique: false });
|
||||
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
|
||||
objectStore2.createIndex('from', 'from', { unique: false });
|
||||
objectStore2.createIndex('to', 'to', { unique: false });
|
||||
objectStore2.createIndex('data', 'data', { unique: false });
|
||||
}
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("superNodeTweet", "readwrite").objectStore("superNodeTweet");
|
||||
var parsedData = JSON.parse(data);
|
||||
var tweetID = ''+parsedData.floID+'_'+parsedData.time;
|
||||
obs.add({tweetID:tweetID,floID:parsedData.floID,tid:tid,data:data});
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function SuperNode_storeViaSuperNodeMsg(from,to,data){
|
||||
var idb = indexedDB.open("FLO_Tweet",2);
|
||||
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
|
||||
idb.onupgradeneeded = (event) => {
|
||||
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
|
||||
objectStore1.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore1.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore1.createIndex('data', 'data', { unique: false });
|
||||
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement :true });
|
||||
objectStore2.createIndex('from', 'from', { unique: false });
|
||||
objectStore2.createIndex('to', 'to', { unique: false });
|
||||
objectStore2.createIndex('data', 'data', { unique: false });
|
||||
}
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("viaSuperNodeMsg", "readwrite").objectStore("viaSuperNodeMsg");
|
||||
obs.add({from:from,to:to,data:data});
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function SuperNode_sendviaMsgFromIDB(floID){
|
||||
var receiverWS = new WebSocket("ws://"+profiles[floID].onionAddr+"/ws");
|
||||
receiverWS.onopen = (event) => {
|
||||
var idb = indexedDB.open("FLO_Tweet",2);
|
||||
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
|
||||
idb.onupgradeneeded = (event) => {
|
||||
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
|
||||
objectStore1.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore1.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore1.createIndex('data', 'data', { unique: false });
|
||||
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
|
||||
objectStore2.createIndex('from', 'from', { unique: false });
|
||||
objectStore2.createIndex('to', 'to', { unique: false });
|
||||
objectStore2.createIndex('data', 'data', { unique: false });
|
||||
};
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("viaSuperNodeMsg", "readwrite").objectStore("viaSuperNodeMsg");
|
||||
obs.openCursor().onsuccess = (event) => {
|
||||
var cursor = event.target.result;
|
||||
if(cursor) {
|
||||
if(cursor.value.to == floID){
|
||||
receiverWS.send(cursor.value.data);
|
||||
cursor.delete();
|
||||
}
|
||||
cursor.continue();
|
||||
}else{
|
||||
console.log('Sent All messages to '+floID)
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
};
|
||||
};
|
||||
receiverWS.onerror = (event) => { console.log('Connection Error to '+floID) };
|
||||
receiverWS.onclose = (event) => { console.log('Disconnected from '+floID) };
|
||||
}
|
||||
|
||||
/* ---end of app.js --- */
|
||||
|
||||
/*Kademlia DHT K-bucket implementation as a binary tree.*/
|
||||
|
||||
if (typeof reactor == "undefined" || !reactor) {
|
||||
if (typeof reactor == "undefined" || !reactor) {
|
||||
(function () {
|
||||
|
||||
function Event(name) {
|
||||
@ -317,25 +694,6 @@ reactor.addEventListener('bucket_full', function (someObject) {
|
||||
console.log('Bucket full ' + someObject);
|
||||
});
|
||||
|
||||
/*
|
||||
//Sample Usage
|
||||
//Creating and defining the event
|
||||
reactor.registerEvent('big bang');
|
||||
reactor.addEventListener('big bang', function(someObject){
|
||||
console.log('This is big bang listener yo!'+ someObject.a);
|
||||
});
|
||||
|
||||
//Firing the event
|
||||
reactor.dispatchEvent('big bang');
|
||||
reactor.dispatchEvent('big bang',{a:1});
|
||||
reactor.dispatchEvent('big bang',{a:55});
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//Checking if existing NodeID can be used
|
||||
//This first block of if will initialize the configuration of KBucket
|
||||
//Add Events, Messaging between different K-Buckets, and attach relevant distributed data
|
||||
|
||||
/**
|
||||
* @param {Uint8Array} array1
|
||||
@ -753,7 +1111,7 @@ reactor.dispatchEvent('big bang',{a:55});
|
||||
|
||||
kBucketObj = {
|
||||
|
||||
decodeBase58Address: function (blockchain, address) {
|
||||
decodeBase58Address: function (address) {
|
||||
let k = bitjs.Base58.decode(address)
|
||||
k.shift()
|
||||
k.splice(-4, 4)
|
||||
@ -764,12 +1122,12 @@ kBucketObj = {
|
||||
try {
|
||||
//const master_flo_pubKey = localbitcoinplusplus.master_configurations.masterFLOPubKey;
|
||||
const master_flo_addr = adminID;
|
||||
const SuKBucketId = this.floIdToKbucketId(crypto, master_flo_addr);
|
||||
const SuKBucketId = this.floIdToKbucketId(master_flo_addr);
|
||||
const SukbOptions = { localNodeId: SuKBucketId }
|
||||
supernodeKBucket = new BuildKBucket(SukbOptions);
|
||||
for(var i=0; i<superNodeList.length ; i++){
|
||||
this.addNewUserNodeInKbucket(crypto,superNodeList[i],supernodeKBucket)
|
||||
}
|
||||
var SNArray = Array.from(superNodeList);
|
||||
for(var i=0; i<SNArray.length ; i++)
|
||||
this.addNewUserNodeInKbucket(SNArray[i],supernodeKBucket)
|
||||
resolve('SuperNode KBucket formed');
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
@ -783,7 +1141,7 @@ kBucketObj = {
|
||||
try {
|
||||
let flo_id = bitjs.pubkey2address(pubKey);
|
||||
let kname = `SKBucket_${pubKey}`;
|
||||
const KBucketId = this.floIdToKbucketId(crypto, flo_id)
|
||||
const KBucketId = this.floIdToKbucketId(flo_id)
|
||||
const kbOptions = { localNodeId: KBucketId }
|
||||
window[kname] = new BuildKBucket(kbOptions);
|
||||
resolve(true);
|
||||
@ -800,18 +1158,18 @@ kBucketObj = {
|
||||
};
|
||||
KB.add(contact)
|
||||
},
|
||||
addNewUserNodeInKbucket: function(blockchain, address, KB=supernodeKBucket) {
|
||||
addNewUserNodeInKbucket: function(address, KB=supernodeKBucket) {
|
||||
let decodedId = address;
|
||||
try {
|
||||
decodedId = this.floIdToKbucketId(blockchain, address);
|
||||
decodedId = this.floIdToKbucketId(address);
|
||||
} catch(e) {
|
||||
decodedId = address;
|
||||
}
|
||||
const addNewUserNode = this.addContact(decodedId, address, KB);
|
||||
return {decodedId:decodedId, address:address};
|
||||
},
|
||||
floIdToKbucketId: function (blockchain, address) {
|
||||
const decodedId = this.decodeBase58Address(blockchain, address);
|
||||
floIdToKbucketId: function (address) {
|
||||
const decodedId = this.decodeBase58Address(address);
|
||||
const nodeIdBigInt = new BigInteger(decodedId, 16);
|
||||
const nodeIdBytes = nodeIdBigInt.toByteArrayUnsigned();
|
||||
const nodeIdNewInt8Array = new Uint8Array(nodeIdBytes);
|
||||
@ -835,7 +1193,7 @@ kBucketObj = {
|
||||
let pubKeyBytes = Crypto.util.hexToBytes(pubKey);
|
||||
return Crypto.util.bytesToBase64(pubKeyBytes);
|
||||
},
|
||||
restoreKbucket: function(flo_addr, blockchain="FLO_TEST", KB=KBucket) {
|
||||
restoreKbucket: function(flo_addr, KB=KBucket) {
|
||||
return new Promise((resolve, reject)=>{
|
||||
readAllDB('kBucketStore')
|
||||
.then(dbObject => {
|
||||
@ -846,7 +1204,7 @@ kBucketObj = {
|
||||
dbObject
|
||||
.filter(f=>!su_flo_addr_array.includes(f.data.id))
|
||||
.map(dbObj=>{
|
||||
this.addNewUserNodeInKbucket(blockchain, flo_addr, dbObj.data, KB);
|
||||
this.addNewUserNodeInKbucket(flo_addr, dbObj.data, KB);
|
||||
});
|
||||
} else {
|
||||
reject(`Failed to restore kBucket.`);
|
||||
@ -862,7 +1220,7 @@ kBucketObj = {
|
||||
let supernodeSeedsObj = JSON.parse(supernodeSeeds);
|
||||
|
||||
Object.entries(supernodeSeedsObj).map(seedObj=>{
|
||||
let kbuck = this.addNewUserNodeInKbucket(crypto, seedObj[1].kbucketId,
|
||||
let kbuck = this.addNewUserNodeInKbucket(seedObj[1].kbucketId,
|
||||
{ id: seedObj[1].kbucketId }, supernodeKBucket);
|
||||
});
|
||||
|
||||
@ -940,7 +1298,7 @@ kBucketObj = {
|
||||
}
|
||||
let isFloIdUint8 = flo_addr instanceof Uint8Array;
|
||||
if (!isFloIdUint8) {
|
||||
flo_addr = this.floIdToKbucketId(crypto, flo_addr);
|
||||
flo_addr = this.floIdToKbucketId(flo_addr);
|
||||
}
|
||||
const closestSupernode = supernodeKBucket.closest(flo_addr, n);
|
||||
resolve(closestSupernode);
|
||||
@ -951,49 +1309,5 @@ kBucketObj = {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
addClosestSupernodeInDB: function(flo_addr, KB=KBucket) {
|
||||
return new Promise(async (resolve, reject)=>{
|
||||
const supernodeSeeds = localbitcoinplusplus.master_configurations.supernodeSeeds;
|
||||
if (typeof supernodeSeeds !== "object") reject("Failed to get supernode seeds.");
|
||||
let supernodeSeedsObj = JSON.parse(supernodeSeeds);
|
||||
|
||||
Object.entries(supernodeSeedsObj).map(seedObj=>{
|
||||
console.log(seedObj);
|
||||
this.addNewUserNodeInKbucketAndDB(
|
||||
crypto, seedObj[1].kbucketId,
|
||||
{ id: seedObj[1].kbucketId });
|
||||
});
|
||||
|
||||
let primarySu = await this.determineClosestSupernode(flo_addr);
|
||||
let nearestSupernode = await this.determineClosestSupernode(flo_addr="", n=1, supernodeKBucket, primarySu[0].data.id);
|
||||
let nearestSupernodeIds = nearestSupernode.map(f=>f.data.id);
|
||||
let supernodeSeedsArray = Object.values(supernodeSeedsObj)
|
||||
.filter(seed=>nearestSupernodeIds.includes(seed.kbucketId))
|
||||
.sort(function(a, b){
|
||||
return nearestSupernodeIds.indexOf(a.kbucketId) - nearestSupernodeIds.indexOf(b.kbucketId);
|
||||
});
|
||||
|
||||
if (supernodeSeedsArray.length>0) {
|
||||
resolve(supernodeSeedsArray);
|
||||
} else {
|
||||
reject(false);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function sendDataToSuperNode(floID,data){
|
||||
kBucketObj.determineClosestSupernode(floID).then(result=>{
|
||||
var superNodeWS = new WebSocket("ws://"+profiles[result[0].floID].onionAddr+"/ws");
|
||||
superNodeWS.onopen = function(ev){
|
||||
console.log(`Connected to ${floID}'s SuperNode!`);
|
||||
superNodeWS.send(data);
|
||||
};
|
||||
superNodeWS.onerror = function(ev) {console.log(`${floid}'s SuperNode is offline!`);};
|
||||
superNodeWS.onclose = function(ev) {console.log(`Disconnected from ${floid}'s SuperNode!`);};
|
||||
}).catch(e => {
|
||||
console.log(e.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -8,12 +8,12 @@
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<!-- Font Awesome File -->
|
||||
|
||||
<script type="text/javascript" src="registerID.js"></script>
|
||||
<script type="text/javascript" src="init.js"></script>
|
||||
<script type="text/javascript" src="app.js"></script>
|
||||
<script type="text/javascript" src="home.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload = "userDataStartUp();">
|
||||
<body onload = "viewHome();">
|
||||
|
||||
<div class="navbar navbar-default navbar-static-top">
|
||||
<div class="container">
|
||||
@ -35,10 +35,13 @@
|
||||
<input type="text" class="form-control-nav" id="search" aria-describedby="search1">
|
||||
<span class="glyphicon glyphicon-search form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-default btn-sm" onclick="reloadInitData()">
|
||||
<span class="glyphicon glyphicon-refresh"> </span>
|
||||
</button>
|
||||
<button class="btn btn-default btn-sm" onclick="logout()">
|
||||
<span class="glyphicon glyphicon-log-out"> </span> Log out
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
670
app/web/home.js
670
app/web/home.js
@ -1,317 +1,65 @@
|
||||
var profiles = []
|
||||
var selfID;
|
||||
var profiles, following;
|
||||
var selfWebsocket,followingWebSockets = [];
|
||||
var privKey;
|
||||
var following;
|
||||
var privKey, modSuperNode, selfID;
|
||||
|
||||
function userDataStartUp(){
|
||||
console.log("StartUp");
|
||||
|
||||
/*document.getElementById("sendMsgInput").addEventListener("keyup",function(event){
|
||||
if(event.keyCode === 13){
|
||||
event.preventDefault();
|
||||
sendMsg();
|
||||
}
|
||||
});*/
|
||||
|
||||
getDatafromAPI().then(function (result) {
|
||||
console.log(result);
|
||||
getProfilesfromIDB().then(function (result){
|
||||
profiles = arrayToObject(result);
|
||||
console.log(profiles);
|
||||
sessionStorage.profiles = JSON.stringify(profiles);
|
||||
getSuperNodeListfromIDB().then(function(result){
|
||||
console.log(result)
|
||||
superNodeList = result;
|
||||
sessionStorage.superNodeList = JSON.stringify(superNodeList);
|
||||
kBucketObj.launchKBucket().then(function(result){
|
||||
console.log(result)
|
||||
getuserID().then(function(result){
|
||||
console.log(result);
|
||||
selfID = result;
|
||||
if(superNodeList.includes(selfID))
|
||||
modSuperNode = true;
|
||||
sessionStorage.privKey = JSON.stringify(encrypt.createShamirsSecretShares(privKey,10,10));
|
||||
sessionStorage.selfID = selfID;
|
||||
alert(`${selfID}\nWelcome ${profiles[selfID].name}`)
|
||||
initselfWebSocket();
|
||||
listProfiles();
|
||||
pingSuperNodeforNewMsgs();
|
||||
getFollowinglistFromIDB().then(function(result){
|
||||
following = result;
|
||||
if(!following.includes(selfID))
|
||||
following.push(selfID);
|
||||
console.log(following);
|
||||
displayTweetsFromIDB().then(function(result){
|
||||
connectToAllFollowing();
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
})
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
})
|
||||
}).catch(function (error) {
|
||||
console.log(error.message);
|
||||
});
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
});
|
||||
}).catch(function (error) {
|
||||
console.log(error.message);
|
||||
});
|
||||
}).catch(function (error) {
|
||||
console.log(error.message);
|
||||
});
|
||||
}).catch(function (error) {
|
||||
console.log(error.message);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function storedata(data){
|
||||
return new Promise(
|
||||
function(resolve, reject) {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction('profiles', "readwrite").objectStore('profiles');
|
||||
objectRequest = obs.put(data);
|
||||
objectRequest.onerror = function(event) {
|
||||
reject(Error('Error occured: Unable to store data'));
|
||||
};
|
||||
|
||||
objectRequest.onsuccess = function(event) {
|
||||
resolve('Data saved OK');
|
||||
db.close();
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getDatafromAPI(){
|
||||
return new Promise(
|
||||
function(resolve, reject) {
|
||||
var addr = adminID;
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onupgradeneeded = function(event) {
|
||||
var db = event.target.result;
|
||||
var objectStore0 = event.target.result.createObjectStore("superNodes");
|
||||
var objectStore1 = db.createObjectStore("profiles",{ keyPath: 'floID' });
|
||||
objectStore1.createIndex('onionAddr', 'onionAddr', { unique: false });
|
||||
objectStore1.createIndex('name', 'name', { unique: false });
|
||||
objectStore1.createIndex('pubKey', 'pubKey', { unique: false });
|
||||
var objectStore2 = db.createObjectStore("lastTx");
|
||||
var objectStore3 = db.createObjectStore("tweets",{ keyPath: 'tweetID' });
|
||||
objectStore3.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore3.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore3.createIndex('time', 'time', { unique: false });
|
||||
objectStore3.createIndex('data', 'data', { unique: false });
|
||||
var objectStore4 = db.createObjectStore("lastTweet");
|
||||
var objectStore5 = db.createObjectStore("followers");
|
||||
var objectStore6 = db.createObjectStore("following");
|
||||
var objectStore7 = event.target.result.createObjectStore("messages",{ keyPath: 'msgID' });
|
||||
objectStore7.createIndex('time', 'time', { unique: false });
|
||||
objectStore7.createIndex('text', 'text', { unique: false });
|
||||
objectStore7.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore7.createIndex('type', 'type', { unique: false });
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
//window["wait"] = addrList.length;
|
||||
var lastTx = db.transaction('lastTx', "readwrite").objectStore('lastTx');
|
||||
//addrList.forEach(function(addr){
|
||||
console.log(addr);
|
||||
new Promise(function(res,rej){
|
||||
var lastTxReq = lastTx.get(addr);
|
||||
lastTxReq.onsuccess = function(event){
|
||||
var lasttx = event.target.result;
|
||||
if(lasttx === undefined){
|
||||
lasttx = 0;
|
||||
}
|
||||
res(lasttx);
|
||||
}
|
||||
}).then(function(lasttx){
|
||||
var response = ajax("GET",`api/addrs/${addr}/txs`);
|
||||
var nRequired = JSON.parse(response).totalItems - lasttx;
|
||||
console.log(nRequired);
|
||||
while(true && nRequired){
|
||||
var response = ajax("GET",`api/addrs/${addr}/txs?from=0&to=${nRequired}`);
|
||||
response = JSON.parse(response);
|
||||
if (nRequired + lasttx != response.totalItems ){
|
||||
nRequired = response.totalItems - lasttx;
|
||||
continue;
|
||||
}
|
||||
response.items.reverse().forEach(function(tx){
|
||||
try {
|
||||
if (tx.vin[0].addr == addr){
|
||||
var data = JSON.parse(tx.floData).FLO_Tweet_SuperNode;
|
||||
if(data !== undefined){
|
||||
storeSuperNodeData(data).then(function (response) {
|
||||
}).catch(function (error) {
|
||||
console.log(error.message);
|
||||
});
|
||||
}
|
||||
}else{
|
||||
var data = JSON.parse(tx.floData).FLO_Tweet;
|
||||
if(data !== undefined){
|
||||
if(encrypt.getFLOIDfromPubkeyHex(data.pubKey)!=tx.vin[0].addr)
|
||||
throw("PublicKey doesnot match with floID")
|
||||
data = {floID : tx.vin[0].addr, onionAddr : data.onionAddr, name : data.name, pubKey:data.pubKey};
|
||||
storedata(data).then(function (response) {
|
||||
}).catch(function (error) {
|
||||
console.log(error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
//console.log(e)
|
||||
}
|
||||
});
|
||||
|
||||
var obs = db.transaction('lastTx', "readwrite").objectStore('lastTx');
|
||||
obs.put(response.totalItems,addr);
|
||||
break;
|
||||
}
|
||||
db.close();
|
||||
resolve('retrived data from API');
|
||||
});
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function storeSuperNodeData(data){
|
||||
return new Promise(
|
||||
function(resolve, reject) {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction('superNodes', "readwrite").objectStore('superNodes');
|
||||
if(data.addNodes)
|
||||
for(var i=0; i<data.addNodes.length; i++)
|
||||
obs.add(true,data.addNodes[i])
|
||||
if(data.removeNodes)
|
||||
for(var i=0; i<data.removeNodes.length; i++)
|
||||
obs.delete(data.removeNodes[i])
|
||||
db.close();
|
||||
resolve('Updated superNodes list in IDB');
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getSuperNodeListfromIDB(){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("superNodes", "readwrite").objectStore("superNodes");
|
||||
var getReq = obs.getAllKeys();
|
||||
getReq.onsuccess = function(event){
|
||||
resolve(event.target.result);
|
||||
}
|
||||
getReq.onerror = function(event){
|
||||
reject('Unable to read superNode list!')
|
||||
}
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getuserID(){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
privKey = (sessionStorage.privKey !== undefined ? encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey)):prompt("Enter FLO Private Key : "));
|
||||
var key = new Bitcoin.ECKey(privKey);
|
||||
while(key.priv == null){
|
||||
privKey = prompt("Invalid FLO Private Key! Retry : ")
|
||||
key = Bitcoin.ECKey(privKey);
|
||||
}
|
||||
key.setCompressed(true);
|
||||
var userID = key.getBitcoinAddress();
|
||||
if (profiles[userID] === undefined)
|
||||
var reg = confirm(`${userID} is not registers to FLO Tweet!\nRegister FLO ID to this onion?`);
|
||||
else if (profiles[userID].onionAddr == window.location.host)
|
||||
resolve(userID)
|
||||
else
|
||||
var reg = confirm(`${userID} is registered to another onion!\nChange to this onion?`);
|
||||
|
||||
if(reg){
|
||||
var name = prompt("Enter your name :");
|
||||
var pubKey = key.getPubKeyHex();
|
||||
if(registerID(userID,window.location.host,privKey,pubKey,name)){
|
||||
profiles[userID] = {onionAddr : window.location.host, name : name, pubKey : pubKey};
|
||||
resolve(userID);
|
||||
}
|
||||
}
|
||||
reject(`Unable to bind ${userID} to this onionAddress!\nTry again later!`);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getProfilesfromIDB(){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("profiles", "readwrite").objectStore("profiles");
|
||||
var getReq = obs.getAll();
|
||||
getReq.onsuccess = function(event){
|
||||
resolve(event.target.result);
|
||||
}
|
||||
getReq.onerror = function(event){
|
||||
reject('Unable to read profiles!')
|
||||
}
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
);
|
||||
function viewHome(){
|
||||
if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined || sessionStorage.superNodeList === undefined ){
|
||||
alert("Login credentials failed! Returning to login page!");
|
||||
window.location.href = "index.html";
|
||||
return;
|
||||
}
|
||||
profiles = JSON.parse(sessionStorage.profiles);
|
||||
console.log(profiles);
|
||||
privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey));
|
||||
selfID = sessionStorage.selfID;
|
||||
superNodeList = new Set(JSON.parse(sessionStorage.superNodeList));
|
||||
if(superNodeList.has(selfID)){
|
||||
modSuperNode = true;
|
||||
setInterval(reloadInitData, 3600000);
|
||||
}
|
||||
kBucketObj.launchKBucket().then(result => {
|
||||
console.log(result);
|
||||
initselfWebSocket();
|
||||
listProfiles();
|
||||
pingSuperNodeforNewMsgs();
|
||||
getFollowinglistFromIDB().then(result => {
|
||||
following = result;
|
||||
if(!following.includes(selfID))
|
||||
following.push(selfID);
|
||||
console.log(following);
|
||||
displayTweetsFromIDB().then(result => {
|
||||
connectToAllFollowing();
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function initselfWebSocket(){
|
||||
selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
|
||||
selfWebsocket.onopen = function(evt){
|
||||
selfWebsocket.onopen = (event) => {
|
||||
console.log("Connecting");
|
||||
var pass = (sessionStorage.serverPass !== undefined ? encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass)): prompt("Enter server password :"));
|
||||
selfWebsocket.send("$"+pass);
|
||||
sessionStorage.serverPass = JSON.stringify(encrypt.createShamirsSecretShares(pass,5,5));
|
||||
var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass));
|
||||
selfWebsocket.send("$"+serverPass);
|
||||
};
|
||||
selfWebsocket.onclose = function(evt){
|
||||
selfWebsocket.onclose = (event) => {
|
||||
console.log("DISCONNECTED");
|
||||
initselfWebSocket();
|
||||
};
|
||||
selfWebsocket.onmessage = function(evt){
|
||||
console.log(evt.data);
|
||||
if(evt.data == "$Access Denied!"){
|
||||
var pass = prompt("Access Denied! reEnter server password :");
|
||||
selfWebsocket.send("$"+pass);
|
||||
sessionStorage.serverPass = JSON.stringify(encrypt.createShamirsSecretShares(pass,5,5));
|
||||
}else if(evt.data == "$Access Granted!")
|
||||
alert("Access Granted!")
|
||||
else{
|
||||
try{
|
||||
data = JSON.parse(evt.data);
|
||||
selfWebsocket.onmessage = (event) => {
|
||||
console.log(event.data);
|
||||
if(event.data[0] == '$')
|
||||
return;
|
||||
try{
|
||||
data = JSON.parse(event.data);
|
||||
if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
||||
obs.add(data.sign,data.floID);
|
||||
@ -320,7 +68,7 @@ function initselfWebSocket(){
|
||||
selfWebsocket.send(`F${data.floID}`);
|
||||
}else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
||||
obs.delete(data.floID);
|
||||
@ -339,44 +87,13 @@ function initselfWebSocket(){
|
||||
createTweetElement(data.floID,data.time,data.tweet);
|
||||
}
|
||||
}else if(modSuperNode){
|
||||
if(data.reqNewTweets){
|
||||
kBucketObj.determineClosestSupernode(data.floID).then(result=>{
|
||||
if(result[0].floID == selfID)
|
||||
SuperNode_sendTweetsFromIDB(data.floID,data.tid,data.requestor);
|
||||
}).catch(e => {
|
||||
console.log(e.message);
|
||||
});
|
||||
}else if(data.newSuperNodeTweet){
|
||||
kBucketObj.determineClosestSupernode(data.floID).then(result=>{
|
||||
if(result[0].floID == selfID)
|
||||
SuperNode_storeSuperNodeTweet(data.data,data.tid);
|
||||
}).catch(e => {
|
||||
console.log(e.message);
|
||||
});
|
||||
}else if(data.viaSuperNodeMsg){
|
||||
kBucketObj.determineClosestSupernode(data.to).then(result=>{
|
||||
if(result[0].floID == selfID)
|
||||
SuperNode_storeViaSuperNodeMsg(data.from,data.to,data.data);
|
||||
}).catch(e => {
|
||||
console.log(e.message);
|
||||
});
|
||||
}else if(data.viaMsgreq){
|
||||
kBucketObj.determineClosestSupernode(data.floID).then(result=>{
|
||||
if(result[0].floID == selfID)
|
||||
SuperNode_sendviaMsgFromIDB(data.floID);
|
||||
}).catch(e => {
|
||||
console.log(e.message);
|
||||
});
|
||||
}
|
||||
superNodeMode(data);
|
||||
}
|
||||
}catch(error){
|
||||
console.log(error.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
selfWebsocket.onerror = function(evt){
|
||||
console.log(evt);
|
||||
}catch(error){
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
selfWebsocket.onerror = (event) => { console.log(event) };
|
||||
}
|
||||
|
||||
function listProfiles(){
|
||||
@ -394,7 +111,6 @@ function listProfiles(){
|
||||
</div></a>`
|
||||
profileList.appendChild(element);
|
||||
}
|
||||
//document.getElementById("profileInfo").style.display = "none";
|
||||
}
|
||||
|
||||
function postTweet(){
|
||||
@ -406,98 +122,40 @@ function postTweet(){
|
||||
var data = JSON.stringify({floID:selfID,time:time,tweet:tweet,sign:sign});
|
||||
console.log(data);
|
||||
selfWebsocket.send(data);
|
||||
getLastTweetCount(selfID).then(function(result){
|
||||
sendTweetToSuperNode(data,result+1);
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
getLastTweetCount(selfID).then(result => {
|
||||
var SNdata = JSON.stringify({newSuperNodeTweet:true,floID:selfID,tid:result+1,data:data});
|
||||
sendDataToSuperNode(selfID,SNdata);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function storeTweet(data,tid){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
|
||||
data.tweetID = `${data.time}_${data.floID}`;
|
||||
data.tid = tid;
|
||||
obs.add(data);
|
||||
var obsL = db.transaction("lastTweet", "readwrite").objectStore("lastTweet");
|
||||
obsL.put(tid,data.floID);
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function storeMsg(data){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("messages", "readwrite").objectStore("messages");
|
||||
data.msgID = `${data.time}_${data.floID}`;
|
||||
obs.add(data);
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function sendTweetToSuperNode(data,tid){
|
||||
kBucketObj.determineClosestSupernode(selfID).then(result=>{
|
||||
var superNodeWS = new WebSocket("ws://"+profiles[result[0].floID].onionAddr+"/ws");
|
||||
superNodeWS.onopen = function(ev){
|
||||
console.log(`Connected to self SuperNode!`);
|
||||
data = JSON.stringify({newSuperNodeTweet:true,floID:selfID,tid:tid,data:data})
|
||||
console.log(data)
|
||||
superNodeWS.send(data);
|
||||
};
|
||||
superNodeWS.onerror = function(ev) {console.log(`self SuperNode is offline!`);};
|
||||
superNodeWS.onclose = function(ev) {console.log(`Disconnected from self SuperNode!`);};
|
||||
}).catch(e => {
|
||||
console.log(e.message);
|
||||
});
|
||||
}
|
||||
|
||||
function getFollowinglistFromIDB(){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
return new Promise((resolve,reject) => {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("following", "readwrite").objectStore("following");
|
||||
var getReq = obs.getAllKeys();
|
||||
getReq.onsuccess = function(event){
|
||||
resolve(event.target.result);
|
||||
}
|
||||
getReq.onerror = function(event){
|
||||
reject('Unable to read following list!')
|
||||
}
|
||||
getReq.onsuccess = (event) => { resolve(event.target.result) }
|
||||
getReq.onerror = (event) => { reject('Unable to read following list!') }
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function displayTweetsFromIDB(){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
return new Promise((resolve,reject) => {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
|
||||
var curReq = obs.openCursor();
|
||||
curReq.onsuccess = function(event) {
|
||||
curReq.onsuccess = (event) => {
|
||||
var cursor = event.target.result;
|
||||
if(cursor) {
|
||||
//console.log(cursor.value)
|
||||
if(cursor.value.floID == selfID || following.includes(cursor.value.floID))
|
||||
createTweetElement(cursor.value.floID,cursor.value.time,cursor.value.data);
|
||||
cursor.continue();
|
||||
@ -505,13 +163,10 @@ function displayTweetsFromIDB(){
|
||||
resolve("Displayed Tweets from IDB!");
|
||||
}
|
||||
}
|
||||
curReq.onerror = function(event){
|
||||
reject("Error in Reading tweets from IDB!");
|
||||
}
|
||||
curReq.onerror = (event) => { reject("Error in Reading tweets from IDB!") }
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function createTweetElement(floID,time,tweet){
|
||||
@ -539,27 +194,24 @@ function connectToAllFollowing(){
|
||||
console.log(floid)
|
||||
followingWebSockets[floid] = new WebSocket("ws://"+profiles[floid].onionAddr+"/ws");
|
||||
|
||||
followingWebSockets[floid].onopen = function(ev){
|
||||
followingWebSockets[floid].onopen = (event) => {
|
||||
console.log(`Connected to ${floid} Server!`);
|
||||
getLastTweetCount(floid).then(function(result){
|
||||
getLastTweetCount(floid).then(result => {
|
||||
followingWebSockets[floid].send(`>${result}`);
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
followingWebSockets[floid].onerror = function(ev) {
|
||||
followingWebSockets[floid].onerror = (event) => {
|
||||
console.log(`${floid} Server is offline!`);
|
||||
//Ping SuperNode for any new tweets
|
||||
pingSuperNodeforNewTweets(floid);
|
||||
|
||||
};
|
||||
followingWebSockets[floid].onclose = function(ev) {
|
||||
console.log(`Disconnected from ${floid} Server!`);
|
||||
};
|
||||
followingWebSockets[floid].onmessage = function(evt){
|
||||
console.log(evt.data);
|
||||
followingWebSockets[floid].onclose = (event) => { console.log(`Disconnected from ${floid} Server!`); };
|
||||
followingWebSockets[floid].onmessage = (event) => {
|
||||
console.log(event.data);
|
||||
try{
|
||||
var data = JSON.parse(evt.data);
|
||||
var data = JSON.parse(event.data);
|
||||
var id = data.id;
|
||||
data = data.data;
|
||||
if( floid!=data.floID || !encrypt.verify(data.tweet,data.sign,profiles[floid].pubKey))
|
||||
@ -567,21 +219,20 @@ function connectToAllFollowing(){
|
||||
storeTweet({floID:data.floID,time:data.time,data:data.tweet},id);
|
||||
createTweetElement(data.floID,data.time,data.tweet);
|
||||
}catch(error){
|
||||
console.log(error.message);
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getLastTweetCount(floid){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
return new Promise((resolve,reject) => {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var lastTweet = db.transaction('lastTweet', "readwrite").objectStore('lastTweet');
|
||||
var lastTweetReq = lastTweet.get(floid);
|
||||
lastTweetReq.onsuccess = function(event){
|
||||
lastTweetReq.onsuccess = (event) => {
|
||||
var result = event.target.result;
|
||||
if(result === undefined)
|
||||
result = 0;
|
||||
@ -589,8 +240,7 @@ function getLastTweetCount(floid){
|
||||
}
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function pingSuperNodeforNewMsgs(){
|
||||
@ -599,150 +249,10 @@ function pingSuperNodeforNewMsgs(){
|
||||
}
|
||||
|
||||
function pingSuperNodeforNewTweets(floID){
|
||||
getLastTweetCount(floID).then(function(result){
|
||||
getLastTweetCount(floID).then(result => {
|
||||
var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID})
|
||||
sendDataToSuperNode(floID,data);
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function SuperNode_storeSuperNodeTweet(data,tid){
|
||||
var idb = indexedDB.open("FLO_Tweet",2);
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onupgradeneeded = function(event){
|
||||
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
|
||||
objectStore1.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore1.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore1.createIndex('data', 'data', { unique: false });
|
||||
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
|
||||
objectStore2.createIndex('from', 'from', { unique: false });
|
||||
objectStore2.createIndex('to', 'to', { unique: false });
|
||||
objectStore2.createIndex('data', 'data', { unique: false });
|
||||
}
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("superNodeTweet", "readwrite").objectStore("superNodeTweet");
|
||||
var parsedData = JSON.parse(data);
|
||||
var tweetID = ''+parsedData.floID+'_'+parsedData.time;
|
||||
obs.add({tweetID:tweetID,floID:parsedData.floID,tid:tid,data:data});
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function SuperNode_storeViaSuperNodeMsg(from,to,data){
|
||||
var idb = indexedDB.open("FLO_Tweet",2);
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onupgradeneeded = function(event){
|
||||
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
|
||||
objectStore1.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore1.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore1.createIndex('data', 'data', { unique: false });
|
||||
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement :true });
|
||||
objectStore2.createIndex('from', 'from', { unique: false });
|
||||
objectStore2.createIndex('to', 'to', { unique: false });
|
||||
objectStore2.createIndex('data', 'data', { unique: false });
|
||||
}
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("viaSuperNodeMsg", "readwrite").objectStore("viaSuperNodeMsg");
|
||||
obs.add({from:from,to:to,data:data});
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function SuperNode_sendTweetsFromIDB(floID,tid,requestor){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
var requestorWS = new WebSocket("ws://"+profiles[requestor].onionAddr+"/ws");
|
||||
|
||||
requestorWS.onopen = function(ev){
|
||||
console.log(`sending ${floID} tweets to ${requestor} Server!`);
|
||||
var idb = indexedDB.open("FLO_Tweet",2);
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onupgradeneeded = function(event){
|
||||
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
|
||||
objectStore1.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore1.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore1.createIndex('data', 'data', { unique: false });
|
||||
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
|
||||
objectStore2.createIndex('from', 'from', { unique: false });
|
||||
objectStore2.createIndex('to', 'to', { unique: false });
|
||||
objectStore2.createIndex('data', 'data', { unique: false });
|
||||
}
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("superNodeTweet", "readwrite").objectStore("superNodeTweet");
|
||||
var curReq = obs.openCursor();
|
||||
curReq.onsuccess = function(event) {
|
||||
var cursor = event.target.result;
|
||||
if(cursor) {
|
||||
if(cursor.value.floID == floID && cursor.value.tid > tid){
|
||||
data = JSON.stringify({fromSuperNode:true, floID:cursor.value.floID,tid:cursor.value.tid,data:cursor.value.data})
|
||||
requestorWS.send(data);
|
||||
}
|
||||
cursor.continue();
|
||||
}else{
|
||||
resolve("Displayed Tweets from IDB!");
|
||||
}
|
||||
}
|
||||
curReq.onerror = function(event){
|
||||
reject("Error in Reading tweets from IDB!");
|
||||
}
|
||||
db.close();
|
||||
};
|
||||
};
|
||||
requestorWS.onerror = function(ev) {
|
||||
console.log(`${requestor} Server is offline!`);
|
||||
};
|
||||
requestorWS.onclose = function(ev) {
|
||||
console.log(`Disconnected from ${requestor} Server!`);
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function SuperNode_sendviaMsgFromIDB(floID){
|
||||
var receiverWS = new WebSocket("ws://"+profiles[floID].onionAddr+"/ws");
|
||||
receiverWS.onopen = function(ev){
|
||||
var idb = indexedDB.open("FLO_Tweet",2);
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onupgradeneeded = function(event) {
|
||||
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
|
||||
objectStore1.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore1.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore1.createIndex('data', 'data', { unique: false });
|
||||
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
|
||||
objectStore2.createIndex('from', 'from', { unique: false });
|
||||
objectStore2.createIndex('to', 'to', { unique: false });
|
||||
objectStore2.createIndex('data', 'data', { unique: false });
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("viaSuperNodeMsg", "readwrite").objectStore("viaSuperNodeMsg");
|
||||
obs.openCursor().onsuccess = function(event) {
|
||||
var cursor = event.target.result;
|
||||
if(cursor) {
|
||||
if(cursor.value.to == floID){
|
||||
receiverWS.send(cursor.value.data);
|
||||
cursor.delete();
|
||||
}
|
||||
cursor.continue();
|
||||
}else{
|
||||
console.log('Sent All messages to '+floID)
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
};
|
||||
};
|
||||
receiverWS.onerror = function(ev) { console.log('Connection Error to '+floID) };
|
||||
receiverWS.onclose = function(ev) { console.log('Disconnected from '+floID) };
|
||||
}
|
||||
@ -1,5 +1,146 @@
|
||||
<html>
|
||||
<script type="text/javascript">
|
||||
window.location.href = "home.html";
|
||||
</script>
|
||||
<head>
|
||||
<title>Login</title>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||
|
||||
<style>
|
||||
@charset "utf-8";
|
||||
/* CSS Document */
|
||||
|
||||
h1{
|
||||
margin: 0 auto;
|
||||
padding-left: 15%;
|
||||
text-transform:uppercase;
|
||||
font-size:30px;
|
||||
color:white;
|
||||
}
|
||||
|
||||
|
||||
h2{
|
||||
margin: 0 auto;
|
||||
padding-left: 15%;
|
||||
font-size:18px;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
font-family: Helvetica;
|
||||
margin:0 auto;
|
||||
min-height:100%;
|
||||
background: lightblue;
|
||||
-webkit-background-size: cover;
|
||||
-moz-background-size: cover;
|
||||
-o-background-size: cover;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.nav {
|
||||
margin: 0 auto;
|
||||
margin-top: 100px;
|
||||
margin-left: 35%;
|
||||
width: 300px;
|
||||
height: auto;
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0, .5);
|
||||
|
||||
}
|
||||
|
||||
.input {
|
||||
border: 1px solid #a6a6a6;
|
||||
width: 230px;
|
||||
height: 40px;
|
||||
border-radius: 3px;
|
||||
margin-top: 5px;
|
||||
padding-left: 9px;
|
||||
color: #6c6c6c;
|
||||
background: #fcfcfc;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.input:hover:enabled{
|
||||
box-shadow: 0 0 10px #337AB7;
|
||||
border: 1px #337AB7 solid ;
|
||||
}
|
||||
|
||||
.input:focus, .button:focus, .button:hover:focus{
|
||||
box-shadow: 0 0 10px #337AB7;
|
||||
border: 1px #337AB7 solid ;
|
||||
}
|
||||
|
||||
.button {
|
||||
color:#fff;
|
||||
font-size:20px;
|
||||
border: 1px solid #a6a6a6;
|
||||
width: 243px;
|
||||
height: 43px;
|
||||
border-radius: 5px;
|
||||
margin-top: 5px;
|
||||
margin-right: 6px;
|
||||
outline: none;
|
||||
}
|
||||
.button:disabled,.input:disabled{
|
||||
cursor:not-allowed;
|
||||
}
|
||||
label {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
margin-right: 115px;
|
||||
}
|
||||
label span {
|
||||
margin-left: 5px;
|
||||
font-size:14px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
#alert-container{
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
top:0;
|
||||
z-index: 2;
|
||||
}
|
||||
.alert {
|
||||
padding: 10px;
|
||||
color: white;
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.closebtn {
|
||||
margin-left: 15px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.closebtn:hover {
|
||||
color: black;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="init.js"></script>
|
||||
<script type="text/javascript" src="app.js"></script>
|
||||
<script type="text/javascript" src="login.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="initAPIdata();">
|
||||
<div id="alert-container"></div>
|
||||
<div class="nav">
|
||||
<form id='serverConnect'>
|
||||
<input type="password" id="serverPass" class="input" placeholder="ServerPass" />
|
||||
<input type="button" value="Connect" class="button btn-primary" onclick="connect()"/></br>
|
||||
</form>
|
||||
<form id='userSignIn'>
|
||||
<input type="text" id="username" class="input" placeholder="Username" disabled/>
|
||||
<input type="password" id="privKey" class="input" placeholder="PrivKey" disabled/>
|
||||
<input type="button" value="Sign In" class="button btn-primary" onclick="signIn()" disabled/>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
13418
app/web/registerID.js → app/web/init.js
vendored
Executable file → Normal file
13418
app/web/registerID.js → app/web/init.js
vendored
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
334
app/web/login.js
Normal file
334
app/web/login.js
Normal file
@ -0,0 +1,334 @@
|
||||
if( sessionStorage.profiles && sessionStorage.privKey && sessionStorage.selfID && sessionStorage.serverPass && sessionStorage.superNodeList ){
|
||||
window.location.replace("home.html");
|
||||
}
|
||||
|
||||
const sendAmt = 0.001 ;
|
||||
const fee = 0.0005;
|
||||
var username,privKey,floID;
|
||||
var profiles;
|
||||
|
||||
function initAPIdata(){
|
||||
return new Promise((resolve,reject) => {
|
||||
console.log("initAPIdata");
|
||||
getDatafromAPI().then(result => {
|
||||
console.log(result);
|
||||
getProfilesfromIDB().then(result => {
|
||||
profiles = arrayToObject(result);
|
||||
console.log(profiles);
|
||||
sessionStorage.profiles = JSON.stringify(profiles);
|
||||
getSuperNodeListfromIDB().then(result => {
|
||||
console.log(result)
|
||||
superNodeList = new Set(result);
|
||||
sessionStorage.superNodeList = JSON.stringify(Array.from(superNodeList));
|
||||
resolve('Refresh API data Successful!')
|
||||
}).catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
}).catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
}).catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function customAlert(msg,type){
|
||||
color = {info:"#2196F3",danger:"#f44336",warning:"#ff9800",success:"#4CAF50"};
|
||||
var alertBox = document.createElement('div');
|
||||
alertBox.setAttribute('class','alert');
|
||||
alertBox.style.backgroundColor = color[type];
|
||||
alertBox.innerHTML = `<span class="closebtn" onclick="this.parentElement.style.display='none';">✖</span>
|
||||
${msg}`;
|
||||
document.getElementById("alert-container").appendChild(alertBox);
|
||||
}
|
||||
|
||||
function disableForm(formId, disableFlag) {
|
||||
var form = document.getElementById(formId);
|
||||
for(var i=0; i<form.length; i++)
|
||||
form[i].disabled = disableFlag;
|
||||
}
|
||||
|
||||
function connect(){
|
||||
document.getElementById("alert-container").innerHTML = '';
|
||||
var serverPass = document.getElementById('serverPass').value;
|
||||
initselfWebSocket(serverPass).then(result => {
|
||||
sessionStorage.serverPass = JSON.stringify(encrypt.createShamirsSecretShares(serverPass,10,10));
|
||||
customAlert(result,'success');
|
||||
disableForm('serverConnect',true);
|
||||
disableForm('userSignIn',false);
|
||||
}).catch(error => {
|
||||
customAlert(error,'danger');
|
||||
});
|
||||
}
|
||||
|
||||
function signIn(){
|
||||
document.getElementById("alert-container").innerHTML = '';
|
||||
username = document.getElementById('username').value;
|
||||
privKey = document.getElementById('privKey').value;
|
||||
var key = new Bitcoin.ECKey(privKey);
|
||||
if(key.priv == null){
|
||||
customAlert("Invalid FLO Private Key!",'danger');
|
||||
return false;
|
||||
}
|
||||
key.setCompressed(true);
|
||||
floID = key.getBitcoinAddress();
|
||||
try{
|
||||
console.log(floID)
|
||||
if (profiles[floID] === undefined)
|
||||
throw `${floID} is not registers to FLO Tweet!<br/>Register FLO ID to this onion?`;
|
||||
if (profiles[floID].onionAddr != window.location.host)
|
||||
throw `${floID} is registered to another onion!<br/>Change to this onion?`;
|
||||
if (profiles[floID].name != username)
|
||||
throw `${floID} is registered to another username!<br/>Change username?`;
|
||||
login();
|
||||
}catch(msg){
|
||||
console.log(msg)
|
||||
customAlert(`${msg}<span class="closebtn" onclick="this.parentElement.parentElement.style.display='none'; signUp();">✔</span>`,'warning');
|
||||
}
|
||||
}
|
||||
|
||||
function login(){
|
||||
sessionStorage.privKey = JSON.stringify(encrypt.createShamirsSecretShares(privKey,10,10));
|
||||
sessionStorage.selfID = floID;
|
||||
disableForm('userSignIn',true);
|
||||
customAlert(`Welcome ${username}`,'info');
|
||||
setTimeout(window.location.replace("home.html"), 3000);
|
||||
}
|
||||
|
||||
function signUp(){
|
||||
registerID(floID,window.location.host,privKey,privKey.getPubKeyHex(),username).then(result =>{
|
||||
customAlert(`Registration Successful!<br/> txid : ${result}`,'success');
|
||||
refreshAPIdata().then(result => {
|
||||
console.log(result);
|
||||
login();
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(error => {
|
||||
customAlert(error,'danger');
|
||||
});
|
||||
}
|
||||
|
||||
function ajax(method, uri){
|
||||
var request = new XMLHttpRequest();
|
||||
var url = `${api_url}/${uri}`
|
||||
console.log(url)
|
||||
var result;
|
||||
request.open(method,url , false);
|
||||
request.onload = function () {
|
||||
if (request.readyState == 4 && request.status == 200)
|
||||
result = this.response;
|
||||
else {
|
||||
console.log('error');
|
||||
result = false;
|
||||
}
|
||||
};
|
||||
request.send();
|
||||
console.log(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function getDatafromAPI(){
|
||||
return new Promise((resolve,reject) => {
|
||||
var addr = adminID;
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onupgradeneeded = (event) => {
|
||||
var db = event.target.result;
|
||||
var objectStore0 = event.target.result.createObjectStore("superNodes");
|
||||
var objectStore1 = db.createObjectStore("profiles",{ keyPath: 'floID' });
|
||||
objectStore1.createIndex('onionAddr', 'onionAddr', { unique: false });
|
||||
objectStore1.createIndex('name', 'name', { unique: false });
|
||||
objectStore1.createIndex('pubKey', 'pubKey', { unique: false });
|
||||
var objectStore2 = db.createObjectStore("lastTx");
|
||||
var objectStore3 = db.createObjectStore("tweets",{ keyPath: 'tweetID' });
|
||||
objectStore3.createIndex('tid', 'tid', { unique: false });
|
||||
objectStore3.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore3.createIndex('time', 'time', { unique: false });
|
||||
objectStore3.createIndex('data', 'data', { unique: false });
|
||||
var objectStore4 = db.createObjectStore("lastTweet");
|
||||
var objectStore5 = db.createObjectStore("followers");
|
||||
var objectStore6 = db.createObjectStore("following");
|
||||
var objectStore7 = event.target.result.createObjectStore("messages",{ keyPath: 'msgID' });
|
||||
objectStore7.createIndex('time', 'time', { unique: false });
|
||||
objectStore7.createIndex('text', 'text', { unique: false });
|
||||
objectStore7.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore7.createIndex('type', 'type', { unique: false });
|
||||
};
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var lastTx = db.transaction('lastTx', "readwrite").objectStore('lastTx');
|
||||
console.log(addr);
|
||||
new Promise((res,rej) => {
|
||||
var lastTxReq = lastTx.get(addr);
|
||||
lastTxReq.onsuccess = (event) => {
|
||||
var lasttx = event.target.result;
|
||||
if(lasttx === undefined){
|
||||
lasttx = 0;
|
||||
}
|
||||
res(lasttx);
|
||||
}
|
||||
}).then(lasttx => {
|
||||
var response = ajax("GET",`api/addrs/${addr}/txs`);
|
||||
var nRequired = JSON.parse(response).totalItems - lasttx;
|
||||
console.log(nRequired);
|
||||
while(true && nRequired){
|
||||
var response = ajax("GET",`api/addrs/${addr}/txs?from=0&to=${nRequired}`);
|
||||
response = JSON.parse(response);
|
||||
if (nRequired + lasttx != response.totalItems ){
|
||||
nRequired = response.totalItems - lasttx;
|
||||
continue;
|
||||
}
|
||||
response.items.reverse().forEach(tx => {
|
||||
try {
|
||||
if (tx.vin[0].addr == addr){
|
||||
var data = JSON.parse(tx.floData).FLO_Tweet_SuperNode;
|
||||
if(data !== undefined){
|
||||
storeSuperNodeData(data).then(function (response) {
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}else{
|
||||
var data = JSON.parse(tx.floData).FLO_Tweet;
|
||||
if(data !== undefined){
|
||||
if(encrypt.getFLOIDfromPubkeyHex(data.pubKey)!=tx.vin[0].addr)
|
||||
throw("PublicKey doesnot match with floID")
|
||||
data = {floID : tx.vin[0].addr, onionAddr : data.onionAddr, name : data.name, pubKey:data.pubKey};
|
||||
storeProfile(data).then(function (response) {
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
//console.log(error)
|
||||
}
|
||||
});
|
||||
var obs = db.transaction('lastTx', "readwrite").objectStore('lastTx');
|
||||
obs.put(response.totalItems,addr);
|
||||
break;
|
||||
}
|
||||
db.close();
|
||||
resolve('retrived data from API');
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getProfilesfromIDB(){
|
||||
return new Promise((resolve,reject) => {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("profiles", "readwrite").objectStore("profiles");
|
||||
var getReq = obs.getAll();
|
||||
getReq.onsuccess = (event) => { resolve(event.target.result) }
|
||||
getReq.onerror = (event) => { reject('Unable to read profiles!') }
|
||||
db.close();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function getSuperNodeListfromIDB(){
|
||||
return new Promise((resolve,reject) => {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("superNodes", "readwrite").objectStore("superNodes");
|
||||
var getReq = obs.getAllKeys();
|
||||
getReq.onsuccess = (event) => { resolve(event.target.result) }
|
||||
getReq.onerror = (event) => { reject('Unable to read superNode list!') }
|
||||
db.close();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function initselfWebSocket(serverPass){
|
||||
return new Promise((resolve,reject) => {
|
||||
selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
|
||||
selfWebsocket.onopen = (event) => {
|
||||
console.log("Connecting");
|
||||
selfWebsocket.send("$"+serverPass);
|
||||
};
|
||||
selfWebsocket.onclose = (event) => { console.log("DISCONNECTED") };
|
||||
selfWebsocket.onmessage = (event) => {
|
||||
console.log(event.data);
|
||||
if(event.data == "$Access Denied!")
|
||||
reject("Access Denied!");
|
||||
else if(event.data == "$Access Granted!")
|
||||
resolve("Access Granted!");
|
||||
};
|
||||
selfWebsocket.onerror = (event) => { console.log(event) };
|
||||
});
|
||||
}
|
||||
|
||||
function registerID(sender,onionAddr,wif,pubkey,username) {
|
||||
return new Promise((resolve,reject) => {
|
||||
var trx = bitjs.transaction();
|
||||
var utxoAmt = 0.0;
|
||||
var x = sendAmt+fee;
|
||||
var response = ajax("GET",`api/addr/${sender}/utxo`);
|
||||
var utxos = JSON.parse(response);
|
||||
for(var x = utxos.length-1; x >= 0; x--){
|
||||
if(utxoAmt < sendAmt+fee){
|
||||
trx.addinput(utxos[x].txid, utxos[x].vout, utxos[x].scriptPubKey);
|
||||
utxoAmt += utxos[x].amount;
|
||||
}else
|
||||
break;
|
||||
}
|
||||
console.log(utxoAmt+":"+(sendAmt+fee));
|
||||
if(utxoAmt < sendAmt+fee)
|
||||
reject("Insufficient balance!");
|
||||
trx.addoutput(adminID, sendAmt);
|
||||
console.log(adminID+":"+ sendAmt);
|
||||
var change = utxoAmt-sendAmt-fee;
|
||||
if(change>0)
|
||||
trx.addoutput(sender, change);
|
||||
console.log(sender+":"+ change);
|
||||
var key = new Bitcoin.ECKey(wif);
|
||||
var sendFloData = JSON.stringify({FLO_Tweet:{onionAddr:onionAddr, name: username, pubKey: pubkey}});;
|
||||
trx.addflodata(sendFloData);
|
||||
console.log(sendFloData);
|
||||
var signedTxHash = trx.sign(wif, 1);
|
||||
console.log(signedTxHash);
|
||||
var txid = broadcastTx(signedTxHash);
|
||||
if (txid)
|
||||
resolve(txid);
|
||||
else
|
||||
reject('Registration Unsuccessful!')
|
||||
});
|
||||
}
|
||||
|
||||
function broadcastTx(signedTxHash) {
|
||||
var http = new XMLHttpRequest();
|
||||
var url = `${api_url}/api/tx/send`;
|
||||
if (signedTxHash.length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var params = `{"rawtx":"${signedTxHash}"}`;
|
||||
var result;
|
||||
http.open('POST', url, false);
|
||||
|
||||
//Send the proper header information along with the request
|
||||
http.setRequestHeader('Content-type', 'application/json');
|
||||
|
||||
http.onreadystatechange = function () { //Call a function when the state changes.
|
||||
if (http.readyState == 4 && http.status == 200) {
|
||||
console.log(http.response);
|
||||
var txid = JSON.parse(http.response).txid.result;
|
||||
console.log("Transaction successful! txid : " + txid);
|
||||
result = txid;
|
||||
} else {
|
||||
console.log(http.responseText);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
http.send(params);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<!-- Font Awesome File -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
|
||||
<script type="text/javascript" src="registerID.js"></script>
|
||||
<script type="text/javascript" src="init.js"></script>
|
||||
<script type="text/javascript" src="app.js"></script>
|
||||
<script type="text/javascript" src="msg.js"></script>
|
||||
|
||||
|
||||
110
app/web/msg.js
110
app/web/msg.js
@ -1,33 +1,37 @@
|
||||
var profiles;
|
||||
var receiverID,selfID,privKey;
|
||||
var receiverID,selfID,privKey,modSuperNode;
|
||||
var selfwebsocket,receiverWebSocket,recStat;
|
||||
|
||||
function initMsgs(){
|
||||
if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined){
|
||||
alert("Login credentials failed! Returning to home page!");
|
||||
window.location.href = "home.html";
|
||||
if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined || sessionStorage.superNodeList === undefined ){
|
||||
alert("Login credentials failed! Returning to login page!");
|
||||
window.location.href = "index.html";
|
||||
return;
|
||||
}
|
||||
profiles = JSON.parse(sessionStorage.profiles);
|
||||
console.log(profiles);
|
||||
privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey));
|
||||
selfID = sessionStorage.selfID;
|
||||
superNodeList = JSON.parse(sessionStorage.superNodeList);
|
||||
kBucketObj.launchKBucket().then(function(result){
|
||||
superNodeList = new Set(JSON.parse(sessionStorage.superNodeList));
|
||||
if(superNodeList.has(selfID)){
|
||||
modSuperNode = true;
|
||||
setInterval(reloadInitData, 3600000);
|
||||
}
|
||||
kBucketObj.launchKBucket().then(result => {
|
||||
console.log(result)
|
||||
initselfWebSocket();
|
||||
readMsgfromIDB().then(function(result){
|
||||
readMsgfromIDB().then(result => {
|
||||
listProfiles();
|
||||
document.getElementById("sendMsgInput").addEventListener("keyup",function(event){
|
||||
document.getElementById("sendMsgInput").addEventListener("keyup",(event) => {
|
||||
if(event.keyCode === 13){
|
||||
event.preventDefault();
|
||||
sendMsg();
|
||||
}
|
||||
});
|
||||
}).catch(function(error){
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(function(error){
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
@ -42,32 +46,33 @@ function listProfiles(){
|
||||
var element = document.createElement("div");
|
||||
element.setAttribute("class", "media");
|
||||
element.innerHTML = `<a href="javascript:changeReceiver('${p}');"><div class="media-body">
|
||||
<h5 class="media-heading">${profiles[p].name}</h5>
|
||||
<small>@${p}</small>
|
||||
</div></a>`
|
||||
<h5 class="media-heading">${profiles[p].name}</h5>
|
||||
<small>@${p}</small>
|
||||
</div></a>`
|
||||
profileList.appendChild(element);
|
||||
}
|
||||
}
|
||||
|
||||
function initselfWebSocket(){
|
||||
selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
|
||||
selfWebsocket.onopen = function(evt){
|
||||
selfWebsocket.onopen = (event) => {
|
||||
console.log("Connecting");
|
||||
var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass));
|
||||
selfWebsocket.send("$"+serverPass);
|
||||
};
|
||||
selfWebsocket.onclose = function(evt){
|
||||
selfWebsocket.onclose = (event) => {
|
||||
console.log("DISCONNECTED");
|
||||
initselfWebSocket();
|
||||
};
|
||||
selfWebsocket.onmessage = function(evt){
|
||||
console.log(evt.data);
|
||||
if(evt.data[0] == '$')
|
||||
selfWebsocket.onmessage = (event) => {
|
||||
console.log(event.data);
|
||||
if(event.data[0] == '$')
|
||||
return;
|
||||
try{
|
||||
data = JSON.parse(evt.data);
|
||||
data = JSON.parse(event.data);
|
||||
if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
||||
obs.add(data.sign,data.floID);
|
||||
@ -76,7 +81,7 @@ function initselfWebSocket(){
|
||||
selfWebsocket.send(`F${data.floID}-${data.sign}`);
|
||||
}else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
||||
obs.delete(data.floID);
|
||||
@ -89,19 +94,18 @@ function initselfWebSocket(){
|
||||
createMsgElement(data.from,data.time,msg,'R')
|
||||
storeMsg({time:data.time,floID:data.from,text:msg,type:'R'});
|
||||
}
|
||||
}else if(modSuperNode){
|
||||
superNodeMode(data);
|
||||
}
|
||||
}catch(error){
|
||||
console.log(error.message)
|
||||
console.log(error)
|
||||
}
|
||||
};
|
||||
selfWebsocket.onerror = function(evt){
|
||||
console.log(evt);
|
||||
};
|
||||
selfWebsocket.onerror = (event) => { console.log(event) };
|
||||
}
|
||||
|
||||
function readMsgfromIDB(){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
return new Promise((resolve,reject) => {
|
||||
var disp = document.getElementById("msgsContainer");
|
||||
for(floID in profiles){
|
||||
var element = document.createElement('div');
|
||||
@ -110,13 +114,11 @@ function readMsgfromIDB(){
|
||||
disp.appendChild(element);
|
||||
}
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("messages", "readwrite").objectStore("messages");
|
||||
obs.openCursor().onsuccess = function(event) {
|
||||
obs.openCursor().onsuccess = (event) => {
|
||||
var cursor = event.target.result;
|
||||
if(cursor) {
|
||||
createMsgElement(cursor.value.floID,cursor.value.time,cursor.value.text,cursor.value.type);
|
||||
@ -128,8 +130,7 @@ function readMsgfromIDB(){
|
||||
};
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function changeReceiver(floID){
|
||||
@ -148,9 +149,9 @@ function changeReceiver(floID){
|
||||
document.getElementById(receiverID).style.display = 'block';
|
||||
try{
|
||||
receiverWebSocket = new WebSocket("ws://"+profiles[receiverID].onionAddr+"/ws");
|
||||
receiverWebSocket.onopen = function(ev){ recStat = true; };
|
||||
receiverWebSocket.onerror = function(ev) { recStat = false;};
|
||||
receiverWebSocket.onclose = function(ev) { recStat = false; };
|
||||
receiverWebSocket.onopen = (event) => { recStat = true; };
|
||||
receiverWebSocket.onerror = (event) => { recStat = false;};
|
||||
receiverWebSocket.onclose = (event) => { recStat = false; };
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
@ -161,23 +162,22 @@ function sendMsg(){
|
||||
alert("Select a contact and send message");
|
||||
return;
|
||||
}
|
||||
var inp = document.getElementById('sendMsgInput')
|
||||
var msg = inp.value
|
||||
inp.value = ""
|
||||
console.log(msg)
|
||||
var time = Date.now()
|
||||
var sign = encrypt.sign(msg,privKey)
|
||||
var msgEncrypt = encrypt.encryptMessage(msg,profiles[receiverID].pubKey)
|
||||
var inp = document.getElementById('sendMsgInput');
|
||||
var msg = inp.value;
|
||||
inp.value = "";
|
||||
console.log(msg);
|
||||
var time = Date.now();
|
||||
var sign = encrypt.sign(msg,privKey);
|
||||
var msgEncrypt = encrypt.encryptMessage(msg,profiles[receiverID].pubKey);
|
||||
var data = JSON.stringify({message:true,from:selfID,to:receiverID,time:time,secret:msgEncrypt.secret,sign:sign,pubVal:msgEncrypt.senderPublicKeyString});
|
||||
|
||||
if(recStat)
|
||||
receiverWebSocket.send(data);
|
||||
else{
|
||||
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:receiverID,data:data})
|
||||
sendDataToSuperNode(receiverID,SNdata)
|
||||
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:receiverID,data:data});
|
||||
sendDataToSuperNode(receiverID,SNdata);
|
||||
}
|
||||
console.log(`sentMsg : ${data}`);
|
||||
createMsgElement(receiverID,time,msg,'S')
|
||||
createMsgElement(receiverID,time,msg,'S');
|
||||
storeMsg({time:time,floID:receiverID,text:msg,type:'S'});
|
||||
}
|
||||
|
||||
@ -194,17 +194,3 @@ function createMsgElement(floID,time,msg,type){
|
||||
</div>`;
|
||||
msgField.appendChild(element);
|
||||
}
|
||||
|
||||
function storeMsg(data){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("messages", "readwrite").objectStore("messages");
|
||||
data.msgID = `${data.time}_${data.floID}`;
|
||||
obs.add(data);
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<!-- Font Awesome File -->
|
||||
|
||||
<script type="text/javascript" src="registerID.js"></script>
|
||||
<script type="text/javascript" src="init.js"></script>
|
||||
<script type="text/javascript" src="app.js"></script>
|
||||
<script type="text/javascript" src="profile.js"></script>
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
|
||||
var profileWebsocket, selfWebsocket,profileServerStatus;
|
||||
var profiles;
|
||||
var profileID, privKey, selfID;
|
||||
var profileID, privKey, selfID, modSuperNode;
|
||||
|
||||
function viewProfile(){
|
||||
if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined){
|
||||
alert("Login credentials failed! Returning to home page!");
|
||||
window.location.href = "home.html";
|
||||
if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined || sessionStorage.superNodeList === undefined ){
|
||||
alert("Login credentials failed! Returning to login page!");
|
||||
window.location.href = "index.html";
|
||||
return;
|
||||
}
|
||||
profiles = JSON.parse(sessionStorage.profiles);
|
||||
@ -15,13 +15,17 @@ function viewProfile(){
|
||||
selfID = sessionStorage.selfID;
|
||||
var url = new URL(window.location.href);
|
||||
profileID = url.searchParams.get("floID");
|
||||
superNodeList = JSON.parse(sessionStorage.superNodeList);
|
||||
kBucketObj.launchKBucket().then(function(result){
|
||||
superNodeList = new Set(JSON.parse(sessionStorage.superNodeList));
|
||||
if(superNodeList.has(selfID)){
|
||||
modSuperNode = true;
|
||||
setInterval(reloadInitData, 3600000);
|
||||
}
|
||||
kBucketObj.launchKBucket().then(result => {
|
||||
console.log(result)
|
||||
listProfiles();
|
||||
displayProfile(profileID);
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
@ -30,7 +34,7 @@ function displayProfile(profileID){
|
||||
var errorMsg;
|
||||
if(!profileID)
|
||||
errorMsg = "Select a Profile to display";
|
||||
else if(!validateAddr(profileID))
|
||||
else if(!encrypt.validateAddr(profileID))
|
||||
errorMsg = "Invalid FLO ID";
|
||||
else if(!(profileID in profiles))
|
||||
errorMsg = "FLO ID not registered to FLO Tweet";
|
||||
@ -44,32 +48,29 @@ function displayProfile(profileID){
|
||||
document.getElementById("profileName").innerHTML=profiles[profileID].name;
|
||||
document.getElementById("profileFloID").innerHTML='@'+profileID;
|
||||
initselfWebSocket();
|
||||
displayTweetFromIDB(profileID).then(function(result){
|
||||
connectToX(profileID).then(function(result){
|
||||
displayTweetFromIDB(profileID).then(result => {
|
||||
connectToProfileServer(profileID).then(result => {
|
||||
console.log(result);
|
||||
profileServerStatus = true;
|
||||
getTweetsFromX(profileID);
|
||||
}).catch(function(error){
|
||||
pingProfileServerforNewTweets(profileID);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
pingSuperNodeforNewTweets(profileID);
|
||||
profileServerStatus = false;
|
||||
});
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function displayTweetFromIDB(floID){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
return new Promise((resolve,reject) => {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obj = db.transaction("following", "readwrite").objectStore("following");
|
||||
obj.get(floID).onsuccess = function (event) {
|
||||
obj.get(floID).onsuccess = (event) => {
|
||||
var followBtn = document.getElementById("follow-button");
|
||||
if(event.target.result === undefined){
|
||||
followBtn.innerHTML = "+ Follow";
|
||||
@ -81,7 +82,7 @@ function displayTweetFromIDB(floID){
|
||||
followBtn.disabled = false;
|
||||
}
|
||||
var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
|
||||
obs.openCursor().onsuccess = function(event) {
|
||||
obs.openCursor().onsuccess = (event) => {
|
||||
var cursor = event.target.result;
|
||||
if(cursor) {
|
||||
//console.log(cursor.value)
|
||||
@ -94,8 +95,7 @@ function displayTweetFromIDB(floID){
|
||||
}
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function listProfiles(){
|
||||
@ -111,7 +111,6 @@ function listProfiles(){
|
||||
</div></a>`
|
||||
profileList.appendChild(element);
|
||||
}
|
||||
//document.getElementById("profileInfo").style.display = "none";
|
||||
}
|
||||
|
||||
function createTweetElement(floID,time,tweet){
|
||||
@ -133,23 +132,16 @@ function createTweetElement(floID,time,tweet){
|
||||
tweetDisplay.insertBefore(element, tweetDisplay.firstChild);
|
||||
}
|
||||
|
||||
function connectToX(floID){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
function connectToProfileServer(floID){
|
||||
return new Promise((resolve,reject) => {
|
||||
profileWebsocket = new WebSocket("ws://"+profiles[floID].onionAddr+"/ws");
|
||||
profileWebsocket.onopen = function(ev){
|
||||
resolve("Connected to Profile Server!");
|
||||
};
|
||||
profileWebsocket.onerror = function(ev) {
|
||||
reject("Profile Server is offline!");
|
||||
};
|
||||
profileWebsocket.onclose = function(ev) {
|
||||
console.log("Disconnected from Profile Server!")
|
||||
};
|
||||
profileWebsocket.onmessage = function(evt){
|
||||
console.log(evt.data);
|
||||
profileWebsocket.onopen = (event) => { resolve("Connected to Profile Server!") };
|
||||
profileWebsocket.onerror = (event) => { reject("Profile Server is offline!") };
|
||||
profileWebsocket.onclose = (event) => { console.log("Disconnected from Profile Server!") };
|
||||
profileWebsocket.onmessage = (event) => {
|
||||
console.log(event.data);
|
||||
try{
|
||||
var data = JSON.parse(evt.data);
|
||||
var data = JSON.parse(event.data);
|
||||
var id = data.id;
|
||||
data = data.data;
|
||||
if( floID!=data.floID || !encrypt.verify(data.tweet,data.sign,profiles[floID].pubKey))
|
||||
@ -157,76 +149,41 @@ function connectToX(floID){
|
||||
storeTweet({floID:floID,time:data.time,data:data.tweet},id);
|
||||
createTweetElement(floID,data.time,data.tweet);
|
||||
}catch(error){
|
||||
console.log(error.message);
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function storeTweet(data,id){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
|
||||
data.tweetID = `${data.time}_${data.floID}`;
|
||||
obs.add(data);
|
||||
var obsL = db.transaction("lastTweet", "readwrite").objectStore("lastTweet");
|
||||
obsL.put(id,data.floID);
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function storeMsg(data){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("messages", "readwrite").objectStore("messages");
|
||||
data.msgID = `${data.time}_${data.floID}`;
|
||||
obs.add(data);
|
||||
db.close();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function pingSuperNodeforNewTweets(floID){
|
||||
getLastTweetCount(floID).then(function(result){
|
||||
var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID})
|
||||
sendDataToSuperNode(floID,data);
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
});
|
||||
getLastTweetCount(floID).then(result => {
|
||||
var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID})
|
||||
sendDataToSuperNode(floID,data);
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function getTweetsFromX(floID){
|
||||
return new Promise(
|
||||
function (resolve,reject){
|
||||
getLastTweetCount(floID).then(function(result){
|
||||
console.log(profileWebsocket);
|
||||
profileWebsocket.send(`>${result}`);
|
||||
console.log("sent");
|
||||
resolve('Sent New tweet request to user server!');
|
||||
}).catch(function(error){
|
||||
console.log(error.message);
|
||||
});
|
||||
}
|
||||
);
|
||||
function pingProfileServerforNewTweets(floID){
|
||||
getLastTweetCount(floID).then(result => {
|
||||
console.log(profileWebsocket);
|
||||
profileWebsocket.send(`>${result}`);
|
||||
console.log("Sent New tweet request to user server!");
|
||||
//resolve('Sent New tweet request to user server!');
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function getLastTweetCount(floid){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
return new Promise((resolve,reject) => {
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var lastTweet = db.transaction('lastTweet', "readwrite").objectStore('lastTweet');
|
||||
var lastTweetReq = lastTweet.get(floid);
|
||||
lastTweetReq.onsuccess = function(event){
|
||||
lastTweetReq.onsuccess = (event) => {
|
||||
var result = event.target.result;
|
||||
if(result === undefined)
|
||||
result = 0;
|
||||
@ -234,29 +191,29 @@ function getLastTweetCount(floid){
|
||||
}
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function initselfWebSocket(){
|
||||
selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
|
||||
selfWebsocket.onopen = function(evt){
|
||||
selfWebsocket.onopen = (event) => {
|
||||
console.log("Connecting");
|
||||
var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass));
|
||||
selfWebsocket.send("$"+serverPass);
|
||||
};
|
||||
selfWebsocket.onclose = function(evt){
|
||||
selfWebsocket.onclose = (event) => {
|
||||
console.log("DISCONNECTED");
|
||||
initselfWebSocket();
|
||||
};
|
||||
selfWebsocket.onmessage = function(evt){
|
||||
console.log(evt.data);
|
||||
if(evt.data[0] == '$')
|
||||
selfWebsocket.onmessage = (event) => {
|
||||
console.log(event.data);
|
||||
if(event.data[0] == '$')
|
||||
return;
|
||||
try{
|
||||
data = JSON.parse(evt.data);
|
||||
data = JSON.parse(event.data);
|
||||
if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
||||
obs.add(data.sign,data.floID);
|
||||
@ -265,7 +222,7 @@ function initselfWebSocket(){
|
||||
selfWebsocket.send(`F${data.floID}-${data.sign}`);
|
||||
}else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
||||
obs.delete(data.floID);
|
||||
@ -283,14 +240,14 @@ function initselfWebSocket(){
|
||||
storeTweet({floID:data.floID,time:data.time,data:data.tweet},tid);
|
||||
createTweetElement(data.floID,data.time,data.tweet);
|
||||
}
|
||||
}else if(modSuperNode){
|
||||
superNodeMode(data);
|
||||
}
|
||||
}catch(error){
|
||||
console.log(error.message)
|
||||
console.log(error)
|
||||
}
|
||||
};
|
||||
selfWebsocket.onerror = function(evt){
|
||||
console.log(evt);
|
||||
};
|
||||
selfWebsocket.onerror = (event) => { console.log(event) };
|
||||
}
|
||||
|
||||
function follow(){
|
||||
@ -301,12 +258,12 @@ function follow(){
|
||||
if(profileServerStatus)
|
||||
profileWebsocket.send(data);
|
||||
else{
|
||||
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data})
|
||||
sendDataToSuperNode(profileID,SNdata)
|
||||
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data});
|
||||
sendDataToSuperNode(profileID,SNdata);
|
||||
}
|
||||
selfWebsocket.send(`f${profileID}-${sign}`)
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("following", "readwrite").objectStore("following");
|
||||
obs.add(sign,profileID);
|
||||
@ -321,12 +278,12 @@ function follow(){
|
||||
if(profileServerStatus)
|
||||
profileWebsocket.send(data);
|
||||
else{
|
||||
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data})
|
||||
sendDataToSuperNode(profileID,SNdata)
|
||||
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data});
|
||||
sendDataToSuperNode(profileID,SNdata);
|
||||
}
|
||||
selfWebsocket.send(`u${profileID}`)
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
idb.onsuccess = (event) => {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("following", "readwrite").objectStore("following");
|
||||
obs.delete(profileID);
|
||||
@ -336,4 +293,3 @@ function follow(){
|
||||
followBtn.innerHTML = "+ Follow";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user