@ai-ecoverse/slicc-kernel 1.110.7 → 1.111.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 +18 -2
- package/dist/kernel-worker.js +1031 -826
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +106 -23
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +615 -410
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +103 -20
- package/dist/process-worker.js.map +3 -3
- package/dist/types/kernel/fd-table.d.ts +1 -1
- package/dist/types/kernel/net/datagram-wire.d.ts +1 -0
- package/dist/types/kernel/socket-syscalls.d.ts +1 -0
- package/dist/types/kernel/socket.d.ts +6 -0
- package/dist/types/kernel/unix-dgram.d.ts +47 -0
- package/dist/types/process/wasi/wasi-host.d.ts +4 -0
- package/package.json +3 -3
package/dist/node.js
CHANGED
|
@@ -1858,6 +1858,7 @@ var LOCAL_ONLY = new Routes();
|
|
|
1858
1858
|
var LoopbackNet = class {
|
|
1859
1859
|
bound = /* @__PURE__ */ new Map();
|
|
1860
1860
|
dgrams = /* @__PURE__ */ new Map();
|
|
1861
|
+
unixDgrams = /* @__PURE__ */ new Map();
|
|
1861
1862
|
activators = /* @__PURE__ */ new Map();
|
|
1862
1863
|
internal = /* @__PURE__ */ new Set();
|
|
1863
1864
|
reserved = /* @__PURE__ */ new Set();
|
|
@@ -1883,6 +1884,18 @@ var LoopbackNet = class {
|
|
|
1883
1884
|
this.dgrams.set(port, socket);
|
|
1884
1885
|
return { ...addr, port };
|
|
1885
1886
|
}
|
|
1887
|
+
bindUnixDgram(socket, key) {
|
|
1888
|
+
if (this.bound.has(key) || this.unixDgrams.has(key)) throw new KernelError("EADDRINUSE");
|
|
1889
|
+
this.unixDgrams.set(key, socket);
|
|
1890
|
+
}
|
|
1891
|
+
releaseUnixDgram(key, socket) {
|
|
1892
|
+
if (this.unixDgrams.get(key) === socket) this.unixDgrams.delete(key);
|
|
1893
|
+
}
|
|
1894
|
+
unixDgramAt(key) {
|
|
1895
|
+
const socket = this.unixDgrams.get(key);
|
|
1896
|
+
if (socket) return socket;
|
|
1897
|
+
throw new KernelError(this.bound.has(key) ? "EPROTOTYPE" : "ECONNREFUSED");
|
|
1898
|
+
}
|
|
1886
1899
|
releaseDgram(addr, socket) {
|
|
1887
1900
|
if (this.dgrams.get(addr.port) === socket) this.dgrams.delete(addr.port);
|
|
1888
1901
|
}
|
|
@@ -1936,7 +1949,9 @@ var LoopbackNet = class {
|
|
|
1936
1949
|
} else this.bindable(addr, kernel);
|
|
1937
1950
|
const named = addr.family === "inet" && addr.port === 0 ? { ...addr, port: this.ephemeral() } : addr;
|
|
1938
1951
|
const key = keyOf(named, name2);
|
|
1939
|
-
if (this.bound.has(key) && !name2
|
|
1952
|
+
if (this.bound.has(key) && !name2 || this.unixDgrams.has(key)) {
|
|
1953
|
+
throw new KernelError("EADDRINUSE");
|
|
1954
|
+
}
|
|
1940
1955
|
this.bound.set(key, socket);
|
|
1941
1956
|
socket.named = name2;
|
|
1942
1957
|
return named;
|
|
@@ -1950,6 +1965,7 @@ var LoopbackNet = class {
|
|
|
1950
1965
|
throw new KernelError("ENETUNREACH");
|
|
1951
1966
|
}
|
|
1952
1967
|
const key = keyOf(addr, name2);
|
|
1968
|
+
if (this.unixDgrams.has(key)) throw new KernelError("EPROTOTYPE");
|
|
1953
1969
|
if (!this.bound.has(key)) this.activators.get(key)?.();
|
|
1954
1970
|
const socket = this.bound.get(key);
|
|
1955
1971
|
if (!socket?.listening) throw new KernelError("ECONNREFUSED");
|
|
@@ -6494,7 +6510,7 @@ function satisfies(version, range2) {
|
|
|
6494
6510
|
}
|
|
6495
6511
|
|
|
6496
6512
|
// src/version.ts
|
|
6497
|
-
var KERNEL_VERSION = true ? "1.
|
|
6513
|
+
var KERNEL_VERSION = true ? "1.111.0" : "0.0.0-dev";
|
|
6498
6514
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6499
6515
|
function procVersion() {
|
|
6500
6516
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -11860,391 +11876,115 @@ var ProcessClocks = class {
|
|
|
11860
11876
|
}
|
|
11861
11877
|
};
|
|
11862
11878
|
|
|
11863
|
-
// src/
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
|
|
11870
|
-
|
|
11871
|
-
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
var DGRAM_SEND_ROOM = 256 * 1024;
|
|
11881
|
-
var MAX_DATAGRAM_V4 = 65507;
|
|
11882
|
-
var MAX_DATAGRAM_V6 = 65527;
|
|
11883
|
-
var SOL_SOCKET2 = 1;
|
|
11884
|
-
var IPPROTO_IP = 0;
|
|
11885
|
-
var SO_TYPE2 = 3;
|
|
11886
|
-
var SO_ERROR2 = 4;
|
|
11887
|
-
var SO_BROADCAST = 6;
|
|
11888
|
-
var SO_SNDBUF2 = 7;
|
|
11889
|
-
var SO_RCVBUF2 = 8;
|
|
11890
|
-
var SO_DOMAIN2 = 39;
|
|
11891
|
-
var SOCK_DGRAM = 2;
|
|
11892
|
-
var AF_INET2 = 2;
|
|
11893
|
-
var IP_MULTICAST_FIRST = 32;
|
|
11894
|
-
var IP_MULTICAST_LAST = 36;
|
|
11895
|
-
var SEND_ERRORS = ["ENETUNREACH", "EHOSTUNREACH", "EACCES", "EMSGSIZE"];
|
|
11896
|
-
var UNREACHABLE = ["EACCES", "ENETUNREACH", "EHOSTUNREACH"];
|
|
11897
|
-
function sendError(e) {
|
|
11898
|
-
if (e instanceof KernelError) return e;
|
|
11899
|
-
const code = e?.code;
|
|
11900
|
-
return new KernelError(SEND_ERRORS.find((errno2) => errno2 === code) ?? "EHOSTUNREACH");
|
|
11901
|
-
}
|
|
11902
|
-
function sameAddr(a, b) {
|
|
11903
|
-
return a.port === b.port && canonicalHost(a.host) === canonicalHost(b.host);
|
|
11904
|
-
}
|
|
11905
|
-
function familyOf(host) {
|
|
11906
|
-
return host.includes(":") ? 6 : 4;
|
|
11907
|
-
}
|
|
11908
|
-
var KernelDgram = class {
|
|
11909
|
-
local;
|
|
11910
|
-
peer;
|
|
11911
|
-
net;
|
|
11912
|
-
queue = [];
|
|
11913
|
-
queued = 0;
|
|
11914
|
-
pending;
|
|
11915
|
-
closed = false;
|
|
11916
|
-
sending = 0;
|
|
11917
|
-
changes = new Changes();
|
|
11918
|
-
options = /* @__PURE__ */ new Map();
|
|
11919
|
-
uplinks = /* @__PURE__ */ new Map();
|
|
11920
|
-
stop = new AbortController();
|
|
11921
|
-
constructor(net) {
|
|
11922
|
-
this.net = net;
|
|
11879
|
+
// src/fs/pages.ts
|
|
11880
|
+
var PAGE = 64 * 1024;
|
|
11881
|
+
var READAHEAD = 1024 * 1024;
|
|
11882
|
+
var CLEAN_LIMIT = 4 * 1024 * 1024;
|
|
11883
|
+
var WRITEBACK = 8 * 1024 * 1024;
|
|
11884
|
+
var RUN = 1024 * 1024;
|
|
11885
|
+
var Pages = class {
|
|
11886
|
+
length;
|
|
11887
|
+
stored;
|
|
11888
|
+
shrink;
|
|
11889
|
+
pages = /* @__PURE__ */ new Map();
|
|
11890
|
+
dirty = /* @__PURE__ */ new Set();
|
|
11891
|
+
free = [];
|
|
11892
|
+
pinned = false;
|
|
11893
|
+
constructor(size) {
|
|
11894
|
+
this.length = size;
|
|
11895
|
+
this.stored = size;
|
|
11923
11896
|
}
|
|
11924
|
-
|
|
11925
|
-
|
|
11926
|
-
this.local = this.net.bindDgram(this, addr);
|
|
11897
|
+
get dirtyBytes() {
|
|
11898
|
+
return this.dirty.size * PAGE;
|
|
11927
11899
|
}
|
|
11928
|
-
|
|
11929
|
-
this.
|
|
11930
|
-
return this.local;
|
|
11900
|
+
get changed() {
|
|
11901
|
+
return this.dirty.size > 0 || this.shrink !== void 0 || this.length !== this.stored;
|
|
11931
11902
|
}
|
|
11932
|
-
|
|
11933
|
-
|
|
11934
|
-
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
|
|
11938
|
-
|
|
11903
|
+
missing(at, length2) {
|
|
11904
|
+
this.evict();
|
|
11905
|
+
const end = Math.min(this.stored, at + length2, this.length);
|
|
11906
|
+
const runs = [];
|
|
11907
|
+
for (let page = Math.floor(at / PAGE); page * PAGE < end; page++) {
|
|
11908
|
+
if (this.pages.has(page)) continue;
|
|
11909
|
+
const last2 = runs[runs.length - 1];
|
|
11910
|
+
if (last2 && last2[0] + last2[1] === page * PAGE) last2[1] += PAGE;
|
|
11911
|
+
else runs.push([page * PAGE, PAGE]);
|
|
11912
|
+
}
|
|
11913
|
+
const last = runs[runs.length - 1];
|
|
11914
|
+
if (last) last[1] = Math.max(last[1], Math.min(READAHEAD, this.stored - last[0]));
|
|
11915
|
+
return runs.map(([start2, n]) => [start2, Math.min(n, this.stored - start2)]);
|
|
11939
11916
|
}
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
this.
|
|
11943
|
-
|
|
11917
|
+
partial(at, length2) {
|
|
11918
|
+
if (length2 === 0) return [];
|
|
11919
|
+
this.evict();
|
|
11920
|
+
const edges = /* @__PURE__ */ new Set([Math.floor(at / PAGE), Math.floor((at + length2 - 1) / PAGE)]);
|
|
11921
|
+
const runs = [];
|
|
11922
|
+
for (const page of edges) {
|
|
11923
|
+
const start2 = page * PAGE;
|
|
11924
|
+
const covered = at <= start2 && at + length2 >= start2 + PAGE;
|
|
11925
|
+
if (covered || this.pages.has(page) || start2 >= this.stored) continue;
|
|
11926
|
+
runs.push([start2, Math.min(PAGE, this.stored - start2)]);
|
|
11927
|
+
}
|
|
11928
|
+
return runs;
|
|
11944
11929
|
}
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
|
|
11930
|
+
fill(start2, bytes) {
|
|
11931
|
+
for (let at = 0; at < bytes.length; at += PAGE) {
|
|
11932
|
+
const page = (start2 + at) / PAGE;
|
|
11933
|
+
if (this.pages.has(page)) continue;
|
|
11934
|
+
const part = bytes.subarray(at, Math.min(at + PAGE, bytes.length));
|
|
11935
|
+
const fresh2 = this.take(part.length);
|
|
11936
|
+
fresh2.set(part);
|
|
11937
|
+
this.pages.set(page, fresh2);
|
|
11938
|
+
}
|
|
11949
11939
|
}
|
|
11950
|
-
|
|
11951
|
-
const
|
|
11952
|
-
this.
|
|
11953
|
-
return
|
|
11940
|
+
read(at, length2) {
|
|
11941
|
+
const out = new Uint8Array(Math.max(0, Math.min(this.length, at + length2) - at));
|
|
11942
|
+
this.readInto(at, out);
|
|
11943
|
+
return out;
|
|
11954
11944
|
}
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
|
|
11960
|
-
|
|
11961
|
-
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
const local = this.bound();
|
|
11966
|
-
if (where === "uplink") return this.sendUp(bytes, target);
|
|
11967
|
-
const from = {
|
|
11968
|
-
family: "inet",
|
|
11969
|
-
host: local.host === "0.0.0.0" ? "127.0.0.1" : local.host,
|
|
11970
|
-
port: local.port
|
|
11971
|
-
};
|
|
11972
|
-
const delivered = this.net.deliverDgram(target.port, { bytes: bytes.slice(), from });
|
|
11973
|
-
if (!delivered && this.peer && sameAddr(this.peer, target)) {
|
|
11974
|
-
this.pending = "ECONNREFUSED";
|
|
11975
|
-
this.changes.wake();
|
|
11945
|
+
readInto(at, out) {
|
|
11946
|
+
const end = Math.min(this.length, at + out.length);
|
|
11947
|
+
for (let pos = at; pos < end; ) {
|
|
11948
|
+
const page = Math.floor(pos / PAGE);
|
|
11949
|
+
const from = pos - page * PAGE;
|
|
11950
|
+
const n = Math.min(PAGE - from, end - pos);
|
|
11951
|
+
const bytes = this.pages.get(page);
|
|
11952
|
+
if (bytes) out.set(bytes.subarray(from, from + n), pos - at);
|
|
11953
|
+
else out.fill(0, pos - at, pos - at + n);
|
|
11954
|
+
pos += n;
|
|
11976
11955
|
}
|
|
11977
|
-
return
|
|
11956
|
+
return Math.max(0, end - at);
|
|
11978
11957
|
}
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
const
|
|
11985
|
-
|
|
11986
|
-
|
|
11987
|
-
|
|
11988
|
-
|
|
11989
|
-
|
|
11990
|
-
|
|
11958
|
+
write(at, bytes) {
|
|
11959
|
+
for (let done4 = 0; done4 < bytes.length; ) {
|
|
11960
|
+
const pos = at + done4;
|
|
11961
|
+
const page = Math.floor(pos / PAGE);
|
|
11962
|
+
const from = pos - page * PAGE;
|
|
11963
|
+
const n = Math.min(PAGE - from, bytes.length - done4);
|
|
11964
|
+
let target = this.pages.get(page);
|
|
11965
|
+
if (!target) {
|
|
11966
|
+
target = this.take(0);
|
|
11967
|
+
this.pages.set(page, target);
|
|
11968
|
+
}
|
|
11969
|
+
target.set(bytes.subarray(done4, done4 + n), from);
|
|
11970
|
+
this.dirty.add(page);
|
|
11971
|
+
done4 += n;
|
|
11991
11972
|
}
|
|
11992
|
-
|
|
11993
|
-
}
|
|
11994
|
-
uplinkSocket(uplink, family) {
|
|
11995
|
-
const known = this.uplinks.get(family);
|
|
11996
|
-
if (known !== void 0) return known;
|
|
11997
|
-
const opening2 = Promise.resolve().then(() => {
|
|
11998
|
-
if (!uplink.udp) throw new KernelError("ENETUNREACH");
|
|
11999
|
-
return uplink.udp({ family, signal: this.stop.signal });
|
|
12000
|
-
});
|
|
12001
|
-
this.uplinks.set(family, opening2);
|
|
12002
|
-
opening2.then(
|
|
12003
|
-
(socket) => {
|
|
12004
|
-
if (this.closed) {
|
|
12005
|
-
socket.close();
|
|
12006
|
-
return;
|
|
12007
|
-
}
|
|
12008
|
-
void this.pump(socket, family);
|
|
12009
|
-
},
|
|
12010
|
-
() => this.uplinks.delete(family)
|
|
12011
|
-
);
|
|
12012
|
-
return opening2;
|
|
11973
|
+
this.length = Math.max(this.length, at + bytes.length);
|
|
12013
11974
|
}
|
|
12014
|
-
|
|
12015
|
-
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
11975
|
+
truncate(size) {
|
|
11976
|
+
if (size < this.stored) {
|
|
11977
|
+
this.stored = size;
|
|
11978
|
+
this.shrink = Math.min(this.shrink ?? size, size);
|
|
11979
|
+
}
|
|
11980
|
+
if (size < this.length) {
|
|
11981
|
+
const edge = Math.floor(size / PAGE);
|
|
11982
|
+
for (const page of [...this.pages.keys()]) {
|
|
11983
|
+
if (page > edge || page === edge && size === edge * PAGE) this.drop(page);
|
|
12021
11984
|
}
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
socket.close();
|
|
12026
|
-
}
|
|
12027
|
-
unreachable(error, from) {
|
|
12028
|
-
if (!this.peer || !sameAddr(this.peer, from)) return;
|
|
12029
|
-
this.pending = UNREACHABLE.find((errno2) => errno2 === error) ?? "EHOSTUNREACH";
|
|
12030
|
-
this.changes.wake();
|
|
12031
|
-
}
|
|
12032
|
-
deliver(datagram2) {
|
|
12033
|
-
if (this.closed) return false;
|
|
12034
|
-
if (this.peer && !sameAddr(this.peer, datagram2.from)) return true;
|
|
12035
|
-
const full = this.queue.length >= DGRAM_QUEUE_COUNT || this.queued + datagram2.bytes.length > DGRAM_QUEUE_BYTES;
|
|
12036
|
-
if (full) return true;
|
|
12037
|
-
this.queue.push(datagram2);
|
|
12038
|
-
this.queued += datagram2.bytes.length;
|
|
12039
|
-
this.changes.wake();
|
|
12040
|
-
return true;
|
|
12041
|
-
}
|
|
12042
|
-
async receive(max, peek, signal) {
|
|
12043
|
-
for (; ; ) {
|
|
12044
|
-
const pending = this.takeError();
|
|
12045
|
-
if (pending) throw new KernelError(pending);
|
|
12046
|
-
if (this.closed) throw new KernelError("EBADF");
|
|
12047
|
-
const next3 = this.queue[0];
|
|
12048
|
-
if (next3) {
|
|
12049
|
-
if (!peek) {
|
|
12050
|
-
this.queue.shift();
|
|
12051
|
-
this.queued -= next3.bytes.length;
|
|
12052
|
-
this.changes.wake();
|
|
12053
|
-
}
|
|
12054
|
-
const size = Math.max(0, max);
|
|
12055
|
-
return {
|
|
12056
|
-
bytes: next3.bytes.slice(0, size),
|
|
12057
|
-
from: next3.from,
|
|
12058
|
-
truncated: next3.bytes.length > size
|
|
12059
|
-
};
|
|
12060
|
-
}
|
|
12061
|
-
await this.changes.wait(signal);
|
|
12062
|
-
}
|
|
12063
|
-
}
|
|
12064
|
-
async read(max, signal) {
|
|
12065
|
-
return (await this.receive(max, false, signal)).bytes;
|
|
12066
|
-
}
|
|
12067
|
-
async peek(max, signal) {
|
|
12068
|
-
return (await this.receive(max, true, signal)).bytes;
|
|
12069
|
-
}
|
|
12070
|
-
write(bytes) {
|
|
12071
|
-
return this.send(bytes);
|
|
12072
|
-
}
|
|
12073
|
-
poll() {
|
|
12074
|
-
return {
|
|
12075
|
-
readable: this.queue.length > 0 || this.pending !== void 0 || this.closed,
|
|
12076
|
-
writable: this.sending < DGRAM_SEND_ROOM,
|
|
12077
|
-
hangup: this.closed,
|
|
12078
|
-
...this.pending !== void 0 ? { error: true } : {}
|
|
12079
|
-
};
|
|
12080
|
-
}
|
|
12081
|
-
changed(signal) {
|
|
12082
|
-
return this.changes.wait(signal);
|
|
12083
|
-
}
|
|
12084
|
-
shutdown(how) {
|
|
12085
|
-
if (!this.peer) throw new KernelError("ENOTCONN");
|
|
12086
|
-
if (how < 0 || how > 2) throw new KernelError("EINVAL");
|
|
12087
|
-
}
|
|
12088
|
-
getOption(level, name2) {
|
|
12089
|
-
if (level === SOL_SOCKET2) {
|
|
12090
|
-
switch (name2) {
|
|
12091
|
-
case SO_TYPE2:
|
|
12092
|
-
return SOCK_DGRAM;
|
|
12093
|
-
case SO_ERROR2: {
|
|
12094
|
-
const pending = this.takeError();
|
|
12095
|
-
return pending ? wasiErrno(pending) : 0;
|
|
12096
|
-
}
|
|
12097
|
-
case SO_DOMAIN2:
|
|
12098
|
-
return AF_INET2;
|
|
12099
|
-
case SO_BROADCAST:
|
|
12100
|
-
return 0;
|
|
12101
|
-
case SO_SNDBUF2:
|
|
12102
|
-
return this.options.get(`${level}:${name2}`) ?? DGRAM_SEND_ROOM;
|
|
12103
|
-
case SO_RCVBUF2:
|
|
12104
|
-
return this.options.get(`${level}:${name2}`) ?? DGRAM_QUEUE_BYTES;
|
|
12105
|
-
}
|
|
12106
|
-
}
|
|
12107
|
-
if (level === IPPROTO_IP && name2 >= IP_MULTICAST_FIRST && name2 <= IP_MULTICAST_LAST) {
|
|
12108
|
-
throw new KernelError("ENOPROTOOPT");
|
|
12109
|
-
}
|
|
12110
|
-
return this.options.get(`${level}:${name2}`) ?? 0;
|
|
12111
|
-
}
|
|
12112
|
-
setOption(level, name2, value2) {
|
|
12113
|
-
if (level === SOL_SOCKET2 && name2 === SO_BROADCAST && value2 !== 0) {
|
|
12114
|
-
throw new KernelError("EOPNOTSUPP");
|
|
12115
|
-
}
|
|
12116
|
-
if (level === IPPROTO_IP && name2 >= IP_MULTICAST_FIRST && name2 <= IP_MULTICAST_LAST) {
|
|
12117
|
-
throw new KernelError("ENOPROTOOPT");
|
|
12118
|
-
}
|
|
12119
|
-
this.options.set(`${level}:${name2}`, value2);
|
|
12120
|
-
}
|
|
12121
|
-
close() {
|
|
12122
|
-
if (this.closed) return;
|
|
12123
|
-
this.closed = true;
|
|
12124
|
-
this.stop.abort();
|
|
12125
|
-
for (const opening2 of this.uplinks.values()) {
|
|
12126
|
-
opening2.then(
|
|
12127
|
-
(socket) => socket.close(),
|
|
12128
|
-
() => void 0
|
|
12129
|
-
);
|
|
12130
|
-
}
|
|
12131
|
-
this.uplinks.clear();
|
|
12132
|
-
if (this.local) this.net.releaseDgram(this.local, this);
|
|
12133
|
-
this.queue.length = 0;
|
|
12134
|
-
this.queued = 0;
|
|
12135
|
-
this.changes.wake();
|
|
12136
|
-
}
|
|
12137
|
-
};
|
|
12138
|
-
|
|
12139
|
-
// src/fs/pages.ts
|
|
12140
|
-
var PAGE = 64 * 1024;
|
|
12141
|
-
var READAHEAD = 1024 * 1024;
|
|
12142
|
-
var CLEAN_LIMIT = 4 * 1024 * 1024;
|
|
12143
|
-
var WRITEBACK = 8 * 1024 * 1024;
|
|
12144
|
-
var RUN = 1024 * 1024;
|
|
12145
|
-
var Pages = class {
|
|
12146
|
-
length;
|
|
12147
|
-
stored;
|
|
12148
|
-
shrink;
|
|
12149
|
-
pages = /* @__PURE__ */ new Map();
|
|
12150
|
-
dirty = /* @__PURE__ */ new Set();
|
|
12151
|
-
free = [];
|
|
12152
|
-
pinned = false;
|
|
12153
|
-
constructor(size) {
|
|
12154
|
-
this.length = size;
|
|
12155
|
-
this.stored = size;
|
|
12156
|
-
}
|
|
12157
|
-
get dirtyBytes() {
|
|
12158
|
-
return this.dirty.size * PAGE;
|
|
12159
|
-
}
|
|
12160
|
-
get changed() {
|
|
12161
|
-
return this.dirty.size > 0 || this.shrink !== void 0 || this.length !== this.stored;
|
|
12162
|
-
}
|
|
12163
|
-
missing(at, length2) {
|
|
12164
|
-
this.evict();
|
|
12165
|
-
const end = Math.min(this.stored, at + length2, this.length);
|
|
12166
|
-
const runs = [];
|
|
12167
|
-
for (let page = Math.floor(at / PAGE); page * PAGE < end; page++) {
|
|
12168
|
-
if (this.pages.has(page)) continue;
|
|
12169
|
-
const last2 = runs[runs.length - 1];
|
|
12170
|
-
if (last2 && last2[0] + last2[1] === page * PAGE) last2[1] += PAGE;
|
|
12171
|
-
else runs.push([page * PAGE, PAGE]);
|
|
12172
|
-
}
|
|
12173
|
-
const last = runs[runs.length - 1];
|
|
12174
|
-
if (last) last[1] = Math.max(last[1], Math.min(READAHEAD, this.stored - last[0]));
|
|
12175
|
-
return runs.map(([start2, n]) => [start2, Math.min(n, this.stored - start2)]);
|
|
12176
|
-
}
|
|
12177
|
-
partial(at, length2) {
|
|
12178
|
-
if (length2 === 0) return [];
|
|
12179
|
-
this.evict();
|
|
12180
|
-
const edges = /* @__PURE__ */ new Set([Math.floor(at / PAGE), Math.floor((at + length2 - 1) / PAGE)]);
|
|
12181
|
-
const runs = [];
|
|
12182
|
-
for (const page of edges) {
|
|
12183
|
-
const start2 = page * PAGE;
|
|
12184
|
-
const covered = at <= start2 && at + length2 >= start2 + PAGE;
|
|
12185
|
-
if (covered || this.pages.has(page) || start2 >= this.stored) continue;
|
|
12186
|
-
runs.push([start2, Math.min(PAGE, this.stored - start2)]);
|
|
12187
|
-
}
|
|
12188
|
-
return runs;
|
|
12189
|
-
}
|
|
12190
|
-
fill(start2, bytes) {
|
|
12191
|
-
for (let at = 0; at < bytes.length; at += PAGE) {
|
|
12192
|
-
const page = (start2 + at) / PAGE;
|
|
12193
|
-
if (this.pages.has(page)) continue;
|
|
12194
|
-
const part = bytes.subarray(at, Math.min(at + PAGE, bytes.length));
|
|
12195
|
-
const fresh2 = this.take(part.length);
|
|
12196
|
-
fresh2.set(part);
|
|
12197
|
-
this.pages.set(page, fresh2);
|
|
12198
|
-
}
|
|
12199
|
-
}
|
|
12200
|
-
read(at, length2) {
|
|
12201
|
-
const out = new Uint8Array(Math.max(0, Math.min(this.length, at + length2) - at));
|
|
12202
|
-
this.readInto(at, out);
|
|
12203
|
-
return out;
|
|
12204
|
-
}
|
|
12205
|
-
readInto(at, out) {
|
|
12206
|
-
const end = Math.min(this.length, at + out.length);
|
|
12207
|
-
for (let pos = at; pos < end; ) {
|
|
12208
|
-
const page = Math.floor(pos / PAGE);
|
|
12209
|
-
const from = pos - page * PAGE;
|
|
12210
|
-
const n = Math.min(PAGE - from, end - pos);
|
|
12211
|
-
const bytes = this.pages.get(page);
|
|
12212
|
-
if (bytes) out.set(bytes.subarray(from, from + n), pos - at);
|
|
12213
|
-
else out.fill(0, pos - at, pos - at + n);
|
|
12214
|
-
pos += n;
|
|
12215
|
-
}
|
|
12216
|
-
return Math.max(0, end - at);
|
|
12217
|
-
}
|
|
12218
|
-
write(at, bytes) {
|
|
12219
|
-
for (let done4 = 0; done4 < bytes.length; ) {
|
|
12220
|
-
const pos = at + done4;
|
|
12221
|
-
const page = Math.floor(pos / PAGE);
|
|
12222
|
-
const from = pos - page * PAGE;
|
|
12223
|
-
const n = Math.min(PAGE - from, bytes.length - done4);
|
|
12224
|
-
let target = this.pages.get(page);
|
|
12225
|
-
if (!target) {
|
|
12226
|
-
target = this.take(0);
|
|
12227
|
-
this.pages.set(page, target);
|
|
12228
|
-
}
|
|
12229
|
-
target.set(bytes.subarray(done4, done4 + n), from);
|
|
12230
|
-
this.dirty.add(page);
|
|
12231
|
-
done4 += n;
|
|
12232
|
-
}
|
|
12233
|
-
this.length = Math.max(this.length, at + bytes.length);
|
|
12234
|
-
}
|
|
12235
|
-
truncate(size) {
|
|
12236
|
-
if (size < this.stored) {
|
|
12237
|
-
this.stored = size;
|
|
12238
|
-
this.shrink = Math.min(this.shrink ?? size, size);
|
|
12239
|
-
}
|
|
12240
|
-
if (size < this.length) {
|
|
12241
|
-
const edge = Math.floor(size / PAGE);
|
|
12242
|
-
for (const page of [...this.pages.keys()]) {
|
|
12243
|
-
if (page > edge || page === edge && size === edge * PAGE) this.drop(page);
|
|
12244
|
-
}
|
|
12245
|
-
this.pages.get(edge)?.fill(0, size - edge * PAGE);
|
|
12246
|
-
}
|
|
12247
|
-
this.length = size;
|
|
11985
|
+
this.pages.get(edge)?.fill(0, size - edge * PAGE);
|
|
11986
|
+
}
|
|
11987
|
+
this.length = size;
|
|
12248
11988
|
}
|
|
12249
11989
|
plan() {
|
|
12250
11990
|
const runs = [];
|
|
@@ -14867,6 +14607,20 @@ var HttpHandles = class {
|
|
|
14867
14607
|
}
|
|
14868
14608
|
};
|
|
14869
14609
|
|
|
14610
|
+
// src/kernel/net/uplink.ts
|
|
14611
|
+
function carriesUdp(uplink) {
|
|
14612
|
+
return uplink.traits.udp === true && typeof uplink.udp === "function";
|
|
14613
|
+
}
|
|
14614
|
+
function answerOf(result) {
|
|
14615
|
+
const answer = Array.isArray(result) ? { addresses: result } : result;
|
|
14616
|
+
const addresses = Array.isArray(answer?.addresses) ? answer.addresses.filter((a) => typeof a === "string") : [];
|
|
14617
|
+
return {
|
|
14618
|
+
addresses,
|
|
14619
|
+
...typeof answer?.ttl === "number" && answer.ttl >= 0 ? { ttl: answer.ttl } : {}
|
|
14620
|
+
};
|
|
14621
|
+
}
|
|
14622
|
+
var NEVER = new Routes(true);
|
|
14623
|
+
|
|
14870
14624
|
// src/kernel/net/resolver.ts
|
|
14871
14625
|
var RESOLVE_TTL_MAX = 60;
|
|
14872
14626
|
var RESOLVE_TIMEOUT_MS = 1e4;
|
|
@@ -15852,63 +15606,476 @@ function socketNames(deps) {
|
|
|
15852
15606
|
};
|
|
15853
15607
|
}
|
|
15854
15608
|
|
|
15855
|
-
// src/kernel/
|
|
15856
|
-
|
|
15857
|
-
|
|
15858
|
-
|
|
15859
|
-
|
|
15860
|
-
|
|
15861
|
-
|
|
15862
|
-
|
|
15863
|
-
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
|
|
15867
|
-
|
|
15868
|
-
|
|
15869
|
-
var
|
|
15870
|
-
|
|
15871
|
-
|
|
15872
|
-
|
|
15873
|
-
|
|
15874
|
-
|
|
15875
|
-
|
|
15876
|
-
|
|
15877
|
-
|
|
15878
|
-
"
|
|
15879
|
-
|
|
15609
|
+
// src/kernel/dgram.ts
|
|
15610
|
+
var DGRAM_QUEUE_BYTES = 256 * 1024;
|
|
15611
|
+
var DGRAM_QUEUE_COUNT = 512;
|
|
15612
|
+
var DGRAM_SEND_ROOM = 256 * 1024;
|
|
15613
|
+
var MAX_DATAGRAM_V4 = 65507;
|
|
15614
|
+
var MAX_DATAGRAM_V6 = 65527;
|
|
15615
|
+
var SOL_SOCKET2 = 1;
|
|
15616
|
+
var IPPROTO_IP = 0;
|
|
15617
|
+
var SO_TYPE2 = 3;
|
|
15618
|
+
var SO_ERROR2 = 4;
|
|
15619
|
+
var SO_BROADCAST = 6;
|
|
15620
|
+
var SO_SNDBUF2 = 7;
|
|
15621
|
+
var SO_RCVBUF2 = 8;
|
|
15622
|
+
var SO_DOMAIN2 = 39;
|
|
15623
|
+
var SOCK_DGRAM = 2;
|
|
15624
|
+
var AF_INET2 = 2;
|
|
15625
|
+
var IP_MULTICAST_FIRST = 32;
|
|
15626
|
+
var IP_MULTICAST_LAST = 36;
|
|
15627
|
+
var SEND_ERRORS = ["ENETUNREACH", "EHOSTUNREACH", "EACCES", "EMSGSIZE"];
|
|
15628
|
+
var UNREACHABLE = ["EACCES", "ENETUNREACH", "EHOSTUNREACH"];
|
|
15629
|
+
function sendError(e) {
|
|
15630
|
+
if (e instanceof KernelError) return e;
|
|
15631
|
+
const code = e?.code;
|
|
15632
|
+
return new KernelError(SEND_ERRORS.find((errno2) => errno2 === code) ?? "EHOSTUNREACH");
|
|
15633
|
+
}
|
|
15634
|
+
function sameAddr(a, b) {
|
|
15635
|
+
return a.port === b.port && canonicalHost(a.host) === canonicalHost(b.host);
|
|
15636
|
+
}
|
|
15637
|
+
function familyOf(host) {
|
|
15638
|
+
return host.includes(":") ? 6 : 4;
|
|
15639
|
+
}
|
|
15640
|
+
var KernelDgram = class {
|
|
15641
|
+
local;
|
|
15642
|
+
peer;
|
|
15643
|
+
net;
|
|
15644
|
+
queue = [];
|
|
15645
|
+
queued = 0;
|
|
15646
|
+
pending;
|
|
15647
|
+
closed = false;
|
|
15648
|
+
sending = 0;
|
|
15649
|
+
changes = new Changes();
|
|
15650
|
+
options = /* @__PURE__ */ new Map();
|
|
15651
|
+
uplinks = /* @__PURE__ */ new Map();
|
|
15652
|
+
stop = new AbortController();
|
|
15653
|
+
constructor(net) {
|
|
15654
|
+
this.net = net;
|
|
15655
|
+
}
|
|
15656
|
+
bind(addr) {
|
|
15657
|
+
if (this.local) throw new KernelError("EINVAL");
|
|
15658
|
+
this.local = this.net.bindDgram(this, addr);
|
|
15659
|
+
}
|
|
15660
|
+
bound() {
|
|
15661
|
+
this.local ??= this.net.bindDgram(this, { family: "inet", host: "0.0.0.0", port: 0 });
|
|
15662
|
+
return this.local;
|
|
15663
|
+
}
|
|
15664
|
+
connectTo(addr) {
|
|
15665
|
+
if (addr.family !== "inet") throw new KernelError("EAFNOSUPPORT");
|
|
15666
|
+
this.route(addr.host);
|
|
15667
|
+
this.bound();
|
|
15668
|
+
this.peer = { family: "inet", host: canonicalHost(addr.host), port: addr.port };
|
|
15669
|
+
this.pending = void 0;
|
|
15670
|
+
this.drain((d) => sameAddr(d.from, addr));
|
|
15671
|
+
}
|
|
15672
|
+
drain(keep2) {
|
|
15673
|
+
const kept = this.queue.filter(keep2);
|
|
15674
|
+
this.queue.splice(0, this.queue.length, ...kept);
|
|
15675
|
+
this.queued = kept.reduce((sum, d) => sum + d.bytes.length, 0);
|
|
15676
|
+
}
|
|
15677
|
+
route(host) {
|
|
15678
|
+
const where = this.net.destination(host);
|
|
15679
|
+
if (where === "loopback" || where === "uplink") return where;
|
|
15680
|
+
throw new KernelError("ENETUNREACH");
|
|
15681
|
+
}
|
|
15682
|
+
takeError() {
|
|
15683
|
+
const pending = this.pending;
|
|
15684
|
+
this.pending = void 0;
|
|
15685
|
+
return pending;
|
|
15686
|
+
}
|
|
15687
|
+
async send(bytes, to) {
|
|
15688
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
15689
|
+
const pending = this.takeError();
|
|
15690
|
+
if (pending) throw new KernelError(pending);
|
|
15691
|
+
const target = to ?? this.peer;
|
|
15692
|
+
if (!target) throw new KernelError("EDESTADDRREQ");
|
|
15693
|
+
if (target.family !== "inet") throw new KernelError("EAFNOSUPPORT");
|
|
15694
|
+
const max = familyOf(target.host) === 6 ? MAX_DATAGRAM_V6 : MAX_DATAGRAM_V4;
|
|
15695
|
+
if (bytes.length > max) throw new KernelError("EMSGSIZE");
|
|
15696
|
+
const where = this.route(target.host);
|
|
15697
|
+
const local = this.bound();
|
|
15698
|
+
if (where === "uplink") return this.sendUp(bytes, target);
|
|
15699
|
+
const from = {
|
|
15700
|
+
family: "inet",
|
|
15701
|
+
host: local.host === "0.0.0.0" ? "127.0.0.1" : local.host,
|
|
15702
|
+
port: local.port
|
|
15703
|
+
};
|
|
15704
|
+
const delivered = this.net.deliverDgram(target.port, { bytes: bytes.slice(), from });
|
|
15705
|
+
if (!delivered && this.peer && sameAddr(this.peer, target)) {
|
|
15706
|
+
this.pending = "ECONNREFUSED";
|
|
15707
|
+
this.changes.wake();
|
|
15708
|
+
}
|
|
15709
|
+
return bytes.length;
|
|
15710
|
+
}
|
|
15711
|
+
async sendUp(bytes, to) {
|
|
15712
|
+
const uplink = this.net.uplinkFor(to.host)?.uplink;
|
|
15713
|
+
if (!uplink || !carriesUdp(uplink)) throw new KernelError("ENETUNREACH");
|
|
15714
|
+
this.sending += bytes.length;
|
|
15715
|
+
try {
|
|
15716
|
+
const socket = await this.uplinkSocket(uplink, familyOf(to.host));
|
|
15717
|
+
await socket.send(bytes.slice(), to.host, to.port);
|
|
15718
|
+
} catch (e) {
|
|
15719
|
+
throw sendError(e);
|
|
15720
|
+
} finally {
|
|
15721
|
+
this.sending -= bytes.length;
|
|
15722
|
+
this.changes.wake();
|
|
15723
|
+
}
|
|
15724
|
+
return bytes.length;
|
|
15725
|
+
}
|
|
15726
|
+
uplinkSocket(uplink, family) {
|
|
15727
|
+
const known = this.uplinks.get(family);
|
|
15728
|
+
if (known !== void 0) return known;
|
|
15729
|
+
const opening2 = Promise.resolve().then(() => {
|
|
15730
|
+
if (!uplink.udp) throw new KernelError("ENETUNREACH");
|
|
15731
|
+
return uplink.udp({ family, signal: this.stop.signal });
|
|
15732
|
+
});
|
|
15733
|
+
this.uplinks.set(family, opening2);
|
|
15734
|
+
opening2.then(
|
|
15735
|
+
(socket) => {
|
|
15736
|
+
if (this.closed) {
|
|
15737
|
+
socket.close();
|
|
15738
|
+
return;
|
|
15739
|
+
}
|
|
15740
|
+
void this.pump(socket, family);
|
|
15741
|
+
},
|
|
15742
|
+
() => this.uplinks.delete(family)
|
|
15743
|
+
);
|
|
15744
|
+
return opening2;
|
|
15745
|
+
}
|
|
15746
|
+
async pump(socket, family) {
|
|
15747
|
+
const iterate = async () => {
|
|
15748
|
+
for await (const message3 of socket.messages) {
|
|
15749
|
+
if (this.closed) return;
|
|
15750
|
+
const from = { family: "inet", host: message3.host, port: message3.port };
|
|
15751
|
+
if ("bytes" in message3) this.deliver({ bytes: message3.bytes, from });
|
|
15752
|
+
else this.unreachable(message3.error, from);
|
|
15753
|
+
}
|
|
15754
|
+
};
|
|
15755
|
+
await iterate().catch(() => void 0);
|
|
15756
|
+
if (!this.closed) this.uplinks.delete(family);
|
|
15757
|
+
socket.close();
|
|
15758
|
+
}
|
|
15759
|
+
unreachable(error, from) {
|
|
15760
|
+
if (!this.peer || !sameAddr(this.peer, from)) return;
|
|
15761
|
+
this.pending = UNREACHABLE.find((errno2) => errno2 === error) ?? "EHOSTUNREACH";
|
|
15762
|
+
this.changes.wake();
|
|
15763
|
+
}
|
|
15764
|
+
deliver(datagram2) {
|
|
15765
|
+
if (this.closed) return false;
|
|
15766
|
+
if (this.peer && !sameAddr(this.peer, datagram2.from)) return true;
|
|
15767
|
+
const full = this.queue.length >= DGRAM_QUEUE_COUNT || this.queued + datagram2.bytes.length > DGRAM_QUEUE_BYTES;
|
|
15768
|
+
if (full) return true;
|
|
15769
|
+
this.queue.push(datagram2);
|
|
15770
|
+
this.queued += datagram2.bytes.length;
|
|
15771
|
+
this.changes.wake();
|
|
15772
|
+
return true;
|
|
15773
|
+
}
|
|
15774
|
+
async receive(max, peek, signal) {
|
|
15775
|
+
for (; ; ) {
|
|
15776
|
+
const pending = this.takeError();
|
|
15777
|
+
if (pending) throw new KernelError(pending);
|
|
15778
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
15779
|
+
const next3 = this.queue[0];
|
|
15780
|
+
if (next3) {
|
|
15781
|
+
if (!peek) {
|
|
15782
|
+
this.queue.shift();
|
|
15783
|
+
this.queued -= next3.bytes.length;
|
|
15784
|
+
this.changes.wake();
|
|
15785
|
+
}
|
|
15786
|
+
const size = Math.max(0, max);
|
|
15787
|
+
return {
|
|
15788
|
+
bytes: next3.bytes.slice(0, size),
|
|
15789
|
+
from: next3.from,
|
|
15790
|
+
truncated: next3.bytes.length > size
|
|
15791
|
+
};
|
|
15792
|
+
}
|
|
15793
|
+
await this.changes.wait(signal);
|
|
15794
|
+
}
|
|
15795
|
+
}
|
|
15796
|
+
async read(max, signal) {
|
|
15797
|
+
return (await this.receive(max, false, signal)).bytes;
|
|
15798
|
+
}
|
|
15799
|
+
async peek(max, signal) {
|
|
15800
|
+
return (await this.receive(max, true, signal)).bytes;
|
|
15801
|
+
}
|
|
15802
|
+
write(bytes) {
|
|
15803
|
+
return this.send(bytes);
|
|
15804
|
+
}
|
|
15805
|
+
poll() {
|
|
15806
|
+
return {
|
|
15807
|
+
readable: this.queue.length > 0 || this.pending !== void 0 || this.closed,
|
|
15808
|
+
writable: this.sending < DGRAM_SEND_ROOM,
|
|
15809
|
+
hangup: this.closed,
|
|
15810
|
+
...this.pending !== void 0 ? { error: true } : {}
|
|
15811
|
+
};
|
|
15812
|
+
}
|
|
15813
|
+
changed(signal) {
|
|
15814
|
+
return this.changes.wait(signal);
|
|
15815
|
+
}
|
|
15816
|
+
shutdown(how) {
|
|
15817
|
+
if (!this.peer) throw new KernelError("ENOTCONN");
|
|
15818
|
+
if (how < 0 || how > 2) throw new KernelError("EINVAL");
|
|
15819
|
+
}
|
|
15820
|
+
getOption(level, name2) {
|
|
15821
|
+
if (level === SOL_SOCKET2) {
|
|
15822
|
+
switch (name2) {
|
|
15823
|
+
case SO_TYPE2:
|
|
15824
|
+
return SOCK_DGRAM;
|
|
15825
|
+
case SO_ERROR2: {
|
|
15826
|
+
const pending = this.takeError();
|
|
15827
|
+
return pending ? wasiErrno(pending) : 0;
|
|
15828
|
+
}
|
|
15829
|
+
case SO_DOMAIN2:
|
|
15830
|
+
return AF_INET2;
|
|
15831
|
+
case SO_BROADCAST:
|
|
15832
|
+
return 0;
|
|
15833
|
+
case SO_SNDBUF2:
|
|
15834
|
+
return this.options.get(`${level}:${name2}`) ?? DGRAM_SEND_ROOM;
|
|
15835
|
+
case SO_RCVBUF2:
|
|
15836
|
+
return this.options.get(`${level}:${name2}`) ?? DGRAM_QUEUE_BYTES;
|
|
15837
|
+
}
|
|
15838
|
+
}
|
|
15839
|
+
if (level === IPPROTO_IP && name2 >= IP_MULTICAST_FIRST && name2 <= IP_MULTICAST_LAST) {
|
|
15840
|
+
throw new KernelError("ENOPROTOOPT");
|
|
15841
|
+
}
|
|
15842
|
+
return this.options.get(`${level}:${name2}`) ?? 0;
|
|
15843
|
+
}
|
|
15844
|
+
setOption(level, name2, value2) {
|
|
15845
|
+
if (level === SOL_SOCKET2 && name2 === SO_BROADCAST && value2 !== 0) {
|
|
15846
|
+
throw new KernelError("EOPNOTSUPP");
|
|
15847
|
+
}
|
|
15848
|
+
if (level === IPPROTO_IP && name2 >= IP_MULTICAST_FIRST && name2 <= IP_MULTICAST_LAST) {
|
|
15849
|
+
throw new KernelError("ENOPROTOOPT");
|
|
15850
|
+
}
|
|
15851
|
+
this.options.set(`${level}:${name2}`, value2);
|
|
15852
|
+
}
|
|
15853
|
+
close() {
|
|
15854
|
+
if (this.closed) return;
|
|
15855
|
+
this.closed = true;
|
|
15856
|
+
this.stop.abort();
|
|
15857
|
+
for (const opening2 of this.uplinks.values()) {
|
|
15858
|
+
opening2.then(
|
|
15859
|
+
(socket) => socket.close(),
|
|
15860
|
+
() => void 0
|
|
15861
|
+
);
|
|
15862
|
+
}
|
|
15863
|
+
this.uplinks.clear();
|
|
15864
|
+
if (this.local) this.net.releaseDgram(this.local, this);
|
|
15865
|
+
this.queue.length = 0;
|
|
15866
|
+
this.queued = 0;
|
|
15867
|
+
this.changes.wake();
|
|
15868
|
+
}
|
|
15869
|
+
};
|
|
15870
|
+
|
|
15871
|
+
// src/kernel/net/datagram-wire.ts
|
|
15872
|
+
function encodeReceived(got) {
|
|
15873
|
+
const host = new TextEncoder().encode(got.host);
|
|
15874
|
+
const out = new Uint8Array(4 + host.length + got.bytes.length);
|
|
15875
|
+
const view2 = new DataView(out.buffer);
|
|
15876
|
+
view2.setUint8(0, (got.truncated ? 1 : 0) | (got.unix ? 2 : 0));
|
|
15877
|
+
view2.setUint16(1, got.port);
|
|
15878
|
+
view2.setUint8(3, host.length);
|
|
15879
|
+
out.set(host, 4);
|
|
15880
|
+
out.set(got.bytes, 4 + host.length);
|
|
15881
|
+
return out;
|
|
15882
|
+
}
|
|
15883
|
+
|
|
15884
|
+
// src/kernel/unix-dgram.ts
|
|
15885
|
+
var SOL_SOCKET3 = 1;
|
|
15886
|
+
var SO_TYPE3 = 3;
|
|
15887
|
+
var SO_ERROR3 = 4;
|
|
15888
|
+
var SO_SNDBUF3 = 7;
|
|
15889
|
+
var SO_RCVBUF3 = 8;
|
|
15890
|
+
var SO_DOMAIN3 = 39;
|
|
15891
|
+
var SOCK_DGRAM2 = 2;
|
|
15892
|
+
var AF_UNIX2 = 1;
|
|
15893
|
+
var UNNAMED = { family: "unix", path: "" };
|
|
15894
|
+
var UnixDgram = class _UnixDgram {
|
|
15895
|
+
local;
|
|
15896
|
+
peer;
|
|
15897
|
+
key;
|
|
15898
|
+
peerCred;
|
|
15899
|
+
target;
|
|
15900
|
+
net;
|
|
15901
|
+
queue = [];
|
|
15902
|
+
queued = 0;
|
|
15903
|
+
closed = false;
|
|
15904
|
+
changes = new Changes();
|
|
15905
|
+
options = /* @__PURE__ */ new Map();
|
|
15906
|
+
constructor(net) {
|
|
15907
|
+
this.net = net;
|
|
15908
|
+
}
|
|
15909
|
+
static pair(net, cred) {
|
|
15910
|
+
const a = new _UnixDgram(net);
|
|
15911
|
+
const b = new _UnixDgram(net);
|
|
15912
|
+
a.target = b;
|
|
15913
|
+
b.target = a;
|
|
15914
|
+
a.peer = b.peer = UNNAMED;
|
|
15915
|
+
a.peerCred = b.peerCred = cred;
|
|
15916
|
+
return [a, b];
|
|
15917
|
+
}
|
|
15918
|
+
bind(addr, key) {
|
|
15919
|
+
if (addr.family !== "unix") throw new KernelError("EINVAL");
|
|
15920
|
+
if (this.local) throw new KernelError("EINVAL");
|
|
15921
|
+
if (addr.path === "") throw new KernelError("EINVAL");
|
|
15922
|
+
this.net.bindUnixDgram(this, key);
|
|
15923
|
+
this.local = { family: "unix", path: addr.path };
|
|
15924
|
+
this.key = key;
|
|
15925
|
+
}
|
|
15926
|
+
connectTo(addr, target) {
|
|
15927
|
+
this.target = target;
|
|
15928
|
+
this.peer = addr;
|
|
15929
|
+
const kept = this.queue.filter((d) => d.sender === target);
|
|
15930
|
+
this.queue.splice(0, this.queue.length, ...kept);
|
|
15931
|
+
this.queued = kept.reduce((sum, d) => sum + d.bytes.length, 0);
|
|
15932
|
+
}
|
|
15933
|
+
destination() {
|
|
15934
|
+
if (!this.target) throw new KernelError("EDESTADDRREQ");
|
|
15935
|
+
return this.target;
|
|
15936
|
+
}
|
|
15937
|
+
room(bytes) {
|
|
15938
|
+
return this.closed || this.queue.length < DGRAM_QUEUE_COUNT && this.queued + bytes <= DGRAM_QUEUE_BYTES;
|
|
15939
|
+
}
|
|
15940
|
+
async send(bytes, to, nonblock, signal) {
|
|
15941
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
15942
|
+
if (bytes.length > DGRAM_QUEUE_BYTES) throw new KernelError("EMSGSIZE");
|
|
15943
|
+
if (to.target && to.target !== this) throw new KernelError("EPERM");
|
|
15944
|
+
while (!to.room(bytes.length)) {
|
|
15945
|
+
if (nonblock) throw new KernelError("EAGAIN");
|
|
15946
|
+
await to.changed(signal);
|
|
15947
|
+
}
|
|
15948
|
+
if (to.closed) throw new KernelError("ECONNREFUSED");
|
|
15949
|
+
to.queue.push({ bytes: bytes.slice(), from: this.local ?? UNNAMED, sender: this });
|
|
15950
|
+
to.queued += bytes.length;
|
|
15951
|
+
to.changes.wake();
|
|
15952
|
+
return bytes.length;
|
|
15953
|
+
}
|
|
15954
|
+
async receive(max, peek, signal) {
|
|
15955
|
+
for (; ; ) {
|
|
15956
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
15957
|
+
const next3 = this.queue[0];
|
|
15958
|
+
if (next3) {
|
|
15959
|
+
if (!peek) {
|
|
15960
|
+
this.queue.shift();
|
|
15961
|
+
this.queued -= next3.bytes.length;
|
|
15962
|
+
this.changes.wake();
|
|
15963
|
+
}
|
|
15964
|
+
const size = Math.max(0, max);
|
|
15965
|
+
return {
|
|
15966
|
+
bytes: next3.bytes.slice(0, size),
|
|
15967
|
+
from: next3.from,
|
|
15968
|
+
truncated: next3.bytes.length > size
|
|
15969
|
+
};
|
|
15970
|
+
}
|
|
15971
|
+
await this.changes.wait(signal);
|
|
15972
|
+
}
|
|
15973
|
+
}
|
|
15974
|
+
async read(max, signal) {
|
|
15975
|
+
return (await this.receive(max, false, signal)).bytes;
|
|
15976
|
+
}
|
|
15977
|
+
async peek(max, signal) {
|
|
15978
|
+
return (await this.receive(max, true, signal)).bytes;
|
|
15979
|
+
}
|
|
15980
|
+
write(bytes, signal) {
|
|
15981
|
+
return this.send(bytes, this.destination(), false, signal);
|
|
15982
|
+
}
|
|
15983
|
+
poll() {
|
|
15984
|
+
const target = this.target;
|
|
15985
|
+
return {
|
|
15986
|
+
readable: this.queue.length > 0 || this.closed,
|
|
15987
|
+
writable: !target || target.room(1),
|
|
15988
|
+
hangup: this.closed
|
|
15989
|
+
};
|
|
15990
|
+
}
|
|
15991
|
+
changed(signal) {
|
|
15992
|
+
return this.changes.wait(signal);
|
|
15993
|
+
}
|
|
15994
|
+
shutdown(how) {
|
|
15995
|
+
if (!this.peer) throw new KernelError("ENOTCONN");
|
|
15996
|
+
if (how < 0 || how > 2) throw new KernelError("EINVAL");
|
|
15997
|
+
}
|
|
15998
|
+
getOption(level, name2) {
|
|
15999
|
+
if (level === SOL_SOCKET3) {
|
|
16000
|
+
switch (name2) {
|
|
16001
|
+
case SO_TYPE3:
|
|
16002
|
+
return SOCK_DGRAM2;
|
|
16003
|
+
case SO_ERROR3:
|
|
16004
|
+
return 0;
|
|
16005
|
+
case SO_DOMAIN3:
|
|
16006
|
+
return AF_UNIX2;
|
|
16007
|
+
case SO_SNDBUF3:
|
|
16008
|
+
case SO_RCVBUF3:
|
|
16009
|
+
return this.options.get(`${level}:${name2}`) ?? DGRAM_QUEUE_BYTES;
|
|
16010
|
+
}
|
|
16011
|
+
}
|
|
16012
|
+
return this.options.get(`${level}:${name2}`) ?? 0;
|
|
16013
|
+
}
|
|
16014
|
+
setOption(level, name2, value2) {
|
|
16015
|
+
this.options.set(`${level}:${name2}`, value2);
|
|
16016
|
+
}
|
|
16017
|
+
close() {
|
|
16018
|
+
if (this.closed) return;
|
|
16019
|
+
this.closed = true;
|
|
16020
|
+
if (this.key !== void 0) this.net.releaseUnixDgram(this.key, this);
|
|
16021
|
+
this.queue.length = 0;
|
|
16022
|
+
this.queued = 0;
|
|
16023
|
+
this.changes.wake();
|
|
16024
|
+
}
|
|
16025
|
+
};
|
|
16026
|
+
function isDatagram(file) {
|
|
16027
|
+
return file instanceof KernelDgram || file instanceof UnixDgram;
|
|
16028
|
+
}
|
|
16029
|
+
|
|
16030
|
+
// src/kernel/socket-syscalls.ts
|
|
16031
|
+
var SOCKET_OPS = [
|
|
16032
|
+
"sock-open",
|
|
16033
|
+
"sock-pair",
|
|
16034
|
+
"sock-bind",
|
|
16035
|
+
"sock-listen",
|
|
16036
|
+
"sock-accept",
|
|
16037
|
+
"sock-connect",
|
|
16038
|
+
"sock-shutdown",
|
|
16039
|
+
"sock-name",
|
|
16040
|
+
"sock-getopt",
|
|
16041
|
+
"sock-setopt",
|
|
15880
16042
|
"sock-resolve",
|
|
15881
16043
|
"sock-sendto",
|
|
15882
16044
|
"sock-recvfrom"
|
|
15883
16045
|
];
|
|
15884
16046
|
function socketAt(fds, fd) {
|
|
15885
16047
|
const file = anySocketAt(fds, fd);
|
|
15886
|
-
if (file instanceof
|
|
16048
|
+
if (!(file instanceof KernelSocket)) throw new KernelError("EOPNOTSUPP");
|
|
15887
16049
|
return file;
|
|
15888
16050
|
}
|
|
15889
16051
|
function anySocketAt(fds, fd) {
|
|
15890
16052
|
const file = fds.get(fd).file;
|
|
15891
|
-
if (!(file instanceof KernelSocket) && !(file instanceof KernelDgram)) {
|
|
16053
|
+
if (!(file instanceof KernelSocket) && !(file instanceof KernelDgram) && !(file instanceof UnixDgram)) {
|
|
15892
16054
|
throw new KernelError("ENOTSOCK");
|
|
15893
16055
|
}
|
|
15894
16056
|
return file;
|
|
15895
16057
|
}
|
|
15896
16058
|
function dgramAt(fds, fd) {
|
|
15897
16059
|
const file = anySocketAt(fds, fd);
|
|
15898
|
-
if (
|
|
16060
|
+
if (file instanceof KernelSocket) throw new KernelError("EOPNOTSUPP");
|
|
15899
16061
|
return file;
|
|
15900
16062
|
}
|
|
16063
|
+
async function unixTarget(proc, addr) {
|
|
16064
|
+
if (addr.family !== "unix") throw new KernelError("EAFNOSUPPORT");
|
|
16065
|
+
const path = filePath(addr);
|
|
16066
|
+
const name2 = path !== void 0 ? await proc.names?.find(path) : void 0;
|
|
16067
|
+
return proc.net.unixDgramAt(keyOf(path !== void 0 ? { family: "unix", path } : addr, name2));
|
|
16068
|
+
}
|
|
15901
16069
|
var ok3 = (json5) => json5 === void 0 ? { ok: true, kind: "void" } : { ok: true, kind: "json", json: json5 };
|
|
15902
16070
|
async function socketSyscall(req, proc) {
|
|
15903
16071
|
const { fds, net } = proc;
|
|
15904
16072
|
switch (req.op) {
|
|
15905
16073
|
case "sock-open": {
|
|
15906
|
-
|
|
15907
|
-
const file = req.type === "dgram" ? new KernelDgram(net) : net.socket(req.domain);
|
|
16074
|
+
const file = req.type !== "dgram" ? net.socket(req.domain) : req.domain === "unix" ? new UnixDgram(net) : new KernelDgram(net);
|
|
15908
16075
|
return ok3(fds.install(new OpenFile(file), 3));
|
|
15909
16076
|
}
|
|
15910
16077
|
case "sock-pair": {
|
|
15911
|
-
const [a, b] = KernelSocket.pair(net, req.domain, proc.cred?.());
|
|
16078
|
+
const [a, b] = req.type === "dgram" && req.domain === "unix" ? UnixDgram.pair(net, proc.cred?.()) : KernelSocket.pair(net, req.domain, proc.cred?.());
|
|
15912
16079
|
const first = fds.install(new OpenFile(a), 3);
|
|
15913
16080
|
try {
|
|
15914
16081
|
return ok3([first, fds.install(new OpenFile(b), 3)]);
|
|
@@ -15934,7 +16101,7 @@ async function socketSyscall(req, proc) {
|
|
|
15934
16101
|
const socket = anySocketAt(fds, req.fd);
|
|
15935
16102
|
const addr = req.peer ? socket.peer : socket.local;
|
|
15936
16103
|
if (req.peer && !addr) throw new KernelError("ENOTCONN");
|
|
15937
|
-
return ok3(addr ?? unnamed(socket instanceof
|
|
16104
|
+
return ok3(addr ?? unnamed(socket instanceof KernelSocket ? socket.domain : domainOf(socket)));
|
|
15938
16105
|
}
|
|
15939
16106
|
case "sock-getopt":
|
|
15940
16107
|
return ok3(anySocketAt(fds, req.fd).getOption(req.level, req.name));
|
|
@@ -15956,6 +16123,10 @@ async function connect(req, proc) {
|
|
|
15956
16123
|
target.connectTo(req.addr);
|
|
15957
16124
|
return ok3();
|
|
15958
16125
|
}
|
|
16126
|
+
if (target instanceof UnixDgram) {
|
|
16127
|
+
target.connectTo(req.addr, await unixTarget(proc, req.addr));
|
|
16128
|
+
return ok3();
|
|
16129
|
+
}
|
|
15959
16130
|
const path = filePath(req.addr);
|
|
15960
16131
|
const name2 = path !== void 0 ? await proc.names?.find(path) : void 0;
|
|
15961
16132
|
const stamp = proc.net.facadeAt(req.addr) && await proc.stamp?.();
|
|
@@ -15967,8 +16138,23 @@ async function connect(req, proc) {
|
|
|
15967
16138
|
if (dialing !== void 0) await interruptible2(dialing, proc.blocking());
|
|
15968
16139
|
return ok3();
|
|
15969
16140
|
}
|
|
16141
|
+
async function bindUnixDgram(proc, socket, addr) {
|
|
16142
|
+
const path = filePath(addr);
|
|
16143
|
+
if (path === void 0 || !proc.names) {
|
|
16144
|
+
socket.bind(addr, keyOf(addr));
|
|
16145
|
+
return;
|
|
16146
|
+
}
|
|
16147
|
+
const name2 = await proc.names.make(path);
|
|
16148
|
+
try {
|
|
16149
|
+
socket.bind({ family: "unix", path }, keyOf({ family: "unix", path }, name2));
|
|
16150
|
+
} catch (err) {
|
|
16151
|
+
await name2.remove();
|
|
16152
|
+
throw err;
|
|
16153
|
+
}
|
|
16154
|
+
}
|
|
15970
16155
|
async function bind(proc, fd, addr) {
|
|
15971
16156
|
const socket = anySocketAt(proc.fds, fd);
|
|
16157
|
+
if (socket instanceof UnixDgram) return bindUnixDgram(proc, socket, addr);
|
|
15972
16158
|
const path = filePath(addr);
|
|
15973
16159
|
if (!(socket instanceof KernelSocket) || path === void 0 || !proc.names) {
|
|
15974
16160
|
socket.bind(addr);
|
|
@@ -15985,6 +16171,7 @@ async function bind(proc, fd, addr) {
|
|
|
15985
16171
|
}
|
|
15986
16172
|
async function datagram(req, proc) {
|
|
15987
16173
|
const dgram = dgramAt(proc.fds, req.fd);
|
|
16174
|
+
if (dgram instanceof UnixDgram) return unixDatagram(req, dgram, proc);
|
|
15988
16175
|
if (req.op === "sock-sendto") {
|
|
15989
16176
|
if (req.nonblock && !pollFile(dgram).writable) throw new KernelError("EAGAIN");
|
|
15990
16177
|
return ok3(await dgram.send(req.body, req.addr));
|
|
@@ -15995,6 +16182,24 @@ async function datagram(req, proc) {
|
|
|
15995
16182
|
const { bytes, from, truncated } = got;
|
|
15996
16183
|
return { ok: true, kind: "bytes", bytes: encodeReceived({ bytes, truncated, ...from }) };
|
|
15997
16184
|
}
|
|
16185
|
+
async function unixDatagram(req, dgram, proc) {
|
|
16186
|
+
if (req.op === "sock-sendto") {
|
|
16187
|
+
const to = req.addr ? await unixTarget(proc, req.addr) : dgram.destination();
|
|
16188
|
+
return ok3(await dgram.send(req.body, to, req.nonblock, proc.blocking()));
|
|
16189
|
+
}
|
|
16190
|
+
const ready2 = pollFile(dgram).readable;
|
|
16191
|
+
if (req.nonblock && !ready2) throw new KernelError("EAGAIN");
|
|
16192
|
+
const got = await dgram.receive(req.max, req.peek, ready2 ? void 0 : proc.blocking());
|
|
16193
|
+
const { bytes, from, truncated } = got;
|
|
16194
|
+
return {
|
|
16195
|
+
ok: true,
|
|
16196
|
+
kind: "bytes",
|
|
16197
|
+
bytes: encodeReceived({ bytes, truncated, host: from.path, port: 0, unix: true })
|
|
16198
|
+
};
|
|
16199
|
+
}
|
|
16200
|
+
function domainOf(socket) {
|
|
16201
|
+
return socket instanceof UnixDgram ? "unix" : "inet";
|
|
16202
|
+
}
|
|
15998
16203
|
function interruptible2(dialing, signal) {
|
|
15999
16204
|
return new Promise((resolve2, reject) => {
|
|
16000
16205
|
const abort = () => reject(new KernelError("EINTR"));
|
|
@@ -17812,8 +18017,8 @@ var WasmProcess = class {
|
|
|
17812
18017
|
const terminal = (file.tty ?? file.pty?.slave)?.name;
|
|
17813
18018
|
return {
|
|
17814
18019
|
tty: file.tty !== void 0,
|
|
17815
|
-
kind: file instanceof KernelSocket || file
|
|
17816
|
-
...file
|
|
18020
|
+
kind: file instanceof KernelSocket || isDatagram(file) ? "socket" : kernelFdKind(file),
|
|
18021
|
+
...isDatagram(file) ? { dgram: true } : {},
|
|
17817
18022
|
...file.heldMeta ? { meta: file.heldMeta } : {},
|
|
17818
18023
|
...flags2 !== void 0 ? { flags: flags2 } : {},
|
|
17819
18024
|
...this.fds.closesOnExec(fd) ? { cloexec: true } : {},
|
|
@@ -18249,7 +18454,7 @@ function inheritedFds(fds) {
|
|
|
18249
18454
|
return fds.numbers().filter((fd) => fd > 2 && !fds.get(fd).file.held).map((fd) => {
|
|
18250
18455
|
const open = fds.get(fd);
|
|
18251
18456
|
const flags2 = fds.statusFlags(fd);
|
|
18252
|
-
const kind = open.file instanceof KernelSocket || open.file
|
|
18457
|
+
const kind = open.file instanceof KernelSocket || isDatagram(open.file) ? "socket" : kernelFdKind(open.file);
|
|
18253
18458
|
const meta = open.file.heldMeta;
|
|
18254
18459
|
return {
|
|
18255
18460
|
fd,
|