Compare commits

..

No commits in common. "server" and "master" have entirely different histories.

18 changed files with 8 additions and 58224 deletions

View File

@ -1,4 +0,0 @@
SERVER_PWD=
BROWSER=firefox
PORT=
SERVER_PAGE=webAppServer.html

View File

@ -1,44 +1,9 @@
# webAppServer
This server is used to get the appObjects and generalData for the webApp clients without the need for blockchain or supernode cloud
# TEDxKanke
TEDxKanke Event Management App
## Instructions
### scanner-tedxkanke.html
This webpage is used to view and manage the content of TEDxKanke app
Uses floSight (for Blockchain data) and Supernode cloud
### To run the server
1. Clone/download this repository
2. Add a strong `<server_password>` in `.config` file
3. Add the `<port>` in `.config` file for the server to run
4. open terminal in the directory and run `./start_webAppServer.sh`
### To use in client side
1. copy the floGlobals and webAppClient script tag to the webApp page
2. Add the server's `<website_url/ip_addr>:<port>` in floGlobals script tag
### Properties
#### sendGeneralData
webAppClient.sendGeneralData(message, type, options = {})
Sends a message to the cloud via webAppServer
* message: content of the message
* type: type of the message
#### requestGeneralData
webAppClient.requestGeneralData(type, vectorClock = '0')
Requests the generalData from webAppServer
* type: type of the message
* vectorClock: vectorClock after which the message should be requested (can be used with Date.now()) (default = '0')
* Returns an object (set of generalData)
#### requestObjectData
webAppClient.requestObjectData(keyPath)
Requests the objectData/appObjects from webAppServer
* path: (an Array) path of the required object (eg. \['Sample', Property1, property2..]
* Returns an Object/Array (requested path)
#### requestSubAdminList
webAppClient.requestSubAdminList()
Requests the subAdmin list of the application from webAppServer
* Returns an Array (of subAdmins)
### Architecture Diagram
![TEDxKanke-Architecture.png](util/TEDxKanke-Architecture.png)
### monitor-tedxkanke.html
This is a fast loading webpage that gets the direct data from the webAppServer

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,121 +0,0 @@
<html>
<head>
<script id="floGlobals">
/* Constants for FLO blockchain operations !!Make sure to add this at begining!! */
const floGlobals = {
blockchain: "FLO",
adminID: "FKAEdnPfjXLHSYwrXQu377ugN4tXU7VGdf",
webAppURL: "<website_url/ip_addr>:<port>",
application: "TEST_MODE"
}
</script>
</head>
<body>
TEST_MODE (use console)
<script id="webAppClient">
//Add this to the client script to request data from floWebappServer
const webAppClient = {
util: {
sendData(data) {
return new Promise((resolve, reject) => {
var websocket = new WebSocket("wss://" + floGlobals.webAppURL + "/ws");
websocket.onmessage = (evt => {
if (evt.data == '$+') {
websocket.send(data);
resolve(`Data sent to webApp`);
} else if (evt.data == '$-')
reject(`webApp not available`)
else
reject(evt.data)
websocket.close();
})
websocket.onerror = (evt) => {
reject(`webApp server not found`)
};
})
},
requestData(request = []) {
return new Promise((resolve, reject) => {
var websocket = new WebSocket("wss://" + floGlobals.webAppURL + "/ws");
websocket.onmessage = (evt => {
if (evt.data == '$+') {
websocket.send(`?${JSON.stringify(request)}`);
} else if (evt.data == '$-') {
reject(`webApp not available`)
websocket.close()
} else {
resolve(JSON.parse(evt.data));
websocket.close();
}
})
websocket.onerror = (evt) => {
reject(`webApp server not found`)
};
})
}
},
sendGeneralData: function (message, type, options = {}) {
return new Promise((resolve, reject) => {
var data = {
senderID: myFloID,
receiverID: options.receiverID || floGlobals.adminID,
pubKey: myPubKey,
message: message,
sign: floCrypto.signData(JSON.stringify(message), myPrivKey),
application: options.application || floGlobals.application,
type: type,
comment: options.comment || ""
}
this.util.sendData(JSON.stringify(data), data.receiverID)
.then(result => resolve(result))
.catch(error => reject(error))
})
},
requestGeneralData: function (type, vectorClock = '0') {
if (typeof vectorClock !== 'string')
vectorClock.toString()
return new Promise((resolve, reject) => {
this.util.requestData([floGlobals.application, 'generalData', type, vectorClock])
.then(
result => {
if (result[0])
resolve(result[1])
else
reject(result[1])
}).catch(error => reject(error))
})
},
requestObjectData: function (keyPath) {
return new Promise((resolve, reject) => {
this.util.requestData([floGlobals.application, 'appObjects'].concat(keyPath)).then(
result => {
if (result[0])
resolve(result[1])
else
reject(result[1])
}).catch(error => reject(error))
})
},
requestSubAdminList: function(){
return new Promise((resolve, reject) => {
this.util.requestData([floGlobals.application, 'subAdmins']).then(
result => {
if (result[0])
resolve(result[1])
else
reject(result[1])
}).catch(error => reject(error))
})
}
}
</script>
</body>
</html>

View File

@ -1,282 +0,0 @@
<html>
<head>
<title>FLO webApp Server</title>
<script id="onLoadStartUp">
function onLoadStartUp() {
const apps = ['TEDxKanke']
webAppServer.setServeAppList(apps)
var consoleClear = setInterval(console.clear, 60 * 60000) // clear console every 1 hr
webAppServer.initWebSocket()
.then(result => console.log(result))
.catch(error => console.error(error))
}
</script>
</head>
</html>
<body onload="onLoadStartUp()">
<script id="compactIDB">
/* Compact IndexedDB operations */
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
if (!window.indexedDB)
window.alert("Your browser doesn't support a stable version of IndexedDB.")
const compactIDB = {
setDefaultDB: function (dbName) {
this.dbName = dbName;
},
initDB: function (dbName, objectStores = {}) {
return new Promise((resolve, reject) => {
this.dbName = this.dbName || dbName;
var idb = indexedDB.open(dbName);
idb.onerror = (event) => {
reject("Error in opening IndexedDB!");
};
idb.onupgradeneeded = (event) => {
var db = event.target.result;
for (obs in objectStores) {
var objectStore = db.createObjectStore(obs, objectStores[obs].options ||
{});
if (objectStores[obs].indexes && typeof objectStores[obs].indexes ===
'object')
for (i in objectStores[obs].indexes)
objectStore.createIndex(i, i, objectStores[obs].indexes[i] ||
{});
}
}
idb.onsuccess = (event) => {
var db = event.target.result;
if (JSON.stringify(Object.values(db.objectStoreNames).sort()) === JSON
.stringify(Object.keys(
objectStores).sort()))
resolve("Initiated IndexedDB");
else
reject("IndexedDB already exist with different ObjectStores!");
db.close();
}
});
},
openDB: function (dbName = this.dbName) {
return new Promise((resolve, reject) => {
var idb = indexedDB.open(dbName);
idb.onerror = (event) => reject("Error in opening IndexedDB!");
idb.onsuccess = (event) => resolve(event.target.result);
});
},
deleteDB: function (dbName = this.dbName) {
return new Promise((resolve, reject) => {
var deleteReq = indexedDB.deleteDatabase(dbName);;
deleteReq.onerror = (event) => reject("Error deleting database!");
deleteReq.onsuccess = (event) => resolve("Database deleted successfully");
});
},
addData: function (obsName, data, key = false, dbName = this.dbName) {
return new Promise((resolve, reject) => {
this.openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let addReq = (key ? obs.add(data, key) : obs.add(data));
addReq.onsuccess = (evt) => resolve(`Add data successful`);
addReq.onerror = (evt) => reject(
`Add data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
},
removeData: function (obsName, key, dbName = this.dbName) {
return new Promise((resolve, reject) => {
this.openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let delReq = obs.delete(key);
delReq.onsuccess = (evt) => resolve(`Removed Data ${key}`);
delReq.onerror = (evt) => reject(
`Remove data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
},
readData: function (obsName, key, dbName = this.dbName) {
return new Promise((resolve, reject) => {
this.openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
let getReq = obs.get(key);
getReq.onsuccess = (evt) => resolve(evt.target.result);
getReq.onerror = (evt) => reject(
`Read data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
},
readAllData: function (obsName, dbName = this.dbName) {
return new Promise((resolve, reject) => {
this.openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
var tmpResult = {}
let curReq = obs.openCursor();
curReq.onsuccess = (evt) => {
var cursor = evt.target.result;
if (cursor) {
tmpResult[cursor.primaryKey] = cursor.value;
cursor.continue();
} else
resolve(tmpResult);
}
curReq.onerror = (evt) => reject(
`Read-All data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
},
searchData: function (obsName, patternEval, dbName = this.dbName) {
return new Promise((resolve, reject) => {
this.openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
var filteredResult = {}
let curReq = obs.openCursor();
curReq.onsuccess = (evt) => {
var cursor = evt.target.result;
if (cursor) {
if (patternEval(cursor.primaryKey, cursor.value))
filteredResult[cursor.primaryKey] = cursor.value;
cursor.continue();
} else
resolve(filteredResult);
}
curReq.onerror = (evt) => reject(
`Search unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
}
</script>
<script id="webAppServer">
const webAppServer = {
util: {
objectDataFetch(object, path) {
var pos = object;
path.forEach(p => pos = pos[p])
return pos
},
getNextGeneralData: function (generalData, vectorClock) {
var filteredResult = []
for (var i = 0; i < generalData.length; i++)
if (generalData[i].vectorClock > vectorClock)
filteredResult.push(generalData[i])
return filteredResult
},
getFilterString: function(application, type, comment = undefined){
var filterStr = JSON.stringify({application: application, type: type, comment: comment})
return filterStr
}
},
serveAppList: [],
setServeAppList: function(appList = []){
this.serveAppList = appList
},
initWebSocket: function () {
return new Promise((resolve, reject) => {
try {
console.log("Attempting to connect to websocket server")
this.webSocket = new WebSocket("ws://" + location.host + "/ws");
this.webSocket.onopen = (evt) => {
console.log("Connected to websocket server")
this.webSocket.send("$" + location.hash.substr(1));
};
this.webSocket.onclose = (evt) => {
console.log("Disconnected from websocket server");
this.initWebSocket()
.then(result => console.log(result))
.catch(error => console.error(error))
}
this.webSocket.onmessage = (evt) => {
if (evt.data[0] == '$') {
if (evt.data == '$Access Granted!')
resolve("Access Granted!");
else if (evt.data == '$Access Denied!')
reject("Access Denied!");
else
console.log(evt.data.substr(1))
}
else if (evt.data[0] == '?') {
var request = evt.data.substr(1).split(" ");
var requestor = request[0]
request = JSON.parse(request[1])
try{
if (!this.serveAppList.includes(request[0]))
throw Error("This application is not served by the webApp")
if(request[1] == "appObjects"){
compactIDB.readData(request[1], request[2], request[0]).then(result => {
var response = [true, this.util.objectDataFetch(result, request.slice(3))]
console.log(request, response)
this.webSocket.send(`${requestor} ${JSON.stringify(response)}`)
})
}
else if (request[1] == "generalData"){
var filterStr = this.util.getFilterString(request[0], request[2])
compactIDB.readData(request[1], filterStr, request[0]).then(result => {
var response = [true, this.util.getNextGeneralData(result, request[3])]
console.log(request, response)
this.webSocket.send(`${requestor} ${JSON.stringify(response)}`)
})
}
else if(request[1] == "subAdmins"){
compactIDB.readAllData(request[1], request[0]).then(result => {
var response = [true, Object.keys(result)]
console.log(request, response)
this.webSocket.send(`${requestor} ${JSON.stringify(response)}`)
})
}
else
throw Error('Invalid Request! Only subAdmins, appObjects and generalData can be requested')
}catch(error){
response = [false, error.message]
this.webSocket.send(`${requestor} ${JSON.stringify(response)}`)
}
} else {
var data = JSON.parse(evt.data)
if (this.serveAppList.includes(data.application))
floSupernode.sendData(JSON.stringify(data), data.receiverID)
.then(result => resolve(result))
.catch(error => reject(error))
}
};
this.webSocket.onerror = (evt) => {
reject("Error! Unable to connect websocket server");
};
} catch (error) {
reject(error)
}
})
}
}
</script>
</body>

Binary file not shown.

View File

@ -1,2 +0,0 @@
All logs are stored in this directory
NOTE: DO NOT delete this directory

View File

@ -1,18 +0,0 @@
Wed Feb 26 11:50:36 UTC 2020 : Starting webApp
Wed Feb 26 12:18:40 UTC 2020 : Starting webApp
Mon Mar 2 13:13:38 UTC 2020 : Starting webApp
Mon Mar 2 13:16:18 UTC 2020 : Starting webApp
Mon Mar 2 13:30:00 UTC 2020 : Starting webApp
Tue Mar 3 09:26:12 UTC 2020 : Starting webApp
Mon Mar 16 13:33:08 UTC 2020 : Starting webApp
Mon Mar 16 13:41:39 UTC 2020 : Starting webApp
Fri Apr 17 20:05:31 UTC 2020 : Starting webApp
Fri Apr 17 20:06:34 UTC 2020 : Starting webApp
Fri Jun 12 20:43:11 UTC 2020 : Starting webApp
Fri Jun 12 20:46:12 UTC 2020 : Starting webApp
Fri Jun 12 20:47:56 UTC 2020 : Starting webApp
Sat Jun 13 16:16:40 UTC 2020 : Starting webApp
Mon Jun 15 17:15:13 UTC 2020 : Starting webApp
Mon Aug 10 06:22:47 UTC 2020 : Starting webApp
Mon Aug 10 06:25:58 UTC 2020 : Starting webApp
Mon Aug 10 06:42:05 UTC 2020 : Starting webApp

View File

@ -1,18 +0,0 @@
Wed Feb 26 11:50:36 UTC 2020
Wed Feb 26 12:18:40 UTC 2020
Mon Mar 2 13:13:38 UTC 2020
Mon Mar 2 13:16:18 UTC 2020
Mon Mar 2 13:30:00 UTC 2020
Tue Mar 3 09:26:12 UTC 2020
Mon Mar 16 13:33:08 UTC 2020
Mon Mar 16 13:41:39 UTC 2020
Fri Apr 17 20:05:31 UTC 2020
Fri Apr 17 20:06:34 UTC 2020
Fri Jun 12 20:43:11 UTC 2020
Fri Jun 12 20:46:12 UTC 2020
Fri Jun 12 20:47:56 UTC 2020
Sat Jun 13 16:16:40 UTC 2020
Mon Jun 15 17:15:13 UTC 2020
Mon Aug 10 06:22:47 UTC 2020
Mon Aug 10 06:25:58 UTC 2020
Mon Aug 10 06:42:05 UTC 2020

File diff suppressed because it is too large Load Diff

View File

@ -1073,4 +1073,4 @@
}
</script>
</body>
</html>
</html>

View File

@ -1,20 +0,0 @@
#!/bin/sh
current_date=$(date)
echo "$current_date : Starting webApp" >> logs/app.log
#Read configurations
IFS="="
while read -r var value
do
export "$var"="${value}"
done < .config
#Start the app
echo $current_date >> logs/server.log
app/webSocketServer.bin $PORT $SERVER_PWD >> logs/server.log &
echo $current_date >> logs/browser.log
$BROWSER --headless "http://localhost:$PORT/$SERVER_PAGE#$SERVER_PWD" >> logs/browser.log &
$BROWSER --headless "http://localhost:$PORT/autoRefreshapp.html" >> logs/browser.log &
wait

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,172 +0,0 @@
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#include "mongoose.h"
static sig_atomic_t s_signal_received = 0;
static struct mg_serve_http_opts s_http_server_opts;
static char *s_http_port, *server_pwd;
static struct mg_connection *node = NULL;
static void signal_handler(int sig_num) {
signal(sig_num, signal_handler); // Reinstantiate signal handler
s_signal_received = sig_num;
}
//Display Message in console/terminal
static void display(struct mg_connection *nc, char type[25]){
char addr[32];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
printf("%s\t%s\n", addr, type);
}
//Broadcast incoming message (from nc to all)
static void broadcast(struct mg_connection *nc, const struct mg_str msg) {
char addr[32];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
printf("%s\tBroadcast\t[%d]\n", addr, (int)msg.len);
struct mg_connection *c;
for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
if (c == nc) continue; /* Don't send to the sender. */
mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, msg.p, msg.len);
}
}
//Unicast message (to nc)
static void unicast(struct mg_connection *nc, const struct mg_str msg) {
char addr[32];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
printf("%s\tUnicast\t[%d]\n", addr, (int)msg.len);
if(nc != NULL)
mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, msg.p, msg.len);
}
//Forward message (from nc to supernode)
static void unicast_forward(struct mg_connection *nc, const struct mg_str msg) {
char addr[32];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
printf("%s\tForward\t[%d]\n", addr, (int)msg.len);
if(node != NULL)
mg_send_websocket_frame(node, WEBSOCKET_OP_TEXT, msg.p, msg.len);
else
printf("webApp_node is offline!\n");
}
//Request message (from nc to supernode)
static void unicast_request(struct mg_connection *nc, const struct mg_str msg) {
if(node == NULL){
printf("webApp_node is offline!\n");
return;
}
char addr[32], buf[500];
mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
printf("%s\tRequest\t[%d]\n", addr, (int)msg.len-1);
snprintf(buf, sizeof(buf), "?%s %.*s", addr, (int) msg.len-1, msg.p+1);
mg_send_websocket_frame(node, WEBSOCKET_OP_TEXT, buf, strlen(buf));
}
//Reply message (from node)
static void unicast_reply(const struct mg_str msg) {
if(node == NULL){
printf("webApp_node is offline!\n");
return;
}
//Get receiver address from msg
char receiverAddr[32];
int index = (int)(strchr(msg.p, ' ') - msg.p) + 1;
snprintf(receiverAddr, sizeof(receiverAddr), "%.*s", index - 1, msg.p);
printf("%s\tReply\t[%d]\n", receiverAddr, (int)msg.len - index);
//send msg to receiver
struct mg_connection *c;
for (c = mg_next(node->mgr, NULL); c != NULL; c = mg_next(node->mgr, c)) {
char addr[32];
mg_sock_addr_to_str(&c->sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);
if (!strcmp(receiverAddr,addr))
mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, msg.p + index, msg.len - index);
}
}
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
switch (ev) {
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
/*New websocket connection*/
display(nc, "+Connected+");
if(node!=NULL)
unicast(nc, mg_mk_str("$+"));
else
unicast(nc, mg_mk_str("$-"));
break;
}
case MG_EV_WEBSOCKET_FRAME: {
struct websocket_message *wm = (struct websocket_message *) ev_data;
/* New websocket message*/
struct mg_str d = {(char *) wm->data, wm->size};
if (d.p[0] == '$'){
char pass[100];
snprintf(pass, sizeof(pass), "%.*s",(int)d.len-1, &d.p[1]);
if(!strcmp(pass,server_pwd)){
if(node!=NULL)
unicast(node,mg_mk_str("$Another login is encountered! Please close/refresh this window"));
else
broadcast(nc, mg_mk_str("$+"));
node = nc;
unicast(node,mg_mk_str("$Access Granted!"));
display(nc, "*Became webApp_node*");
}else
unicast(nc,mg_mk_str("$Access Denied!"));
}
else if (d.p[0] == '?')
unicast_request(nc,d);
else if (nc == node)
unicast_reply(d);
else
unicast_forward(nc,d);
break;
}
case MG_EV_HTTP_REQUEST: {
mg_serve_http(nc, (struct http_message *) ev_data, s_http_server_opts);
break;
}
case MG_EV_CLOSE: {
/* Disconnect websocket*/
if(nc == node){
node = NULL;
display(nc,"!webApp_node Disconnected!");
broadcast(nc, mg_mk_str("$-"));
}else
display(nc, "-Disconnected-");
break;
}
}
}
int main(int argc, char** argv) {
s_http_port = argv[1];
server_pwd = argv[2];
struct mg_mgr mgr;
struct mg_connection *nc;
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
mg_mgr_init(&mgr, NULL);
nc = mg_bind(&mgr, s_http_port, ev_handler);
mg_set_protocol_http_websocket(nc);
s_http_server_opts.document_root = "app/"; // Serve current directory
s_http_server_opts.enable_directory_listing = "no";
printf("Started on port %s\n", s_http_port);
while (s_signal_received == 0) {
mg_mgr_poll(&mgr, 200);
}
mg_mgr_free(&mgr);
return 0;
}