@ai-ecoverse/slicc-kernel 1.154.3 → 1.155.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 +1 -1
- package/dist/kernel-worker.js +30 -4
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-process-worker.js +9 -2
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +30 -4
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +9 -2
- package/dist/process-worker.js.map +2 -2
- package/dist/types/kernel/socket-syscalls.d.ts +3 -0
- package/dist/types/kernel/socket.d.ts +6 -0
- package/dist/types/process/js/js-net.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -453,7 +453,7 @@ The module's default export (or its `main` export) is called with a context and
|
|
|
453
453
|
- `wait(pid, { untraced })` resolves with `{ status }` once a child ends, or `{ status: 128 + signal, signal }` when a signal ended it, without blocking the program; with `untraced: true` it also resolves when the child stops, with `{ status: 128 + signal, signal, stopped: true }`, as `waitpid` with `WUNTRACED` (a child's `wait({ untraced })` is the same), and options that aren't an object are `EINVAL`; `kill(pid, signal)` signals any process, by number or as `'SIGTERM'` (the default);
|
|
454
454
|
- `sudo(args)`, what the [`sudo`](#sudo) command calls: `args` are its arguments after `sudo`, and it resolves with `{ pid }`, the command the kernel started as the program's child, to `wait` for; `{ run }`, an argv to run as the caller (with `users: 'off'`); `{ list }`, the text of `sudo -l`; or `{ error, errno }`, the message to print;
|
|
455
455
|
- `crontab({ action, user?, text? })`, what the [`crontab`](#cron) command calls: `action` is `'list'`, `'remove'` or `'install'` (with the table as `text`), on the caller's own table or, for an effective uid of 0, on `user`'s. It resolves with `{ text }` (the table for `list`, `''` otherwise) or `{ error }`, the message to print. A malformed call is `EINVAL`;
|
|
456
|
-
- `net`: `listen({ port, host, backlog })` and `connect({ host, port, signal })` (`host` defaults to `127.0.0.1`) on the kernel's loopback, the same sockets WASIX programs use, so a JS server is reached by other processes, by the page as `<port>.kernel.localhost` (`loopbackFetch`, `dial`) and by attached clients. A listener has its `port` (as bound, so port `0` picks a free one), `accept({ signal })`, `close()` and `for await` over its connections. A connection has `local` and `remote` addresses, `readable` and `writable` web streams (closing the writable shuts down the sending side, so the peer reads the end), and `
|
|
456
|
+
- `net`: `listen({ port, host, backlog })` and `connect({ host, port, signal })` (`host` defaults to `127.0.0.1`) on the kernel's loopback, the same sockets WASIX programs use, so a JS server is reached by other processes, by the page as `<port>.kernel.localhost` (`loopbackFetch`, `dial`) and by attached clients. A listener has its `port` (as bound, so port `0` picks a free one), `accept({ signal })`, `close()` and `for await` over its connections. A connection has `local` and `remote` addresses, `readable` and `writable` web streams (closing the writable shuts down the sending side, so the peer reads the end), `close()`, and `reset()`, which closes it with an RST as Node's `resetAndDestroy()` does ([#1530](https://github.com/ai-ecoverse/slicc-kernel/issues/1530)): on the kernel's loopback, the peer's pending and later reads and its writes fail with `ECONNRESET` instead of seeing the end, and bytes still in flight to it are dropped. A TLS connection (`secure()`, a `tls` connect on the loopback) resets the same way. On an uplink connection `reset()` closes at once with a FIN, as the transport can't send an RST: bytes still buffered for the peer are discarded instead of sent. The loopback is IPv4 (`127.0.0.1` by default, or `0.0.0.0`), so an IPv6 host such as `::1` fails with `EADDRNOTAVAIL` for both `listen` and `connect`, and binding and connecting fail as they would for a WASIX program (`EADDRINUSE`, `ECONNREFUSED`, `EADDRNOTAVAIL`). `sync.net.listen` takes the same options and gives the same listener, bound and listening when it returns, so its `port` is known at once, as Node's `listen()` needs ([#1398](https://github.com/ai-ecoverse/slicc-kernel/issues/1398)); it needs the sync lane. A blocked accept, read or write waits without holding anything in the kernel, so aborting it or closing the socket leaves nothing behind. A write to a connection the peer closed fails with `EPIPE` and no `SIGPIPE`;
|
|
457
457
|
- `net.connect({ host, port, tls: { servername, alpn, rejectUnauthorized, ca, path, cert, key, passphrase, sni, checkHostname, keylog } })` takes one of two paths. By default it's **A1, TLS through the transport** ([#914](https://github.com/ai-ecoverse/slicc-kernel/issues/914)), described first below. For a destination the uplink routes it can also be **A2, a TLS handshake in the kernel** ([#922](https://github.com/ai-ecoverse/slicc-kernel/issues/922)), described after it. `conn.tls.path` (`'transport'` or `'kernel'`) and `conn.tls.substitutes` say which one was taken.
|
|
458
458
|
- **What it does:** there's no handshake in the kernel. The connection carries plain HTTP/1.1 (and WebSocket upgrades) to the realm proxy's HTTP path for the origin `https://<servername or host>[:port]`, exactly as a `CONNECT` through `127.0.0.1:3128` does after the kernel terminates its TLS. The transport (the page's `fetch` or WebSocket, or the uplink's) makes the real TLS connection and verifies it. So `https.request` over a socket, keep-alive agents, `agent-base` and `wss://` clients work with the transport's semantics. That includes sealed placeholders in headers, which reach the transport exactly as from `ctx.fetch`.
|
|
459
459
|
- **The `tls` property:** the connection's `tls` is `{ path: 'transport', substitutes: true, protocol: 'transport', alpnProtocol: 'http/1.1', authorized: true, servername }`. `authorized` means the transport verified the server. There's no peer certificate chain and no TLS version of the kernel's own, so don't read it as a real handshake's result.
|
package/dist/kernel-worker.js
CHANGED
|
@@ -6097,8 +6097,8 @@ function link(a, b) {
|
|
|
6097
6097
|
pipe.openRead();
|
|
6098
6098
|
pipe.openWrite();
|
|
6099
6099
|
}
|
|
6100
|
-
a.attach({ rx: ba, tx: ab });
|
|
6101
|
-
b.attach({ rx: ab, tx: ba });
|
|
6100
|
+
a.attach({ rx: ba, tx: ab, peer: b });
|
|
6101
|
+
b.attach({ rx: ab, tx: ba, peer: a });
|
|
6102
6102
|
}
|
|
6103
6103
|
var SERVE_CHUNK = 64 * 1024;
|
|
6104
6104
|
var NEVER_ABORTED = new AbortController().signal;
|
|
@@ -6110,6 +6110,8 @@ var KernelSocket = class _KernelSocket {
|
|
|
6110
6110
|
dialing;
|
|
6111
6111
|
failed;
|
|
6112
6112
|
reset;
|
|
6113
|
+
abortive = false;
|
|
6114
|
+
refused;
|
|
6113
6115
|
local;
|
|
6114
6116
|
peer;
|
|
6115
6117
|
peerCred;
|
|
@@ -6146,20 +6148,25 @@ var KernelSocket = class _KernelSocket {
|
|
|
6146
6148
|
}
|
|
6147
6149
|
async read(max, signal) {
|
|
6148
6150
|
const { rx } = this.connection();
|
|
6151
|
+
if (this.refused) throw this.refused;
|
|
6149
6152
|
if (this.readShut || max <= 0) return new Uint8Array(0);
|
|
6150
6153
|
const bytes = await pipeCall(() => rx.read(max, signal));
|
|
6154
|
+
if (this.refused) throw this.refused;
|
|
6151
6155
|
if (bytes.length === 0 && this.reset) throw this.reset;
|
|
6152
6156
|
return bytes;
|
|
6153
6157
|
}
|
|
6154
6158
|
async peek(max, signal) {
|
|
6155
6159
|
const { rx } = this.connection();
|
|
6160
|
+
if (this.refused) throw this.refused;
|
|
6156
6161
|
if (this.readShut || max <= 0) return new Uint8Array(0);
|
|
6157
6162
|
const bytes = await pipeCall(() => rx.peek(max, signal));
|
|
6163
|
+
if (this.refused) throw this.refused;
|
|
6158
6164
|
if (bytes.length === 0 && this.reset) throw this.reset;
|
|
6159
6165
|
return bytes;
|
|
6160
6166
|
}
|
|
6161
6167
|
async write(bytes, signal) {
|
|
6162
6168
|
const { tx } = this.connection();
|
|
6169
|
+
if (this.refused) throw this.refused;
|
|
6163
6170
|
if (this.writeShut) throw new KernelError("EPIPE");
|
|
6164
6171
|
if (this.reset?.code === "EPROTO") throw this.reset;
|
|
6165
6172
|
return pipeCall(() => tx.write(bytes, signal));
|
|
@@ -6346,10 +6353,11 @@ var KernelSocket = class _KernelSocket {
|
|
|
6346
6353
|
handshaking = false;
|
|
6347
6354
|
signal.removeEventListener("abort", abandon);
|
|
6348
6355
|
}
|
|
6349
|
-
|
|
6356
|
+
const plain3 = uplinkLink(made2.conn, (err) => {
|
|
6350
6357
|
this.reset = err instanceof KernelError && err.code === "EPROTO" ? err : new KernelError("ECONNRESET");
|
|
6351
6358
|
this.changes.wake();
|
|
6352
6359
|
});
|
|
6360
|
+
this.link = { ...plain3, ...raw2.peer ? { peer: raw2.peer } : {} };
|
|
6353
6361
|
this.changes.wake();
|
|
6354
6362
|
return made2.info;
|
|
6355
6363
|
}
|
|
@@ -6467,8 +6475,22 @@ var KernelSocket = class _KernelSocket {
|
|
|
6467
6475
|
setOption(level, name2, value2) {
|
|
6468
6476
|
this.options.set(`${level}:${name2}`, value2);
|
|
6469
6477
|
}
|
|
6478
|
+
resetOnClose() {
|
|
6479
|
+
this.connection();
|
|
6480
|
+
this.abortive = true;
|
|
6481
|
+
}
|
|
6482
|
+
abort() {
|
|
6483
|
+
const link2 = this.link;
|
|
6484
|
+
if (link2.peer) link2.peer.resetBy();
|
|
6485
|
+
else link2.tx.closeRead();
|
|
6486
|
+
}
|
|
6487
|
+
resetBy() {
|
|
6488
|
+
this.refused ??= new KernelError("ECONNRESET");
|
|
6489
|
+
this.changes.wake();
|
|
6490
|
+
}
|
|
6470
6491
|
close() {
|
|
6471
6492
|
const was = this.state;
|
|
6493
|
+
if (this.abortive && was === "connected") this.abort();
|
|
6472
6494
|
this.state = "closed";
|
|
6473
6495
|
this.dialing?.abort(new KernelError("ECONNABORTED"));
|
|
6474
6496
|
this.dialing = void 0;
|
|
@@ -8090,7 +8112,7 @@ function satisfies(version, range2) {
|
|
|
8090
8112
|
}
|
|
8091
8113
|
|
|
8092
8114
|
// src/version.ts
|
|
8093
|
-
var KERNEL_VERSION = true ? "1.
|
|
8115
|
+
var KERNEL_VERSION = true ? "1.155.0" : "0.0.0-dev";
|
|
8094
8116
|
var OS_RELEASE = "6.0.0-slicc";
|
|
8095
8117
|
function procVersion() {
|
|
8096
8118
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -23272,6 +23294,7 @@ var SOCKET_OPS = [
|
|
|
23272
23294
|
"sock-accept",
|
|
23273
23295
|
"sock-connect",
|
|
23274
23296
|
"sock-shutdown",
|
|
23297
|
+
"sock-reset",
|
|
23275
23298
|
"sock-name",
|
|
23276
23299
|
"sock-getopt",
|
|
23277
23300
|
"sock-setopt",
|
|
@@ -23339,6 +23362,9 @@ async function socketSyscall(req, proc) {
|
|
|
23339
23362
|
case "sock-shutdown":
|
|
23340
23363
|
anySocketAt(fds, req.fd).shutdown(req.how);
|
|
23341
23364
|
return ok3();
|
|
23365
|
+
case "sock-reset":
|
|
23366
|
+
socketAt(fds, req.fd).resetOnClose();
|
|
23367
|
+
return ok3();
|
|
23342
23368
|
case "sock-name": {
|
|
23343
23369
|
const socket = anySocketAt(fds, req.fd);
|
|
23344
23370
|
const addr = req.peer ? socket.peer : socket.local;
|