pinokiod 3.9.0 → 3.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/kernel/api/filepicker/index.js +59 -0
- package/kernel/api/fs/index.js +6 -4
- package/kernel/api/index.js +123 -37
- package/kernel/api/input/index.js +2 -0
- package/kernel/api/web/index.js +6 -0
- package/kernel/bin/caddy.js +127 -0
- package/kernel/bin/cloudflared.js +1 -0
- package/kernel/bin/conda.js +10 -2
- package/kernel/bin/cuda.js +0 -16
- package/kernel/bin/ffmpeg.js +4 -6
- package/kernel/bin/git.js +55 -29
- package/kernel/bin/gxx.js +8 -6
- package/kernel/bin/huggingface.js +4 -5
- package/kernel/bin/index.js +347 -88
- package/kernel/bin/node.js +13 -6
- package/kernel/bin/py.js +1 -1
- package/kernel/bin/setup.js +146 -0
- package/kernel/bin/uv.js +4 -5
- package/kernel/bin/zip.js +7 -8
- package/kernel/connect/index.js +25 -0
- package/kernel/connect/providers/github/README.md +11 -0
- package/kernel/connect/providers/x/README.md +96 -0
- package/kernel/connect/providers/x/index.js +152 -0
- package/kernel/environment.js +50 -1
- package/kernel/index.js +152 -32
- package/kernel/info.js +4 -2
- package/kernel/kv.js +38 -0
- package/kernel/loader.js +13 -3
- package/kernel/peer.js +161 -0
- package/kernel/procs.js +116 -0
- package/kernel/prototype.js +62 -0
- package/kernel/router/common.js +42 -0
- package/kernel/router/connector.js +81 -0
- package/kernel/router/index.js +235 -0
- package/kernel/router/localhost_home_router.js +84 -0
- package/kernel/router/localhost_port_router.js +15 -0
- package/kernel/router/localhost_variable_router.js +37 -0
- package/kernel/router/peer_home_router.js +15 -0
- package/kernel/router/peer_peer_router.js +26 -0
- package/kernel/router/peer_port_router.js +45 -0
- package/kernel/router/peer_variable_router.js +46 -0
- package/kernel/router/processor.js +31 -0
- package/kernel/shell.js +141 -60
- package/kernel/shells.js +32 -17
- package/kernel/store.js +58 -0
- package/kernel/sysinfo.js +0 -1
- package/kernel/util.js +143 -36
- package/package.json +4 -1
- package/pipe/index.js +0 -2
- package/script/index.js +12 -0
- package/server/index.js +1473 -553
- package/server/public/Socket.js +5 -1
- package/server/public/SourceCodePro-Regular.ttf +0 -0
- package/server/public/SpaceMono-Bold.ttf +0 -0
- package/server/public/SpaceMono-BoldItalic.ttf +0 -0
- package/server/public/SpaceMono-Italic.ttf +0 -0
- package/server/public/SpaceMono-Regular.ttf +0 -0
- package/server/public/commander.js +40 -0
- package/server/public/common.js +60 -0
- package/server/public/dropzone-min.js +2 -0
- package/server/public/dropzone.css +1 -0
- package/server/public/filepond-plugin-file-validate-type.min.js +9 -0
- package/server/public/filepond-plugin-image-crop.min.js +9 -0
- package/server/public/filepond-plugin-image-edit.min.css +8 -0
- package/server/public/filepond-plugin-image-edit.min.js +9 -0
- package/server/public/filepond-plugin-image-exif-orientation.min.js +9 -0
- package/server/public/filepond-plugin-image-preview.min.css +8 -0
- package/server/public/filepond-plugin-image-preview.min.js +9 -0
- package/server/public/filepond-plugin-image-resize.min.js +9 -0
- package/server/public/filepond-plugin-image-transform.min.js +9 -0
- package/server/public/filepond.min.css +8 -0
- package/server/public/filepond.min.js +9 -0
- package/server/public/fscreator.js +174 -0
- package/server/public/fseditor.js +212 -0
- package/server/public/github.png +0 -0
- package/server/public/highlight-js.js +81 -0
- package/server/public/highlight.css +9 -0
- package/server/public/highlight.js +1244 -0
- package/server/public/install.js +17 -20
- package/server/public/modalinput.js +105 -9
- package/server/public/opener.js +3 -1
- package/server/public/pinokio-black.png +0 -0
- package/server/public/pinokio-black2.png +0 -0
- package/server/public/redoc.standalone.js +1832 -0
- package/server/public/style.css +211 -17
- package/server/public/swagger-ui-bundle.js +2 -0
- package/server/public/swagger-ui.css +3 -0
- package/server/public/x.js +63 -0
- package/server/socket.js +136 -39
- package/server/views/404.ejs +0 -1
- package/server/views/app.ejs +356 -90
- package/server/views/bootstrap.ejs +22 -19
- package/server/views/connect/x.ejs +324 -0
- package/server/views/connect.ejs +197 -0
- package/server/views/download.ejs +7 -1
- package/server/views/editor.ejs +68 -9
- package/server/views/explore.ejs +13 -10
- package/server/views/file_explorer.ejs +10 -37
- package/server/views/github.ejs +218 -0
- package/server/views/help.ejs +4 -3
- package/server/views/index.ejs +268 -118
- package/server/views/install.ejs +56 -29
- package/server/views/keys.ejs +276 -0
- package/server/views/network.ejs +889 -0
- package/server/views/partials/dynamic.ejs +9 -0
- package/server/views/partials/menu.ejs +7 -1
- package/server/views/prototype/index.ejs +311 -0
- package/server/views/prototype/show.ejs +383 -0
- package/server/views/redoc.ejs +18 -0
- package/server/views/required_env_editor.ejs +11 -2
- package/server/views/settings.ejs +38 -10
- package/server/views/setup.ejs +254 -0
- package/server/views/setup_home.ejs +192 -0
- package/server/views/shell.ejs +781 -0
- package/server/views/swaggerui.ejs +19 -0
- package/server/views/terminal.ejs +174 -42
- package/LICENSE +0 -7
- package/server/views/proxy.ejs +0 -405
package/kernel/procs.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const os = require('os')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const { fork, exec } = require('child_process');
|
|
4
|
+
const platform = os.platform();
|
|
5
|
+
class Procs {
|
|
6
|
+
constructor () {
|
|
7
|
+
console.log("Initializing procs")
|
|
8
|
+
}
|
|
9
|
+
getPortPidList(callback) {
|
|
10
|
+
const isWin = platform === 'win32';
|
|
11
|
+
const cmd = isWin ? 'netstat -ano -p tcp' : 'lsof -nP -iTCP -sTCP:LISTEN';
|
|
12
|
+
exec(cmd, (err, stdout) => {
|
|
13
|
+
if (err) return callback(err);
|
|
14
|
+
|
|
15
|
+
const results = [];
|
|
16
|
+
let pids = new Set()
|
|
17
|
+
const lines = stdout.trim().split('\n');
|
|
18
|
+
|
|
19
|
+
lines.forEach(line => {
|
|
20
|
+
if (isWin) {
|
|
21
|
+
// Skip headers
|
|
22
|
+
if (!line.startsWith(' TCP')) return;
|
|
23
|
+
const parts = line.trim().split(/\s+/);
|
|
24
|
+
const [ , localAddress, , state, pid ] = parts;
|
|
25
|
+
if (state !== 'LISTENING') return;
|
|
26
|
+
const chunks = localAddress.split(":")
|
|
27
|
+
const port = chunks.pop()
|
|
28
|
+
let ip = chunks.pop()
|
|
29
|
+
if (!ip || ip === "*") {
|
|
30
|
+
ip = "127.0.0.1:" + port
|
|
31
|
+
} else {
|
|
32
|
+
ip = localAddress
|
|
33
|
+
}
|
|
34
|
+
if (pids.has(pid+"/"+port)) return;
|
|
35
|
+
pids.add(pid+"/"+port)
|
|
36
|
+
results.push({ port, pid, ip });
|
|
37
|
+
} else {
|
|
38
|
+
if (!/LISTEN/.test(line)) return;
|
|
39
|
+
const parts = line.trim().split(/\s+/);
|
|
40
|
+
const pid = parts[1];
|
|
41
|
+
|
|
42
|
+
const match = line.match(/([^\s]+:\d+)\s/);
|
|
43
|
+
const localAddress = match?.[1];
|
|
44
|
+
const chunks = localAddress.split(":")
|
|
45
|
+
const port = chunks.pop()
|
|
46
|
+
let ip = chunks.pop()
|
|
47
|
+
if (!ip || ip === "*") {
|
|
48
|
+
ip = "127.0.0.1:" + port
|
|
49
|
+
} else {
|
|
50
|
+
ip = localAddress
|
|
51
|
+
}
|
|
52
|
+
//const portMatch = line.match(/:(\d+)\s/);
|
|
53
|
+
//const port = portMatch?.[1];
|
|
54
|
+
if (pids.has(pid+"/"+port)) return;
|
|
55
|
+
pids.add(pid+"/"+port)
|
|
56
|
+
if (pid && port) results.push({ port, pid, ip });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
callback(null, results);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
getPidToNameMap(callback) {
|
|
64
|
+
const isWin = platform === 'win32';
|
|
65
|
+
const cmd = isWin ? 'tasklist /fo csv /nh' : 'ps -Ao pid,comm';
|
|
66
|
+
exec(cmd, (err, stdout) => {
|
|
67
|
+
if (err) return callback(err);
|
|
68
|
+
const lines = stdout.trim().split('\n');
|
|
69
|
+
const map = {};
|
|
70
|
+
lines.forEach(line => {
|
|
71
|
+
if (isWin) {
|
|
72
|
+
const [name, pid] = line.split('","').map(s => s.replace(/(^"|"$)/g, ''));
|
|
73
|
+
map[pid] = name;
|
|
74
|
+
} else {
|
|
75
|
+
const [pid, ...nameParts] = line.trim().split(/\s+/);
|
|
76
|
+
map[pid] = nameParts.join(' ');
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
callback(null, map);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
async refresh() {
|
|
83
|
+
let map = {}
|
|
84
|
+
let list = await new Promise((resolve, reject) => {
|
|
85
|
+
this.getPortPidList((err, portPidList) => {
|
|
86
|
+
if (err) {
|
|
87
|
+
reject(err)
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
this.getPidToNameMap((err, pidToName) => {
|
|
92
|
+
if (err) {
|
|
93
|
+
reject(err)
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let list = portPidList.map(({ port, pid, ip }) => {
|
|
98
|
+
const fullname = pidToName[pid] || 'Unknown';
|
|
99
|
+
const name = fullname.split(path.sep).pop()
|
|
100
|
+
if (["caddy", "caddy.exe"].includes(name)) {
|
|
101
|
+
this.caddy_pid = pid
|
|
102
|
+
return null
|
|
103
|
+
} else {
|
|
104
|
+
map["" + pid] = fullname
|
|
105
|
+
return { port, pid , name, fullname, ip }
|
|
106
|
+
}
|
|
107
|
+
}).filter((x) => { return x })
|
|
108
|
+
resolve(list)
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
})
|
|
112
|
+
this.info = list
|
|
113
|
+
this.map = map
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
module.exports = Procs
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const { glob, sync, hasMagic } = require('glob-gitignore')
|
|
4
|
+
const marked = require('marked')
|
|
5
|
+
class Proto {
|
|
6
|
+
constructor(kernel) {
|
|
7
|
+
this.kernel = kernel
|
|
8
|
+
}
|
|
9
|
+
async init() {
|
|
10
|
+
|
|
11
|
+
// if ~/pinokio/prototype doesn't exist, clone
|
|
12
|
+
let exists = await this.kernel.exists("prototype")
|
|
13
|
+
if (!exists) {
|
|
14
|
+
console.log("prototype doesn't exist. cloning...")
|
|
15
|
+
await fs.promises.mkdir(this.kernel.path("prototype"), { recursive: true }).catch((e) => { })
|
|
16
|
+
await this.kernel.exec({
|
|
17
|
+
message: "git clone https://github.com/peanutcocktail/prototype system",
|
|
18
|
+
path: this.kernel.path("prototype")
|
|
19
|
+
}, (e) => {
|
|
20
|
+
process.stdout.write(e.raw)
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
let cwd = path.resolve(this.kernel.homedir, "prototype")
|
|
26
|
+
let prototype_paths = (await glob('**/pinokio.js', { cwd }))
|
|
27
|
+
let prototype_dir = path.resolve(this.kernel.homedir, "prototype")
|
|
28
|
+
this.items = []
|
|
29
|
+
this.kv = {}
|
|
30
|
+
for(let prototype_path of prototype_paths) {
|
|
31
|
+
let proto = path.dirname(prototype_path)
|
|
32
|
+
let pinokiojs = path.resolve(prototype_dir, prototype_path)
|
|
33
|
+
let config = await this.kernel.require(pinokiojs)
|
|
34
|
+
if (config && config.run) {
|
|
35
|
+
if (config.icon) {
|
|
36
|
+
config.icon = "/prototype/" + proto + "/" + config.icon
|
|
37
|
+
} else {
|
|
38
|
+
config.icon === "/pinokio-black.png"
|
|
39
|
+
}
|
|
40
|
+
let c = {
|
|
41
|
+
id: proto,
|
|
42
|
+
...config
|
|
43
|
+
}
|
|
44
|
+
this.items.push(c)
|
|
45
|
+
this.kv[proto] = c
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async readme(proto) {
|
|
50
|
+
console.log("proto.readme", proto)
|
|
51
|
+
let readme_path = path.resolve(this.kernel.homedir, "prototype", proto, "README.md")
|
|
52
|
+
let readme
|
|
53
|
+
try {
|
|
54
|
+
readme = await fs.promises.readFile(readme_path, "utf8")
|
|
55
|
+
} catch (e) {
|
|
56
|
+
readme = ""
|
|
57
|
+
}
|
|
58
|
+
console.log({ readme_path, readme })
|
|
59
|
+
return marked.parse(readme)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
module.exports = Proto
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const Processor = require('./processor')
|
|
2
|
+
class Common extends Processor {
|
|
3
|
+
constructor (router) {
|
|
4
|
+
super()
|
|
5
|
+
this.router = router
|
|
6
|
+
}
|
|
7
|
+
handle({ match, dial, host }) {
|
|
8
|
+
let handler = [{
|
|
9
|
+
"handler": "reverse_proxy",
|
|
10
|
+
"upstreams": [{ "dial": dial }],
|
|
11
|
+
"headers": {
|
|
12
|
+
"request": {
|
|
13
|
+
"set": {
|
|
14
|
+
"X-Forwarded-Proto": ["https"],
|
|
15
|
+
"X-Forwarded-Host": ["{http.request.host}"]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"response": {
|
|
19
|
+
"set": {
|
|
20
|
+
"Access-Control-Allow-Origin": ["*"],
|
|
21
|
+
"Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
|
|
22
|
+
"Access-Control-Allow-Headers": ["*"],
|
|
23
|
+
"Vary": ["Origin"]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}]
|
|
28
|
+
|
|
29
|
+
// if the dial port has been overridden by router.custom_routers, use that instead
|
|
30
|
+
let parsed_dial = this.parse_ip(dial)
|
|
31
|
+
let override_handler = this.router.custom_routers[String(parsed_dial.port)]
|
|
32
|
+
if (override_handler) {
|
|
33
|
+
handler = override_handler
|
|
34
|
+
}
|
|
35
|
+
this.router.config.apps.http.servers.main.routes.push({
|
|
36
|
+
"match": [{ "host": [match] }],
|
|
37
|
+
"handle": handler
|
|
38
|
+
})
|
|
39
|
+
this.router.add({ host, dial, match })
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
module.exports = Common
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const Processor = require('./processor')
|
|
2
|
+
class Connector extends Processor {
|
|
3
|
+
constructor(router) {
|
|
4
|
+
super()
|
|
5
|
+
this.router = router
|
|
6
|
+
}
|
|
7
|
+
handle ({ match, connector, dial, }) {
|
|
8
|
+
let connector_name = connector.host + ":" + connector.port
|
|
9
|
+
let listener = "0.0.0.0:PORT_PLACEHOLDER_" + connector_name
|
|
10
|
+
let listener_pointer = connector.host + ":PORT_PLACEHOLDER_" + connector_name
|
|
11
|
+
let port_placeholder = "PORT_PLACEHOLDER_" + connector_name
|
|
12
|
+
|
|
13
|
+
let handler = [{
|
|
14
|
+
"handler": "reverse_proxy",
|
|
15
|
+
"upstreams": [{ "dial": dial }],
|
|
16
|
+
"headers": {
|
|
17
|
+
"request": {
|
|
18
|
+
"set": {
|
|
19
|
+
"X-Forwarded-Proto": ["{http.request.header.X-Forwarded-Proto}"],
|
|
20
|
+
//"X-Forwarded-Proto": ["{http.request.scheme}"],
|
|
21
|
+
//"X-Forwarded-Proto": ["https"],
|
|
22
|
+
//"X-Forwarded-Host": ["{http.request.host}"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"response": {
|
|
26
|
+
"set": {
|
|
27
|
+
"Access-Control-Allow-Origin": ["*"],
|
|
28
|
+
"Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
|
|
29
|
+
"Access-Control-Allow-Headers": ["*"],
|
|
30
|
+
"Vary": ["Origin"]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}]
|
|
35
|
+
// if the dial port has been overridden by router.custom_routers, use that instead
|
|
36
|
+
let parsed_dial = this.parse_ip(dial)
|
|
37
|
+
let override_handler = this.router.custom_routers[String(parsed_dial.port)]
|
|
38
|
+
if (override_handler) {
|
|
39
|
+
handler = override_handler
|
|
40
|
+
}
|
|
41
|
+
if(!this.router.config.apps.http.servers[connector_name]) {
|
|
42
|
+
this.router.config.apps.http.servers[connector_name] = {
|
|
43
|
+
"listen": [listener],
|
|
44
|
+
"routes": [{
|
|
45
|
+
"handle": handler
|
|
46
|
+
}]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
this.router.config.apps.http.servers.main.routes.push({
|
|
50
|
+
"match": [{
|
|
51
|
+
"host": [match],
|
|
52
|
+
}],
|
|
53
|
+
"handle": [
|
|
54
|
+
{
|
|
55
|
+
"handler": "reverse_proxy",
|
|
56
|
+
"upstreams": [{ "dial": listener_pointer }],
|
|
57
|
+
"headers": {
|
|
58
|
+
"request": {
|
|
59
|
+
"set": {
|
|
60
|
+
//"X-Forwarded-Proto": ["https"],
|
|
61
|
+
//"Origin": "localhost",
|
|
62
|
+
"X-Forwarded-Proto": ["{http.request.scheme}"],
|
|
63
|
+
"X-Forwarded-Host": ["{http.request.host}"]
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"response": {
|
|
67
|
+
"set": {
|
|
68
|
+
"Access-Control-Allow-Origin": ["*"],
|
|
69
|
+
"Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
|
|
70
|
+
"Access-Control-Allow-Headers": ["*"],
|
|
71
|
+
"Vary": ["Origin"]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
]
|
|
77
|
+
})
|
|
78
|
+
this.router.add({ host: connector.host, dial: listener_pointer, match })
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
module.exports = Connector
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
const axios = require('axios')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const { glob, sync, hasMagic } = require('glob-gitignore')
|
|
4
|
+
const Util = require('../util')
|
|
5
|
+
const LocalhostHomeRouter = require('./localhost_home_router')
|
|
6
|
+
const LocalhostVariableRouter = require('./localhost_variable_router')
|
|
7
|
+
const LocalhostPortRouter = require('./localhost_port_router')
|
|
8
|
+
const PeerHomeRouter = require('./peer_home_router')
|
|
9
|
+
const PeerVariableRouter = require('./peer_variable_router')
|
|
10
|
+
const PeerPortRouter = require('./peer_port_router')
|
|
11
|
+
const PeerPeerRouter = require('./peer_peer_router')
|
|
12
|
+
const Environment = require("../environment")
|
|
13
|
+
class Router {
|
|
14
|
+
constructor(kernel) {
|
|
15
|
+
this.kernel = kernel
|
|
16
|
+
this.localhost_home_router = new LocalhostHomeRouter(this)
|
|
17
|
+
this.localhost_variable_router = new LocalhostVariableRouter(this)
|
|
18
|
+
this.localhost_port_router = new LocalhostPortRouter(this)
|
|
19
|
+
this.peer_home_router = new PeerHomeRouter(this)
|
|
20
|
+
this.peer_variable_router = new PeerVariableRouter(this)
|
|
21
|
+
this.peer_port_router = new PeerPortRouter(this)
|
|
22
|
+
this.peer_peer_router = new PeerPeerRouter(this)
|
|
23
|
+
this.default_prefix = "pinokio"
|
|
24
|
+
this.default_suffix = "localhost"
|
|
25
|
+
this.default_match = this.default_prefix + "." + this.default_suffix
|
|
26
|
+
this.default_port = "42000"
|
|
27
|
+
this.default_host = "127.0.0.1"
|
|
28
|
+
|
|
29
|
+
this.info = {}
|
|
30
|
+
this.mapping = {}
|
|
31
|
+
this.port_mapping = {} // 127.0.0.1 => 192.168,..
|
|
32
|
+
this.local_network_mapping = {}
|
|
33
|
+
this.custom_routers = {}
|
|
34
|
+
}
|
|
35
|
+
async init() {
|
|
36
|
+
// if ~/pinokio/network doesn't exist, clone
|
|
37
|
+
let exists = await this.kernel.exists("network/system")
|
|
38
|
+
if (!exists) {
|
|
39
|
+
console.log("network doesn't exist. cloning...")
|
|
40
|
+
await fs.promises.mkdir(this.kernel.path("network"), { recursive: true }).catch((e) => { })
|
|
41
|
+
await this.kernel.exec({
|
|
42
|
+
message: "git clone https://github.com/peanutcocktail/network system",
|
|
43
|
+
path: this.kernel.path("network")
|
|
44
|
+
}, (e) => {
|
|
45
|
+
process.stdout.write(e.raw)
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
let cwd = path.resolve(this.kernel.homedir, "network")
|
|
51
|
+
let router_paths = (await glob('**/*.json', { cwd }))
|
|
52
|
+
let router_dir = path.resolve(this.kernel.homedir, "network")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
// create a custom_map that maps port to custom router declarations
|
|
56
|
+
/*
|
|
57
|
+
custom_routers = {
|
|
58
|
+
PORT1: <caddy handler>,
|
|
59
|
+
PORT2: <caddy handler>,
|
|
60
|
+
...
|
|
61
|
+
}
|
|
62
|
+
*/
|
|
63
|
+
this.custom_routers = {}
|
|
64
|
+
for(let router_path of router_paths) {
|
|
65
|
+
let router_abs_path = this.kernel.path("network", router_path)
|
|
66
|
+
let config = await this.kernel.require(router_abs_path)
|
|
67
|
+
for(let port in config) {
|
|
68
|
+
this.custom_routers[port] = config[port]
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let env = await Environment.get(this.kernel.homedir)
|
|
73
|
+
this.active = false
|
|
74
|
+
if (env && env.PINOKIO_HTTPS_ACTIVE && (env.PINOKIO_HTTPS_ACTIVE==="1" || env.PINOKIO_HTTPS_ACTIVE.toLowerCase()==="true")) {
|
|
75
|
+
this.active = true
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
async add({ host, match, dial }) {
|
|
81
|
+
if (!this._mapping[host]) {
|
|
82
|
+
this._mapping[host] = {}
|
|
83
|
+
}
|
|
84
|
+
if (!this._mapping[host][dial]) {
|
|
85
|
+
this._mapping[host][dial] = new Set()
|
|
86
|
+
}
|
|
87
|
+
this._mapping[host][dial].add(match)
|
|
88
|
+
}
|
|
89
|
+
_info() {
|
|
90
|
+
let mapping = {}
|
|
91
|
+
for(let host in this.mapping) {
|
|
92
|
+
let internal_maps = this.mapping[host]
|
|
93
|
+
if (!mapping[host]) {
|
|
94
|
+
mapping[host] = {}
|
|
95
|
+
}
|
|
96
|
+
for(let url in internal_maps) {
|
|
97
|
+
mapping[host][url] = Array.from(internal_maps[url])
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
let host_mapping = mapping[this.kernel.peer.host]
|
|
101
|
+
if (host_mapping) {
|
|
102
|
+
for(let key in host_mapping) {
|
|
103
|
+
for(let cache_key in this.port_cache) {
|
|
104
|
+
if (key.endsWith(cache_key)) {
|
|
105
|
+
let transformed = key.replace(":" + cache_key, '')
|
|
106
|
+
let port = this.port_cache[cache_key]
|
|
107
|
+
host_mapping[transformed + ":" + port] = host_mapping[key]
|
|
108
|
+
delete host_mapping[key]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
mapping[this.kernel.peer.host] = host_mapping
|
|
113
|
+
}
|
|
114
|
+
return mapping
|
|
115
|
+
}
|
|
116
|
+
/*
|
|
117
|
+
returns only the published peer info
|
|
118
|
+
{
|
|
119
|
+
<peer1 host>: {
|
|
120
|
+
<dial1>: [<match1>, <match2>, ..],
|
|
121
|
+
<dial2>: [<match1>, <match2>, ..],
|
|
122
|
+
},
|
|
123
|
+
<peer2 host>: {
|
|
124
|
+
<dial1>: [<match1>, <match2>, ..],
|
|
125
|
+
<dial2>: [<match1>, <match2>, ..],
|
|
126
|
+
},
|
|
127
|
+
}
|
|
128
|
+
*/
|
|
129
|
+
published() {
|
|
130
|
+
let pub = {}
|
|
131
|
+
if (this.info) {
|
|
132
|
+
let routes = this.info[this.kernel.peer.host]
|
|
133
|
+
for(let dial in routes) {
|
|
134
|
+
let matches = routes[dial]
|
|
135
|
+
pub[dial] = matches
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return pub
|
|
139
|
+
}
|
|
140
|
+
async fill() {
|
|
141
|
+
const jsonString = JSON.stringify(this.config)
|
|
142
|
+
// find all PORT_PLACEHOLDER patterns
|
|
143
|
+
const matches = jsonString.match(/:PORT_PLACEHOLDER_[0-9.:]+/g)
|
|
144
|
+
|
|
145
|
+
// iterate through them and see if the port already exists
|
|
146
|
+
let count = matches ? new Set(matches).size : 0
|
|
147
|
+
let new_config
|
|
148
|
+
if (count > 0) {
|
|
149
|
+
let ports = await this.kernel.ports(count)
|
|
150
|
+
let response = Util.fill_object(this.config, /PORT_PLACEHOLDER_.+/, ports, this.port_cache)
|
|
151
|
+
this.config = response.result
|
|
152
|
+
let replaced_map = response.replaced_map
|
|
153
|
+
for(let key in replaced_map) {
|
|
154
|
+
// local_share_ip :- 192.168....
|
|
155
|
+
let local_share_key = key.replace("PORT_PLACEHOLDER_", "")
|
|
156
|
+
let chunks = local_share_key.split(":")
|
|
157
|
+
let original_port = chunks[chunks.length-1]
|
|
158
|
+
let local_share_ip = chunks.slice(0, chunks.length-1).join(":")
|
|
159
|
+
let local_share_port = replaced_map[key]
|
|
160
|
+
if (!this.local_network_mapping[local_share_ip]) {
|
|
161
|
+
this.local_network_mapping[local_share_ip] = {}
|
|
162
|
+
}
|
|
163
|
+
this.local_network_mapping[local_share_ip][original_port] = local_share_port
|
|
164
|
+
//let original_port = key.replace("PORT_PLACEHOLDER_", "")
|
|
165
|
+
this.port_mapping[original_port] = replaced_map[key]
|
|
166
|
+
}
|
|
167
|
+
this.port_cache = replaced_map
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
// set local config
|
|
173
|
+
async local() {
|
|
174
|
+
this._mapping = {}
|
|
175
|
+
this.localhost_home_router.handle()
|
|
176
|
+
this.localhost_variable_router.handle(this.kernel.memory.local)
|
|
177
|
+
for(let proc of this.kernel.processes.info) {
|
|
178
|
+
this.localhost_port_router.handle(proc)
|
|
179
|
+
}
|
|
180
|
+
if (this.kernel.peer.active) {
|
|
181
|
+
for(let host in this.kernel.peer.info) {
|
|
182
|
+
let peer = this.kernel.peer.info[host]
|
|
183
|
+
if (peer.host === this.kernel.peer.host) {
|
|
184
|
+
this.peer_home_router.handle(peer)
|
|
185
|
+
this.peer_variable_router.handle(peer)
|
|
186
|
+
this.peer_port_router.handle(peer)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
await this.fill()
|
|
190
|
+
}
|
|
191
|
+
this.mapping = this._mapping
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// set remote config
|
|
195
|
+
async remote() {
|
|
196
|
+
for(let host in this.kernel.peer.info) {
|
|
197
|
+
let peer = this.kernel.peer.info[host]
|
|
198
|
+
if (peer.host !== this.kernel.peer.host) {
|
|
199
|
+
this.peer_peer_router.handle(peer)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//await this.fill()
|
|
203
|
+
this.mapping = this._mapping
|
|
204
|
+
this.info = this._info()
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// update caddy config
|
|
208
|
+
async update() {
|
|
209
|
+
if (JSON.stringify(this.config) === JSON.stringify(this.old_config)) {
|
|
210
|
+
// console.log("config hasn't updated")
|
|
211
|
+
} else {
|
|
212
|
+
console.log("caddy config has updated", this.config)
|
|
213
|
+
try {
|
|
214
|
+
let response = await axios.post('http://127.0.0.1:2019/load', this.config, {
|
|
215
|
+
headers: { 'Content-Type': 'application/json' }
|
|
216
|
+
})
|
|
217
|
+
// console.log("Caddy Response", { response })
|
|
218
|
+
this.old_config = this.config
|
|
219
|
+
} catch (e) {
|
|
220
|
+
console.log("EEEEEEEEEEEEE", e)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async check() {
|
|
225
|
+
try {
|
|
226
|
+
let res = await axios.get(`http://localhost:2019/config/`, {
|
|
227
|
+
timeout: 2000
|
|
228
|
+
})
|
|
229
|
+
return res.data
|
|
230
|
+
} catch (e) {
|
|
231
|
+
return null
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
module.exports = Router
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
class LocalhostHomeRouter {
|
|
2
|
+
constructor(router) {
|
|
3
|
+
this.router = router
|
|
4
|
+
}
|
|
5
|
+
handle () {
|
|
6
|
+
this.router.add({ host: this.router.kernel.peer.host, dial: this.router.default_host + ":" + this.router.default_port, match: this.router.default_match })
|
|
7
|
+
this.router.config = {
|
|
8
|
+
"apps": {
|
|
9
|
+
"http": {
|
|
10
|
+
"servers": {
|
|
11
|
+
"main": {
|
|
12
|
+
"listen": [":443"],
|
|
13
|
+
"routes": [
|
|
14
|
+
{
|
|
15
|
+
"match": [{ "method": ["OPTIONS"] }],
|
|
16
|
+
"handle": [
|
|
17
|
+
{
|
|
18
|
+
"handler": "headers",
|
|
19
|
+
"response": {
|
|
20
|
+
"set": {
|
|
21
|
+
"Access-Control-Allow-Origin": ["*"],
|
|
22
|
+
"Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
|
|
23
|
+
"Access-Control-Allow-Headers": ["*"],
|
|
24
|
+
"Vary": ["Origin"],
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"handler": "static_response",
|
|
30
|
+
"status_code": 204
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"match": [{ "host": [ this.router.default_match ] }],
|
|
36
|
+
"handle": [
|
|
37
|
+
{
|
|
38
|
+
"handler": "reverse_proxy",
|
|
39
|
+
"upstreams": [{ "dial": this.router.default_host + ":" + this.router.default_port }],
|
|
40
|
+
"headers": {
|
|
41
|
+
"request": {
|
|
42
|
+
"set": {
|
|
43
|
+
"X-Forwarded-Proto": ["https"],
|
|
44
|
+
"X-Forwarded-Host": ["{http.request.host}"]
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"response": {
|
|
48
|
+
"set": {
|
|
49
|
+
"Access-Control-Allow-Origin": ["*"],
|
|
50
|
+
"Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
|
|
51
|
+
"Access-Control-Allow-Headers": ["*"],
|
|
52
|
+
"Vary": ["Origin"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"logging": {
|
|
65
|
+
"logs": {
|
|
66
|
+
"default": {
|
|
67
|
+
"writer": {
|
|
68
|
+
"output": "file",
|
|
69
|
+
"filename": this.router.kernel.path("logs/caddy.log"),
|
|
70
|
+
"roll": true,
|
|
71
|
+
"roll_size_mb": 1,
|
|
72
|
+
"roll_keep": 1,
|
|
73
|
+
"roll_keep_days": 1,
|
|
74
|
+
"roll_gzip": false,
|
|
75
|
+
"roll_local_time": true
|
|
76
|
+
},
|
|
77
|
+
"level": "INFO"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
module.exports = LocalhostHomeRouter
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const Common = require('./common')
|
|
2
|
+
class LocalhostPortRouter {
|
|
3
|
+
constructor(router) {
|
|
4
|
+
this.router = router
|
|
5
|
+
this.common = new Common(router)
|
|
6
|
+
}
|
|
7
|
+
handle (proc) {
|
|
8
|
+
this.common.handle({
|
|
9
|
+
match: `${proc.port}.localhost`,
|
|
10
|
+
dial: proc.ip,
|
|
11
|
+
host: this.router.kernel.peer.host,
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
module.exports = LocalhostPortRouter
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const Common = require('./common')
|
|
3
|
+
const Processor = require('./processor')
|
|
4
|
+
class LocalhostVariableRouter extends Processor {
|
|
5
|
+
constructor(router) {
|
|
6
|
+
super()
|
|
7
|
+
this.router = router
|
|
8
|
+
this.common = new Common(router)
|
|
9
|
+
}
|
|
10
|
+
handle (local) {
|
|
11
|
+
for(let script_path in local) {
|
|
12
|
+
let local_variables_for_script = local[script_path]
|
|
13
|
+
for(let key in local_variables_for_script) {
|
|
14
|
+
let val = local_variables_for_script[key]
|
|
15
|
+
if (val.startsWith("http")) {
|
|
16
|
+
let dial = val.replace(/https?:\/\//, '')
|
|
17
|
+
let name = this.api_name(this.router.kernel.platform, this.router.kernel.homedir, script_path)
|
|
18
|
+
if (this.has_port(dial)) {
|
|
19
|
+
if (key === "url") {
|
|
20
|
+
this.common.handle({
|
|
21
|
+
match: `${name}.localhost`.toLowerCase(),
|
|
22
|
+
dial,
|
|
23
|
+
host: this.router.kernel.peer.host,
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
this.common.handle({
|
|
27
|
+
match: `${key}.${name}.localhost`.toLowerCase(),
|
|
28
|
+
dial,
|
|
29
|
+
host: this.router.kernel.peer.host,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
module.exports = LocalhostVariableRouter
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const Common = require('./common')
|
|
2
|
+
class PeerHomeRouter {
|
|
3
|
+
constructor(router) {
|
|
4
|
+
this.router = router
|
|
5
|
+
this.common = new Common(router)
|
|
6
|
+
}
|
|
7
|
+
handle(peer) {
|
|
8
|
+
this.common.handle({
|
|
9
|
+
match: `${this.router.default_prefix}.${peer.name}.${this.router.default_suffix}`,
|
|
10
|
+
dial: `${peer.host}:${this.router.default_port}`,
|
|
11
|
+
host: peer.host
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
module.exports = PeerHomeRouter
|