From 174b9fddf68104a9b67f51e77e54a447a811e48b Mon Sep 17 00:00:00 2001 From: sairajzero Date: Wed, 24 Jul 2019 03:01:29 +0530 Subject: [PATCH 01/11] Improved user login and stability of funtions Old prompt based user login and server connect are replaced with login page Improved stability and simplification of functions Moved all superNode functions to app.js Supernode mode will now work in all pages (home,profile,msg) instead of just home --- app/web/app.js | 242 +- app/web/home.html | 4 +- app/web/home.js | 665 +- app/web/index.html | 147 +- app/web/{registerID.js => init.js} | 13418 +++++++++++++-------------- app/web/login.js | 379 + app/web/msg.html | 2 +- app/web/msg.js | 105 +- app/web/profile.html | 2 +- app/web/profile.js | 181 +- 10 files changed, 7581 insertions(+), 7564 deletions(-) rename app/web/{registerID.js => init.js} (95%) mode change 100755 => 100644 create mode 100644 app/web/login.js diff --git a/app/web/app.js b/app/web/app.js index 20ba838..a4fd2f7 100644 --- a/app/web/app.js +++ b/app/web/app.js @@ -6,7 +6,8 @@ window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.ms if (!window.indexedDB) { window.alert("Your browser doesn't support a stable version of IndexedDB.") } - +var supernodeKBucket; +var superNodeList; var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; var encrypt = { @@ -14,7 +15,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) { @@ -159,6 +160,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,11 +284,9 @@ function getTime(time){ function logout(){ sessionStorage.clear(); - location.reload(); + window.location.href = "index.html"; } -var supernodeKBucket; -var superNodeList; /*Kademlia DHT K-bucket implementation as a binary tree.*/ if (typeof reactor == "undefined" || !reactor) { @@ -317,25 +344,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 @@ -984,6 +992,35 @@ kBucketObj = { } } +/* Common IDB functions */ +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"); @@ -996,4 +1033,159 @@ function sendDataToSuperNode(floID,data){ }).catch(e => { console.log(e.message); }); - } \ No newline at end of file +} + +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) }; +} \ No newline at end of file diff --git a/app/web/home.html b/app/web/home.html index b0f30e2..7d72347 100644 --- a/app/web/home.html +++ b/app/web/home.html @@ -8,12 +8,12 @@ - + - + ` 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){ - console.log("DISCONNECTED"); - }; - selfWebsocket.onmessage = function(evt){ - console.log(evt.data); - if(evt.data[0] == '$') + selfWebsocket.onclose = (event) => { console.log("DISCONNECTED") }; + 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 +76,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 +89,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) } }; - 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 +109,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 +125,7 @@ function readMsgfromIDB(){ }; db.close(); }; - } - ); + }); } function changeReceiver(floID){ @@ -148,9 +144,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 +157,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 +189,3 @@ function createMsgElement(floID,time,msg,type){ `; 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(); - }; -} \ No newline at end of file diff --git a/app/web/profile.html b/app/web/profile.html index 4fd9dd7..eef8929 100644 --- a/app/web/profile.html +++ b/app/web/profile.html @@ -8,7 +8,7 @@ - + diff --git a/app/web/profile.js b/app/web/profile.js index f32c19f..8c4d9ed 100644 --- a/app/web/profile.js +++ b/app/web/profile.js @@ -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); @@ -16,11 +16,13 @@ function viewProfile(){ var url = new URL(window.location.href); profileID = url.searchParams.get("floID"); superNodeList = JSON.parse(sessionStorage.superNodeList); - kBucketObj.launchKBucket().then(function(result){ + if(superNodeList.includes(selfID)) + modSuperNode = true; + kBucketObj.launchKBucket().then(result => { console.log(result) listProfiles(); displayProfile(profileID); - }).catch(function(error){ + }).catch(error => { console.log(error.message); }); } @@ -30,7 +32,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 +46,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){ + }).catch(error => { console.log(error.message); }); } 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 +80,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 +93,7 @@ function displayTweetFromIDB(floID){ } db.close(); }; - } - ); + }); } function listProfiles(){ @@ -111,7 +109,6 @@ function listProfiles(){ ` profileList.appendChild(element); } - //document.getElementById("profileInfo").style.display = "none"; } function createTweetElement(floID,time,tweet){ @@ -133,23 +130,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)) @@ -160,73 +150,38 @@ function connectToX(floID){ console.log(error.message); } } - } - ); -} - -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.message); + }); } -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"); + resolve('Sent New tweet request to user server!'); + }).catch(error => { + console.log(error.message); + }); } 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 +189,26 @@ 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){ - console.log("DISCONNECTED"); - }; - selfWebsocket.onmessage = function(evt){ - console.log(evt.data); - if(evt.data[0] == '$') + selfWebsocket.onclose = (event) => { console.log("DISCONNECTED") }; + 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 +217,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 +235,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) } }; - selfWebsocket.onerror = function(evt){ - console.log(evt); - }; + selfWebsocket.onerror = (event) => { console.log(event) }; } function follow(){ @@ -301,12 +253,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 +273,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 +288,3 @@ function follow(){ followBtn.innerHTML = "+ Follow"; } } - From 2c405ec3d3668ff9b9aeaf49d51943e19b4518bd Mon Sep 17 00:00:00 2001 From: Sai Raj <39055732+sairajzero@users.noreply.github.com> Date: Wed, 24 Jul 2019 03:50:06 +0530 Subject: [PATCH 02/11] Create .gitattributes --- .gitattributes | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9105c93 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +*.gitattributes linguist-vendored +util/mongoose.c linguist-vendored +util/mongoose.h linguist-vendored + +.gitattributes export-ignore From 629f3fb089db6e84887f01a889113ce80da34ae2 Mon Sep 17 00:00:00 2001 From: Sai Raj <39055732+sairajzero@users.noreply.github.com> Date: Wed, 24 Jul 2019 03:56:36 +0530 Subject: [PATCH 03/11] Update .gitattributes --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 9105c93..ecac0ea 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ *.gitattributes linguist-vendored util/mongoose.c linguist-vendored util/mongoose.h linguist-vendored +app/web/init.js linguist-vendored .gitattributes export-ignore From 20c8f124e52d2235473050f1ca97451b4e7e1a8a Mon Sep 17 00:00:00 2001 From: sairajzero Date: Wed, 24 Jul 2019 15:01:21 +0530 Subject: [PATCH 04/11] Adding reload API data button The reload API data button (top-right) refreshes the API for new data The refreshed API data are added to memory as well as stored in IDB. The kBucket is reloaded --- app/web/app.js | 600 +++++++++++++++++++++++++++------------------ app/web/home.html | 5 +- app/web/home.js | 14 +- app/web/index.html | 2 +- app/web/login.js | 46 +--- app/web/msg.js | 6 +- app/web/profile.js | 16 +- 7 files changed, 383 insertions(+), 306 deletions(-) diff --git a/app/web/app.js b/app/web/app.js index a4fd2f7..e61f35d 100644 --- a/app/web/app.js +++ b/app/web/app.js @@ -148,7 +148,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); @@ -287,9 +287,349 @@ function logout(){ window.location.href = "index.html"; } +/*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); + 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 { + 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 { 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) { @@ -761,7 +1101,7 @@ reactor.addEventListener('bucket_full', function (someObject) { kBucketObj = { - decodeBase58Address: function (blockchain, address) { + decodeBase58Address: function (address) { let k = bitjs.Base58.decode(address) k.shift() k.splice(-4, 4) @@ -772,12 +1112,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{ readAllDB('kBucketStore') .then(dbObject => { @@ -854,7 +1194,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.`); @@ -870,7 +1210,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); }); @@ -948,7 +1288,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); @@ -959,233 +1299,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); - } - }) } -} - -/* Common IDB functions */ -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) }; } \ No newline at end of file diff --git a/app/web/home.html b/app/web/home.html index 7d72347..925d70a 100644 --- a/app/web/home.html +++ b/app/web/home.html @@ -35,10 +35,13 @@ - + + diff --git a/app/web/home.js b/app/web/home.js index 7f815f4..b4f57cb 100644 --- a/app/web/home.js +++ b/app/web/home.js @@ -12,10 +12,10 @@ function viewHome(){ console.log(profiles); privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey)); selfID = sessionStorage.selfID; - superNodeList = JSON.parse(sessionStorage.superNodeList); - if(superNodeList.includes(selfID)) + superNodeList = new Set(JSON.parse(sessionStorage.superNodeList)); + if(superNodeList.has(selfID)) modSuperNode = true; - kBucketObj.launchKBucket().then(function(result){ + kBucketObj.launchKBucket().then(result => { console.log(result); initselfWebSocket(); listProfiles(); @@ -33,8 +33,8 @@ function viewHome(){ }).catch(error => { console.log(error); }) - }).catch(function(error){ - console.log(error.message); + }).catch(error => { + console.log(error); }); } @@ -85,7 +85,7 @@ function initselfWebSocket(){ superNodeMode(data); } }catch(error){ - console.log(error.message); + console.log(error); } }; selfWebsocket.onerror = (event) => { console.log(event) }; @@ -214,7 +214,7 @@ 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); } }; }); diff --git a/app/web/index.html b/app/web/index.html index baa4acb..4200896 100644 --- a/app/web/index.html +++ b/app/web/index.html @@ -129,7 +129,7 @@ label span { - +