Skip to content

Commit

Permalink
Implement endpoints to receive file and command data
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelg29 committed Oct 25, 2023
1 parent 3756012 commit 433f15b
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 9 deletions.
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,9 @@ RUN sudo chmod +x ${JAMOTA_ROOT}/start.sh
# redis script setup
COPY ./redis/redis.sh ${JAMOTA_ROOT}/redis/redis.sh
RUN sudo chmod +x ${JAMOTA_ROOT}/redis/redis.sh

RUN sudo mkdir -p ${JAMOTA_ROOT}/channels/files
RUN sudo chmod a+rwx ${JAMOTA_ROOT}/channels/files

RUN sudo mkdir -p ${JAMOTA_ROOT}/channels/commands
RUN sudo chmod a+rwx ${JAMOTA_ROOT}/channels/commands
1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* through website, user executes jamkill to stop current running JAMScript program
* through website, user uploads new .jxe file
* through website, user executes jamrun to start new file
* update jxe_loader to match website data
1. website
* robust UI
* auto-refresh page data (pull/push)
Expand Down
1 change: 1 addition & 0 deletions ota-portal/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var app = express();

// basic middleware
app.use(logger('dev'));
app.use(express.raw());
app.use(express.text({
type: "text/*"
}));
Expand Down
3 changes: 3 additions & 0 deletions ota-portal/bin/www
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ var fs = require('fs');
var crypto = require('crypto');
var rclient = require('../utils/redis-client');

// Print current user
console.log(require("os").userInfo().username);

/**
* Create admin user.
*/
Expand Down
22 changes: 19 additions & 3 deletions ota-portal/public/javascripts/nodes/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ async function deleteNode(nodeId) {
await dataRequest("DELETE", `nodes/${nodeId}`);
}

async function uploadFile(networkId) {
async function getChannel(networkId) {
// get node IDs to upload to
let nodeSelectElements = document.querySelectorAll("input.node-selector");
let nodeIds = [];
Expand All @@ -24,21 +24,37 @@ async function uploadFile(networkId) {
let channelRes = await dataRequest("POST", `networks/${networkId}/channel`, undefined, {
"nodeIds": nodeIds
});
console.log(channelRes);
}

return;
async function uploadFile(networkId) {
await getChannel(networkId);

// upload file
let file = document.querySelector("#file-input").files[0];
const reader = new FileReader();
reader.onload = (e) => {
console.log("Sending file " + file.name);
dataRequest("POST", "file", undefined, e.target.result, "application/octet-stream")
dataRequest("POST", `networks/${networkId}/channel/file`, undefined, e.target.result, "application/octet-stream")
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err);
});
};

// read file
reader.readAsArrayBuffer(file);
}

async function uploadCommand(networkId) {
await getChannel(networkId);

// read command
const cmd = document.querySelector("#cmd-input").value;

// upload command
let cmdRes = await dataRequest("POST", `networks/${networkId}/channel/cmd`, undefined, cmd, "text/plain");
console.log(cmdRes);
}
71 changes: 70 additions & 1 deletion ota-portal/routes/networkChannels.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,31 @@ const rclient = require("../utils/redis-client");
const network = require("../utils/network");
const channel = require("../utils/channel");
const node = require("../utils/node");
const fs = require("fs");

const { spawn } = require("child_process");

const scriptPath = (script) => `${process.env.JAMOTA_ROOT}/ota-portal/bin/${script}.js`;

async function execNodeScript(args, onstdout, onstderr) {
return new Promise((resolve, reject) => {
const proc = spawn("node", args, {
detached: true
});

if (onstdout) {
proc.stdout.on("data", onstdout);
}

if (onstderr) {
proc.stderr.on("data", onstderr);
}

proc.on("exit", (code) => {
resolve(code);
});
});
}

/**
* Create a channel to communicate with multiple nodes. Each network can only have one active channel.
Expand Down Expand Up @@ -45,7 +70,51 @@ router.post("/:id/channel", errors.asyncWrap(async function(req, res) {
await channel.newChannelObj(networkId, nodeIds);

// return response
res.status(200);
res.sendStatus(200);
}));

/**
* Upload a file to the channel.
*/
router.post("/:id/channel/file", async function(req, res) {
req.setEncoding(null);

try {
// persist file locally
fs.writeFileSync(`${process.env.JAMOTA_ROOT}/channels/${req.params.id}`, Buffer.from(req.body));

// asynchronously dispatch process to upload file to nodes
execNodeScript([scriptPath("jxe_loader"), "--networkId", req.params.id, "--type", "file"], (data) => {
console.log(data.toString());
});

res.sendStatus(200);
}
catch (e) {
console.log("Failed", e);
res.sendStatus(500);
}
});

/**
* Upload a command to the channel.
*/
router.post("/:id/channel/cmd", async function(req, res) {
try {
let cmd = req.body;
console.log(cmd);

// dispatch process to send command to nodes
execScript([scriptPath("jxe_loader"), "--networkId", req.params.id, "--type", "command"], (data) => {
console.log(data.toString());
});

res.sendStatus(200);
}
catch (e) {
console.log("Failed", e);
res.sendStatus(500);
}
});

module.exports = router;
5 changes: 3 additions & 2 deletions ota-portal/routes/networks.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const request = require("../utils/request");

const ijam_types = require("../utils/ijam_types");
const network = require("../utils/network");
const passphrases = require("../utils/network_passphrase");
const node = require("../utils/node");

/**
Expand Down Expand Up @@ -61,7 +62,7 @@ router.delete("/:id", errors.asyncWrap(async function(req, res, next) {
await rclient.del(node.networkNodesKey(networkId));

// delete passphrases
await network.clearPassphrases(networkId);
await passphrases.clearPassphrases(networkId);

// remove from user network list
await rclient.removeFromSet(network.userNetworksKeyFromReq(req), networkId);
Expand Down Expand Up @@ -91,7 +92,7 @@ async function filterNetworkEntries(networkIds) {

networks[networkId] = map(networkObj,
await rclient.getSetSize(node.networkNodesKey(networkId)),
await network.getNumberOfPassphrases(networkId));
await passphrases.getNumberOfPassphrases(networkId));
}
}

Expand Down
2 changes: 2 additions & 0 deletions ota-portal/utils/network_passphrase.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

const rclient = require("./redis-client");

const maxPassphraseLength = 16;

/** Get the key mapping to the network's active passphrases. */
Expand Down
12 changes: 9 additions & 3 deletions ota-portal/views/node/list.pug
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ block content
h2 Command center

div
label Select file to upload to selected nodes
input(type="file" id="file-input")
input(type="submit" value="Upload", onclick="uploadFile('" + networkId + "')")
p
label Select file to upload to selected nodes
input(type="file" id="file-input")
input(type="submit" value="Upload", onclick="uploadFile('" + networkId + "')")

p
label Send command to selected nodes
input(type="text" id="cmd-input")
input(type="submit" value="Upload" onclick="uploadCommand('" + networkId + "')")

h2 Table of nodes

Expand Down

0 comments on commit 433f15b

Please sign in to comment.