@ai-ecoverse/slicc-kernel 1.136.9 → 1.138.0
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/README.md +21 -5
- package/dist/index.js +3 -1
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +675 -168
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js.map +1 -1
- package/dist/node-process-worker.js +58 -5
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +662 -164
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +58 -5
- package/dist/process-worker.js.map +4 -4
- package/dist/testing.js +1 -0
- package/dist/testing.js.map +2 -2
- package/dist/types/fs/notice.d.ts +1 -0
- package/dist/types/fs/opfs.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/kernel/net/dns-stub.d.ts +65 -0
- package/dist/types/kernel/net/resolver.d.ts +4 -1
- package/dist/types/kernel/net/uplink.d.ts +3 -1
- package/dist/types/kernel/proc-info.d.ts +2 -0
- package/dist/types/kernel/socket.d.ts +3 -1
- package/dist/types/launcher.d.ts +2 -0
- package/dist/types/node.d.ts +1 -0
- package/dist/types/process/procfs.d.ts +1 -1
- package/dist/types/process/wasi/wasi-procfs.d.ts +2 -1
- package/dist/types/serve.d.ts +2 -0
- package/dist/types/testing.d.ts +1 -0
- package/package.json +2 -2
package/dist/kernel-worker.js
CHANGED
|
@@ -358,7 +358,7 @@ function noticeOf(data) {
|
|
|
358
358
|
if (Array.isArray(data)) return { paths: data.filter((p) => typeof p === "string"), trees: [] };
|
|
359
359
|
const notice = data ?? {};
|
|
360
360
|
const strings = (list) => Array.isArray(list) ? list.filter((p) => typeof p === "string") : [];
|
|
361
|
-
return { paths: strings(notice.paths), trees: strings(notice.trees) };
|
|
361
|
+
return { paths: strings(notice.paths), trees: strings(notice.trees), outside: true };
|
|
362
362
|
}
|
|
363
363
|
|
|
364
364
|
// src/fs/types.ts
|
|
@@ -1307,9 +1307,11 @@ var OpfsFs = class {
|
|
|
1307
1307
|
for (const path of [...c.paths, ...c.trees]) this.forget(path);
|
|
1308
1308
|
});
|
|
1309
1309
|
this.channel.onmessage = ({ data }) => {
|
|
1310
|
-
const { paths, trees } = noticeOf(data);
|
|
1310
|
+
const { paths, trees, outside } = noticeOf(data);
|
|
1311
1311
|
for (const path of [...paths, ...trees]) this.forget(normalizePath(path));
|
|
1312
|
-
remote?.emit({ paths, trees });
|
|
1312
|
+
const tell = () => remote?.emit({ paths, trees });
|
|
1313
|
+
if (!outside) tell();
|
|
1314
|
+
else void this.noticed(paths.map(normalizePath), Date.now()).finally(tell);
|
|
1313
1315
|
};
|
|
1314
1316
|
this.channel.unref?.();
|
|
1315
1317
|
}
|
|
@@ -1768,6 +1770,14 @@ var OpfsFs = class {
|
|
|
1768
1770
|
this.fileTimes.set(target, Date.now());
|
|
1769
1771
|
this.scheduleFileTimes();
|
|
1770
1772
|
}
|
|
1773
|
+
async noticed(paths, at) {
|
|
1774
|
+
for (const path of new Set(paths)) {
|
|
1775
|
+
const st = await this.lstat(path).catch(() => void 0);
|
|
1776
|
+
if (!st?.isFile || st.mtime.getTime() >= at) continue;
|
|
1777
|
+
this.fileTimes.set(path, Math.max(at, this.fileTimes.get(path) ?? 0));
|
|
1778
|
+
}
|
|
1779
|
+
this.scheduleFileTimes();
|
|
1780
|
+
}
|
|
1771
1781
|
scheduleFileTimes() {
|
|
1772
1782
|
if (this.flushing.file || this.fileTimes.size === 0) return;
|
|
1773
1783
|
this.flushing.file = setTimeout(() => {
|
|
@@ -2427,8 +2437,8 @@ var OpfsFs = class {
|
|
|
2427
2437
|
renamingDirs = /* @__PURE__ */ new Set();
|
|
2428
2438
|
intents = 0;
|
|
2429
2439
|
async intend(rename, at = `${RENAMES}/${crypto.randomUUID()}`) {
|
|
2430
|
-
const
|
|
2431
|
-
await this.meta.update(at, () => ({ path: at, rename:
|
|
2440
|
+
const record2 = { ...rename, at: Date.now() * 1e3 + this.intents++ % 1e3 };
|
|
2441
|
+
await this.meta.update(at, () => ({ path: at, rename: record2 }));
|
|
2432
2442
|
return at;
|
|
2433
2443
|
}
|
|
2434
2444
|
async rollBack(from, to, intents) {
|
|
@@ -2939,7 +2949,7 @@ async function rootId(factory, root, locks = globalThis.navigator?.locks) {
|
|
|
2939
2949
|
const all = await request(
|
|
2940
2950
|
db.transaction(ROOTS_STORE, "readonly").objectStore(ROOTS_STORE).getAll()
|
|
2941
2951
|
);
|
|
2942
|
-
for (const
|
|
2952
|
+
for (const record2 of all) if (await same(record2.handle, root)) return record2.id;
|
|
2943
2953
|
const id2 = crypto.randomUUID();
|
|
2944
2954
|
if (await used(root)) await seed(factory, nameOf(id2));
|
|
2945
2955
|
const tx = db.transaction(ROOTS_STORE, "readwrite");
|
|
@@ -4879,6 +4889,15 @@ function isHostname(name2) {
|
|
|
4879
4889
|
function ownNames(hostname) {
|
|
4880
4890
|
return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
|
|
4881
4891
|
}
|
|
4892
|
+
function hostsFile(hostname = DEFAULT_HOSTNAME) {
|
|
4893
|
+
return [
|
|
4894
|
+
"127.0.0.1 localhost localhost.localdomain",
|
|
4895
|
+
"::1 localhost ip6-localhost",
|
|
4896
|
+
`${HOSTNAME_ADDRESS} ${ownNames(hostname).join(" ")}`,
|
|
4897
|
+
`${HOST_LOOPBACK_ADDRESS.join(".")} ${HOST_LOOPBACK}`,
|
|
4898
|
+
""
|
|
4899
|
+
].join("\n");
|
|
4900
|
+
}
|
|
4882
4901
|
|
|
4883
4902
|
// src/kernel/net/routes.ts
|
|
4884
4903
|
var HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join(".");
|
|
@@ -5563,6 +5582,7 @@ var LOCAL_ONLY = new Routes();
|
|
|
5563
5582
|
var LoopbackNet = class {
|
|
5564
5583
|
bound = /* @__PURE__ */ new Map();
|
|
5565
5584
|
dgrams = /* @__PURE__ */ new Map();
|
|
5585
|
+
dgramServices = /* @__PURE__ */ new Map();
|
|
5566
5586
|
unixDgrams = /* @__PURE__ */ new Map();
|
|
5567
5587
|
activators = /* @__PURE__ */ new Map();
|
|
5568
5588
|
internal = /* @__PURE__ */ new Set();
|
|
@@ -5613,9 +5633,16 @@ var LoopbackNet = class {
|
|
|
5613
5633
|
releaseDgram(addr, socket) {
|
|
5614
5634
|
if (this.dgrams.get(addr.port) === socket) this.dgrams.delete(addr.port);
|
|
5615
5635
|
}
|
|
5616
|
-
|
|
5636
|
+
serveDgram(port, serve) {
|
|
5637
|
+
this.dgramServices.set(port, serve);
|
|
5638
|
+
}
|
|
5639
|
+
deliverDgram(port, datagram2, to) {
|
|
5617
5640
|
const target = this.dgrams.get(port);
|
|
5618
|
-
|
|
5641
|
+
if (target) return target.deliver(datagram2);
|
|
5642
|
+
const service = this.dgramServices.get(port);
|
|
5643
|
+
if (!service) return false;
|
|
5644
|
+
service(datagram2, to ?? { family: "inet", host: "127.0.0.1", port });
|
|
5645
|
+
return true;
|
|
5619
5646
|
}
|
|
5620
5647
|
bindable(addr, kernel) {
|
|
5621
5648
|
if (addr.host !== "0.0.0.0" && !isLoopback(addr.host)) {
|
|
@@ -7098,7 +7125,7 @@ function satisfies(version, range2) {
|
|
|
7098
7125
|
}
|
|
7099
7126
|
|
|
7100
7127
|
// src/version.ts
|
|
7101
|
-
var KERNEL_VERSION = true ? "1.
|
|
7128
|
+
var KERNEL_VERSION = true ? "1.138.0" : "0.0.0-dev";
|
|
7102
7129
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7103
7130
|
function procVersion() {
|
|
7104
7131
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -8616,11 +8643,11 @@ var CronService = class {
|
|
|
8616
8643
|
}
|
|
8617
8644
|
if (this.stopping.signal.aborted) return;
|
|
8618
8645
|
const exit = ended.signal ? `signal=${ended.signal}` : `exit=${ended.status}`;
|
|
8619
|
-
const
|
|
8646
|
+
const header4 = encoder.encode(`--- ${iso} ${exit} missed=${missed} ---
|
|
8620
8647
|
`);
|
|
8621
8648
|
const body = output.bytes();
|
|
8622
8649
|
const newline = body.length > 0 && body[body.length - 1] !== 10 ? encoder.encode("\n") : new Uint8Array();
|
|
8623
|
-
await this.append(log, concat2([
|
|
8650
|
+
await this.append(log, concat2([header4, body, newline]), account.uid, account.gid).catch(
|
|
8624
8651
|
(err) => this.error(messageOf(err))
|
|
8625
8652
|
);
|
|
8626
8653
|
}
|
|
@@ -9428,8 +9455,8 @@ var FileWatches = class {
|
|
|
9428
9455
|
live = /* @__PURE__ */ new Set();
|
|
9429
9456
|
local;
|
|
9430
9457
|
remote;
|
|
9431
|
-
constructor(
|
|
9432
|
-
this.local =
|
|
9458
|
+
constructor(local2, remote) {
|
|
9459
|
+
this.local = local2;
|
|
9433
9460
|
this.remote = remote;
|
|
9434
9461
|
}
|
|
9435
9462
|
announce() {
|
|
@@ -13149,18 +13176,18 @@ var SAB_I_ASYNC = 14;
|
|
|
13149
13176
|
var SAB_I_STOP = 15;
|
|
13150
13177
|
var SAB_I_BLOCKED = 16;
|
|
13151
13178
|
var SAB_I_BLOCKED_HI = 17;
|
|
13152
|
-
function loadBlocked(
|
|
13153
|
-
return [Atomics.load(
|
|
13179
|
+
function loadBlocked(header4) {
|
|
13180
|
+
return [Atomics.load(header4, SAB_I_BLOCKED), Atomics.load(header4, SAB_I_BLOCKED_HI)];
|
|
13154
13181
|
}
|
|
13155
|
-
function storeBlocked(
|
|
13156
|
-
Atomics.store(
|
|
13157
|
-
Atomics.store(
|
|
13182
|
+
function storeBlocked(header4, [low, high]) {
|
|
13183
|
+
Atomics.store(header4, SAB_I_BLOCKED_HI, high);
|
|
13184
|
+
Atomics.store(header4, SAB_I_BLOCKED, low);
|
|
13158
13185
|
}
|
|
13159
13186
|
var anyBlocked = (mask) => mask !== void 0 && (mask[0] !== 0 || mask[1] !== 0);
|
|
13160
13187
|
var U32 = 2 ** 32;
|
|
13161
|
-
function storeU53(
|
|
13162
|
-
Atomics.store(
|
|
13163
|
-
Atomics.store(
|
|
13188
|
+
function storeU53(header4, lo, hi, value2) {
|
|
13189
|
+
Atomics.store(header4, hi, Math.floor(value2 / U32));
|
|
13190
|
+
Atomics.store(header4, lo, value2 % U32 | 0);
|
|
13164
13191
|
}
|
|
13165
13192
|
var SAB_STATE_READY = 2;
|
|
13166
13193
|
var SAB_STATUS_BYTES = 1;
|
|
@@ -13209,7 +13236,7 @@ function sabViews(sab) {
|
|
|
13209
13236
|
var PENDING_TTL_MS = SYNC_FS_REQUEST_TIMEOUT_MS + 5e3;
|
|
13210
13237
|
function attachSyncSabResponder(port, sab, token, opts) {
|
|
13211
13238
|
const views = sabViews(sab);
|
|
13212
|
-
const { header:
|
|
13239
|
+
const { header: header4, window } = views;
|
|
13213
13240
|
const pending = /* @__PURE__ */ new Map();
|
|
13214
13241
|
let disposed = false;
|
|
13215
13242
|
const { dispatch: dispatch2 } = opts;
|
|
@@ -13220,20 +13247,20 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
13220
13247
|
pending.delete(id2);
|
|
13221
13248
|
}
|
|
13222
13249
|
function publish(id2, entry, offset) {
|
|
13223
|
-
if (Atomics.load(
|
|
13250
|
+
if (Atomics.load(header4, SAB_I_REQ) !== id2) {
|
|
13224
13251
|
drop(id2);
|
|
13225
13252
|
return;
|
|
13226
13253
|
}
|
|
13227
13254
|
const chunk2 = Math.min(window.byteLength, entry.payload.byteLength - offset);
|
|
13228
13255
|
if (chunk2 > 0) window.set(entry.payload.subarray(offset, offset + chunk2));
|
|
13229
|
-
Atomics.store(
|
|
13230
|
-
storeU53(
|
|
13231
|
-
Atomics.store(
|
|
13232
|
-
storeU53(
|
|
13233
|
-
Atomics.store(
|
|
13234
|
-
Atomics.store(
|
|
13235
|
-
Atomics.add(
|
|
13236
|
-
Atomics.notify(
|
|
13256
|
+
Atomics.store(header4, SAB_I_STATUS, entry.status);
|
|
13257
|
+
storeU53(header4, SAB_I_TOTAL, SAB_I_TOTAL_HI, entry.payload.byteLength);
|
|
13258
|
+
Atomics.store(header4, SAB_I_CHUNK, chunk2);
|
|
13259
|
+
storeU53(header4, SAB_I_OFFSET, SAB_I_OFFSET_HI, offset);
|
|
13260
|
+
Atomics.store(header4, SAB_I_SEQ, id2);
|
|
13261
|
+
Atomics.store(header4, SAB_I_STATE, SAB_STATE_READY);
|
|
13262
|
+
Atomics.add(header4, SAB_I_PUB, 1);
|
|
13263
|
+
Atomics.notify(header4, SAB_I_PUB);
|
|
13237
13264
|
if (offset + chunk2 >= entry.payload.byteLength) drop(id2);
|
|
13238
13265
|
else if (entry.timer) {
|
|
13239
13266
|
clearTimeout(entry.timer);
|
|
@@ -13448,6 +13475,15 @@ var ProcessClocks = class {
|
|
|
13448
13475
|
}
|
|
13449
13476
|
};
|
|
13450
13477
|
|
|
13478
|
+
// src/kernel/proc-info.ts
|
|
13479
|
+
function mayTrace(viewer, target) {
|
|
13480
|
+
const by = viewer?.cred;
|
|
13481
|
+
const of = target.cred;
|
|
13482
|
+
if (!by || !of || by.euid === 0) return true;
|
|
13483
|
+
const uid = of.ruid === by.euid && of.euid === by.euid && of.suid === by.euid;
|
|
13484
|
+
return uid && of.rgid === by.egid && of.egid === by.egid && of.sgid === by.egid;
|
|
13485
|
+
}
|
|
13486
|
+
|
|
13451
13487
|
// src/fs/pages.ts
|
|
13452
13488
|
var PAGE = 64 * 1024;
|
|
13453
13489
|
var READAHEAD = 1024 * 1024;
|
|
@@ -14003,7 +14039,16 @@ var ProcTree = class {
|
|
|
14003
14039
|
if (!/^[1-9]\d*$/.test(top) || !this.alive(Number(top))) return void 0;
|
|
14004
14040
|
if (leaf === "task") return this.task(Number(top), rest2);
|
|
14005
14041
|
if (rest2.length > 0) return void 0;
|
|
14006
|
-
if (leaf === void 0)
|
|
14042
|
+
if (leaf === void 0) {
|
|
14043
|
+
const exe = () => this.info(Number(top))?.exe === void 0 ? [] : ["exe"];
|
|
14044
|
+
return { kind: "dir", names: () => [...PID_NAMES, ...exe(), "task"] };
|
|
14045
|
+
}
|
|
14046
|
+
if (leaf === "exe") {
|
|
14047
|
+
const info = this.info(Number(top));
|
|
14048
|
+
if (info?.exe === void 0) return void 0;
|
|
14049
|
+
const denied2 = !mayTrace(this.ownInfo(), info);
|
|
14050
|
+
return { kind: "link", target: info.exe, ...denied2 ? { denied: denied2 } : {} };
|
|
14051
|
+
}
|
|
14007
14052
|
if (!PID_NAMES.includes(leaf)) return void 0;
|
|
14008
14053
|
return {
|
|
14009
14054
|
kind: "file",
|
|
@@ -14015,6 +14060,10 @@ var ProcTree = class {
|
|
|
14015
14060
|
}
|
|
14016
14061
|
};
|
|
14017
14062
|
}
|
|
14063
|
+
ownInfo() {
|
|
14064
|
+
const processes2 = this.listing().processes;
|
|
14065
|
+
return processes2.find((p) => p.tid === this.pid) ?? processes2.find((p) => p.pid === this.pid);
|
|
14066
|
+
}
|
|
14018
14067
|
info(pid) {
|
|
14019
14068
|
return this.listing().processes.find((p) => p.pid === pid);
|
|
14020
14069
|
}
|
|
@@ -14078,6 +14127,7 @@ var ProcTree = class {
|
|
|
14078
14127
|
readlink(path) {
|
|
14079
14128
|
const node = this.find(path, false);
|
|
14080
14129
|
if (node.kind !== "link") throw syncError("EINVAL", path);
|
|
14130
|
+
if (node.denied) throw syncError("EACCES", path);
|
|
14081
14131
|
return node.target;
|
|
14082
14132
|
}
|
|
14083
14133
|
exists(path) {
|
|
@@ -15482,8 +15532,8 @@ function sameCert(a, b) {
|
|
|
15482
15532
|
if (!a || !b) return a === b;
|
|
15483
15533
|
return a.cert.length === b.cert.length && a.cert.every((byte, i) => byte === b.cert[i]);
|
|
15484
15534
|
}
|
|
15485
|
-
function winner(current, expected,
|
|
15486
|
-
return sameCert(current, expected) ?
|
|
15535
|
+
function winner(current, expected, record2) {
|
|
15536
|
+
return sameCert(current, expected) ? record2 : current;
|
|
15487
15537
|
}
|
|
15488
15538
|
var DAY = 24 * 60 * 60 * 1e3;
|
|
15489
15539
|
var CA_LIFETIME = 3650 * DAY;
|
|
@@ -15516,15 +15566,15 @@ function indexedDbCaStore(dbName = "slicc-realm-ca") {
|
|
|
15516
15566
|
const store = (await open2()).transaction("ca").objectStore("ca");
|
|
15517
15567
|
return await request2(store.get(owner));
|
|
15518
15568
|
},
|
|
15519
|
-
async swap(owner, expected,
|
|
15569
|
+
async swap(owner, expected, record2) {
|
|
15520
15570
|
const tx = (await open2()).transaction("ca", "readwrite");
|
|
15521
15571
|
const store = tx.objectStore("ca");
|
|
15522
|
-
let stored =
|
|
15572
|
+
let stored = record2;
|
|
15523
15573
|
const read = store.get(owner);
|
|
15524
15574
|
read.onsuccess = () => {
|
|
15525
15575
|
const current = read.result;
|
|
15526
|
-
const kept = winner(current, expected,
|
|
15527
|
-
if (kept ===
|
|
15576
|
+
const kept = winner(current, expected, record2);
|
|
15577
|
+
if (kept === record2) store.put(record2, owner);
|
|
15528
15578
|
else stored = kept;
|
|
15529
15579
|
};
|
|
15530
15580
|
await new Promise((resolve2, reject) => {
|
|
@@ -15544,14 +15594,14 @@ function validLeafName(host) {
|
|
|
15544
15594
|
}
|
|
15545
15595
|
var RealmCa = class _RealmCa {
|
|
15546
15596
|
record;
|
|
15547
|
-
constructor(
|
|
15548
|
-
this.record =
|
|
15597
|
+
constructor(record2) {
|
|
15598
|
+
this.record = record2;
|
|
15549
15599
|
}
|
|
15550
15600
|
static async open(owner, store, now = Date.now()) {
|
|
15551
15601
|
const stored = await store.get(owner).catch(() => void 0);
|
|
15552
15602
|
if (stored && stored.notAfter - now > CA_RENEW_BEFORE) return new _RealmCa(stored);
|
|
15553
|
-
const
|
|
15554
|
-
return new _RealmCa(await store.swap(owner, stored,
|
|
15603
|
+
const record2 = await _RealmCa.create(owner, now);
|
|
15604
|
+
return new _RealmCa(await store.swap(owner, stored, record2));
|
|
15555
15605
|
}
|
|
15556
15606
|
static async create(owner, now) {
|
|
15557
15607
|
const pair = await crypto.subtle.generateKey(ECDSA, false, ["sign", "verify"]);
|
|
@@ -15710,10 +15760,15 @@ var TlsEngine = class {
|
|
|
15710
15760
|
const m = this.clientModule();
|
|
15711
15761
|
if (servername.includes("\0")) throw new TlsError(-3, "tls engine: a server name has no NUL");
|
|
15712
15762
|
const wire = alpnWire(alpn);
|
|
15713
|
-
const
|
|
15763
|
+
const bytes = new TextEncoder().encode(servername);
|
|
15764
|
+
const name2 = this.put(bytes);
|
|
15714
15765
|
try {
|
|
15715
15766
|
const at = store?.ptr ?? 0;
|
|
15716
|
-
const
|
|
15767
|
+
const named = m._tls_client_new_name;
|
|
15768
|
+
const ptr = this.withBytes(
|
|
15769
|
+
wire,
|
|
15770
|
+
(p) => named ? named(at, name2, bytes.length, p, wire.length, flags2) : m._tls_client_new(at, name2, p, wire.length, flags2)
|
|
15771
|
+
);
|
|
15717
15772
|
if (!ptr) throw this.error(m._tls_last_error(), "tls client");
|
|
15718
15773
|
return new TlsSession(this, m, ptr);
|
|
15719
15774
|
} finally {
|
|
@@ -16082,8 +16137,8 @@ function memoryCaStore() {
|
|
|
16082
16137
|
const records = /* @__PURE__ */ new Map();
|
|
16083
16138
|
return {
|
|
16084
16139
|
get: async (owner) => records.get(owner),
|
|
16085
|
-
swap: async (owner, expected,
|
|
16086
|
-
const kept = winner(records.get(owner), expected,
|
|
16140
|
+
swap: async (owner, expected, record2) => {
|
|
16141
|
+
const kept = winner(records.get(owner), expected, record2);
|
|
16087
16142
|
records.set(owner, kept);
|
|
16088
16143
|
return kept;
|
|
16089
16144
|
}
|
|
@@ -16213,10 +16268,10 @@ var WsHandles = class {
|
|
|
16213
16268
|
open = /* @__PURE__ */ new Map();
|
|
16214
16269
|
next;
|
|
16215
16270
|
local;
|
|
16216
|
-
constructor(transport, next3,
|
|
16271
|
+
constructor(transport, next3, local2) {
|
|
16217
16272
|
this.transport = transport;
|
|
16218
16273
|
this.next = next3;
|
|
16219
|
-
this.local =
|
|
16274
|
+
this.local = local2;
|
|
16220
16275
|
}
|
|
16221
16276
|
owns(handle) {
|
|
16222
16277
|
return this.open.has(handle);
|
|
@@ -16245,8 +16300,8 @@ var WsHandles = class {
|
|
|
16245
16300
|
return { ok: true, kind: "json", json: handle };
|
|
16246
16301
|
}
|
|
16247
16302
|
async connect(handle, req, entry) {
|
|
16248
|
-
const { transport, local } = this;
|
|
16249
|
-
const port =
|
|
16303
|
+
const { transport, local: local2 } = this;
|
|
16304
|
+
const port = local2?.port(req.url);
|
|
16250
16305
|
const open2 = { protocols: req.protocols, headers: req.headers, signal: entry.abort.signal };
|
|
16251
16306
|
if (port === void 0 && (!transport.traits.websocket || !transport.websocket)) {
|
|
16252
16307
|
return fail("ENOTSUP", NO_WEBSOCKET2);
|
|
@@ -16256,7 +16311,7 @@ var WsHandles = class {
|
|
|
16256
16311
|
socket = port === void 0 ? await transport.websocket({
|
|
16257
16312
|
url: toHostLoopback(req.url),
|
|
16258
16313
|
...open2
|
|
16259
|
-
}) : await
|
|
16314
|
+
}) : await local2.websocket({ url: req.url, ...open2 }, port);
|
|
16260
16315
|
} catch (e) {
|
|
16261
16316
|
return fail(errnoOf(e), message(e));
|
|
16262
16317
|
}
|
|
@@ -16387,11 +16442,11 @@ var HttpHandles = class {
|
|
|
16387
16442
|
ws;
|
|
16388
16443
|
owner;
|
|
16389
16444
|
local;
|
|
16390
|
-
constructor(transport, owner,
|
|
16445
|
+
constructor(transport, owner, local2) {
|
|
16391
16446
|
this.transport = transport;
|
|
16392
16447
|
this.owner = owner;
|
|
16393
|
-
this.local =
|
|
16394
|
-
this.ws = new WsHandles(transport, () => ++this.nextHandle,
|
|
16448
|
+
this.local = local2;
|
|
16449
|
+
this.ws = new WsHandles(transport, () => ++this.nextHandle, local2);
|
|
16395
16450
|
}
|
|
16396
16451
|
syscall(req) {
|
|
16397
16452
|
if (req.op.startsWith("net-ws-")) return this.ws.syscall(req);
|
|
@@ -16543,6 +16598,43 @@ var HttpHandles = class {
|
|
|
16543
16598
|
}
|
|
16544
16599
|
};
|
|
16545
16600
|
|
|
16601
|
+
// src/kernel/net/hosts-file.ts
|
|
16602
|
+
var HOSTS_PATH = "/etc/hosts";
|
|
16603
|
+
function parseHosts(text) {
|
|
16604
|
+
const table = /* @__PURE__ */ new Map();
|
|
16605
|
+
for (const raw2 of text.split("\n")) {
|
|
16606
|
+
const [address, ...names2] = raw2.replace(/#.*/, "").trim().split(/\s+/);
|
|
16607
|
+
if (!address || names2.length === 0) continue;
|
|
16608
|
+
if (ipv4Bytes(address) === void 0 && ipv6Groups(address) === void 0) continue;
|
|
16609
|
+
for (const name2 of names2) {
|
|
16610
|
+
const key = name2.toLowerCase().replace(/\.$/, "");
|
|
16611
|
+
const known = table.get(key) ?? [];
|
|
16612
|
+
if (!known.includes(address)) known.push(address);
|
|
16613
|
+
table.set(key, known);
|
|
16614
|
+
}
|
|
16615
|
+
}
|
|
16616
|
+
return table;
|
|
16617
|
+
}
|
|
16618
|
+
function hostsReader(fs, path = HOSTS_PATH) {
|
|
16619
|
+
let stamp = "";
|
|
16620
|
+
let table;
|
|
16621
|
+
return async () => {
|
|
16622
|
+
const st = await fs.stat(path).catch(() => void 0);
|
|
16623
|
+
if (!st?.isFile) {
|
|
16624
|
+
stamp = "";
|
|
16625
|
+
table = void 0;
|
|
16626
|
+
return void 0;
|
|
16627
|
+
}
|
|
16628
|
+
const now = `${st.ino}:${st.size}:${st.mtime.getTime()}`;
|
|
16629
|
+
if (now === stamp && table) return table;
|
|
16630
|
+
const text = await fs.readFile(path).catch(() => void 0);
|
|
16631
|
+
if (text === void 0) return void 0;
|
|
16632
|
+
stamp = now;
|
|
16633
|
+
table = parseHosts(text);
|
|
16634
|
+
return table;
|
|
16635
|
+
};
|
|
16636
|
+
}
|
|
16637
|
+
|
|
16546
16638
|
// src/kernel/net/uplink.ts
|
|
16547
16639
|
function carriesUdp(uplink) {
|
|
16548
16640
|
return uplink.traits.udp === true && typeof uplink.udp === "function";
|
|
@@ -16559,13 +16651,15 @@ var NEVER = new Routes(true);
|
|
|
16559
16651
|
var RemoteUplink = class {
|
|
16560
16652
|
traits;
|
|
16561
16653
|
routes;
|
|
16654
|
+
nameserver;
|
|
16562
16655
|
port;
|
|
16563
16656
|
waiting = /* @__PURE__ */ new Map();
|
|
16564
16657
|
nextId = 0;
|
|
16565
|
-
constructor(port, traits, routes) {
|
|
16658
|
+
constructor(port, traits, routes, nameserver) {
|
|
16566
16659
|
this.port = port;
|
|
16567
16660
|
this.traits = traits;
|
|
16568
16661
|
this.routes = routes;
|
|
16662
|
+
this.nameserver = nameserver;
|
|
16569
16663
|
}
|
|
16570
16664
|
receive(reply) {
|
|
16571
16665
|
const waiter = this.waiting.get(reply.uid);
|
|
@@ -16688,6 +16782,7 @@ var Resolver = class {
|
|
|
16688
16782
|
timeoutMs;
|
|
16689
16783
|
log;
|
|
16690
16784
|
own;
|
|
16785
|
+
builtin;
|
|
16691
16786
|
cache = /* @__PURE__ */ new Map();
|
|
16692
16787
|
pending = /* @__PURE__ */ new Map();
|
|
16693
16788
|
hosts;
|
|
@@ -16698,6 +16793,7 @@ var Resolver = class {
|
|
|
16698
16793
|
this.timeoutMs = options.timeoutMs ?? RESOLVE_TIMEOUT_MS;
|
|
16699
16794
|
this.log = options.log ?? ((message3) => console.warn(message3));
|
|
16700
16795
|
this.own = ownNames(options.hostname ?? DEFAULT_HOSTNAME);
|
|
16796
|
+
this.builtin = parseHosts(hostsFile(options.hostname ?? DEFAULT_HOSTNAME));
|
|
16701
16797
|
this.hosts = options.hosts;
|
|
16702
16798
|
}
|
|
16703
16799
|
async fromFile(key, family) {
|
|
@@ -16707,18 +16803,34 @@ var Resolver = class {
|
|
|
16707
16803
|
const v6 = listed.filter((a) => ipv4Bytes(a) === void 0);
|
|
16708
16804
|
return family === 4 ? v4 : family === 6 ? v6 : [...v4, ...v6];
|
|
16709
16805
|
}
|
|
16806
|
+
async known(name2) {
|
|
16807
|
+
const key = name2.toLowerCase().replace(/\.$/, "");
|
|
16808
|
+
if (ipv4Bytes(key) || ipv6Groups(key)) return false;
|
|
16809
|
+
if (hostsEntry(key, this.own) !== void 0) return true;
|
|
16810
|
+
return ((await this.hosts?.().catch(() => void 0))?.get(key)?.length ?? 0) > 0;
|
|
16811
|
+
}
|
|
16812
|
+
async reverse(address) {
|
|
16813
|
+
const v6 = ipv6Groups(address)?.join(":");
|
|
16814
|
+
const same3 = (a) => a === address || v6 !== void 0 && ipv6Groups(a)?.join(":") === v6;
|
|
16815
|
+
const file = await this.hosts?.().catch(() => void 0);
|
|
16816
|
+
for (const table of [file, this.builtin]) {
|
|
16817
|
+
for (const [name2, addresses] of table ?? []) if (addresses.some(same3)) return name2;
|
|
16818
|
+
}
|
|
16819
|
+
if (ipv4Bytes(address)?.[0] === 127) return "localhost";
|
|
16820
|
+
return void 0;
|
|
16821
|
+
}
|
|
16710
16822
|
async resolve(name2, family, blocking) {
|
|
16711
16823
|
const key = name2.toLowerCase().replace(/\.$/, "");
|
|
16712
|
-
const
|
|
16824
|
+
const local2 = hostsEntry(key, this.own);
|
|
16713
16825
|
if (ipv6Groups(key)) {
|
|
16714
|
-
const v4 = family !== 6 &&
|
|
16826
|
+
const v4 = family !== 6 && local2 ? [local2] : [];
|
|
16715
16827
|
return family === 4 ? v4 : [...v4, key];
|
|
16716
16828
|
}
|
|
16717
16829
|
const listed = this.hosts ? await this.fromFile(key, family) : void 0;
|
|
16718
16830
|
if (listed?.length) return listed;
|
|
16719
|
-
if (
|
|
16831
|
+
if (local2) {
|
|
16720
16832
|
const six = loopbackName(key, this.own) ? ["::1"] : [];
|
|
16721
|
-
return family === 6 ? six : family === 4 ? [
|
|
16833
|
+
return family === 6 ? six : family === 4 ? [local2] : [local2, ...six];
|
|
16722
16834
|
}
|
|
16723
16835
|
if (!this.uplink || key === "") return [];
|
|
16724
16836
|
const asked = this.uplink.traits.ipv6 ? family : 4;
|
|
@@ -17757,14 +17869,15 @@ var KernelDgram = class {
|
|
|
17757
17869
|
const max = familyOf(target.host) === 6 ? MAX_DATAGRAM_V6 : MAX_DATAGRAM_V4;
|
|
17758
17870
|
if (bytes.length > max) throw new KernelError("EMSGSIZE");
|
|
17759
17871
|
const where = this.route(target.host);
|
|
17760
|
-
const
|
|
17872
|
+
const local2 = this.bound();
|
|
17761
17873
|
if (where === "uplink") return this.sendUp(bytes, target);
|
|
17762
17874
|
const from = {
|
|
17763
17875
|
family: "inet",
|
|
17764
|
-
host:
|
|
17765
|
-
port:
|
|
17876
|
+
host: local2.host === "0.0.0.0" ? "127.0.0.1" : local2.host,
|
|
17877
|
+
port: local2.port
|
|
17766
17878
|
};
|
|
17767
|
-
const
|
|
17879
|
+
const dest = { family: "inet", host: canonicalHost(target.host), port: target.port };
|
|
17880
|
+
const delivered = this.net.deliverDgram(target.port, { bytes: bytes.slice(), from }, dest);
|
|
17768
17881
|
if (!delivered && this.peer && sameAddr(this.peer, target)) {
|
|
17769
17882
|
this.pending = "ECONNREFUSED";
|
|
17770
17883
|
this.changes.wake();
|
|
@@ -19361,8 +19474,8 @@ function clientFirstOf(message3) {
|
|
|
19361
19474
|
return m ? { header: m[1], bare: m[2] } : void 0;
|
|
19362
19475
|
}
|
|
19363
19476
|
var latinBytes = (text) => Uint8Array.from(text, (c) => c.charCodeAt(0));
|
|
19364
|
-
function channelOf(
|
|
19365
|
-
const head = latinBytes(
|
|
19477
|
+
function channelOf(header4, binding) {
|
|
19478
|
+
const head = latinBytes(header4);
|
|
19366
19479
|
const all = new Uint8Array(head.length + (binding?.length ?? 0));
|
|
19367
19480
|
all.set(head);
|
|
19368
19481
|
if (binding) all.set(binding, head.length);
|
|
@@ -19587,8 +19700,8 @@ function frame3(type, body) {
|
|
|
19587
19700
|
return out;
|
|
19588
19701
|
}
|
|
19589
19702
|
function pgLength(bytes, started) {
|
|
19590
|
-
const
|
|
19591
|
-
if (bytes.length <
|
|
19703
|
+
const header4 = started ? 5 : 4;
|
|
19704
|
+
if (bytes.length < header4) return void 0;
|
|
19592
19705
|
const length2 = int32(bytes, started ? 1 : 0);
|
|
19593
19706
|
return started ? 1 + length2 : length2;
|
|
19594
19707
|
}
|
|
@@ -19616,16 +19729,16 @@ function initial(message3) {
|
|
|
19616
19729
|
function int32Text(n) {
|
|
19617
19730
|
return String.fromCharCode(n >>> 24 & 255, n >>> 16 & 255, n >>> 8 & 255, n & 255);
|
|
19618
19731
|
}
|
|
19619
|
-
function serverHeader(
|
|
19620
|
-
if (
|
|
19621
|
-
if (
|
|
19622
|
-
if (
|
|
19732
|
+
function serverHeader(header4, server) {
|
|
19733
|
+
if (header4 === "n,,") return header4;
|
|
19734
|
+
if (header4 === "y,," && !server.plus) return header4;
|
|
19735
|
+
if (header4 === END_POINT && server.binding) return header4;
|
|
19623
19736
|
return server.plus && server.binding ? END_POINT : "n,,";
|
|
19624
19737
|
}
|
|
19625
|
-
function rewritten(first,
|
|
19738
|
+
function rewritten(first, header4) {
|
|
19626
19739
|
const parsed2 = clientFirstOf(first.data);
|
|
19627
|
-
if (!parsed2 || parsed2.header ===
|
|
19628
|
-
return { mechanism:
|
|
19740
|
+
if (!parsed2 || parsed2.header === header4) return first;
|
|
19741
|
+
return { mechanism: header4 === END_POINT ? PLUS : PLAIN, data: `${header4}${parsed2.bare}` };
|
|
19629
19742
|
}
|
|
19630
19743
|
var PgClient = class {
|
|
19631
19744
|
clientFirst;
|
|
@@ -20750,8 +20863,8 @@ async function datagram(req, proc) {
|
|
|
20750
20863
|
const ready2 = pollFile(dgram).readable;
|
|
20751
20864
|
if (req.nonblock && !ready2) throw new KernelError("EAGAIN");
|
|
20752
20865
|
const got = await dgram.receive(req.max, req.peek, ready2 ? void 0 : proc.blocking());
|
|
20753
|
-
const { bytes, from, truncated } = got;
|
|
20754
|
-
return { ok: true, kind: "bytes", bytes: encodeReceived({ bytes, truncated, ...from }) };
|
|
20866
|
+
const { bytes, from, truncated: truncated2 } = got;
|
|
20867
|
+
return { ok: true, kind: "bytes", bytes: encodeReceived({ bytes, truncated: truncated2, ...from }) };
|
|
20755
20868
|
}
|
|
20756
20869
|
async function unixDatagram(req, dgram, proc) {
|
|
20757
20870
|
if (req.op === "sock-sendto") {
|
|
@@ -20761,11 +20874,11 @@ async function unixDatagram(req, dgram, proc) {
|
|
|
20761
20874
|
const ready2 = pollFile(dgram).readable;
|
|
20762
20875
|
if (req.nonblock && !ready2) throw new KernelError("EAGAIN");
|
|
20763
20876
|
const got = await dgram.receive(req.max, req.peek, ready2 ? void 0 : proc.blocking());
|
|
20764
|
-
const { bytes, from, truncated } = got;
|
|
20877
|
+
const { bytes, from, truncated: truncated2 } = got;
|
|
20765
20878
|
return {
|
|
20766
20879
|
ok: true,
|
|
20767
20880
|
kind: "bytes",
|
|
20768
|
-
bytes: encodeReceived({ bytes, truncated, host: from.path, port: 0, unix: true })
|
|
20881
|
+
bytes: encodeReceived({ bytes, truncated: truncated2, host: from.path, port: 0, unix: true })
|
|
20769
20882
|
};
|
|
20770
20883
|
}
|
|
20771
20884
|
function domainOf(socket) {
|
|
@@ -23516,9 +23629,9 @@ var JsThreads = class {
|
|
|
23516
23629
|
const { control, port } = msg;
|
|
23517
23630
|
const tid = ++this.last;
|
|
23518
23631
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
23519
|
-
const
|
|
23632
|
+
const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
23520
23633
|
const owned4 = new SharedArrayBuffer(4 * (1 + JS_THREAD_OWNED_FDS));
|
|
23521
|
-
if (this.frozen) Atomics.store(
|
|
23634
|
+
if (this.frozen) Atomics.store(header4, SAB_I_STOP, 1);
|
|
23522
23635
|
const clock = this.deps.clocks.thread(tid + 1, sab);
|
|
23523
23636
|
let ended = false;
|
|
23524
23637
|
const end = (code) => {
|
|
@@ -23526,7 +23639,7 @@ var JsThreads = class {
|
|
|
23526
23639
|
ended = true;
|
|
23527
23640
|
this.live.delete(tid);
|
|
23528
23641
|
this.headers.delete(tid);
|
|
23529
|
-
this.deps.wakes.delete(
|
|
23642
|
+
this.deps.wakes.delete(header4);
|
|
23530
23643
|
for (const [id2, token] of ops) {
|
|
23531
23644
|
void this.deps.dispatch({ op: "async-cancel", id: id2, token });
|
|
23532
23645
|
}
|
|
@@ -23576,8 +23689,8 @@ var JsThreads = class {
|
|
|
23576
23689
|
control.addEventListener("message", onControl);
|
|
23577
23690
|
control.start();
|
|
23578
23691
|
this.live.set(tid, end);
|
|
23579
|
-
this.headers.set(tid,
|
|
23580
|
-
this.deps.wakes.add(
|
|
23692
|
+
this.headers.set(tid, header4);
|
|
23693
|
+
this.deps.wakes.add(header4);
|
|
23581
23694
|
const init = {
|
|
23582
23695
|
...this.deps.init(sab, lane.lane),
|
|
23583
23696
|
type: JS_THREAD_INIT,
|
|
@@ -23597,9 +23710,9 @@ var JsThreads = class {
|
|
|
23597
23710
|
}
|
|
23598
23711
|
stopped(stopped) {
|
|
23599
23712
|
this.frozen = stopped;
|
|
23600
|
-
for (const
|
|
23601
|
-
Atomics.store(
|
|
23602
|
-
Atomics.notify(
|
|
23713
|
+
for (const header4 of this.headers.values()) {
|
|
23714
|
+
Atomics.store(header4, SAB_I_STOP, stopped ? 1 : 0);
|
|
23715
|
+
Atomics.notify(header4, SAB_I_STOP);
|
|
23603
23716
|
}
|
|
23604
23717
|
}
|
|
23605
23718
|
close() {
|
|
@@ -23644,13 +23757,13 @@ var Dying = class {
|
|
|
23644
23757
|
hard;
|
|
23645
23758
|
busy = 0;
|
|
23646
23759
|
finish;
|
|
23647
|
-
start(code, sig,
|
|
23760
|
+
start(code, sig, header4, process, finish) {
|
|
23648
23761
|
if (this.ending) return;
|
|
23649
23762
|
this.ending = { code, sig };
|
|
23650
23763
|
this.finish = finish;
|
|
23651
23764
|
this.hard = setTimeout(finish, KILL_HARD_MS);
|
|
23652
23765
|
this.arm();
|
|
23653
|
-
Atomics.store(
|
|
23766
|
+
Atomics.store(header4, SAB_I_KILLED, code);
|
|
23654
23767
|
process.die();
|
|
23655
23768
|
}
|
|
23656
23769
|
serve(req, work) {
|
|
@@ -23697,8 +23810,8 @@ function unblockedThread(threads, sig) {
|
|
|
23697
23810
|
}
|
|
23698
23811
|
return void 0;
|
|
23699
23812
|
}
|
|
23700
|
-
function unblocked(
|
|
23701
|
-
return Atomics.load(
|
|
23813
|
+
function unblocked(header4) {
|
|
23814
|
+
return Atomics.load(header4, SAB_I_SIGNALS) & ~Atomics.load(header4, SAB_I_BLOCKED);
|
|
23702
23815
|
}
|
|
23703
23816
|
function threadCall(process, req, cancelled, block) {
|
|
23704
23817
|
return isWasmSyscall(req) ? process.syscall(req, cancelled, block) : dispatchSyncFs(req);
|
|
@@ -23710,24 +23823,24 @@ function threadCancel(thread) {
|
|
|
23710
23823
|
return unblocked(thread.header) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
|
|
23711
23824
|
}
|
|
23712
23825
|
var asyncFanout = /* @__PURE__ */ new WeakMap();
|
|
23713
|
-
function notifiers(
|
|
23826
|
+
function notifiers(header4) {
|
|
23714
23827
|
return {
|
|
23715
23828
|
onPending(sig) {
|
|
23716
|
-
Atomics.or(
|
|
23717
|
-
Atomics.notify(
|
|
23829
|
+
Atomics.or(header4, SAB_I_SIGNALS, sigbit(sig));
|
|
23830
|
+
Atomics.notify(header4, SAB_I_SIGNALS);
|
|
23718
23831
|
},
|
|
23719
23832
|
onAsync() {
|
|
23720
|
-
for (const at of [
|
|
23833
|
+
for (const at of [header4, ...asyncFanout.get(header4) ?? []]) {
|
|
23721
23834
|
Atomics.add(at, SAB_I_ASYNC, 1);
|
|
23722
23835
|
Atomics.notify(at, SAB_I_ASYNC);
|
|
23723
23836
|
}
|
|
23724
23837
|
}
|
|
23725
23838
|
};
|
|
23726
23839
|
}
|
|
23727
|
-
function publishStops(process,
|
|
23840
|
+
function publishStops(process, header4) {
|
|
23728
23841
|
process.onState((state) => {
|
|
23729
|
-
Atomics.store(
|
|
23730
|
-
Atomics.notify(
|
|
23842
|
+
Atomics.store(header4, SAB_I_STOP, state === "stopped" ? 1 : 0);
|
|
23843
|
+
Atomics.notify(header4, SAB_I_STOP);
|
|
23731
23844
|
});
|
|
23732
23845
|
}
|
|
23733
23846
|
function transferOf(opts, lane) {
|
|
@@ -23819,7 +23932,7 @@ function linksOf(opts) {
|
|
|
23819
23932
|
function clipboardName(opts) {
|
|
23820
23933
|
return opts.program.abi === "js" ? {} : { clipboardName: opts.argv0 };
|
|
23821
23934
|
}
|
|
23822
|
-
function processOptions(opts,
|
|
23935
|
+
function processOptions(opts, header4, hooks, created4) {
|
|
23823
23936
|
return {
|
|
23824
23937
|
...inherited(opts),
|
|
23825
23938
|
...opts.owners ? { owners: true } : {},
|
|
@@ -23858,16 +23971,16 @@ function processOptions(opts, header3, hooks, created4) {
|
|
|
23858
23971
|
watches: opts.watches,
|
|
23859
23972
|
onReap: opts.onReap,
|
|
23860
23973
|
resolver: opts.resolver,
|
|
23861
|
-
...notifiers(
|
|
23862
|
-
onTimer: (which) => void Atomics.or(
|
|
23863
|
-
hasPending: () => unblocked(
|
|
23974
|
+
...notifiers(header4),
|
|
23975
|
+
onTimer: (which) => void Atomics.or(header4, SAB_I_TIMERS, 1 << which),
|
|
23976
|
+
hasPending: () => unblocked(header4) !== 0 || Atomics.load(header4, SAB_I_TIMERS) !== 0,
|
|
23864
23977
|
raise: hooks.raise,
|
|
23865
23978
|
threadKill: hooks.threadKill,
|
|
23866
23979
|
unblockedThread: hooks.unblockedThread,
|
|
23867
23980
|
...hooks.exitNow ? { exitNow: hooks.exitNow } : {},
|
|
23868
23981
|
...hooks.exitSignal ? { exitSignal: hooks.exitSignal } : {},
|
|
23869
|
-
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(
|
|
23870
|
-
...opts.program.abi === "wasi" ? { blockedBits: () => Atomics.load(
|
|
23982
|
+
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header4, SAB_I_SIGNALS) } : {},
|
|
23983
|
+
...opts.program.abi === "wasi" ? { blockedBits: () => Atomics.load(header4, SAB_I_BLOCKED) } : {}
|
|
23871
23984
|
};
|
|
23872
23985
|
}
|
|
23873
23986
|
function threadInit(opts, program, sab, cred, thread, main) {
|
|
@@ -23933,9 +24046,9 @@ async function crashReport(process, onError, message3) {
|
|
|
23933
24046
|
function spawnWasmProcess(opts) {
|
|
23934
24047
|
const { promise: ready2, resolve: started } = readiness(opts.program.abi);
|
|
23935
24048
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
23936
|
-
const
|
|
24049
|
+
const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
23937
24050
|
const blocked2 = opts.fork?.wasi?.blocked ?? opts.blocked;
|
|
23938
|
-
if (blocked2 && anyBlocked(blocked2) && opts.program.abi === "wasi") storeBlocked(
|
|
24051
|
+
if (blocked2 && anyBlocked(blocked2) && opts.program.abi === "wasi") storeBlocked(header4, blocked2);
|
|
23939
24052
|
const threadSignals = /* @__PURE__ */ new Map();
|
|
23940
24053
|
const created4 = new Created();
|
|
23941
24054
|
const process = new WasmProcess(
|
|
@@ -23943,7 +24056,7 @@ function spawnWasmProcess(opts) {
|
|
|
23943
24056
|
opts.fds,
|
|
23944
24057
|
processOptions(
|
|
23945
24058
|
opts,
|
|
23946
|
-
|
|
24059
|
+
header4,
|
|
23947
24060
|
{
|
|
23948
24061
|
raise: (sig, info) => signal(sig, info),
|
|
23949
24062
|
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process.signalMasks().caught, sig),
|
|
@@ -23956,7 +24069,7 @@ function spawnWasmProcess(opts) {
|
|
|
23956
24069
|
created4
|
|
23957
24070
|
)
|
|
23958
24071
|
);
|
|
23959
|
-
publishStops(process,
|
|
24072
|
+
publishStops(process, header4);
|
|
23960
24073
|
const holds2 = new HeldPaths();
|
|
23961
24074
|
opts.held?.add(holds2);
|
|
23962
24075
|
const token = holdingToken(opts, holds2, {
|
|
@@ -23977,7 +24090,7 @@ function spawnWasmProcess(opts) {
|
|
|
23977
24090
|
dispatch: clocks.timed(void 0, dispatch2)
|
|
23978
24091
|
});
|
|
23979
24092
|
const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
|
|
23980
|
-
const jsThreads = jsThreadsOf(opts, process, token, dispatch2, clocks,
|
|
24093
|
+
const jsThreads = jsThreadsOf(opts, process, token, dispatch2, clocks, header4);
|
|
23981
24094
|
const { promise: exited, resolve: settle3 } = Promise.withResolvers();
|
|
23982
24095
|
let done5 = false;
|
|
23983
24096
|
const crash = new CrashSlot((message3) => crashReport(process, opts.onError, message3));
|
|
@@ -24076,7 +24189,7 @@ function spawnWasmProcess(opts) {
|
|
|
24076
24189
|
);
|
|
24077
24190
|
const terminate = (code, sig) => {
|
|
24078
24191
|
if (opts.program.abi !== "wasi" || done5) finish(code, sig);
|
|
24079
|
-
else dying.start(code, sig,
|
|
24192
|
+
else dying.start(code, sig, header4, process, () => finish(code, sig));
|
|
24080
24193
|
};
|
|
24081
24194
|
const signal = (sig, info) => {
|
|
24082
24195
|
if (process.signal(sig, info) === "terminate")
|
|
@@ -24091,16 +24204,16 @@ function spawnWasmProcess(opts) {
|
|
|
24091
24204
|
signal,
|
|
24092
24205
|
termsig: () => endedBy,
|
|
24093
24206
|
onState: (listener) => process.onState(listener),
|
|
24094
|
-
memory: () => Atomics.load(
|
|
24095
|
-
...processViews(process, opts,
|
|
24207
|
+
memory: () => Atomics.load(header4, SAB_I_MEMORY) * 65536,
|
|
24208
|
+
...processViews(process, opts, header4),
|
|
24096
24209
|
writesBack: () => opts.program.abi === "wasi" && !done5,
|
|
24097
24210
|
...clockViews(clocks)
|
|
24098
24211
|
};
|
|
24099
24212
|
}
|
|
24100
|
-
function jsThreadsOf(opts, process, token, dispatch2, clocks,
|
|
24213
|
+
function jsThreadsOf(opts, process, token, dispatch2, clocks, header4) {
|
|
24101
24214
|
if (opts.program.abi !== "js") return void 0;
|
|
24102
24215
|
const wakes = /* @__PURE__ */ new Set();
|
|
24103
|
-
asyncFanout.set(
|
|
24216
|
+
asyncFanout.set(header4, wakes);
|
|
24104
24217
|
const threads = new JsThreads({
|
|
24105
24218
|
wakes,
|
|
24106
24219
|
cap: jsThreadCap(opts.env),
|
|
@@ -24115,10 +24228,10 @@ function jsThreadsOf(opts, process, token, dispatch2, clocks, header3) {
|
|
|
24115
24228
|
process.onState((state) => threads.stopped(state === "stopped"));
|
|
24116
24229
|
return threads;
|
|
24117
24230
|
}
|
|
24118
|
-
function processViews(process, opts,
|
|
24231
|
+
function processViews(process, opts, header4) {
|
|
24119
24232
|
return {
|
|
24120
24233
|
ignoredSignals: (fork) => process.inheritable(fork),
|
|
24121
|
-
blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(
|
|
24234
|
+
blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header4) : [0, 0],
|
|
24122
24235
|
signalMasks: () => process.signalMasks(),
|
|
24123
24236
|
umask: () => process.umask,
|
|
24124
24237
|
cred: () => copyCred(process.cred)
|
|
@@ -24676,42 +24789,398 @@ function isMessage(data) {
|
|
|
24676
24789
|
return adopt !== null && Array.isArray(adopt.records) && Array.isArray(adopt.flocks);
|
|
24677
24790
|
}
|
|
24678
24791
|
|
|
24679
|
-
// src/kernel/net/
|
|
24680
|
-
var
|
|
24681
|
-
|
|
24682
|
-
|
|
24683
|
-
|
|
24684
|
-
|
|
24685
|
-
|
|
24686
|
-
|
|
24687
|
-
|
|
24688
|
-
|
|
24689
|
-
|
|
24690
|
-
|
|
24691
|
-
|
|
24792
|
+
// src/kernel/net/dns-stub.ts
|
|
24793
|
+
var DNS_PORT = 53;
|
|
24794
|
+
var DNS_STUB_ADDRESS = "127.0.0.53";
|
|
24795
|
+
var RESOLV_CONF_PATH = "/etc/resolv.conf";
|
|
24796
|
+
var RESOLV_CONF = `nameserver ${DNS_STUB_ADDRESS}
|
|
24797
|
+
options edns0
|
|
24798
|
+
`;
|
|
24799
|
+
var DNS_STUB_TTL = 30;
|
|
24800
|
+
var DNS_FORWARD_TIMEOUT_MS = 5e3;
|
|
24801
|
+
var DNS_TCP_IDLE_MS = 1e4;
|
|
24802
|
+
var DNS_TCP_MAX = 64;
|
|
24803
|
+
var DNS_UDP_INFLIGHT = 64;
|
|
24804
|
+
var TYPE_A = 1;
|
|
24805
|
+
var TYPE_PTR = 12;
|
|
24806
|
+
var TYPE_AAAA = 28;
|
|
24807
|
+
var TYPE_OPT = 41;
|
|
24808
|
+
var CLASS_IN = 1;
|
|
24809
|
+
var NOERROR = 0;
|
|
24810
|
+
var FORMERR = 1;
|
|
24811
|
+
var SERVFAIL = 2;
|
|
24812
|
+
var NXDOMAIN = 3;
|
|
24813
|
+
var NOTIMP = 4;
|
|
24814
|
+
var QR = 32768;
|
|
24815
|
+
var AA = 1024;
|
|
24816
|
+
var TC = 512;
|
|
24817
|
+
var RD = 256;
|
|
24818
|
+
var RA = 128;
|
|
24819
|
+
var CD = 16;
|
|
24820
|
+
var UDP_PLAIN = 512;
|
|
24821
|
+
var UDP_EDNS = 1232;
|
|
24822
|
+
var UDP_MAX = 4096;
|
|
24823
|
+
var DOH_MAX = 65535;
|
|
24824
|
+
var LOCAL_ZONES = ["localhost", "slicc.internal"];
|
|
24825
|
+
var MESSAGE = "application/dns-message";
|
|
24826
|
+
var u16 = (b, at) => b[at] << 8 | b[at + 1];
|
|
24827
|
+
function skipName(b, at) {
|
|
24828
|
+
let i = at;
|
|
24829
|
+
for (let hops = 0; hops < 128; hops++) {
|
|
24830
|
+
if (i >= b.length) return void 0;
|
|
24831
|
+
const len = b[i];
|
|
24832
|
+
if (len === 0) return i + 1;
|
|
24833
|
+
if ((len & 192) === 192) return i + 2 <= b.length ? i + 2 : void 0;
|
|
24834
|
+
if (len & 192) return void 0;
|
|
24835
|
+
i += len + 1;
|
|
24836
|
+
}
|
|
24837
|
+
return void 0;
|
|
24838
|
+
}
|
|
24839
|
+
function readName(b, at) {
|
|
24840
|
+
const labels = [];
|
|
24841
|
+
let i = at;
|
|
24842
|
+
let size = 0;
|
|
24843
|
+
for (; ; ) {
|
|
24844
|
+
if (i >= b.length) return void 0;
|
|
24845
|
+
const len = b[i];
|
|
24846
|
+
if (len === 0) break;
|
|
24847
|
+
if (len & 192) return void 0;
|
|
24848
|
+
size += len + 1;
|
|
24849
|
+
if (size > 254 || i + 1 + len > b.length) return void 0;
|
|
24850
|
+
labels.push(new TextDecoder().decode(b.subarray(i + 1, i + 1 + len)));
|
|
24851
|
+
i += len + 1;
|
|
24852
|
+
}
|
|
24853
|
+
return { name: labels.join(".").toLowerCase(), end: i + 1 };
|
|
24854
|
+
}
|
|
24855
|
+
function parseQuery(b) {
|
|
24856
|
+
if (b.length < 12) return void 0;
|
|
24857
|
+
const id2 = u16(b, 0);
|
|
24858
|
+
const flags2 = u16(b, 2);
|
|
24859
|
+
if (flags2 & QR) return void 0;
|
|
24860
|
+
if (flags2 >> 11 & 15) return { ok: false, id: id2, flags: flags2, rcode: NOTIMP };
|
|
24861
|
+
if (u16(b, 4) !== 1) return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
|
|
24862
|
+
const read = readName(b, 12);
|
|
24863
|
+
if (!read || read.end + 4 > b.length) return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
|
|
24864
|
+
const type = u16(b, read.end);
|
|
24865
|
+
const klass = u16(b, read.end + 2);
|
|
24866
|
+
const end = read.end + 4;
|
|
24867
|
+
let edns;
|
|
24868
|
+
let at = end;
|
|
24869
|
+
const records = u16(b, 6) + u16(b, 8) + u16(b, 10);
|
|
24870
|
+
for (let n = 0; n < records; n++) {
|
|
24871
|
+
const after = skipName(b, at);
|
|
24872
|
+
if (after === void 0 || after + 10 > b.length)
|
|
24873
|
+
return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
|
|
24874
|
+
if (u16(b, after) === TYPE_OPT) edns = Math.max(UDP_PLAIN, u16(b, after + 2));
|
|
24875
|
+
at = after + 10 + u16(b, after + 8);
|
|
24876
|
+
if (at > b.length) return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
|
|
24877
|
+
}
|
|
24878
|
+
return { ok: true, question: { id: id2, flags: flags2, name: read.name, type, klass, end, edns } };
|
|
24879
|
+
}
|
|
24880
|
+
function encodeName(name2) {
|
|
24881
|
+
const out = [];
|
|
24882
|
+
for (const label of name2.split(".").filter(Boolean)) {
|
|
24883
|
+
const bytes = new TextEncoder().encode(label);
|
|
24884
|
+
out.push(bytes.length, ...bytes);
|
|
24885
|
+
}
|
|
24886
|
+
out.push(0);
|
|
24887
|
+
return out;
|
|
24888
|
+
}
|
|
24889
|
+
function header2(id2, flags2, counts) {
|
|
24890
|
+
const out = [id2 >> 8, id2 & 255, flags2 >> 8, flags2 & 255];
|
|
24891
|
+
for (const c of counts) out.push(c >> 8, c & 255);
|
|
24892
|
+
return out;
|
|
24893
|
+
}
|
|
24894
|
+
function opt() {
|
|
24895
|
+
return [0, 0, TYPE_OPT, UDP_EDNS >> 8, UDP_EDNS & 255, 0, 0, 0, 0, 0, 0];
|
|
24896
|
+
}
|
|
24897
|
+
function record(type, rdata) {
|
|
24898
|
+
const ttl = DNS_STUB_TTL;
|
|
24899
|
+
return [
|
|
24900
|
+
192,
|
|
24901
|
+
12,
|
|
24902
|
+
type >> 8,
|
|
24903
|
+
type & 255,
|
|
24904
|
+
0,
|
|
24905
|
+
CLASS_IN,
|
|
24906
|
+
ttl >>> 24 & 255,
|
|
24907
|
+
ttl >>> 16 & 255,
|
|
24908
|
+
ttl >>> 8 & 255,
|
|
24909
|
+
ttl & 255,
|
|
24910
|
+
rdata.length >> 8,
|
|
24911
|
+
rdata.length & 255,
|
|
24912
|
+
...rdata
|
|
24913
|
+
];
|
|
24914
|
+
}
|
|
24915
|
+
function replyFlags(query, rcode, aa) {
|
|
24916
|
+
return QR | query & 30720 | (aa ? AA : 0) | query & RD | RA | query & CD | rcode;
|
|
24917
|
+
}
|
|
24918
|
+
function answers(reply, q) {
|
|
24919
|
+
if (reply.length < 12 || !(u16(reply, 2) & QR) || u16(reply, 4) !== 1) return false;
|
|
24920
|
+
const read = readName(reply, 12);
|
|
24921
|
+
if (!read || read.end + 4 > reply.length) return false;
|
|
24922
|
+
return read.name === q.name && u16(reply, read.end) === q.type && u16(reply, read.end + 2) === q.klass;
|
|
24923
|
+
}
|
|
24924
|
+
function errorReply(id2, flags2, rcode) {
|
|
24925
|
+
return new Uint8Array(header2(id2, replyFlags(flags2, rcode, false), [0, 0, 0, 0]));
|
|
24926
|
+
}
|
|
24927
|
+
function answerReply(query, q, rcode, answers2, aa) {
|
|
24928
|
+
const extra = q.edns !== void 0 ? [opt()] : [];
|
|
24929
|
+
return new Uint8Array([
|
|
24930
|
+
...header2(q.id, replyFlags(q.flags, rcode, aa), [1, answers2.length, 0, extra.length]),
|
|
24931
|
+
...query.subarray(12, q.end),
|
|
24932
|
+
...answers2.flat(),
|
|
24933
|
+
...extra.flat()
|
|
24934
|
+
]);
|
|
24935
|
+
}
|
|
24936
|
+
function truncated(reply, q, query) {
|
|
24937
|
+
const limit = q.edns !== void 0 ? Math.min(q.edns, UDP_MAX) : UDP_PLAIN;
|
|
24938
|
+
if (reply.length <= limit) return reply;
|
|
24939
|
+
const flags2 = u16(reply, 2) | TC;
|
|
24940
|
+
const extra = q.edns !== void 0 ? [opt()] : [];
|
|
24941
|
+
return new Uint8Array([
|
|
24942
|
+
...header2(q.id, flags2, [1, 0, 0, extra.length]),
|
|
24943
|
+
...query.subarray(12, q.end),
|
|
24944
|
+
...extra.flat()
|
|
24945
|
+
]);
|
|
24946
|
+
}
|
|
24947
|
+
function ipv6Text(groups) {
|
|
24948
|
+
return groups.map((g) => g.toString(16)).join(":");
|
|
24949
|
+
}
|
|
24950
|
+
function reverseAddress(name2) {
|
|
24951
|
+
if (name2.endsWith(".in-addr.arpa")) {
|
|
24952
|
+
const parts2 = name2.slice(0, -".in-addr.arpa".length).split(".");
|
|
24953
|
+
if (parts2.length !== 4) return void 0;
|
|
24954
|
+
const text = parts2.reverse().join(".");
|
|
24955
|
+
return ipv4Bytes(text) ? text.split(".").map(Number).join(".") : void 0;
|
|
24956
|
+
}
|
|
24957
|
+
if (name2.endsWith(".ip6.arpa")) {
|
|
24958
|
+
const nibbles = name2.slice(0, -".ip6.arpa".length).split(".");
|
|
24959
|
+
if (nibbles.length !== 32 || !nibbles.every((n) => /^[0-9a-f]$/.test(n))) return void 0;
|
|
24960
|
+
const hex4 = nibbles.reverse().join("");
|
|
24961
|
+
const groups = Array.from(
|
|
24962
|
+
{ length: 8 },
|
|
24963
|
+
(_, i) => Number.parseInt(hex4.slice(i * 4, i * 4 + 4), 16)
|
|
24964
|
+
);
|
|
24965
|
+
return ipv6Text(groups);
|
|
24966
|
+
}
|
|
24967
|
+
return void 0;
|
|
24968
|
+
}
|
|
24969
|
+
function local(name2) {
|
|
24970
|
+
return LOCAL_ZONES.some((zone) => name2 === zone || name2.endsWith(`.${zone}`));
|
|
24971
|
+
}
|
|
24972
|
+
function literal(name2) {
|
|
24973
|
+
return ipv4Bytes(name2) !== void 0 || ipv6Groups(name2) !== void 0;
|
|
24974
|
+
}
|
|
24975
|
+
function addressData(address, type) {
|
|
24976
|
+
if (type === TYPE_A) return ipv4Bytes(address);
|
|
24977
|
+
const groups = type === TYPE_AAAA ? ipv6Groups(address) : void 0;
|
|
24978
|
+
return groups?.flatMap((g) => [g >> 8, g & 255]);
|
|
24979
|
+
}
|
|
24980
|
+
var DnsStub = class {
|
|
24981
|
+
resolver;
|
|
24982
|
+
forwarder;
|
|
24983
|
+
timeoutMs;
|
|
24984
|
+
constructor(options) {
|
|
24985
|
+
this.resolver = options.resolver;
|
|
24986
|
+
this.forwarder = options.forward;
|
|
24987
|
+
this.timeoutMs = options.timeoutMs ?? DNS_FORWARD_TIMEOUT_MS;
|
|
24988
|
+
}
|
|
24989
|
+
async answer(query, udp) {
|
|
24990
|
+
const parsed2 = parseQuery(query);
|
|
24991
|
+
if (!parsed2) return void 0;
|
|
24992
|
+
if (!parsed2.ok) return errorReply(parsed2.id, parsed2.flags, parsed2.rcode);
|
|
24993
|
+
const q = parsed2.question;
|
|
24994
|
+
const reply = await this.reply(query, q).catch(
|
|
24995
|
+
() => answerReply(query, q, SERVFAIL, [], false)
|
|
24996
|
+
);
|
|
24997
|
+
return udp ? truncated(reply, q, query) : reply;
|
|
24998
|
+
}
|
|
24999
|
+
async reply(query, q) {
|
|
25000
|
+
if (q.klass !== CLASS_IN || literal(q.name)) return this.forward(query, q);
|
|
25001
|
+
if (q.type === TYPE_PTR) {
|
|
25002
|
+
const address = reverseAddress(q.name);
|
|
25003
|
+
const name2 = address !== void 0 ? await this.reverse(address) : void 0;
|
|
25004
|
+
if (name2 !== void 0)
|
|
25005
|
+
return answerReply(query, q, NOERROR, [record(TYPE_PTR, encodeName(name2))], true);
|
|
25006
|
+
return this.forward(query, q);
|
|
25007
|
+
}
|
|
25008
|
+
if (q.type === TYPE_A || q.type === TYPE_AAAA) {
|
|
25009
|
+
const addresses = q.name === "" ? [] : await this.lookup(q.name);
|
|
25010
|
+
const answers2 = addresses.flatMap((a) => {
|
|
25011
|
+
const data = addressData(a, q.type);
|
|
25012
|
+
return data ? [record(q.type, data)] : [];
|
|
25013
|
+
});
|
|
25014
|
+
if (answers2.length > 0 || local(q.name) || await this.known(q.name)) {
|
|
25015
|
+
const rcode = addresses.length > 0 ? NOERROR : NXDOMAIN;
|
|
25016
|
+
return answerReply(query, q, rcode, answers2, local(q.name));
|
|
25017
|
+
}
|
|
25018
|
+
return this.forward(query, q);
|
|
25019
|
+
}
|
|
25020
|
+
if (await this.known(q.name)) return answerReply(query, q, NOERROR, [], true);
|
|
25021
|
+
if (local(q.name)) {
|
|
25022
|
+
const there = (await this.lookup(q.name)).length > 0;
|
|
25023
|
+
return answerReply(query, q, there ? NOERROR : NXDOMAIN, [], true);
|
|
24692
25024
|
}
|
|
25025
|
+
return this.forward(query, q);
|
|
24693
25026
|
}
|
|
24694
|
-
|
|
25027
|
+
lookup(name2) {
|
|
25028
|
+
return this.resolver.resolve(name2, 0).catch(() => []);
|
|
25029
|
+
}
|
|
25030
|
+
known(name2) {
|
|
25031
|
+
return this.resolver.known(name2).catch(() => false);
|
|
25032
|
+
}
|
|
25033
|
+
reverse(address) {
|
|
25034
|
+
return this.resolver.reverse(address).catch(() => void 0);
|
|
25035
|
+
}
|
|
25036
|
+
async forward(query, q) {
|
|
25037
|
+
if (!this.forwarder) return answerReply(query, q, SERVFAIL, [], false);
|
|
25038
|
+
const asked = query.slice();
|
|
25039
|
+
asked[0] = 0;
|
|
25040
|
+
asked[1] = 0;
|
|
25041
|
+
const got = await this.forwarder(asked, AbortSignal.timeout(this.timeoutMs)).catch(
|
|
25042
|
+
() => void 0
|
|
25043
|
+
);
|
|
25044
|
+
if (!got || !answers(got, q)) return answerReply(query, q, SERVFAIL, [], false);
|
|
25045
|
+
const reply = got.slice();
|
|
25046
|
+
reply[0] = q.id >> 8;
|
|
25047
|
+
reply[1] = q.id & 255;
|
|
25048
|
+
return reply;
|
|
25049
|
+
}
|
|
25050
|
+
};
|
|
25051
|
+
async function collect(body, max) {
|
|
25052
|
+
const parts2 = [];
|
|
25053
|
+
let size = 0;
|
|
25054
|
+
for await (const part of body) {
|
|
25055
|
+
size += part.length;
|
|
25056
|
+
if (size > max) return void 0;
|
|
25057
|
+
parts2.push(part);
|
|
25058
|
+
}
|
|
25059
|
+
const out = new Uint8Array(size);
|
|
25060
|
+
let at = 0;
|
|
25061
|
+
for (const part of parts2) {
|
|
25062
|
+
out.set(part, at);
|
|
25063
|
+
at += part.length;
|
|
25064
|
+
}
|
|
25065
|
+
return out;
|
|
24695
25066
|
}
|
|
24696
|
-
function
|
|
24697
|
-
|
|
24698
|
-
|
|
24699
|
-
|
|
24700
|
-
|
|
24701
|
-
|
|
24702
|
-
|
|
24703
|
-
|
|
25067
|
+
function dohForward(transport, url) {
|
|
25068
|
+
return async (query, signal) => {
|
|
25069
|
+
const res = await transport.fetch({
|
|
25070
|
+
url,
|
|
25071
|
+
method: "POST",
|
|
25072
|
+
headers: [
|
|
25073
|
+
["content-type", MESSAGE],
|
|
25074
|
+
["accept", MESSAGE]
|
|
25075
|
+
],
|
|
25076
|
+
body: query,
|
|
25077
|
+
signal
|
|
25078
|
+
});
|
|
25079
|
+
const type = res.headers.find(([k]) => k.toLowerCase() === "content-type")?.[1] ?? "";
|
|
25080
|
+
if (res.status !== 200 || type.split(";")[0].trim().toLowerCase() !== MESSAGE) {
|
|
25081
|
+
await res.cancel().catch(() => void 0);
|
|
24704
25082
|
return void 0;
|
|
24705
25083
|
}
|
|
24706
|
-
|
|
24707
|
-
if (now === stamp && table) return table;
|
|
24708
|
-
const text = await fs.readFile(path).catch(() => void 0);
|
|
24709
|
-
if (text === void 0) return void 0;
|
|
24710
|
-
stamp = now;
|
|
24711
|
-
table = parseHosts(text);
|
|
24712
|
-
return table;
|
|
25084
|
+
return collect(res.body, DOH_MAX);
|
|
24713
25085
|
};
|
|
24714
25086
|
}
|
|
25087
|
+
function uplinkForward(uplink, server) {
|
|
25088
|
+
return async (query, signal) => {
|
|
25089
|
+
const conn = await uplink.dial({ network: "tcp", host: server, port: DNS_PORT, signal });
|
|
25090
|
+
const stop = () => conn.close();
|
|
25091
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
25092
|
+
try {
|
|
25093
|
+
await conn.write(new Uint8Array([query.length >> 8, query.length & 255, ...query]));
|
|
25094
|
+
let got = new Uint8Array();
|
|
25095
|
+
for (; ; ) {
|
|
25096
|
+
if (got.length >= 2 && got.length >= 2 + u16(got, 0)) return got.slice(2, 2 + u16(got, 0));
|
|
25097
|
+
const piece = await conn.read();
|
|
25098
|
+
if (!piece) return void 0;
|
|
25099
|
+
const next3 = new Uint8Array(got.length + piece.length);
|
|
25100
|
+
next3.set(got);
|
|
25101
|
+
next3.set(piece, got.length);
|
|
25102
|
+
got = next3;
|
|
25103
|
+
}
|
|
25104
|
+
} finally {
|
|
25105
|
+
signal.removeEventListener("abort", stop);
|
|
25106
|
+
conn.close();
|
|
25107
|
+
}
|
|
25108
|
+
};
|
|
25109
|
+
}
|
|
25110
|
+
function dnsForward(uplink, transport, doh) {
|
|
25111
|
+
const server = uplink?.nameserver;
|
|
25112
|
+
if (uplink && server && (ipv4Bytes(server) || ipv6Groups(server)))
|
|
25113
|
+
return uplinkForward(uplink, server);
|
|
25114
|
+
return typeof doh === "string" ? dohForward(transport, doh) : void 0;
|
|
25115
|
+
}
|
|
25116
|
+
function kernelDnsStub(resolver, transport, uplink, doh) {
|
|
25117
|
+
return new DnsStub({ resolver, forward: dnsForward(uplink, transport, doh) });
|
|
25118
|
+
}
|
|
25119
|
+
async function readExactly(conn, size, signal) {
|
|
25120
|
+
const out = new Uint8Array(size);
|
|
25121
|
+
let at = 0;
|
|
25122
|
+
while (at < size) {
|
|
25123
|
+
const piece = await conn.read(size - at, signal);
|
|
25124
|
+
if (piece.length === 0) return void 0;
|
|
25125
|
+
out.set(piece, at);
|
|
25126
|
+
at += piece.length;
|
|
25127
|
+
}
|
|
25128
|
+
return out;
|
|
25129
|
+
}
|
|
25130
|
+
async function serveTcp(stub, conn) {
|
|
25131
|
+
try {
|
|
25132
|
+
for (; ; ) {
|
|
25133
|
+
const idle2 = AbortSignal.timeout(DNS_TCP_IDLE_MS);
|
|
25134
|
+
const size = await readExactly(conn, 2, idle2);
|
|
25135
|
+
if (!size) return;
|
|
25136
|
+
const query = await readExactly(conn, u16(size, 0), idle2);
|
|
25137
|
+
if (!query) return;
|
|
25138
|
+
const reply = await stub.answer(query, false);
|
|
25139
|
+
if (!reply) return;
|
|
25140
|
+
const framed = new Uint8Array([reply.length >> 8, reply.length & 255, ...reply]);
|
|
25141
|
+
const sent = await conn.write(framed, AbortSignal.timeout(DNS_TCP_IDLE_MS));
|
|
25142
|
+
if (sent < framed.length) return;
|
|
25143
|
+
}
|
|
25144
|
+
} catch {
|
|
25145
|
+
return;
|
|
25146
|
+
} finally {
|
|
25147
|
+
conn.close();
|
|
25148
|
+
}
|
|
25149
|
+
}
|
|
25150
|
+
function enableDnsStub(net, stub) {
|
|
25151
|
+
const at = { family: "inet", host: "127.0.0.1", port: DNS_PORT };
|
|
25152
|
+
net.reserve(DNS_PORT);
|
|
25153
|
+
net.kernelOnly(DNS_PORT, true);
|
|
25154
|
+
net.activate(at, () => {
|
|
25155
|
+
const listener = net.listen(at);
|
|
25156
|
+
const open2 = /* @__PURE__ */ new Set();
|
|
25157
|
+
void (async () => {
|
|
25158
|
+
for (; ; ) {
|
|
25159
|
+
const conn = await listener.accept().catch(() => void 0);
|
|
25160
|
+
if (!conn) return;
|
|
25161
|
+
if (open2.size >= DNS_TCP_MAX) {
|
|
25162
|
+
conn.close();
|
|
25163
|
+
continue;
|
|
25164
|
+
}
|
|
25165
|
+
open2.add(conn);
|
|
25166
|
+
void serveTcp(stub, conn).finally(() => open2.delete(conn));
|
|
25167
|
+
}
|
|
25168
|
+
})();
|
|
25169
|
+
});
|
|
25170
|
+
let inflight = 0;
|
|
25171
|
+
net.serveDgram(DNS_PORT, (datagram2, to) => {
|
|
25172
|
+
if (inflight >= DNS_UDP_INFLIGHT) return;
|
|
25173
|
+
inflight++;
|
|
25174
|
+
void stub.answer(datagram2.bytes, true).then(
|
|
25175
|
+
(reply) => {
|
|
25176
|
+
if (!reply) return;
|
|
25177
|
+
const from = { family: "inet", host: to.host, port: DNS_PORT };
|
|
25178
|
+
net.deliverDgram(datagram2.from.port, { bytes: reply, from });
|
|
25179
|
+
},
|
|
25180
|
+
() => void 0
|
|
25181
|
+
).finally(() => inflight--);
|
|
25182
|
+
});
|
|
25183
|
+
}
|
|
24715
25184
|
|
|
24716
25185
|
// src/kernel/net/redirect-hops.ts
|
|
24717
25186
|
var HELD_MS = 3e4;
|
|
@@ -24719,13 +25188,13 @@ var HELD_MAX = 64;
|
|
|
24719
25188
|
var HELD_PER_OWNER = 8;
|
|
24720
25189
|
var MATCHED = ["range", "if-none-match", "if-modified-since", "if-range", "accept-encoding"];
|
|
24721
25190
|
var KERNEL = -1;
|
|
24722
|
-
function
|
|
25191
|
+
function header3(headers, name2) {
|
|
24723
25192
|
const values = headers.filter(([n]) => n.toLowerCase() === name2).map(([, v]) => v);
|
|
24724
25193
|
return values.length > 0 ? values.join(", ") : void 0;
|
|
24725
25194
|
}
|
|
24726
25195
|
function fingerprint(headers) {
|
|
24727
|
-
const fields = MATCHED.map((name2) =>
|
|
24728
|
-
return JSON.stringify([...fields,
|
|
25196
|
+
const fields = MATCHED.map((name2) => header3(headers, name2) ?? "");
|
|
25197
|
+
return JSON.stringify([...fields, header3(headers, "authorization") !== void 0]);
|
|
24729
25198
|
}
|
|
24730
25199
|
function unauthorized(print) {
|
|
24731
25200
|
return JSON.stringify([...JSON.parse(print).slice(0, -1), false]);
|
|
@@ -24768,7 +25237,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
|
|
|
24768
25237
|
};
|
|
24769
25238
|
const replay = (chain2) => {
|
|
24770
25239
|
const [hop, ...rest2] = chain2.hops;
|
|
24771
|
-
const location = hop &&
|
|
25240
|
+
const location = hop && header3(hop.headers, "location");
|
|
24772
25241
|
if (!hop || location === void 0) return chain2.final;
|
|
24773
25242
|
const target = new URL(location, hop.url);
|
|
24774
25243
|
target.hash = "";
|
|
@@ -24893,7 +25362,7 @@ function materializable(req) {
|
|
|
24893
25362
|
if (req.shellGrants !== true && !isStrings(req.names)) return false;
|
|
24894
25363
|
return isStrings(req.argv) && typeof req.path === "string" && typeof req.cwd === "string";
|
|
24895
25364
|
}
|
|
24896
|
-
function
|
|
25365
|
+
function errorReply2(code, message3) {
|
|
24897
25366
|
return { v: 1, error: { code, message: message3 } };
|
|
24898
25367
|
}
|
|
24899
25368
|
function isRecord(value2) {
|
|
@@ -24905,9 +25374,9 @@ function serialized(reply) {
|
|
|
24905
25374
|
const text = JSON.stringify(reply);
|
|
24906
25375
|
plain3 = text === void 0 ? void 0 : JSON.parse(text);
|
|
24907
25376
|
} catch (err) {
|
|
24908
|
-
return JSON.stringify(
|
|
25377
|
+
return JSON.stringify(errorReply2("EIO", lineOf2(err)));
|
|
24909
25378
|
}
|
|
24910
|
-
if (!isRecord(plain3)) return JSON.stringify(
|
|
25379
|
+
if (!isRecord(plain3)) return JSON.stringify(errorReply2("EIO", "the vault gave no reply"));
|
|
24911
25380
|
const { v: _, ...rest2 } = plain3;
|
|
24912
25381
|
return JSON.stringify({ v: 1, ...rest2 });
|
|
24913
25382
|
}
|
|
@@ -24955,18 +25424,18 @@ var SealedChannel = class {
|
|
|
24955
25424
|
}
|
|
24956
25425
|
async answer(req, signal) {
|
|
24957
25426
|
const hook = this.broker.hook;
|
|
24958
|
-
if (!hook) return
|
|
25427
|
+
if (!hook) return errorReply2("ENOTCONN", "no vault is connected");
|
|
24959
25428
|
const stopped = new Promise((resolve2) => {
|
|
24960
25429
|
signal.addEventListener("abort", () => resolve2(void 0), { once: true });
|
|
24961
25430
|
});
|
|
24962
25431
|
if (signal.aborted) return void 0;
|
|
24963
25432
|
const asked = Promise.resolve().then(() => hook(req, { signal })).then(
|
|
24964
|
-
(reply2) => isRecord(reply2) ? reply2 :
|
|
24965
|
-
(err) =>
|
|
25433
|
+
(reply2) => isRecord(reply2) ? reply2 : errorReply2("EIO", "the vault gave no reply"),
|
|
25434
|
+
(err) => errorReply2("EIO", lineOf2(err))
|
|
24966
25435
|
);
|
|
24967
25436
|
const reply = await Promise.race([asked, stopped]);
|
|
24968
25437
|
if (!signal.aborted) return reply;
|
|
24969
|
-
return signal.reason === "timeout" ?
|
|
25438
|
+
return signal.reason === "timeout" ? errorReply2("ETIMEDOUT", "the vault did not answer within 10 s") : void 0;
|
|
24970
25439
|
}
|
|
24971
25440
|
drop() {
|
|
24972
25441
|
this.reply?.fill(0);
|
|
@@ -27312,6 +27781,10 @@ function blobModuleUrl(source) {
|
|
|
27312
27781
|
const url = URL.createObjectURL(new Blob([source], { type: "text/javascript" }));
|
|
27313
27782
|
return { url, revoke: () => URL.revokeObjectURL(url) };
|
|
27314
27783
|
}
|
|
27784
|
+
function describe(req, tty) {
|
|
27785
|
+
const exe = req.exe === void 0 ? {} : { exe: req.exe };
|
|
27786
|
+
return { argv: [req.argv0, ...req.args], tty, started: Date.now(), ...exe };
|
|
27787
|
+
}
|
|
27315
27788
|
function linksOf2(req) {
|
|
27316
27789
|
return req.links === void 0 ? {} : { links: req.links };
|
|
27317
27790
|
}
|
|
@@ -27333,6 +27806,7 @@ var LAYOUT = [
|
|
|
27333
27806
|
["/etc", 493],
|
|
27334
27807
|
[PASSWD, 420],
|
|
27335
27808
|
[GROUP, 420],
|
|
27809
|
+
[RESOLV_CONF_PATH, 420],
|
|
27336
27810
|
["/usr", 493],
|
|
27337
27811
|
["/usr/local", 493]
|
|
27338
27812
|
];
|
|
@@ -27675,6 +28149,10 @@ var Launcher = class {
|
|
|
27675
28149
|
roots: packageTlsRoots(this.verifiedFs(options.fs), this.modulesDir),
|
|
27676
28150
|
ca: this.ca
|
|
27677
28151
|
});
|
|
28152
|
+
enableDnsStub(
|
|
28153
|
+
this.net,
|
|
28154
|
+
kernelDnsStub(this.resolver, this.transport, options.uplink, options.doh)
|
|
28155
|
+
);
|
|
27678
28156
|
enableCdp(this.net, this.cdp);
|
|
27679
28157
|
this.facades.enable(this.net);
|
|
27680
28158
|
const fs = this.commandFs(this.base);
|
|
@@ -27762,10 +28240,10 @@ var Launcher = class {
|
|
|
27762
28240
|
ready: () => this.fstab,
|
|
27763
28241
|
lookup: (name2) => this.users.lookup(name2),
|
|
27764
28242
|
watch: async (paths, notify) => {
|
|
27765
|
-
const
|
|
28243
|
+
const local2 = this.watchers.watch(paths, { recursive: true }, () => notify());
|
|
27766
28244
|
const remote = await this.watchFiles(paths, notify);
|
|
27767
28245
|
return () => {
|
|
27768
|
-
|
|
28246
|
+
local2();
|
|
27769
28247
|
remote();
|
|
27770
28248
|
};
|
|
27771
28249
|
},
|
|
@@ -27951,7 +28429,7 @@ var Launcher = class {
|
|
|
27951
28429
|
abi: "wasi",
|
|
27952
28430
|
glue,
|
|
27953
28431
|
wasm: glue,
|
|
27954
|
-
argv0
|
|
28432
|
+
argv0,
|
|
27955
28433
|
...asked
|
|
27956
28434
|
};
|
|
27957
28435
|
}
|
|
@@ -28493,7 +28971,18 @@ var Launcher = class {
|
|
|
28493
28971
|
const handle = await this.admitted(
|
|
28494
28972
|
program.abi !== "js",
|
|
28495
28973
|
req.fds,
|
|
28496
|
-
(fds, quietOom) => this.start({
|
|
28974
|
+
(fds, quietOom) => this.start({
|
|
28975
|
+
...req,
|
|
28976
|
+
fds,
|
|
28977
|
+
quietOom,
|
|
28978
|
+
cwd,
|
|
28979
|
+
program,
|
|
28980
|
+
argv0: target.argv0,
|
|
28981
|
+
exe: target.copy ?? target.glue,
|
|
28982
|
+
args,
|
|
28983
|
+
env,
|
|
28984
|
+
cwdSlot
|
|
28985
|
+
})
|
|
28497
28986
|
).finally(() => this.cwds.release(cwdSlot));
|
|
28498
28987
|
void handle.exited.finally(done5);
|
|
28499
28988
|
return handle;
|
|
@@ -28685,11 +29174,7 @@ var Launcher = class {
|
|
|
28685
29174
|
if (req.pgid !== void 0) this.jobs.join(pid, req.pgid);
|
|
28686
29175
|
if (req.group === "lead") this.jobs.lead(pid);
|
|
28687
29176
|
if (req.group === "session") this.jobs.setsid(pid);
|
|
28688
|
-
this.described.set(pid,
|
|
28689
|
-
argv: [req.argv0, ...req.args],
|
|
28690
|
-
tty: terminal?.name ?? null,
|
|
28691
|
-
started: Date.now()
|
|
28692
|
-
});
|
|
29177
|
+
this.described.set(pid, describe(req, terminal?.name ?? null));
|
|
28693
29178
|
handle.onState(
|
|
28694
29179
|
(state) => state === "stopped" ? this.stopped.add(pid) : this.stopped.delete(pid)
|
|
28695
29180
|
);
|
|
@@ -29297,6 +29782,19 @@ var Launcher = class {
|
|
|
29297
29782
|
inUse(path) {
|
|
29298
29783
|
return [...this.openFiles].some((nodes) => nodes.holds(path)) || heldUnder(this.held, path);
|
|
29299
29784
|
}
|
|
29785
|
+
async resolvConf() {
|
|
29786
|
+
if (isProtected(this.prefixes, RESOLV_CONF_PATH)) return;
|
|
29787
|
+
try {
|
|
29788
|
+
const there = await this.base.lstat(RESOLV_CONF_PATH).then(
|
|
29789
|
+
() => true,
|
|
29790
|
+
() => false
|
|
29791
|
+
);
|
|
29792
|
+
if (there) return;
|
|
29793
|
+
await this.base.writeFile(RESOLV_CONF_PATH, RESOLV_CONF);
|
|
29794
|
+
} catch {
|
|
29795
|
+
return;
|
|
29796
|
+
}
|
|
29797
|
+
}
|
|
29300
29798
|
async stampLayout() {
|
|
29301
29799
|
const layout = [
|
|
29302
29800
|
...LAYOUT,
|
|
@@ -29432,6 +29930,7 @@ var Launcher = class {
|
|
|
29432
29930
|
await this.mountShm();
|
|
29433
29931
|
await this.pnpmReady();
|
|
29434
29932
|
await this.users.ensure();
|
|
29933
|
+
await this.resolvConf();
|
|
29435
29934
|
if (this.owners) await this.stampLayout();
|
|
29436
29935
|
if (this.owners) await this.sudoer.provision();
|
|
29437
29936
|
await writeCaFile(this.base, this.ca).catch(() => void 0);
|
|
@@ -29670,12 +30169,12 @@ var Launcher = class {
|
|
|
29670
30169
|
const out = [];
|
|
29671
30170
|
const err = [];
|
|
29672
30171
|
const keep2 = options.collect !== false;
|
|
29673
|
-
const
|
|
30172
|
+
const collect2 = (chunks, tee) => (bytes) => {
|
|
29674
30173
|
if (keep2) chunks.push(bytes);
|
|
29675
30174
|
tee?.(bytes);
|
|
29676
30175
|
};
|
|
29677
|
-
const stdout =
|
|
29678
|
-
const stderr =
|
|
30176
|
+
const stdout = collect2(out, options.onStdout);
|
|
30177
|
+
const stderr = collect2(err, options.onStderr);
|
|
29679
30178
|
const report = (message3) => stderr(encoder10.encode(`${message3}
|
|
29680
30179
|
`));
|
|
29681
30180
|
if (!planned) {
|
|
@@ -30093,7 +30592,14 @@ function facadesOption(req, port) {
|
|
|
30093
30592
|
function remotes(port, req) {
|
|
30094
30593
|
return {
|
|
30095
30594
|
...req.transport ? { transport: new RemoteTransport(port, req.transport) } : {},
|
|
30096
|
-
...req.uplink ? {
|
|
30595
|
+
...req.uplink ? {
|
|
30596
|
+
uplink: new RemoteUplink(
|
|
30597
|
+
port,
|
|
30598
|
+
req.uplink.traits,
|
|
30599
|
+
req.uplink.routes,
|
|
30600
|
+
req.uplink.nameserver
|
|
30601
|
+
)
|
|
30602
|
+
} : {}
|
|
30097
30603
|
};
|
|
30098
30604
|
}
|
|
30099
30605
|
function dial(l, req) {
|
|
@@ -30191,6 +30697,7 @@ function hostOptions(req, port, sealed, clipboard, lookup2) {
|
|
|
30191
30697
|
return {
|
|
30192
30698
|
cron: { lock: `slicc-kernel-cron:${req.metadata ?? META_DB}` },
|
|
30193
30699
|
...req.hostname !== void 0 ? { hostname: req.hostname } : {},
|
|
30700
|
+
...req.doh !== void 0 ? { doh: req.doh } : {},
|
|
30194
30701
|
...req.users !== void 0 ? { users: req.users } : {},
|
|
30195
30702
|
...req.denials ? { onDenial: (denial) => port.postMessage({ denial }) } : {},
|
|
30196
30703
|
...req.protect ? { protect: hostProtect(req.protect, lookup2) } : {},
|