@ai-ecoverse/slicc-kernel 1.148.1 → 1.149.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.
@@ -2412,7 +2412,9 @@ var init_js_kernel = __esm({
2412
2412
  "fd-open-clipboard",
2413
2413
  "net-ws-ready",
2414
2414
  "sock-tls",
2415
- "sock-tls-upgrade"
2415
+ "sock-tls-upgrade",
2416
+ "sock-tls-serve",
2417
+ "sock-tls-listen"
2416
2418
  ]);
2417
2419
  JsKernel = class {
2418
2420
  header;
@@ -7185,7 +7187,7 @@ var KERNEL_VERSION, OS_RELEASE;
7185
7187
  var init_version = __esm({
7186
7188
  "src/version.ts"() {
7187
7189
  "use strict";
7188
- KERNEL_VERSION = true ? "1.148.1" : "0.0.0-dev";
7190
+ KERNEL_VERSION = true ? "1.149.0" : "0.0.0-dev";
7189
7191
  OS_RELEASE = "6.0.0-slicc";
7190
7192
  }
7191
7193
  });
@@ -8010,22 +8012,44 @@ function caList(ca) {
8010
8012
  }
8011
8013
  return out;
8012
8014
  }
8013
- function keyText(key) {
8015
+ function keyText(key, what) {
8014
8016
  if (key instanceof Uint8Array) return toBase64(key);
8015
8017
  if (typeof key === "string") return toBase64(new TextEncoder().encode(key));
8016
- throw new JsCallError("EINVAL", "connect", "ERR_INVALID_ARG_TYPE: key must be a string or bytes");
8018
+ throw new JsCallError("EINVAL", what, "ERR_INVALID_ARG_TYPE: key must be a string or bytes");
8017
8019
  }
8018
- function clientCert(tls) {
8020
+ function serveRequest(tls) {
8021
+ const own = clientCert(tls, "listen").clientCert;
8022
+ if (!own)
8023
+ throw new JsCallError("EINVAL", "listen", "ERR_INVALID_ARG_VALUE: a server needs cert and key");
8024
+ return {
8025
+ cert: own,
8026
+ ...tls.ca !== void 0 ? { ca: caList(tls.ca) } : {},
8027
+ ...tls.requestCert ? { requestCert: true } : {},
8028
+ ...tls.rejectUnauthorized === false ? { rejectUnauthorized: false } : {},
8029
+ ...tls.alpn ? { alpn: [...tls.alpn] } : {},
8030
+ ...tls.handshakeTimeout !== void 0 ? { handshakeTimeout: tls.handshakeTimeout } : {}
8031
+ };
8032
+ }
8033
+ function servedOf(r) {
8034
+ const { authorizationError, ...rest2 } = r;
8035
+ return Object.freeze({
8036
+ ...rest2,
8037
+ path: "kernel",
8038
+ ...authorizationError ? { authorizationError } : {},
8039
+ peerCertificates: Object.freeze(r.peerCertificates.map(fromBase642))
8040
+ });
8041
+ }
8042
+ function clientCert(tls, what = "connect") {
8019
8043
  if (tls.pfx !== void 0) {
8020
- throw new JsCallError("ENOTSUP", "connect", "pfx is not supported: pass cert and key");
8044
+ throw new JsCallError("ENOTSUP", what, "pfx is not supported: pass cert and key");
8021
8045
  }
8022
8046
  if (tls.cert === void 0 && tls.key === void 0) return {};
8023
8047
  const chain3 = tls.cert === void 0 ? [] : caList(tls.cert);
8024
8048
  if (chain3.length === 0 || tls.key === void 0) {
8025
- throw new JsCallError("EINVAL", "connect", "ERR_INVALID_ARG_VALUE: cert and key go together");
8049
+ throw new JsCallError("EINVAL", what, "ERR_INVALID_ARG_VALUE: cert and key go together");
8026
8050
  }
8027
8051
  const passphrase = tls.passphrase === void 0 ? {} : { passphrase: String(tls.passphrase) };
8028
- return { clientCert: { chain: chain3, key: keyText(tls.key), ...passphrase } };
8052
+ return { clientCert: { chain: chain3, key: keyText(tls.key, what), ...passphrase } };
8029
8053
  }
8030
8054
  function tlsRequest(tls) {
8031
8055
  return {
@@ -8100,6 +8124,118 @@ function port(n) {
8100
8124
  if (!Number.isInteger(n) || n < 0 || n > 65535) throw new JsCallError("EINVAL", `port ${n}`);
8101
8125
  return n;
8102
8126
  }
8127
+ async function serveOn(kernel, conn, req, signal = NEVER) {
8128
+ const r = await secureCall(
8129
+ () => kernel.blocking({ op: "sock-tls-serve", fd: conn.fd, ...req }, signal),
8130
+ "accept"
8131
+ );
8132
+ const wire = r.ok && r.kind === "json" ? r.json : {};
8133
+ return Object.assign(Object.create(conn), { tls: servedOf(wire) });
8134
+ }
8135
+ function changeOf(waiters, signal) {
8136
+ return new Promise((resolve2) => {
8137
+ const done = () => {
8138
+ waiters.delete(done);
8139
+ signal.removeEventListener("abort", done);
8140
+ resolve2();
8141
+ };
8142
+ waiters.add(done);
8143
+ signal.addEventListener("abort", done, { once: true });
8144
+ });
8145
+ }
8146
+ function securedAccepts(plain2, serve, stop, cap) {
8147
+ const ready = [];
8148
+ const waiters = /* @__PURE__ */ new Set();
8149
+ let failure;
8150
+ let pumping = false;
8151
+ let inFlight = 0;
8152
+ const wake = () => {
8153
+ for (const w of [...waiters]) w();
8154
+ };
8155
+ const handshake = (conn) => {
8156
+ inFlight++;
8157
+ serve(conn, stop).then(
8158
+ (secured) => {
8159
+ if (stop.aborted) void secured.close();
8160
+ else ready.push(secured);
8161
+ },
8162
+ () => conn.close()
8163
+ ).finally(() => {
8164
+ inFlight--;
8165
+ wake();
8166
+ });
8167
+ };
8168
+ const pump2 = async () => {
8169
+ for (; ; ) {
8170
+ try {
8171
+ while (inFlight + ready.length >= cap) {
8172
+ stop.throwIfAborted();
8173
+ await changeOf(waiters, stop);
8174
+ }
8175
+ handshake(await plain2(stop));
8176
+ } catch (err) {
8177
+ failure = err;
8178
+ for (const left of ready.splice(0)) void left.close();
8179
+ wake();
8180
+ return;
8181
+ }
8182
+ }
8183
+ };
8184
+ return async (signal) => {
8185
+ if (!pumping) {
8186
+ pumping = true;
8187
+ void pump2();
8188
+ }
8189
+ for (; ; ) {
8190
+ if (stop.aborted) throw stop.reason;
8191
+ const next2 = ready.shift();
8192
+ if (next2) {
8193
+ wake();
8194
+ return next2;
8195
+ }
8196
+ if (failure !== void 0) throw failure;
8197
+ signal.throwIfAborted();
8198
+ await changeOf(waiters, signal);
8199
+ }
8200
+ };
8201
+ }
8202
+ function listenerOf(ops, fd, at, handshakes) {
8203
+ const { kernel, io, connection, serve } = ops;
8204
+ const stop = new AbortController();
8205
+ const acceptPlain = async (signal) => {
8206
+ for (; ; ) {
8207
+ signal.throwIfAborted();
8208
+ const r = await kernel.raw({ op: "sock-accept", fd, nonblock: true });
8209
+ if (r.ok) return connection((r.kind === "json" ? r.json : {}).fd);
8210
+ if (r.errno !== "EAGAIN") throw new JsCallError(r.errno, "accept");
8211
+ await kernel.blocking({ op: "fd-select", read: [fd], write: [], timeoutMs: -1 }, signal);
8212
+ }
8213
+ };
8214
+ const next2 = handshakes > 0 ? securedAccepts(acceptPlain, (c, s) => serve(c, { from: fd }, s), stop.signal, handshakes) : acceptPlain;
8215
+ const accept = (options = {}) => next2(AbortSignal.any([options.signal ?? NEVER, stop.signal]));
8216
+ return {
8217
+ fd,
8218
+ ...at,
8219
+ accept,
8220
+ async close() {
8221
+ stop.abort(new JsCallError("EBADF", "listener closed"));
8222
+ await io.close(fd);
8223
+ },
8224
+ async *[Symbol.asyncIterator]() {
8225
+ for (; ; ) {
8226
+ try {
8227
+ yield await accept();
8228
+ } catch (err) {
8229
+ if (stop.signal.aborted) return;
8230
+ throw err;
8231
+ }
8232
+ }
8233
+ }
8234
+ };
8235
+ }
8236
+ function capOf(options, tls) {
8237
+ return tls ? Math.max(1, Math.min(options.backlog ?? 128, HANDSHAKES_MAX)) : 0;
8238
+ }
8103
8239
  function netOps(kernel, io, sync) {
8104
8240
  const name2 = async (fd, peer) => addressOf(await kernel.json({ op: "sock-name", fd, peer }));
8105
8241
  const connection = async (fd) => {
@@ -8147,53 +8283,58 @@ function netOps(kernel, io, sync) {
8147
8283
  throw err;
8148
8284
  }
8149
8285
  };
8150
- const listener = (fd, at) => {
8151
- const stop = new AbortController();
8152
- const accept = async (options = {}) => {
8153
- const signal = AbortSignal.any([options.signal ?? NEVER, stop.signal]);
8154
- for (; ; ) {
8155
- signal.throwIfAborted();
8156
- const r = await kernel.raw({ op: "sock-accept", fd, nonblock: true });
8157
- if (r.ok) return connection((r.kind === "json" ? r.json : {}).fd);
8158
- if (r.errno !== "EAGAIN") throw new JsCallError(r.errno, "accept");
8159
- await kernel.blocking({ op: "fd-select", read: [fd], write: [], timeoutMs: -1 }, signal);
8160
- }
8161
- };
8162
- return {
8163
- fd,
8164
- ...at,
8165
- accept,
8166
- async close() {
8167
- stop.abort(new JsCallError("EBADF", "listener closed"));
8168
- await io.close(fd);
8169
- },
8170
- async *[Symbol.asyncIterator]() {
8171
- for (; ; ) {
8172
- try {
8173
- yield await accept();
8174
- } catch (err) {
8175
- if (stop.signal.aborted) return;
8176
- throw err;
8177
- }
8178
- }
8179
- }
8286
+ const serve = (conn, req, signal) => serveOn(kernel, conn, req, signal);
8287
+ const ops = { kernel, io, connection, serve };
8288
+ const listener = (fd, at, handshakes = 0) => listenerOf(ops, fd, at, handshakes);
8289
+ const connect = async (options) => {
8290
+ const signal = options.signal ?? NEVER;
8291
+ const host = options.host ?? "127.0.0.1";
8292
+ if (host.includes(":")) throw new JsCallError("EADDRNOTAVAIL", host);
8293
+ const addr = {
8294
+ family: "inet",
8295
+ host: await resolve2(host, signal),
8296
+ port: port(options.port)
8180
8297
  };
8298
+ return opened2(async (fd) => {
8299
+ const r = await kernel.raw({ op: "sock-connect", fd, addr, nonblock: true });
8300
+ if (!r.ok && r.errno !== "EINPROGRESS") throw new JsCallError(r.errno, "connect");
8301
+ await kernel.blocking({ op: "fd-select", read: [], write: [fd], timeoutMs: -1 }, signal);
8302
+ const failed5 = await kernel.json({
8303
+ op: "sock-getopt",
8304
+ fd,
8305
+ level: SOL_SOCKET2,
8306
+ name: SO_ERROR2
8307
+ });
8308
+ if (failed5 !== 0) throw new JsCallError(errnoName(failed5), "connect");
8309
+ return connection(fd);
8310
+ });
8181
8311
  };
8182
8312
  const tlsConnect = async (options, tls) => {
8313
+ const host = options.host ?? "localhost";
8314
+ if (!options.socket && LOOPBACK3.test(host)) {
8315
+ const { tls: _, ...plain2 } = options;
8316
+ const socket = await connect({ ...plain2, host });
8317
+ return tlsConnect({ ...plain2, host, socket }, tls).catch(async (err) => {
8318
+ await socket.close();
8319
+ throw err;
8320
+ });
8321
+ }
8183
8322
  const common = tlsRequest(
8184
8323
  options.socket && !tls.servername && options.host ? { ...tls, servername: options.host } : tls
8185
8324
  );
8186
- const r = await secureCall(
8187
- () => kernel.json(
8188
- options.socket ? { op: "sock-tls-upgrade", fd: options.socket.fd, ...common } : {
8325
+ const r = await secureCall(async () => {
8326
+ if (!options.socket)
8327
+ return kernel.json({
8189
8328
  op: "sock-tls",
8190
- host: options.host ?? "localhost",
8329
+ host,
8191
8330
  port: port(options.port),
8192
8331
  ...common,
8193
8332
  ...tls.path ? { path: tls.path } : {}
8194
- }
8195
- )
8196
- );
8333
+ });
8334
+ const req = { op: "sock-tls-upgrade", fd: options.socket.fd, ...common };
8335
+ const done = await kernel.blocking(req, options.signal ?? NEVER);
8336
+ return done.ok && done.kind === "json" ? done.json : void 0;
8337
+ });
8197
8338
  const session = sessionOf(r);
8198
8339
  if (options.socket) return Object.assign(Object.create(options.socket), { tls: session });
8199
8340
  return Object.assign(await connection(r.fd), { tls: session });
@@ -8223,11 +8364,14 @@ function netOps(kernel, io, sync) {
8223
8364
  const listenSync = (options = {}) => {
8224
8365
  const lane = sync;
8225
8366
  const addr = inetAt(options);
8367
+ const tls = options.tls ? serveRequest(options.tls) : void 0;
8226
8368
  const fd = lane.json({ op: "sock-open", domain: "inet" });
8227
8369
  try {
8228
8370
  lane.call({ op: "sock-bind", fd, addr });
8229
8371
  lane.call({ op: "sock-listen", fd, backlog: options.backlog ?? 128 });
8230
- return listener(fd, addressOf(lane.json({ op: "sock-name", fd, peer: false })));
8372
+ if (tls) lane.call({ op: "sock-tls-listen", fd, ...tls });
8373
+ const at = addressOf(lane.json({ op: "sock-name", fd, peer: false }));
8374
+ return listener(fd, at, capOf(options, tls));
8231
8375
  } catch (err) {
8232
8376
  lane.raw({ op: "fd-close", fd });
8233
8377
  throw err;
@@ -8236,40 +8380,28 @@ function netOps(kernel, io, sync) {
8236
8380
  return {
8237
8381
  sync: { listen: listenSync },
8238
8382
  resolve: lookup2,
8239
- listen: (options = {}) => opened2(async (fd) => {
8240
- const addr = inetAt(options);
8241
- await kernel.call({ op: "sock-bind", fd, addr });
8242
- await kernel.call({ op: "sock-listen", fd, backlog: options.backlog ?? 128 });
8243
- return listener(fd, await name2(fd, false));
8244
- }),
8245
- connect: async (options) => {
8246
- const signal = options.signal ?? NEVER;
8247
- signal.throwIfAborted();
8248
- if (options.tls) return tlsConnect(options, options.tls);
8249
- const host = options.host ?? "127.0.0.1";
8250
- if (host.includes(":")) throw new JsCallError("EADDRNOTAVAIL", host);
8251
- const addr = {
8252
- family: "inet",
8253
- host: await resolve2(host, signal),
8254
- port: port(options.port)
8255
- };
8383
+ listen: async (options = {}) => {
8384
+ const tls = options.tls ? serveRequest(options.tls) : void 0;
8256
8385
  return opened2(async (fd) => {
8257
- const r = await kernel.raw({ op: "sock-connect", fd, addr, nonblock: true });
8258
- if (!r.ok && r.errno !== "EINPROGRESS") throw new JsCallError(r.errno, "connect");
8259
- await kernel.blocking({ op: "fd-select", read: [], write: [fd], timeoutMs: -1 }, signal);
8260
- const failed5 = await kernel.json({
8261
- op: "sock-getopt",
8262
- fd,
8263
- level: SOL_SOCKET2,
8264
- name: SO_ERROR2
8265
- });
8266
- if (failed5 !== 0) throw new JsCallError(errnoName(failed5), "connect");
8267
- return connection(fd);
8386
+ const addr = inetAt(options);
8387
+ await kernel.call({ op: "sock-bind", fd, addr });
8388
+ await kernel.call({ op: "sock-listen", fd, backlog: options.backlog ?? 128 });
8389
+ if (tls)
8390
+ await secureCall(() => kernel.call({ op: "sock-tls-listen", fd, ...tls }), "listen");
8391
+ return listener(fd, await name2(fd, false), capOf(options, tls));
8268
8392
  });
8393
+ },
8394
+ secure: async (conn, tls) => {
8395
+ if (tls.server !== true) return tlsConnect({ socket: conn }, tls);
8396
+ return serve(conn, serveRequest(tls));
8397
+ },
8398
+ connect: (options) => {
8399
+ (options.signal ?? NEVER).throwIfAborted();
8400
+ return options.tls ? tlsConnect(options, options.tls) : connect(options);
8269
8401
  }
8270
8402
  };
8271
8403
  }
8272
- var PEM, TLS_CODE, ALERT, SHUT_RD, SHUT_WR, IPV4, NEVER, SOL_SOCKET2, SO_ERROR2;
8404
+ var PEM, TLS_CODE, ALERT, SHUT_RD, SHUT_WR, LOOPBACK3, IPV4, NEVER, SOL_SOCKET2, SO_ERROR2, HANDSHAKES_MAX;
8273
8405
  var init_js_net = __esm({
8274
8406
  "src/process/js/js-net.ts"() {
8275
8407
  "use strict";
@@ -8280,10 +8412,12 @@ var init_js_net = __esm({
8280
8412
  ALERT = / \(alert (\d+)\)$/;
8281
8413
  SHUT_RD = 0;
8282
8414
  SHUT_WR = 1;
8415
+ LOOPBACK3 = /^(localhost|127\.\d{1,3}\.\d{1,3}\.\d{1,3})$/;
8283
8416
  IPV4 = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
8284
8417
  NEVER = new AbortController().signal;
8285
8418
  SOL_SOCKET2 = 1;
8286
8419
  SO_ERROR2 = 4;
8420
+ HANDSHAKES_MAX = 64;
8287
8421
  }
8288
8422
  });
8289
8423