@ai-ecoverse/slicc-kernel 1.110.8 → 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/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) throw new KernelError("EADDRINUSE");
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.110.8" : "0.0.0-dev";
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/kernel/net/uplink.ts
11864
- function carriesUdp(uplink) {
11865
- return uplink.traits.udp === true && typeof uplink.udp === "function";
11866
- }
11867
- function answerOf(result) {
11868
- const answer = Array.isArray(result) ? { addresses: result } : result;
11869
- const addresses = Array.isArray(answer?.addresses) ? answer.addresses.filter((a) => typeof a === "string") : [];
11870
- return {
11871
- addresses,
11872
- ...typeof answer?.ttl === "number" && answer.ttl >= 0 ? { ttl: answer.ttl } : {}
11873
- };
11874
- }
11875
- var NEVER = new Routes(true);
11876
-
11877
- // src/kernel/dgram.ts
11878
- var DGRAM_QUEUE_BYTES = 256 * 1024;
11879
- var DGRAM_QUEUE_COUNT = 512;
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
- bind(addr) {
11925
- if (this.local) throw new KernelError("EINVAL");
11926
- this.local = this.net.bindDgram(this, addr);
11897
+ get dirtyBytes() {
11898
+ return this.dirty.size * PAGE;
11927
11899
  }
11928
- bound() {
11929
- this.local ??= this.net.bindDgram(this, { family: "inet", host: "0.0.0.0", port: 0 });
11930
- return this.local;
11900
+ get changed() {
11901
+ return this.dirty.size > 0 || this.shrink !== void 0 || this.length !== this.stored;
11931
11902
  }
11932
- connectTo(addr) {
11933
- if (addr.family !== "inet") throw new KernelError("EAFNOSUPPORT");
11934
- this.route(addr.host);
11935
- this.bound();
11936
- this.peer = { family: "inet", host: canonicalHost(addr.host), port: addr.port };
11937
- this.pending = void 0;
11938
- this.drain((d) => sameAddr(d.from, addr));
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
- drain(keep2) {
11941
- const kept = this.queue.filter(keep2);
11942
- this.queue.splice(0, this.queue.length, ...kept);
11943
- this.queued = kept.reduce((sum, d) => sum + d.bytes.length, 0);
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
- route(host) {
11946
- const where = this.net.destination(host);
11947
- if (where === "loopback" || where === "uplink") return where;
11948
- throw new KernelError("ENETUNREACH");
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
- takeError() {
11951
- const pending = this.pending;
11952
- this.pending = void 0;
11953
- return pending;
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
- async send(bytes, to) {
11956
- if (this.closed) throw new KernelError("EBADF");
11957
- const pending = this.takeError();
11958
- if (pending) throw new KernelError(pending);
11959
- const target = to ?? this.peer;
11960
- if (!target) throw new KernelError("EDESTADDRREQ");
11961
- if (target.family !== "inet") throw new KernelError("EAFNOSUPPORT");
11962
- const max = familyOf(target.host) === 6 ? MAX_DATAGRAM_V6 : MAX_DATAGRAM_V4;
11963
- if (bytes.length > max) throw new KernelError("EMSGSIZE");
11964
- const where = this.route(target.host);
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 bytes.length;
11956
+ return Math.max(0, end - at);
11978
11957
  }
11979
- async sendUp(bytes, to) {
11980
- const uplink = this.net.uplinkFor(to.host)?.uplink;
11981
- if (!uplink || !carriesUdp(uplink)) throw new KernelError("ENETUNREACH");
11982
- this.sending += bytes.length;
11983
- try {
11984
- const socket = await this.uplinkSocket(uplink, familyOf(to.host));
11985
- await socket.send(bytes.slice(), to.host, to.port);
11986
- } catch (e) {
11987
- throw sendError(e);
11988
- } finally {
11989
- this.sending -= bytes.length;
11990
- this.changes.wake();
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
- return bytes.length;
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
- async pump(socket, family) {
12015
- const iterate = async () => {
12016
- for await (const message3 of socket.messages) {
12017
- if (this.closed) return;
12018
- const from = { family: "inet", host: message3.host, port: message3.port };
12019
- if ("bytes" in message3) this.deliver({ bytes: message3.bytes, from });
12020
- else this.unreachable(message3.error, from);
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
- await iterate().catch(() => void 0);
12024
- if (!this.closed) this.uplinks.delete(family);
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/net/datagram-wire.ts
15856
- function encodeReceived(got) {
15857
- const host = new TextEncoder().encode(got.host);
15858
- const out = new Uint8Array(4 + host.length + got.bytes.length);
15859
- const view2 = new DataView(out.buffer);
15860
- view2.setUint8(0, got.truncated ? 1 : 0);
15861
- view2.setUint16(1, got.port);
15862
- view2.setUint8(3, host.length);
15863
- out.set(host, 4);
15864
- out.set(got.bytes, 4 + host.length);
15865
- return out;
15866
- }
15867
-
15868
- // src/kernel/socket-syscalls.ts
15869
- var SOCKET_OPS = [
15870
- "sock-open",
15871
- "sock-pair",
15872
- "sock-bind",
15873
- "sock-listen",
15874
- "sock-accept",
15875
- "sock-connect",
15876
- "sock-shutdown",
15877
- "sock-name",
15878
- "sock-getopt",
15879
- "sock-setopt",
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 KernelDgram) throw new KernelError("EOPNOTSUPP");
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 (!(file instanceof KernelDgram)) throw new KernelError("EOPNOTSUPP");
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
- if (req.type === "dgram" && req.domain !== "inet") throw new KernelError("EPROTONOSUPPORT");
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 KernelDgram ? "inet" : socket.domain));
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 instanceof KernelDgram ? "socket" : kernelFdKind(file),
17816
- ...file instanceof KernelDgram ? { dgram: true } : {},
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 instanceof KernelDgram ? "socket" : kernelFdKind(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,