Compare commits
9 Commits
responsive
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2eedef5398 | ||
|
|
3e7aa01e34 | ||
| f8443bd342 | |||
| 0712c4e2b5 | |||
| aabd112c16 | |||
| a1fc2458c0 | |||
| e4a27f273d | |||
| 67460f125d | |||
| 5c3b7063d3 |
43
README.md
Normal file
43
README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Offtopus, offline-octopus
|
||||
|
||||
## Goal
|
||||
Provide a way to connect local machines to work and tinker with efficiently, building prototypes with resilience in mind.
|
||||
|
||||
## Demo
|
||||
|
||||
5min recorded demo video https://video.benetou.fr/w/sHE39WSZkQgfPNDdiypfog
|
||||
|
||||
Note that XR is optional. Original extract from https://youtu.be/BRjohy0ruAg?t=2061 for Future of Text demo day.
|
||||
|
||||
## How does it work
|
||||
It provides a Web server with endpoints for different functions, including listing machines joining that network, make functions available to that new network of machines, sharing files, etc. Note that the point is to build on top of it, consequently functions as endpoints here are solely examples.
|
||||
|
||||
## How to install
|
||||
1. clone repository
|
||||
1. install dependancies (no package.json yet) but mostly express missing, i.e `npm i express`
|
||||
1. run e.g `node .`
|
||||
1. connect to it locally first, e.g https://localhost:8082 (assumes existing SSL certificates) or https://localhost:8082/routes
|
||||
|
||||
Note that the cloudinit file is an example on a brand new machine.
|
||||
|
||||
### tested on
|
||||
- Linux machines, e.g Ubuntu on desktop, RPi Zero
|
||||
- Android devices using Termux, e.g Quest 1
|
||||
- iOS via iSH
|
||||
Most likely partially works on Windows with Linux subsystem. System commands, e.g shutdown, xrandr, etc must be adapted.
|
||||
|
||||
### Developing and debugging
|
||||
- See the console REPL, starting with help()
|
||||
- see `/routes/json` to connect to all services
|
||||
|
||||
## Digging deeper
|
||||
- Future of Text WebXR demo with shared filesystems https://video.benetou.fr/w/h291CfZiezenY1t46cQQo5 extract from https://www.youtube.com/results?search_query=demo+prototype+session
|
||||
- hour long video discussion https://video.benetou.fr/w/aR81WVHg6H3E93GPG4jYUg
|
||||
- self hosting AI notes https://fabien.benetou.fr/Content/SelfHostingArtificialIntelligence
|
||||
- self hosting subreddit https://old.reddit.com/r/selfhosted/
|
||||
- small Web https://ar.al/2020/08/07/what-is-the-small-web/
|
||||
- DWeb https://en.wikipedia.org/wiki/Decentralized_web
|
||||
|
||||
### Inspiration
|
||||
- Designing for serendipity: supporting end-user configuration of ubiquitous computing environments, Xerox PARC 2002
|
||||
- Providing an Integrated User Experience of Networked Media, Devices, and Services through End-User Composition, 2008
|
||||
16
cloudinit
Normal file
16
cloudinit
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd /root
|
||||
curl -sL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh
|
||||
source nodesource_setup.sh
|
||||
apt install -y nodejs
|
||||
apt update && apt install -y git
|
||||
git clone https://git.benetou.fr/utopiah/offline-octopus
|
||||
mkdir Prototypes
|
||||
mv offline-octopus/ Prototypes/
|
||||
cd Prototypes/offline-octopus/
|
||||
npm i express
|
||||
openssl req -nodes -new -x509 -keyout naf-key.pem -out naf.pem -subj "/C=BE/ST=Brussels/L=Brussels/O=Global Security/OU=IT Department/CN=offtopus.benetou.fr"
|
||||
touch /root/.ssh/id_rsa_offlineoctopus.pub
|
||||
touch /root/Prototypes/offline-octopus/.keyfrommd5
|
||||
HOME=/root /usr/bin/node index.js &>> log.txt
|
||||
29
examples/events.html
Normal file
29
examples/events.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="https://glitch.com/favicon.ico" />
|
||||
<title>offtopus events</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
<hr>
|
||||
<div id="events"></div>
|
||||
|
||||
<script>
|
||||
const source = new EventSource('/events');
|
||||
|
||||
source.addEventListener('message', message => {
|
||||
console.log('Got', message);
|
||||
|
||||
// Display the event data in the `content` div
|
||||
document.querySelector('#events').innerHTML = event.data;
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
29
index.js
29
index.js
@@ -10,7 +10,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 subclass = '10.160.168.'
|
||||
//const subclass = '192.168.4.'
|
||||
|
||||
const publicKeyPath = path.resolve(process.env.HOME,'.ssh','id_rsa_offlineoctopus.pub')
|
||||
const publicKey = fs.readFileSync(publicKeyPath).toString().split(' ')[1]
|
||||
@@ -250,6 +251,7 @@ app.get('/scan', (req, res) => {
|
||||
})
|
||||
|
||||
function scanpeers(){
|
||||
sendEventsToAll({'action':'scanning started'})
|
||||
foundPeers = []
|
||||
for (let i=1;i<25;i++){ // async so blasting, gives very quick result for positives
|
||||
let url=protocol+'://'+subclass+i+':'+port+'/available'
|
||||
@@ -381,3 +383,28 @@ const webServer = https.createServer(credentials, app);
|
||||
webServer.listen(port, () => {
|
||||
console.log("listening on "+protocol+"://localhost:" + port);
|
||||
});
|
||||
|
||||
// SSE from https://www.digitalocean.com/community/tutorials/nodejs-server-sent-events-build-realtime-app
|
||||
// adapted from jxr-permanence
|
||||
let clients = [];
|
||||
|
||||
function eventsHandler(request, response, next) {
|
||||
const headers = {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Connection': 'keep-alive',
|
||||
'Cache-Control': 'no-cache'
|
||||
};
|
||||
response.writeHead(200, headers);
|
||||
const clientId = Date.now();
|
||||
const newClient = { id: clientId, response };
|
||||
clients.push(newClient);
|
||||
request.on('close', () => { clients = clients.filter(client => client.id !== clientId); });
|
||||
}
|
||||
|
||||
function sendEventsToAll(data) {
|
||||
// function used to broadcast
|
||||
clients.forEach(client => client.response.write(`data: ${JSON.stringify(data)}\n\n`))
|
||||
}
|
||||
|
||||
app.get('/events', eventsHandler);
|
||||
// for example /events.html shows when /scan begings (but not ends)
|
||||
|
||||
Reference in New Issue
Block a user