pinokiod 3.8.26 → 3.8.28

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/caddy.js CHANGED
@@ -4,34 +4,16 @@ class Caddy {
4
4
  constructor(kernel) {
5
5
  this.kernel = kernel
6
6
  }
7
- async update() {
8
- this.mapping = {}
9
- let payload = await this.payload()
10
- console.log("Make request to caddy", JSON.stringify(payload, null, 2))
11
- let response = await axios.post('http://127.0.0.1:2019/load', payload, {
12
- headers: { 'Content-Type': 'application/json' }
13
- }).catch((e) => {
14
- console.log("EEEEEEEEEEEEE", e)
15
- })
16
- console.log("Caddy Response", { response })
17
- }
18
- async procs (payload) {
19
- console.log("####### procs", payload)
20
- let list = this.kernel.processes.list
21
- if (!list) {
22
- list = await this.kernel.processes.refresh()
23
- }
24
- for(let item of list) {
25
- let url = `${item.port}.localhost`
26
- this.mapping[item.ip] = url
7
+ peers_home (payload) {
8
+ let peers = this.kernel.peer.get()
9
+ for(let ip of peers) {
10
+ let account = this.kernel.peer.account(ip)
27
11
  payload.apps.http.servers.main.routes.push({
28
- "match": [{
29
- "host": [url],
30
- }],
12
+ "match": [{ "host": [`pinokio.${account}.localhost`] }],
31
13
  "handle": [
32
14
  {
33
15
  "handler": "reverse_proxy",
34
- "upstreams": [{ "dial": item.ip }]
16
+ "upstreams": [{ "dial": `${ip}:42000` }]
35
17
  },
36
18
  {
37
19
  "handler": "headers",
@@ -49,6 +31,136 @@ class Caddy {
49
31
  }
50
32
  return payload
51
33
  }
34
+ home () {
35
+ return {
36
+ "apps": {
37
+ "http": {
38
+ "servers": {
39
+ "main": {
40
+ "listen": [":443"],
41
+ "routes": [
42
+ {
43
+ "match": [{ "method": ["OPTIONS"] }],
44
+ "handle": [
45
+ {
46
+ "handler": "headers",
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
+ "handler": "static_response",
58
+ "status_code": 204
59
+ }
60
+ ]
61
+ },
62
+ {
63
+ "match": [{ "host": [`pinokio.localhost`] }],
64
+ "handle": [
65
+ {
66
+ "handler": "reverse_proxy",
67
+ "upstreams": [{ "dial": "127.0.0.1:42000" }]
68
+ },
69
+ {
70
+ "handler": "headers",
71
+ "response": {
72
+ "set": {
73
+ "Access-Control-Allow-Origin": ["*"],
74
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
75
+ "Access-Control-Allow-Headers": ["*"],
76
+ "Vary": ["Origin"]
77
+ }
78
+ }
79
+ }
80
+ ]
81
+ },
82
+ ]
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ peers_locals(payload) {
90
+ let peers = this.kernel.peer.get()
91
+ for(let ip of peers) {
92
+ let account = this.kernel.peer.account(ip)
93
+ let local = this.kernel.peer.local(ip)
94
+ // construct Caddy update payload
95
+ console.log({ local })
96
+ for(let script_path in local) {
97
+ let local_variables = local[script_path]
98
+ console.log({ local_variables })
99
+ for(let key in local_variables) {
100
+ let val = local_variables[key]
101
+ if (val.startsWith("http")) {
102
+ val = val.replace(/https?:\/\//, '')
103
+
104
+ // replace 127,0.0.1 or localhost with the 192.168 address
105
+ val = val.replace(/localhost|127\.0\.0\.1/g, ip)
106
+ let api_path = path.resolve(this.kernel.peer.homedir(ip), "api")
107
+ let rel_path = path.relative(api_path, script_path)
108
+ let name = rel_path.split(path.sep)[0]
109
+ console.log({ api_path, rel_path, name, val })
110
+ if (key === "url") {
111
+ let url = `${name}.${account}.localhost`.toLowerCase()
112
+ this.mapping[val] = url
113
+ payload.apps.http.servers.main.routes.push({
114
+ "match": [{
115
+ "host": [url]
116
+ }],
117
+ "handle": [
118
+ {
119
+ "handler": "reverse_proxy",
120
+ "upstreams": [{ "dial": val }]
121
+ },
122
+ {
123
+ "handler": "headers",
124
+ "response": {
125
+ "set": {
126
+ "Access-Control-Allow-Origin": ["*"],
127
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
128
+ "Access-Control-Allow-Headers": ["*"],
129
+ "Vary": ["Origin"]
130
+ }
131
+ }
132
+ }
133
+ ]
134
+ })
135
+ }
136
+ payload.apps.http.servers.main.routes.push({
137
+ "match": [{
138
+ "host": [`${key}.${name}${account}.localhost`.toLowerCase()],
139
+ }],
140
+ "handle": [
141
+ {
142
+ "handler": "reverse_proxy",
143
+ "upstreams": [{ "dial": val }]
144
+ },
145
+ {
146
+ "handler": "headers",
147
+ "response": {
148
+ "set": {
149
+ "Access-Control-Allow-Origin": ["*"],
150
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
151
+ "Access-Control-Allow-Headers": ["*"],
152
+ "Vary": ["Origin"]
153
+ }
154
+ }
155
+ }
156
+ ]
157
+ })
158
+ }
159
+ }
160
+ }
161
+ }
162
+ return payload
163
+ }
52
164
  locals (payload) {
53
165
  // construct Caddy update payload
54
166
  let local = this.kernel.memory.local;
@@ -70,13 +182,8 @@ class Caddy {
70
182
  payload.apps.http.servers.main.routes.push({
71
183
  "match": [{
72
184
  "host": [url]
73
- //"path": [`/local/${key}/${uri}/*`]
74
185
  }],
75
186
  "handle": [
76
- //{
77
- // "handler": "rewrite",
78
- // "uri": "/"
79
- //},
80
187
  {
81
188
  "handler": "reverse_proxy",
82
189
  "upstreams": [{ "dial": val }]
@@ -98,13 +205,8 @@ class Caddy {
98
205
  payload.apps.http.servers.main.routes.push({
99
206
  "match": [{
100
207
  "host": [`${key}.${name}.localhost`.toLowerCase()],
101
- //"path": [`/local/${key}/${uri}/*`]
102
208
  }],
103
209
  "handle": [
104
- //{
105
- // "handler": "rewrite",
106
- // "uri": "/"
107
- //},
108
210
  {
109
211
  "handler": "reverse_proxy",
110
212
  "upstreams": [{ "dial": val }]
@@ -127,66 +229,113 @@ class Caddy {
127
229
  }
128
230
  return payload
129
231
  }
130
- home () {
131
- return {
132
- "apps": {
133
- "http": {
134
- "servers": {
135
- "main": {
136
- //"listen": ["127.0.0.1:443"],
137
- "listen": [":443"],
138
- "routes": [
139
- {
140
- "match": [{ "method": ["OPTIONS"] }],
141
- "handle": [
142
- {
143
- "handler": "headers",
144
- "response": {
145
- "set": {
146
- "Access-Control-Allow-Origin": ["*"],
147
- "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
148
- "Access-Control-Allow-Headers": ["*"],
149
- "Vary": ["Origin"]
150
- }
151
- }
152
- },
153
- {
154
- "handler": "static_response",
155
- "status_code": 204
156
- }
157
- ]
158
- },
159
- {
160
- "match": [{ "host": ["pinokio.localhost"] }],
161
- "handle": [
162
- {
163
- "handler": "reverse_proxy",
164
- "upstreams": [{ "dial": "127.0.0.1:42000" }]
165
- },
166
- {
167
- "handler": "headers",
168
- "response": {
169
- "set": {
170
- "Access-Control-Allow-Origin": ["*"],
171
- "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
172
- "Access-Control-Allow-Headers": ["*"],
173
- "Vary": ["Origin"]
174
- }
175
- }
176
- }
177
- ]
178
- },
179
- ]
232
+ async peers_procs (payload) {
233
+ console.log("####### procs", payload)
234
+ let list = this.kernel.peer.get()
235
+ for(let ip of list) {
236
+ let account = this.kernel.peer.account(ip)
237
+
238
+ // caddy_mapping := { IP => HTTPS_DOMAIN }
239
+ let caddy_mapping = this.kernel.peer.caddy(ip)
240
+ for(let app_ip in caddy_mapping) {
241
+ let https_domain = caddy_mapping[app_ip]
242
+ let remote_app_ip = app_ip.replace(/localhost|127\.0\.0\.1/g, ip)
243
+ // https_domain <port>.localhost
244
+ let url = https_domain.replace(/\.localhost$/, '') + `${account}.localhost`
245
+ this.mapping[remote_app_ip] = url
246
+ payload.apps.http.servers.main.routes.push({
247
+ "match": [{
248
+ "host": [url],
249
+ }],
250
+ "handle": [
251
+ {
252
+ "handler": "reverse_proxy",
253
+ "upstreams": [{ "dial": remote_app_ip }]
254
+ },
255
+ {
256
+ "handler": "headers",
257
+ "response": {
258
+ "set": {
259
+ "Access-Control-Allow-Origin": ["*"],
260
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
261
+ "Access-Control-Allow-Headers": ["*"],
262
+ "Vary": ["Origin"]
263
+ }
264
+ }
180
265
  }
181
- }
182
- }
266
+ ]
267
+ })
183
268
  }
184
269
  }
270
+ return payload
271
+ }
272
+ async procs (payload) {
273
+ console.log("####### procs", payload)
274
+ let list = this.kernel.processes.list
275
+ if (!list) {
276
+ list = await this.kernel.processes.refresh()
277
+ }
278
+ for(let item of list) {
279
+ let url = `${item.port}.localhost`
280
+ this.mapping[item.ip] = url
281
+ payload.apps.http.servers.main.routes.push({
282
+ "match": [{
283
+ "host": [url],
284
+ }],
285
+ "handle": [
286
+ {
287
+ "handler": "reverse_proxy",
288
+ "upstreams": [{ "dial": item.ip }]
289
+ },
290
+ {
291
+ "handler": "headers",
292
+ "response": {
293
+ "set": {
294
+ "Access-Control-Allow-Origin": ["*"],
295
+ "Access-Control-Allow-Methods": ["GET, POST, OPTIONS, PUT, DELETE"],
296
+ "Access-Control-Allow-Headers": ["*"],
297
+ "Vary": ["Origin"]
298
+ }
299
+ }
300
+ }
301
+ ]
302
+ })
303
+ }
304
+ return payload
305
+ }
306
+ peers(payload) {
307
+ let peers = this.kernel.peer.get()
308
+ for(let peer of peers) {
309
+ let account = peer.username
310
+ }
311
+ }
312
+ async update() {
313
+ this.mapping = {}
314
+ let payload = await this.payload()
315
+ console.log("Make request to caddy", JSON.stringify(payload, null, 2))
316
+ let response = await axios.post('http://127.0.0.1:2019/load', payload, {
317
+ headers: { 'Content-Type': 'application/json' }
318
+ }).catch((e) => {
319
+ console.log("EEEEEEEEEEEEE", e)
320
+ })
321
+ console.log("Caddy Response", { response })
185
322
  }
186
323
  async payload () {
324
+
325
+ // localhost home
187
326
  let payload = this.home()
327
+ // peers home
328
+ let peers = this.kernel.peer.get()
329
+ payload = this.peers_home(payload)
330
+
331
+ // localhost local variables
188
332
  payload = this.locals(payload)
333
+ // peers local variables
334
+ payload = this.peers_locals(payload)
335
+
189
336
  payload = await this.procs(payload)
337
+ payload = this.peers_procs(payload)
338
+
190
339
  return payload
191
340
  }
192
341
  }
package/kernel/index.js CHANGED
@@ -32,6 +32,7 @@ const Store = require('./store')
32
32
  const Proto = require('./prototype')
33
33
  const Caddy = require("./caddy")
34
34
  const Procs = require('./procs')
35
+ const Peer = require('./peer')
35
36
  const VARS = {
36
37
  pip: {
37
38
  install: {
@@ -86,6 +87,8 @@ class Kernel {
86
87
  this.kv = new KV(this)
87
88
  this.cloudflare = new Cloudflare()
88
89
  this.shellpath = shellPath.sync()
90
+
91
+ this.peer = new Peer()
89
92
  }
90
93
  /*
91
94
  kernel.env() => return the system environment
package/kernel/peer.js ADDED
@@ -0,0 +1,65 @@
1
+ const dgram = require('dgram');
2
+ const axios = require('axios');
3
+ const os = require('os')
4
+ class PeerDiscovery {
5
+ constructor(port = 41234, message = 'ping', interval = 1000) {
6
+ this.port = port;
7
+ this.message = Buffer.from(message);
8
+ this.interval = interval;
9
+ this.socket = dgram.createSocket('udp4');
10
+ this.peers = new Set();
11
+ this.current_account = os.userInfo()
12
+ // this.start();
13
+ }
14
+ account(ip) {
15
+ return this.data[ip].account
16
+ }
17
+ home(ip) {
18
+ return this.data[ip].homedir
19
+ }
20
+ caddy(ip) {
21
+ return this.data[ip].caddy
22
+ }
23
+ local(ip) {
24
+ return this.data[ip].memory.local
25
+ }
26
+ global(ip) {
27
+ return this.data[ip].memory.global
28
+ }
29
+ start() {
30
+ // Listen for incoming pings
31
+ this.data = {}
32
+ this.socket.on('message', (msg, rinfo) => {
33
+ const ip = rinfo.address;
34
+ if (msg.toString() === this.message.toString() && this._isLocalLAN(ip)) {
35
+ if (!this.peers.has(ip)) {
36
+ this.peers.add(ip);
37
+ axios.get(`http://${ip}:42000/pinokio/mem`).then((res) => {
38
+ this.data[ip] = res.data
39
+ })
40
+ console.log(`Discovered peer: ${ip}`);
41
+ }
42
+ }
43
+ });
44
+
45
+ // Enable broadcast
46
+ this.socket.bind(this.port, () => {
47
+ this.socket.setBroadcast(true);
48
+
49
+ // Send broadcast pings every interval
50
+ setInterval(() => {
51
+ this.socket.send(this.message, 0, this.message.length, this.port, '255.255.255.255');
52
+ }, this.interval);
53
+ });
54
+ }
55
+
56
+ get() {
57
+ return Array.from(this.peers);
58
+ }
59
+
60
+ _isLocalLAN(ip) {
61
+ return ip.startsWith('192.168.');
62
+ }
63
+ }
64
+
65
+ module.exports = PeerDiscovery;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "3.8.26",
3
+ "version": "3.8.28",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -2668,6 +2668,8 @@ class Server {
2668
2668
  })
2669
2669
  await this.kernel.caddy.update()
2670
2670
 
2671
+ let peers = this.kernel.peer.get()
2672
+
2671
2673
  let live_proxies = this.kernel.api.proxies["/proxy"]
2672
2674
  if (!live_proxies) live_proxies = []
2673
2675
  let proxies = []
@@ -2745,6 +2747,7 @@ class Server {
2745
2747
  }
2746
2748
  }
2747
2749
  res.render("proxy", {
2750
+ peers,
2748
2751
  list,
2749
2752
  agent: this.agent,
2750
2753
  theme: this.theme,
@@ -3274,6 +3277,14 @@ class Server {
3274
3277
  */
3275
3278
 
3276
3279
  }))
3280
+ this.app.get("/pinokio/mem", ex((req, res) => {
3281
+ res.json({
3282
+ homedir: this.kernel.homedir,
3283
+ account: this.kernel.peer.current_account,
3284
+ caddy: this.kernel.caddy.mapping, // mapping: { IP => https_domain }
3285
+ memory: this.kernel.memory
3286
+ })
3287
+ }))
3277
3288
  this.app.get("/pinokio/memory", ex((req, res) => {
3278
3289
  let filepath = req.query.filepath
3279
3290
  let mem = this.getMemory(filepath)
@@ -3893,6 +3904,7 @@ class Server {
3893
3904
  server: this.listening
3894
3905
  });
3895
3906
  })
3907
+ this.kernel.peer.start()
3896
3908
  console.timeEnd("SERVER START")
3897
3909
 
3898
3910
 
@@ -161,7 +161,7 @@ body.dark .browser-options-row {
161
161
  }
162
162
  .container {
163
163
  display: grid;
164
- grid-template-columns: repeat(3, 1fr);
164
+ grid-template-columns: repeat(4, 1fr);
165
165
  }
166
166
  .dark .container-row {
167
167
  background: rgba(255, 255, 255, 0.04);
@@ -210,6 +210,14 @@ body.dark .browser-options-row {
210
210
  <div class='header-label'><i class='fa-solid fa-wifi'></i> Local Sharing</div>
211
211
  <div class='desc'>Serve Pinokio, installed apps, and even external apps to any device on the same network.</div>
212
212
  <div class='container'>
213
+ <div class='container-row'>
214
+ <div class='header-label-sub'><i class="fa-solid fa-microchip"></i> Peers</div>
215
+ <% peers.forEach((item) => { %>
216
+ <a target="_blank" href="http://<%=item%>" class='line align-top'>
217
+ <h3 class='table-grid'><%=item%></h3>
218
+ </a>
219
+ <% }) %>
220
+ </div>
213
221
  <div class='container-row'>
214
222
  <div class='header-label-sub'><i class="fa-solid fa-microchip"></i> Apps</div>
215
223
  <div class='line align-top'>