@ai-ecoverse/slicc-kernel 1.95.2 → 1.96.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 +19 -2
- package/dist/index.js +71 -8
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +556 -178
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +710 -604
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +581 -218
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +783 -677
- package/dist/process-worker.js.map +4 -4
- package/dist/testing.js +45 -1
- package/dist/testing.js.map +2 -2
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -3265,6 +3265,149 @@ function wasiErrno(code) {
|
|
|
3265
3265
|
return WASI_ERRNO[code] ?? E.IO;
|
|
3266
3266
|
}
|
|
3267
3267
|
|
|
3268
|
+
// src/kernel/net/loopback-names.ts
|
|
3269
|
+
var HOST_LOOPBACK = "host.slicc.internal";
|
|
3270
|
+
var HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
|
|
3271
|
+
var PAGE_LOOPBACK = "kernel.localhost";
|
|
3272
|
+
var PAGE_LOOPBACK_URL = `http://{port}.${PAGE_LOOPBACK}`;
|
|
3273
|
+
function toHostLoopback(href) {
|
|
3274
|
+
const url = new URL(href);
|
|
3275
|
+
if (url.hostname.replace(/\.$/, "").toLowerCase() !== HOST_LOOPBACK) return href;
|
|
3276
|
+
url.hostname = "127.0.0.1";
|
|
3277
|
+
return url.href;
|
|
3278
|
+
}
|
|
3279
|
+
var LOOPBACK_V4 = /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
3280
|
+
var LOOPBACK_V6 = /* @__PURE__ */ new Set(["::1", "::", "0:0:0:0:0:0:0:1"]);
|
|
3281
|
+
var MAPPED_V4 = /^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/;
|
|
3282
|
+
var KERNEL_PORT = /^(\d{1,5})\.kernel\.localhost$/;
|
|
3283
|
+
var SCHEMES = {
|
|
3284
|
+
"http:": 80,
|
|
3285
|
+
"ws:": 80,
|
|
3286
|
+
"https:": 443,
|
|
3287
|
+
"wss:": 443
|
|
3288
|
+
};
|
|
3289
|
+
function isKernelLoopbackHost(hostname) {
|
|
3290
|
+
const host = hostname.replace(/^\[(.*)\]$/, "$1").replace(/\.$/, "").toLowerCase();
|
|
3291
|
+
return host === "localhost" || host.endsWith(".localhost") || host === "0.0.0.0" || LOOPBACK_V4.test(host) || LOOPBACK_V6.has(host) || MAPPED_V4.test(host);
|
|
3292
|
+
}
|
|
3293
|
+
function kernelLoopbackPort(href) {
|
|
3294
|
+
let url;
|
|
3295
|
+
try {
|
|
3296
|
+
url = new URL(href);
|
|
3297
|
+
} catch {
|
|
3298
|
+
return void 0;
|
|
3299
|
+
}
|
|
3300
|
+
const fallback = SCHEMES[url.protocol];
|
|
3301
|
+
if (fallback === void 0 || !isKernelLoopbackHost(url.hostname)) return void 0;
|
|
3302
|
+
const named = KERNEL_PORT.exec(url.hostname.replace(/\.$/, "").toLowerCase())?.[1];
|
|
3303
|
+
const port = Number(named ?? (url.port || fallback));
|
|
3304
|
+
return port >= 1 && port <= 65535 ? port : void 0;
|
|
3305
|
+
}
|
|
3306
|
+
var DEFAULT_HOSTNAME = "slicc";
|
|
3307
|
+
var HOSTNAME_ADDRESS = "127.0.1.1";
|
|
3308
|
+
var LIBC_HOSTNAMES = ["emscripten", "wasmer.sh"];
|
|
3309
|
+
var LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;
|
|
3310
|
+
function reserved(name2) {
|
|
3311
|
+
const lower = name2.toLowerCase();
|
|
3312
|
+
return lower === "localhost" || lower.endsWith(".localhost") || lower === HOST_LOOPBACK || lower === "wasmer.sh" || /^\d+(\.\d+){3}$/.test(lower);
|
|
3313
|
+
}
|
|
3314
|
+
function isHostname(name2) {
|
|
3315
|
+
if (typeof name2 !== "string" || name2.length > 253 || reserved(name2)) return false;
|
|
3316
|
+
return name2.split(".").every((l) => LABEL.test(l));
|
|
3317
|
+
}
|
|
3318
|
+
function ownNames(hostname) {
|
|
3319
|
+
return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3322
|
+
// src/kernel/net/routes.ts
|
|
3323
|
+
var HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join(".");
|
|
3324
|
+
function ipv4Bytes(text) {
|
|
3325
|
+
const parts2 = text.split(".");
|
|
3326
|
+
if (parts2.length !== 4 || !parts2.every((p) => /^\d{1,3}$/.test(p))) return void 0;
|
|
3327
|
+
const bytes = parts2.map(Number);
|
|
3328
|
+
return bytes.every((b) => b <= 255) ? bytes : void 0;
|
|
3329
|
+
}
|
|
3330
|
+
function ipv6Groups(text) {
|
|
3331
|
+
if (!text.includes(":")) return void 0;
|
|
3332
|
+
let canonical;
|
|
3333
|
+
try {
|
|
3334
|
+
canonical = new URL(`http://[${text}]/`).hostname.slice(1, -1);
|
|
3335
|
+
} catch {
|
|
3336
|
+
return void 0;
|
|
3337
|
+
}
|
|
3338
|
+
const [head, tail] = canonical.split("::");
|
|
3339
|
+
const part = (s) => s ? s.split(":").map((h) => Number.parseInt(h, 16)) : [];
|
|
3340
|
+
const front = part(head);
|
|
3341
|
+
const back = part(tail);
|
|
3342
|
+
return tail === void 0 ? front : [...front, ...new Array(8 - front.length - back.length).fill(0), ...back];
|
|
3343
|
+
}
|
|
3344
|
+
function toBits(values, width) {
|
|
3345
|
+
return values.reduce((acc, v) => acc << BigInt(width) | BigInt(v), 0n);
|
|
3346
|
+
}
|
|
3347
|
+
function addressBits(host) {
|
|
3348
|
+
const v4 = ipv4Bytes(host);
|
|
3349
|
+
if (v4) return { v6: false, bits: toBits(v4, 8) };
|
|
3350
|
+
const v6 = ipv6Groups(host);
|
|
3351
|
+
return v6 ? { v6: true, bits: toBits(v6, 16) } : void 0;
|
|
3352
|
+
}
|
|
3353
|
+
function parsePrefix(text) {
|
|
3354
|
+
const parts2 = text.trim().split("/");
|
|
3355
|
+
if (parts2.length > 2) return void 0;
|
|
3356
|
+
const [address = "", size] = parts2;
|
|
3357
|
+
const parsed2 = addressBits(address);
|
|
3358
|
+
if (!parsed2) return void 0;
|
|
3359
|
+
const max = parsed2.v6 ? 128 : 32;
|
|
3360
|
+
const length2 = size === void 0 ? max : /^\d{1,3}$/.test(size) ? Number(size) : -1;
|
|
3361
|
+
if (length2 < 0 || length2 > max) return void 0;
|
|
3362
|
+
return { ...parsed2, length: length2 };
|
|
3363
|
+
}
|
|
3364
|
+
function within3(prefix, addr) {
|
|
3365
|
+
if (prefix.v6 !== addr.v6) return false;
|
|
3366
|
+
const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);
|
|
3367
|
+
return addr.bits >> shift === prefix.bits >> shift;
|
|
3368
|
+
}
|
|
3369
|
+
var RESERVED = [
|
|
3370
|
+
"0.0.0.0/8",
|
|
3371
|
+
"127.0.0.0/8",
|
|
3372
|
+
"169.254.0.0/16",
|
|
3373
|
+
"224.0.0.0/4",
|
|
3374
|
+
"240.0.0.0/4",
|
|
3375
|
+
"::/96",
|
|
3376
|
+
"::ffff:0:0/96",
|
|
3377
|
+
"fe80::/10",
|
|
3378
|
+
"ff00::/8"
|
|
3379
|
+
].map((p) => parsePrefix(p));
|
|
3380
|
+
var Routes = class {
|
|
3381
|
+
table = [];
|
|
3382
|
+
exit = false;
|
|
3383
|
+
ipv6;
|
|
3384
|
+
constructor(ipv62 = false) {
|
|
3385
|
+
this.ipv6 = ipv62;
|
|
3386
|
+
}
|
|
3387
|
+
set(table) {
|
|
3388
|
+
const parsed2 = (table.prefixes ?? []).map(parsePrefix);
|
|
3389
|
+
const bad = (table.prefixes ?? []).find((_, i) => !parsed2[i]);
|
|
3390
|
+
if (bad !== void 0) throw new Error(`not an address prefix: ${bad}`);
|
|
3391
|
+
this.table = parsed2;
|
|
3392
|
+
this.exit = table.exit === true;
|
|
3393
|
+
}
|
|
3394
|
+
classify(host) {
|
|
3395
|
+
const name2 = host.toLowerCase().replace(/\.$/, "");
|
|
3396
|
+
if (name2 === "localhost" || name2.endsWith(".localhost") || name2 === "0.0.0.0") {
|
|
3397
|
+
return "loopback";
|
|
3398
|
+
}
|
|
3399
|
+
if (name2 === HOST_LOOPBACK || name2 === HOST_ADDRESS) return "host";
|
|
3400
|
+
const addr = addressBits(name2);
|
|
3401
|
+
if (!addr) return "unreachable";
|
|
3402
|
+
if (addr.v6 && addr.bits === 1n) return "loopback";
|
|
3403
|
+
if (!addr.v6 && addr.bits >> 24n === 127n) return "loopback";
|
|
3404
|
+
if (RESERVED.some((p) => within3(p, addr))) return "reserved";
|
|
3405
|
+
if (addr.v6 && !this.ipv6) return "unreachable";
|
|
3406
|
+
if (this.exit || this.table.some((p) => within3(p, addr))) return "uplink";
|
|
3407
|
+
return "unreachable";
|
|
3408
|
+
}
|
|
3409
|
+
};
|
|
3410
|
+
|
|
3268
3411
|
// src/kernel/net/uplink-socket.ts
|
|
3269
3412
|
var CHUNK = 64 * 1024;
|
|
3270
3413
|
function hostPort(text) {
|
|
@@ -3669,8 +3812,10 @@ function canonicalHost(host) {
|
|
|
3669
3812
|
function keyOf(addr) {
|
|
3670
3813
|
return addr.family === "inet" ? `inet:${addr.port}` : `unix:${addr.path}`;
|
|
3671
3814
|
}
|
|
3815
|
+
var LOCAL_ONLY = new Routes();
|
|
3672
3816
|
var LoopbackNet = class {
|
|
3673
3817
|
bound = /* @__PURE__ */ new Map();
|
|
3818
|
+
dgrams = /* @__PURE__ */ new Map();
|
|
3674
3819
|
activators = /* @__PURE__ */ new Map();
|
|
3675
3820
|
internal = /* @__PURE__ */ new Set();
|
|
3676
3821
|
reserved = /* @__PURE__ */ new Set();
|
|
@@ -3683,7 +3828,31 @@ var LoopbackNet = class {
|
|
|
3683
3828
|
uplinkFor(host) {
|
|
3684
3829
|
const route = this.route;
|
|
3685
3830
|
if (!route) return void 0;
|
|
3686
|
-
return
|
|
3831
|
+
return this.destination(host) === "uplink" ? route : void 0;
|
|
3832
|
+
}
|
|
3833
|
+
destination(host) {
|
|
3834
|
+
return (this.route?.routes ?? LOCAL_ONLY).classify(host);
|
|
3835
|
+
}
|
|
3836
|
+
bindDgram(socket, addr, kernel = false) {
|
|
3837
|
+
if (addr.family !== "inet") throw new KernelError("EAFNOSUPPORT");
|
|
3838
|
+
this.bindable(addr, kernel);
|
|
3839
|
+
const port = addr.port === 0 ? this.ephemeral() : addr.port;
|
|
3840
|
+
if (this.dgrams.has(port)) throw new KernelError("EADDRINUSE");
|
|
3841
|
+
this.dgrams.set(port, socket);
|
|
3842
|
+
return { ...addr, port };
|
|
3843
|
+
}
|
|
3844
|
+
releaseDgram(addr, socket) {
|
|
3845
|
+
if (this.dgrams.get(addr.port) === socket) this.dgrams.delete(addr.port);
|
|
3846
|
+
}
|
|
3847
|
+
deliverDgram(port, datagram2) {
|
|
3848
|
+
const target = this.dgrams.get(port);
|
|
3849
|
+
return target ? target.deliver(datagram2) : false;
|
|
3850
|
+
}
|
|
3851
|
+
bindable(addr, kernel) {
|
|
3852
|
+
if (addr.host !== "0.0.0.0" && !isLoopback(addr.host)) {
|
|
3853
|
+
throw new KernelError("EADDRNOTAVAIL");
|
|
3854
|
+
}
|
|
3855
|
+
if (!kernel && this.reserved.has(addr.port)) throw new KernelError("EADDRINUSE");
|
|
3687
3856
|
}
|
|
3688
3857
|
kernelOnly(port, reserve = false) {
|
|
3689
3858
|
if (reserve) this.internal.add(port);
|
|
@@ -3721,11 +3890,7 @@ var LoopbackNet = class {
|
|
|
3721
3890
|
bind(socket, addr, kernel = false) {
|
|
3722
3891
|
if (addr.family === "unix") {
|
|
3723
3892
|
if (addr.path === "") throw new KernelError("EINVAL");
|
|
3724
|
-
} else
|
|
3725
|
-
throw new KernelError("EADDRNOTAVAIL");
|
|
3726
|
-
} else if (!kernel && this.reserved.has(addr.port)) {
|
|
3727
|
-
throw new KernelError("EADDRINUSE");
|
|
3728
|
-
}
|
|
3893
|
+
} else this.bindable(addr, kernel);
|
|
3729
3894
|
const named = addr.family === "inet" && addr.port === 0 ? { ...addr, port: this.ephemeral() } : addr;
|
|
3730
3895
|
const key = keyOf(named);
|
|
3731
3896
|
if (this.bound.has(key)) throw new KernelError("EADDRINUSE");
|
|
@@ -3751,7 +3916,8 @@ var LoopbackNet = class {
|
|
|
3751
3916
|
for (let i = 0; i < span; i++) {
|
|
3752
3917
|
const port = this.nextEphemeral;
|
|
3753
3918
|
this.nextEphemeral = port === EPHEMERAL_LAST ? EPHEMERAL_FIRST : port + 1;
|
|
3754
|
-
|
|
3919
|
+
const taken = this.bound.has(`inet:${port}`) || this.dgrams.has(port);
|
|
3920
|
+
if (!taken && !this.reserved.has(port)) return port;
|
|
3755
3921
|
}
|
|
3756
3922
|
throw new KernelError("EADDRINUSE");
|
|
3757
3923
|
}
|
|
@@ -5167,60 +5333,6 @@ function integrityAsker(port) {
|
|
|
5167
5333
|
return { lookup: lookup2, answer };
|
|
5168
5334
|
}
|
|
5169
5335
|
|
|
5170
|
-
// src/kernel/net/loopback-names.ts
|
|
5171
|
-
var HOST_LOOPBACK = "host.slicc.internal";
|
|
5172
|
-
var HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
|
|
5173
|
-
var PAGE_LOOPBACK = "kernel.localhost";
|
|
5174
|
-
var PAGE_LOOPBACK_URL = `http://{port}.${PAGE_LOOPBACK}`;
|
|
5175
|
-
function toHostLoopback(href) {
|
|
5176
|
-
const url = new URL(href);
|
|
5177
|
-
if (url.hostname.replace(/\.$/, "").toLowerCase() !== HOST_LOOPBACK) return href;
|
|
5178
|
-
url.hostname = "127.0.0.1";
|
|
5179
|
-
return url.href;
|
|
5180
|
-
}
|
|
5181
|
-
var LOOPBACK_V4 = /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
5182
|
-
var LOOPBACK_V6 = /* @__PURE__ */ new Set(["::1", "::", "0:0:0:0:0:0:0:1"]);
|
|
5183
|
-
var MAPPED_V4 = /^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/;
|
|
5184
|
-
var KERNEL_PORT = /^(\d{1,5})\.kernel\.localhost$/;
|
|
5185
|
-
var SCHEMES = {
|
|
5186
|
-
"http:": 80,
|
|
5187
|
-
"ws:": 80,
|
|
5188
|
-
"https:": 443,
|
|
5189
|
-
"wss:": 443
|
|
5190
|
-
};
|
|
5191
|
-
function isKernelLoopbackHost(hostname) {
|
|
5192
|
-
const host = hostname.replace(/^\[(.*)\]$/, "$1").replace(/\.$/, "").toLowerCase();
|
|
5193
|
-
return host === "localhost" || host.endsWith(".localhost") || host === "0.0.0.0" || LOOPBACK_V4.test(host) || LOOPBACK_V6.has(host) || MAPPED_V4.test(host);
|
|
5194
|
-
}
|
|
5195
|
-
function kernelLoopbackPort(href) {
|
|
5196
|
-
let url;
|
|
5197
|
-
try {
|
|
5198
|
-
url = new URL(href);
|
|
5199
|
-
} catch {
|
|
5200
|
-
return void 0;
|
|
5201
|
-
}
|
|
5202
|
-
const fallback = SCHEMES[url.protocol];
|
|
5203
|
-
if (fallback === void 0 || !isKernelLoopbackHost(url.hostname)) return void 0;
|
|
5204
|
-
const named = KERNEL_PORT.exec(url.hostname.replace(/\.$/, "").toLowerCase())?.[1];
|
|
5205
|
-
const port = Number(named ?? (url.port || fallback));
|
|
5206
|
-
return port >= 1 && port <= 65535 ? port : void 0;
|
|
5207
|
-
}
|
|
5208
|
-
var DEFAULT_HOSTNAME = "slicc";
|
|
5209
|
-
var HOSTNAME_ADDRESS = "127.0.1.1";
|
|
5210
|
-
var LIBC_HOSTNAMES = ["emscripten", "wasmer.sh"];
|
|
5211
|
-
var LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;
|
|
5212
|
-
function reserved(name2) {
|
|
5213
|
-
const lower = name2.toLowerCase();
|
|
5214
|
-
return lower === "localhost" || lower.endsWith(".localhost") || lower === HOST_LOOPBACK || lower === "wasmer.sh" || /^\d+(\.\d+){3}$/.test(lower);
|
|
5215
|
-
}
|
|
5216
|
-
function isHostname(name2) {
|
|
5217
|
-
if (typeof name2 !== "string" || name2.length > 253 || reserved(name2)) return false;
|
|
5218
|
-
return name2.split(".").every((l) => LABEL.test(l));
|
|
5219
|
-
}
|
|
5220
|
-
function ownNames(hostname) {
|
|
5221
|
-
return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
|
|
5222
|
-
}
|
|
5223
|
-
|
|
5224
5336
|
// src/kernel/net/http1.ts
|
|
5225
5337
|
var HttpError = class extends Error {
|
|
5226
5338
|
status;
|
|
@@ -7134,96 +7246,10 @@ var RemoteTransport = class {
|
|
|
7134
7246
|
}
|
|
7135
7247
|
};
|
|
7136
7248
|
|
|
7137
|
-
// src/kernel/net/routes.ts
|
|
7138
|
-
var HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join(".");
|
|
7139
|
-
function ipv4Bytes(text) {
|
|
7140
|
-
const parts2 = text.split(".");
|
|
7141
|
-
if (parts2.length !== 4 || !parts2.every((p) => /^\d{1,3}$/.test(p))) return void 0;
|
|
7142
|
-
const bytes = parts2.map(Number);
|
|
7143
|
-
return bytes.every((b) => b <= 255) ? bytes : void 0;
|
|
7144
|
-
}
|
|
7145
|
-
function ipv6Groups(text) {
|
|
7146
|
-
if (!text.includes(":")) return void 0;
|
|
7147
|
-
let canonical;
|
|
7148
|
-
try {
|
|
7149
|
-
canonical = new URL(`http://[${text}]/`).hostname.slice(1, -1);
|
|
7150
|
-
} catch {
|
|
7151
|
-
return void 0;
|
|
7152
|
-
}
|
|
7153
|
-
const [head, tail] = canonical.split("::");
|
|
7154
|
-
const part = (s) => s ? s.split(":").map((h) => Number.parseInt(h, 16)) : [];
|
|
7155
|
-
const front = part(head);
|
|
7156
|
-
const back = part(tail);
|
|
7157
|
-
return tail === void 0 ? front : [...front, ...new Array(8 - front.length - back.length).fill(0), ...back];
|
|
7158
|
-
}
|
|
7159
|
-
function toBits(values, width) {
|
|
7160
|
-
return values.reduce((acc, v) => acc << BigInt(width) | BigInt(v), 0n);
|
|
7161
|
-
}
|
|
7162
|
-
function addressBits(host) {
|
|
7163
|
-
const v4 = ipv4Bytes(host);
|
|
7164
|
-
if (v4) return { v6: false, bits: toBits(v4, 8) };
|
|
7165
|
-
const v6 = ipv6Groups(host);
|
|
7166
|
-
return v6 ? { v6: true, bits: toBits(v6, 16) } : void 0;
|
|
7167
|
-
}
|
|
7168
|
-
function parsePrefix(text) {
|
|
7169
|
-
const parts2 = text.trim().split("/");
|
|
7170
|
-
if (parts2.length > 2) return void 0;
|
|
7171
|
-
const [address = "", size] = parts2;
|
|
7172
|
-
const parsed2 = addressBits(address);
|
|
7173
|
-
if (!parsed2) return void 0;
|
|
7174
|
-
const max = parsed2.v6 ? 128 : 32;
|
|
7175
|
-
const length2 = size === void 0 ? max : /^\d{1,3}$/.test(size) ? Number(size) : -1;
|
|
7176
|
-
if (length2 < 0 || length2 > max) return void 0;
|
|
7177
|
-
return { ...parsed2, length: length2 };
|
|
7178
|
-
}
|
|
7179
|
-
function within3(prefix, addr) {
|
|
7180
|
-
if (prefix.v6 !== addr.v6) return false;
|
|
7181
|
-
const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);
|
|
7182
|
-
return addr.bits >> shift === prefix.bits >> shift;
|
|
7183
|
-
}
|
|
7184
|
-
var RESERVED = [
|
|
7185
|
-
"0.0.0.0/8",
|
|
7186
|
-
"127.0.0.0/8",
|
|
7187
|
-
"169.254.0.0/16",
|
|
7188
|
-
"224.0.0.0/4",
|
|
7189
|
-
"240.0.0.0/4",
|
|
7190
|
-
"::/96",
|
|
7191
|
-
"::ffff:0:0/96",
|
|
7192
|
-
"fe80::/10",
|
|
7193
|
-
"ff00::/8"
|
|
7194
|
-
].map((p) => parsePrefix(p));
|
|
7195
|
-
var Routes = class {
|
|
7196
|
-
table = [];
|
|
7197
|
-
exit = false;
|
|
7198
|
-
ipv6;
|
|
7199
|
-
constructor(ipv62 = false) {
|
|
7200
|
-
this.ipv6 = ipv62;
|
|
7201
|
-
}
|
|
7202
|
-
set(table) {
|
|
7203
|
-
const parsed2 = (table.prefixes ?? []).map(parsePrefix);
|
|
7204
|
-
const bad = (table.prefixes ?? []).find((_, i) => !parsed2[i]);
|
|
7205
|
-
if (bad !== void 0) throw new Error(`not an address prefix: ${bad}`);
|
|
7206
|
-
this.table = parsed2;
|
|
7207
|
-
this.exit = table.exit === true;
|
|
7208
|
-
}
|
|
7209
|
-
classify(host) {
|
|
7210
|
-
const name2 = host.toLowerCase().replace(/\.$/, "");
|
|
7211
|
-
if (name2 === "localhost" || name2.endsWith(".localhost") || name2 === "0.0.0.0") {
|
|
7212
|
-
return "loopback";
|
|
7213
|
-
}
|
|
7214
|
-
if (name2 === HOST_LOOPBACK || name2 === HOST_ADDRESS) return "host";
|
|
7215
|
-
const addr = addressBits(name2);
|
|
7216
|
-
if (!addr) return "unreachable";
|
|
7217
|
-
if (addr.v6 && addr.bits === 1n) return "loopback";
|
|
7218
|
-
if (!addr.v6 && addr.bits >> 24n === 127n) return "loopback";
|
|
7219
|
-
if (RESERVED.some((p) => within3(p, addr))) return "reserved";
|
|
7220
|
-
if (addr.v6 && !this.ipv6) return "unreachable";
|
|
7221
|
-
if (this.exit || this.table.some((p) => within3(p, addr))) return "uplink";
|
|
7222
|
-
return "unreachable";
|
|
7223
|
-
}
|
|
7224
|
-
};
|
|
7225
|
-
|
|
7226
7249
|
// src/kernel/net/uplink.ts
|
|
7250
|
+
function carriesUdp(uplink) {
|
|
7251
|
+
return uplink.traits.udp === true && typeof uplink.udp === "function";
|
|
7252
|
+
}
|
|
7227
7253
|
function answerOf(result) {
|
|
7228
7254
|
const answer = Array.isArray(result) ? { addresses: result } : result;
|
|
7229
7255
|
const addresses = Array.isArray(answer?.addresses) ? answer.addresses.filter((a) => typeof a === "string") : [];
|
|
@@ -7304,6 +7330,44 @@ var RemoteUplink = class {
|
|
|
7304
7330
|
close: () => this.port.postMessage({ uplink: "close", cid })
|
|
7305
7331
|
};
|
|
7306
7332
|
}
|
|
7333
|
+
async udp(req) {
|
|
7334
|
+
req.signal.throwIfAborted();
|
|
7335
|
+
const opened2 = await this.ask(
|
|
7336
|
+
{ uplink: "udp-open", uid: ++this.nextId, family: req.family },
|
|
7337
|
+
req.signal
|
|
7338
|
+
);
|
|
7339
|
+
const { cid, localAddr } = opened2;
|
|
7340
|
+
const recv = () => this.ask({
|
|
7341
|
+
uplink: "udp-recv",
|
|
7342
|
+
uid: ++this.nextId,
|
|
7343
|
+
cid
|
|
7344
|
+
});
|
|
7345
|
+
return {
|
|
7346
|
+
localAddr,
|
|
7347
|
+
send: async (bytes, host, port) => {
|
|
7348
|
+
const copy = bytes.slice();
|
|
7349
|
+
const call = {
|
|
7350
|
+
uplink: "udp-send",
|
|
7351
|
+
uid: ++this.nextId,
|
|
7352
|
+
cid,
|
|
7353
|
+
bytes: copy,
|
|
7354
|
+
host,
|
|
7355
|
+
port
|
|
7356
|
+
};
|
|
7357
|
+
await this.ask(call, void 0, [copy.buffer]);
|
|
7358
|
+
},
|
|
7359
|
+
messages: {
|
|
7360
|
+
[Symbol.asyncIterator]: async function* () {
|
|
7361
|
+
for (; ; ) {
|
|
7362
|
+
const got = await recv();
|
|
7363
|
+
if (!got.message) return;
|
|
7364
|
+
yield got.message;
|
|
7365
|
+
}
|
|
7366
|
+
}
|
|
7367
|
+
},
|
|
7368
|
+
close: () => this.port.postMessage({ uplink: "udp-close", cid })
|
|
7369
|
+
};
|
|
7370
|
+
}
|
|
7307
7371
|
};
|
|
7308
7372
|
|
|
7309
7373
|
// src/cdp/types.ts
|
|
@@ -11470,6 +11534,268 @@ var ProcessClocks = class {
|
|
|
11470
11534
|
}
|
|
11471
11535
|
};
|
|
11472
11536
|
|
|
11537
|
+
// src/kernel/dgram.ts
|
|
11538
|
+
var DGRAM_QUEUE_BYTES = 256 * 1024;
|
|
11539
|
+
var DGRAM_QUEUE_COUNT = 512;
|
|
11540
|
+
var DGRAM_SEND_ROOM = 256 * 1024;
|
|
11541
|
+
var MAX_DATAGRAM_V4 = 65507;
|
|
11542
|
+
var MAX_DATAGRAM_V6 = 65527;
|
|
11543
|
+
var SOL_SOCKET2 = 1;
|
|
11544
|
+
var IPPROTO_IP = 0;
|
|
11545
|
+
var SO_TYPE2 = 3;
|
|
11546
|
+
var SO_ERROR2 = 4;
|
|
11547
|
+
var SO_BROADCAST = 6;
|
|
11548
|
+
var SO_SNDBUF2 = 7;
|
|
11549
|
+
var SO_RCVBUF2 = 8;
|
|
11550
|
+
var SO_DOMAIN2 = 39;
|
|
11551
|
+
var SOCK_DGRAM = 2;
|
|
11552
|
+
var AF_INET2 = 2;
|
|
11553
|
+
var IP_MULTICAST_FIRST = 32;
|
|
11554
|
+
var IP_MULTICAST_LAST = 36;
|
|
11555
|
+
var SEND_ERRORS = ["ENETUNREACH", "EHOSTUNREACH", "EACCES", "EMSGSIZE"];
|
|
11556
|
+
var UNREACHABLE = ["EACCES", "ENETUNREACH", "EHOSTUNREACH"];
|
|
11557
|
+
function sendError(e) {
|
|
11558
|
+
if (e instanceof KernelError) return e;
|
|
11559
|
+
const code = e?.code;
|
|
11560
|
+
return new KernelError(SEND_ERRORS.find((errno2) => errno2 === code) ?? "EHOSTUNREACH");
|
|
11561
|
+
}
|
|
11562
|
+
function sameAddr(a, b) {
|
|
11563
|
+
return a.port === b.port && canonicalHost(a.host) === canonicalHost(b.host);
|
|
11564
|
+
}
|
|
11565
|
+
function familyOf(host) {
|
|
11566
|
+
return host.includes(":") ? 6 : 4;
|
|
11567
|
+
}
|
|
11568
|
+
var KernelDgram = class {
|
|
11569
|
+
local;
|
|
11570
|
+
peer;
|
|
11571
|
+
net;
|
|
11572
|
+
queue = [];
|
|
11573
|
+
queued = 0;
|
|
11574
|
+
pending;
|
|
11575
|
+
closed = false;
|
|
11576
|
+
sending = 0;
|
|
11577
|
+
changes = new Changes();
|
|
11578
|
+
options = /* @__PURE__ */ new Map();
|
|
11579
|
+
uplinks = /* @__PURE__ */ new Map();
|
|
11580
|
+
stop = new AbortController();
|
|
11581
|
+
constructor(net) {
|
|
11582
|
+
this.net = net;
|
|
11583
|
+
}
|
|
11584
|
+
bind(addr) {
|
|
11585
|
+
if (this.local) throw new KernelError("EINVAL");
|
|
11586
|
+
this.local = this.net.bindDgram(this, addr);
|
|
11587
|
+
}
|
|
11588
|
+
bound() {
|
|
11589
|
+
this.local ??= this.net.bindDgram(this, { family: "inet", host: "0.0.0.0", port: 0 });
|
|
11590
|
+
return this.local;
|
|
11591
|
+
}
|
|
11592
|
+
connectTo(addr) {
|
|
11593
|
+
if (addr.family !== "inet") throw new KernelError("EAFNOSUPPORT");
|
|
11594
|
+
this.route(addr.host);
|
|
11595
|
+
this.bound();
|
|
11596
|
+
this.peer = { family: "inet", host: canonicalHost(addr.host), port: addr.port };
|
|
11597
|
+
this.pending = void 0;
|
|
11598
|
+
this.drain((d) => sameAddr(d.from, addr));
|
|
11599
|
+
}
|
|
11600
|
+
drain(keep2) {
|
|
11601
|
+
const kept = this.queue.filter(keep2);
|
|
11602
|
+
this.queue.splice(0, this.queue.length, ...kept);
|
|
11603
|
+
this.queued = kept.reduce((sum, d) => sum + d.bytes.length, 0);
|
|
11604
|
+
}
|
|
11605
|
+
route(host) {
|
|
11606
|
+
const where = this.net.destination(host);
|
|
11607
|
+
if (where === "loopback" || where === "uplink") return where;
|
|
11608
|
+
throw new KernelError("ENETUNREACH");
|
|
11609
|
+
}
|
|
11610
|
+
takeError() {
|
|
11611
|
+
const pending = this.pending;
|
|
11612
|
+
this.pending = void 0;
|
|
11613
|
+
return pending;
|
|
11614
|
+
}
|
|
11615
|
+
async send(bytes, to) {
|
|
11616
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
11617
|
+
const pending = this.takeError();
|
|
11618
|
+
if (pending) throw new KernelError(pending);
|
|
11619
|
+
const target = to ?? this.peer;
|
|
11620
|
+
if (!target) throw new KernelError("EDESTADDRREQ");
|
|
11621
|
+
if (target.family !== "inet") throw new KernelError("EAFNOSUPPORT");
|
|
11622
|
+
const max = familyOf(target.host) === 6 ? MAX_DATAGRAM_V6 : MAX_DATAGRAM_V4;
|
|
11623
|
+
if (bytes.length > max) throw new KernelError("EMSGSIZE");
|
|
11624
|
+
const where = this.route(target.host);
|
|
11625
|
+
const local = this.bound();
|
|
11626
|
+
if (where === "uplink") return this.sendUp(bytes, target);
|
|
11627
|
+
const from = {
|
|
11628
|
+
family: "inet",
|
|
11629
|
+
host: local.host === "0.0.0.0" ? "127.0.0.1" : local.host,
|
|
11630
|
+
port: local.port
|
|
11631
|
+
};
|
|
11632
|
+
const delivered = this.net.deliverDgram(target.port, { bytes: bytes.slice(), from });
|
|
11633
|
+
if (!delivered && this.peer && sameAddr(this.peer, target)) {
|
|
11634
|
+
this.pending = "ECONNREFUSED";
|
|
11635
|
+
this.changes.wake();
|
|
11636
|
+
}
|
|
11637
|
+
return bytes.length;
|
|
11638
|
+
}
|
|
11639
|
+
async sendUp(bytes, to) {
|
|
11640
|
+
const uplink = this.net.uplinkFor(to.host)?.uplink;
|
|
11641
|
+
if (!uplink || !carriesUdp(uplink)) throw new KernelError("ENETUNREACH");
|
|
11642
|
+
this.sending += bytes.length;
|
|
11643
|
+
try {
|
|
11644
|
+
const socket = await this.uplinkSocket(uplink, familyOf(to.host));
|
|
11645
|
+
await socket.send(bytes.slice(), to.host, to.port);
|
|
11646
|
+
} catch (e) {
|
|
11647
|
+
throw sendError(e);
|
|
11648
|
+
} finally {
|
|
11649
|
+
this.sending -= bytes.length;
|
|
11650
|
+
this.changes.wake();
|
|
11651
|
+
}
|
|
11652
|
+
return bytes.length;
|
|
11653
|
+
}
|
|
11654
|
+
uplinkSocket(uplink, family) {
|
|
11655
|
+
const known = this.uplinks.get(family);
|
|
11656
|
+
if (known !== void 0) return known;
|
|
11657
|
+
const opening2 = Promise.resolve().then(() => {
|
|
11658
|
+
if (!uplink.udp) throw new KernelError("ENETUNREACH");
|
|
11659
|
+
return uplink.udp({ family, signal: this.stop.signal });
|
|
11660
|
+
});
|
|
11661
|
+
this.uplinks.set(family, opening2);
|
|
11662
|
+
opening2.then(
|
|
11663
|
+
(socket) => {
|
|
11664
|
+
if (this.closed) {
|
|
11665
|
+
socket.close();
|
|
11666
|
+
return;
|
|
11667
|
+
}
|
|
11668
|
+
void this.pump(socket, family);
|
|
11669
|
+
},
|
|
11670
|
+
() => this.uplinks.delete(family)
|
|
11671
|
+
);
|
|
11672
|
+
return opening2;
|
|
11673
|
+
}
|
|
11674
|
+
async pump(socket, family) {
|
|
11675
|
+
const iterate = async () => {
|
|
11676
|
+
for await (const message3 of socket.messages) {
|
|
11677
|
+
if (this.closed) return;
|
|
11678
|
+
const from = { family: "inet", host: message3.host, port: message3.port };
|
|
11679
|
+
if ("bytes" in message3) this.deliver({ bytes: message3.bytes, from });
|
|
11680
|
+
else this.unreachable(message3.error, from);
|
|
11681
|
+
}
|
|
11682
|
+
};
|
|
11683
|
+
await iterate().catch(() => void 0);
|
|
11684
|
+
if (!this.closed) this.uplinks.delete(family);
|
|
11685
|
+
socket.close();
|
|
11686
|
+
}
|
|
11687
|
+
unreachable(error, from) {
|
|
11688
|
+
if (!this.peer || !sameAddr(this.peer, from)) return;
|
|
11689
|
+
this.pending = UNREACHABLE.find((errno2) => errno2 === error) ?? "EHOSTUNREACH";
|
|
11690
|
+
this.changes.wake();
|
|
11691
|
+
}
|
|
11692
|
+
deliver(datagram2) {
|
|
11693
|
+
if (this.closed) return false;
|
|
11694
|
+
if (this.peer && !sameAddr(this.peer, datagram2.from)) return true;
|
|
11695
|
+
const full = this.queue.length >= DGRAM_QUEUE_COUNT || this.queued + datagram2.bytes.length > DGRAM_QUEUE_BYTES;
|
|
11696
|
+
if (full) return true;
|
|
11697
|
+
this.queue.push(datagram2);
|
|
11698
|
+
this.queued += datagram2.bytes.length;
|
|
11699
|
+
this.changes.wake();
|
|
11700
|
+
return true;
|
|
11701
|
+
}
|
|
11702
|
+
async receive(max, peek, signal) {
|
|
11703
|
+
for (; ; ) {
|
|
11704
|
+
const pending = this.takeError();
|
|
11705
|
+
if (pending) throw new KernelError(pending);
|
|
11706
|
+
if (this.closed) throw new KernelError("EBADF");
|
|
11707
|
+
const next2 = this.queue[0];
|
|
11708
|
+
if (next2) {
|
|
11709
|
+
if (!peek) {
|
|
11710
|
+
this.queue.shift();
|
|
11711
|
+
this.queued -= next2.bytes.length;
|
|
11712
|
+
this.changes.wake();
|
|
11713
|
+
}
|
|
11714
|
+
const size = Math.max(0, max);
|
|
11715
|
+
return {
|
|
11716
|
+
bytes: next2.bytes.slice(0, size),
|
|
11717
|
+
from: next2.from,
|
|
11718
|
+
truncated: next2.bytes.length > size
|
|
11719
|
+
};
|
|
11720
|
+
}
|
|
11721
|
+
await this.changes.wait(signal);
|
|
11722
|
+
}
|
|
11723
|
+
}
|
|
11724
|
+
async read(max, signal) {
|
|
11725
|
+
return (await this.receive(max, false, signal)).bytes;
|
|
11726
|
+
}
|
|
11727
|
+
async peek(max, signal) {
|
|
11728
|
+
return (await this.receive(max, true, signal)).bytes;
|
|
11729
|
+
}
|
|
11730
|
+
write(bytes) {
|
|
11731
|
+
return this.send(bytes);
|
|
11732
|
+
}
|
|
11733
|
+
poll() {
|
|
11734
|
+
return {
|
|
11735
|
+
readable: this.queue.length > 0 || this.pending !== void 0 || this.closed,
|
|
11736
|
+
writable: this.sending < DGRAM_SEND_ROOM,
|
|
11737
|
+
hangup: this.closed,
|
|
11738
|
+
...this.pending !== void 0 ? { error: true } : {}
|
|
11739
|
+
};
|
|
11740
|
+
}
|
|
11741
|
+
changed(signal) {
|
|
11742
|
+
return this.changes.wait(signal);
|
|
11743
|
+
}
|
|
11744
|
+
shutdown(how) {
|
|
11745
|
+
if (!this.peer) throw new KernelError("ENOTCONN");
|
|
11746
|
+
if (how < 0 || how > 2) throw new KernelError("EINVAL");
|
|
11747
|
+
}
|
|
11748
|
+
getOption(level, name2) {
|
|
11749
|
+
if (level === SOL_SOCKET2) {
|
|
11750
|
+
switch (name2) {
|
|
11751
|
+
case SO_TYPE2:
|
|
11752
|
+
return SOCK_DGRAM;
|
|
11753
|
+
case SO_ERROR2: {
|
|
11754
|
+
const pending = this.takeError();
|
|
11755
|
+
return pending ? wasiErrno(pending) : 0;
|
|
11756
|
+
}
|
|
11757
|
+
case SO_DOMAIN2:
|
|
11758
|
+
return AF_INET2;
|
|
11759
|
+
case SO_BROADCAST:
|
|
11760
|
+
return 0;
|
|
11761
|
+
case SO_SNDBUF2:
|
|
11762
|
+
return this.options.get(`${level}:${name2}`) ?? DGRAM_SEND_ROOM;
|
|
11763
|
+
case SO_RCVBUF2:
|
|
11764
|
+
return this.options.get(`${level}:${name2}`) ?? DGRAM_QUEUE_BYTES;
|
|
11765
|
+
}
|
|
11766
|
+
}
|
|
11767
|
+
if (level === IPPROTO_IP && name2 >= IP_MULTICAST_FIRST && name2 <= IP_MULTICAST_LAST) {
|
|
11768
|
+
throw new KernelError("ENOPROTOOPT");
|
|
11769
|
+
}
|
|
11770
|
+
return this.options.get(`${level}:${name2}`) ?? 0;
|
|
11771
|
+
}
|
|
11772
|
+
setOption(level, name2, value) {
|
|
11773
|
+
if (level === SOL_SOCKET2 && name2 === SO_BROADCAST && value !== 0) {
|
|
11774
|
+
throw new KernelError("EOPNOTSUPP");
|
|
11775
|
+
}
|
|
11776
|
+
if (level === IPPROTO_IP && name2 >= IP_MULTICAST_FIRST && name2 <= IP_MULTICAST_LAST) {
|
|
11777
|
+
throw new KernelError("ENOPROTOOPT");
|
|
11778
|
+
}
|
|
11779
|
+
this.options.set(`${level}:${name2}`, value);
|
|
11780
|
+
}
|
|
11781
|
+
close() {
|
|
11782
|
+
if (this.closed) return;
|
|
11783
|
+
this.closed = true;
|
|
11784
|
+
this.stop.abort();
|
|
11785
|
+
for (const opening2 of this.uplinks.values()) {
|
|
11786
|
+
opening2.then(
|
|
11787
|
+
(socket) => socket.close(),
|
|
11788
|
+
() => void 0
|
|
11789
|
+
);
|
|
11790
|
+
}
|
|
11791
|
+
this.uplinks.clear();
|
|
11792
|
+
if (this.local) this.net.releaseDgram(this.local, this);
|
|
11793
|
+
this.queue.length = 0;
|
|
11794
|
+
this.queued = 0;
|
|
11795
|
+
this.changes.wake();
|
|
11796
|
+
}
|
|
11797
|
+
};
|
|
11798
|
+
|
|
11473
11799
|
// src/fs/pages.ts
|
|
11474
11800
|
var PAGE = 64 * 1024;
|
|
11475
11801
|
var READAHEAD = 1024 * 1024;
|
|
@@ -11728,7 +12054,7 @@ function mountTable(mounts = []) {
|
|
|
11728
12054
|
}
|
|
11729
12055
|
|
|
11730
12056
|
// src/version.ts
|
|
11731
|
-
var KERNEL_VERSION = true ? "1.
|
|
12057
|
+
var KERNEL_VERSION = true ? "1.96.0" : "0.0.0-dev";
|
|
11732
12058
|
var OS_RELEASE = "6.0.0-slicc";
|
|
11733
12059
|
function procVersion() {
|
|
11734
12060
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -12215,6 +12541,7 @@ function levelOf(file) {
|
|
|
12215
12541
|
if (state.readable) bits2 |= EPOLL.IN;
|
|
12216
12542
|
if (state.writable) bits2 |= EPOLL.OUT;
|
|
12217
12543
|
if (state.rdhup) bits2 |= EPOLL.RDHUP;
|
|
12544
|
+
if (state.error) bits2 |= EPOLL.ERR;
|
|
12218
12545
|
if (state.hangup) bits2 |= file.read ? EPOLL.HUP : EPOLL.ERR;
|
|
12219
12546
|
return bits2;
|
|
12220
12547
|
}
|
|
@@ -13980,6 +14307,19 @@ async function waitReady(fds, read, write, deadline, interrupted3) {
|
|
|
13980
14307
|
}
|
|
13981
14308
|
}
|
|
13982
14309
|
|
|
14310
|
+
// src/kernel/net/datagram-wire.ts
|
|
14311
|
+
function encodeReceived(got) {
|
|
14312
|
+
const host = new TextEncoder().encode(got.host);
|
|
14313
|
+
const out = new Uint8Array(4 + host.length + got.bytes.length);
|
|
14314
|
+
const view2 = new DataView(out.buffer);
|
|
14315
|
+
view2.setUint8(0, got.truncated ? 1 : 0);
|
|
14316
|
+
view2.setUint16(1, got.port);
|
|
14317
|
+
view2.setUint8(3, host.length);
|
|
14318
|
+
out.set(host, 4);
|
|
14319
|
+
out.set(got.bytes, 4 + host.length);
|
|
14320
|
+
return out;
|
|
14321
|
+
}
|
|
14322
|
+
|
|
13983
14323
|
// src/kernel/socket-syscalls.ts
|
|
13984
14324
|
var SOCKET_OPS = [
|
|
13985
14325
|
"sock-open",
|
|
@@ -13992,19 +14332,36 @@ var SOCKET_OPS = [
|
|
|
13992
14332
|
"sock-name",
|
|
13993
14333
|
"sock-getopt",
|
|
13994
14334
|
"sock-setopt",
|
|
13995
|
-
"sock-resolve"
|
|
14335
|
+
"sock-resolve",
|
|
14336
|
+
"sock-sendto",
|
|
14337
|
+
"sock-recvfrom"
|
|
13996
14338
|
];
|
|
13997
14339
|
function socketAt(fds, fd) {
|
|
14340
|
+
const file = anySocketAt(fds, fd);
|
|
14341
|
+
if (file instanceof KernelDgram) throw new KernelError("EOPNOTSUPP");
|
|
14342
|
+
return file;
|
|
14343
|
+
}
|
|
14344
|
+
function anySocketAt(fds, fd) {
|
|
13998
14345
|
const file = fds.get(fd).file;
|
|
13999
|
-
if (!(file instanceof KernelSocket)
|
|
14346
|
+
if (!(file instanceof KernelSocket) && !(file instanceof KernelDgram)) {
|
|
14347
|
+
throw new KernelError("ENOTSOCK");
|
|
14348
|
+
}
|
|
14349
|
+
return file;
|
|
14350
|
+
}
|
|
14351
|
+
function dgramAt(fds, fd) {
|
|
14352
|
+
const file = anySocketAt(fds, fd);
|
|
14353
|
+
if (!(file instanceof KernelDgram)) throw new KernelError("EOPNOTSUPP");
|
|
14000
14354
|
return file;
|
|
14001
14355
|
}
|
|
14002
14356
|
var ok2 = (json5) => json5 === void 0 ? { ok: true, kind: "void" } : { ok: true, kind: "json", json: json5 };
|
|
14003
14357
|
async function socketSyscall(req, proc) {
|
|
14004
14358
|
const { fds, net } = proc;
|
|
14005
14359
|
switch (req.op) {
|
|
14006
|
-
case "sock-open":
|
|
14007
|
-
|
|
14360
|
+
case "sock-open": {
|
|
14361
|
+
if (req.type === "dgram" && req.domain !== "inet") throw new KernelError("EPROTONOSUPPORT");
|
|
14362
|
+
const file = req.type === "dgram" ? new KernelDgram(net) : net.socket(req.domain);
|
|
14363
|
+
return ok2(fds.install(new OpenFile(file), 3));
|
|
14364
|
+
}
|
|
14008
14365
|
case "sock-pair": {
|
|
14009
14366
|
const [a, b] = KernelSocket.pair(net, req.domain, proc.cred?.());
|
|
14010
14367
|
const first = fds.install(new OpenFile(a), 3);
|
|
@@ -14016,44 +14373,64 @@ async function socketSyscall(req, proc) {
|
|
|
14016
14373
|
}
|
|
14017
14374
|
}
|
|
14018
14375
|
case "sock-bind":
|
|
14019
|
-
|
|
14376
|
+
anySocketAt(fds, req.fd).bind(req.addr);
|
|
14020
14377
|
return ok2();
|
|
14021
14378
|
case "sock-listen":
|
|
14022
14379
|
socketAt(fds, req.fd).listen(req.backlog, proc.cred?.());
|
|
14023
14380
|
return ok2();
|
|
14024
14381
|
case "sock-accept":
|
|
14025
14382
|
return ok2(await accept(proc, req.fd, req.nonblock));
|
|
14026
|
-
case "sock-connect":
|
|
14027
|
-
|
|
14028
|
-
const stamp = net.facadeAt(req.addr) && await proc.stamp?.();
|
|
14029
|
-
const dialing = socket.connect(req.addr, true, proc.cred?.(), stamp || void 0);
|
|
14030
|
-
if (req.nonblock) {
|
|
14031
|
-
dialing?.catch(() => void 0);
|
|
14032
|
-
throw new KernelError("EINPROGRESS");
|
|
14033
|
-
}
|
|
14034
|
-
if (dialing !== void 0) await interruptible2(dialing, proc.blocking());
|
|
14035
|
-
return ok2();
|
|
14036
|
-
}
|
|
14383
|
+
case "sock-connect":
|
|
14384
|
+
return connect(req, proc);
|
|
14037
14385
|
case "sock-shutdown":
|
|
14038
|
-
|
|
14386
|
+
anySocketAt(fds, req.fd).shutdown(req.how);
|
|
14039
14387
|
return ok2();
|
|
14040
14388
|
case "sock-name": {
|
|
14041
|
-
const socket =
|
|
14389
|
+
const socket = anySocketAt(fds, req.fd);
|
|
14042
14390
|
const addr = req.peer ? socket.peer : socket.local;
|
|
14043
14391
|
if (req.peer && !addr) throw new KernelError("ENOTCONN");
|
|
14044
|
-
return ok2(addr ?? unnamed(socket.domain));
|
|
14392
|
+
return ok2(addr ?? unnamed(socket instanceof KernelDgram ? "inet" : socket.domain));
|
|
14045
14393
|
}
|
|
14046
14394
|
case "sock-getopt":
|
|
14047
|
-
return ok2(
|
|
14395
|
+
return ok2(anySocketAt(fds, req.fd).getOption(req.level, req.name));
|
|
14048
14396
|
case "sock-setopt":
|
|
14049
|
-
|
|
14397
|
+
anySocketAt(fds, req.fd).setOption(req.level, req.name, req.value);
|
|
14050
14398
|
return ok2();
|
|
14051
14399
|
case "sock-resolve": {
|
|
14052
14400
|
const addresses = await proc.resolve(req.name, req.family, () => proc.blocking());
|
|
14053
14401
|
if (addresses.length === 0) throw new KernelError("ENOENT");
|
|
14054
14402
|
return ok2(addresses);
|
|
14055
14403
|
}
|
|
14404
|
+
default:
|
|
14405
|
+
return datagram(req, proc);
|
|
14406
|
+
}
|
|
14407
|
+
}
|
|
14408
|
+
async function connect(req, proc) {
|
|
14409
|
+
const target = anySocketAt(proc.fds, req.fd);
|
|
14410
|
+
if (target instanceof KernelDgram) {
|
|
14411
|
+
target.connectTo(req.addr);
|
|
14412
|
+
return ok2();
|
|
14413
|
+
}
|
|
14414
|
+
const stamp = proc.net.facadeAt(req.addr) && await proc.stamp?.();
|
|
14415
|
+
const dialing = target.connect(req.addr, true, proc.cred?.(), stamp || void 0);
|
|
14416
|
+
if (req.nonblock) {
|
|
14417
|
+
dialing?.catch(() => void 0);
|
|
14418
|
+
throw new KernelError("EINPROGRESS");
|
|
14419
|
+
}
|
|
14420
|
+
if (dialing !== void 0) await interruptible2(dialing, proc.blocking());
|
|
14421
|
+
return ok2();
|
|
14422
|
+
}
|
|
14423
|
+
async function datagram(req, proc) {
|
|
14424
|
+
const dgram = dgramAt(proc.fds, req.fd);
|
|
14425
|
+
if (req.op === "sock-sendto") {
|
|
14426
|
+
if (req.nonblock && !pollFile(dgram).writable) throw new KernelError("EAGAIN");
|
|
14427
|
+
return ok2(await dgram.send(req.body, req.addr));
|
|
14056
14428
|
}
|
|
14429
|
+
const ready2 = pollFile(dgram).readable;
|
|
14430
|
+
if (req.nonblock && !ready2) throw new KernelError("EAGAIN");
|
|
14431
|
+
const got = await dgram.receive(req.max, req.peek, ready2 ? void 0 : proc.blocking());
|
|
14432
|
+
const { bytes, from, truncated } = got;
|
|
14433
|
+
return { ok: true, kind: "bytes", bytes: encodeReceived({ bytes, truncated, ...from }) };
|
|
14057
14434
|
}
|
|
14058
14435
|
function interruptible2(dialing, signal) {
|
|
14059
14436
|
return new Promise((resolve2, reject) => {
|
|
@@ -15657,7 +16034,8 @@ var WasmProcess = class {
|
|
|
15657
16034
|
const terminal = (file.tty ?? file.pty?.slave)?.name;
|
|
15658
16035
|
return {
|
|
15659
16036
|
tty: file.tty !== void 0,
|
|
15660
|
-
kind: file instanceof KernelSocket ? "socket" : kernelFdKind(file),
|
|
16037
|
+
kind: file instanceof KernelSocket || file instanceof KernelDgram ? "socket" : kernelFdKind(file),
|
|
16038
|
+
...file instanceof KernelDgram ? { dgram: true } : {},
|
|
15661
16039
|
...file.heldMeta ? { meta: file.heldMeta } : {},
|
|
15662
16040
|
...flags2 !== void 0 ? { flags: flags2 } : {},
|
|
15663
16041
|
...this.fds.closesOnExec(fd) ? { cloexec: true } : {},
|
|
@@ -16046,7 +16424,7 @@ function inheritedFds(fds) {
|
|
|
16046
16424
|
return fds.numbers().filter((fd) => fd > 2 && !fds.get(fd).file.held).map((fd) => {
|
|
16047
16425
|
const open = fds.get(fd);
|
|
16048
16426
|
const flags2 = fds.statusFlags(fd);
|
|
16049
|
-
const kind = open.file instanceof KernelSocket ? "socket" : kernelFdKind(open.file);
|
|
16427
|
+
const kind = open.file instanceof KernelSocket || open.file instanceof KernelDgram ? "socket" : kernelFdKind(open.file);
|
|
16050
16428
|
const meta = open.file.heldMeta;
|
|
16051
16429
|
return {
|
|
16052
16430
|
fd,
|
|
@@ -18691,7 +19069,7 @@ function grantConnect(hook, fetch2, liveness = {}) {
|
|
|
18691
19069
|
return new HostfsClient(first, grant, fetch2);
|
|
18692
19070
|
};
|
|
18693
19071
|
}
|
|
18694
|
-
async function openHostfs(spec,
|
|
19072
|
+
async function openHostfs(spec, connect2, timing = {}) {
|
|
18695
19073
|
const readonly2 = spec.options?.ro !== void 0;
|
|
18696
19074
|
const { port1, port2 } = new MessageChannel();
|
|
18697
19075
|
const slot2 = mediumSlot(
|
|
@@ -18718,7 +19096,7 @@ async function openHostfs(spec, connect, timing = {}) {
|
|
|
18718
19096
|
);
|
|
18719
19097
|
const watching = keepWatching(
|
|
18720
19098
|
{
|
|
18721
|
-
connect: () =>
|
|
19099
|
+
connect: () => connect2(spec.source, { readonly: readonly2 }),
|
|
18722
19100
|
up(client) {
|
|
18723
19101
|
active = timed(client, timing.callMs ?? HOSTFS_CALL_MS);
|
|
18724
19102
|
slot2.insert(client, handlers);
|
|
@@ -21817,7 +22195,7 @@ function serveKernel(port, deps) {
|
|
|
21817
22195
|
});
|
|
21818
22196
|
return holding;
|
|
21819
22197
|
}
|
|
21820
|
-
async function
|
|
22198
|
+
async function connect2(user, tag) {
|
|
21821
22199
|
const l = await ready2();
|
|
21822
22200
|
tagOption(tag);
|
|
21823
22201
|
if (user !== void 0 && !await l.users.lookup(user)) {
|
|
@@ -21898,7 +22276,7 @@ function serveKernel(port, deps) {
|
|
|
21898
22276
|
if (req.op === "init") return init(req);
|
|
21899
22277
|
if (isAttestRequest(req)) return attestOp(await ready2(), req);
|
|
21900
22278
|
if (req.op === "open-terminal") return terminal(req);
|
|
21901
|
-
if (req.op === "connect") return
|
|
22279
|
+
if (req.op === "connect") return connect2(req.user, req.tag);
|
|
21902
22280
|
if (isUsersRequest(req)) return usersOp(await ready2(), req);
|
|
21903
22281
|
if (req.op === "routes" || req.op === "transport-traits") {
|
|
21904
22282
|
return networkOp(await ready2(), req, remote);
|