@ai-ecoverse/slicc-kernel 1.158.1 → 1.159.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
@@ -991,6 +991,9 @@ var KernelPipe = class {
991
991
  readers = 0;
992
992
  writers = 0;
993
993
  waiters = [];
994
+ pushed = 0;
995
+ taken = 0;
996
+ marks = [];
994
997
  capacity;
995
998
  constructor(capacity = PIPE_CAPACITY) {
996
999
  this.capacity = capacity;
@@ -1021,6 +1024,7 @@ var KernelPipe = class {
1021
1024
  if (this.readers === 0) {
1022
1025
  this.chunks = [];
1023
1026
  this.size = 0;
1027
+ this.dropMarks(() => true);
1024
1028
  }
1025
1029
  this.wake();
1026
1030
  }
@@ -1033,10 +1037,59 @@ var KernelPipe = class {
1033
1037
  if (this.writers === 0) return new Uint8Array(0);
1034
1038
  await this.changed(signal);
1035
1039
  }
1036
- const out = this.take(Math.min(max, this.size));
1040
+ const out = this.take(this.bounded(Math.min(max, this.size)));
1041
+ this.dropMarks((mark) => mark.at < this.taken);
1037
1042
  this.wake();
1038
1043
  return out;
1039
1044
  }
1045
+ get inFlight() {
1046
+ return this.marks.reduce((sum, mark) => sum + mark.count, 0);
1047
+ }
1048
+ async receive(max, nonblock, signal) {
1049
+ while (this.size === 0) {
1050
+ if (this.writers === 0) return { bytes: new Uint8Array(0), marks: [] };
1051
+ if (nonblock) throw new PipeError("EAGAIN");
1052
+ await this.changed(signal);
1053
+ }
1054
+ const marks = this.marks.filter((mark) => mark.at === this.taken);
1055
+ this.marks = this.marks.filter((mark) => mark.at !== this.taken);
1056
+ const bytes = this.take(this.bounded(Math.min(max, this.size)));
1057
+ this.dropMarks((mark) => mark.at < this.taken);
1058
+ this.wake();
1059
+ return { bytes, marks };
1060
+ }
1061
+ async writeMarked(bytes, mark, nonblock, signal) {
1062
+ while (this.readers > 0 && this.size >= this.capacity) {
1063
+ if (nonblock) throw new PipeError("EAGAIN");
1064
+ await this.changed(signal);
1065
+ }
1066
+ if (this.readers === 0) throw new PipeError("EPIPE");
1067
+ const before = this.pushed;
1068
+ const made2 = mark(before);
1069
+ this.marks.push(made2);
1070
+ try {
1071
+ const n = await this.write(bytes, signal);
1072
+ this.orphan(made2, before);
1073
+ return n;
1074
+ } catch (err) {
1075
+ this.orphan(made2, before);
1076
+ throw err;
1077
+ }
1078
+ }
1079
+ orphan(made2, before) {
1080
+ if (this.pushed !== before) return;
1081
+ this.dropMarks((mark) => mark === made2);
1082
+ }
1083
+ bounded(n) {
1084
+ const next3 = this.marks.find((mark) => mark.at > this.taken);
1085
+ return next3 ? Math.min(n, next3.at - this.taken) : n;
1086
+ }
1087
+ dropMarks(gone) {
1088
+ const dropped2 = this.marks.filter(gone);
1089
+ if (dropped2.length === 0) return;
1090
+ this.marks = this.marks.filter((mark) => !gone(mark));
1091
+ for (const mark of dropped2) mark.drop();
1092
+ }
1040
1093
  async peek(max, signal) {
1041
1094
  while (this.size === 0) {
1042
1095
  if (this.writers === 0) return new Uint8Array(0);
@@ -1069,6 +1122,7 @@ var KernelPipe = class {
1069
1122
  const n = Math.min(room, bytes.length - offset);
1070
1123
  this.chunks.push(bytes.slice(offset, offset + n));
1071
1124
  this.size += n;
1125
+ this.pushed += n;
1072
1126
  offset += n;
1073
1127
  this.wake();
1074
1128
  }
@@ -1086,6 +1140,7 @@ var KernelPipe = class {
1086
1140
  else this.chunks[0] = head.subarray(count2);
1087
1141
  }
1088
1142
  this.size -= n;
1143
+ this.taken += n;
1089
1144
  return out;
1090
1145
  }
1091
1146
  changed(signal) {
@@ -1962,6 +2017,30 @@ var KernelSocket = class _KernelSocket {
1962
2017
  if (bytes.length === 0 && this.reset) throw this.reset;
1963
2018
  return bytes;
1964
2019
  }
2020
+ rightsLink() {
2021
+ const link2 = this.connection();
2022
+ if (this.domain !== "unix" || this.switch || this.served) throw new KernelError("EOPNOTSUPP");
2023
+ if (this.refused) throw this.refused;
2024
+ return link2;
2025
+ }
2026
+ sendRights(bytes, mark, nonblock, signal) {
2027
+ const { tx } = this.rightsLink();
2028
+ if (this.writeShut) throw new KernelError("EPIPE");
2029
+ return pipeCall(() => tx.writeMarked(bytes, (at) => mark(at, tx.inFlight), nonblock, signal));
2030
+ }
2031
+ async receiveRights(max, nonblock, signal) {
2032
+ const { rx } = this.rightsLink();
2033
+ if (this.readShut || max <= 0) return { bytes: EMPTY, marks: [] };
2034
+ const got = await pipeCall(() => rx.receive(max, nonblock, signal));
2035
+ if (this.refused) {
2036
+ for (const mark of got.marks) mark.drop();
2037
+ throw this.refused;
2038
+ }
2039
+ return got;
2040
+ }
2041
+ get secured() {
2042
+ return this.served || this.tlsDial || this.serving !== void 0 || !!this.switch?.upgraded;
2043
+ }
1965
2044
  async write(bytes, signal) {
1966
2045
  const { tx } = this.connection();
1967
2046
  if (this.refused) throw this.refused;
@@ -2103,11 +2182,13 @@ var KernelSocket = class _KernelSocket {
2103
2182
  switch;
2104
2183
  connectSecure(addr, route2, secure2) {
2105
2184
  if (this.state !== "open") throw new KernelError("EISCONN");
2185
+ this.tlsDial = true;
2106
2186
  return this.dial(addr, route2, secure2);
2107
2187
  }
2108
2188
  serving;
2109
2189
  pending;
2110
2190
  served = false;
2191
+ tlsDial = false;
2111
2192
  get loopbackLinked() {
2112
2193
  return this.state === "connected" && !this.switch;
2113
2194
  }
@@ -3588,7 +3669,7 @@ function satisfies(version, range2) {
3588
3669
  }
3589
3670
 
3590
3671
  // src/version.ts
3591
- var KERNEL_VERSION = true ? "1.158.1" : "0.0.0-dev";
3672
+ var KERNEL_VERSION = true ? "1.159.0" : "0.0.0-dev";
3592
3673
  var OS_RELEASE = "6.0.0-slicc";
3593
3674
  function procVersion() {
3594
3675
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -10738,8 +10819,8 @@ async function guarded(entry, path, req) {
10738
10819
  const paths = await guard(g, path, req, entry.cwd);
10739
10820
  return { paths };
10740
10821
  } catch (err) {
10741
- const refusal2 = err.code === "EACCES";
10742
- const refused3 = req.op === "exists" && refusal2 ? json2(false) : toErrno(err);
10822
+ const refusal3 = err.code === "EACCES";
10823
+ const refused3 = req.op === "exists" && refusal3 ? json2(false) : toErrno(err);
10743
10824
  return { refused: refused3 };
10744
10825
  }
10745
10826
  }
@@ -17516,19 +17597,6 @@ var KernelDgram = class {
17516
17597
  }
17517
17598
  };
17518
17599
 
17519
- // src/kernel/net/datagram-wire.ts
17520
- function encodeReceived(got) {
17521
- const host = new TextEncoder().encode(got.host);
17522
- const out = new Uint8Array(4 + host.length + got.bytes.length);
17523
- const view2 = new DataView(out.buffer);
17524
- view2.setUint8(0, (got.truncated ? 1 : 0) | (got.unix ? 2 : 0));
17525
- view2.setUint16(1, got.port);
17526
- view2.setUint8(3, host.length);
17527
- out.set(host, 4);
17528
- out.set(got.bytes, 4 + host.length);
17529
- return out;
17530
- }
17531
-
17532
17600
  // src/kernel/net/sealed-binding.ts
17533
17601
  var HASH_OF_SIGNATURE = {
17534
17602
  "1.2.840.113549.1.1.4": "SHA-256",
@@ -19248,6 +19316,120 @@ function isDatagram(file) {
19248
19316
  return file instanceof KernelDgram || file instanceof UnixDgram;
19249
19317
  }
19250
19318
 
19319
+ // src/kernel/fd-rights.ts
19320
+ var RIGHTS_MAX = 253;
19321
+ var RIGHTS_IN_FLIGHT = 1024;
19322
+ var RECEIVE_MAX = 1024 * 1024;
19323
+ var CTRUNC = 1;
19324
+ var RightsMark = class {
19325
+ at;
19326
+ passed;
19327
+ constructor(at, passed) {
19328
+ this.at = at;
19329
+ this.passed = passed;
19330
+ }
19331
+ get count() {
19332
+ return this.passed.length;
19333
+ }
19334
+ drop() {
19335
+ for (const { file } of this.passed) void Promise.resolve(file.release()).catch(() => void 0);
19336
+ }
19337
+ };
19338
+ function refusal(file) {
19339
+ if (file instanceof KernelSocket) {
19340
+ if (file.domain === "unix") return "EOPNOTSUPP";
19341
+ return file.secured ? "EPERM" : void 0;
19342
+ }
19343
+ if (file instanceof UnixDgram) return "EOPNOTSUPP";
19344
+ if (file instanceof EpollFile || file instanceof TlsContext) return "EPERM";
19345
+ return file.sealed || file.clipboard || file.embedder ? "EPERM" : void 0;
19346
+ }
19347
+ function carrierAt(fds, fd) {
19348
+ const file = fds.get(fd).file;
19349
+ if (!(file instanceof KernelSocket)) {
19350
+ throw new KernelError(file instanceof UnixDgram ? "EOPNOTSUPP" : "ENOTSOCK");
19351
+ }
19352
+ return file;
19353
+ }
19354
+ async function sendRights(fds, req, signal) {
19355
+ const carrier = carrierAt(fds, req.fd);
19356
+ if (req.nonblock && !carrier.poll().writable) throw new KernelError("EAGAIN");
19357
+ if (req.nonblock) signal = AbortSignal.abort();
19358
+ if (req.fds.length === 0) return carrier.write(req.body, signal);
19359
+ if (req.fds.length > RIGHTS_MAX || req.body.length === 0) throw new KernelError("EINVAL");
19360
+ const passed = req.fds.map((fd) => ({ file: fds.get(fd), status: fds.statusFlags(fd) }));
19361
+ for (const { file } of passed) {
19362
+ const errno3 = refusal(file.file);
19363
+ if (errno3) throw new KernelError(errno3, "this descriptor cannot be passed");
19364
+ }
19365
+ for (const { file } of passed) file.retain();
19366
+ let handed2 = false;
19367
+ const mark = (at, inFlight) => {
19368
+ if (inFlight + passed.length > RIGHTS_IN_FLIGHT) {
19369
+ throw new KernelError("EMFILE", "too many descriptors in flight");
19370
+ }
19371
+ handed2 = true;
19372
+ return new RightsMark(at, passed);
19373
+ };
19374
+ try {
19375
+ return await carrier.sendRights(req.body, mark, req.nonblock, signal);
19376
+ } catch (err) {
19377
+ if (!handed2) new RightsMark(0, passed).drop();
19378
+ throw err;
19379
+ }
19380
+ }
19381
+ function installed(fds, passed, cloexec) {
19382
+ let fd;
19383
+ try {
19384
+ fd = fds.install(passed.file);
19385
+ } catch {
19386
+ return void 0;
19387
+ }
19388
+ if (passed.status !== void 0) fds.setStatusFlags(fd, passed.status);
19389
+ if (cloexec) fds.setCloseOnExec(fd);
19390
+ return fd;
19391
+ }
19392
+ function encodeRights(bytes, got, truncated2) {
19393
+ const out = new Uint8Array(8 + got.length * 4 + bytes.length);
19394
+ const view2 = new DataView(out.buffer);
19395
+ view2.setUint32(0, got.length, true);
19396
+ view2.setUint32(4, truncated2 ? CTRUNC : 0, true);
19397
+ for (const [i, fd] of got.entries()) view2.setUint32(8 + i * 4, fd, true);
19398
+ out.set(bytes, 8 + got.length * 4);
19399
+ return out;
19400
+ }
19401
+ async function receiveRights(fds, req, signal) {
19402
+ const carrier = carrierAt(fds, req.fd);
19403
+ const { bytes, marks } = await carrier.receiveRights(
19404
+ Math.min(req.max, RECEIVE_MAX),
19405
+ req.nonblock,
19406
+ signal
19407
+ );
19408
+ const got = [];
19409
+ let truncated2 = false;
19410
+ for (const mark of marks) {
19411
+ for (const passed of mark.passed) {
19412
+ const fd = installed(fds, passed, req.cloexec);
19413
+ if (fd === void 0) truncated2 = true;
19414
+ else got.push(fd);
19415
+ }
19416
+ }
19417
+ return encodeRights(bytes, got, truncated2);
19418
+ }
19419
+
19420
+ // src/kernel/net/datagram-wire.ts
19421
+ function encodeReceived(got) {
19422
+ const host = new TextEncoder().encode(got.host);
19423
+ const out = new Uint8Array(4 + host.length + got.bytes.length);
19424
+ const view2 = new DataView(out.buffer);
19425
+ view2.setUint8(0, (got.truncated ? 1 : 0) | (got.unix ? 2 : 0));
19426
+ view2.setUint16(1, got.port);
19427
+ view2.setUint8(3, host.length);
19428
+ out.set(host, 4);
19429
+ out.set(got.bytes, 4 + host.length);
19430
+ return out;
19431
+ }
19432
+
19251
19433
  // src/kernel/socket-syscalls.ts
19252
19434
  var SOCKET_OPS = [
19253
19435
  "sock-open",
@@ -19258,6 +19440,8 @@ var SOCKET_OPS = [
19258
19440
  "sock-connect",
19259
19441
  "sock-shutdown",
19260
19442
  "sock-reset",
19443
+ "sock-sendmsg",
19444
+ "sock-recvmsg",
19261
19445
  "sock-name",
19262
19446
  "sock-getopt",
19263
19447
  "sock-setopt",
@@ -19328,6 +19512,10 @@ async function socketSyscall(req, proc) {
19328
19512
  case "sock-reset":
19329
19513
  socketAt(fds, req.fd).resetOnClose();
19330
19514
  return ok3();
19515
+ case "sock-sendmsg":
19516
+ return ok3(await sendRights(fds, req, proc.blocking()));
19517
+ case "sock-recvmsg":
19518
+ return { ok: true, kind: "bytes", bytes: await receiveRights(fds, req, proc.blocking()) };
19331
19519
  case "sock-name": {
19332
19520
  const socket = anySocketAt(fds, req.fd);
19333
19521
  const addr = req.peer ? socket.peer : socket.local;
@@ -33124,7 +33312,7 @@ function allows(policy, port) {
33124
33312
  if (Array.isArray(policy)) return policy.includes(port);
33125
33313
  return policy === true && !DEVTOOLS_PORTS.includes(port);
33126
33314
  }
33127
- function refusal(url, address, place) {
33315
+ function refusal2(url, address, place) {
33128
33316
  const where = `${address}:${portOf(url)}`;
33129
33317
  const why = place === "link-local" ? `nodeTransport refuses link-local ${where}` : `nodeTransport refuses the host's loopback ${where} (see nodeTransport({ hostLoopback }))`;
33130
33318
  return Object.assign(new Error(why), { status: 403, code: "EACCES" });
@@ -33146,7 +33334,7 @@ async function checkDestination(target, policy, resolve2 = resolveHost) {
33146
33334
  const place = placeOf(address);
33147
33335
  if (!place) continue;
33148
33336
  if (place === "loopback" && allows(policy, portOf(url))) continue;
33149
- throw refusal(url, address, place);
33337
+ throw refusal2(url, address, place);
33150
33338
  }
33151
33339
  }
33152
33340
  function guarded2(check, signal) {