|
|
|
@ -9,8 +9,8 @@ const express = require("express"); // could be good to replace with c |
|
|
|
|
|
|
|
|
|
// Get port or default to 8082
|
|
|
|
|
const port = process.env.PORT || 8082; |
|
|
|
|
const protocol = 'https' |
|
|
|
|
const subclass = '192.168.4.' |
|
|
|
|
const protocol = process.env.PROTOCOL || 'https' |
|
|
|
|
const subclass = process.env.SUBCLASS || '192.168.4.' |
|
|
|
|
|
|
|
|
|
const publicKeyPath = path.resolve(process.env.HOME,'.ssh','id_rsa_offlineoctopus.pub') |
|
|
|
|
const publicKey = fs.readFileSync(publicKeyPath).toString().split(' ')[1] |
|
|
|
@ -27,6 +27,12 @@ const minfileSaveFullPath = path.join(__dirname,'examples', minfilename) |
|
|
|
|
const sshconfigpath = path.resolve(process.env.HOME,'.ssh','config') |
|
|
|
|
const propath = path.resolve(process.env.HOME,'Prototypes') |
|
|
|
|
|
|
|
|
|
const sshfsmounts = "sshfsmounts" |
|
|
|
|
|
|
|
|
|
let workspaces = {} |
|
|
|
|
let mountPoints = [] |
|
|
|
|
// note that stopping this process removes the mounts
|
|
|
|
|
|
|
|
|
|
// does not apply in a P2P fashion, must rely on local configuration here config.json
|
|
|
|
|
let localServices = [ ] |
|
|
|
|
const configFilePath = path.resolve(__dirname, "config.json") |
|
|
|
@ -231,7 +237,8 @@ app.get('/hmdlink', (req, res) => { |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
app.get('/webxr', (req, res) => { |
|
|
|
|
res.redirect( '/local-metaverse-tooling/local-aframe-test.html' ) |
|
|
|
|
res.redirect( '/spasca-offline/engine/index.html') |
|
|
|
|
//res.redirect( '/local-metaverse-tooling/local-aframe-test.html' )
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// user for /scan to populate foundPeers
|
|
|
|
@ -251,7 +258,7 @@ app.get('/scan', (req, res) => { |
|
|
|
|
|
|
|
|
|
function scanpeers(){ |
|
|
|
|
foundPeers = [] |
|
|
|
|
for (let i=1;i<25;i++){ // async so blasting, gives very quick result for positives
|
|
|
|
|
for (let i=1;i<254;i++){ // async so blasting, gives very quick result for positives
|
|
|
|
|
let url=protocol+'://'+subclass+i+':'+port+'/available' |
|
|
|
|
let opt={rejectUnauthorized: false} |
|
|
|
|
https.get(url, opt, res => { |
|
|
|
@ -272,20 +279,57 @@ function scanpeers(){ |
|
|
|
|
|
|
|
|
|
app.get('/sshconfig', (req, res) => { |
|
|
|
|
res.json( getSshConfig() ) |
|
|
|
|
// should filter on foundPeers to avoid offline peers
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// note that stopping this process removes the mounts
|
|
|
|
|
app.get('/sshconfig/live', (req, res) => { |
|
|
|
|
res.json( getSshConfig().filter( i => foundPeers.map( e => subclass+e ).filter( x => i.connectionString.match(x) ).length ) ) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
app.get('/unifiedworkspaces', (req, res) => { |
|
|
|
|
res.json( workspaces ) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
function getUnifiedworkspaces(){ |
|
|
|
|
mountPoints.map( mp => { |
|
|
|
|
let dir = path.resolve(__dirname, sshfsmounts, mp) |
|
|
|
|
workspaces[mp] = fs.readdirSync( dir ) |
|
|
|
|
console.log('reading', mp, workspaces.mp) |
|
|
|
|
}) |
|
|
|
|
return workspaces |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function mountAll(){ |
|
|
|
|
getSshConfig().map( l => { |
|
|
|
|
// should scanpeers() first
|
|
|
|
|
if (foundPeers.length==0) return |
|
|
|
|
getSshConfig().filter( i => foundPeers.map( e => subclass+e ).filter( x => i.connectionString.match(x) ).length ) |
|
|
|
|
.map( l => { |
|
|
|
|
let cs = 'sshfs ' + l.name + ':' |
|
|
|
|
if (l.custom) |
|
|
|
|
cs+= l.custom |
|
|
|
|
else |
|
|
|
|
cs+='/home/'+l.user |
|
|
|
|
return cs + ' ' + path.resolve(__dirname, "sshfsmounts", l.name) |
|
|
|
|
let targetPath = path.resolve(__dirname, sshfsmounts, l.name) |
|
|
|
|
if (!fs.existsSync(targetPath)){ fs.mkdirSync(targetPath, { recursive: true }); } |
|
|
|
|
mountPoints.push(l.name) |
|
|
|
|
return cs + ' ' + targetPath |
|
|
|
|
} ) |
|
|
|
|
//.map( l => console.log(l))
|
|
|
|
|
.map( l => { try { execSync(l) } catch (err) { console.log(err) } } ) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function umountAll(){ |
|
|
|
|
mpath = path.resolve(__dirname, sshfsmounts) |
|
|
|
|
fs.readdirSync( mpath ) |
|
|
|
|
// could rely on mountPoints instead
|
|
|
|
|
.map( f => { |
|
|
|
|
try { |
|
|
|
|
execSync('umount ' + path.resolve(__dirname, sshfsmounts, f) ) |
|
|
|
|
// should update mountPoints instead
|
|
|
|
|
} catch (err) { |
|
|
|
|
console.log(err) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
.map( l => execSync(l)) |
|
|
|
|
mountPoints = [] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getSshConfig(){ |
|
|
|
@ -379,5 +423,86 @@ const webServer = https.createServer(credentials, app); |
|
|
|
|
// const webServer = http.createServer(app);
|
|
|
|
|
// Listen on port
|
|
|
|
|
webServer.listen(port, () => { |
|
|
|
|
console.log("listening on "+protocol+"://localhost:" + port); |
|
|
|
|
console.log("listening on "+protocol+"://localhost:" + port) |
|
|
|
|
getCommand() |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// REPL testing
|
|
|
|
|
const readline = require("readline"); |
|
|
|
|
const rl = readline.createInterface({ |
|
|
|
|
input: process.stdin, |
|
|
|
|
output: process.stdout, |
|
|
|
|
completer: completer |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// https://nodejs.org/api/readline.html#use-of-the-completer-function
|
|
|
|
|
function completer(line) { |
|
|
|
|
const completions = help().split('\n'); |
|
|
|
|
const hits = completions.filter((c) => c.startsWith(line)); |
|
|
|
|
// Show all completions if none found
|
|
|
|
|
return [hits.length ? hits : completions, line]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let command = '' |
|
|
|
|
function getCommand(){ |
|
|
|
|
rl.question(process.title+" REPL: ", function(command) { |
|
|
|
|
if (command == "close") { |
|
|
|
|
rl.close(); |
|
|
|
|
} else { |
|
|
|
|
try { |
|
|
|
|
console.log(command, eval(command) ) |
|
|
|
|
} catch (err) { |
|
|
|
|
console.log(err) |
|
|
|
|
} |
|
|
|
|
getCommand() |
|
|
|
|
// somehow switch to node REPL proper after?!
|
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function help(){ |
|
|
|
|
return ` |
|
|
|
|
help() |
|
|
|
|
execConfiguredCommand(cmdName) |
|
|
|
|
getSshConfig() |
|
|
|
|
mountAll() |
|
|
|
|
umountAll() |
|
|
|
|
scanpeers() |
|
|
|
|
getUnifiedworkspaces() |
|
|
|
|
foundPeers |
|
|
|
|
port |
|
|
|
|
protocol |
|
|
|
|
subclass |
|
|
|
|
publicKeyPath |
|
|
|
|
publicKey |
|
|
|
|
md5fromPub |
|
|
|
|
process.title |
|
|
|
|
filename |
|
|
|
|
fileSaveFullPath |
|
|
|
|
minfilename |
|
|
|
|
minfileSaveFullPath |
|
|
|
|
sshconfigpath |
|
|
|
|
propath |
|
|
|
|
localServices |
|
|
|
|
configFilePath |
|
|
|
|
utilsCmd |
|
|
|
|
instructions |
|
|
|
|
auth_instructions |
|
|
|
|
process.title |
|
|
|
|
sshfsmounts |
|
|
|
|
mountPoints |
|
|
|
|
workspaces |
|
|
|
|
` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rl.on("close", function() { |
|
|
|
|
console.log("\ndone"); |
|
|
|
|
umountAll() |
|
|
|
|
process.exit(0); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Demo Day target :
|
|
|
|
|
// show files from ~/Prototypes as cubes from ssh mounted on a virtual workspace
|
|
|
|
|
// sshfs might not even be needed, see allpeers/exec instead
|
|
|
|
|
// wouldn't easily get content back though, just meta data
|
|
|
|
|
|
|
|
|
|