@ai-ecoverse/slicc-kernel 1.110.8 → 1.112.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 +11 -3
- package/dist/kernel-worker.js +790 -532
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +21 -11
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +706 -448
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +21 -11
- package/dist/process-worker.js.map +2 -2
- 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/net/hosts-file.d.ts +5 -0
- package/dist/types/kernel/net/resolver.d.ts +4 -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/package.json +1 -1
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.112.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;
|
|
@@ -14890,6 +14644,7 @@ var Resolver = class {
|
|
|
14890
14644
|
own;
|
|
14891
14645
|
cache = /* @__PURE__ */ new Map();
|
|
14892
14646
|
pending = /* @__PURE__ */ new Map();
|
|
14647
|
+
hosts;
|
|
14893
14648
|
constructor(options) {
|
|
14894
14649
|
this.uplink = options.uplink;
|
|
14895
14650
|
this.routes = options.routes;
|
|
@@ -14897,6 +14652,14 @@ var Resolver = class {
|
|
|
14897
14652
|
this.timeoutMs = options.timeoutMs ?? RESOLVE_TIMEOUT_MS;
|
|
14898
14653
|
this.log = options.log ?? ((message3) => console.warn(message3));
|
|
14899
14654
|
this.own = ownNames(options.hostname ?? DEFAULT_HOSTNAME);
|
|
14655
|
+
this.hosts = options.hosts;
|
|
14656
|
+
}
|
|
14657
|
+
async fromFile(key, family) {
|
|
14658
|
+
const listed = (await this.hosts?.().catch(() => void 0))?.get(key);
|
|
14659
|
+
if (!listed) return void 0;
|
|
14660
|
+
const v4 = listed.filter((a) => ipv4Bytes(a) !== void 0);
|
|
14661
|
+
const v6 = listed.filter((a) => ipv4Bytes(a) === void 0);
|
|
14662
|
+
return family === 4 ? v4 : family === 6 ? v6 : [...v4, ...v6];
|
|
14900
14663
|
}
|
|
14901
14664
|
async resolve(name2, family, blocking) {
|
|
14902
14665
|
const key = name2.toLowerCase().replace(/\.$/, "");
|
|
@@ -14905,6 +14668,8 @@ var Resolver = class {
|
|
|
14905
14668
|
const v4 = family !== 6 && local ? [local] : [];
|
|
14906
14669
|
return family === 4 ? v4 : [...v4, key];
|
|
14907
14670
|
}
|
|
14671
|
+
const listed = this.hosts ? await this.fromFile(key, family) : void 0;
|
|
14672
|
+
if (listed?.length) return listed;
|
|
14908
14673
|
if (local) {
|
|
14909
14674
|
const six = loopbackName(key, this.own) ? ["::1"] : [];
|
|
14910
14675
|
return family === 6 ? six : family === 4 ? [local] : [local, ...six];
|
|
@@ -15786,78 +15551,340 @@ async function semSyscall(req, proc) {
|
|
|
15786
15551
|
)
|
|
15787
15552
|
);
|
|
15788
15553
|
}
|
|
15789
|
-
case "sem-close":
|
|
15790
|
-
handles.close(req.handle);
|
|
15791
|
-
return ok2();
|
|
15792
|
-
case "sem-unlink": {
|
|
15793
|
-
const name2 = semName(req.name);
|
|
15794
|
-
table.unlink(name2, unlinks(name2));
|
|
15795
|
-
return ok2();
|
|
15554
|
+
case "sem-close":
|
|
15555
|
+
handles.close(req.handle);
|
|
15556
|
+
return ok2();
|
|
15557
|
+
case "sem-unlink": {
|
|
15558
|
+
const name2 = semName(req.name);
|
|
15559
|
+
table.unlink(name2, unlinks(name2));
|
|
15560
|
+
return ok2();
|
|
15561
|
+
}
|
|
15562
|
+
case "sem-post":
|
|
15563
|
+
handles.get(req.handle).post();
|
|
15564
|
+
return ok2();
|
|
15565
|
+
case "sem-getvalue":
|
|
15566
|
+
return ok2(handles.get(req.handle).value);
|
|
15567
|
+
case "sem-wait": {
|
|
15568
|
+
const sem = handles.get(req.handle);
|
|
15569
|
+
if (sem.take()) return ok2();
|
|
15570
|
+
if (req.how === "try") throw new KernelError("EAGAIN");
|
|
15571
|
+
if (req.how === "timed" && req.timeoutMs === 0) throw new KernelError("ETIMEDOUT");
|
|
15572
|
+
const got = await sem.wait(proc.blocking(), req.how === "block" ? -1 : req.timeoutMs);
|
|
15573
|
+
if (!got) throw new KernelError("ETIMEDOUT");
|
|
15574
|
+
return ok2();
|
|
15575
|
+
}
|
|
15576
|
+
}
|
|
15577
|
+
}
|
|
15578
|
+
|
|
15579
|
+
// src/kernel/socket-nodes.ts
|
|
15580
|
+
function filePath(addr) {
|
|
15581
|
+
if (addr.family !== "unix" || addr.path === "" || addr.path.startsWith("\0")) return void 0;
|
|
15582
|
+
return normalizePath(addr.path);
|
|
15583
|
+
}
|
|
15584
|
+
function nameOf(st) {
|
|
15585
|
+
return { key: `${st.dev ?? 0}:${st.ino}`, typed: st.isSocket === true };
|
|
15586
|
+
}
|
|
15587
|
+
function codeOf3(err) {
|
|
15588
|
+
return err?.code;
|
|
15589
|
+
}
|
|
15590
|
+
function socketNames(deps) {
|
|
15591
|
+
const { fs } = deps;
|
|
15592
|
+
return {
|
|
15593
|
+
async make(path) {
|
|
15594
|
+
const g = deps.guard();
|
|
15595
|
+
if (g) await inParent(g, "bind", path);
|
|
15596
|
+
const owner = deps.owner();
|
|
15597
|
+
try {
|
|
15598
|
+
await deps.create(path, owner);
|
|
15599
|
+
} catch (err) {
|
|
15600
|
+
if (codeOf3(err) === "EEXIST") throw new KernelError("EADDRINUSE");
|
|
15601
|
+
throw err;
|
|
15602
|
+
}
|
|
15603
|
+
const remove = () => fs.rm(path, { file: true }).catch(() => void 0);
|
|
15604
|
+
try {
|
|
15605
|
+
if (!deps.owners && owner.mode !== void 0) await fs.chmod(path, owner.mode);
|
|
15606
|
+
return { ...nameOf(await fs.lstat(path)), remove };
|
|
15607
|
+
} catch (err) {
|
|
15608
|
+
await remove();
|
|
15609
|
+
throw err;
|
|
15610
|
+
}
|
|
15611
|
+
},
|
|
15612
|
+
async find(path) {
|
|
15613
|
+
const g = deps.guard();
|
|
15614
|
+
if (g) await need(g, "connect", path, W_OK, { directory: false });
|
|
15615
|
+
return nameOf(await fs.stat(path));
|
|
15616
|
+
}
|
|
15617
|
+
};
|
|
15618
|
+
}
|
|
15619
|
+
|
|
15620
|
+
// src/kernel/dgram.ts
|
|
15621
|
+
var DGRAM_QUEUE_BYTES = 256 * 1024;
|
|
15622
|
+
var DGRAM_QUEUE_COUNT = 512;
|
|
15623
|
+
var DGRAM_SEND_ROOM = 256 * 1024;
|
|
15624
|
+
var MAX_DATAGRAM_V4 = 65507;
|
|
15625
|
+
var MAX_DATAGRAM_V6 = 65527;
|
|
15626
|
+
var SOL_SOCKET2 = 1;
|
|
15627
|
+
var IPPROTO_IP = 0;
|
|
15628
|
+
var SO_TYPE2 = 3;
|
|
15629
|
+
var SO_ERROR2 = 4;
|
|
15630
|
+
var SO_BROADCAST = 6;
|
|
15631
|
+
var SO_SNDBUF2 = 7;
|
|
15632
|
+
var SO_RCVBUF2 = 8;
|
|
15633
|
+
var SO_DOMAIN2 = 39;
|
|
15634
|
+
var SOCK_DGRAM = 2;
|
|
15635
|
+
var AF_INET2 = 2;
|
|
15636
|
+
var IP_MULTICAST_FIRST = 32;
|
|
15637
|
+
var IP_MULTICAST_LAST = 36;
|
|
15638
|
+
var SEND_ERRORS = ["ENETUNREACH", "EHOSTUNREACH", "EACCES", "EMSGSIZE"];
|
|
15639
|
+
var UNREACHABLE = ["EACCES", "ENETUNREACH", "EHOSTUNREACH"];
|
|
15640
|
+
function sendError(e) {
|
|
15641
|
+
if (e instanceof KernelError) return e;
|
|
15642
|
+
const code = e?.code;
|
|
15643
|
+
return new KernelError(SEND_ERRORS.find((errno2) => errno2 === code) ?? "EHOSTUNREACH");
|
|
15644
|
+
}
|
|
15645
|
+
function sameAddr(a, b) {
|
|
15646
|
+
return a.port === b.port && canonicalHost(a.host) === canonicalHost(b.host);
|
|
15647
|
+
}
|
|
15648
|
+
function familyOf(host) {
|
|
15649
|
+
return host.includes(":") ? 6 : 4;
|
|
15650
|
+
}
|
|
15651
|
+
var KernelDgram = class {
|
|
15652
|
+
local;
|
|
15653
|
+
peer;
|
|
15654
|
+
net;
|
|
15655
|
+
queue = [];
|
|
15656
|
+
queued = 0;
|
|
15657
|
+
pending;
|
|
15658
|
+
closed = false;
|
|
15659
|
+
sending = 0;
|
|
15660
|
+
changes = new Changes();
|
|
15661
|
+
options = /* @__PURE__ */ new Map();
|
|
15662
|
+
uplinks = /* @__PURE__ */ new Map();
|
|
15663
|
+
stop = new AbortController();
|
|
15664
|
+
constructor(net) {
|
|
15665
|
+
this.net = net;
|
|
15666
|
+
}
|
|
15667
|
+
bind(addr) {
|
|
15668
|
+
if (this.local) throw new KernelError("EINVAL");
|
|
15669
|
+
this.local = this.net.bindDgram(this, addr);
|
|
15670
|
+
}
|
|
15671
|
+
bound() {
|
|
15672
|
+
this.local ??= this.net.bindDgram(this, { family: "inet", host: "0.0.0.0", port: 0 });
|
|
15673
|
+
return this.local;
|
|
15674
|
+
}
|
|
15675
|
+
connectTo(addr) {
|
|
15676
|
+
if (addr.family !== "inet") throw new KernelError("EAFNOSUPPORT");
|
|
15677
|
+
this.route(addr.host);
|
|
15678
|
+
this.bound();
|
|
15679
|
+
this.peer = { family: "inet", host: canonicalHost(addr.host), port: addr.port };
|
|
15680
|
+
this.pending = void 0;
|
|
15681
|
+
this.drain((d) => sameAddr(d.from, addr));
|
|
15682
|
+
}
|
|
15683
|
+
drain(keep2) {
|
|
15684
|
+
const kept = this.queue.filter(keep2);
|
|
15685
|
+
this.queue.splice(0, this.queue.length, ...kept);
|
|
15686
|
+
this.queued = kept.reduce((sum, d) => sum + d.bytes.length, 0);
|
|
15687
|
+
}
|
|
15688
|
+
route(host) {
|
|
15689
|
+
const where = this.net.destination(host);
|
|
15690
|
+
if (where === "loopback" || where === "uplink") return where;
|
|
15691
|
+
throw new KernelError("ENETUNREACH");
|
|
15692
|
+
}
|
|
15693
|
+
takeError() {
|
|
15694
|
+
const pending = this.pending;
|
|
15695
|
+
this.pending = void 0;
|
|
15696
|
+
return pending;
|
|
15697
|
+
}
|
|
15698
|
+
async send(bytes, to) {
|
|
15699
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
15700
|
+
const pending = this.takeError();
|
|
15701
|
+
if (pending) throw new KernelError(pending);
|
|
15702
|
+
const target = to ?? this.peer;
|
|
15703
|
+
if (!target) throw new KernelError("EDESTADDRREQ");
|
|
15704
|
+
if (target.family !== "inet") throw new KernelError("EAFNOSUPPORT");
|
|
15705
|
+
const max = familyOf(target.host) === 6 ? MAX_DATAGRAM_V6 : MAX_DATAGRAM_V4;
|
|
15706
|
+
if (bytes.length > max) throw new KernelError("EMSGSIZE");
|
|
15707
|
+
const where = this.route(target.host);
|
|
15708
|
+
const local = this.bound();
|
|
15709
|
+
if (where === "uplink") return this.sendUp(bytes, target);
|
|
15710
|
+
const from = {
|
|
15711
|
+
family: "inet",
|
|
15712
|
+
host: local.host === "0.0.0.0" ? "127.0.0.1" : local.host,
|
|
15713
|
+
port: local.port
|
|
15714
|
+
};
|
|
15715
|
+
const delivered = this.net.deliverDgram(target.port, { bytes: bytes.slice(), from });
|
|
15716
|
+
if (!delivered && this.peer && sameAddr(this.peer, target)) {
|
|
15717
|
+
this.pending = "ECONNREFUSED";
|
|
15718
|
+
this.changes.wake();
|
|
15719
|
+
}
|
|
15720
|
+
return bytes.length;
|
|
15721
|
+
}
|
|
15722
|
+
async sendUp(bytes, to) {
|
|
15723
|
+
const uplink = this.net.uplinkFor(to.host)?.uplink;
|
|
15724
|
+
if (!uplink || !carriesUdp(uplink)) throw new KernelError("ENETUNREACH");
|
|
15725
|
+
this.sending += bytes.length;
|
|
15726
|
+
try {
|
|
15727
|
+
const socket = await this.uplinkSocket(uplink, familyOf(to.host));
|
|
15728
|
+
await socket.send(bytes.slice(), to.host, to.port);
|
|
15729
|
+
} catch (e) {
|
|
15730
|
+
throw sendError(e);
|
|
15731
|
+
} finally {
|
|
15732
|
+
this.sending -= bytes.length;
|
|
15733
|
+
this.changes.wake();
|
|
15734
|
+
}
|
|
15735
|
+
return bytes.length;
|
|
15736
|
+
}
|
|
15737
|
+
uplinkSocket(uplink, family) {
|
|
15738
|
+
const known = this.uplinks.get(family);
|
|
15739
|
+
if (known !== void 0) return known;
|
|
15740
|
+
const opening2 = Promise.resolve().then(() => {
|
|
15741
|
+
if (!uplink.udp) throw new KernelError("ENETUNREACH");
|
|
15742
|
+
return uplink.udp({ family, signal: this.stop.signal });
|
|
15743
|
+
});
|
|
15744
|
+
this.uplinks.set(family, opening2);
|
|
15745
|
+
opening2.then(
|
|
15746
|
+
(socket) => {
|
|
15747
|
+
if (this.closed) {
|
|
15748
|
+
socket.close();
|
|
15749
|
+
return;
|
|
15750
|
+
}
|
|
15751
|
+
void this.pump(socket, family);
|
|
15752
|
+
},
|
|
15753
|
+
() => this.uplinks.delete(family)
|
|
15754
|
+
);
|
|
15755
|
+
return opening2;
|
|
15756
|
+
}
|
|
15757
|
+
async pump(socket, family) {
|
|
15758
|
+
const iterate = async () => {
|
|
15759
|
+
for await (const message3 of socket.messages) {
|
|
15760
|
+
if (this.closed) return;
|
|
15761
|
+
const from = { family: "inet", host: message3.host, port: message3.port };
|
|
15762
|
+
if ("bytes" in message3) this.deliver({ bytes: message3.bytes, from });
|
|
15763
|
+
else this.unreachable(message3.error, from);
|
|
15764
|
+
}
|
|
15765
|
+
};
|
|
15766
|
+
await iterate().catch(() => void 0);
|
|
15767
|
+
if (!this.closed) this.uplinks.delete(family);
|
|
15768
|
+
socket.close();
|
|
15769
|
+
}
|
|
15770
|
+
unreachable(error, from) {
|
|
15771
|
+
if (!this.peer || !sameAddr(this.peer, from)) return;
|
|
15772
|
+
this.pending = UNREACHABLE.find((errno2) => errno2 === error) ?? "EHOSTUNREACH";
|
|
15773
|
+
this.changes.wake();
|
|
15774
|
+
}
|
|
15775
|
+
deliver(datagram2) {
|
|
15776
|
+
if (this.closed) return false;
|
|
15777
|
+
if (this.peer && !sameAddr(this.peer, datagram2.from)) return true;
|
|
15778
|
+
const full = this.queue.length >= DGRAM_QUEUE_COUNT || this.queued + datagram2.bytes.length > DGRAM_QUEUE_BYTES;
|
|
15779
|
+
if (full) return true;
|
|
15780
|
+
this.queue.push(datagram2);
|
|
15781
|
+
this.queued += datagram2.bytes.length;
|
|
15782
|
+
this.changes.wake();
|
|
15783
|
+
return true;
|
|
15784
|
+
}
|
|
15785
|
+
async receive(max, peek, signal) {
|
|
15786
|
+
for (; ; ) {
|
|
15787
|
+
const pending = this.takeError();
|
|
15788
|
+
if (pending) throw new KernelError(pending);
|
|
15789
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
15790
|
+
const next3 = this.queue[0];
|
|
15791
|
+
if (next3) {
|
|
15792
|
+
if (!peek) {
|
|
15793
|
+
this.queue.shift();
|
|
15794
|
+
this.queued -= next3.bytes.length;
|
|
15795
|
+
this.changes.wake();
|
|
15796
|
+
}
|
|
15797
|
+
const size = Math.max(0, max);
|
|
15798
|
+
return {
|
|
15799
|
+
bytes: next3.bytes.slice(0, size),
|
|
15800
|
+
from: next3.from,
|
|
15801
|
+
truncated: next3.bytes.length > size
|
|
15802
|
+
};
|
|
15803
|
+
}
|
|
15804
|
+
await this.changes.wait(signal);
|
|
15805
|
+
}
|
|
15806
|
+
}
|
|
15807
|
+
async read(max, signal) {
|
|
15808
|
+
return (await this.receive(max, false, signal)).bytes;
|
|
15809
|
+
}
|
|
15810
|
+
async peek(max, signal) {
|
|
15811
|
+
return (await this.receive(max, true, signal)).bytes;
|
|
15812
|
+
}
|
|
15813
|
+
write(bytes) {
|
|
15814
|
+
return this.send(bytes);
|
|
15815
|
+
}
|
|
15816
|
+
poll() {
|
|
15817
|
+
return {
|
|
15818
|
+
readable: this.queue.length > 0 || this.pending !== void 0 || this.closed,
|
|
15819
|
+
writable: this.sending < DGRAM_SEND_ROOM,
|
|
15820
|
+
hangup: this.closed,
|
|
15821
|
+
...this.pending !== void 0 ? { error: true } : {}
|
|
15822
|
+
};
|
|
15823
|
+
}
|
|
15824
|
+
changed(signal) {
|
|
15825
|
+
return this.changes.wait(signal);
|
|
15826
|
+
}
|
|
15827
|
+
shutdown(how) {
|
|
15828
|
+
if (!this.peer) throw new KernelError("ENOTCONN");
|
|
15829
|
+
if (how < 0 || how > 2) throw new KernelError("EINVAL");
|
|
15830
|
+
}
|
|
15831
|
+
getOption(level, name2) {
|
|
15832
|
+
if (level === SOL_SOCKET2) {
|
|
15833
|
+
switch (name2) {
|
|
15834
|
+
case SO_TYPE2:
|
|
15835
|
+
return SOCK_DGRAM;
|
|
15836
|
+
case SO_ERROR2: {
|
|
15837
|
+
const pending = this.takeError();
|
|
15838
|
+
return pending ? wasiErrno(pending) : 0;
|
|
15839
|
+
}
|
|
15840
|
+
case SO_DOMAIN2:
|
|
15841
|
+
return AF_INET2;
|
|
15842
|
+
case SO_BROADCAST:
|
|
15843
|
+
return 0;
|
|
15844
|
+
case SO_SNDBUF2:
|
|
15845
|
+
return this.options.get(`${level}:${name2}`) ?? DGRAM_SEND_ROOM;
|
|
15846
|
+
case SO_RCVBUF2:
|
|
15847
|
+
return this.options.get(`${level}:${name2}`) ?? DGRAM_QUEUE_BYTES;
|
|
15848
|
+
}
|
|
15796
15849
|
}
|
|
15797
|
-
|
|
15798
|
-
|
|
15799
|
-
return ok2();
|
|
15800
|
-
case "sem-getvalue":
|
|
15801
|
-
return ok2(handles.get(req.handle).value);
|
|
15802
|
-
case "sem-wait": {
|
|
15803
|
-
const sem = handles.get(req.handle);
|
|
15804
|
-
if (sem.take()) return ok2();
|
|
15805
|
-
if (req.how === "try") throw new KernelError("EAGAIN");
|
|
15806
|
-
if (req.how === "timed" && req.timeoutMs === 0) throw new KernelError("ETIMEDOUT");
|
|
15807
|
-
const got = await sem.wait(proc.blocking(), req.how === "block" ? -1 : req.timeoutMs);
|
|
15808
|
-
if (!got) throw new KernelError("ETIMEDOUT");
|
|
15809
|
-
return ok2();
|
|
15850
|
+
if (level === IPPROTO_IP && name2 >= IP_MULTICAST_FIRST && name2 <= IP_MULTICAST_LAST) {
|
|
15851
|
+
throw new KernelError("ENOPROTOOPT");
|
|
15810
15852
|
}
|
|
15853
|
+
return this.options.get(`${level}:${name2}`) ?? 0;
|
|
15811
15854
|
}
|
|
15812
|
-
|
|
15813
|
-
|
|
15814
|
-
|
|
15815
|
-
function filePath(addr) {
|
|
15816
|
-
if (addr.family !== "unix" || addr.path === "" || addr.path.startsWith("\0")) return void 0;
|
|
15817
|
-
return normalizePath(addr.path);
|
|
15818
|
-
}
|
|
15819
|
-
function nameOf(st) {
|
|
15820
|
-
return { key: `${st.dev ?? 0}:${st.ino}`, typed: st.isSocket === true };
|
|
15821
|
-
}
|
|
15822
|
-
function codeOf3(err) {
|
|
15823
|
-
return err?.code;
|
|
15824
|
-
}
|
|
15825
|
-
function socketNames(deps) {
|
|
15826
|
-
const { fs } = deps;
|
|
15827
|
-
return {
|
|
15828
|
-
async make(path) {
|
|
15829
|
-
const g = deps.guard();
|
|
15830
|
-
if (g) await inParent(g, "bind", path);
|
|
15831
|
-
const owner = deps.owner();
|
|
15832
|
-
try {
|
|
15833
|
-
await deps.create(path, owner);
|
|
15834
|
-
} catch (err) {
|
|
15835
|
-
if (codeOf3(err) === "EEXIST") throw new KernelError("EADDRINUSE");
|
|
15836
|
-
throw err;
|
|
15837
|
-
}
|
|
15838
|
-
const remove = () => fs.rm(path, { file: true }).catch(() => void 0);
|
|
15839
|
-
try {
|
|
15840
|
-
if (!deps.owners && owner.mode !== void 0) await fs.chmod(path, owner.mode);
|
|
15841
|
-
return { ...nameOf(await fs.lstat(path)), remove };
|
|
15842
|
-
} catch (err) {
|
|
15843
|
-
await remove();
|
|
15844
|
-
throw err;
|
|
15845
|
-
}
|
|
15846
|
-
},
|
|
15847
|
-
async find(path) {
|
|
15848
|
-
const g = deps.guard();
|
|
15849
|
-
if (g) await need(g, "connect", path, W_OK, { directory: false });
|
|
15850
|
-
return nameOf(await fs.stat(path));
|
|
15855
|
+
setOption(level, name2, value2) {
|
|
15856
|
+
if (level === SOL_SOCKET2 && name2 === SO_BROADCAST && value2 !== 0) {
|
|
15857
|
+
throw new KernelError("EOPNOTSUPP");
|
|
15851
15858
|
}
|
|
15852
|
-
|
|
15853
|
-
|
|
15859
|
+
if (level === IPPROTO_IP && name2 >= IP_MULTICAST_FIRST && name2 <= IP_MULTICAST_LAST) {
|
|
15860
|
+
throw new KernelError("ENOPROTOOPT");
|
|
15861
|
+
}
|
|
15862
|
+
this.options.set(`${level}:${name2}`, value2);
|
|
15863
|
+
}
|
|
15864
|
+
close() {
|
|
15865
|
+
if (this.closed) return;
|
|
15866
|
+
this.closed = true;
|
|
15867
|
+
this.stop.abort();
|
|
15868
|
+
for (const opening2 of this.uplinks.values()) {
|
|
15869
|
+
opening2.then(
|
|
15870
|
+
(socket) => socket.close(),
|
|
15871
|
+
() => void 0
|
|
15872
|
+
);
|
|
15873
|
+
}
|
|
15874
|
+
this.uplinks.clear();
|
|
15875
|
+
if (this.local) this.net.releaseDgram(this.local, this);
|
|
15876
|
+
this.queue.length = 0;
|
|
15877
|
+
this.queued = 0;
|
|
15878
|
+
this.changes.wake();
|
|
15879
|
+
}
|
|
15880
|
+
};
|
|
15854
15881
|
|
|
15855
15882
|
// src/kernel/net/datagram-wire.ts
|
|
15856
15883
|
function encodeReceived(got) {
|
|
15857
15884
|
const host = new TextEncoder().encode(got.host);
|
|
15858
15885
|
const out = new Uint8Array(4 + host.length + got.bytes.length);
|
|
15859
15886
|
const view2 = new DataView(out.buffer);
|
|
15860
|
-
view2.setUint8(0, got.truncated ? 1 : 0);
|
|
15887
|
+
view2.setUint8(0, (got.truncated ? 1 : 0) | (got.unix ? 2 : 0));
|
|
15861
15888
|
view2.setUint16(1, got.port);
|
|
15862
15889
|
view2.setUint8(3, host.length);
|
|
15863
15890
|
out.set(host, 4);
|
|
@@ -15865,6 +15892,152 @@ function encodeReceived(got) {
|
|
|
15865
15892
|
return out;
|
|
15866
15893
|
}
|
|
15867
15894
|
|
|
15895
|
+
// src/kernel/unix-dgram.ts
|
|
15896
|
+
var SOL_SOCKET3 = 1;
|
|
15897
|
+
var SO_TYPE3 = 3;
|
|
15898
|
+
var SO_ERROR3 = 4;
|
|
15899
|
+
var SO_SNDBUF3 = 7;
|
|
15900
|
+
var SO_RCVBUF3 = 8;
|
|
15901
|
+
var SO_DOMAIN3 = 39;
|
|
15902
|
+
var SOCK_DGRAM2 = 2;
|
|
15903
|
+
var AF_UNIX2 = 1;
|
|
15904
|
+
var UNNAMED = { family: "unix", path: "" };
|
|
15905
|
+
var UnixDgram = class _UnixDgram {
|
|
15906
|
+
local;
|
|
15907
|
+
peer;
|
|
15908
|
+
key;
|
|
15909
|
+
peerCred;
|
|
15910
|
+
target;
|
|
15911
|
+
net;
|
|
15912
|
+
queue = [];
|
|
15913
|
+
queued = 0;
|
|
15914
|
+
closed = false;
|
|
15915
|
+
changes = new Changes();
|
|
15916
|
+
options = /* @__PURE__ */ new Map();
|
|
15917
|
+
constructor(net) {
|
|
15918
|
+
this.net = net;
|
|
15919
|
+
}
|
|
15920
|
+
static pair(net, cred) {
|
|
15921
|
+
const a = new _UnixDgram(net);
|
|
15922
|
+
const b = new _UnixDgram(net);
|
|
15923
|
+
a.target = b;
|
|
15924
|
+
b.target = a;
|
|
15925
|
+
a.peer = b.peer = UNNAMED;
|
|
15926
|
+
a.peerCred = b.peerCred = cred;
|
|
15927
|
+
return [a, b];
|
|
15928
|
+
}
|
|
15929
|
+
bind(addr, key) {
|
|
15930
|
+
if (addr.family !== "unix") throw new KernelError("EINVAL");
|
|
15931
|
+
if (this.local) throw new KernelError("EINVAL");
|
|
15932
|
+
if (addr.path === "") throw new KernelError("EINVAL");
|
|
15933
|
+
this.net.bindUnixDgram(this, key);
|
|
15934
|
+
this.local = { family: "unix", path: addr.path };
|
|
15935
|
+
this.key = key;
|
|
15936
|
+
}
|
|
15937
|
+
connectTo(addr, target) {
|
|
15938
|
+
this.target = target;
|
|
15939
|
+
this.peer = addr;
|
|
15940
|
+
const kept = this.queue.filter((d) => d.sender === target);
|
|
15941
|
+
this.queue.splice(0, this.queue.length, ...kept);
|
|
15942
|
+
this.queued = kept.reduce((sum, d) => sum + d.bytes.length, 0);
|
|
15943
|
+
}
|
|
15944
|
+
destination() {
|
|
15945
|
+
if (!this.target) throw new KernelError("EDESTADDRREQ");
|
|
15946
|
+
return this.target;
|
|
15947
|
+
}
|
|
15948
|
+
room(bytes) {
|
|
15949
|
+
return this.closed || this.queue.length < DGRAM_QUEUE_COUNT && this.queued + bytes <= DGRAM_QUEUE_BYTES;
|
|
15950
|
+
}
|
|
15951
|
+
async send(bytes, to, nonblock, signal) {
|
|
15952
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
15953
|
+
if (bytes.length > DGRAM_QUEUE_BYTES) throw new KernelError("EMSGSIZE");
|
|
15954
|
+
if (to.target && to.target !== this) throw new KernelError("EPERM");
|
|
15955
|
+
while (!to.room(bytes.length)) {
|
|
15956
|
+
if (nonblock) throw new KernelError("EAGAIN");
|
|
15957
|
+
await to.changed(signal);
|
|
15958
|
+
}
|
|
15959
|
+
if (to.closed) throw new KernelError("ECONNREFUSED");
|
|
15960
|
+
to.queue.push({ bytes: bytes.slice(), from: this.local ?? UNNAMED, sender: this });
|
|
15961
|
+
to.queued += bytes.length;
|
|
15962
|
+
to.changes.wake();
|
|
15963
|
+
return bytes.length;
|
|
15964
|
+
}
|
|
15965
|
+
async receive(max, peek, signal) {
|
|
15966
|
+
for (; ; ) {
|
|
15967
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
15968
|
+
const next3 = this.queue[0];
|
|
15969
|
+
if (next3) {
|
|
15970
|
+
if (!peek) {
|
|
15971
|
+
this.queue.shift();
|
|
15972
|
+
this.queued -= next3.bytes.length;
|
|
15973
|
+
this.changes.wake();
|
|
15974
|
+
}
|
|
15975
|
+
const size = Math.max(0, max);
|
|
15976
|
+
return {
|
|
15977
|
+
bytes: next3.bytes.slice(0, size),
|
|
15978
|
+
from: next3.from,
|
|
15979
|
+
truncated: next3.bytes.length > size
|
|
15980
|
+
};
|
|
15981
|
+
}
|
|
15982
|
+
await this.changes.wait(signal);
|
|
15983
|
+
}
|
|
15984
|
+
}
|
|
15985
|
+
async read(max, signal) {
|
|
15986
|
+
return (await this.receive(max, false, signal)).bytes;
|
|
15987
|
+
}
|
|
15988
|
+
async peek(max, signal) {
|
|
15989
|
+
return (await this.receive(max, true, signal)).bytes;
|
|
15990
|
+
}
|
|
15991
|
+
write(bytes, signal) {
|
|
15992
|
+
return this.send(bytes, this.destination(), false, signal);
|
|
15993
|
+
}
|
|
15994
|
+
poll() {
|
|
15995
|
+
const target = this.target;
|
|
15996
|
+
return {
|
|
15997
|
+
readable: this.queue.length > 0 || this.closed,
|
|
15998
|
+
writable: !target || target.room(1),
|
|
15999
|
+
hangup: this.closed
|
|
16000
|
+
};
|
|
16001
|
+
}
|
|
16002
|
+
changed(signal) {
|
|
16003
|
+
return this.changes.wait(signal);
|
|
16004
|
+
}
|
|
16005
|
+
shutdown(how) {
|
|
16006
|
+
if (!this.peer) throw new KernelError("ENOTCONN");
|
|
16007
|
+
if (how < 0 || how > 2) throw new KernelError("EINVAL");
|
|
16008
|
+
}
|
|
16009
|
+
getOption(level, name2) {
|
|
16010
|
+
if (level === SOL_SOCKET3) {
|
|
16011
|
+
switch (name2) {
|
|
16012
|
+
case SO_TYPE3:
|
|
16013
|
+
return SOCK_DGRAM2;
|
|
16014
|
+
case SO_ERROR3:
|
|
16015
|
+
return 0;
|
|
16016
|
+
case SO_DOMAIN3:
|
|
16017
|
+
return AF_UNIX2;
|
|
16018
|
+
case SO_SNDBUF3:
|
|
16019
|
+
case SO_RCVBUF3:
|
|
16020
|
+
return this.options.get(`${level}:${name2}`) ?? DGRAM_QUEUE_BYTES;
|
|
16021
|
+
}
|
|
16022
|
+
}
|
|
16023
|
+
return this.options.get(`${level}:${name2}`) ?? 0;
|
|
16024
|
+
}
|
|
16025
|
+
setOption(level, name2, value2) {
|
|
16026
|
+
this.options.set(`${level}:${name2}`, value2);
|
|
16027
|
+
}
|
|
16028
|
+
close() {
|
|
16029
|
+
if (this.closed) return;
|
|
16030
|
+
this.closed = true;
|
|
16031
|
+
if (this.key !== void 0) this.net.releaseUnixDgram(this.key, this);
|
|
16032
|
+
this.queue.length = 0;
|
|
16033
|
+
this.queued = 0;
|
|
16034
|
+
this.changes.wake();
|
|
16035
|
+
}
|
|
16036
|
+
};
|
|
16037
|
+
function isDatagram(file) {
|
|
16038
|
+
return file instanceof KernelDgram || file instanceof UnixDgram;
|
|
16039
|
+
}
|
|
16040
|
+
|
|
15868
16041
|
// src/kernel/socket-syscalls.ts
|
|
15869
16042
|
var SOCKET_OPS = [
|
|
15870
16043
|
"sock-open",
|
|
@@ -15883,32 +16056,37 @@ var SOCKET_OPS = [
|
|
|
15883
16056
|
];
|
|
15884
16057
|
function socketAt(fds, fd) {
|
|
15885
16058
|
const file = anySocketAt(fds, fd);
|
|
15886
|
-
if (file instanceof
|
|
16059
|
+
if (!(file instanceof KernelSocket)) throw new KernelError("EOPNOTSUPP");
|
|
15887
16060
|
return file;
|
|
15888
16061
|
}
|
|
15889
16062
|
function anySocketAt(fds, fd) {
|
|
15890
16063
|
const file = fds.get(fd).file;
|
|
15891
|
-
if (!(file instanceof KernelSocket) && !(file instanceof KernelDgram)) {
|
|
16064
|
+
if (!(file instanceof KernelSocket) && !(file instanceof KernelDgram) && !(file instanceof UnixDgram)) {
|
|
15892
16065
|
throw new KernelError("ENOTSOCK");
|
|
15893
16066
|
}
|
|
15894
16067
|
return file;
|
|
15895
16068
|
}
|
|
15896
16069
|
function dgramAt(fds, fd) {
|
|
15897
16070
|
const file = anySocketAt(fds, fd);
|
|
15898
|
-
if (
|
|
16071
|
+
if (file instanceof KernelSocket) throw new KernelError("EOPNOTSUPP");
|
|
15899
16072
|
return file;
|
|
15900
16073
|
}
|
|
16074
|
+
async function unixTarget(proc, addr) {
|
|
16075
|
+
if (addr.family !== "unix") throw new KernelError("EAFNOSUPPORT");
|
|
16076
|
+
const path = filePath(addr);
|
|
16077
|
+
const name2 = path !== void 0 ? await proc.names?.find(path) : void 0;
|
|
16078
|
+
return proc.net.unixDgramAt(keyOf(path !== void 0 ? { family: "unix", path } : addr, name2));
|
|
16079
|
+
}
|
|
15901
16080
|
var ok3 = (json5) => json5 === void 0 ? { ok: true, kind: "void" } : { ok: true, kind: "json", json: json5 };
|
|
15902
16081
|
async function socketSyscall(req, proc) {
|
|
15903
16082
|
const { fds, net } = proc;
|
|
15904
16083
|
switch (req.op) {
|
|
15905
16084
|
case "sock-open": {
|
|
15906
|
-
|
|
15907
|
-
const file = req.type === "dgram" ? new KernelDgram(net) : net.socket(req.domain);
|
|
16085
|
+
const file = req.type !== "dgram" ? net.socket(req.domain) : req.domain === "unix" ? new UnixDgram(net) : new KernelDgram(net);
|
|
15908
16086
|
return ok3(fds.install(new OpenFile(file), 3));
|
|
15909
16087
|
}
|
|
15910
16088
|
case "sock-pair": {
|
|
15911
|
-
const [a, b] = KernelSocket.pair(net, req.domain, proc.cred?.());
|
|
16089
|
+
const [a, b] = req.type === "dgram" && req.domain === "unix" ? UnixDgram.pair(net, proc.cred?.()) : KernelSocket.pair(net, req.domain, proc.cred?.());
|
|
15912
16090
|
const first = fds.install(new OpenFile(a), 3);
|
|
15913
16091
|
try {
|
|
15914
16092
|
return ok3([first, fds.install(new OpenFile(b), 3)]);
|
|
@@ -15934,7 +16112,7 @@ async function socketSyscall(req, proc) {
|
|
|
15934
16112
|
const socket = anySocketAt(fds, req.fd);
|
|
15935
16113
|
const addr = req.peer ? socket.peer : socket.local;
|
|
15936
16114
|
if (req.peer && !addr) throw new KernelError("ENOTCONN");
|
|
15937
|
-
return ok3(addr ?? unnamed(socket instanceof
|
|
16115
|
+
return ok3(addr ?? unnamed(socket instanceof KernelSocket ? socket.domain : domainOf(socket)));
|
|
15938
16116
|
}
|
|
15939
16117
|
case "sock-getopt":
|
|
15940
16118
|
return ok3(anySocketAt(fds, req.fd).getOption(req.level, req.name));
|
|
@@ -15956,6 +16134,10 @@ async function connect(req, proc) {
|
|
|
15956
16134
|
target.connectTo(req.addr);
|
|
15957
16135
|
return ok3();
|
|
15958
16136
|
}
|
|
16137
|
+
if (target instanceof UnixDgram) {
|
|
16138
|
+
target.connectTo(req.addr, await unixTarget(proc, req.addr));
|
|
16139
|
+
return ok3();
|
|
16140
|
+
}
|
|
15959
16141
|
const path = filePath(req.addr);
|
|
15960
16142
|
const name2 = path !== void 0 ? await proc.names?.find(path) : void 0;
|
|
15961
16143
|
const stamp = proc.net.facadeAt(req.addr) && await proc.stamp?.();
|
|
@@ -15967,8 +16149,23 @@ async function connect(req, proc) {
|
|
|
15967
16149
|
if (dialing !== void 0) await interruptible2(dialing, proc.blocking());
|
|
15968
16150
|
return ok3();
|
|
15969
16151
|
}
|
|
16152
|
+
async function bindUnixDgram(proc, socket, addr) {
|
|
16153
|
+
const path = filePath(addr);
|
|
16154
|
+
if (path === void 0 || !proc.names) {
|
|
16155
|
+
socket.bind(addr, keyOf(addr));
|
|
16156
|
+
return;
|
|
16157
|
+
}
|
|
16158
|
+
const name2 = await proc.names.make(path);
|
|
16159
|
+
try {
|
|
16160
|
+
socket.bind({ family: "unix", path }, keyOf({ family: "unix", path }, name2));
|
|
16161
|
+
} catch (err) {
|
|
16162
|
+
await name2.remove();
|
|
16163
|
+
throw err;
|
|
16164
|
+
}
|
|
16165
|
+
}
|
|
15970
16166
|
async function bind(proc, fd, addr) {
|
|
15971
16167
|
const socket = anySocketAt(proc.fds, fd);
|
|
16168
|
+
if (socket instanceof UnixDgram) return bindUnixDgram(proc, socket, addr);
|
|
15972
16169
|
const path = filePath(addr);
|
|
15973
16170
|
if (!(socket instanceof KernelSocket) || path === void 0 || !proc.names) {
|
|
15974
16171
|
socket.bind(addr);
|
|
@@ -15985,6 +16182,7 @@ async function bind(proc, fd, addr) {
|
|
|
15985
16182
|
}
|
|
15986
16183
|
async function datagram(req, proc) {
|
|
15987
16184
|
const dgram = dgramAt(proc.fds, req.fd);
|
|
16185
|
+
if (dgram instanceof UnixDgram) return unixDatagram(req, dgram, proc);
|
|
15988
16186
|
if (req.op === "sock-sendto") {
|
|
15989
16187
|
if (req.nonblock && !pollFile(dgram).writable) throw new KernelError("EAGAIN");
|
|
15990
16188
|
return ok3(await dgram.send(req.body, req.addr));
|
|
@@ -15995,6 +16193,24 @@ async function datagram(req, proc) {
|
|
|
15995
16193
|
const { bytes, from, truncated } = got;
|
|
15996
16194
|
return { ok: true, kind: "bytes", bytes: encodeReceived({ bytes, truncated, ...from }) };
|
|
15997
16195
|
}
|
|
16196
|
+
async function unixDatagram(req, dgram, proc) {
|
|
16197
|
+
if (req.op === "sock-sendto") {
|
|
16198
|
+
const to = req.addr ? await unixTarget(proc, req.addr) : dgram.destination();
|
|
16199
|
+
return ok3(await dgram.send(req.body, to, req.nonblock, proc.blocking()));
|
|
16200
|
+
}
|
|
16201
|
+
const ready2 = pollFile(dgram).readable;
|
|
16202
|
+
if (req.nonblock && !ready2) throw new KernelError("EAGAIN");
|
|
16203
|
+
const got = await dgram.receive(req.max, req.peek, ready2 ? void 0 : proc.blocking());
|
|
16204
|
+
const { bytes, from, truncated } = got;
|
|
16205
|
+
return {
|
|
16206
|
+
ok: true,
|
|
16207
|
+
kind: "bytes",
|
|
16208
|
+
bytes: encodeReceived({ bytes, truncated, host: from.path, port: 0, unix: true })
|
|
16209
|
+
};
|
|
16210
|
+
}
|
|
16211
|
+
function domainOf(socket) {
|
|
16212
|
+
return socket instanceof UnixDgram ? "unix" : "inet";
|
|
16213
|
+
}
|
|
15998
16214
|
function interruptible2(dialing, signal) {
|
|
15999
16215
|
return new Promise((resolve2, reject) => {
|
|
16000
16216
|
const abort = () => reject(new KernelError("EINTR"));
|
|
@@ -17812,8 +18028,8 @@ var WasmProcess = class {
|
|
|
17812
18028
|
const terminal = (file.tty ?? file.pty?.slave)?.name;
|
|
17813
18029
|
return {
|
|
17814
18030
|
tty: file.tty !== void 0,
|
|
17815
|
-
kind: file instanceof KernelSocket || file
|
|
17816
|
-
...file
|
|
18031
|
+
kind: file instanceof KernelSocket || isDatagram(file) ? "socket" : kernelFdKind(file),
|
|
18032
|
+
...isDatagram(file) ? { dgram: true } : {},
|
|
17817
18033
|
...file.heldMeta ? { meta: file.heldMeta } : {},
|
|
17818
18034
|
...flags2 !== void 0 ? { flags: flags2 } : {},
|
|
17819
18035
|
...this.fds.closesOnExec(fd) ? { cloexec: true } : {},
|
|
@@ -18249,7 +18465,7 @@ function inheritedFds(fds) {
|
|
|
18249
18465
|
return fds.numbers().filter((fd) => fd > 2 && !fds.get(fd).file.held).map((fd) => {
|
|
18250
18466
|
const open = fds.get(fd);
|
|
18251
18467
|
const flags2 = fds.statusFlags(fd);
|
|
18252
|
-
const kind = open.file instanceof KernelSocket || open.file
|
|
18468
|
+
const kind = open.file instanceof KernelSocket || isDatagram(open.file) ? "socket" : kernelFdKind(open.file);
|
|
18253
18469
|
const meta = open.file.heldMeta;
|
|
18254
18470
|
return {
|
|
18255
18471
|
fd,
|
|
@@ -18855,6 +19071,43 @@ var JobTable = class {
|
|
|
18855
19071
|
}
|
|
18856
19072
|
};
|
|
18857
19073
|
|
|
19074
|
+
// src/kernel/net/hosts-file.ts
|
|
19075
|
+
var HOSTS_PATH = "/etc/hosts";
|
|
19076
|
+
function parseHosts(text) {
|
|
19077
|
+
const table = /* @__PURE__ */ new Map();
|
|
19078
|
+
for (const raw of text.split("\n")) {
|
|
19079
|
+
const [address, ...names] = raw.replace(/#.*/, "").trim().split(/\s+/);
|
|
19080
|
+
if (!address || names.length === 0) continue;
|
|
19081
|
+
if (ipv4Bytes(address) === void 0 && ipv6Groups(address) === void 0) continue;
|
|
19082
|
+
for (const name2 of names) {
|
|
19083
|
+
const key = name2.toLowerCase().replace(/\.$/, "");
|
|
19084
|
+
const known = table.get(key) ?? [];
|
|
19085
|
+
if (!known.includes(address)) known.push(address);
|
|
19086
|
+
table.set(key, known);
|
|
19087
|
+
}
|
|
19088
|
+
}
|
|
19089
|
+
return table;
|
|
19090
|
+
}
|
|
19091
|
+
function hostsReader(fs, path = HOSTS_PATH) {
|
|
19092
|
+
let stamp = "";
|
|
19093
|
+
let table;
|
|
19094
|
+
return async () => {
|
|
19095
|
+
const st = await fs.stat(path).catch(() => void 0);
|
|
19096
|
+
if (!st?.isFile) {
|
|
19097
|
+
stamp = "";
|
|
19098
|
+
table = void 0;
|
|
19099
|
+
return void 0;
|
|
19100
|
+
}
|
|
19101
|
+
const now = `${st.ino}:${st.size}:${st.mtime.getTime()}`;
|
|
19102
|
+
if (now === stamp && table) return table;
|
|
19103
|
+
const text = await fs.readFile(path).catch(() => void 0);
|
|
19104
|
+
if (text === void 0) return void 0;
|
|
19105
|
+
stamp = now;
|
|
19106
|
+
table = parseHosts(text);
|
|
19107
|
+
return table;
|
|
19108
|
+
};
|
|
19109
|
+
}
|
|
19110
|
+
|
|
18858
19111
|
// src/kernel/net/redirect-hops.ts
|
|
18859
19112
|
var HELD_MS = 3e4;
|
|
18860
19113
|
var HELD_MAX = 64;
|
|
@@ -22295,7 +22548,12 @@ var Launcher = class {
|
|
|
22295
22548
|
this.uplink = options.uplink;
|
|
22296
22549
|
this.routes = new Routes(options.uplink?.traits.ipv6 === true);
|
|
22297
22550
|
if (options.uplink?.routes) this.routes.set(options.uplink.routes);
|
|
22298
|
-
this.resolver = new Resolver({
|
|
22551
|
+
this.resolver = new Resolver({
|
|
22552
|
+
uplink: options.uplink,
|
|
22553
|
+
routes: this.routes,
|
|
22554
|
+
hostname,
|
|
22555
|
+
hosts: hostsReader(this.base)
|
|
22556
|
+
});
|
|
22299
22557
|
if (options.uplink) this.net.useUplink({ uplink: options.uplink, routes: this.routes });
|
|
22300
22558
|
enableNetwork(this.net, {
|
|
22301
22559
|
transport: this.transport,
|